'#174
+ +#230#163#254'i'#159#202#185#25'+/'#127'T}'#246#27#127'G]'#255#220'W'#223#215
+ +#251#151#206'>g5'#254#188'P'#251#179'\l~'#29#235#207#165#188'W'#199#251#181
+ +#218#159#10#248#19'&'#130#153#26'o'#223'S'#253#135'?`'#211' [,'#172#215#191
+ +#17#206#251'/'#147#221'/'#223#4#213#31'&'#192#152#22#132#130#224#12#180#170
+ +'?-'#152#231#15#14#193#145#211#236#243#185'I'#127#251#155#143'iX'#135' &'#20
+ +'%'#192'cZ'#241'Mt'#14#130'/'#0#166#0#189#230#10'-k'#15'G'#189#183'v'''#205
+ +#151#141'w_;'#250'b'#213'\'#135'?'#224'u'#21#213'$1'#168#17'["'#240'M[q'#19
+ +#30#180'='#5'i'#9#138#217#134'r'#201#21'8'#15'n'#129'{'#255#231#191#169#255
+ +#250';'#191'z'#218#167'q'#166'Gs'#253#138'z'#233#203'_S?'#243'+'#191#165#234
+ +#171#155#207#245#179'M#'#15'//'#8#0#21'}'#153#16#0#219#253#146#230#11#149#30
+ +'E> '#0#150#254#0#255'Tk'#1#179#193#158#218#187#253#135#244#191#194#238'W'
+ +#176#251#189'd'#241#234#202#246#247'B'#178#255#149#168#254#180'L'#137#4'0'
+ +#203'/:'#253#222#147'f'#159'w$'#1'h'#219'8'#254#158'W'#216#175':'#142#149#0
+ +#224#16#252#214#183#190#197'MC'#136#201'Z'#244#195'`'#152']'#22'-'#0'$pM!J'
+ +#160#188#149'w'#247#214#190'0Kk=eH'#0#210#157'H'#160's'#249'5'#186#233'/IRP'
+ +#205'j'#1#8#13#194#28#240'b'#157'#'#160#195#131#18'"4'#25#131#158''''#10#192
+ +#249#9#19#254#254#223#254'e'#245#240'";'#176'4'#26'kW'#212#205#159#255#154'z'
+ +#235#24'@_'#26#206#196#157'6'#209'G&'#241#204#165#161'g.'#177'~V'#253#167#218
+ +#238'O'#5#252')'#183#249#30#178#211'o1'#30'j'#233#159'&'#186'4'#152#237#254
+ +#189'w'#218#209#180'oT'#127'z>9'#230'Ok4'#250#228'f'#31' '#0#244#249#203#178
+ +#12#190#128#253#227'p'#252#185#227#184'aa'#29#130#244#163'j'#164#1'tMn'#0'H@'
+ +#136#0#29#133#215#147'<'#218#248#233#222#250#23'3'#130#189'q'#10#194#31#0'{'
+ +#191's'#245#227#170#209#187','#192#143#181'?'#192'5'#7'b]>\'#20#14'A'#11#208
+ +'D'#144#151#10#136#156#159#251#164'_~'#18#254#129'C'#190#31's'#1#254#222#175
+ +#127'A'#141#30#221'9'#129#147'8'#187#163#177'vYK'#250'_'#251'['#31#12#244'O{'
+ +#194#141#202#159#231#142#237'o'#192#159#217#226#158'\'#178#252'8'#140'7[X'
+ +#192'C'#242#167'Sc'#255#143#9#252#127#164'f'#163'}Q'#253#19#235'7Xo'#142#238
+ +'m6'#251#144#240#244'Hz'#166#216'g'#12#144'#'#227'O'#21#210#255'.'#225#4#181
+ +#254#187#180' '#230'?'#251#250#215#191#158'>O'#199#223#179'\'#158#231#241#249
+ +#236#16#188'v'#237'ZD?'#166'I?'#142'M'#1':~]'#242#2#224#16#132'V'#176#218#159
+ +'7n'#222#31#174'|'#138#253#1#220#16'$'#212#243#6#196#177#234'^{K'#213'z'#235
+ +'L'#0'69'#168')'#249#1'5m'#10#232'D'#161'P'#207'1`'#252#2#158'8'#6#13#1'x:'
+ +#195#235','#155#4#217'|'#170#254#227'o|^M'#182#31#156#246#169#156#232#208#160
+ +#255#243#234#19#4'zl'#31#247'0A'#23#207#216#251#210#196#147#255'!'#192'5Y~'
+ +#185#128#31#146'?'#19#181#127'!$'#144'Ng'#236#245#239#223#253#174#154#13'w4'
+ +#248#209#223#15#170#127#134'x?'#236#254#157#183#229#27'!'#253#145#245'7'#161
+ +#239#178'1'#127'I'#246'A'#143'?T'#254'm#'#227#143#204#229#217'q8'#254#220'q'
+ +#18'0`-'#128#214#193#189'{'#247'0'#181'x'#11#141'C'#148#6#189'!'#1#248#5'6i{'
+ +'e{'#210'}'#227#241#164#253#154'.'#24#242#25#208' '#129#176#214'P'#221#171'o'
+ +'q'#255#128'@'#204#129#192#248#3#140'S'#208'!'#1#27#29'p'#27#140'B#p'#253#1
+ +'v6'#226#167'\'#134#147'L)'#150's'#193#148#224#223#250#245#159'S'#211#189#173
+ +#147#251#238#19#30'A\S'#221#151'^W'#215#190#240#139#234#245#191#240#13#213'X'
+ +#127'N'#160'?'#202#253't<'#253'&'#191'7wm'#254#212'H'#254#2#252#25#131'_'''
+ +#251'X'#181#31#14#192#217'L'#245#31'|_M'#247#183#216''#239#186#170#127#179#217#156#16
+ +'^'#22#199#225#248'+]'#138#227#248#208'e'#223'cL'#1#218#174#199'q'#220'Y,'#22
+ +'k'#196'vp'#2#26#18#192#246#6#189#180#247'`'#216'{s'#127#214#188'a'#253#1'a'
+ +#164'g'#24#170#183'T'#239#198'[*nuu'#211#16'h'#2#13#153'h'#148#246#217#31'P3'
+ +#230'@A'#2'z'#242'Q_'#151#17'{^'#209'r'#251#6#242#202#229#240'N'#185#167'X'
+ +'Bv'#228#127#250#198#159'T'#227#199#247'O'#245'<'#158#215#128'F'#215#190#246
+ +#138#186#242#179#127'Z}'#228'k'#191#161'z/'#127#244#216#190#235'i'#247#210
+ +#230#243#155'F'#30#166#176'G'#156'}'#214#219#15#135'_R'#128#159#157'~'#211'"'
+ ,#236#135#253#193#131#183#9#252#247#11#143'?'#252#4'Y'#170'B/'#153#223'$'#240
+ +#199'~2sC~2'#193#7#167#251'*'#173#250#223#145'\'#255'GF'#245''''#201#143#196
+ +#160#244'8'#165#191#190'.''3'#216#20#248#202'W'#190#226#147#25#16#175#172#172
+ +'4'#8#252']'#250#161#27'2'#185'('#204#0#16#1'G'#5#8#176#157#187#131#149'O'#14
+ +#231#141'K'#202')'#29#230#28#129'f['#245#174#127#146#236#255#150#245#9'0'#17
+ +#196#146#31' '#154#128'I'#27'6'#181#3#158#211'_'#176#152's@'#251#8#220'^'#131
+ +'O'#157#233#229#20#198'w'#254#233'7'#213';'#255#254#159')'#253#12#157#159#1
+ +#226'mn^W'#151'>'#253'e'#245#234'/'#253'U'#181#249#214#23#143#241#203#158#208
+ +#198'/'#175#188#206'H{'''#179'O'#247#242'3'#224#207'X'#234'g'#21#201#207#241
+ +'~'#2'}'#6'{_'#136#0#165#189#147#157#247#24#252#186#181#151#158#212#211#207
+ +#210#228#229#149#237#31#212#130#197#196#181#251#149#14#249#193#238#223#18#213
+ +#31's'#252'q'#200#143#182'w'#8#15#195#231'Y'#236's'#132#203'vb'#195#166#9'_'
+ +#191'~'#29#154'@'#11#181#2#240#7#208#15#191'*aA'#204'1'#8'=p5'#247#252#206
+ +#157#254#234#167#198'I}'#213#23#167#160#23#232','#192#184#217'c'#18#8#26'uM'
+ +#0'l'#18'D'#146')'#136#16#161'4'#18'A'#152#208#180#21#243#29#18'0'#221#133'<'
+ +'!'#0#229#2#255'9D'#12#142'a6'#227#225#253#159#168#255#254#219#191#172#134
+ +#247'~z'#130#183#236#217#6#8#186#190#178#169#214'>'#254#179#234#213'?'#251'+'
+ +#234#218#159#248#165#163#191#249#176'k'#246'<'#158'PG'#218'kG'#191#201#231
+ +#207'm#'#143#194#230'/'#210'{y'#153#27#169#191#208#192#135#148#135#250'O'#132
+ +'0'#217#190#163'F[?"'#146#152'Ks'#15']'#223#143'?7'#187'{o7'#194#217#208#177
+ +#251#231#244'l'#163#197#23#18'='#182'%'#215#159#193'O8'#128#25#176#141#132
+ +#159#157#157#157#169'x'#253#13#248'_'#24#2#224#239's'#19#132#8#248#173'$I'
+ +#216#31'@'#11'B'#130#208#4#216#31'@'#235#149'\'#249#157'w'#247#214'?='#205
+ +#162#14#146#132#152#4#184'7'#0#145'@gMu'#174#189'%'#229#194#162#1#152#252#0
+ +'h'#1#146'-X8'#6#203#154'@a'#18#248#197#228'#N1'#209'Y'#237'='#248#255#254
+ +#205'?R?'#248'w'#255'DMw'#30#158#234'y'#4#245#166'jn\S+'#175'}'#130'$'#252
+ +#159'R7'#190#244#231'T}'#253#202'i_'#158#202#200#203#210'_Rz='#227#236#147'r'
+ +'^'#6#191#163#246'['#240#139#202#15#224#179'z'#207'*'#191#246#1#204'v'#31#168
+ +#193#195#183#233'usn'#238#193#239'Cyo'#154#229'W'#187'{?'#236#196#147#190#168
+ +'l'#214#238#23#167#223'.'#236'~ZX'#245#135#211#143'0'#240#152#222#187'O'#166
+ +#241#4#9'?'#199#233#245#175#142#211'x'#202'}'#152#2#180#6#9'X'#127#0#217'?'
+ +#151#29'S'#0#26#1#252#1#221'$'#243#187#239#246#215'?'#179#200#163#134'o'#204
+ +#1#216#247'$'#233#153#4#174'|'#156'H'#160'nA'#207'f'#128'h'#4'L'#2#145'&'#1
+ +#21#233#168#2#147'@h'#8'@r'#5'|'#129';'#214'2)'#225'Y'#159#166'|'#240#222#219
+ +#234#143#255#249#223'W'#15#254#247#31#208'C99'#190'/'#162'k'#17#183'{'#170'u'
+ +#245'e'#181#250#209#207#168'+'#159#251#170#186#250#249#175#210#245#175#159
+ +#246'%x'#250'03L'#219#130#30'c'#231#23#253#251#140#167#223'H~V'#225#231'I'#1
+ +'x'#6#255#156#155'{'#178'&@'#255#155#238#222'U'#163'G'#210#206'{Q'#168#253' '
+ +#146#203#173'}L'#231#181#131'/q'#156'~H'#245'E'#188#127#15#133'='#180#141'F'
+ +#144'P'#251#225#244'{D'#207#245#222'I'#218#253#238'8'#141'G|'#169'?@f'#22'b'
+ +#167#160#210'Z'#0#182#215#233#1#236#204#147'`'#229#189#254#250#167#19#21#198
+ +''#28#234'#p'#231'R'#217#151'I'
+ +#184#15#142'>'#14#251#137#31'`'#188#253#30'-'#239'jR'#224'i'#188'S'#142#22#0
+ +#252#27#205#193#237#245#198#240#145#11'~z'#182#140#221#15#240'o'#153'J?z'#230
+ +#239#201'4'#223#232#240#131#6' '#199#150#237#247','#151#242#196#190#215#245#7
+ +#208#197'h'#18#248'{'#164#10'm'#18#192#175'Hx'#144#179#4'iY'#3#9#204#210'x'
+ +#237#246#254#250'''3'#207#15'Yr#<'#24'j'#18#8#27'm'#213'!'#18#136#154#29#2'~'
+ +'h'#181#0#228#8'x'#236#20',H'#128#181#129'J'#152#208#212#17#24#18'`'#231' t'
+ +#148#220#153#144#164'`'#132#234#147#246#244'+y'#10#4'1'#219'{'#172#230#253#29
+ +'5'#31#236#210'zO-'#134#251'\9'#217'}'#249#13#213#185#249#250#217#149#224'G'
+ +#189#142'K'#239'C'#17#222's[u'#219#16#159#11#254#170#212#151#220#254'L'#154
+ +'z'#148#9'@K'#255#209#214#143#213'd'#239#30#189'n'#206#145#1'~'#159#228#248
+ +#175#214'F'#15#174#180#251'w'#243#2#252#200#244#131#221#15#240#195#238#127','
+ +'!'#191'{R'#223#15#27'n{:'#157#14#136#0#160#194'%''e'#247#31#245'r'#31#251'w'
+ +'W'#243#3#200#28'@3'#209'Md'#10'*'#237#16#196#26'$'#176'J m'#141#23#181#205
+ +#187#253#213#183#136#4#2'm'#207#11#9'p'#4#160#201#230'@D'#234#170#213#4#156
+ +#181#23#11#17#24'M'#128'L'#2#21'j'#191#130'2s'#17#26's'#192'M'#30'2UEn'#163
+ +#145'3l'#26'|'#232'F^'#10#226#8#224'M'#21#159#210#158'}'#137#239#187'i'#189
+ +#218#230#215#128#207#13#248#173#228'_0'#200#217#241'7'#211#161#190#225#163
+ ,#183#213#172#255'H'#146'|'#140#218#175'k'#251#187#209'd'#235'zw'#239'=m]d'
+ +#153'x'#252#145#236#3#240'#'#151#127'['#233'y'#253#24#252#216'F'#178#207'I'
+ +#198#251#15#27#167#253'('#151'R'#133'I'#11'h#'#25#136#180#128'K'#208#4'h'#31
+ +'Z'#0'H'#0#164#176'B@lM'#147'x'#237'N'#127#245#19#169#23#198#218#179'/>'#1
+ +#174#12#172#17#9'|L'#197#157'uM'#10#198#15'`'#192'/m'#198'=!'#2'_z'#10'('#19
+ +'%'#16#231#160'2'#230#128#239#21#4'`'#174#214#139'>]'#241'y'#25'.'#234']sGl|'
+ +'O'#202'wm'#3#143#170#179#207'8'#250#0'f'#212#243'/'#28#240#27#231#31#175#167
+ +'j'#240#240#7#164'ImK'#140'?'#209#196#145'j'#240#175#213'F'#247'/'#183#145
+ +#226'k'#193#159'I'#154'/g'#250')]'#226#251'H'#230#245#131#228#199#164#30#143
+ +'1'#171#207'|>'#31#31'w'#170#239'Q.'#227'i'#223'F'#207'8'#5#209'@'#4']'#132
+ +#208'P'#212#9#15'"O'#224#138#201#20#4#9'$y'#220#189#189#191#250#214'BE'#245
+ +#18#9#136's'#176's'#249#13#21'w/'#177'/'#192'3'#181#2#177#244#16#176'&A'#164
+ +#253#2'b'#14#168#208'/'#146#134#140'i '#13'F'#172'F`'#175#152#163#10#156#159
+ +':'#163#23'f'#148#146'xl'#171'.}'#140#193#159'i'#201'oc'#251#169'n'#226#1#240
+ +'+'''#204#151'K'#190'>'#171#244'3'#241#250#211#177'\B'#127#201't'#162#6#247
+ +#191#175#18#228#246'''s'#157#21#232#128#127#163'1'#184#189#217#28'>'#210#138
+ +'F'#150';'#146#31'*={'#252#149#238#237#7#240#223#151'p'#223'cH'#254#197'b1'
+ +#186'v'#237#26#156#131''''#234#244#171#142#179#240#236'Z'#18#232't:1'#177'b'
+ +#157'.T'#27#149#131#232'$'#4#2'0$ '#173#198'A'#2#205'L'#133#237#219#253#181
+ +'7gY'#220#214'}'#0#196#174#143't)qk'#243#150'j'#172'^'#215#146#222#1#189#217
+ +'f-'#160#166#147#139'8Dh'#219#142#7#133's0'#240#10#141#192'I rs'#137#205'f~'
+ +#224'''='#225#10'?'#211#173'>'#175']'#130#142#248'h='#245#250','#191#178#185
+ +#211#151#223#5#191#246#238#235#248#190'J'#181#202#175#4#176#156#155#159':'
+ +#246#254'\'#131'?'#183'j'#191'd'#242#17#25'$'#147#161#234#223#255#158'Ji]H~'
+ +#157#225#167#210','#191#220#217#255#201'j<'#217#21#193'o'#193#175#138#190'~'
+ +#166#190#255#1#164#191#132#254#30#163#190#159#198#168#209'h'#204#143';'#207
+ +#255'9'#222#165#227'?'#15'S:'#140#162#161#241'x'#140#134#162#29#169#25#184'd'
+ +'4'#1#165#251#7#160#177'H'#143#174'X'#147#16#218#188#211'_'#251#216'8'#173
+ +#173'x2'#239#160#206#254#211#18#191#190'rU'#181#214'oiM'#192#250#1'B'#157',$'
+ +'d'#224'I%'#161#138#138#190#2#166#152'Hq'#132#192#244#23#240#203#145#2#167
+ +#243'P.'#161#195#234#21#245#202#127#158'q'#228'O'#220'='#179#195'{'#234#129
+ +#167#255#238'|'#201#207#21#144#27#129#175#14#11#237'9'#133'<*-b'#251#197#162
+ +#129#207#210#127#190#144'p'#223'B'#180#129#5#255'o>'#216'a'#155'?'#157#142'u'
+ +''''#31'Z'#148#128#223'#'#241#127#181#187#247#163'n8'#27','#3#191#210#225'>'
+ +#128#31'-'#188#31#144'&'#203#14'?'#228#248'#'#220'G'#175#27#161#200'G'#157
+ +#146#211#239#131#222#157'c='#23#248#3'~'#252#227#31#251'h%F'#154'@'#195#228#8
+ +'`V!'#164#12#131#8'h'#141#164'!4'#26#237#210'Uk'#17#240#234#247#6'k'#175#15
+ +#23#245#13'c'#14'0'#17'DP'#241#145':'#220'Sm2'#9'PG'#224'K?'#193#2#252#142'6'
+ +#192#254#0'c'#14#232'm'#155'8Ti9f'#195#134#158#201'(tr'#207#171#253#7#204#173
+ +'=KW'#250','#143#202#245#202#157#166#156'%'#208#27#162#200#164'eW'#150#29'H'
+ +#231'Ui'#1'z'#227#237'O%'#212#151#207#231#142#195'O|'#0'D'#2#147#221#219'j'
+ +#178#253#158#222'w$?>'#223#167#15#184#222#219'{'#167#21#204#199'K'#192'ob'
+ +#253'h'#234#137'4_+'#249#233#153'}L'#160#223#165#231#23'5'#0' '#137'3'#1'~'
+ +#231'2'#159#153#193'$'#240#189#239'}/@x'#16'$@Z@W'#26#137#184#154#0'"'#3#235
+ +'('#28#162#27#129#18#227#248#254#160'wko'#222#188#234'['#245']k'#2#200#26#244
+ +#227#26#153#4#31'Q'#181#206#166#150#248#174#244#23#223#128#206#17'0'#249#2
+ +#129#205#30'TN'#6#161#237'@'#236#251#5#1'8m'#201#221#26#3#235#164#170#22#27
+ +#157#181'+~F'#134'Wr'#228#185#155#249#1#240'k'''#159'H'#251#180#144#250#165
+ +'t^'#168#251#137#238#215#175#9'@<'#254#226#237'7'#26#0#19#0#166#233#154'N'
+ +#213#136#164#254'|'#180#171#227#251'IR'#2#127#160#146#217'K'#221#221#31#214
+ +#131#197'T'#192'o'#28'~F'#242's'#129#15'r'#252#209#220#3#146#31#26#0#212#254
+ +'('#138'v'#7#131#193#136#180#218#19'M'#243'='#210'u?'#237#19'XvN&<'#184#181
+ +#181#21#211'Ek'#208#5'4$'#128'lA'#180#24#135')'#192'$@'#251']'#248#4#232'X'
+ +#237#209#168#243#210#246#180'}SO8bH@2'#0#137#8#234#189#171#170#185#241'*'#131
+ +#222's'#181#129'H'#147#129'''-'#199#149'q'#14'F'#21'm'#192'u'#16#154'z'#2'&'
+ +#3'eg)'#202#29'2p'#181#255#220'!'#133#15'f'#26#188'(C'#210'u\'#137#159#23#181
+ +#249#202'sT}'#199#201'W'#168#249'"'#245#197#214#231'2'#222#180'p'#242'1'#232
+ +#165#148#215'z'#252#141#234'/'#170'>'#219#254#201'B-'#250#187'j'#184#245#14
+ +#29#27#219#200#128#174#229#151#137';'#189#249#228#165#238#222#15#185#170#143
+ +#235#8'l'#168#143'S|'#149'd'#249')'#237#224'C'#184#15'R'#255#1#212'~'#178#249
+ +'w'#233#249#29'6'#155#205')i'#183#201'iz'#252#151#141#179#250#4#150'H'#160'A'
+ +'c2'#153#160#145#8#155#3'B'#2' '#3#209#4'T'#151#128#136#190#131#181#253'Yc'
+ +#243#225#168#251'Z'#166#194'PKn'#169'!'#8'C1'#9#186#164#13#188#193#213#132#0
+ +'>'#28#129#158'D'#4#220#16#161#155'9'#168#156'Z'#2#229#18#129#231#23#179#22
+ ,#251#198'I'#232'j'#3'E'#30'a'#238#148#25'z'#213#146#195#3#153'mg'#245#182#188
+ +#223#187#249#4#127#134#233#191#167#156#198#28'|'#188#2'zP'#168#3'~'#211#173
+ +#135'U}'#9#239')'#167'O?'#188#245#249#28#251#11'+'#249's)'#238#201'%'#207'?'
+ +''''#240#143'wn'#171')-'#153'y]*R_f'#238'iG'#147#237#171#173#253#219#129#151
+ +'&:'#151'(3e'#189#240#246'3'#248#149#206#242'CO?'#246#248#195#230'G'#168#15
+ +#224#167'eH'#166#236#20#177#254#179#6'~}'#205#207#238#176#133'C'#4#254#136'.'
+ +'b'#147'L'#130'.H@:'#10']6'#225'A%$'#128#16'!H`'#158#133#237#187#131#222#235
+ +#179#172#214#230'y'#3#140'o'#192#132#10#163#186'j_zM'#197#221#205#2#248'f1'#4
+ +#16'W'#142#7#186#211#144#178#243#19#6'em@'#26#143#148'#'#6#158#149#244#172#29
+ +','#137#30#152#249#11#142'zG'#206#204#147#227#222#168#167#189' ?'#252#128'i'
+ +#197#229'y'#14#248'3'''#150#175#28#27#223'Q'#247'y'#31#182#190#27#222'K'#11
+ +#137#159#27#208''':'#181'7/'#145'@'#194#245#19'#'#146#250#243#225#142'h'#11
+ +':'#188#167#138#30'~'#217#165'F'#255#246'Zc'#244#152'S{%'#212#167'tz/O'#223
+ +'-s'#248'A'#237'7'#137'>'#15#207#19#248#143't'#239'N'#251#252#12#9#244#251
+ +#253#184#213'j5'#232#226#162#197#248#154#132#4#225#16#188#12#173'@i'#18#232
+ +'1'#9'('#175#158#7'~'#252'p'#208#189#185'?o]-'#146'|t'#184#15'&'#129'oL'#130
+ +#245'W'#8#236#177#205#9#240'L'#5'a'#172'5'#6#171#9'p'#10'qPT'#21#210':'#15
+ +#220')'#202#140'V'#224#21'D'#160#138#237'"JP'#172'K%'#200#206'f^9'#236'='#235
+ +#173'z'#158'w'#245#153#31#215#188#152'>'#219'='#149#188#188#145';/'#178#245
+ +#249'n'#18#143#177#243'MG^'#145#250'*u$'#191'c'#235#27'/?'#219#237#12#244'E'
+ +#161#254#207#11'R'#192#255#23#240#242'?'#254'!i'#1#19#177#247'u|'#223'|n'#228
+ +'/&'#215#218'{?i'#132's'#174#229#23'G'#4#236'}'#147#222';'#145'P'#31#171#253
+ +'J'#194'}'#178'F'#169#239#222'y'#0#127#233#254#156#209#193#231'W%'#1'd'#12'"'
+ +'Y'#136'.'#178'!'#1#152#5#151'0'#247#128#210'y'#2'm'#186#212'u'#146#184#241
+ +'p'#222'X{0^'#185#149#145#236#215'@-'#155#4'H!'#6#9#196#157#13#201#7#144#136
+ +#128#1#191')$'#10'+$ '#11#147#138'h'#6#156'N,'#145#130'\'#162#6'V'#27'x'#26
+ +#17'8'#221#137'rG;'#240#202'^'#196''''#220#177#147#184#149#249#225#135'+'#167
+ +'i'#140'{'#175#244'6'#167'<'#23#0'WO'#0'~^'#150#248#202#22#239'8N>c'#239#187
+ +'v'#191#149#252#139#18#240'Y'#19#152'N'#213'd'#251#167'j6'#220'b'#130'@'#179
+ +#15'+'#241'3=__'''#154'<'#190#210#234#223'!'#149'?'#205'm'#147'@]'#210#235'd'
+ +#248#245#165#178#15#222#254'G'#146#215#255'H4'#129'}8'#252'666'#206'<'#248
+ +#237#253'9'#227#195#146#128#18#159#128#146'2b"'#130#21'h'#2#146'%h'#178#5'9Y'
+ +#136'$r'#155#192#211#160';'#23'''Y'#212#184';'#236#189'6Kk'#29'S'#0'd'#27#140
+ +#8#184#163#214#26#19'APo'#21#17#1#167#138#208's'#251#10'<'#137#8#220#148'b'
+ +#153#194#220#134#14#205#196'%'#165')'#204#202'k7'#132'h'#230'4'#176#135#14
+ +#132#20#143'n:<'#151'q'#152'*o'#156'v'#246#144#145#236#230#127#249#146#216
+ +#189'~'#157#14#227'I'#230#158'!'#2'k'#227'/Q'#247'S'#145#248#2'|'#181#208#149
+ +'|J'#236'w'#215#222'7'#206'?E'#251#147#254'=5'#221#189#173#19#127#210'%*?}'
+ +#209#229#198#224#189#149#198'h'#199#203'MI'#143#14#243')'#1'?'#173#199#180
+ +#223#151#154'~4k'#132#196'GE'#31#182#183'I('#161#145'''{'#251#201'\=s'#14#191
+ +'e'#227'<'#16#128'=OC'#2#251#251#251#17']'#228':]x'#174#29#136#162'h'#157#246
+ +'a'#6'\'#18''''#225#134#212#14'th'#27'}'#4'b'#210#0#162'G'#195#206'K{U'#147
+ +' '#212#201'C'#138#171#11'#U'#235']S'#245#181#27#156'M'#200#14'@'#199#4#0#1
+ +'(''Dh'#136#192#148#24'+'#153#181'X'#249#229#198'#'#182#21'Y%'#179'P'#231#15
+ +'-'''#3#207#209#255#139#222#4#166#151#161'{UN'#136#4#170#143#176#19#182'+m'
+ +#229#5'Y'#149'CxN'#165#158#27#198'3N='''#150'oA'#159#154'm'#0'>#b'#0#160'u'
+ +#17#143'Z'#20#13';'#173#199'?IJ>'#0#132#0#147#209#158#154#236#252'D-&'#131'B'
+ +#213#135#169#128#207'pU'#254#238#238'O'#234'^2'#245't'#229'@'#213#211'?'#147
+ +#22#222#168#234#219'q'#193#15'O'#127#24#134#232#235#223'_,'#22#227#25#141#243
+ +#2'~'#140#243'B'#0#246'\'#221'<'#1'8'#252#232#194#183#232'p'#143'.'#254#186
+ +'8'#7'A'#4#156','#132'V'#227'$'#129';$u'#27#180'_#'#240'E'#131'i}'#237#193
+ +#164#247'j'#150#235#249#7#180#147'0`'#21#222#244#16#132'Y'#208'X{'#133#139
+ +#138#188#208#137#6#200#220#3#134#8'4q'#4#162#29#136'&`{'#13'8]'#137#131#138
+ +#163'P'#8#161'hF"'#19#152#28'H76'#161#195#162','#185#240#15'T='#3'G'#200'1'
+ +#248#160'%'#203'y^yi'#25#240'z'#229'4'#218'TE|'#159'%'#189#153'l'#195#190#230
+ +#160#154#207#246'~'#154#149#218'r+'#150#250#153#6#173#0'_'#137'='#175#164#131
+ +#143'2'#4#144'h'#239#127':''u'#127#231']5'#239'?'#210#173#186'L'#26'p'#146#10
+ +#209'h'#149#31#149'|'#151'['#253#187'P'#249'9'#188#143#254'}'#160'!m'#239#219
+ +#24#191#1#191#210'e'#189#15'e'#198#222#199'R'#207'? '#1'4>K'#25'~G'#29#231
+ +#137#0#236'9'#155#180'a'#218#142#26#141'F'#13#17#2#164#7#27#231#160'8'#5'/'
+ +#217#218#1#29'&'#132's'#176#6#147' Sa'#252'h'#220'~'#169'?onz@'#166#137#20
+ +#216'f!Z'#226#195',h'#192', B'#176'R'#223#1#188'Bd '#22'B'#16'M@9'#25#132#214
+ +'I'#24'>A+8'#204'GP'#154#242#188#186'v:'#26'['#13#193#161#130#165#190#130'CB'
+ +#143'O'#200#187#183#160'.%'#224#23#26'H.'#234'})Q'#199'%'#0#215#147'/'#158'}'
+ ,#163#226#219'p'#158'q'#240'Y'#208#167'b'#231';'#158'}l'#11#192#181#202#175
+ +#215':'#175#223'8'#2'%vO'#235#217#222'}5'#222#131#186'?'#211#199#229'3y'#157
+ +#167'"'#245#147#201#149#230#254#237'f<'#27'z'#26#247'8'#15#146#250'%{'#223'&'
+ +#248#208#178'C'#210#254'1'#9#153'G'#210#213'g'#155#128#191'K'#160#31#160#149
+ +#23#13#152#8#231#10#252'K'#158#138's3,'#9#208#197#15'k4'#200#12'h"B'#16#4#193
+ +#170#227#23#128'F'#0#18'X'#5'A B &A'#148#19#196''''#139#176#253'p'#178#242
+ +#202','#141'ZE'#235#240#162'('#200#147'9'#10'k'#221'+'#170#182'rM'#5'h'#162
+ +#17#154'y'#8#3#199#28'pM'#3#9#17#134'RK`'#10#140'l'#14'A Z'#129#201'$t'#218
+ +#146'U'#137#160'j*'#148#202#146'+'#21#137#21'G'#162';'#242''''#146'A'#165#216
+ +'f'#217'c'#235'Jw'#222#168#172'e;7'#137'<'#153#27#190'3'#137'<'#142#164'wc'
+ +#249#2'|'#29#203'/'#192#175#137#192#9#241#217't^'#13'r'#237#3'H'#10''' -'#139
+ +#225#14#219#249#9#171#251#186'I'#167#146'L>'#179#246#232#207'j}t'#127#189'1x'
+ +#228#177#180#207'3'#147#214#171'$'#190'O'#203'\j'#249#135#226#233#135's'#15
+ +#210#30#249#252'['#178#191'O'#207#220#160#223#239'O'#187#221#238#156#8' =o'
+ +#224#175'>'#9#231'm'#148'J'#137'I'#19#136'%u'#152#157#131't'#140#181#1#144#0
+ +#250#11#210'z'#141#253#2#202'k#}'#152#182'czDc rw'#218#186#180'=m_'#207'H'
+ +#164#235#226#31#237'$'#132'fP'#168#249#145#170#181'/'#169#6#17#129#31'7'#180
+ +#244'7j'#191'k'#14#24#127'@'#224#164#17#187#166#129#201'!p'#29#133#198'<'#176
+ +#4#224'W'#18#139#180'G'#192#246'.'#180'='#11#141'iP'#152#3'n'#194'Q'#217';'
+ +#239#29'XU"s'#202'Az'#217#181#144#187#161'='#137#215#231'y'#197#214#151'B'#29
+ +#163#226'gy'#145#167'oSu'#139')'#183'\'#201'_H'#253#20'M5'#197'VO-'#9#184'a'
+ +#190#220#170#251#198'!H'#18#127#184#173#166'{wU:'#27#22'f'#129#11'~'#241')'
+ +#180#162#217'.I'#253';'#152#156#211'C/`}n'#172#242'+'#221#187#207#228#244#143
+ +#140#167#159#182#183#197#219#191'Ej'#254'6'#9#24'h'#2'}'#147#215#239#244#241
+ +'3'#192'?7'#224'w'#30#135's;,'#9#16#1#4#8#19#18#27#195'9'#216#154#205'f=h'#3
+ +#244#127#244#26'D'#171'1h'#2#240#11#160'r'#144#211#135#17'% '#192'D'#244#17
+ +'A'#146#249#241#163'I'#247#230'`'#214'X'#247'l'#241'O'#1'^?0 '#142#184#166#0
+ +#206'B'#244#211'3'#166#0#167#13'['#208#23#161'A'#27'!'#136#180#244#207#131
+ +#224'@wb'#235'#p*'#15#11'"P:'#164'h'#211#139#165']'#153'*L'#4#151#24#150'^"'
+ +#175'r'#197#170#26#192'!'#14#190#18#15#184#245#246#216#204#242#146#189'o5'#0
+ +'7W'#223#128#221'z'#244#141#202'/'#246'~'#166#167#219'V'#226#228#179#128#183
+ +#29'{'#202#224#183#197'='#236#253'_'#168#217'`K'#205#246#239#17#240#199#146
+ +#16#148'X'#147#1#251'J:'#246'D^2'#187#212#26#220'n'#215#166'}'#248#28'<'#143
+ +'U~V'#252#233#146#177#163'Oz'#247'Me'#178'Nk'#239'C'#237#151#153'{9'#190#15
+ +#149#159#20#206'1b'#252#245'z'#29#164'a'#234#249#237'U:O'#227#188#19#128#249
+ +#13'H'#24#194#154'#'#4'p'#14#18#1'4E'#27'X5'#190#1'!'#1'6'#9'h'#191#7#191#0
+ +'m'#195'A'#8'm'#128#222#231#251#163'$'#238'>'#28'uo.'#178#168#233#154#5#202
+ +'I+V'#226''''#136#219#27#170#222#187#174#130'F'#235#160#212'7'#170#191'C'#4
+ +#134'L'#148'K'#2#2'z'#229'U'#157#133#14')x'#166#10'Q9~'#130'J7cq$'#30#152#241
+ +#232#176#154#3'[m'#231#188#196'm'#180'a6'#189'B+'#240#158#2'zW'#213#247'*'
+ +#222'|'#29#215#207#172'Df'#7'`R'#168#251#158#1'}'#226'H~'#163#13'd'#134#8'2'
+ +#142#223#207#6#143#24#248#217'bb'#237'~'#227#216#203'\u'#159#132#252'J}'#252
+ +'p'#179'9x'#224#209#142#199#165#130#224#29#218'f%'#198':'#250'f'#210#187#207
+ +'t'#238#133#167#223#130#31#19'v'#160#137#7#254#143#254'}'#163#209'h^'#241#244
+ +'+u'#14#193#127#200#147'q.'#135#141#16#160#156#248#214#173'['#225#214#214'V'
+ +#141#14#213#137#173#17'*'#236#145#250#134'b'#162'u''u'#24#251#200'#hC'#27#160
+ +#237#26#251#6''#204'r'#143#204#130#246#229#221'Y'#243'J'#154#135#145'1'#11
+ +#236':'#8#172#175#0'N'#191#184#181#166#234'+D'#4#245'N'#17#1'p{'#10#28#0#190
+ +#16#131#235#24'tk'#11'l'#152'R'#230'3t'#29#134'Nv!k'#7'jIU'#162'\'#17#175#148
+ +'\T'#190#213#182#143'A'#245'B'#26#233'_r'#240')I'#218#145'}3}'#182#19#194#179
+ +#224#183#251#6#240'N"O'#213#203'/'#241'}'#227#236'c'#144#27#147'@r'#251#141
+ +'6'#144'%s'#246#232'O'#25#248'3'#171#254'g'#198#163#239'F'#17'h'#187'I'#234
+ +#254#229'F'#255'^'#28#192'3O'#146#158#5'>'#199#245'3'#201#231#183'R'#159#22
+ +#19#226'c'#149#31#160#199#2#149'_'#8#1#29'|'#198#244#182')'#217#253' '#140
+ +#132#180#206#236'<'#132#249#142#4#156#23'h'#176's'#240#219#223#254'6'#251#5
+ +#232#166'E'#4#234':'#28#132'259'#155#4'XD'#27'0$'#208#165#183#146'>'#175#26#4
+ +#167#24'f'#1#129'='#160#199'%'#220#157#183'6'#247'&'#173#203#137#10#226#3'D'
+ +#224#23#246'>4'#130#176#209'!'#173'`'#147#8'a]'#249'a,m'#198#140#3#240'0'#167
+ +#224'!'#5'F'#146'3'#224#149'|'#3#166#23'A1'#169#137'%'#2#153#224#196'LuV'#10
+ +#18#10'7'#148#156#132#14#3'xF'#210'Wd'#153#145#246#7#28'{N'#252#222#149#252
+ +#182'B'#207#237#200'c'#192'/'#132#160'\'#167#159#149#242#142#211#207#233#224
+ +#131#255'-'#166#251'j1'#220#162'e'#155'I w'#205#128','#147#150'_'#236#220#195
+ +'~'#222#138'g'#187#27#141#193#131'Z'#184#152#150#212'}'#199#214#151#182']'
+ +#166'c/l'#249'}i'#226#193#158'~Z?Fl'#159#164#252'>='''#3'2/'#199#244','#205
+ ,'{'#189#30#192#127'n'#237#253#165#128'9'#237#19'8'#166#223'T2'#9'h N'#211'di'
+ +'O'#128#167#155'j'#137'@'#204#3#236#19#9#168#14#1#174'A'#251'u:'#30#25#179
+ +#128'@'#21#236#205'Z'#27#187#227#230#229#133#10#235#218'F'#247#203#211#141#17
+ +#1'('#223#183'ZA'#173#177#170'""'#131#176#185#162#163#4#230#181#142'3'#208'H'
+ +'~'#255'0-'#192#152#8'&'#147#208#248#7#248#23'V2'#12#221#28#130#220#137#12#8
+ +#27#152#196#220#131#209#130'Jz'#174#167#172'j/'#255'V'#226#245'+Iyc'#227#27
+ +'{'#223'4'#227#176'Z'#128#1#186#172#165#192#166't'#220'M'#237'u'#215'('#203
+ +#157#13#31'3'#240'S'#132#242'2'']W'#166#220#206'e'#209#192'O'#243'vm'#182#189
+ +#217#24'>'#140'|H|'#28#23#191'>'#171#251#220'%'#208#205#232#227#240#30#242
+ +#249'i'#189'/'#237#187#182#205'"'#206'?'#28#199'k'#166'F'#229''''#205'2;'#207
+ +#246#254'a`y'#17'G'#201'$@'#168#176#213'j'#197#2'lT'#12'v'#197#25#184'J'#140
+ +#143#232#0#22#248#5'D'#27'P-!'#2#152#5'a'#206'd'#128#174#225#190#191'7k'#174
+ +#237#142'[W'#230'y'#216#176#206':'#3'|'#207'H'#242#162#2#17#154'@'#212#222' '
+ +#173'`C'#5#141#142#227#252#11#184#231#160#231'8'#2#139#168'@u'#10'3'#207#2
+ +#222'F'#5#2#209#4'\'#237#192#151#144#161#149#252'U'#7'`%'#159#192#12#183#149
+ +'6'#239'+'#235#28#176#213'zF'#229'O'#171#234'~&fA'#230'T'#234#21#206'?~'#189
+ +#209#0'*a'#191#18#9','#230'j6'#218'f'#208''''#211'A'#161'!'#152'L@'#199'l0}'
+ +#0#16#210#235#198#147#199#27#4'|x'#246'M'#190#241#19#212'}k'#235#211#210#151
+ +#238'='#12'~'#186#207#144#254#216#222#15#130#128#19'{h'#153#145#244'_ '#196
+ +#247#162#168#252'K'#129#242#2#15'k'#18' J'#128#178'b'#186#185'54'#25'!R@'#227
+ +'Q'#152#5'+ '#1#133'Y'#137'5'#9'@'#27#232#209#210#17#179#160#238'{~Lk'#16'A'
+ +#8'"'#240#9'}'#251#179#250#234#206#164'ue'#150'!'#135#192#128#177#144#218#5
+ +#176#3'K'#10'a'#212'Tq'#7'Z'#193#154#10'j'#141'2'#184#157#210'bo'#9'!'#184#9
+ +'C'#133#25#224#21'~'#2'''R`o'#173'u'#11'H'#180#192'M$'#146'W'#185'~'#128#210
+ +#172#185#178'*'#194'}'#174#244#207#156#233#180#225#240#203'd'#178#205#138#183
+ +#191'*'#245#179#188#18#1'H'#212'b'#178#175#230'P'#241#199#187#156#216#147';6'
+ +#189#251'~K '#244'}>1B'#183'6f'#224#7#200#15'6'#192#231#138#221'2'#240#149#6
+ +'?'#128#143'N'#189'#'#201#229#223#23#240#195#185#135#25'y'#25#248#240#240'+M'
+ +#14#211'N'#167'3G'#3#143'7'#223'|'#243#133'R'#249#15#0#228#180'O'#224#132'~#'
+ +#155#4#208#6'h;Z]]'#141#160#13#200#140'D0'#11'z'#162#17#172#233#244'aM'#4#180
+ +'&'#18'Pm'#186#235#220'l'#4'&'#129'o'#136' '#131'F'#224'y'#195#164#209#219
+ +#153'4/O'#211'Z'#7#200#180#192'tH'#160'4'#231#128#152#0#232'I'#16#212'z*jt'
+ +#201#168#232#210'~'#173#210'[`I'#231'!G'#213'/'#171#254'x'#173#18#159#128#241
+ +#234'{'#182#152#168#8#4'x'#149#181'*7'#222'PE'#218#190#178#13'8'#157#146#221
+ +#204#13#241#21#234#190'w'#192#23'P'#201#233'7'#145#0#2'v2'#27#170#20'v'#253
+ +#164'O'#219#131'"'#219#207'x'#239#197#137#231#153#254'~v;'#231'p^'#167'6'#217
+ +'^'#175#143#182'|'#143'sy'#213'2'#224';'#237#185#173#147'O'#233#9':'#160#214
+ +#239#25#240#3#248'$'#12#246#200#222#135#3#16'z'#254#132'l'#253#217#139#230
+ +#232'{'#26'8>,'#227#128'6P'#171#213'bz^0G'#22#166'*G'#159#129#30#28#133#240
+ +#17#28#212#6'T'#211#152#5#4#180#18#17'(.'#25#11#163#253'yc}0k'#172#205#210
+ +#168'Y'#0#180#172#198#27#245'>'#247#202#196#0'B'#8#27'+*'#170'wT'#0'B'#128#19
+ +#209'!'#0#27#14#148#162#162'jc'#210#146#9#224'4"'#177'w'#185#218#140'D'#194
+ +'~n'#233'n)'#12#232'j'#2#198#9#232#168#251'n'#184'/'#207'+I?yA'#0'H'#206'I'
+ +#166'}'#150#244#201'tH'#255'J'#10''' '#155#20'i)4'#200'Q'#0'K&'#184#184'Y'
+ +#138#4#158#149#218'x'#167#25#209#135'i'#204#231#154#160#24#248#0'<'#235#252
+ +'b'#231'/*'#234#254'H'#226#250#198#214'G'#136'oW'#188#251'}'#186#215'C'#168
+ +#251#176#245'www'#23'd'#231'sl'#255#19#159#248'D'#254#162#131#223'yB>4'#163
+ +#164#13#192'7'#176#178#178#18#17#25#208'f'#204'}'#6'h'#1#216#225'(\1'#218#128
+ +#210#26#2#250#18'"'#164'h'#136#0'Y'#132'1a.'#160'g=dg!'#20'r'#210#11#166'i'
+ +#220#216#155'5'#215'G'#179#218'Z'#162#130#200'S'#5#25#20#146#220#169#7#240
+ +#141#243#207#28#15#148#31'7Y;'#8#226#22'}B'#131#9#130#29#141#202'5'#3#156#181
+ +#141#18#136#170#159#171#194'$'#200#171#209#1'U'#16#130#155#244#227'6'#222'4'
+ +#7#149#201#4#212'$'#192' u'#18'}'#12#232#177'dp'#188#211#146'/'#198'l'#199'c'
+ +#201#200'4/'#1#190#186'm'#181#137#204#250#20'`'#195'7'#195'y'#191'S'#159#236
+ +'t'#163#233#158#199'I'#5'b'#143#232#188#131'Ll|l'#1#244#236#224's'#128#143
+ +#134#29'#'#153#153#135#195'{'#198#222'7'#14'>'#216#249't'#175#199't'#159#167
+ +'('#224'[b'#235';W'#224#197#29#31'6'#2#176#191#217'h'#3#155#155#155#254't:'
+ +#13'1S1'#252#3'0'#11#232#223'-'#178#7#225#12'D6'#225#138'8'#7'W'#196'y'#168
+ +#157#132#158#215#164#199#177'A'#159'V;@'#4#30#224#166'Q:'#152#215#187#253'Yc'
+ +'}'#148#196'+'#185#22#233'V'#133'7)'#191'E'#135#225#162#243#176'K'#8#185#152
+ +#0#164'x'#16#25#212#153#28#130#176#206')'#201'>'#214'd>'#148#10#139'J'#191
+ +#244'`'#219#242'"G'#160#236#237#247'Jf@^$'#7#25'3'#1#248'K'#209'H'#19'@'#159
+ +'p'#197']'#150#152#245#212#206#198#163#242#195#0#15#252'f%'#147#1#239'1'#251
+ +#181'`1&'#21#127#167'GK'#232#193'!'#160'L'#237'0'#147'B'#154'iu'#223#177#241
+ ,#171#18#223#216#249#3#1'?'#146'w'#0'~^'#144#194'K'#210#30#197';'#172#238'w'
+ +#187#221#217#214#214'V'#226'x'#248'_X['#255#176#241'a$'#128#210'o_f'#22#208
+ +#225#26#217#130#28'6$'#2#128'F'#208's'#23#209#6#208'k'#160'm'#136#128#128#140
+ +'(CL'#251#16#211'Rc'#204#157#238'|'#180'*O'#9#206#251#179#198#234'h^'#235'M'
+ +#211#168#157#230#162#25#24#199#158'r'#10#131'J'#132'`'#156#127#190'>ig'#187
+ +#152#199#16']'#144#27'*'#8'"q:'#134'tX"'#17#158#164'"'#243#233#232#181'/Z'
+ +#134#150#190#137#216#218'R)'#151'9'#139's'#28#146#28#18#158'_'#207#225'7'#7
+ +#196#182#196#183#240#1#184#0'W'#165#130' 1#8T'#167#242#154#191#24#213#163#249
+ +#176'G*>Zn'#23#17#8#145#246'8'#3#2'>x'#18#206'}''o'#223#134#244#164'K'#207
+ +#184#2'|'#187#208'=d'#224'#'#172#135'L>"'#2#246#238'#'#149#151#8' '#251#176
+ +'I}w|'#152#9#192#140#3'f'#1'B'#127#244'p'#196#198'QH'#255'o'#9#216#187#244' '
+ +#245#184#150#128#136'@4'#2'v'#20'*'#204'T'#164#188':4'#2')4'#10#173'V'#224'#'
+ +#29'E'#251#10#176#13#208#18#9#212#137#12#186#147'E'#220#157'$q'#139#224#16#26
+ +'S'#161#232''''#232';'#205'D+'#246#190#152#2#150','#148#155'*l~'#150#252'@.'
+ +#30':$$'#232#216#255#182'EW'#169'1'#191#201#250'S'#165'\'#0'['#221#167#138
+ +#148'`'#6'u'#166'T'#158'/'#7'<'#214#181' '#25#215#131#249#176#25#207#251#237
+ +'h6'#242#149'8'#243'<61'#140'moA'#175't'#202'.'#24#133#213'|Y'#230#198#179'o'
+ +'T}'#19#211#151#5#158#254'>'#128'OD>'#140#162'h'#12#137'O'#199#167't'#127#23
+ +'t<'#249'0'#170#251#203#198#5#1#20#195's'#205#130';w'#238#4#198'?'#128'9'#7
+ +#232'!B'#205'@'#203#241#19#244'$'#140#200'k'#248#7#20'"'#6'9W'#26#214#161#209
+ +#18#216#17'm@BQ'#24#248#30#200' '#160'c>'#180'^F'#165'/'#229'<'#244'wL$@'#132
+ +#208#153'.'#162#206'4'#141#219#153#14#8#138#237'^T'#4#22'e'#194#170#168#10'T'
+ +#254'R'#240#219#191'U'#207#127#241#207'J'#246'_'#197#7'`Gn'#205#0#3'z'#183
+ +#145'g'#225'G(^g'#0#31#251#201#164#22#206#135#173'h>h'#147#164#15#252'4)^c'
+ +#153#197#128'^Y'#21#255#160#180'/'#169#250#144#248'p'#224')'#1#187#164#242
+ +#150#164#189#1'~'#171#213#154#141'F#'#246#236#147#169#151'~X'#213#253'e'#227
+ +#130#0#202#227#128#127#192#16#1'=H'#28':'#164#127's2'#17#173'['#244#0#162#216
+ +#168'+'#26#129#171#13#176#143#0#175#229#228'#'#223#135'Ya'#200' 8@'#6#128#174
+ +#158'`'#132'a'#142'|<"'#132#246'x'#17#183#146'4'#168#207#179#176#190'H'#131
+ +'Z'#170#160#219'k'#251#221'8'#245#140'K'#191'T'#13#184'$'#239#223#141#8#228
+ +#203'~t5'#20'h'#134'['#251#239#185#210#221#253#191#6'n'#228#167#211#208#207
+ +'fQ'#144#204#234#225'bL'#18'~'#16'.'#3#188#233#18'"'#182'C'#174#127#145#168
+ +#248'E'#214#30'-'#11'g'#218'-'#171#234'+'#157#190#203#224#167'{'#224#18#192
+ +#144'#'#179'I'#194#210#254#2#248'O'#31#23#4#176'|,%'#2'Z'#135#244'@'#177'F'#0
+ +'`'#211#186'I*f'#139#236'J'#214#10#132#16#12#9'X"@'#19#18#218#6'y'#212'@'#6
+ +' '#2#218#14#133#12'|'#218#151#194#2#206#177#169#16#130#178#128'N'#179' '#154
+ +'fQm'#158#16')'#164'!'#19'C'#146#250#181'E'#22#214'r'#195#2'y'#17#247#207#221
+ +#219#235#29#248'y2'#242#165#155#252#170'R'#11'0'#253'7'#240#178'E'#236#167
+ +#179#200'O'#166'Q'#152#206#226' '#153#214'BZ'#252'd^'#10#31#28#4#188#212#222
+ +#235#20']Ro'#178#220#168#19#185'JM'''#30'U'#150#246'('#207#157'J?>'#11'|'#168
+ +#251't'#157#135#0#191#0#30'j>&'#221#132'I0E'#6#159#249#172'%'#192'_'#242'K?'
+ +#188#227#130#0#158'<'#150#18#1'|'#4#237'6'#201#183#217#140';'#20#19#1#160#203
+ +#144#169'5h'#201#186'm'#246#141#198#0#243'@i'#13#2#4#2'2`"'#144#133#181#2'!'
+ +#4#175'B'#8#162#229#235'F'#0'E*'#191#201#243#247#2'"'#129'('#205#252' '#205
+ +#149#159#229'~'#0#19'"'#203#184#160')'#160#181#143#207'&'#158#241#233'8'#142
+ +#249'x'#15' '#233'{y'#202#139#162'Wy'#10#219#153'g'#142'y'#244#137'~'#158#6#4
+ +'N'#218'N#?K0C'#14#127#181#237#249#167#247#204'1}Z'#185#20#11'j'#213#222#145
+ +#240#12'B'#237#197#183'q{+'#237'Mi'#174#210#192#159'HW'#158#145'*'#128#15#169
+ +#143#184'='#239#147#186#143#10#189'1'#173'!'#241#209#140'snl'#252'G'#143#30
+ +'e'#23#192#127#250#184' '#128#163#13'K'#4#223#253#238'w=4%'#5#25#208#161#144
+ +#164'N'#212'l6'#1'd'#214#10#232#129'lxz'#174'B'#180'('#3#240#153#4'h'#223#144
+ +'C'#211#209#10'jB'#6#136#30'DJG'#16't'#20'A'#19#2#242#10#8#139#220#2'Dr'#130
+ +#217'y^'#164#249#225#143#239#219'm'#140#220'sN'#250#224#207#240#14#252'#?'
+ +#176#225#202#240#138#242' '#249#0'z;/'#210#133'9'#25#152#147'!3'#237'P'#212
+ +#21'x'#158#199#217#3'.'#224#233'X"'#221'vy'#150#29#167'@'#7#224#7#152'a'#223
+ +#143' '#229#165' '#135#215't|'#4#208'C'#210#3#244#240#230'c!'#2'^'#192#171'O'
+ +#199#211#11#224'?'#219#184' '#128'g'#27'%"@'#212#224#210#165'K>I'#164#144#30
+ +'D&'#3#180''''#4#168#145'a'#8'2'#192#2'2P'#152#202#220'Y'#132#8#140'i'#192
+ +#230#1'k'#5#30';'#14']B`2'#160'c'#1'b'#8#162#29'0'#17#152#22' '#24'y'#145#223
+ +#167'r'#183#11'`'#165#17#192#129'y'#9#151#254'J'#227#225'We'#253'_)'#227#164
+ +#211'h'#215'L$'#130']'#25#231#157#150#242#136#238#231'6Vo='#248#6#240'R'#142
+ +'k'#194'x'#0#255'd'#137#212#231'E'#18'vX'#189#23#21#127#14#208'c'#166']'#196
+ +#241'WVV2x'#245#137#148#243#11#224'?'#219#184' '#128#247'7l^-'#194#135#244#16
+ +'z'#198'<'#160#135#18#128'E'#143'B6'#17#224'/'#160'}'#16'B'#131#164#22#8#129
+ ,'5'#0#172'}'#157'Q'#216#144'F'#165'L'#4'R'#177#200#239#177'D'#160#29#136#161
+ +#199'A}'#144#129'v '#210#182#246#31'(]'#151' '#219#170#152'}'#132#165's'#209
+ +'4'#200#156#244'!, '#160'Vy^v'#3'j'#183#164'W'#184#253#10'U>7'#157't'#217#129
+ +''''#222'{'#165#165#188#5#190'S'#127#207'^|'#165#165'=/p'#236#161#209#6#253
+ +'~'#168#243#19#172'%'#166'?!'#160'c'#31#196'0C=>'#169#247' '#142#132#142'!y'
+ +#7#128#207#156'8'#190#156#253#5#232#159'e\'#16#192#7#27#150#8#240#0#186'Z'#1
+ +'I'#168'`gg'#7'R;'#132#137#0#243#20'd'#0'p'#139#218'_'#23#240'#'#215#192#128
+ +#159'5'#2'G30D`4'#3#215'g`'#9'Ai'#13#1'$'#16'pI?'#231#28's'#242#156'''`'#247
+ +#12#17'('#19';8D'#19'p'#192#207#0'/'#8'AK~'#165'{'#230#27#213'>'#173#0#222
+ +#196#233#141#138'o'#156'y'#0#191#241#228'O'#5#220'v'#27#199#1'~'#243#127#168
+ +#245'x}'#20'Es'#0#31#210#30#234'='#17'jz'#227#198#141#20#160#135#180'w'#242
+ +#245#249'|O'#251'a8'#143#227#130#0#158#223'8'#160#21#12#6#3#175#211#233#4#180
+ +#248#244#0#179#153#0'I'#14'S'#129#30#234#152#30'n'#164#31'C'#202#215#232'X'
+ +#141#142#25'S'#192#152#5#150#4#232#189#186'eY'#161#21#132'UBP'#154#20'x'#246
+ +'$!'#4#156#147'/'#224#247'DK'#176#219#149#243#182#170#188'2'#210#221#181#225
+ +'s''>/'#210']z'#234#25#208'/'#28#208'W'#213'|+'#245'E'#221#231#181#144#194#12
+ +'*=IwH'#249#5'@O@_'#200'g&'#0'=T|c'#219#11#232#205'y'#186#235#139#241'>'#198
+ +#5#1#28#207'Xj"'#208#218#7#25'@3'#160#7#157'M'#5','#4'nL'#127#142#233#206'"'
+ +#151#16'|'#157'?`4'#6#248#22'P'#189#24#11#17'D'#134#16'@*'#244#186'RD'#1'D@'
+ +#175'E'#196#194#19'2`"'#192#182#28#243#212#146'x`'#201#142'/'#0#159#27#21'_'
+ +#21'j=7'#212#196'B'#223#195#192#167#207#157#211#246#1#2#192'B'#191'k'#230#2
+ +#158#200#14#210#29#239'Y@'#194#131'H'#232'xj$'#189#1'=]'#175#188#162#226#187
+ +#235#139#241#1#199#5#1#28#239#176#215#215'8'#14#141'f'#0'3aoo'#143#9'!@i'#218
+ +'`'#16#192'l'#160#151#134' '#3#172'A'#8' '#7':'#206'k'#128#158'^'#202'k9'#30
+ +#154#227'J'#252#4#202'1'#13#180'I'#192'f'#128'oH'#0#231#148'!.X'#144'@q'#178
+ +#5#208'sQ'#237'-'#240#177#166#247'X'#201#175#196#161''''#4#176'0'#251#134#0
+ +'d!<'''#6#228#144#236#176#223#23'Fk'#0#224#137#3#210#181#181#181#148'~?'#212
+ +#250#140'L'#168#28#160#191'p'#232#157#204#184' '#128#147#27#165'D\'#233'Y'
+ +#168'@'#8#208#12'n'#222#188#233'-#'#4#12#2'M '#160#14#5#212'au'#219#172#149
+ +'&'#14#214#0'0'#0'v'#1'k6'#155#217't:'#205#232#156#243'e'#18'~'#9#224#171#219#23#227#152
+ +#199#5#1#156#141'Q'#186#15#198'\'#192#182'1'#25#8'H'#30'H'#129'H'#192'#py'
+ +#134#24#8#148#30#200#129#128#232#25'r'#160'}'#143'@j'#23':'#206#128#199'6>'
+ +#19#219#4'V'#187#141#181#207#253'L'#148'"'#0#27#192#243'>}/o'#155#133#190'?'
+ +#7#208#137'Dr'#128#156#190'+'#235#247#251'9'#129#222#2#29#146#189#221'n'#231
+ +#6#236#248#156#11#192#159#205'qA'#0'gsT'#239#139''''#192'Q.1`'#13'r'#184'u'
+ +#235#150'7'#28#14'-9'#224'8'#8#2'k'#179'O'#192#230'5'#8#3#235#245#245'u'#187
+ +'m'#6#128#140'5Iy'#11'J'#2';o'#3#220'X?~'#252'8'#199'6@'#142#253'e@'#199#250
+ +#16#176'/'#219#191#24#167'8.'#8#224'|'#141'e'#247#235#0'9`'#24#130'0'#3'D'
+ +#177#236#3#161'Y`]'#175#215#15#0#211#128#218#29#6#224#24#0'9'#214#135#0#253
+ +#176'c'#23#227#12#141#11#2'x1'#198#179#220#199#163#190#246#168#224#189#0#249
+ +'9'#30#23#4'p1.'#198#135'x'#252#127'p'#251'ut'#3#215#244'"'#0#0#0#0'IEND'#174
+ +'B`'#130'('#0#0#0#128#0#0#0#0#1#0#0#1#0' '#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#1#0#0#0#1#0#0#0#1#0#0#0#1#0#0#0#1#0#0#0#1#0#0#0#1#0#0
+ +#0#1#0#0#0#1#0#0#0#1#0#0#0#1#0#0#0#1#0#0#0#1#0#0#0#1#0#0#0#1#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ ,#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#1#0#0#0#1#0#0#0#2#128#128#128#2'UUU'#3'@@@'#4'333'#5'III'#7'@@@'#8
+ +'999'#9'999'#9'MMM'#10'FFF'#11'FFF'#11'FFF'#11'MMM'#10'999'#9'@@@'#8'@@@'#8
+ +'UUU'#6'333'#5'UUU'#3#128#128#128#2#0#0#0#2#0#0#0#1#0#0#0#1#0#0#0#1#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#1#0#0#0#1#128#128#128#2'UUU'#3'UUU'#6'@@@'#8'FFF'#11'III'#14'<<'
+ +'<'#17'III'#21'EEE'#26'DDD'#30'DDD"EEE%AAA''DDD)AAA+AAA+AAA+DDD)AAA''GGG$FFF'
+ +'!DDD'#30'==='#25'@@@'#20'@@@'#16';;;'#13'FFF'#11'@@@'#8'333'#5'UUU'#3#128
+ +#128#128#2#0#0#0#1#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1#0#0#0
+ +#2'UUU'#3'+++'#6'999'#9'NNN'#13'CCC'#19'BBB'#27'GGG$DDD-CCC5DDD'#211'SC6'#219'W@0'#227'[>+'#235']<('#238'^<'''#240
+ +'_<%'#243'`<#'#245'a;"'#247'a:!'#248'a;"'#246'`<$'#245'_<%'#242'^='''#240'\='
+ +')'#237'Z=,'#233'V@1'#225'RD8'#217'NG?'#210'JHD'#204'IHC'#204'HHD'#204'GEC'
+ +#203'FEC'#202'EED'#198'EED'#195'DDC'#190'DDC'#183'DDD'#172'DDD'#157'DDD'#138
+ +'DDDtCCC\DDDDCCC.@@@'#28'DDD'#15'III'#7'UUU'#3#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'UUU'#3'@@'
+ +'@'#8'KKK'#17'HHH CCC5CCCPDDDlCCC'#134'DDC'#156'EED'#172'FEC'#185'GFD'#193'G'
+ +'FC'#198'HFC'#202'IGD'#203'PE;'#213'VA0'#227']<('#239'a;#'#246'd9'#30#254'g:'
+ +#29#255'g:'#30#255'i<'#30#255'j='#31#255'j>'#30#255'k>'#30#255'l?'#31#255'l@'
+ +#31#255'mA'#31#255'nA'#31#255'm@'#31#255'l@'#31#255'l?'#31#255'k>'#30#255'j>'
+ +#30#255'j='#31#255'i<'#30#255'g:'#30#255'f:'#29#255'd9'#31#252'`<#'#245'[=*'
+ +#236'UA3'#223'MF?'#210'IHC'#204'HFD'#204'FFC'#203'FFE'#200'DDC'#197'EED'#191
+ +'DCC'#182'DDD'#170'CCC'#152'CCC'#129'DDDfDDDKDDD1FFF'#29'@@@'#16'III'#7'UUU'
+ +#3#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'UUU'#3'II'
+ +'I'#7'@@@'#16'@@@ FFF7DDDRCCCoCCC'#140'DDC'#163'EED'#180'EED'#191'FFC'#198'I'
+ +'GD'#201'ME?'#208'UA2'#224'\<('#238'b9 '#250'f:'#29#255'h;'#30#255'j>'#30#255
+ +'m@'#31#255'oB '#255'qD '#255'sF '#255'uH!'#255'|L#'#255#128'O$'#255#133'Q%'
+ +#255#136'S&'#255#139'V'''#255#143'X('#255#145'Y)'#255#142'W('#255#139'U'''
+ +#255#135'S&'#255#131'Q%'#255#128'O$'#255'yK"'#255'tG!'#255'rE '#255'pD '#255
+ +'nA '#255'l@'#31#255'j='#31#255'g;'#30#255'e9'#29#255'a;!'#247'Z=+'#234'RB5'
+ +#221'JGC'#207'HFD'#204'FEC'#203'FFE'#200'EED'#196'DDC'#189'DDD'#177'CCC'#159
+ +'DDD'#135'CCCjBBBMBBB2FFF'#29'III'#14'UUU'#6#128#128#128#2#0#0#0#1#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#2'333'#5';;;'#13'BBB'#27'AAA3BBBQDDDqDDD'#142'EED'#165
+ +'EDB'#183'FEC'#194'HFD'#200'IFB'#205'SA3'#223'^;&'#242'e8'#29#255'g;'#30#255
+ +'j>'#31#255'mA'#31#255'pD!'#255'tG!'#255'~M#'#255#141'W('#255#151']*'#255#160
+ +'c-'#255#169'i0'#255#178'n1'#255#181'q2'#255#182's3'#255#183't3'#255#184't3'
+ +#255#184'v3'#255#185'v4'#255#186'w3'#255#185'v3'#255#184'u3'#255#184't3'#255
+ +#183't3'#255#182'r3'#255#181'q2'#255#175'l1'#255#166'h/'#255#158'a,'#255#149
+ ,'\*'#255#138'U('#255'zK"'#255'sF '#255'pC '#255'l@'#31#255'i='#31#255'g;'#30
+ +#255'c8'#31#252'[<*'#237'RC8'#218'IGD'#205'HFD'#204'EED'#201'DDC'#198'EED'
+ +#191'DDD'#179'CCC'#161'DDD'#136'CCCkEEEJDDD-@@@'#24'FFF'#11'@@@'#4#0#0#0#1#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#1'UUU'#3'999'#9'FFF'#22'CCC*DDDGDDDiCCC'#138'EED'#165'FEC'#184'FEC'#194
+ +'HHD'#200'QC9'#216'[<*'#237'c8'#31#253'g;'#30#255'j>'#31#255'nA '#255'sF!'
+ +#255'|M#'#255#141'W('#255#158'a,'#255#173'k1'#255#181'r3'#255#185'v4'#255#187
+ +'y4'#255#189'{4'#255#191'~5'#255#193#129'5'#255#195#131'5'#255#196#132'6'#255
+ +#197#134'6'#255#198#134'6'#255#199#136'6'#255#200#136'6'#255#200#137'6'#255
+ +#199#136'6'#255#198#135'6'#255#198#134'6'#255#197#133'5'#255#196#132'6'#255
+ +#195#131'5'#255#193#128'5'#255#191'~4'#255#188'z4'#255#186'x4'#255#184'u3'
+ +#255#181'q2'#255#168'i/'#255#153'_+'#255#137'T'''#255'yJ"'#255'rE '#255'm@'
+ +#31#255'i<'#31#255'f:'#30#255'b9!'#249'X>.'#232'MD>'#212'HFD'#204'EED'#202'E'
+ +'ED'#198'EED'#192'CCC'#180'CCC'#160'DDD'#132'DDDbCCCACCC&CCC'#19'@@@'#8'UUU'
+ +#3#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'333'#5
+ +'III'#14'>>>!DDD'#255
+ +#232#177'>'#255#234#179'?'#255#236#181'>'#255#236#182'?'#255#237#183'?'#255
+ ,#237#183'?'#255#238#183'@'#255#238#184'?'#255#238#185'?'#255#238#184'?'#255
+ +#238#183'@'#255#237#182'?'#255#237#183'?'#255#236#182'?'#255#236#181'>'#255
+ +#234#179'>'#255#232#176'>'#255#230#175'>'#255#229#172'='#255#227#169'='#255
+ +#224#167'='#255#220#161'<'#255#217#157'<'#255#213#153';'#255#209#148':'#255
+ +#204#142'9'#255#198#135'8'#255#193#129'7'#255#188'{6'#255#183't5'#255#171'k2'
+ +#255#142'W)'#255'tH"'#255'nA '#255'h<'#31#255'd7'#30#255'[:('#240'KD?'#211'G'
+ +'FD'#204'DDC'#201'EDD'#195'CCC'#182'CCC'#159'CCC}EEEUBBB2@@@'#24'999'#9'UUU'
+ +#3#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#1'333'#5'III'#14'BBB#EEECCCCkEEE'#145'DDC'#174'FFE'#192'KE@'#206'Z;)'
+ +#238'c8'#30#255'i<'#31#255'oB!'#255'|M%'#255#153'_-'#255#178'o4'#255#186'x6'
+ +#255#192#128'7'#255#198#135'9'#255#204#142':'#255#209#149';'#255#214#155'='
+ +#255#219#161'>'#255#223#167'>'#255#227#170'>'#255#230#174'?'#255#232#177'@'
+ +#255#235#181'A'#255#237#183'A'#255#238#185'A'#255#240#187'A'#255#241#188'A'
+ +#255#242#189'B'#255#243#190'A'#255#244#191'B'#255#244#192'B'#255#244#191'B'
+ +#255#244#192'B'#255#244#192'B'#255#245#193'A'#255#244#192'B'#255#244#192'B'
+ +#255#244#191'B'#255#244#192'B'#255#244#191'B'#255#243#190'A'#255#242#189'B'
+ +#255#240#187'A'#255#239#186'A'#255#238#184'@'#255#237#183'A'#255#235#179'@'
+ +#255#232#176'?'#255#229#173'?'#255#226#169'?'#255#223#165'>'#255#218#160'='
+ +#255#213#153'<'#255#208#147';'#255#202#140':'#255#196#133'9'#255#190'~7'#255
+ +#184'v6'#255#173'l3'#255#145'Y+'#255'uH$'#255'm@ '#255'g;'#31#255'b7'#31#253
+ +'U>/'#230'IEC'#206'FFE'#202'EED'#199'CCC'#189'DDD'#170'DDD'#139'BBBdCCC=BBB'
+ +#31'@@@'#12'UUU'#3#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#1'UUU'#6'KKK'#17'DDD)EEENDDDxDCC'#157'DDC'#182'GGC'#197'T=1'#225'a7 '
+ +#252'g;'#31#255'l@ '#255'wI$'#255#154'^.'#255#179'o6'#255#186'x7'#255#193#128
+ +'9'#255#200#137':'#255#207#146'<'#255#212#153'>'#255#217#159'>'#255#222#166
+ +'?'#255#227#170'@'#255#231#175'A'#255#234#180'B'#255#236#182'B'#255#238#185
+ +'B'#255#240#187'B'#255#242#190'D'#255#243#191'C'#255#244#192'D'#255#245#193
+ +'C'#255#246#194'D'#255#247#194'D'#255#247#196'E'#255#247#196'D'#255#247#196
+ +'D'#255#248#197'D'#255#248#197'D'#255#248#197'D'#255#248#197'D'#255#248#197
+ +'D'#255#248#197'D'#255#248#196'D'#255#247#196'D'#255#247#196'D'#255#247#195
+ +'E'#255#246#195'D'#255#245#193'D'#255#245#193'C'#255#244#192'D'#255#243#191
+ +'C'#255#242#189'C'#255#240#186'C'#255#238#184'C'#255#236#182'B'#255#233#179
+ +'B'#255#230#174'A'#255#226#169'@'#255#221#164'?'#255#216#157'>'#255#211#151
+ +'='#255#205#143'<'#255#198#135':'#255#191#127'8'#255#184'w7'#255#174'l4'#255
+ +#144'X+'#255'rE"'#255'j> '#255'e9'#30#255'_8"'#247'O@8'#219'GFD'#204'DDC'#201
+ +'CCC'#194'CCC'#178'DDD'#151'DDDqDDDGGGG$III'#14'@@@'#4#0#0#0#1#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#2'III'#7'@@@'#20'CCC.DDDVCCC'#130'EED'#165'DDC'#189
+ +'LB='#207']7$'#244'd7'#31#255'j> '#255'qE"'#255#140'W+'#255#174'l5'#255#186
+ +'x8'#255#193#129':'#255#200#138'<'#255#207#146'>'#255#213#155'?'#255#220#163
+ +'@'#255#225#169'A'#255#229#174'B'#255#233#179'D'#255#236#182'D'#255#239#185
+ +'D'#255#241#189'E'#255#242#190'E'#255#244#192'E'#255#245#194'E'#255#246#195
+ +'F'#255#247#195'F'#255#247#196'G'#255#247#197'F'#255#248#197'F'#255#248#197
+ +'F'#255#249#198'F'#255#249#198'G'#255#249#198'G'#255#249#198'G'#255#249#198
+ +'G'#255#249#198'G'#255#249#198'G'#255#249#198'G'#255#249#198'G'#255#249#198
+ +'G'#255#249#198'G'#255#249#198'G'#255#249#198'F'#255#248#197'F'#255#248#197
+ +'F'#255#247#196'F'#255#247#196'F'#255#247#195'F'#255#246#194'F'#255#244#193
+ +'F'#255#243#191'E'#255#242#190'E'#255#240#188'E'#255#238#185'D'#255#235#181
+ +'D'#255#232#178'C'#255#228#172'C'#255#223#167'B'#255#218#161'@'#255#212#153
+ +'?'#255#205#144'='#255#198#135';'#255#191#127'9'#255#183'u7'#255#167'g3'#255
+ +#130'P('#255'oB"'#255'h< '#255'c7'#30#255'X:*'#237'HFB'#207'EEE'#202'DCC'#197
+ +'DDD'#184'CCC'#160'CCCzEEENFFF(@@@'#16'333'#5#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ ,#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#2
+ +'III'#7'FFF'#22'BBB2CCC\DDD'#136'DDC'#171'EED'#192'Q?5'#219'a6'#31#252'f:'#31
+ +#255'mA!'#255#127'N'''#255#164'f3'#255#182'u8'#255#190#127':'#255#199#138'='
+ +#255#207#147'?'#255#213#155'A'#255#220#163'B'#255#225#170'D'#255#230#177'E'
+ +#255#234#181'E'#255#237#184'F'#255#240#188'G'#255#242#189'G'#255#243#192'G'
+ +#255#244#193'H'#255#245#194'H'#255#246#195'H'#255#247#196'H'#255#247#197'H'
+ +#255#247#197'H'#255#248#198'H'#255#248#198'H'#255#248#197'H'#255#248#198'H'
+ +#255#248#198'I'#255#249#198'I'#255#249#198'I'#255#249#198'I'#255#249#198'I'
+ +#255#249#198'I'#255#249#198'I'#255#249#198'I'#255#249#198'I'#255#249#198'I'
+ +#255#249#198'I'#255#249#198'I'#255#248#198'I'#255#248#198'H'#255#248#198'H'
+ +#255#248#198'H'#255#248#198'H'#255#247#197'H'#255#247#196'I'#255#247#195'H'
+ +#255#246#195'H'#255#245#195'H'#255#244#193'H'#255#243#191'G'#255#241#189'G'
+ +#255#239#186'G'#255#236#183'F'#255#233#180'F'#255#229#175'D'#255#224#168'D'
+ +#255#218#161'B'#255#211#153'@'#255#205#144'?'#255#196#134'='#255#188'{:'#255
+ +#180'r8'#255#155'_/'#255'wJ$'#255'j? '#255'e8'#30#255']8#'#246'LB<'#213'FEE'
+ +#203'EED'#199'DDD'#188'DDD'#165'DDD'#128'DDDSFFF,GGG'#18'+++'#6#0#0#0#1#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#2'III'#7'CCC'#23'BBB6DDDaCCC'#141'DDC'#174'GDB'#196'V:+'#233'c7'#30#255'h; '
+ +#255'pC#'#255#146'Z-'#255#179'p7'#255#187'{;'#255#196#133'='#255#204#144'?'
+ +#255#212#154'B'#255#219#163'E'#255#225#170'E'#255#230#176'G'#255#234#181'H'
+ +#255#238#185'I'#255#240#189'I'#255#242#190'J'#255#243#192'J'#255#244#193'J'
+ +#255#245#195'J'#255#246#195'J'#255#246#196'J'#255#247#196'K'#255#247#196'K'
+ +#255#247#197'K'#255#247#197'K'#255#247#197'K'#255#247#197'J'#255#247#197'J'
+ +#255#247#198'J'#255#247#198'J'#255#247#198'J'#255#247#198'J'#255#247#198'J'
+ +#255#247#198'J'#255#247#198'J'#255#247#198'J'#255#247#198'J'#255#247#198'J'
+ +#255#247#198'J'#255#247#198'J'#255#247#198'J'#255#247#198'J'#255#247#197'J'
+ +#255#247#197'J'#255#247#197'J'#255#247#197'K'#255#247#197'K'#255#247#197'K'
+ +#255#247#196'K'#255#246#196'K'#255#246#196'J'#255#246#195'J'#255#245#195'J'
+ +#255#244#194'J'#255#243#191'I'#255#241#189'I'#255#239#188'I'#255#236#184'H'
+ +#255#233#180'H'#255#228#174'G'#255#223#168'E'#255#217#160'C'#255#210#151'B'
+ +#255#202#141'?'#255#193#130'<'#255#185'x:'#255#174'm6'#255#134'S*'#255'mA"'
+ +#255'f:'#31#255'a6'#30#253'R>4'#224'FFE'#203'EED'#200'CCC'#190'DDD'#169'CCC'
+ +#133'CCCXAAA/CCC'#19'+++'#6#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#1'III'#7'CCC'#23'BBB6CCCcCCC'#144'EED'#177'JC>'#202
+ +'[6"'#244'c8'#31#255'j?!'#255'xI&'#255#162'd2'#255#183'u:'#255#192#129'='#255
+ +#200#140'@'#255#209#150'B'#255#217#160'E'#255#223#169'G'#255#229#176'H'#255
+ +#233#181'J'#255#236#185'J'#255#239#188'K'#255#241#190'K'#255#242#192'K'#255
+ +#243#193'L'#255#244#194'L'#255#245#195'L'#255#245#195'L'#255#245#195'L'#255
+ +#246#196'L'#255#246#196'L'#255#246#196'L'#255#246#196'L'#255#246#196'M'#255
+ +#246#196'M'#255#246#197'M'#255#246#197'M'#255#246#197'M'#255#246#197'M'#255
+ +#246#197'M'#255#246#197'M'#255#246#197'M'#255#246#197'M'#255#246#197'M'#255
+ +#246#197'M'#255#246#197'M'#255#246#197'M'#255#246#197'M'#255#246#197'M'#255
+ +#246#197'M'#255#246#197'M'#255#246#197'M'#255#246#197'M'#255#246#196'M'#255
+ +#246#196'M'#255#246#196'M'#255#246#196'L'#255#246#196'L'#255#246#196'L'#255
+ +#246#196'L'#255#245#195'L'#255#245#196'L'#255#244#195'M'#255#244#194'L'#255
+ +#243#193'L'#255#242#192'L'#255#241#190'K'#255#238#188'K'#255#236#184'J'#255
+ +#232#179'I'#255#228#173'H'#255#222#166'F'#255#215#158'E'#255#207#148'B'#255
+ +#198#137'?'#255#190'~<'#255#180'r9'#255#150']/'#255'qE$'#255'h< '#255'b6'#30
+ +#255'W9*'#235'GED'#204'DDC'#201'DDD'#192'CCC'#172'CCC'#137'DDDZAAA/GGG'#18'3'
+ +'33'#5#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'+++'#6'II'
+ +'I'#21'CCC5DDDbCCC'#145'DDC'#178'LB;'#206'^6 '#249'd8'#31#255'l@!'#255#131'Q'
+ +'*'#255#172'k7'#255#186'z;'#255#196#133'?'#255#205#146'C'#255#213#156'E'#255
+ +#220#165'G'#255#227#173'I'#255#232#180'K'#255#236#184'L'#255#238#187'L'#255
+ ,#240#189'N'#255#241#191'N'#255#242#192'N'#255#243#193'N'#255#244#194'N'#255
+ +#244#194'N'#255#244#194'O'#255#244#195'O'#255#244#195'O'#255#244#195'O'#255
+ +#244#195'O'#255#244#195'O'#255#244#195'O'#255#244#195'O'#255#244#195'O'#255
+ +#244#195'O'#255#244#195'O'#255#244#195'O'#255#244#195'O'#255#244#195'O'#255
+ +#244#195'O'#255#244#195'O'#255#244#195'O'#255#244#195'O'#255#244#195'O'#255
+ +#244#195'O'#255#244#195'O'#255#244#195'O'#255#244#195'O'#255#244#195'O'#255
+ +#244#195'O'#255#244#195'O'#255#244#195'O'#255#244#195'O'#255#244#195'O'#255
+ +#244#195'O'#255#244#195'O'#255#244#195'O'#255#244#195'O'#255#244#195'O'#255
+ +#244#195'O'#255#244#195'O'#255#244#194'O'#255#244#195'N'#255#244#194'N'#255
+ +#243#193'N'#255#242#192'M'#255#241#190'N'#255#240#189'M'#255#237#186'M'#255
+ +#235#182'L'#255#230#178'K'#255#225#171'I'#255#219#163'G'#255#211#153'D'#255
+ +#202#143'B'#255#192#130'>'#255#183'u:'#255#164'f4'#255'yK&'#255'i=!'#255'c7'
+ +#30#255'Z8%'#241'GEC'#205'DDC'#201'CCC'#193'DDD'#173'DDD'#136'BBBYDDD-KKK'#17
+ +'333'#5#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'333'#5'CCC'#19'BBB2CCC_DD'
+ +'D'#143'DDC'#178'M@8'#211'_5'#31#251'e9'#31#255'lA"'#255#144'Y/'#255#179'r9'
+ +#255#188'}='#255#198#138'B'#255#208#149'D'#255#217#161'H'#255#223#170'K'#255
+ +#229#177'L'#255#234#181'M'#255#236#186'N'#255#239#188'O'#255#240#190'P'#255
+ +#241#191'P'#255#242#192'P'#255#242#192'P'#255#242#193'P'#255#243#193'P'#255
+ +#243#194'P'#255#243#194'P'#255#243#194'P'#255#243#194'P'#255#243#194'P'#255
+ +#243#194'P'#255#243#194'P'#255#243#194'P'#255#243#194'P'#255#243#194'P'#255
+ +#243#194'P'#255#243#194'P'#255#243#194'P'#255#243#194'P'#255#243#194'P'#255
+ +#243#194'P'#255#243#194'P'#255#243#194'P'#255#243#194'P'#255#243#194'P'#255
+ +#243#194'P'#255#243#194'P'#255#243#194'P'#255#243#194'P'#255#243#194'P'#255
+ +#243#194'P'#255#243#194'P'#255#243#194'P'#255#243#194'P'#255#243#194'P'#255
+ +#243#194'P'#255#243#194'P'#255#243#194'P'#255#243#194'P'#255#243#194'P'#255
+ +#243#194'P'#255#243#194'P'#255#243#194'P'#255#243#194'P'#255#243#193'P'#255
+ +#242#193'P'#255#242#192'O'#255#242#192'P'#255#241#192'P'#255#240#190'P'#255
+ +#238#188'O'#255#236#185'N'#255#232#180'M'#255#228#175'L'#255#222#167'I'#255
+ +#215#159'H'#255#205#147'D'#255#196#134'@'#255#186'y<'#255#173'm7'#255#130'O*'
+ +#255'j?!'#255'c8'#31#255'[7#'#245'HDA'#208'DDC'#201'CCC'#193'CCC'#172'CCC'
+ +#134'AAAVAAA+@@@'#16'@@@'#4#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'@@@'#4'<<<'#17'CCC.CC'
+ +'C[CCC'#140'EED'#176'O>5'#213'_5'#30#253'e9'#31#255'nB#'#255#151'\1'#255#181
+ +'s:'#255#191#129'@'#255#201#142'C'#255#211#154'G'#255#219#164'K'#255#226#173
+ +'M'#255#231#179'O'#255#234#184'P'#255#237#187'Q'#255#239#189'Q'#255#240#190
+ +'R'#255#240#191'Q'#255#241#192'R'#255#241#192'R'#255#241#192'R'#255#242#192
+ +'R'#255#242#192'R'#255#242#193'R'#255#242#193'R'#255#242#193'R'#255#242#193
+ +'R'#255#242#193'R'#255#242#193'R'#255#242#193'R'#255#242#193'R'#255#242#193
+ +'R'#255#242#193'R'#255#242#193'R'#255#242#193'R'#255#242#193'R'#255#242#193
+ +'R'#255#242#193'R'#255#242#193'R'#255#242#193'R'#255#242#193'R'#255#242#193
+ +'R'#255#242#193'R'#255#242#193'R'#255#242#193'R'#255#242#193'R'#255#242#193
+ +'R'#255#242#193'R'#255#242#193'R'#255#242#193'R'#255#242#193'R'#255#242#193
+ +'R'#255#242#193'R'#255#242#193'R'#255#242#193'R'#255#242#193'R'#255#242#193
+ +'R'#255#242#193'R'#255#242#193'R'#255#242#193'R'#255#242#193'R'#255#242#193
+ +'R'#255#242#192'R'#255#242#192'R'#255#241#192'R'#255#241#192'R'#255#241#192
+ +'R'#255#240#191'Q'#255#240#190'R'#255#238#189'Q'#255#236#186'P'#255#234#182
+ +'O'#255#230#177'N'#255#224#171'L'#255#217#162'J'#255#208#150'F'#255#198#138
+ +'C'#255#188'}>'#255#177'o:'#255#136'S,'#255'k?"'#255'c8'#31#255'\6!'#248'JC?'
+ +#211'DCC'#201'CCC'#193'CCC'#171'BBB'#131'DDDRAAA''777'#14'UUU'#3#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +'UUU'#3';;;'#13'AAA''CCCTBBB'#135'DDC'#174'N=5'#213'`4'#29#254'e9'#31#255'oC'
+ +'$'#255#156'`3'#255#181'u<'#255#193#131'A'#255#204#146'E'#255#213#157'I'#255
+ +#221#167'M'#255#227#175'O'#255#232#180'Q'#255#235#184'R'#255#237#187'S'#255
+ +#238#189'S'#255#239#190'S'#255#240#191'T'#255#240#191'T'#255#240#191'T'#255
+ +#240#191'T'#255#240#191'T'#255#240#191'T'#255#240#191'T'#255#240#191'T'#255
+ +#240#191'T'#255#240#191'T'#255#240#191'T'#255#240#191'T'#255#240#191'T'#255
+ +#240#191'T'#255#240#191'T'#255#240#191'T'#255#240#191'T'#255#240#191'T'#255
+ ,#240#191'T'#255#240#191'T'#255#240#191'T'#255#240#191'T'#255#240#191'T'#255
+ +#234#187'R'#255#202#161'G'#255#232#185'R'#255#240#191'T'#255#240#191'T'#255
+ +#240#191'T'#255#240#191'T'#255#240#191'T'#255#240#191'T'#255#240#191'T'#255
+ +#240#191'T'#255#240#191'T'#255#240#191'T'#255#240#191'T'#255#240#191'T'#255
+ +#240#191'T'#255#240#191'T'#255#240#191'T'#255#240#191'T'#255#240#191'T'#255
+ +#240#191'T'#255#240#191'T'#255#240#191'T'#255#240#191'T'#255#240#191'T'#255
+ +#240#191'T'#255#240#191'T'#255#240#191'T'#255#240#191'T'#255#240#191'T'#255
+ +#239#189'S'#255#238#188'R'#255#236#186'R'#255#234#184'Q'#255#231#179'Q'#255
+ +#226#173'O'#255#219#165'L'#255#211#154'H'#255#201#142'E'#255#190#128'@'#255
+ +#179'q:'#255#140'V.'#255'l@"'#255'c8'#31#255'\4'#31#250'JC>'#211'CCC'#201'DD'
+ +'D'#192'CCC'#168'CCC~DDDKFFF!MMM'#10#128#128#128#2#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#128#128#128#2'333'#10'@@@ EEE'
+ +'JCCC~EDD'#169'L?8'#208'^4'#30#253'd8 '#255'pD%'#255#159'b4'#255#182'v='#255
+ +#194#132'C'#255#205#147'H'#255#215#160'L'#255#222#169'O'#255#228#176'Q'#255
+ +#232#181'S'#255#235#185'T'#255#236#187'T'#255#237#188'U'#255#238#189'U'#255
+ +#238#190'U'#255#238#190'U'#255#238#191'U'#255#239#190'U'#255#239#190'U'#255
+ +#239#190'U'#255#239#190'U'#255#239#190'U'#255#239#190'U'#255#239#190'U'#255
+ +#239#190'U'#255#239#190'U'#255#239#190'U'#255#239#190'U'#255#239#190'U'#255
+ +#239#190'U'#255#239#190'U'#255#239#190'U'#255#239#190'U'#255#181#144'@'#255
+ +';/'#21#255#21#16#7#255#9#7#3#255#2#2#1#255#0#0#0#255#0#0#0#255#0#0#0#255#1#1
+ +#1#255#7#6#3#255#17#14#6#255#31#25#11#255'2'''#18#255'SB'#29#255#157'}8'#255
+ +#233#186'S'#255#239#190'U'#255#239#190'U'#255#239#190'U'#255#239#190'U'#255
+ +#239#190'U'#255#239#190'U'#255#239#190'U'#255#239#190'U'#255#239#190'U'#255
+ +#239#190'U'#255#239#190'U'#255#239#190'U'#255#239#190'U'#255#239#190'U'#255
+ +#239#190'U'#255#239#190'U'#255#239#190'U'#255#238#190'U'#255#238#190'U'#255
+ +#238#190'U'#255#238#189'U'#255#237#188'U'#255#236#186'T'#255#234#184'T'#255
+ +#231#180'S'#255#226#175'Q'#255#220#166'N'#255#212#156'K'#255#202#143'F'#255
+ +#190#129'A'#255#179'r<'#255#145'Y0'#255'k?"'#255'c7'#31#255'[4 '#248'IC@'#209
+ +'DDD'#200'CCC'#190'CCC'#163'DDDtCCCAEEE'#26'III'#7#0#0#0#1#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'III'#7'==='#25'AAA?CCCsBBB'
+ +#162'K?;'#202'^4'#30#252'c8 '#255'oB%'#255#160'b5'#255#183'v>'#255#194#134'D'
+ +#255#205#148'J'#255#215#161'M'#255#223#171'Q'#255#228#177'T'#255#232#182'U'
+ +#255#234#185'V'#255#236#187'V'#255#236#187'V'#255#237#188'W'#255#237#189'W'
+ +#255#237#188'W'#255#237#188'W'#255#237#188'W'#255#237#188'W'#255#237#188'W'
+ +#255#237#188'W'#255#237#188'W'#255#237#188'W'#255#237#188'W'#255#237#188'W'
+ +#255#237#188'W'#255#237#188'W'#255#237#188'W'#255#237#188'W'#255#237#188'W'
+ +#255#237#188'W'#255#237#188'W'#255#159'~:'#255#16#13#6#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1#0#0#255#16#13#6
+ +#255'9-'#21#255'y`,'#255#208#165'M'#255#237#188'W'#255#237#188'W'#255#237#188
+ +'W'#255#237#188'W'#255#237#188'W'#255#237#188'W'#255#237#188'W'#255#237#188
+ +'W'#255#237#188'W'#255#237#188'W'#255#237#188'W'#255#237#188'W'#255#237#188
+ +'W'#255#237#188'W'#255#237#188'W'#255#237#188'W'#255#237#189'W'#255#237#188
+ +'W'#255#236#187'V'#255#235#186'V'#255#234#184'U'#255#231#180'U'#255#227#175
+ +'R'#255#221#169'Q'#255#213#157'L'#255#202#144'H'#255#191#129'C'#255#180's='
+ +#255#145'X0'#255'j>#'#255'b6'#31#255'Z5#'#245'GDB'#206'DDD'#200'CCC'#186'DDD'
+ +#154'EEEhBBB6@@@'#20'333'#5#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#1'@@@'#4'GGG'#18'AAA3DDDfCCC'#152'IA>'#195'\4 '#250'c7'#31#255'm@#'#255
+ +#156'_5'#255#182'v?'#255#194#134'E'#255#206#148'K'#255#215#161'O'#255#223#171
+ +'S'#255#228#178'V'#255#232#182'V'#255#233#185'X'#255#234#186'X'#255#235#187
+ +'X'#255#236#187'X'#255#236#188'X'#255#236#188'X'#255#236#188'X'#255#236#188
+ +'X'#255#236#188'X'#255#236#188'X'#255#236#188'X'#255#236#188'X'#255#236#188
+ +'X'#255#236#188'X'#255#236#188'X'#255#236#188'X'#255#236#188'X'#255#236#188
+ +'X'#255#236#188'X'#255#236#188'X'#255#236#188'X'#255#236#188'X'#255'9-'#21
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#6
+ +#5#2#255'$'#29#14#255'ZH"'#255#169#135'@'#255#234#186'X'#255#236#188'X'#255
+ ,#236#188'X'#255#236#188'X'#255#236#188'X'#255#236#188'X'#255#236#188'X'#255
+ +#236#188'X'#255#236#188'X'#255#236#188'X'#255#236#188'X'#255#236#188'X'#255
+ +#236#188'X'#255#236#187'X'#255#235#187'Y'#255#235#186'X'#255#234#186'X'#255
+ +#233#184'W'#255#231#180'W'#255#227#176'T'#255#221#169'R'#255#213#158'N'#255
+ +#203#145'J'#255#192#130'D'#255#179's='#255#139'U/'#255'i="'#255'a5'#30#255'X'
+ +'7%'#242'FDC'#204'CCC'#198'DDD'#180'CCC'#144'CCC[AAA+III'#14'UUU'#3#0#0#0#1#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#128#128#128#2'@@@'#12'AAA''CCCWCCC'#140'GB?'
+ +#185'Z4!'#247'a6'#30#255'j?"'#255#151']2'#255#181't>'#255#194#133'F'#255#206
+ +#149'M'#255#215#161'Q'#255#223#170'T'#255#228#178'W'#255#231#181'Y'#255#232
+ +#183'Y'#255#233#185'Z'#255#234#185'Y'#255#234#186'Y'#255#234#186'Y'#255#234
+ +#186'Z'#255#234#186'Z'#255#234#186'Z'#255#234#186'Z'#255#234#186'Z'#255#234
+ +#186'Z'#255#234#186'Z'#255#234#186'Z'#255#234#186'Z'#255#234#186'Z'#255#234
+ +#186'Z'#255#234#186'Z'#255#234#186'Z'#255#234#186'Z'#255#234#186'Z'#255#234
+ +#186'Z'#255#234#186'Z'#255'C5'#26#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#1#1#1#255#20#16#8#255'K;'#29#255#189#150'I'#255#234#186'Z'#255#234#186
+ +'Z'#255#234#186'Z'#255#234#186'Z'#255#234#186'Z'#255#234#186'Z'#255#234#186
+ +'Z'#255#234#186'Z'#255#234#186'Z'#255#234#186'Z'#255#234#186'Y'#255#234#186
+ +'Y'#255#234#185'Y'#255#233#185'Z'#255#232#183'Y'#255#230#181'X'#255#226#176
+ +'W'#255#221#169'T'#255#213#159'O'#255#203#145'K'#255#190#129'D'#255#178'p='
+ +#255#134'Q-'#255'g;"'#255'`4'#29#255'U7('#238'CCC'#202'DDD'#195'DDD'#173'BBB'
+ +#131'CCCL@@@ 999'#9#0#0#0#2#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'III'#7'BBB'#27'CC'
+ +'CEDDD|DDD'#170'V6%'#238'`5'#30#255'h<"'#255#145'Y1'#255#179's?'#255#192#132
+ +'F'#255#205#148'M'#255#215#161'R'#255#222#171'U'#255#227#176'X'#255#230#181
+ +'Z'#255#231#183'Z'#255#232#183'['#255#232#184'['#255#233#185'['#255#233#185
+ +'['#255#233#185'['#255#233#185'['#255#233#185'['#255#233#185'['#255#233#185
+ +'['#255#233#185'['#255#233#185'['#255#233#185'['#255#233#185'['#255#233#185
+ +'['#255#233#185'['#255#233#185'['#255#233#185'['#255#233#185'['#255#233#185
+ +'['#255#233#185'['#255#233#185'['#255#127'd1'#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#13#11#5
+ +#255'N>'#31#255#193#153'L'#255#233#185'['#255#233#185'['#255#233#185'['#255
+ +#233#185'['#255#233#185'['#255#233#185'['#255#233#185'['#255#233#185'['#255
+ +#233#185'['#255#233#184'['#255#232#184'['#255#232#183'Z'#255#231#182'Z'#255
+ +#229#180'Y'#255#226#175'X'#255#220#168'U'#255#213#158'R'#255#201#144'K'#255
+ +#189#127'D'#255#175'n<'#255#128'N+'#255'e9 '#255'_3'#29#255'Q;1'#227'CCC'#201
+ +'CCC'#191'CCC'#163'CCCrAAA;FFF'#22'333'#5#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'@@@'#4'<<<'
+ +#17'AAA3EEEhCCC'#156'R:/'#220'_3'#29#255'e: '#255#134'Q-'#255#178'p>'#255#190
+ +#130'F'#255#203#145'M'#255#213#161'S'#255#221#170'W'#255#226#176'Z'#255#229
+ +#180'Z'#255#230#182'\'#255#231#182'\'#255#231#183'\'#255#231#183'\'#255#231
+ +#183'\'#255#231#183'\'#255#231#183'\'#255#231#183'\'#255#231#183'\'#255#231
+ +#183'\'#255#231#183'\'#255#231#183'\'#255#231#183'\'#255#231#183'\'#255#231
+ +#183'\'#255#231#183'\'#255#231#183'\'#255#231#183'\'#255#231#183'\'#255#231
+ +#183'\'#255#231#183'\'#255#231#183'\'#255#180#142'G'#255#1#1#1#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#15#12#6#255'VE"'#255#215#171'V'#255
+ +#231#183'\'#255#231#183'\'#255#231#183'\'#255#231#183'\'#255#231#183'\'#255
+ +#231#183'\'#255#231#183'\'#255#231#183'\'#255#231#183'\'#255#231#182'\'#255
+ +#230#181'['#255#228#178'['#255#225#175'Y'#255#219#168'W'#255#211#156'Q'#255
+ +#200#142'K'#255#187'|D'#255#172'k<'#255'wF('#255'c7 '#255'^1'#30#254'K@:'#214
+ +'DDD'#199'CCC'#184'CCC'#148'AAA^GGG+NNN'#13'UUU'#3#0#0#0#0#0#0#0#0#0#0#0#0#0
+ ,#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#2'MMM'#10'@'
+ +'@@$DDDSDDD'#139'L?8'#197'^1'#29#254'c7 '#255'wG)'#255#173'l<'#255#188#127'E'
+ +#255#201#144'N'#255#212#158'T'#255#220#169'X'#255#225#175'['#255#228#179'\'
+ +#255#229#180'\'#255#230#181']'#255#230#181']'#255#230#182']'#255#230#182']'
+ +#255#230#182']'#255#230#182']'#255#230#182']'#255#230#182']'#255#230#182']'
+ +#255#230#182']'#255#230#182']'#255#230#182']'#255#230#182']'#255#230#182']'
+ +#255#230#182']'#255#230#182']'#255#230#182']'#255#230#182']'#255#230#182']'
+ +#255#230#182']'#255#230#182']'#255#221#175'Y'#255#10#8#4#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1#1#1#255'4'
+ +')'#21#255#184#146'J'#255#230#182']'#255#230#182']'#255#230#182']'#255#230
+ +#182']'#255#230#182']'#255#230#182']'#255#230#182']'#255#230#181']'#255#229
+ +#182']'#255#228#180']'#255#227#178'\'#255#224#174'['#255#218#166'W'#255#209
+ +#155'R'#255#198#139'K'#255#184'zC'#255#162'd8'#255'l@$'#255'a5'#30#255'Z3 '
+ +#249'FBA'#206'DDD'#196'CCC'#174'CCC'#129'BBBIFFF'#29'@@@'#8#0#0#0#1#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'333'#5'FF'
+ +'F'#22'BBB>CCCvFA?'#174'Z3'#31#248'`5'#30#255'l@$'#255#163'd9'#255#184'{D'
+ +#255#199#142'N'#255#210#156'T'#255#218#167'Y'#255#223#174'\'#255#226#177'^'
+ +#255#228#179'^'#255#228#179'^'#255#228#180'_'#255#228#180'_'#255#228#180'_'
+ +#255#228#180'_'#255#228#180'_'#255#228#180'_'#255#228#180'_'#255#228#180'_'
+ +#255#228#180'_'#255#228#180'_'#255#228#180'_'#255#228#180'_'#255#228#180'_'
+ +#255#228#180'_'#255#228#180'_'#255#228#180'_'#255#228#180'_'#255#228#180'_'
+ +#255#228#180'_'#255#228#180'_'#255#228#180'_'#255'bM)'#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#27#21#11#255#140'o;'#255#228#180'_'#255#228#180
+ +'_'#255#228#180'_'#255#228#180'_'#255#228#180'_'#255#228#180'_'#255#228#180
+ +'_'#255#228#179'^'#255#227#179'^'#255#226#176']'#255#222#172'['#255#216#164
+ +'X'#255#207#152'R'#255#195#137'K'#255#181'tA'#255#149'Z3'#255'g<"'#255'_3'#29
+ +#255'V6'''#239'CCC'#201'CCC'#190'CCC'#159'CCCkCCC5GGG'#18'@@@'#4#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#2'@@@'#12'CCC'
+ +'*DDD^DDD'#150'U6('#230'^2'#28#255'f:!'#255#149'Z3'#255#181'uB'#255#195#137
+ +'K'#255#208#154'T'#255#216#165'Y'#255#221#172']'#255#225#176'^'#255#226#178
+ +'_'#255#227#178'_'#255#227#178'_'#255#227#179'_'#255#227#179'_'#255#227#179
+ +'_'#255#227#179'_'#255#227#179'_'#255#227#179'_'#255#227#179'_'#255#227#179
+ +'_'#255#227#179'_'#255#227#179'_'#255#227#179'_'#255#227#179'_'#255#227#179
+ +'_'#255#227#179'_'#255#227#179'_'#255#227#179'_'#255#227#179'_'#255#227#179
+ +'_'#255#227#179'_'#255#227#179'_'#255#227#179'_'#255#13#10#6#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'&'#30#16#255#208#164
+ +'W'#255#227#179'_'#255#227#179'_'#255#227#179'_'#255#227#179'_'#255#227#178
+ +'_'#255#227#178'_'#255#226#179'`'#255#226#177'_'#255#224#176'^'#255#220#170
+ +'\'#255#214#162'X'#255#205#149'R'#255#191#131'I'#255#177'p?'#255#131'O.'#255
+ +'c7 '#255']1'#29#255'N;3'#222'DDD'#199'DDD'#181'CCC'#140'DDDSDDD"999'#9#0#0#0
+ +#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'+++'#6'@@@'#24
+ +'EEECCCC~K=7'#193']0'#28#255'b6'#31#255#129'M,'#255#177'o@'#255#191#131'J'
+ +#255#204#149'S'#255#214#163'Z'#255#220#171']'#255#223#174'_'#255#225#176'`'
+ +#255#225#177'`'#255#226#177'`'#255#226#177'`'#255#226#177'`'#255#226#177'`'
+ +#255#226#177'`'#255#226#177'`'#255#226#177'`'#255#226#177'`'#255#226#177'`'
+ +#255#226#177'`'#255#226#177'`'#255#226#177'`'#255#226#177'`'#255#226#177'`'
+ ,#255#226#177'`'#255#226#177'`'#255#226#177'`'#255#226#177'`'#255#226#177'`'
+ +#255#226#177'`'#255#226#177'`'#255#226#177'`'#255#161'~D'#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#4#3#2
+ +#255#134'i9'#255#226#177'`'#255#226#177'`'#255#226#177'`'#255#226#177'`'#255
+ +#226#177'`'#255#225#178'`'#255#225#177'`'#255#224#176'_'#255#222#174'^'#255
+ +#219#169']'#255#212#159'X'#255#200#144'Q'#255#187'~G'#255#170'j<'#255'qB%'
+ +#255'`5'#30#255'Z2'#31#250'FBA'#205'CCC'#193'DDD'#166'CCCsCCC9CCC'#19'@@@'#4
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#2'@@@'#12'AAA+BBB'
+ +'aDBB'#155'Y3!'#244'_3'#29#255'l?$'#255#167'f;'#255#186'}H'#255#200#144'R'
+ +#255#211#158'Y'#255#218#168']'#255#221#172'`'#255#223#174'a'#255#223#176'a'
+ +#255#224#176'b'#255#224#176'b'#255#224#176'b'#255#224#176'b'#255#224#176'b'
+ +#255#224#176'b'#255#224#176'b'#255#224#176'b'#255#224#176'b'#255#224#176'b'
+ +#255#224#176'b'#255#224#176'b'#255#224#176'b'#255#224#176'b'#255#224#176'b'
+ +#255#224#176'b'#255#224#176'b'#255#224#176'b'#255#224#176'b'#255#224#176'b'
+ +#255#224#176'b'#255#224#176'b'#255#224#176'b'#255'hR.'#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255'qY2'#255#224#176'b'#255#224#176'b'#255#224#176'b'#255#224#176
+ +'b'#255#224#176'b'#255#224#176'b'#255#223#176'a'#255#223#174'`'#255#221#172
+ +'_'#255#217#166']'#255#208#155'W'#255#196#139'O'#255#182'wE'#255#152'\5'#255
+ +'e9!'#255'^2'#29#255'S7*'#233'DDD'#200'CCC'#183'DDD'#143'EEEUDDD"UUU'#9#0#0#0
+ +#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'333'#5'@@@'#24'DDDDCCC~P8-'
+ +#211']0'#29#255'c8!'#255#144'V2'#255#180'uD'#255#196#138'P'#255#207#155'X'
+ +#255#215#165']'#255#220#171'`'#255#221#173'b'#255#222#174'a'#255#222#175'b'
+ +#255#222#175'b'#255#222#175'b'#255#222#175'b'#255#222#175'b'#255#222#175'b'
+ +#255#222#175'b'#255#222#175'b'#255#222#175'b'#255#222#175'b'#255#222#175'b'
+ +#255#222#175'b'#255#222#175'b'#255#222#175'b'#255#222#175'b'#255#222#175'b'
+ +#255#222#175'b'#255#222#175'b'#255#222#175'b'#255#222#175'b'#255#222#175'b'
+ +#255#222#175'b'#255#222#175'b'#255#222#175'b'#255'VD&'#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#1#1#0#255#166#132'J'#255#222#175'b'#255#222#175'b'#255#222#175
+ +'b'#255#222#175'b'#255#222#175'b'#255#222#175'b'#255#222#174'a'#255#221#173
+ +'a'#255#219#170'`'#255#213#163'\'#255#205#150'V'#255#192#132'M'#255#176'oA'
+ +#255'}K,'#255'a5'#31#255'\0'#28#254'I?;'#212'CCC'#194'DDD'#166'CCCrDDD8GGG'
+ +#18'@@@'#4#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#2'FFF'#11'DDD)BBB`G@<'
+ +#164'[1'#29#252'_3'#29#255'uD)'#255#174'l?'#255#189#130'L'#255#204#150'V'#255
+ +#213#162'^'#255#217#168'`'#255#220#172'b'#255#221#173'b'#255#221#173'c'#255
+ +#221#173'c'#255#221#173'c'#255#221#173'c'#255#221#173'c'#255#221#173'c'#255
+ +#221#173'c'#255#221#173'c'#255#221#173'c'#255#221#173'c'#255#221#173'c'#255
+ +#221#173'c'#255#221#173'c'#255#221#173'c'#255#221#173'c'#255#221#173'c'#255
+ +#221#173'c'#255#221#173'c'#255#221#173'c'#255#221#173'c'#255#221#173'c'#255
+ +#221#173'c'#255#221#173'c'#255#221#173'c'#255#221#173'c'#255'gQ.'#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ ,#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#8#6#4#255#207#163']'#255#221#173'c'#255
+ +#221#173'c'#255#221#173'c'#255#221#173'c'#255#221#173'c'#255#221#173'c'#255
+ +#221#172'b'#255#219#171'b'#255#217#167'`'#255#211#159'['#255#200#145'T'#255
+ +#185'{H'#255#164'd;'#255'h<#'#255'^1'#29#255'X3#'#244'DDD'#200'CCC'#183'DDD'
+ +#142'DDDSFFF!@@@'#8#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'@@@'#4'III'#21'EEE?DD'
+ +'D|S5'''#222'\1'#28#255'c8!'#255#158'_8'#255#183'yH'#255#198#142'S'#255#209
+ +#158'\'#255#215#166'`'#255#218#170'b'#255#219#171'c'#255#219#171'd'#255#219
+ +#172'd'#255#219#172'd'#255#219#172'd'#255#219#172'd'#255#219#172'd'#255#219
+ +#172'd'#255#219#172'd'#255#219#172'd'#255#219#172'd'#255#219#172'd'#255#219
+ +#172'd'#255#219#172'd'#255#219#172'd'#255#219#172'd'#255#219#172'd'#255#219
+ +#172'd'#255#219#172'd'#255#219#172'd'#255#219#172'd'#255#219#172'd'#255#219
+ +#172'd'#255#219#172'd'#255#219#172'd'#255#219#172'd'#255#219#172'd'#255#213
+ +#168'b'#255#3#3#1#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'M<#'#255#219#172
+ +'d'#255#219#172'd'#255#219#172'd'#255#219#172'd'#255#219#172'd'#255#219#172
+ +'d'#255#219#171'd'#255#219#170'c'#255#217#168'b'#255#214#164'`'#255#207#153
+ +'Z'#255#194#136'P'#255#178'rD'#255#139'R1'#255'a4'#31#255'\0'#28#255'L<5'#219
+ +'CCC'#193'DDD'#164'CCCoCCC5@@@'#16'UUU'#3#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'@@@'#8
+ +'BBB#CCCWHA='#158'\0'#28#253'_3'#29#255'~I+'#255#175'nB'#255#191#133'O'#255
+ +#205#151'Z'#255#213#163'a'#255#216#167'c'#255#217#169'c'#255#218#170'd'#255
+ +#218#170'd'#255#218#170'd'#255#218#170'd'#255#218#170'd'#255#218#170'd'#255
+ +#218#170'd'#255#218#170'd'#255#218#170'd'#255#218#170'd'#255#218#170'd'#255
+ +#218#170'd'#255#218#170'd'#255#218#170'd'#255#218#170'd'#255#218#170'd'#255
+ +#218#170'd'#255#218#170'd'#255#218#170'd'#255#218#170'd'#255#218#170'd'#255
+ +#218#170'd'#255#218#170'd'#255#218#170'd'#255#218#170'd'#255#218#170'd'#255
+ +#218#170'd'#255#218#170'd'#255'YF)'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#15#12#7#255#218#170'd'#255#218#170'd'#255#218#170'd'#255#218#170'd'#255
+ +#218#170'd'#255#218#170'd'#255#218#170'd'#255#218#169'c'#255#217#168'c'#255
+ +#215#166'b'#255#211#160'_'#255#201#147'W'#255#187#127'L'#255#169'h>'#255'l=$'
+ +#255'^1'#29#255'W3"'#244'DDD'#199'DDD'#180'DDD'#136'DDDKBBB'#27'UUU'#6#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0'UUU'#3'DDD'#15'EEE4BBBpS6)'#215'\1'#28#255'b7!'#255#158'_9'
+ +#255#184'{J'#255#199#144'W'#255#209#158'_'#255#214#165'c'#255#216#168'd'#255
+ +#217#168'd'#255#217#168'd'#255#217#168'd'#255#217#168'd'#255#217#168'd'#255
+ +#217#168'd'#255#217#168'd'#255#217#168'd'#255#217#168'd'#255#217#168'd'#255
+ +#217#168'd'#255#217#168'd'#255#217#168'd'#255#217#168'd'#255#217#168'd'#255
+ +#217#168'd'#255#217#168'd'#255#217#168'd'#255#217#168'd'#255#217#168'd'#255
+ +#217#168'd'#255#217#168'd'#255#217#168'd'#255#217#168'd'#255#217#168'd'#255
+ +#217#168'd'#255#217#168'd'#255#217#168'd'#255#217#168'd'#255#217#168'd'#255
+ +'YD)'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#189#147'W'#255#217#168'd'
+ +#255#217#168'd'#255#217#168'd'#255#217#168'd'#255#217#168'd'#255#217#168'd'
+ +#255#217#168'd'#255#216#168'd'#255#215#167'c'#255#213#164'a'#255#207#154']'
+ +#255#195#138'S'#255#179'tF'#255#139'R1'#255'`5'#30#255'\0'#28#255'K=7'#216'D'
+ +'DD'#191'DDD'#157'CCCcAAA+FFF'#11#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ ,#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'+++'#6'EEE'#26'BBBIE?='
+ +#144'Z0'#28#252'^2'#29#255'zF*'#255#174'mB'#255#192#135'R'#255#205#152'\'#255
+ +#211#161'b'#255#214#165'd'#255#215#166'd'#255#215#166'd'#255#215#166'd'#255
+ +#215#166'd'#255#215#166'd'#255#215#166'd'#255#215#166'd'#255#215#166'd'#255
+ +#215#166'd'#255#215#166'd'#255#215#166'd'#255#215#166'd'#255#215#166'd'#255
+ +#215#166'd'#255#215#166'd'#255#215#166'd'#255#215#166'd'#255#215#166'd'#255
+ +#215#166'd'#255#215#166'd'#255#215#166'd'#255#215#166'd'#255#215#166'd'#255
+ +#215#166'd'#255#215#166'd'#255#215#166'd'#255#215#166'd'#255#215#166'd'#255
+ +#215#166'd'#255#215#166'd'#255#215#166'd'#255#215#166'd'#255'jR1'#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255'fN/'#255#215#166'd'#255#215#166'd'#255#215#166'd'
+ +#255#215#166'd'#255#215#166'd'#255#215#166'd'#255#215#166'd'#255#215#166'd'
+ +#255#215#167'e'#255#214#164'c'#255#210#159'a'#255#202#148'Z'#255#187#128'N'
+ +#255#168'f='#255'i;#'#255'\1'#28#255'V3#'#242'CCC'#197'DDD'#173'BBB{FFF>@@@'
+ +#20'@@@'#4#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#1'MMM'#10'FFF(CCC_R6*'#206'\0'#28#255'`5'#31#255#154'\8'
+ +#255#182'yJ'#255#199#144'Y'#255#208#156'`'#255#212#163'd'#255#213#165'd'#255
+ +#214#165'e'#255#214#165'e'#255#214#165'e'#255#214#165'e'#255#214#165'e'#255
+ +#214#165'e'#255#214#165'e'#255#214#165'e'#255#214#165'e'#255#214#165'e'#255
+ +#214#165'e'#255#214#165'e'#255#214#165'e'#255#214#165'e'#255#214#165'e'#255
+ +#214#165'e'#255#214#165'e'#255#214#165'e'#255#214#165'e'#255#214#165'e'#255
+ +#214#165'e'#255#214#165'e'#255#214#165'e'#255#214#165'e'#255#214#165'e'#255
+ +#214#165'e'#255#214#165'e'#255#214#165'e'#255#214#165'e'#255#214#165'e'#255
+ +#214#165'e'#255#214#165'e'#255#214#165'e'#255#135'h@'#255#2#1#1#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'b'
+ +'L/'#255#214#165'e'#255#214#165'e'#255#214#165'e'#255#214#165'e'#255#214#165
+ +'e'#255#214#165'e'#255#214#165'e'#255#214#165'e'#255#213#165'e'#255#213#164
+ +'d'#255#211#161'c'#255#206#154'^'#255#194#139'U'#255#177'sF'#255#135'P/'#255
+ +'^3'#29#255'[/'#27#255'J>9'#213'DDD'#185'CCC'#144'DDDSHHH III'#7#0#0#0#1#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'UUU'#3
+ +'<<<'#17'DDD8DBAyZ0'#29#248'\1'#28#255'uB'''#255#172'lA'#255#190#132'Q'#255
+ +#203#151'^'#255#209#160'c'#255#211#162'e'#255#212#163'e'#255#212#163'e'#255
+ +#212#163'e'#255#212#163'e'#255#212#163'e'#255#212#163'e'#255#212#163'e'#255
+ +#212#163'e'#255#212#163'e'#255#212#163'e'#255#212#163'e'#255#212#163'e'#255
+ +#212#163'e'#255#212#163'e'#255#212#163'e'#255#212#163'e'#255#212#163'e'#255
+ +#212#163'e'#255#212#163'e'#255#212#163'e'#255#212#163'e'#255#212#163'e'#255
+ +#212#163'e'#255#212#163'e'#255#212#163'e'#255#212#163'e'#255#212#163'e'#255
+ +#212#163'e'#255#212#163'e'#255#212#163'e'#255#212#163'e'#255#212#163'e'#255
+ +#212#163'e'#255#212#163'e'#255#212#163'e'#255#156'xK'#255#1#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'jQ2'#255#212
+ +#163'e'#255#212#163'e'#255#212#163'e'#255#212#163'e'#255#212#163'e'#255#212
+ +#163'e'#255#212#163'e'#255#212#163'e'#255#212#163'e'#255#212#162'e'#255#211
+ +#162'd'#255#208#158'b'#255#200#147'['#255#186'~M'#255#165'd<'#255'd8!'#255'\'
+ +'0'#28#255'T5'''#237'CCC'#193'DDD'#162'CCCjCCC.@@@'#12#0#0#0#2#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'333'#5'GGG'#25'BB'
+ +'BIN:1'#174'[/'#27#255'^2'#29#255#145'T3'#255#180'vI'#255#196#142'Y'#255#206
+ +#155'a'#255#209#161'e'#255#211#162'e'#255#211#162'e'#255#211#162'e'#255#211
+ +#162'e'#255#211#162'e'#255#211#162'e'#255#211#162'e'#255#211#162'e'#255#211
+ +#162'e'#255#211#162'e'#255#211#162'e'#255#211#162'e'#255#211#162'e'#255#211
+ ,#162'e'#255#211#162'e'#255#211#162'e'#255#211#162'e'#255#211#162'e'#255#211
+ +#162'e'#255#211#162'e'#255#211#162'e'#255#211#162'e'#255#211#162'e'#255#211
+ +#162'e'#255#211#162'e'#255#211#162'e'#255#211#162'e'#255#211#162'e'#255#211
+ +#162'e'#255#211#162'e'#255#211#162'e'#255#211#162'e'#255#211#162'e'#255#211
+ +#162'e'#255#211#162'e'#255#211#162'e'#255#211#162'e'#255'O=&'#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'sX7'#255#211
+ +#162'e'#255#211#162'e'#255#211#162'e'#255#211#162'e'#255#211#162'e'#255#211
+ +#162'e'#255#211#162'e'#255#211#162'e'#255#211#162'e'#255#211#162'e'#255#210
+ +#161'f'#255#209#159'd'#255#204#153'`'#255#192#135'U'#255#175'pE'#255'~H+'#255
+ +']0'#29#255'Z0'#28#253'FBA'#201'DDD'#176'CCC~FFF>CCC'#19'@@@'#4#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'999'#9'EEE%CCC[V3'
+ +'$'#222'\0'#27#255'f7!'#255#167'd>'#255#187#128'Q'#255#200#148'^'#255#207#156
+ +'d'#255#209#159'e'#255#209#160'e'#255#209#160'e'#255#209#160'e'#255#209#160
+ +'e'#255#209#160'e'#255#209#160'e'#255#209#160'e'#255#209#160'e'#255#209#160
+ +'e'#255#209#160'e'#255#209#160'e'#255#209#160'e'#255#209#160'e'#255#209#160
+ +'e'#255#209#160'e'#255#209#160'e'#255#151'tI'#255'2&'#25#255#27#21#13#255#15
+ +#12#7#255#7#5#3#255#7#5#3#255' '#25#16#255'P='''#255#151'tI'#255#209#160'e'
+ +#255#209#160'e'#255#209#160'e'#255#209#160'e'#255#209#160'e'#255#209#160'e'
+ +#255#209#160'e'#255#209#160'e'#255#209#160'e'#255#209#160'e'#255#209#160'e'
+ +#255#209#160'e'#255#209#160'e'#255#6#5#3#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#146'pF'#255#209#160'e'#255#209#160'e'#255
+ +#209#160'e'#255#209#160'e'#255#209#160'e'#255#209#160'e'#255#209#160'e'#255
+ +#209#160'e'#255#209#160'e'#255#209#160'e'#255#209#160'e'#255#209#159'e'#255
+ +#206#155'c'#255#198#143'['#255#182'zM'#255#151'Y6'#255'^3'#29#255'[/'#27#255
+ +'N:1'#222'DDD'#185'DDD'#142'DDDOIII'#28'+++'#6#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#2';;;'#13'DDD1F@=x[/'#28#253'\1'#28
+ +#255'~G+'#255#174'oE'#255#193#137'X'#255#203#151'b'#255#207#156'e'#255#207
+ +#158'f'#255#208#158'f'#255#208#158'f'#255#208#158'f'#255#208#158'f'#255#208
+ +#158'f'#255#208#158'f'#255#208#158'f'#255#208#158'f'#255#208#158'f'#255#208
+ +#158'f'#255#208#158'f'#255#208#158'f'#255#208#158'f'#255#208#158'f'#255'x[;'
+ +#255#15#12#8#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#4#3#2#255'bJ0'#255#208#158'f'#255#208#158'f'
+ +#255#208#158'f'#255#208#158'f'#255#208#158'f'#255#208#158'f'#255#208#158'f'
+ +#255#208#158'f'#255#208#158'f'#255#208#158'f'#255#208#158'f'#255'3'''#25#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#2#2#1#255#208#158'f'
+ +#255#208#158'f'#255#208#158'f'#255#208#158'f'#255#208#158'f'#255#208#158'f'
+ +#255#208#158'f'#255#208#158'f'#255#208#158'f'#255#208#158'f'#255#208#158'f'
+ +#255#208#158'f'#255#207#158'e'#255#206#156'd'#255#201#149'_'#255#189#131'T'
+ +#255#169'h@'#255'j:#'#255'\0'#28#255'V3#'#242'DDD'#191'CCC'#156'BBB`AAA''333'
+ +#10#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'@@@'#4'C'
+ +'CC'#19'EEE?Q7+'#179'[/'#27#255'^1'#29#255#152'X6'#255#181'yM'#255#197#144']'
+ +#255#204#153'c'#255#206#155'f'#255#206#156'e'#255#206#156'e'#255#206#156'e'
+ +#255#206#156'e'#255#206#156'e'#255#206#156'e'#255#206#156'e'#255#206#156'e'
+ +#255#206#156'e'#255#206#156'e'#255#206#156'e'#255#206#156'e'#255#206#156'e'
+ +#255#202#154'c'#255'6)'#27#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#14#10#7#255#178#135'W'#255#206#156'e'#255#206#156'e'#255#206#156'e'
+ +#255#206#156'e'#255#206#156'e'#255#206#156'e'#255#206#156'e'#255#206#156'e'
+ +#255#206#156'e'#255'WB+'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ ,#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#29#22#14#255#206#156'e'#255#206#156'e'#255#206#156'e'#255#206#156'e'
+ +#255#206#156'e'#255#206#156'e'#255#206#156'e'#255#206#156'e'#255#206#156'e'
+ +#255#206#156'e'#255#206#156'e'#255#206#156'e'#255#206#156'e'#255#205#156'e'
+ +#255#203#151'c'#255#194#139'Z'#255#176'qH'#255#131'K-'#255'\1'#28#255'[/'#27
+ +#255'HA='#204'DDD'#169'DDDqEEE4III'#14#128#128#128#2#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'+++'#6'BBB'#27'EEENW2!'#228'[/'#27#255'i9!'
+ +#255#168'e?'#255#187#130'T'#255#200#147'`'#255#203#153'e'#255#205#154'e'#255
+ +#205#154'e'#255#205#154'e'#255#205#154'e'#255#205#154'e'#255#205#154'e'#255
+ +#205#154'e'#255#205#154'e'#255#205#154'e'#255#205#154'e'#255#205#154'e'#255
+ +#205#154'e'#255#205#154'e'#255#199#150'a'#255#19#14#9#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#7#6#4#255#178#133'W'
+ +#255#205#154'e'#255#205#154'e'#255#205#154'e'#255#205#154'e'#255#205#154'e'
+ +#255#205#154'e'#255#205#154'e'#255#205#154'e'#255'S>)'#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#128'a?'#255#205#154'e'#255#205#154'e'
+ +#255#205#154'e'#255#205#154'e'#255#205#154'e'#255#205#154'e'#255#205#154'e'
+ +#255#205#154'e'#255#205#154'e'#255#205#154'e'#255#205#154'e'#255#205#154'e'
+ +#255#205#154'e'#255#204#154'e'#255#203#152'd'#255#197#145'^'#255#182'zO'#255
+ +#157'Z8'#255']1'#29#255'[/'#27#255'P9.'#226'CCC'#179'CCC'#129'CCCA@@@'#20'@@'
+ +'@'#4#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'999'#9'EEE%EA?'
+ +'b[/'#27#253'\0'#27#255#127'F*'#255#173'nG'#255#191#136'Z'#255#200#149'c'#255
+ +#202#152'e'#255#202#152'e'#255#202#153'e'#255#202#153'e'#255#202#153'e'#255
+ +#202#153'e'#255#202#153'e'#255#202#153'e'#255#202#153'e'#255#202#153'e'#255
+ +#202#153'e'#255#202#153'e'#255#202#153'e'#255#202#153'e'#255#31#24#16#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#11#8#6#255#200#151'e'#255#202#153'e'#255#202#153'e'#255#202
+ +#153'e'#255#202#153'e'#255#202#153'e'#255#202#153'e'#255#202#153'e'#255'O;'''
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255''''#29#19#255#202#153'e'#255
+ +#202#153'e'#255#202#153'e'#255#202#153'e'#255#202#153'e'#255#202#153'e'#255
+ +#202#153'e'#255#202#153'e'#255#202#153'e'#255#202#153'e'#255#202#153'e'#255
+ +#202#153'e'#255#202#153'e'#255#202#153'e'#255#202#152'e'#255#202#151'd'#255
+ +#199#147'b'#255#188#130'U'#255#168'e@'#255'k:"'#255'[/'#27#255'V3$'#241'CCC'
+ +#186'BBB'#142'EEENBBB'#27'+++'#6#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#2'@@@'#12'DDD-O:0'#146'[/'#27#255'\0'#28#255#145'R2'#255#179'wM'
+ +#255#194#141'^'#255#200#148'c'#255#201#150'e'#255#201#150'e'#255#201#150'e'
+ +#255#201#150'e'#255#201#150'e'#255#201#150'e'#255#201#150'e'#255#201#150'e'
+ +#255#201#150'e'#255#201#150'e'#255#201#150'e'#255#201#150'e'#255#201#150'e'
+ +#255';,'#30#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'S>*'#255#201#150'e'
+ +#255#201#150'e'#255#201#150'e'#255#201#150'e'#255#201#150'e'#255#201#150'e'
+ +#255#201#150'e'#255'K8&'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#29#22#14#255
+ +#184#138']'#255#201#150'e'#255#201#150'e'#255#201#150'e'#255#201#150'e'#255
+ ,#201#150'e'#255#201#150'e'#255#201#150'e'#255#201#150'e'#255#201#150'e'#255
+ +#201#150'e'#255#201#150'e'#255#201#150'e'#255#201#150'e'#255#201#150'e'#255
+ +#201#150'e'#255#200#149'd'#255#199#148'c'#255#191#136'['#255#173'mG'#255'}D('
+ +#255'\0'#27#255'Z0'#28#253'DBB'#192'CCC'#152'DDDZBBB#@@@'#8#0#0#0#1#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#128#128#128#2'III'#14'CCC5T5'''#190'[/'#27#255
+ +'_2'#29#255#162'^:'#255#184'}S'#255#195#142'`'#255#198#147'd'#255#199#148'd'
+ +#255#199#148'd'#255#199#148'd'#255#199#148'd'#255#199#148'd'#255#199#148'd'
+ +#255#199#148'd'#255#199#148'd'#255#199#148'd'#255#199#148'd'#255#199#148'd'
+ +#255#199#148'd'#255#147'mJ'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#3#2#1#255#195#144'b'#255#199#148'd'#255#199#148'd'#255#199#148'd'#255
+ +#199#148'd'#255#199#148'd'#255#199#148'd'#255'H6$'#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#3#2#1#255#23#17#12
+ +#255'qT8'#255#199#148'd'#255#199#148'd'#255#199#148'd'#255#199#148'd'#255#199
+ +#148'd'#255#199#148'd'#255#199#148'd'#255#199#148'd'#255#199#148'd'#255#199
+ +#148'd'#255#199#148'd'#255#199#148'd'#255#199#148'd'#255#199#148'd'#255#199
+ +#148'd'#255#199#148'd'#255#199#148'd'#255#199#148'd'#255#198#146'c'#255#193
+ +#140'^'#255#178'uN'#255#143'O1'#255'\0'#28#255'[/'#27#255'J=7'#208'CCC'#161
+ +'DDDfAAA+FFF'#11#0#0#0#2#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'UUU'#3'<<<'
+ +#17'CCC=X1 '#227'[/'#27#255'm:"'#255#167'eA'#255#187#130'X'#255#195#143'a'
+ +#255#196#144'c'#255#197#145'c'#255#197#145'c'#255#197#145'c'#255#197#145'c'
+ +#255#197#145'c'#255#197#145'c'#255#197#145'c'#255#197#145'c'#255#197#145'c'
+ +#255#197#145'c'#255#197#145'c'#255#197#145'c'#255#19#14#10#255#0#0#0#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#135'cD'#255#197#145'c'#255#197
+ +#145'c'#255#197#145'c'#255#197#145'c'#255#197#145'c'#255#197#145'c'#255'I5$'
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#19#14#10#255'4&'#26#255'cI2'#255
+ +#161'vP'#255#197#145'c'#255#197#145'c'#255#197#145'c'#255#197#145'c'#255#197
+ +#145'c'#255#197#145'c'#255#197#145'c'#255#197#145'c'#255#197#145'c'#255#197
+ +#145'c'#255#197#145'c'#255#197#145'c'#255#197#145'c'#255#197#145'c'#255#197
+ +#145'c'#255#197#145'c'#255#197#145'c'#255#197#145'c'#255#197#145'c'#255#197
+ +#145'c'#255#197#145'b'#255#196#144'c'#255#194#140'`'#255#182'|S'#255#159'\:'
+ +#255']2'#28#255'[/'#27#255'Q8-'#226'DDD'#168'DDDqAAA3NNN'#13#128#128#128#2#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'@@@'#4':::'#22'G@/[/'#27
+ +#254'[/'#27#255'}A&'#255#167'gD'#255#180'zW'#255#181'|Y'#255#181'|Y'#255#181
+ +'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'
+ +#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#136']C'#255#0#0#0#255#0#0#0#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#19#13#9#255#151'gJ'#255#181'|Y'#255#181'|Y'#255#181
+ +'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'
+ +#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#171'vU'#255'1"'#24#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1#0#0#255'}V>'#255
+ +#181'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#181
+ +'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'
+ +#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'#255
+ +#181'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#181
+ +'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'
+ +#255#181'|Y'#255#181'|Y'#255#178'wT'#255#161'];'#255'k8 '#255'[/'#27#255'V3#'
+ +#238'DDD'#151'CCCWFFF!@@@'#8#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#2'FFF'#11
+ +'K:3?[/'#27#255'[/'#27#255#131'F*'#255#169'iH'#255#179'xV'#255#180'zW'#255
+ +#180'{W'#255#180'{W'#255#180'{W'#255#180'{W'#255#180'{W'#255#180'{W'#255#180
+ +'{W'#255#180'{W'#255#180'{W'#255#180'{W'#255#180'{W'#255'<)'#29#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#1#1#1#255'O6&'#255#180'{W'#255#180'{W'#255#180'{W'#255#180
+ +'{W'#255#180'{W'#255#180'{W'#255#180'{W'#255#180'{W'#255#180'{W'#255#180'{W'
+ +#255#180'{W'#255#180'{W'#255#180'{W'#255#180'{W'#255#180'{W'#255#180'{W'#255
+ +#180'{W'#255#142'aE'#255#27#19#13#255#2#1#1#255#0#0#0#255#0#0#0#255#0#0#0#255
+ ,#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#8#5#4#255
+ +#135']A'#255#180'{W'#255#180'{W'#255#180'{W'#255#180'{W'#255#180'{W'#255#180
+ +'{W'#255#180'{W'#255#180'{W'#255#180'{W'#255'pL6'#255'+'#29#20#255'('#28#19
+ +#255'*'#28#20#255'+'#29#21#255'-'#30#21#255'fF2'#255#180'{W'#255#180'{W'#255
+ +#180'{W'#255#180'{W'#255#180'{W'#255#180'{W'#255#180'{W'#255#180'{W'#255#180
+ +'{W'#255#180'{W'#255#180'{W'#255#180'{W'#255#180'{W'#255#180'{W'#255#180'{W'
+ +#255#180'{W'#255#180'{W'#255#180'{W'#255#180'zX'#255#178'vU'#255#163'_>'#255
+ +'r<"'#255'[/'#27#255'X2!'#243'CCC'#152'BBBYDDD"@@@'#8#0#0#0#1#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#2'FFF'#11'N8.J[/'#27#255'[/'#27#255#135'H,'#255#170'kI'#255
+ +#178'wV'#255#179'yX'#255#179'yX'#255#179'yX'#255#179'yX'#255#179'yX'#255#179
+ +'yX'#255#179'yX'#255#179'yX'#255#179'yX'#255#179'yX'#255#179'yX'#255#179'yX'
+ +#255#16#11#8#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#19#13#10#255#150'fJ'#255#179'yX'#255#179
+ +'yX'#255#179'yX'#255#179'yX'#255#179'yX'#255#179'yX'#255#179'yX'#255#179'yX'
+ +#255#179'yX'#255#179'yX'#255#179'yX'#255#179'yX'#255#179'yX'#255#179'yX'#255
+ +#179'yX'#255#179'yX'#255#179'yX'#255#179'yX'#255#179'yX'#255#179'yX'#255#179
+ +'yX'#255'~V>'#255'=)'#30#255#19#13#9#255#1#1#1#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255'$'#24#17#255#172'uT'#255#179'yX'#255#179'yX'#255#179'yX'
+ +#255#179'yX'#255#179'yX'#255#179'yX'#255#179'yX'#255#158'kN'#255'=)'#30#255#6
+ +#4#3#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#6#4#3#255'?+'#31#255#164'oP'#255#179'yX'#255#179'yX'#255#179'yX'#255#179
+ +'yX'#255#179'yX'#255#179'yX'#255#179'yX'#255#179'yX'#255#179'yX'#255#179'yX'
+ +#255#179'yX'#255#179'yX'#255#179'yX'#255#179'yX'#255#179'yX'#255#179'yX'#255
+ +#177'uU'#255#164'b@'#255'v?%'#255'[/'#27#255'Y1'#31#246'CCC'#152'BBBYDDD"@@@'
+ +#8#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'FFF'#11'Q7+U[/'#27#255'\0'#28#255
+ +#139'J-'#255#171'lL'#255#177'wW'#255#178'wV'#255#178'wV'#255#178'wV'#255#178
+ +'wV'#255#178'wV'#255#178'wV'#255#178'wV'#255#178'wV'#255#178'wV'#255#178'wV'
+ +#255#178'wV'#255#172'sT'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1#1#1#255'O5&'#255#178'wV'#255#178'wV'
+ +#255#178'wV'#255#178'wV'#255#178'wV'#255#178'wV'#255#178'wV'#255#178'wV'#255
+ +#178'wV'#255#178'wV'#255#178'wV'#255#178'wV'#255#178'wV'#255#178'wV'#255#178
+ +'wV'#255#178'wV'#255#178'wV'#255#178'wV'#255#178'wV'#255#178'wV'#255#178'wV'
+ +#255#178'wV'#255#178'wV'#255#178'wV'#255#178'wV'#255#178'wV'#255#176'wV'#255
+ +'vO9'#255'7%'#27#255#16#10#8#255#1#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0
+ +#0#255#0#0#0#255#11#8#6#255'9&'#28#255#137'\C'#255#178'wV'#255#178'wV'#255
+ +#178'wV'#255#178'wV'#255#178'wV'#255#178'wV'#255#178'wV'#255#178'wV'#255'M3%'
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1#0#0#255'4"'#25#255#178'wV'
+ +#255#178'wV'#255#178'wV'#255#178'wV'#255#178'wV'#255#178'wV'#255#178'wV'#255
+ +#178'wV'#255#178'wV'#255#178'wV'#255#178'wV'#255#178'wV'#255#178'wV'#255#178
+ +'wV'#255#178'wV'#255#176'tT'#255#165'cC'#255'yA'''#255'[/'#27#255'Z0'#29#250
+ +'DDD'#150'CCCWFFF!III'#7#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'MMM'#10'R4'
+ +'''^[/'#27#255'\0'#28#255#142'M.'#255#171'nN'#255#177'uV'#255#177'wX'#255#177
+ +'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'
+ +#255#177'wX'#255#177'wX'#255#177'wX'#255'gF3'#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#23#16#12#255#152'fK'#255#177
+ +'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'
+ +#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255
+ +#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#177
+ +'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'
+ +#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#173'uV'#255
+ +#136'\D'#255#133'YB'#255#131'XA'#255#128'V@'#255#153'gL'#255#177'wX'#255#177
+ +'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'
+ +#255#177'wX'#255#177'wX'#255'S8)'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255'"'#23#17#255#175'wX'#255#177'wX'#255#177
+ +'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'
+ +#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#175'tU'#255
+ +#166'eE'#255'}B)'#255'\0'#28#255'[/'#28#253'CCC'#148'CCCTBBB'#31'III'#7#0#0#0
+ ,#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'999'#9'V4%h[/'#27#255'\0'#28#255#145'O0'
+ +#255#171'mN'#255#175'sU'#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255
+ +#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175
+ +'uW'#255'*'#29#21#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#2
+ +#1#1#255'X;,'#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255
+ +#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175
+ +'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'
+ +#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255
+ +#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175
+ +'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'
+ +#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255
+ +#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255'^?/'#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255'$'#24#18#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255
+ +#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175
+ +'uW'#255#175'uW'#255#175'uW'#255#175'sT'#255#166'eE'#255#128'D*'#255'\0'#28
+ +#255'[/'#27#255'ECB'#149'CCCP@@@'#28'UUU'#6#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#1'@@@'#8'W3#q[/'#27#255'\1'#29#255#150'Q1'#255#171'mN'#255#174'sU'#255
+ +#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175
+ +'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#15#10#8#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#4#3#2#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#29#19#14#255#156'iM'#255#175'uV'#255
+ +#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175
+ +'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'
+ +#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255
+ +#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175
+ +'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'
+ +#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255
+ +#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175
+ +'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#11#7#6#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255'sM9'#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255
+ +#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175
+ +'tV'#255#174'rS'#255#167'fG'#255#131'G,'#255'\0'#28#255'[/'#27#255'GA?'#150
+ +'CCCLGGG'#25'333'#5#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'III'#7'W3#k[/'#27
+ +#255'\1'#29#255#149'P2'#255#169'lM'#255#174'qT'#255#175'tV'#255#175'tV'#255
+ +#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175
+ +'tV'#255#175'tV'#255#175'tV'#255#9#6#4#255#0#0#0#255#0#0#0#255#0#0#0#255#136
+ +'ZC'#255'T8*'#255#1#1#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#7#5#3#255
+ +'bA0'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'
+ +#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255
+ +#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175
+ +'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'
+ +#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255
+ +#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175
+ +'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'
+ +#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255
+ +#165'nR'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#10#7#5#255#175'tV'#255#175
+ +'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'
+ +#255#175'tV'#255#175'tV'#255#175'tV'#255#174'sU'#255#173'qR'#255#166'eG'#255
+ +#131'F,'#255'\0'#28#255'[/'#27#255'EA?'#145'DDDGFFF'#22'@@@'#4#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#1'333'#5'W3#\[/'#27#255'\1'#29#255#146'P3'#255#168
+ +'jM'#255#173'pT'#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'
+ +#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255
+ +#4#3#2#255#0#0#0#255#0#0#0#255#21#14#10#255#173'rU'#255#173'rU'#255#152'dK'
+ +#255'dB1'#255'A+ '#255'D-!'#255#141']E'#255#173'rU'#255#173'rU'#255#173'rU'
+ +#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255
+ +#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173
+ +'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'
+ ,#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255
+ +#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173
+ +'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'
+ +#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255
+ +#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#169'pS'#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#139'\D'#255#173'rU'#255#173'rU'
+ +#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255
+ +#173'rU'#255#173'rU'#255#173'qT'#255#172'oR'#255#165'cF'#255#128'E+'#255'\0'
+ +#28#255'[/'#27#255'CBA'#132'DDD@CCC'#19'UUU'#3#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0'@@@'#4'U2"L[/'#27#255'\1'#29#255#143'N3'#255#168'hK'#255#172'oT'
+ +#255#173'qU'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255
+ +#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#1#1#1#255#0#0#0
+ +#255#0#0#0#255'nI7'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173
+ +'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'
+ +#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255
+ +#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173
+ +'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'
+ +#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255
+ +#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173
+ +'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'
+ +#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255
+ +#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#2#1#1#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255'H0$'#255#173'rV'#255#173'rV'#255#173'rV'
+ +#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255
+ +#173'rV'#255#173'qU'#255#171'nQ'#255#165'dF'#255'~D+'#255'\1'#29#255'Z0'#28
+ +#252'CCCzCCC9@@@'#16#128#128#128#2#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'U'
+ +'UU'#3'T2#=[/'#27#255'\1'#29#255#140'N1'#255#166'gI'#255#171'oR'#255#173'qU'
+ +#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255
+ +#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#1#1#1#255#27#18#13#255'a@0'
+ +#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255
+ +#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173
+ +'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'
+ +#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255
+ +#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173
+ +'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'
+ +#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255
+ +#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173
+ +'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'
+ +#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255'$'#24#18#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#31#20#15#255#173'qU'#255#173'qU'#255#173'qU'#255
+ +#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173
+ +'qU'#255#172'pT'#255#169'lP'#255#164'aD'#255'{C*'#255'\1'#29#255'Y0'#30#247
+ +'CCCoBBB2;;;'#13#0#0#0#2#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#128#128#128
+ +#2'V6''-[/'#27#255'\1'#29#255#137'L0'#255#165'fH'#255#170'mQ'#255#172'pT'#255
+ +#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172
+ +'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#166'lS'#255#172'pU'#255#172'pU'
+ +#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255
+ +#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172
+ +'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'
+ +#255#172'pU'#255#172'pU'#255#172'pU'#255#168'nS'#255#134'WB'#255'b@0'#255'tK'
+ +'9'#255#166'lS'#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'
+ +#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255
+ +#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172
+ +'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'
+ +#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255
+ +#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#129'T@'#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ ,#255#0#0#0#255#0#0#0#255#22#14#11#255#172'pU'#255#172'pU'#255#172'pU'#255#172
+ +'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'
+ +#255#172'oT'#255#170'mP'#255#163'`C'#255'xB*'#255'\1'#29#255'Y1'#31#241'BBBd'
+ +'CCC*MMM'#10#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#2'T7*'#29
+ +'[/'#27#255'\1'#29#255#134'J0'#255#165'dG'#255#169'lQ'#255#171'pU'#255#172'q'
+ +'W'#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'
+ +#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255
+ +#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172
+ +'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'
+ +#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255
+ +#135'YD'#255'$'#24#18#255#3#2#2#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#8#5#4#255#30#20#16#255'xO='#255#172'qW'#255#172'qW'#255#172'qW'#255
+ +#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172
+ +'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'
+ +#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255
+ +#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172
+ +'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#14#9#7#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#20#13#10#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'
+ +#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#171'oT'#255
+ +#169'jM'#255#162'_A'#255's>'''#255'\1'#29#255'X2 '#234'CCCXDDD"@@@'#8#0#0#0#1
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'C><'#9'[/'#27#247'\1'#29#255
+ +'}F-'#255#164'bE'#255#169'lO'#255#171'pT'#255#172'qV'#255#172'qV'#255#172'qV'
+ +#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255
+ +#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255#172
+ +'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'
+ +#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255
+ +#172'qV'#255#172'qV'#255#154'eM'#255#22#15#11#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#25#17#13#255#136'ZE'#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'
+ +#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255
+ +#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255#172
+ +'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'
+ +#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255
+ +#172'qV'#255'U7*'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#17#11#9#255#172'qV'#255#172
+ +'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'
+ +#255#172'qV'#255#172'qV'#255#171'oT'#255#168'jM'#255#161'^@'#255'k;%'#255'\0'
+ +#28#255'V3#'#220'CCCLEEE'#26'333'#5#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0'+++'#6'[/'#28#214'\1'#29#255't@)'#255#162'`B'#255#168'jO'#255
+ +#172'pV'#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#173
+ +'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'
+ +#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255
+ +#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#173
+ +'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#144'_I'#255#6#4#3
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'Z;-'#255
+ +#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#173
+ +'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'
+ +#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255
+ +#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#173
+ +'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#171'pV'#255#3#2#1#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255'!'#22#17#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'
+ +#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#172'qX'#255#171'oU'#255
+ +#167'hM'#255#160'[>'#255'b5!'#255'\0'#28#255'S5'''#196'EEE?CCC'#19'@@@'#4#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'UUU'#3'Z0'#29#176'\1'#29
+ +#255'k:%'#255#162'^A'#255#169'jN'#255#173'qV'#255#174'sY'#255#174'sY'#255#174
+ +'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'
+ +#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255
+ +#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174
+ ,'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'
+ +#255#151'dM'#255#4#2#2#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#1#1#1#255#136'YF'#255#174'sY'#255#174'sY'#255#174's'
+ +'Y'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'
+ +#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255
+ +#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174
+ +'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'
+ +#255#174'sY'#255'5#'#27#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'G.$'#255#174'sY'#255#174'sY'#255
+ +#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174
+ +'sY'#255#174'sY'#255#172'pV'#255#167'gK'#255#153'X:'#255'^3'#31#255'\0'#28
+ +#255'Q7+'#166'BBB2777'#14#0#0#0#2#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#2'Z0'#29#137'\0'#28#255'a5!'#255#160']>'#255#168'jN'#255
+ +#173'sY'#255#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255#175
+ +'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'
+ +#255#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255
+ +#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255#175
+ +'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255#29#20#15#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#8
+ +#5#4#255#169'rX'#255#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'
+ +#255#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255
+ +#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255#175
+ +'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'
+ +#255#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255#156'jR'#255#1#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255'yQ?'#255#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255
+ +#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255#174'u['#255#172'qV'#255#166
+ +'gJ'#255#143'S6'#255'^2'#31#255'[/'#27#255'O;2'#130'CCC&999'#9#0#0#0#1#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'Z0'#29'a\0'#28#255
+ +'^3'#31#255#153'W;'#255#168'jN'#255#174'tZ'#255#176'x_'#255#176'y_'#255#176
+ +'y_'#255#176'y_'#255#176'y_'#255#176'y_'#255#176'y_'#255#176'y_'#255#176'y_'
+ +#255#176'y_'#255#176'y_'#255#176'y_'#255#176'y_'#255#176'y_'#255#176'y_'#255
+ +#176'y_'#255#176'y_'#255#176'y_'#255#176'y_'#255#176'y_'#255#176'y_'#255#176
+ +'y_'#255#176'y_'#255#176'y_'#255#176'y_'#255#176'y_'#255#176'y_'#255'oL='#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255']@2'#255#176'y_'#255#176'y_'#255#176
+ +'y_'#255#176'y_'#255#176'y_'#255#176'y_'#255'Z=1'#255')'#28#22#255#26#18#14
+ +#255#14#10#8#255#10#7#5#255#23#16#12#255'+'#30#23#255'E0&'#255#138'_J'#255
+ +#176'y_'#255#176'y_'#255#176'y_'#255#176'y_'#255#176'y_'#255#176'y_'#255#176
+ +'y_'#255#176'y_'#255#176'y_'#255#176'y_'#255#176'y_'#255#176'y_'#255#176'y_'
+ +#255#176'y_'#255'#'#24#19#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#172'w]'#255#176'y_'#255#176'y_'#255
+ +#176'y_'#255#176'y_'#255#176'y_'#255#176'y_'#255#176'y_'#255#176'y_'#255#176
+ +'y_'#255#175'w^'#255#172'rW'#255#165'fI'#255#134'K2'#255']1'#30#255'[/'#27
+ +#255'H?:ZBBB'#27'+++'#6#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0'X/'#29'7[/'#27#255'^2'#31#255#141'P5'#255#167'hK'#255#174
+ +'sY'#255#177'x_'#255#177'za'#255#177'za'#255#177'za'#255#177'za'#255#177'za'
+ +#255#177'za'#255#177'za'#255#177'za'#255#177'za'#255#177'za'#255#177'za'#255
+ +#177'za'#255#177'za'#255#177'za'#255#177'za'#255#177'za'#255#177'za'#255#177
+ +'za'#255#177'za'#255#177'za'#255#177'za'#255#177'za'#255#177'za'#255#177'za'
+ +#255#177'za'#255#177'za'#255#9#6#5#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255'%'#25#20#255#177'za'#255#177'za'#255#177'za'#255#177'za'#255'bD6'#255#8
+ +#6#4#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255'>+"'#255#175'za'#255#177'za'#255#177'za'#255#177'za'
+ +#255#177'za'#255#177'za'#255#177'za'#255#177'za'#255#177'za'#255#177'za'#255
+ +#177'za'#255#177'za'#255#177'za'#255#136'^K'#255#0#0#0#255#0#0#0#255#0#0#0
+ ,#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#16#11#9#255#177'za'#255#177
+ +'za'#255#177'za'#255#177'za'#255#177'za'#255#177'za'#255#177'za'#255#177'za'
+ +#255#177'za'#255#177'za'#255#176'x^'#255#172'qV'#255#164'cF'#255'{E,'#255']1'
+ +#30#255'Z0'#29#245'DDD'#255
+ +'`5!'#255'\0'#28#255'T5'''#155'DDD'#30'III'#7#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'Z/'#28'w\0'#28#255
+ +'`5!'#255#157'\?'#255#172'pU'#255#179'}d'#255#181#129'i'#255#182#129'j'#255
+ +#182#129'j'#255#182#129'j'#255#182#129'j'#255#182#129'j'#255#182#129'j'#255
+ +#182#129'j'#255#182#129'j'#255#182#129'j'#255#182#129'j'#255#182#129'j'#255
+ +#182#129'j'#255#182#129'j'#255#182#129'j'#255#182#129'j'#255#182#129'j'#255
+ +#182#129'j'#255#182#129'j'#255#182#129'j'#255#182#129'j'#255#182#129'j'#255
+ +#182#129'j'#255#182#129'j'#255#182#129'j'#255'.!'#27#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#2#1#1#255#166'va'#255#182#129'j'#255#182#129'j'#255'A.&'
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#9#6#5#255#170'yd'#255#182#129'j'#255#182#129'j'#255#182#129'j'#255#182
+ +#129'j'#255#182#129'j'#255#182#129'j'#255#182#129'j'#255#182#129'j'#255#182
+ +#129'j'#255#182#129'j'#255#182#129'j'#255#8#6#5#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#135'`O'#255#182#129'j'#255#182#129'j'#255#182#129'j'#255
+ +#182#129'j'#255#182#129'j'#255#182#129'j'#255#182#129'j'#255#182#129'j'#255
+ +#182#129'j'#255#182#129'j'#255#181#128'h'#255#177'za'#255#169'kP'#255#139'Q7'
+ +#255'^3'#31#255'\0'#28#255'N9/\GGG'#18'UUU'#3#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'X.'#26'4\0'#28#255
+ ,'^3'#31#255#141'S8'#255#170'mQ'#255#179'|c'#255#182#130'k'#255#184#132'm'#255
+ +#184#132'm'#255#184#132'm'#255#184#132'm'#255#184#132'm'#255#184#132'm'#255
+ +#184#132'm'#255#184#132'm'#255#184#132'm'#255#184#132'm'#255#184#132'm'#255
+ +#184#132'm'#255#184#132'm'#255#184#132'm'#255#184#132'm'#255#184#132'm'#255
+ +#184#132'm'#255#184#132'm'#255#184#132'm'#255#184#132'm'#255#184#132'm'#255
+ +#184#132'm'#255#184#132'm'#255#184#132'm'#255#20#15#12#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255'N8.'#255#184#132'm'#255#184#132'm'#255#184#132'm'
+ +#255#22#16#13#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#21#15#13#255#182#130'm'#255#184#132'm'#255#184#132
+ +'m'#255#184#132'm'#255#184#132'm'#255#184#132'm'#255#184#132'm'#255#184#132
+ +'m'#255#184#132'm'#255#184#132'm'#255#184#132'm'#255'N8.'#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#23#17#13#255#184#132'm'#255#184#132'm'#255#184#132'm'#255
+ +#184#132'm'#255#184#132'm'#255#184#132'm'#255#184#132'm'#255#184#132'm'#255
+ +#184#132'm'#255#184#132'm'#255#183#131'l'#255#182#129'j'#255#177'x_'#255#167
+ +'hK'#255'zG/'#255']1'#30#255'Z0'#28#241'@@@(MMM'#10#0#0#0#1#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'='#31
+ +#18#3'[/'#27#238']1'#30#255'{G/'#255#167'hL'#255#177'za'#255#183#131'l'#255
+ +#185#134'p'#255#185#134'p'#255#185#134'p'#255#185#134'p'#255#185#134'p'#255
+ +#185#134'p'#255#185#134'p'#255#185#134'p'#255#185#134'p'#255#185#134'p'#255
+ +#185#134'p'#255#185#134'p'#255#185#134'p'#255#185#134'p'#255#185#134'p'#255
+ +#185#134'p'#255#185#134'p'#255#185#134'p'#255#185#134'p'#255#185#134'p'#255
+ +#185#134'p'#255#185#134'p'#255#185#134'p'#255#185#134'p'#255#26#19#16#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#12#9#7#255#185#134'p'#255#185#134'p'#255#185#134'p'
+ +#255#185#134'p'#255#3#2#2#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'U>4'#255#185#134'p'#255#185
+ +#134'p'#255#185#134'p'#255#185#134'p'#255#185#134'p'#255#185#134'p'#255#185
+ +#134'p'#255#185#134'p'#255#185#134'p'#255#185#134'p'#255#185#134'p'#255#25#18
+ +#15#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255'xWI'#255#185#134'p'#255#185#134'p'#255#185#134
+ +'p'#255#185#134'p'#255#185#134'p'#255#185#134'p'#255#185#134'p'#255#185#134
+ +'p'#255#185#134'p'#255#185#134'p'#255#184#134'o'#255#182#129'j'#255#175'v\'
+ +#255#165'dG'#255'h;&'#255'\1'#29#255'X2 '#193'==='#25'+++'#6#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0'[/'#27#170'\1'#29#255'f9%'#255#164'bG'#255#175'v]'#255#183#131
+ +'l'#255#186#135'r'#255#186#137's'#255#186#137's'#255#186#137's'#255#186#137
+ +'s'#255#186#137's'#255#186#137's'#255#186#137's'#255#186#137's'#255#186#137
+ +'s'#255#186#137's'#255#186#137's'#255#186#137's'#255#186#137's'#255#186#137
+ +'s'#255#186#137's'#255#186#137's'#255#186#137's'#255#186#137's'#255#186#137
+ +'s'#255#186#137's'#255#186#137's'#255#186#137's'#255#186#137's'#255'$'#27#23
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#129'_P'#255#186#137's'#255#186#137's'#255
+ +#186#137's'#255#186#137's'#255#1#1#1#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255' '#23#19#255#186
+ +#137's'#255#186#137's'#255#186#137's'#255#186#137's'#255#186#137's'#255#186
+ +#137's'#255#186#137's'#255#186#137's'#255#186#137's'#255#186#137's'#255#186
+ +#137's'#255#172#127'j'#255#7#5#4#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#12#9#7#255#186#137's'#255#186#137's'
+ +#255#186#137's'#255#186#137's'#255#186#137's'#255#186#137's'#255#186#137's'
+ +#255#186#137's'#255#186#137's'#255#186#137's'#255#186#137's'#255#185#135'q'
+ +#255#181#129'i'#255#173'qW'#255#149'X='#255'`5!'#255'\0'#28#255'V4%'#127'333'
+ +#15#0#0#0#3#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'Z/'#27'O\0'#28#255'_4 '#255#144'U:'
+ +#255#172'qV'#255#182#130'k'#255#187#137't'#255#188#139'u'#255#188#140'v'#255
+ +#188#140'v'#255#188#140'v'#255#188#140'v'#255#188#140'v'#255#188#140'v'#255
+ +#188#140'v'#255#188#140'v'#255#188#140'v'#255#188#140'v'#255#188#140'v'#255
+ ,#188#140'v'#255#188#140'v'#255#188#140'v'#255#188#140'v'#255#188#140'v'#255
+ +#188#140'v'#255#188#140'v'#255#188#140'v'#255#188#140'v'#255#188#140'v'#255
+ +#188#140'v'#255'1$'#31#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255':+$'#255#188#140'v'#255#188#140
+ +'v'#255#188#140'v'#255#188#140'v'#255#188#140'v'#255#1#1#1#255#0#0#0#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#4#3#3#255#188#140'v'#255#188#140'v'#255#188#140'v'#255#188#140'v'#255
+ +#188#140'v'#255#188#140'v'#255#188#140'v'#255#188#140'v'#255#188#140'v'#255
+ +#188#140'v'#255#188#140'v'#255#188#140'v'#255#188#140'v'#255'}]N'#255'6("'
+ +#255#14#11#9#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'S>5'#255
+ +#188#140'v'#255#188#140'v'#255#188#140'v'#255#188#140'v'#255#188#140'v'#255
+ +#188#140'v'#255#188#140'v'#255#188#140'v'#255#188#140'v'#255#188#140'v'#255
+ +#188#139'u'#255#186#136'r'#255#180'~f'#255#169'kP'#255'|H1'#255'^2'#31#255'['
+ +'/'#27#249'L=6+III'#7#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#5'[/'#27#235
+ +']1'#30#255'wD/'#255#169'jO'#255#180#127'g'#255#187#137'u'#255#189#141'x'#255
+ +#189#142'y'#255#189#142'y'#255#189#142'y'#255#189#142'y'#255#189#142'y'#255
+ +#189#142'y'#255#189#142'y'#255#189#142'y'#255#189#142'y'#255#189#142'y'#255
+ +#189#142'y'#255#189#142'y'#255#189#142'y'#255#189#142'y'#255#189#142'y'#255
+ +#189#142'y'#255#189#142'y'#255#189#142'y'#255#189#142'y'#255#189#142'y'#255
+ +#189#142'y'#255#189#142'y'#255'J7/'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#16#12#11#255#187#140'y'#255
+ +#189#142'y'#255#189#142'y'#255#189#142'y'#255#189#142'y'#255#189#142'y'#255#1
+ +#1#1#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#181#136'u'#255#189#142'y'#255#189#142
+ +'y'#255#189#142'y'#255#189#142'y'#255#189#142'y'#255#189#142'y'#255#189#142
+ +'y'#255#189#142'y'#255#189#142'y'#255#189#142'y'#255#189#142'y'#255#189#142
+ +'y'#255#189#142'y'#255#189#142'y'#255#189#142'y'#255#11#8#7#255#0#0#0#255#0#0
+ +#0#255#0#0#0#255#1#1#1#255#181#136's'#255#189#142'y'#255#189#142'y'#255#189
+ +#142'y'#255#189#142'y'#255#189#142'y'#255#189#142'y'#255#189#142'y'#255#189
+ +#142'y'#255#189#142'y'#255#189#142'y'#255#189#141'x'#255#186#136'q'#255#177
+ +'za'#255#164'dG'#255'f:&'#255'\1'#29#255'Y1'#31#186'@@@'#16'UUU'#3#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'Z/'#27#147'\1'#29#255'b8$'#255#160'bF'#255
+ +#177'y`'#255#186#137's'#255#190#143'z'#255#191#145'|'#255#191#145'|'#255#191
+ +#145'|'#255#191#145'|'#255#191#145'|'#255#191#145'|'#255#191#145'|'#255#191
+ +#145'|'#255#191#145'|'#255#191#145'|'#255#191#145'|'#255#191#145'|'#255#191
+ +#145'|'#255#191#145'|'#255#191#145'|'#255#191#145'|'#255#191#145'|'#255#191
+ +#145'|'#255#191#145'|'#255#191#145'|'#255#191#145'|'#255#191#145'|'#255#162
+ +'{i'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#1#1#1#255#162'{i'#255#191#145'|'#255#191#145'|'#255#191#145'|'#255
+ +#191#145'|'#255#191#145'|'#255#191#145'|'#255#2#1#1#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1
+ +#1#1#255#191#145'|'#255#191#145'|'#255#191#145'|'#255#191#145'|'#255#191#145
+ +'|'#255#191#145'|'#255#191#145'|'#255#191#145'|'#255#191#145'|'#255#191#145
+ +'|'#255#191#145'|'#255#191#145'|'#255#191#145'|'#255#191#145'|'#255#191#145
+ +'|'#255#191#145'|'#255#5#4#3#255#0#0#0#255#0#0#0#255#0#0#0#255'&'#29#25#255
+ +#191#145'|'#255#191#145'|'#255#191#145'|'#255#191#145'|'#255#191#145'|'#255
+ +#191#145'|'#255#191#145'|'#255#191#145'|'#255#191#145'|'#255#191#145'|'#255
+ +#191#145'|'#255#189#142'y'#255#184#134'o'#255#174'sY'#255#143'U;'#255'`5!'
+ +#255'\0'#28#255'U3$`@@@'#8#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0'Z.'#27'5\0'#28#255'_4 '#255#137'Q8'#255#173'rX'#255#184#134'o'#255#190#144
+ +'{'#255#192#147#127#255#192#147#127#255#192#147#127#255#192#147#127#255#192
+ +#147#127#255#192#147#127#255#192#147#127#255#192#147#127#255#192#147#127#255
+ +#192#147#127#255#192#147#127#255#192#147#127#255#192#147#127#255#192#147#127
+ +#255#192#147#127#255#192#147#127#255#192#147#127#255#192#147#127#255#192#147
+ +#127#255#192#147#127#255#192#147#127#255#192#147#127#255#192#147#127#255#14
+ ,#11#9#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255' '
+ +#24#21#255#192#147#127#255#192#147#127#255#192#147#127#255#192#147#127#255
+ +#192#147#127#255#192#147#127#255#192#147#127#255#4#3#3#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#8#6#5#255#192#147#127#255#192#147#127#255#192#147#127#255#192#147#127
+ +#255#192#147#127#255#192#147#127#255#192#147#127#255#192#147#127#255#192#147
+ +#127#255#192#147#127#255#192#147#127#255#192#147#127#255#192#147#127#255#192
+ +#147#127#255#192#147#127#255#192#147#127#255#1#1#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#137'iZ'#255#192#147#127#255#192#147#127#255#192#147#127#255#192#147
+ +#127#255#192#147#127#255#192#147#127#255#192#147#127#255#192#147#127#255#192
+ +#147#127#255#192#147#127#255#192#146'~'#255#189#142'y'#255#182#129'j'#255#169
+ +'lP'#255'uD.'#255'^2'#31#255'[/'#28#237'NFB'#21'UUU'#3#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#211']1'#30#255'l>)'#255#167'iM'
+ +#255#181#127'g'#255#190#143'z'#255#193#148#128#255#194#149#130#255#194#149
+ +#130#255#194#149#130#255#194#149#130#255#194#149#130#255#194#149#130#255#194
+ +#149#130#255#194#149#130#255#194#149#130#255#194#149#130#255#194#149#130#255
+ +#194#149#130#255#194#149#130#255#194#149#130#255#194#149#130#255#194#149#130
+ +#255#194#149#130#255#194#149#130#255#194#149#130#255#194#149#130#255#194#149
+ +#130#255#194#149#130#255'G60'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255'ZE<'#255#194#149#130#255#194#149#130#255#194#149#130#255
+ +#194#149#130#255#194#149#130#255#194#149#130#255#194#149#130#255#7#6#5#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#23#17#15#255#194#149#130#255#194#149#130#255#194#149#130
+ +#255#194#149#130#255#194#149#130#255#194#149#130#255#194#149#130#255#194#149
+ +#130#255#194#149#130#255#194#149#130#255#194#149#130#255#194#149#130#255#194
+ +#149#130#255#194#149#130#255#194#149#130#255#179#137'x'#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255'-#'#30#255#194#149#130#255#194#149#130#255#194#149#130#255#194
+ +#149#130#255#194#149#130#255#194#149#130#255#194#149#130#255#194#149#130#255
+ +#194#149#130#255#194#149#130#255#194#149#130#255#192#147#127#255#188#140'v'
+ +#255#177'za'#255#156'_D'#255'a6#'#255'\1'#29#255'Y1'#31#153'@@@'#8#0#0#0#1#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'Z/'#27']\0'#28#255
+ +'`5!'#255#143'V='#255#175'v]'#255#187#138'u'#255#193#149#129#255#195#152#132
+ +#255#195#152#133#255#195#152#133#255#195#152#133#255#195#152#133#255#195#152
+ +#133#255#195#152#133#255#195#152#133#255#195#152#133#255#195#152#133#255#195
+ +#152#133#255#195#152#133#255#195#152#133#255#195#152#133#255#195#152#133#255
+ +#195#152#133#255#195#152#133#255#195#152#133#255#195#152#133#255#195#152#133
+ +#255#195#152#133#255#195#152#133#255#170#133't'#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#172#133'u'#255#195#152#133#255#195#152
+ +#133#255#195#152#133#255#195#152#133#255#195#152#133#255#195#152#133#255#146
+ +'rd'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'_JA'#255#195#152#133#255#195#152#133
+ +#255#195#152#133#255#195#152#133#255#195#152#133#255#195#152#133#255#195#152
+ +#133#255#195#152#133#255#195#152#133#255#195#152#133#255#195#152#133#255#195
+ +#152#133#255#195#152#133#255#195#152#133#255#195#152#133#255#140'm`'#255#0#0
+ +#0#255#0#0#0#255#6#5#4#255#186#145#127#255#195#152#133#255#195#152#133#255
+ +#195#152#133#255#195#152#133#255#195#152#133#255#195#152#133#255#195#152#133
+ +#255#195#152#133#255#195#152#133#255#195#152#133#255#195#152#132#255#192#147
+ +#127#255#185#134'p'#255#172'pU'#255'|I2'#255'^3'#31#255'\0'#28#250'R5()UUU'#3
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#3
+ +'[/'#27#221']1'#30#255'oA,'#255#169'lP'#255#183#131'l'#255#192#147#127#255
+ +#196#154#135#255#197#155#136#255#197#155#136#255#197#155#136#255#197#155#136
+ +#255#197#155#136#255#197#155#136#255#197#155#136#255#197#155#136#255#197#155
+ +#136#255#197#155#136#255#197#155#136#255#197#155#136#255#197#155#136#255#197
+ +#155#136#255#197#155#136#255#197#155#136#255#197#155#136#255#197#155#136#255
+ +#197#155#136#255#197#155#136#255#197#155#136#255#197#155#136#255#26#20#18#255
+ ,#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#8#6#5#255#197#155#136#255#197
+ +#155#136#255#197#155#136#255#197#155#136#255#197#155#136#255#197#155#136#255
+ +#197#155#136#255#28#22#19#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#4#3#3#255#193#153#134#255
+ +#197#155#136#255#197#155#136#255#197#155#136#255#197#155#136#255#197#155#136
+ +#255#197#155#136#255#197#155#136#255#197#155#136#255#197#155#136#255#197#155
+ +#136#255#197#155#136#255#197#155#136#255#197#155#136#255#197#155#136#255#197
+ +#155#136#255#182#143'~'#255'=0*'#255#7#5#5#255#130'fY'#255#197#155#136#255
+ +#197#155#136#255#197#155#136#255#197#155#136#255#197#155#136#255#197#155#136
+ +#255#197#155#136#255#197#155#136#255#197#155#136#255#197#155#136#255#196#154
+ +#136#255#195#152#133#255#190#144'{'#255#180'~f'#255#159'bG'#255'c8%'#255'\1'
+ +#29#255'Z0'#30#163'III'#7#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27'g\0'#28#255'a6#'#255#147'Y@'#255#177
+ +'za'#255#190#143'z'#255#196#154#135#255#198#157#139#255#198#157#139#255#198
+ +#157#139#255#198#157#139#255#198#157#139#255#198#157#139#255#198#157#139#255
+ +#198#157#139#255#198#157#139#255#198#157#139#255#198#157#139#255#198#157#139
+ +#255#198#157#139#255#198#157#139#255#198#157#139#255#198#157#139#255#198#157
+ +#139#255#198#157#139#255#198#157#139#255#198#157#139#255#198#157#139#255#198
+ +#157#139#255'<0+'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'*!'#29#255
+ +#198#157#139#255#198#157#139#255#198#157#139#255#198#157#139#255#198#157#139
+ +#255#198#157#139#255#164#130's'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'?2,'#255#198
+ +#157#139#255#198#157#139#255#198#157#139#255#198#157#139#255#198#157#139#255
+ +#198#157#139#255#198#157#139#255#198#157#139#255#198#157#139#255#198#157#139
+ +#255#198#157#139#255#198#157#139#255#198#157#139#255#198#157#139#255#198#157
+ +#139#255#198#157#139#255#198#157#139#255#198#157#139#255#198#157#139#255#198
+ +#157#139#255#198#157#139#255#198#157#139#255#198#157#139#255#198#157#139#255
+ +#198#157#139#255#198#157#139#255#198#157#139#255#198#157#139#255#198#157#139
+ +#255#198#157#139#255#198#156#138#255#195#152#132#255#187#138't'#255#173'sY'
+ +#255#127'L5'#255'^3'#31#255'\0'#28#252'U3$,'#128#128#128#2#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#7
+ +'[/'#27#229'^2'#31#255'qB.'#255#171'nS'#255#185#134'p'#255#194#151#131#255
+ +#198#158#140#255#200#160#142#255#200#160#142#255#200#160#142#255#200#160#142
+ +#255#200#160#142#255#200#160#142#255#200#160#142#255#200#160#142#255#200#160
+ +#142#255#200#160#142#255#200#160#142#255#200#160#142#255#200#160#142#255#200
+ +#160#142#255#200#160#142#255#200#160#142#255#200#160#142#255#200#160#142#255
+ +#200#160#142#255#200#160#142#255#200#160#142#255'9.)'#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255'hSJ'#255#200#160#142#255#200#160#142#255#200#160#142
+ +#255#200#160#142#255#200#160#142#255#200#160#142#255'6+'''#255#0#0#0#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#6#5#5#255#184#148#131#255#200#160#142#255#200#160#142#255#200#160#142
+ +#255#200#160#142#255#200#160#142#255#200#160#142#255#200#160#142#255#200#160
+ +#142#255#200#160#142#255#200#160#142#255#200#160#142#255#200#160#142#255#200
+ +#160#142#255#200#160#142#255#200#160#142#255#200#160#142#255#200#160#142#255
+ +#200#160#142#255#200#160#142#255#200#160#142#255#200#160#142#255#200#160#142
+ +#255#200#160#142#255#200#160#142#255#200#160#142#255#200#160#142#255#200#160
+ +#142#255#200#160#142#255#200#160#142#255#199#159#141#255#198#157#139#255#192
+ +#147#127#255#181#127'g'#255#161'dI'#255'd:&'#255'\1'#29#255'Z0'#29#171'@@@'#4
+ +#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27'q\1'#29#255'a6#'#255#143'W?'#255#177'za'#255
+ +#191#144'|'#255#198#157#139#255#200#161#144#255#201#162#145#255#201#163#145
+ +#255#201#163#145#255#201#163#145#255#201#163#145#255#201#163#145#255#201#163
+ +#145#255#201#163#145#255#201#163#145#255#201#163#145#255#201#163#145#255#201
+ +#163#145#255#201#163#145#255#201#163#145#255#201#163#145#255#201#163#145#255
+ +#201#163#145#255#201#163#145#255#201#163#145#255#201#163#145#255'=2,'#255#0#0
+ ,#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255'!'#27#24#255#197#161#143#255#201#163#145#255
+ +#201#163#145#255#201#163#145#255#201#163#145#255#201#163#145#255#197#161#143
+ +#255#3#2#2#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#1#1#1#255#149'zl'#255#201#163#145#255#201#163#145
+ +#255#201#163#145#255#201#163#145#255#201#163#145#255#201#163#145#255#201#163
+ +#145#255#201#163#145#255#201#163#145#255#201#163#145#255#201#163#145#255#201
+ +#163#145#255#201#163#145#255#201#163#145#255#201#163#145#255#201#163#145#255
+ +#201#163#145#255#201#163#145#255#201#163#145#255#201#163#145#255#201#163#145
+ +#255#201#163#145#255#201#163#145#255#201#163#145#255#201#163#145#255#201#163
+ +#145#255#201#163#145#255#201#163#145#255#201#163#145#255#201#162#145#255#200
+ +#161#143#255#197#155#136#255#187#138'u'#255#173'rX'#255'|I3'#255'_4 '#255'\0'
+ +#28#253'W1 2'#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#6'\0'#28#216'^2'#31#255
+ +'i=)'#255#165'jP'#255#184#133'n'#255#196#152#134#255#201#162#145#255#202#164
+ +#148#255#202#165#148#255#202#165#148#255#202#165#148#255#202#165#148#255#202
+ +#165#148#255#202#165#148#255#202#165#148#255#202#165#148#255#202#165#148#255
+ +#202#165#148#255#202#165#148#255#202#165#148#255#202#165#148#255#202#165#148
+ +#255#202#165#148#255#202#165#148#255#202#165#148#255#202#165#148#255#202#165
+ +#148#255'E82'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#2#2#2#255#1#1#1#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'.&"'#255#202#165#148#255#202#165#148
+ +#255#202#165#148#255#202#165#148#255#202#165#148#255#202#165#148#255#202#165
+ +#148#255#146'wk'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'eRI'#255#202#165#148#255#202#165#148
+ +#255#202#165#148#255#202#165#148#255#202#165#148#255#202#165#148#255#202#165
+ +#148#255#202#165#148#255#202#165#148#255#202#165#148#255#202#165#148#255#202
+ +#165#148#255#202#165#148#255#202#165#148#255#202#165#148#255#202#165#148#255
+ +#202#165#148#255#202#165#148#255#202#165#148#255#202#165#148#255#202#165#148
+ +#255#202#165#148#255#202#165#148#255#202#165#148#255#202#165#148#255#202#165
+ +#148#255#202#165#148#255#202#165#148#255#202#165#148#255#202#165#148#255#202
+ +#164#147#255#200#160#143#255#193#148#128#255#180'~f'#255#151'^D'#255'a7$'#255
+ +'\1'#29#255'Z0'#28#156'UUU'#3#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27
+ +'D\0'#28#255'`5!'#255#128'N8'#255#175'v]'#255#190#143'{'#255#200#159#142#255
+ +#203#165#150#255#204#167#151#255#204#167#151#255#204#167#151#255#204#167#151
+ +#255#204#167#151#255#204#167#151#255#204#167#151#255#204#167#151#255#204#167
+ +#151#255#204#167#151#255#204#167#151#255#204#167#151#255#204#167#151#255#204
+ +#167#151#255#204#167#151#255#204#167#151#255#204#167#151#255#204#167#151#255
+ +#204#167#151#255'N?9'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'vaW'#255
+ +#204#167#151#255#160#131'w'#255'cRI'#255'WG@'#255#168#137'|'#255#204#167#151
+ +#255#204#167#151#255#204#167#151#255#204#167#151#255#204#167#151#255#204#167
+ +#151#255#204#167#151#255#204#167#151#255#145'wk'#255#0#0#0#255#0#0#0#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'G:4'#255#204#167
+ +#151#255#204#167#151#255#204#167#151#255#204#167#151#255#204#167#151#255#204
+ +#167#151#255#204#167#151#255#204#167#151#255#204#167#151#255#204#167#151#255
+ +#204#167#151#255#204#167#151#255#204#167#151#255#204#167#151#255#204#167#151
+ +#255#204#167#151#255#204#167#151#255#204#167#151#255#204#167#151#255#204#167
+ +#151#255#204#167#151#255#204#167#151#255#204#167#151#255#204#167#151#255#204
+ +#167#151#255#204#167#151#255#204#167#151#255#204#167#151#255#204#167#151#255
+ +#204#167#151#255#204#167#150#255#202#165#148#255#198#155#138#255#186#137's'
+ +#255#171'nU'#255'oB.'#255'^2'#31#255'\0'#28#235'V2"'#21#0#0#0#1#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#169'\1'#29#255'c9&'#255#155'aH'#255
+ +#182#128'j'#255#195#152#133#255#202#164#148#255#205#169#154#255#206#169#155
+ +#255#206#169#155#255#206#169#155#255#206#169#155#255#206#169#155#255#206#169
+ +#155#255#206#169#155#255#206#169#155#255#206#169#155#255#206#169#155#255#206
+ +#169#155#255#206#169#155#255#206#169#155#255#206#169#155#255#206#169#155#255
+ +#206#169#155#255#206#169#155#255#206#169#155#255'VGA'#255#0#0#0#255#0#0#0#255
+ ,#0#0#0#255#5#4#4#255#206#169#155#255#206#169#155#255#206#169#155#255#206#169
+ +#155#255#206#169#155#255#206#169#155#255#206#169#155#255#206#169#155#255#206
+ +#169#155#255#206#169#155#255#206#169#155#255#206#169#155#255#206#169#155#255
+ +#206#169#155#255#152'}r'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#2#1#1#255'vaY'#255#206#169#155#255#206#169#155#255#206#169
+ +#155#255#206#169#155#255#206#169#155#255#206#169#155#255#206#169#155#255#206
+ +#169#155#255#206#169#155#255#206#169#155#255#206#169#155#255#206#169#155#255
+ +#206#169#155#255#206#169#155#255#206#169#155#255#206#169#155#255#206#169#155
+ +#255#206#169#155#255#206#169#155#255#206#169#155#255#206#169#155#255#206#169
+ +#155#255#206#169#155#255#206#169#155#255#206#169#155#255#206#169#155#255#206
+ +#169#155#255#206#169#155#255#206#169#155#255#206#169#155#255#206#169#155#255
+ +#205#167#152#255#201#162#145#255#192#147#127#255#177'za'#255#138'T='#255'`6"'
+ +#255'\1'#29#255'[0'#29'e'#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0'[/'#27#27'\0'#28#243'^3'#31#255'pC/'#255#171'oU'#255#188#138'u'
+ +#255#199#158#141#255#205#169#154#255#207#171#157#255#207#172#158#255#207#172
+ +#158#255#207#172#158#255#207#172#158#255#207#172#158#255#207#172#158#255#207
+ +#172#158#255#207#172#158#255#207#172#158#255#207#172#158#255#207#172#158#255
+ +#207#172#158#255#207#172#158#255#207#172#158#255#207#172#158#255#207#172#158
+ +#255#207#172#158#255'~i`'#255#0#0#0#255#0#0#0#255#0#0#0#255#22#18#16#255#207
+ +#172#158#255#207#172#158#255#207#172#158#255#207#172#158#255#207#172#158#255
+ +#207#172#158#255#207#172#158#255#207#172#158#255#207#172#158#255#207#172#158
+ +#255#207#172#158#255#207#172#158#255#207#172#158#255#207#172#158#255#207#172
+ +#158#255'/''$'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#9#7#7#255
+ +#164#136'~'#255#207#172#158#255#207#172#158#255#207#172#158#255#207#172#158
+ +#255#207#172#158#255#207#172#158#255#207#172#158#255#207#172#158#255#207#172
+ +#158#255#207#172#158#255#207#172#158#255#207#172#158#255#207#172#158#255#207
+ +#172#158#255#207#172#158#255#207#172#158#255#207#172#158#255#207#172#158#255
+ +#207#172#158#255#207#172#158#255#207#172#158#255#207#172#158#255#207#172#158
+ +#255#207#172#158#255#207#172#158#255#207#172#158#255#207#172#158#255#207#172
+ +#158#255#207#172#158#255#207#172#158#255#207#172#158#255#207#171#157#255#204
+ +#167#151#255#196#153#136#255#183#131'l'#255#160'fK'#255'f;('#255']1'#30#255
+ +'[/'#27#199'te^'#3#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0'[/'#27'q\0'#28#255'`6"'#255#130'P9'#255#177'x`'#255#192#146
+ +#127#255#203#164#149#255#208#173#159#255#209#175#161#255#209#175#161#255#209
+ +#175#161#255#209#175#161#255#209#175#161#255#209#175#161#255#209#175#161#255
+ +#209#175#161#255#209#175#161#255#209#175#161#255#209#175#161#255#209#175#161
+ +#255#209#175#161#255#209#175#161#255#209#175#161#255#209#175#161#255#209#175
+ +#161#255#199#167#153#255#0#0#0#255#0#0#0#255#0#0#0#255'.'#255#209#175#161
+ +#255#209#175#161#255#209#175#161#255#209#175#161#255#209#175#161#255#209#175
+ +#161#255#209#175#161#255#209#175#161#255#209#175#161#255#209#175#161#255#209
+ +#175#161#255#209#175#161#255#209#175#161#255#209#175#161#255#209#175#161#255
+ +#209#175#161#255'*$!'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'"'#28#26#255#197#165#153#255
+ +#209#175#161#255#209#175#161#255#209#175#161#255#209#175#161#255#209#175#161
+ +#255#209#175#161#255#209#175#161#255#209#175#161#255#209#175#161#255#209#175
+ +#161#255#209#175#161#255#209#175#161#255#209#175#161#255#209#175#161#255#209
+ +#175#161#255#209#175#161#255#209#175#161#255#209#175#161#255#209#175#161#255
+ +#209#175#161#255#209#175#161#255#209#175#161#255#209#175#161#255#209#175#161
+ +#255#209#175#161#255#209#175#161#255#209#175#161#255#209#175#161#255#209#175
+ +#161#255#209#175#161#255#209#175#161#255#209#174#160#255#207#171#157#255#200
+ +#160#144#255#188#139'w'#255#171'pV'#255'rD0'#255'^3'#31#255'\0'#28#250'\2'#30
+ +'1'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0'[/'#27#1'[/'#27#184']1'#30#255'c9&'#255#148'^E'#255#182#128'j'#255#197
+ +#154#136#255#206#170#155#255#210#176#163#255#211#178#164#255#211#178#165#255
+ +#211#178#165#255#211#178#165#255#211#178#165#255#211#178#165#255#211#178#165
+ +#255#211#178#165#255#211#178#165#255#211#178#165#255#211#178#165#255#211#178
+ ,#165#255#211#178#165#255#211#178#165#255#211#178#165#255#211#178#165#255#211
+ +#178#165#255#12#10#9#255#0#0#0#255#0#0#0#255'MA<'#255#211#178#165#255#211#178
+ +#165#255#211#178#165#255#211#178#165#255#211#178#165#255#211#178#165#255#211
+ +#178#165#255#211#178#165#255#211#178#165#255#211#178#165#255#211#178#165#255
+ +#211#178#165#255#211#178#165#255#211#178#165#255#211#178#165#255#211#178#165
+ +#255#211#178#165#255#178#150#139#255'D95'#255#9#7#7#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'VIC'#255#211#178#165#255#211#178#165
+ +#255#211#178#165#255#211#178#165#255#211#178#165#255#211#178#165#255#211#178
+ +#165#255#211#178#165#255#211#178#165#255#211#178#165#255#211#178#165#255#211
+ +#178#165#255#211#178#165#255#211#178#165#255#211#178#165#255#211#178#165#255
+ +#211#178#165#255#211#178#165#255#211#178#165#255#211#178#165#255#211#178#165
+ +#255#211#178#165#255#211#178#165#255#211#178#165#255#211#178#165#255#211#178
+ +#165#255#211#178#165#255#211#178#165#255#211#178#165#255#211#178#165#255#211
+ +#178#165#255#211#178#165#255#211#178#164#255#209#176#162#255#204#167#151#255
+ +#193#148#129#255#177'x`'#255#129'P9'#255'`6"'#255'\0'#28#255'[0'#28't'#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0'[/'#27#21'\0'#28#229'^2'#31#255'i?+'#255#163'jP'#255#186#136
+ +'s'#255#200#160#144#255#209#174#160#255#212#180#167#255#213#181#169#255#213
+ +#181#169#255#213#181#169#255#213#181#169#255#213#181#169#255#213#181#169#255
+ +#213#181#169#255#213#181#169#255#213#181#169#255#213#181#169#255#213#181#169
+ +#255#213#181#169#255#213#181#169#255#213#181#169#255#213#181#169#255#213#181
+ +#169#255'.''%'#255#0#0#0#255',%#'#255#200#170#159#255#213#181#169#255#213#181
+ +#169#255#213#181#169#255#213#181#169#255#213#181#169#255#213#181#169#255#213
+ +#181#169#255#213#181#169#255#213#181#169#255#213#181#169#255#213#181#169#255
+ +#213#181#169#255#213#181#169#255#213#181#169#255#213#181#169#255#213#181#169
+ +#255#213#181#169#255#213#181#169#255#213#181#169#255#139'vo'#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'.''$'#255#213#181#169#255#213#181#169
+ +#255#213#181#169#255#213#181#169#255#213#181#169#255#213#181#169#255#213#181
+ +#169#255#213#181#169#255#213#181#169#255#213#181#169#255#213#181#169#255#213
+ +#181#169#255#213#181#169#255#213#181#169#255#213#181#169#255#213#181#169#255
+ +#213#181#169#255#213#181#169#255#213#181#169#255#213#181#169#255#213#181#169
+ +#255#213#181#169#255#213#181#169#255#213#181#169#255#213#181#169#255#213#181
+ +#169#255#213#181#169#255#213#181#169#255#213#181#169#255#213#181#169#255#213
+ +#181#169#255#213#181#169#255#212#180#168#255#211#178#165#255#207#171#157#255
+ +#197#155#137#255#182#128'j'#255#148']E'#255'c9&'#255']1'#30#255'[/'#27#179#0
+ +#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27'?\0'#28#252'_4 '#255'tF1'#255#172
+ +'sY'#255#190#142'z'#255#203#165#150#255#211#178#164#255#213#183#170#255#214
+ +#184#172#255#214#184#172#255#214#184#172#255#214#184#172#255#214#184#172#255
+ +#214#184#172#255#214#184#172#255#214#184#172#255#214#184#172#255#214#184#172
+ +#255#214#184#172#255#214#184#172#255#214#184#172#255#214#184#172#255#214#184
+ +#172#255#127'ng'#255'{ib'#255#214#184#172#255#214#184#172#255#214#184#172#255
+ +#214#184#172#255#214#184#172#255#214#184#172#255#214#184#172#255#214#184#172
+ +#255#214#184#172#255#214#184#172#255#214#184#172#255#214#184#172#255#214#184
+ +#172#255#214#184#172#255#214#184#172#255#214#184#172#255#214#184#172#255#214
+ +#184#172#255#214#184#172#255#214#184#172#255#214#184#172#255' '#28#26#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#14#12#11#255#209#180#168#255#214#184#172
+ +#255#214#184#172#255#214#184#172#255#214#184#172#255#214#184#172#255#214#184
+ +#172#255#214#184#172#255#214#184#172#255#214#184#172#255#214#184#172#255#214
+ +#184#172#255#214#184#172#255#214#184#172#255#214#184#172#255#214#184#172#255
+ +#214#184#172#255#214#184#172#255#214#184#172#255#214#184#172#255#214#184#172
+ +#255#214#184#172#255#214#184#172#255#214#184#172#255#214#184#172#255#214#184
+ +#172#255#214#184#172#255#214#184#172#255#214#184#172#255#214#184#172#255#214
+ +#184#172#255#214#184#172#255#214#184#172#255#213#182#169#255#209#176#161#255
+ +#200#161#143#255#186#135'q'#255#161'gO'#255'h=*'#255'^2'#31#255'\0'#28#226'W'
+ +'-'#26#19#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27'}\1'#29#255'`6"'
+ +#255'|M8'#255#175'x^'#255#192#147#127#255#205#170#154#255#213#181#169#255#215
+ ,#185#173#255#216#187#175#255#216#187#175#255#216#187#175#255#216#187#175#255
+ +#216#187#175#255#216#187#175#255#216#187#175#255#216#187#175#255#216#187#175
+ +#255#216#187#175#255#216#187#175#255#216#187#175#255#216#187#175#255#216#187
+ +#175#255#216#187#175#255#216#187#175#255#216#187#175#255#216#187#175#255#216
+ +#187#175#255#216#187#175#255#216#187#175#255#216#187#175#255#216#187#175#255
+ +#216#187#175#255#216#187#175#255#216#187#175#255#216#187#175#255#216#187#175
+ +#255#216#187#175#255#216#187#175#255#216#187#175#255#216#187#175#255#216#187
+ +#175#255#216#187#175#255#216#187#175#255#216#187#175#255#187#162#151#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#2#2#2#255#180#156#146#255#216#187#175
+ +#255#216#187#175#255#216#187#175#255#216#187#175#255#216#187#175#255#216#187
+ +#175#255#216#187#175#255#216#187#175#255#216#187#175#255#216#187#175#255#216
+ +#187#175#255#216#187#175#255#216#187#175#255#216#187#175#255#216#187#175#255
+ +#216#187#175#255#216#187#175#255#216#187#175#255#216#187#175#255#216#187#175
+ +#255#216#187#175#255#216#187#175#255#216#187#175#255#216#187#175#255#216#187
+ +#175#255#216#187#175#255#216#187#175#255#216#187#175#255#216#187#175#255#216
+ +#187#175#255#216#187#175#255#216#187#175#255#215#185#173#255#211#179#166#255
+ +#202#165#148#255#188#139'w'#255#167'mU'#255'nC/'#255'^3'#31#255'\0'#28#251'Z'
+ +'.'#27';'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#2'[/'#27
+ +#170'\1'#29#255'a7$'#255#130'Q<'#255#178'{c'#255#195#151#132#255#208#173#159
+ +#255#215#185#173#255#217#189#178#255#217#189#178#255#217#189#178#255#217#189
+ +#178#255#217#189#178#255#217#189#178#255#217#189#178#255#217#189#178#255#217
+ +#189#178#255#217#189#178#255#217#189#178#255#217#189#178#255#217#189#178#255
+ +#217#189#178#255#217#189#178#255#217#189#178#255#217#189#178#255#217#189#178
+ +#255#217#189#178#255#217#189#178#255#217#189#178#255#217#189#178#255#217#189
+ +#178#255#217#189#178#255#217#189#178#255#217#189#178#255#217#189#178#255#217
+ +#189#178#255#217#189#178#255#217#189#178#255#217#189#178#255#217#189#178#255
+ +#217#189#178#255#217#189#178#255#217#189#178#255#217#189#178#255'.(&'#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#128'oi'#255#217#189#178#255#217#189#178
+ +#255#217#189#178#255#217#189#178#255#217#189#178#255#217#189#178#255#217#189
+ +#178#255#217#189#178#255#217#189#178#255#217#189#178#255#217#189#178#255#217
+ +#189#178#255#217#189#178#255#217#189#178#255#217#189#178#255#217#189#178#255
+ +#217#189#178#255#217#189#178#255#217#189#178#255#217#189#178#255#217#189#178
+ +#255#217#189#178#255#217#189#178#255#217#189#178#255#217#189#178#255#217#189
+ +#178#255#217#189#178#255#217#189#178#255#217#189#178#255#217#189#178#255#217
+ +#189#178#255#217#189#178#255#217#188#177#255#213#183#170#255#205#168#153#255
+ +#191#144'|'#255#170'rZ'#255'sF2'#255'`5!'#255'\0'#28#255'Z/'#27'g'#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#6'[/'#27
+ +#188']1'#30#255'c9&'#255#136'V?'#255#180'~g'#255#197#154#136#255#209#176#162
+ +#255#216#187#176#255#219#192#181#255#219#192#182#255#219#193#183#255#219#193
+ +#183#255#219#193#183#255#219#193#183#255#219#193#183#255#219#193#183#255#219
+ +#193#183#255#219#193#183#255#219#193#183#255#219#193#183#255#219#193#183#255
+ +#219#193#183#255#219#193#183#255#219#193#183#255#219#193#183#255#219#193#183
+ +#255#219#193#183#255#219#193#183#255#219#193#183#255#219#193#183#255#219#193
+ +#183#255#219#193#183#255#219#193#183#255#219#193#183#255#219#193#183#255#219
+ +#193#183#255#219#193#183#255#219#193#183#255#219#193#183#255#219#193#183#255
+ +#219#193#183#255#219#193#183#255#158#138#131#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#1#1#1#255#131'sm'#255#219#193#183#255#219#193#183#255#219#193#183#255
+ +#219#193#183#255#219#193#183#255#219#193#183#255#219#193#183#255#219#193#183
+ +#255#219#193#183#255#219#193#183#255#219#193#183#255#219#193#183#255#219#193
+ +#183#255#219#193#183#255#219#193#183#255#219#193#183#255#219#193#183#255#219
+ +#193#183#255#219#193#183#255#219#193#183#255#219#193#183#255#219#193#183#255
+ +#219#193#183#255#219#193#183#255#219#193#183#255#219#193#183#255#219#193#183
+ +#255#219#193#183#255#219#193#183#255#219#193#183#255#219#193#183#255#219#192
+ +#182#255#218#191#180#255#215#185#173#255#207#172#156#255#193#147#128#255#174
+ +'v^'#255'wJ6'#255'`6"'#255'\1'#29#255'[/'#27'~'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ ,#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#12'[/'#27#203
+ +']1'#30#255'c:'''#255#141'YC'#255#181#128'h'#255#198#155#138#255#210#177#164
+ +#255#217#190#178#255#220#194#184#255#221#195#185#255#221#196#186#255#221#196
+ +#186#255#221#196#186#255#221#196#186#255#221#196#186#255#221#196#186#255#221
+ +#196#186#255#221#196#186#255#221#196#186#255#221#196#186#255#221#196#186#255
+ +#221#196#186#255#221#196#186#255#221#196#186#255#221#196#186#255#221#196#186
+ +#255#221#196#186#255#221#196#186#255#221#196#186#255#221#196#186#255#221#196
+ +#186#255#221#196#186#255#221#196#186#255#221#196#186#255#221#196#186#255#221
+ +#196#186#255#221#196#186#255#221#196#186#255#221#196#186#255#221#196#186#255
+ +#221#196#186#255're_'#255#0#0#0#255#0#0#0#255#4#4#4#255#160#142#134#255#221
+ +#196#186#255#221#196#186#255#221#196#186#255#221#196#186#255#221#196#186#255
+ +#221#196#186#255#221#196#186#255#221#196#186#255#221#196#186#255#221#196#186
+ +#255#221#196#186#255#221#196#186#255#221#196#186#255#221#196#186#255#221#196
+ +#186#255#221#196#186#255#221#196#186#255#221#196#186#255#221#196#186#255#221
+ +#196#186#255#221#196#186#255#221#196#186#255#221#196#186#255#221#196#186#255
+ +#221#196#186#255#221#196#186#255#221#196#186#255#221#196#186#255#221#196#186
+ +#255#221#196#186#255#221#196#186#255#221#195#185#255#219#193#183#255#216#187
+ +#175#255#207#172#158#255#194#148#130#255#176'x_'#255'{M8'#255'a6#'#255'\1'#29
+ +#255'[/'#27#148#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#21'\0'#28#217']1'#30#255'c:'''
+ +#255#138'XB'#255#181#127'h'#255#197#156#137#255#211#178#164#255#218#191#180
+ +#255#221#196#187#255#222#198#188#255#223#198#189#255#223#198#189#255#223#198
+ +#189#255#223#198#189#255#223#198#189#255#223#198#189#255#223#198#189#255#223
+ +#198#189#255#223#198#189#255#223#198#189#255#223#198#189#255#223#198#189#255
+ +#223#198#189#255#223#198#189#255#223#198#189#255#223#198#189#255#223#198#189
+ +#255#223#198#189#255#223#198#189#255#223#198#189#255#223#198#189#255#223#198
+ +#189#255#223#198#189#255#223#198#189#255#223#198#189#255#223#198#189#255#223
+ +#198#189#255#223#198#189#255#223#198#189#255#223#198#189#255#221#196#187#255
+ +#6#6#5#255#10#9#8#255#188#167#159#255#223#198#189#255#223#198#189#255#223#198
+ +#189#255#223#198#189#255#223#198#189#255#223#198#189#255#223#198#189#255#223
+ +#198#189#255#223#198#189#255#223#198#189#255#223#198#189#255#223#198#189#255
+ +#223#198#189#255#223#198#189#255#223#198#189#255#223#198#189#255#223#198#189
+ +#255#223#198#189#255#223#198#189#255#223#198#189#255#223#198#189#255#223#198
+ +#189#255#223#198#189#255#223#198#189#255#223#198#189#255#223#198#189#255#223
+ +#198#189#255#223#198#189#255#223#198#189#255#223#198#189#255#223#198#189#255
+ +#222#198#188#255#221#196#186#255#217#188#177#255#208#173#159#255#193#149#129
+ +#255#174'w^'#255'zM8'#255'a7$'#255'\1'#29#255'[/'#27#170'[/'#27#2#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0'[/'#27' \0'#28#223']1'#30#255'c:'''#255#132'T?'#255#180
+ +'~g'#255#197#155#136#255#211#178#164#255#219#193#181#255#223#198#189#255#224
+ +#201#192#255#224#201#192#255#224#201#192#255#224#201#192#255#224#201#192#255
+ +#224#201#192#255#224#201#192#255#224#201#192#255#224#201#192#255#224#201#192
+ +#255#224#201#192#255#224#201#192#255#224#201#192#255#224#201#192#255#224#201
+ +#192#255#224#201#192#255#224#201#192#255#224#201#192#255#224#201#192#255#224
+ +#201#192#255#224#201#192#255#224#201#192#255#224#201#192#255#224#201#192#255
+ +#224#201#192#255#224#201#192#255#224#201#192#255#224#201#192#255#224#201#192
+ +#255#224#201#192#255#224#201#192#255#134'xr'#255#205#184#176#255#224#201#192
+ +#255#224#201#192#255#224#201#192#255#224#201#192#255#224#201#192#255#224#201
+ +#192#255#224#201#192#255#224#201#192#255#224#201#192#255#224#201#192#255#224
+ +#201#192#255#224#201#192#255#224#201#192#255#224#201#192#255#224#201#192#255
+ +#224#201#192#255#224#201#192#255#224#201#192#255#224#201#192#255#224#201#192
+ +#255#224#201#192#255#224#201#192#255#224#201#192#255#224#201#192#255#224#201
+ +#192#255#224#201#192#255#224#201#192#255#224#201#192#255#224#201#192#255#224
+ +#201#192#255#224#201#192#255#223#200#191#255#222#197#187#255#217#189#178#255
+ +#207#172#158#255#192#147#127#255#171'u\'#255'vI6'#255'a6#'#255'\1'#29#255'[/'
+ +#27#179'[/'#27#6#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ ,#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#25'\'
+ +'0'#28#209']1'#30#255'c9&'#255#128'Q='#255#177'{c'#255#195#151#133#255#209
+ +#176#162#255#219#192#181#255#223#200#191#255#225#203#194#255#226#204#196#255
+ +#226#204#196#255#226#204#196#255#226#204#196#255#226#204#196#255#226#204#196
+ +#255#226#204#196#255#226#204#196#255#226#204#196#255#226#204#196#255#226#204
+ +#196#255#226#204#196#255#226#204#196#255#226#204#196#255#226#204#196#255#226
+ +#204#196#255#226#204#196#255#226#204#196#255#226#204#196#255#226#204#196#255
+ +#226#204#196#255#226#204#196#255#226#204#196#255#226#204#196#255#226#204#196
+ +#255#226#204#196#255#226#204#196#255#226#204#196#255#226#204#196#255#226#204
+ +#196#255#226#204#196#255#226#204#196#255#226#204#196#255#226#204#196#255#226
+ +#204#196#255#226#204#196#255#226#204#196#255#226#204#196#255#226#204#196#255
+ +#226#204#196#255#226#204#196#255#226#204#196#255#226#204#196#255#226#204#196
+ +#255#226#204#196#255#226#204#196#255#226#204#196#255#226#204#196#255#226#204
+ +#196#255#226#204#196#255#226#204#196#255#226#204#196#255#226#204#196#255#226
+ +#204#196#255#226#204#196#255#226#204#196#255#226#204#196#255#226#204#196#255
+ +#226#204#196#255#226#204#196#255#226#203#195#255#225#202#193#255#222#198#188
+ +#255#217#188#177#255#206#169#155#255#191#144'|'#255#168'qY'#255'rG3'#255'`6"'
+ +#255'\1'#29#255'[/'#27#159'[/'#27#4#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0'[/'#27#15'\0'#28#193']1'#30#255'b8%'#255'yM8'#255#170
+ +'u\'#255#192#146'~'#255#207#171#156#255#217#189#178#255#223#200#191#255#226
+ +#205#197#255#227#206#198#255#228#207#199#255#228#207#199#255#228#207#199#255
+ +#228#207#199#255#228#207#199#255#228#207#199#255#228#207#199#255#228#207#199
+ +#255#228#207#199#255#228#207#199#255#228#207#199#255#228#207#199#255#228#207
+ +#199#255#228#207#199#255#228#207#199#255#228#207#199#255#228#207#199#255#228
+ +#207#199#255#228#207#199#255#228#207#199#255#228#207#199#255#228#207#199#255
+ +#228#207#199#255#228#207#199#255#228#207#199#255#228#207#199#255#228#207#199
+ +#255#228#207#199#255#228#207#199#255#228#207#199#255#228#207#199#255#228#207
+ +#199#255#228#207#199#255#228#207#199#255#228#207#199#255#228#207#199#255#228
+ +#207#199#255#228#207#199#255#228#207#199#255#228#207#199#255#228#207#199#255
+ +#228#207#199#255#228#207#199#255#228#207#199#255#228#207#199#255#228#207#199
+ +#255#228#207#199#255#228#207#199#255#228#207#199#255#228#207#199#255#228#207
+ +#199#255#228#207#199#255#228#207#199#255#228#207#199#255#228#207#199#255#228
+ +#207#199#255#228#207#199#255#227#206#198#255#226#204#196#255#222#198#188#255
+ +#215#185#173#255#202#165#148#255#187#137'u'#255#159'jR'#255'nD0'#255'`6"'#255
+ +'\1'#29#255'[/'#27#137#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#8'[/'#27#175'\1'#29#255'`6"'#255'n'
+ +'D0'#255#158'iR'#255#187#137'u'#255#202#165#148#255#215#186#174#255#223#199
+ +#190#255#227#205#198#255#229#208#201#255#229#209#202#255#229#210#202#255#229
+ +#210#202#255#229#210#202#255#229#210#202#255#229#210#202#255#229#210#202#255
+ +#229#210#202#255#229#210#202#255#229#210#202#255#229#210#202#255#229#210#202
+ +#255#229#210#202#255#229#210#202#255#229#210#202#255#229#210#202#255#229#210
+ +#202#255#229#210#202#255#229#210#202#255#229#210#202#255#229#210#202#255#229
+ +#210#202#255#229#210#202#255#229#210#202#255#229#210#202#255#229#210#202#255
+ +#229#210#202#255#229#210#202#255#229#210#202#255#229#210#202#255#229#210#202
+ +#255#229#210#202#255#229#210#202#255#229#210#202#255#229#210#202#255#229#210
+ +#202#255#229#210#202#255#229#210#202#255#229#210#202#255#229#210#202#255#229
+ +#210#202#255#229#210#202#255#229#210#202#255#229#210#202#255#229#210#202#255
+ +#229#210#202#255#229#210#202#255#229#210#202#255#229#210#202#255#229#210#202
+ +#255#229#210#202#255#229#210#202#255#229#210#202#255#229#210#202#255#229#209
+ +#202#255#228#207#201#255#226#204#197#255#221#196#187#255#212#180#168#255#198
+ +#157#140#255#183#130'l'#255#143'^G'#255'g>+'#255'_4 '#255'\1'#29#254'[/'#27
+ +'q'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ ,#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#3'[/'#27#132'\1'#29#254'_4 '#255'g>+'
+ +#255#140'[F'#255#181#129'j'#255#198#155#138#255#211#178#165#255#221#195#185
+ +#255#227#204#197#255#230#209#203#255#230#212#205#255#231#212#206#255#231#212
+ +#206#255#231#212#206#255#231#212#206#255#231#212#206#255#231#212#206#255#231
+ +#212#206#255#231#212#206#255#231#212#206#255#231#212#206#255#231#212#206#255
+ +#231#212#206#255#231#212#206#255#231#212#206#255#231#212#206#255#231#212#206
+ +#255#231#212#206#255#231#212#206#255#231#212#206#255#231#212#206#255#231#212
+ +#206#255#231#212#206#255#231#212#206#255#231#212#206#255#231#212#206#255#231
+ +#212#206#255#231#212#206#255#231#212#206#255#231#212#206#255#231#212#206#255
+ +#231#212#206#255#231#212#206#255#231#212#206#255#231#212#206#255#231#212#206
+ +#255#231#212#206#255#231#212#206#255#231#212#206#255#231#212#206#255#231#212
+ +#206#255#231#212#206#255#231#212#206#255#231#212#206#255#231#212#206#255#231
+ +#212#206#255#231#212#206#255#231#212#206#255#231#212#206#255#231#212#206#255
+ +#231#212#206#255#231#211#206#255#230#211#205#255#229#209#201#255#225#203#194
+ +#255#219#191#181#255#208#173#159#255#193#149#129#255#173'w`'#255'~Q='#255'c:'
+ +''''#255'^2'#31#255'\0'#28#238'[/'#27'O'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0'[/'#27'F\0'#28#234'^2'#31#255'c:'''#255'zN:'#255#168's['#255
+ +#190#143'{'#255#205#167#152#255#217#187#177#255#225#201#193#255#229#209#202
+ +#255#232#213#207#255#232#214#209#255#233#215#210#255#233#215#210#255#233#215
+ +#210#255#233#215#210#255#233#215#210#255#233#215#210#255#233#215#210#255#233
+ +#215#210#255#233#215#210#255#233#215#210#255#233#215#210#255#233#215#210#255
+ +#233#215#210#255#233#215#210#255#233#215#210#255#233#215#210#255#233#215#210
+ +#255#233#215#210#255#233#215#210#255#233#215#210#255#233#215#210#255#233#215
+ +#210#255#233#215#210#255#233#215#210#255#233#215#210#255#233#215#210#255#233
+ +#215#210#255#233#215#210#255#233#215#210#255#233#215#210#255#233#215#210#255
+ +#233#215#210#255#233#215#210#255#233#215#210#255#233#215#210#255#233#215#210
+ +#255#233#215#210#255#233#215#210#255#233#215#210#255#233#215#210#255#233#215
+ +#210#255#233#215#210#255#233#215#210#255#233#215#210#255#233#215#210#255#233
+ +#215#210#255#232#215#209#255#232#214#208#255#231#212#206#255#228#207#201#255
+ +#223#198#189#255#213#182#170#255#200#160#144#255#186#136'r'#255#158'iR'#255
+ +'pE2'#255'a7$'#255']1'#30#255'\0'#28#201'[/'#27#31#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#26'\0'#28#193']1'#30#255'`'
+ +'6"'#255'iA.'#255#142']H'#255#179#128'h'#255#196#153#135#255#210#176#163#255
+ +#220#194#184#255#227#205#198#255#231#212#206#255#233#216#211#255#234#217#212
+ +#255#234#218#213#255#234#218#213#255#234#218#213#255#234#218#213#255#234#218
+ +#213#255#234#218#213#255#234#218#213#255#234#218#213#255#234#218#213#255#234
+ +#218#213#255#234#218#213#255#234#218#213#255#234#218#213#255#234#218#213#255
+ +#234#218#213#255#234#218#213#255#234#218#213#255#234#218#213#255#234#218#213
+ +#255#234#218#213#255#234#218#213#255#234#218#213#255#234#218#213#255#234#218
+ +#213#255#234#218#213#255#234#218#213#255#234#218#213#255#234#218#213#255#234
+ +#218#213#255#234#218#213#255#234#218#213#255#234#218#213#255#234#218#213#255
+ +#234#218#213#255#234#218#213#255#234#218#213#255#234#218#213#255#234#218#213
+ +#255#234#218#213#255#234#218#213#255#234#218#213#255#234#218#213#255#234#217
+ +#212#255#234#216#211#255#233#215#210#255#230#211#205#255#226#203#195#255#218
+ +#190#179#255#206#170#155#255#192#146#127#255#172'v`'#255#129'S?'#255'e<)'#255
+ +'_4 '#255'\1'#29#255'[/'#27#143'[/'#27#5#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#3'[/'#27#127'\0'#28
+ +#248'^3'#31#255'c:'''#255'sI6'#255#158'kT'#255#186#136's'#255#200#160#143#255
+ ,#213#180#169#255#222#197#187#255#229#208#201#255#232#214#209#255#234#218#213
+ +#255#235#219#215#255#236#220#215#255#236#220#216#255#236#220#216#255#236#220
+ +#216#255#236#220#216#255#236#220#216#255#236#220#216#255#236#220#216#255#236
+ +#220#216#255#236#220#216#255#236#220#216#255#236#220#216#255#236#220#216#255
+ +#236#220#216#255#236#220#216#255#236#220#216#255#236#220#216#255#236#220#216
+ +#255#236#220#216#255#236#220#216#255#236#220#216#255#236#220#216#255#236#220
+ +#216#255#236#220#216#255#236#220#216#255#236#220#216#255#236#220#216#255#236
+ +#220#216#255#236#220#216#255#236#220#216#255#236#220#216#255#236#220#216#255
+ +#236#220#216#255#236#220#216#255#236#220#216#255#236#220#216#255#236#220#216
+ +#255#236#220#216#255#236#220#215#255#235#219#215#255#234#217#212#255#232#213
+ +#207#255#227#205#198#255#219#193#183#255#209#176#162#255#196#153#136#255#181
+ +#129'l'#255#145'`K'#255'lB0'#255'a7$'#255']1'#30#255'\0'#28#231'[/'#27'O'#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27'$\0'#28#185'\1'#29#255'`5!'#255
+ +'f=*'#255#128'S>'#255#166'r['#255#188#139'v'#255#201#161#145#255#213#181#169
+ +#255#223#197#189#255#229#209#202#255#233#216#210#255#235#219#215#255#236#221
+ +#217#255#237#222#219#255#238#223#220#255#238#223#220#255#238#223#220#255#238
+ +#223#220#255#238#223#220#255#238#223#220#255#238#223#220#255#238#223#220#255
+ +#238#223#220#255#238#223#220#255#238#223#220#255#238#223#220#255#238#223#220
+ +#255#238#223#220#255#238#223#220#255#238#223#220#255#238#223#220#255#238#223
+ +#220#255#238#223#220#255#238#223#220#255#238#223#220#255#238#223#220#255#238
+ +#223#220#255#238#223#220#255#238#223#220#255#238#223#220#255#238#223#220#255
+ +#238#223#220#255#238#223#220#255#238#223#220#255#238#223#220#255#238#223#220
+ +#255#237#222#219#255#237#222#218#255#236#221#217#255#235#218#214#255#232#214
+ +#208#255#228#206#199#255#220#193#184#255#210#176#163#255#197#155#137#255#184
+ +#134'o'#255#155'iR'#255'uI7'#255'c:'''#255'^3'#31#255'\1'#29#252'[/'#27#144
+ +'[/'#27#14#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'['
+ +'/'#27'U\0'#28#228']1'#30#255'`6"'#255'g>,'#255#127'R?'#255#164'qZ'#255#188
+ +#139'v'#255#200#159#144#255#211#179#166#255#220#194#184#255#228#206#199#255
+ +#232#214#209#255#235#219#215#255#237#222#219#255#238#225#221#255#239#225#222
+ +#255#239#225#222#255#239#226#223#255#239#226#223#255#239#226#223#255#239#226
+ +#223#255#239#226#223#255#239#226#223#255#239#226#223#255#239#226#223#255#239
+ +#226#223#255#239#226#223#255#239#226#223#255#239#226#223#255#239#226#223#255
+ +#239#226#223#255#239#226#223#255#239#226#223#255#239#226#223#255#239#226#223
+ +#255#239#226#223#255#239#226#223#255#239#226#223#255#239#226#223#255#239#226
+ +#223#255#239#226#223#255#239#226#223#255#239#225#222#255#238#225#221#255#238
+ +#224#220#255#237#222#218#255#235#218#214#255#231#212#206#255#226#203#195#255
+ +#218#191#180#255#209#174#160#255#197#154#136#255#184#132'o'#255#154'hR'#255
+ +'uK8'#255'e;('#255'_4 '#255'\1'#29#255'\0'#28#197'[/'#27'/'#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27
+ +#12'[/'#27#134'\0'#28#242'^2'#31#255'a5#'#255'g>+'#255'|Q='#255#160'lV'#255
+ +#184#133'p'#255#196#152#134#255#207#170#156#255#216#187#175#255#224#200#192
+ +#255#230#210#203#255#234#216#211#255#236#220#216#255#238#224#220#255#239#226
+ +#223#255#240#227#225#255#240#228#225#255#240#228#225#255#241#229#226#255#241
+ +#229#226#255#241#229#226#255#241#229#226#255#241#229#227#255#241#229#227#255
+ +#241#229#227#255#241#229#227#255#241#229#227#255#241#229#227#255#241#229#227
+ +#255#241#229#227#255#241#229#227#255#241#229#226#255#241#229#226#255#241#229
+ ,#226#255#241#229#226#255#240#228#225#255#240#228#225#255#240#227#224#255#239
+ +#225#222#255#238#223#220#255#236#220#215#255#233#215#210#255#228#207#201#255
+ +#222#196#187#255#213#183#170#255#204#166#150#255#192#147#127#255#179#127'i'
+ +#255#150'fO'#255'tI7'#255'e;('#255'`5!'#255']1'#30#255'\0'#28#223'[/'#27'`[/'
+ +#27#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#17'[/'#27#127'\0'#28#238']1'
+ +#30#255'`6"'#255'e<)'#255'rI6'#255#142'_J'#255#170'wa'#255#188#140'w'#255#199
+ +#158#141#255#208#173#159#255#216#186#175#255#222#196#187#255#227#206#198#255
+ +#232#213#208#255#235#219#214#255#237#222#218#255#238#224#220#255#239#226#223
+ +#255#240#227#225#255#241#229#226#255#242#230#228#255#242#230#228#255#242#231
+ +#229#255#242#231#229#255#242#231#229#255#242#231#229#255#242#231#229#255#242
+ +#231#229#255#242#231#229#255#242#230#228#255#241#229#227#255#241#229#226#255
+ +#240#227#225#255#239#225#222#255#238#224#220#255#236#221#217#255#234#218#213
+ +#255#231#211#206#255#226#204#196#255#220#194#184#255#214#183#171#255#206#169
+ +#155#255#196#153#135#255#185#135'r'#255#162'q['#255#134'XD'#255'lC1'#255'c:'
+ +''''#255'_4 '#255']0'#30#255'\0'#28#217'[/'#27'`[/'#27#4#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#13'[/'#27'w\0'#28#233
+ +']1'#30#255'_4 '#255'b8%'#255'h?-'#255'zN;'#255#149'dP'#255#170'xa'#255#187
+ +#137't'#255#194#150#131#255#202#164#148#255#210#176#163#255#216#187#175#255
+ +#220#194#184#255#224#200#192#255#228#207#199#255#231#212#206#255#234#217#211
+ +#255#236#220#215#255#236#222#217#255#237#222#219#255#238#223#220#255#238#223
+ +#220#255#238#224#220#255#238#223#220#255#237#223#219#255#237#223#218#255#236
+ +#221#217#255#235#219#215#255#233#216#210#255#230#211#204#255#227#204#197#255
+ +#223#199#190#255#219#192#183#255#215#185#173#255#208#173#159#255#200#160#144
+ +#255#192#146#127#255#183#133'o'#255#164's\'#255#142']J'#255'rI7'#255'f=*'#255
+ +'a6#'#255'^3'#31#255'\1'#29#255'\0'#28#210'[/'#27'X[/'#27#2#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0'[/'#27#5'[/'#27'P\0'#28#173'\1'#29#249']1'#30#255'`5!'#255'c9&'#255'g'
+ +'>,'#255'qH6'#255#133'YE'#255#153'iT'#255#172'yd'#255#186#136'q'#255#191#144
+ +'}'#255#196#153#136#255#202#162#146#255#207#171#156#255#211#178#165#255#214
+ +#183#171#255#216#186#175#255#217#188#177#255#218#190#179#255#219#191#182#255
+ +#219#192#182#255#219#192#181#255#218#189#179#255#217#187#177#255#215#185#173
+ +#255#213#182#169#255#210#176#163#255#205#169#154#255#200#160#144#255#195#151
+ +#133#255#190#142'z'#255#183#132'o'#255#167'u_'#255#148'eP'#255#127'S@'#255'm'
+ +'E2'#255'f=*'#255'b7%'#255'_4 '#255']1'#30#255'\0'#28#235'[/'#27#147'[/'#27
+ +'5'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'['
+ ,'/'#27#18'[/'#27'i\0'#28#199'\1'#29#254']1'#30#255'_4 '#255'a6#'#255'd9('#255
+ +'g>,'#255'oF3'#255'}Q>'#255#138'[G'#255#149'fQ'#255#160'oZ'#255#170'xa'#255
+ +#176'}h'#255#180#128'l'#255#183#133'p'#255#186#136's'#255#188#138'u'#255#188
+ +#139'v'#255#187#138'u'#255#186#135'r'#255#183#132'n'#255#178#128'j'#255#174
+ +'|e'#255#168'v`'#255#158'mW'#255#146'bN'#255#133'YE'#255'yM;'#255'mC1'#255'g'
+ +'>+'#255'c9&'#255'`6"'#255'^3'#31#255']1'#30#255'\0'#28#248'\0'#28#173'[/'#27
+ +'O[/'#27#5#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#20'[/'#27'V\0'#28#153
+ +'\0'#28#220'\1'#29#255']1'#30#255'^3'#31#255'`5!'#255'a7$'#255'c9&'#255'e;('
+ +#255'f=*'#255'g>,'#255'i@.'#255'jB0'#255'mE2'#255'qH5'#255'tJ7'#255'qG5'#255
+ +'lC1'#255'jA0'#255'h?-'#255'g>+'#255'e<)'#255'd:('#255'c9&'#255'a6#'#255'`5!'
+ +#255'^2'#31#255']1'#30#255'\1'#29#252'\0'#28#201'[/'#27#134'[/'#27'C[/'#27#8
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0'[/'#27#31'[/'#27'_[/'#27#138'\0'#28#176'\0'#28#213'\0'#28
+ +#248'\1'#29#255'\1'#29#255'\1'#29#255']1'#30#255'^2'#31#255'^2'#31#255'^3'#31
+ +#255'^3'#31#255'^3'#31#255'^2'#31#255']1'#30#255']1'#30#255'\1'#29#255'\1'#29
+ +#255'\1'#29#255'\0'#28#241'\0'#28#203'\0'#28#165'[/'#27#127'[/'#27'N[/'#27#15
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0'[/'#27#2'[/'#27'![/'#27'E[/'#27'U[/'#27'a[/'#27'm[/'#27'y[/'#27
+ +#134'\0'#29#141'[/'#27#130'[/'#27'v[/'#27'j[/'#27'^[/'#27'Q[/'#27'=[/'#27#23
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ ,#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#255#255#255#255#255#255#255#128#0#255#255
+ +#255#255#255#255#255#255#255#255#255#255#255#224#0#0#3#255#255#255#255#255
+ +#255#255#255#255#255#255#254#0#0#0#0'?'#255#255#255#255#255#255#255#255#255
+ +#255#240#0#0#0#0#7#255#255#255#255#255#255#255#255#255#255#128#0#0#0#0#0#255
+ +#255#255#255#255#255#255#255#255#254#0#0#0#0#0#0'?'#255#255#255#255#255#255
+ +#255#255#248#0#0#0#0#0#0#15#255#255#255#255#255#255#255#255#224#0#0#0#0#0#0#3
+ +#255#255#255#255#255#255#255#255#128#0#0#0#0#0#0#0#255#255#255#255#255#255
+ +#255#254#0#0#0#0#0#0#0#0'?'#255#255#255#255#255#255#252#0#0#0#0#0#0#0#0#31
+ +#255#255#255#255#255#255#240#0#0#0#0#0#0#0#0#7#255#255#255#255#255#255#224#0
+ +#0#0#0#0#0#0#0#3#255#255#255#255#255#255#128#0#0#0#0#0#0#0#0#1#255#255#255
+ +#255#255#255#0#0#0#0#0#0#0#0#0#0#127#255#255#255#255#254#0#0#0#0#0#0#0#0#0#0
+ +'?'#255#255#255#255#252#0#0#0#0#0#0#0#0#0#0#31#255#255#255#255#248#0#0#0#0#0
+ +#0#0#0#0#0#15#255#255#255#255#240#0#0#0#0#0#0#0#0#0#0#7#255#255#255#255#224#0
+ +#0#0#0#0#0#0#0#0#0#3#255#255#255#255#192#0#0#0#0#0#0#0#0#0#0#1#255#255#255
+ +#255#128#0#0#0#0#0#0#0#0#0#0#0#255#255#255#255#0#0#0#0#0#0#0#0#0#0#0#0#127
+ +#255#255#254#0#0#0#0#0#0#0#0#0#0#0#0#127#255#255#254#0#0#0#0#0#0#0#0#0#0#0#0
+ +'?'#255#255#252#0#0#0#0#0#0#0#0#0#0#0#0#31#255#255#248#0#0#0#0#0#0#0#0#0#0#0
+ +#0#15#255#255#240#0#0#0#0#0#0#0#0#0#0#0#0#7#255#255#240#0#0#0#0#0#0#0#0#0#0#0
+ +#0#7#255#255#224#0#0#0#0#0#0#0#0#0#0#0#0#3#255#255#192#0#0#0#0#0#0#0#0#0#0#0
+ +#0#3#255#255#192#0#0#0#0#0#0#0#0#0#0#0#0#1#255#255#128#0#0#0#0#0#0#0#0#0#0#0
+ +#0#1#255#255#128#0#0#0#0#0#0#0#0#0#0#0#0#0#255#255#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#255#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#127#254#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#127#254#0#0#0#0#0#0#0#0#0#0#0#0#0#0'?'#254#0#0#0#0#0#0#0#0#0#0#0#0#0#0'?'
+ +#252#0#0#0#0#0#0#0#0#0#0#0#0#0#0'?'#252#0#0#0#0#0#0#0#0#0#0#0#0#0#0#31#252#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#31#248#0#0#0#0#0#0#0#0#0#0#0#0#0#0#15#248#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#15#248#0#0#0#0#0#0#0#0#0#0#0#0#0#0#15#240#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#7#240#0#0#0#0#0#0#0#0#0#0#0#0#0#0#7#240#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#7#224#0#0#0#0#0#0#0#0#0#0#0#0#0#0#7#224#0#0#0#0#0#0#0#0#0#0#0#0#0#0#3
+ +#224#0#0#0#0#0#0#0#0#0#0#0#0#0#0#3#224#0#0#0#0#0#0#0#0#0#0#0#0#0#0#3#224#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#3#224#0#0#0#0#0#0#0#0#0#0#0#0#0#0#3#192#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#3#192#0#0#0#0#0#0#0#0#0#0#0#0#0#0#3#192#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#1#192#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1#192#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#1#192#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1#192#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1#192#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#1#192#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1#192#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#1#192#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1#192#0#0#0#0#0#0#0#0#0
+ ,#0#0#0#0#0#1#192#0#0#0#0#0#0#0#0#0#0#0#0#0#0#3#192#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#3#224#0#0#0#0#0#0#0#0#0#0#0#0#0#0#3#224#0#0#0#0#0#0#0#0#0#0#0#0#0#0#3#224
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#3#224#0#0#0#0#0#0#0#0#0#0#0#0#0#0#3#224#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#3#240#0#0#0#0#0#0#0#0#0#0#0#0#0#0#7#240#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#7#240#0#0#0#0#0#0#0#0#0#0#0#0#0#0#7#240#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#15#248#0#0#0#0#0#0#0#0#0#0#0#0#0#0#15#248#0#0#0#0#0#0#0#0#0#0#0#0#0#0#15
+ +#248#0#0#0#0#0#0#0#0#0#0#0#0#0#0#15#252#0#0#0#0#0#0#0#0#0#0#0#0#0#0#31#252#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#31#252#0#0#0#0#0#0#0#0#0#0#0#0#0#0'?'#254#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0'?'#254#0#0#0#0#0#0#0#0#0#0#0#0#0#0'?'#254#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#127#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#127#255#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#255#255#128#0#0#0#0#0#0#0#0#0#0#0#0#0#255#255#128#0#0#0#0#0#0#0#0
+ +#0#0#0#0#1#255#255#128#0#0#0#0#0#0#0#0#0#0#0#0#1#255#255#192#0#0#0#0#0#0#0#0
+ +#0#0#0#0#3#255#255#192#0#0#0#0#0#0#0#0#0#0#0#0#3#255#255#224#0#0#0#0#0#0#0#0
+ +#0#0#0#0#7#255#255#224#0#0#0#0#0#0#0#0#0#0#0#0#15#255#255#240#0#0#0#0#0#0#0#0
+ +#0#0#0#0#15#255#255#248#0#0#0#0#0#0#0#0#0#0#0#0#31#255#255#248#0#0#0#0#0#0#0
+ +#0#0#0#0#0'?'#255#255#252#0#0#0#0#0#0#0#0#0#0#0#0#127#255#255#252#0#0#0#0#0#0
+ +#0#0#0#0#0#0#255#255#255#254#0#0#0#0#0#0#0#0#0#0#0#0#255#255#255#255#0#0#0#0
+ +#0#0#0#0#0#0#0#1#255#255#255#255#128#0#0#0#0#0#0#0#0#0#0#3#255#255#255#255
+ +#128#0#0#0#0#0#0#0#0#0#0#7#255#255#255#255#192#0#0#0#0#0#0#0#0#0#0#15#255#255
+ +#255#255#224#0#0#0#0#0#0#0#0#0#0#31#255#255#255#255#240#0#0#0#0#0#0#0#0#0#0
+ +#31#255#255#255#255#248#0#0#0#0#0#0#0#0#0#0'?'#255#255#255#255#252#0#0#0#0#0
+ +#0#0#0#0#0#127#255#255#255#255#254#0#0#0#0#0#0#0#0#0#1#255#255#255#255#255
+ +#255#0#0#0#0#0#0#0#0#0#3#255#255#255#255#255#255#128#0#0#0#0#0#0#0#0#7#255
+ +#255#255#255#255#255#224#0#0#0#0#0#0#0#0#15#255#255#255#255#255#255#240#0#0#0
+ +#0#0#0#0#0#31#255#255#255#255#255#255#248#0#0#0#0#0#0#0#0#127#255#255#255#255
+ +#255#255#254#0#0#0#0#0#0#0#0#255#255#255#255#255#255#255#255#128#0#0#0#0#0#0
+ +#3#255#255#255#255#255#255#255#255#192#0#0#0#0#0#0#7#255#255#255#255#255#255
+ +#255#255#240#0#0#0#0#0#0#31#255#255#255#255#255#255#255#255#252#0#0#0#0#0#0
+ +#127#255#255#255#255#255#255#255#255#255#0#0#0#0#0#3#255#255#255#255#255#255
+ +#255#255#255#255#224#0#0#0#0#15#255#255#255#255#255#255#255#255#255#255#252#0
+ +#0#0#0#127#255#255#255#255#255#255#255#255#255#255#255#192#0#0#7#255#255#255
+ +#255#255#255#255#255#255#255#255#255#254#0#1#255#255#255#255#255#255#255#255
+ +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
+ +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
+ +#255#255#255#255#255#255#255#255#255'('#0#0#0'@'#0#0#0#128#0#0#0#1#0' '#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'@@@'#4'III'#7'III'#7
+ +'333'#5#128#128#128#2#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'UUU'#6'DDD'
+ +#15'FFF'#22'EEE'#26'DDD'#30'III#GGG/DDD'#30#255'j>'#31#253'g>#'#249'[>+'#235'PB8'#218'HE'
+ +'C'#203'FEC'#195'EED'#184'DDD'#166'DDDqEEE4@@@'#20'@@@'#4#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1
+ +'999'#9'BBB'#31'CCCPEDD'#143'FFE'#182'NB:'#211'Z?-'#231'g>#'#249'l?'#31#255
+ +'zK$'#253#150']*'#255#165'h.'#255#172'm0'#255#180's2'#255#186'x4'#255#189'{4'
+ +#255#192#127'5'#255#190'|4'#255#187'x4'#255#182'u3'#255#175'p1'#255#167'j/'
+ +#255#156'b+'#255#131'R&'#254'oB '#255'i>!'#253'_>)'#238'S@6'#222'FEB'#203'DD'
+ +'C'#190'DDD'#164'CCCkCCC.PPP'#16'UUU'#3#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#128#128#128#2'CCC'#19'BBBBDDD'#136'EED'#179'LA9'
+ +#209'`=&'#243'k?'#31#255#127'N&'#254#154'`,'#255#176'q1'#255#191'~5'#255#200
+ +#138'7'#255#207#145'8'#255#210#149'9'#255#213#153'9'#255#217#157':'#255#219
+ +#160';'#255#221#162';'#255#220#162':'#255#217#158':'#255#215#155':'#255#211
+ +#151'9'#255#208#146'8'#255#203#141'8'#255#194#129'6'#255#183'v4'#255#163'f.'
+ +#255#137'U('#254'qC"'#254'f'
+ +'>>!+++'#6#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'@@@'#4'BBB'#27'CC'
+ +'C[CCB'#165'LD='#203']<('#238'j> '#255#135'R('#254#176'p3'#255#193#128'7'#255
+ +#202#139'9'#255#211#151';'#255#220#162'<'#255#227#170'>'#255#232#176'?'#255
+ +#234#180'?'#255#237#182'?'#255#239#185'@'#255#241#187'@'#255#242#188'A'#255
+ +#241#187'@'#255#240#185'A'#255#238#183'@'#255#235#180'@'#255#233#178'?'#255
+ +#229#173'>'#255#222#165'='#255#215#156'<'#255#205#144':'#255#196#133'8'#255
+ +#185'x5'#255#152'^-'#255'oC"'#254'd<#'#247'QA7'#220'FFE'#200'CCC'#180'CCC}AA'
+ +'A/UUU'#9#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'III'#7'CCC&DDDpECC'#180'X<,'#232'i='
+ +'!'#254#128'O('#254#170'l3'#255#194#130':'#255#210#150'>'#255#220#163'?'#255
+ +#227#171'A'#255#234#180'B'#255#240#187'D'#255#242#190'D'#255#244#193'E'#255
+ +#246#194'D'#255#247#195'E'#255#248#197'E'#255#249#197'E'#255#249#198'E'#255
+ +#249#197'E'#255#248#196'E'#255#247#195'E'#255#246#195'E'#255#245#194'D'#255
+ +#243#191'D'#255#240#188'C'#255#236#183'C'#255#230#174'B'#255#223#165'@'#255
+ +#215#156'?'#255#200#137';'#255#182'u6'#255#146'[,'#255'm@!'#254'`:%'#244'KA;'
+ +#211'CCC'#189'CCC'#144'BBB>PPP'#16#128#128#128#2#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'999'#9'@@@4CCC'#133
+ +'HD@'#192'_9$'#244'rE%'#254#164'h3'#255#191#127';'#255#206#146'?'#255#219#163
+ +'C'#255#232#178'F'#255#238#185'G'#255#241#189'H'#255#244#193'H'#255#246#195
+ +'I'#255#247#196'I'#255#247#197'J'#255#247#197'I'#255#247#198'I'#255#248#198
+ +'I'#255#248#198'I'#255#248#197'I'#255#248#198'I'#255#248#198'I'#255#248#198
+ +'I'#255#247#197'I'#255#247#197'I'#255#247#196'I'#255#246#196'I'#255#245#194
+ +'H'#255#242#190'H'#255#239#187'H'#255#235#182'G'#255#224#168'D'#255#211#153
+ +'A'#255#196#134'='#255#177'q7'#255#133'Q)'#254'e: '#253'N?7'#218'DDC'#195'CC'
+ +'C'#160'FFFP@@@'#20#0#0#0#2#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0'III'#7'FFF3CCC'#145'LB;'#204'd:"'#250'|L('#254#180's9'#255
+ +#202#143'A'#255#216#159'F'#255#228#174'I'#255#236#184'K'#255#241#191'L'#255
+ +#243#193'M'#255#244#194'M'#255#244#195'M'#255#245#196'M'#255#245#195'M'#255
+ +#245#195'M'#255#245#195'M'#255#245#195'M'#255#245#195'M'#255#245#195'M'#255
+ +#245#195'M'#255#245#195'M'#255#245#195'M'#255#245#195'M'#255#245#195'M'#255
+ +#245#195'M'#255#245#195'M'#255#245#196'M'#255#245#195'M'#255#244#194'M'#255
+ +#243#194'M'#255#242#192'M'#255#238#186'L'#255#232#179'J'#255#220#165'F'#255
+ +#208#150'C'#255#190#127'<'#255#147'[.'#255'h< '#255'S=1'#228'EED'#199'DDD'
+ +#168'BBBUGGG'#18#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +'@@@'#4'FFF(EEE'#134'P?5'#212'e:!'#254#137'U,'#254#186'z='#255#208#150'E'#255
+ +#224#171'L'#255#233#181'O'#255#238#187'P'#255#240#191'P'#255#242#192'Q'#255
+ +#242#193'Q'#255#242#193'Q'#255#242#193'P'#255#242#193'Q'#255#242#193'Q'#255
+ +#242#193'Q'#255#242#193'Q'#255#242#193'Q'#255#242#193'Q'#255#242#193'Q'#255
+ ,#242#193'Q'#255#242#193'Q'#255#242#193'Q'#255#242#193'Q'#255#242#193'Q'#255
+ +#242#193'Q'#255#242#193'Q'#255#242#193'Q'#255#242#193'Q'#255#242#193'Q'#255
+ +#242#193'Q'#255#242#193'Q'#255#241#192'Q'#255#239#189'P'#255#234#184'O'#255
+ +#228#175'M'#255#215#159'I'#255#194#132'@'#255#160'd3'#255'k?"'#254'X:*'#236
+ +'FDC'#201'CCC'#164'AAAG;;;'#13#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'U'
+ +'UU'#3'BBB'#31'CCCvO=3'#211'f:'#31#255#150']2'#255#190#128'A'#255#211#155'I'
+ +#255#226#175'Q'#255#234#185'S'#255#237#188'T'#255#238#190'T'#255#239#191'U'
+ +#255#239#191'U'#255#239#191'U'#255#239#191'U'#255#239#191'U'#255#239#191'U'
+ +#255#239#191'U'#255#239#191'U'#255#235#189'S'#255'|d,'#255'N>'#28#255'4*'#19
+ +#255'=1'#22#255'WE'#31#255'w_*'#255#173#139'='#255#239#191'U'#255#239#191'U'
+ +#255#239#191'U'#255#239#191'U'#255#239#191'U'#255#239#191'U'#255#239#191'U'
+ +#255#239#191'U'#255#239#191'U'#255#239#190'T'#255#238#189'U'#255#236#187'S'
+ +#255#230#179'R'#255#217#162'L'#255#198#138'D'#255#170'l8'#255'pC$'#254'Z8'''
+ +#240'DBB'#197'CCC'#153'FFF:@@@'#8#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#2'FFF'#22
+ +'BBBeJ?9'#195'b8 '#254#150']2'#255#194#133'E'#255#213#158'N'#255#226#176'T'
+ +#255#233#185'W'#255#236#187'W'#255#236#188'X'#255#236#188'X'#255#236#188'X'
+ +#255#236#188'X'#255#236#188'X'#255#236#188'X'#255#236#188'X'#255#236#188'X'
+ +#255#236#188'X'#255'cO%'#255#4#3#1#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#1#1#0#255#18#14#7#255'A4'#24#255#134'k2'
+ +#255#218#174'R'#255#236#188'X'#255#236#188'X'#255#236#188'X'#255#236#188'X'
+ +#255#236#188'X'#255#236#188'X'#255#236#187'W'#255#234#186'W'#255#229#180'U'
+ +#255#218#165'P'#255#201#143'H'#255#173'o<'#255'k>#'#254'S;-'#231'CCC'#193'CC'
+ +'C'#141'DDD-fff'#5#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'@@@'#12'DDDKFA='#179'`7 '#251#137'S-'
+ +#255#192#131'E'#255#214#161'Q'#255#226#176'W'#255#231#183'Y'#255#233#185'['
+ +#255#233#186'['#255#234#185'Z'#255#234#185'Z'#255#234#185'Z'#255#234#185'Z'
+ +#255#234#185'Z'#255#234#185'Z'#255#234#185'Z'#255#234#185'Z'#255'L<'#29#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#8#7#3#255'P'
+ +'?'#31#255#203#161'N'#255#234#185'Z'#255#234#185'Z'#255#234#185'Z'#255#234
+ +#185'Z'#255#233#186'['#255#232#183'Z'#255#228#178'Y'#255#219#167'T'#255#201
+ +#143'K'#255#163'g8'#255'f: '#255'O=4'#222'DDD'#188'CCCzBBB'#27#0#0#0#1#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'U'
+ +'UU'#3'GGG$D@@'#147'\6#'#245'{I*'#254#185'{C'#255#211#157'R'#255#225#175'Z'
+ +#255#229#181'\'#255#230#183']'#255#230#183']'#255#230#183']'#255#230#183']'
+ +#255#230#183']'#255#230#183']'#255#230#183']'#255#230#183']'#255#230#183']'
+ +#255#230#183']'#255#138'm8'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#24#20#10#255'x_0'
+ +#255#226#181'['#255#230#183']'#255#230#183']'#255#230#183']'#255#230#181'\'
+ +#255#227#177'['#255#217#165'V'#255#196#136'J'#255#151']4'#255'b8 '#254'K@9'
+ +#214'CCC'#175'AAAJ...'#11#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0'@@@'#16'CCC\V6'''#228'nA&'#254#178'tA'#255#205
+ +#151'R'#255#221#172'\'#255#226#179'_'#255#228#180'_'#255#228#180'_'#255#228
+ +#180'_'#255#228#180'_'#255#228#180'_'#255#228#180'_'#255#228#180'_'#255#228
+ +#180'_'#255#228#180'_'#255#228#180'_'#255#228#180'_'#255#17#13#7#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#2#1#1#255'H9'#30#255#224#178']'
+ +#255#228#180'_'#255#228#180'_'#255#227#179'^'#255#224#175']'#255#213#160'W'
+ +#255#190#129'H'#255#137'T/'#255'^4 '#252'FB?'#201'CCC'#140'DDD"'#0#0#0#3#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'@@@'#4'FFF,J=7'
+ +#175'`4'#30#255#165'g;'#255#200#144'Q'#255#217#166'\'#255#223#176'`'#255#225
+ +#177'`'#255#225#177'a'#255#225#177'a'#255#225#177'a'#255#225#177'a'#255#225
+ +#177'a'#255#225#177'a'#255#225#177'a'#255#225#177'a'#255#225#177'a'#255#225
+ +#177'a'#255#218#171'^'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#11#9#5#255#196#154'U'#255#225#177'a'#255#225#177
+ +'`'#255#224#177'a'#255#220#171'^'#255#208#154'W'#255#184'{F'#255'nA%'#254'T8'
+ +'*'#233'DDD'#180'CCCX333'#15#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0'CCC'#19'CCCjY5#'#239'~J,'#254#191#132'M'#255#213#162']'#255
+ ,#220#171'a'#255#221#173'c'#255#222#174'b'#255#222#174'b'#255#222#174'b'#255
+ +#222#174'b'#255#222#174'b'#255#222#174'b'#255#222#174'b'#255#222#174'b'#255
+ +#222#174'b'#255#222#174'b'#255#222#174'b'#255#154'yC'#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#15#11#6
+ +#255#218#172'`'#255#222#174'b'#255#222#174'b'#255#221#173'b'#255#217#167'_'
+ +#255#202#146'T'#255#156'a9'#255'^4'#30#254'G@='#206'DDD'#151'>>>)@@@'#4#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'UUU'#3'AAA+L;4'#188'b6 '#254#170
+ +'l@'#255#206#152'Z'#255#217#168'b'#255#219#171'd'#255#219#171'd'#255#219#171
+ +'d'#255#219#171'd'#255#219#171'd'#255#219#171'd'#255#219#171'd'#255#219#171
+ +'d'#255#219#171'd'#255#219#171'd'#255#219#171'd'#255#219#171'd'#255#219#171
+ +'d'#255#219#171'd'#255#26#20#12#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'oW3'#255#219#171'd'#255#219
+ +#171'd'#255#219#171'd'#255#218#169'c'#255#212#161'_'#255#187#127'L'#255'uD)'
+ +#254'W6('#238'CCC'#182'CCC[III'#14#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0'@@@'#12'EBBS[3'#31#244#134'O/'#255#192#134'Q'#255#212#162'b'#255#215
+ +#167'd'#255#216#168'd'#255#216#168'd'#255#216#168'd'#255#216#168'd'#255#216
+ +#168'd'#255#216#168'd'#255#216#168'd'#255#216#168'd'#255#216#168'd'#255#216
+ +#168'd'#255#216#168'd'#255#216#168'd'#255#216#168'd'#255#216#168'd'#255#198
+ +#154'\'#255#5#4#2#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255'!'#25#15#255#216#168'd'#255#216#168'd'#255#216#168
+ +'d'#255#216#168'd'#255#214#166'd'#255#202#147'Y'#255#161'e='#255'^2'#29#255
+ +'J?:'#208'CCC'#137'EEE'#26#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'C'
+ +'CC'#23'O9/'#171'`3'#31#254#174'pD'#255#203#150']'#255#212#163'e'#255#213#164
+ +'e'#255#213#164'e'#255#213#164'e'#255#213#164'e'#255#213#164'e'#255#213#164
+ +'e'#255#213#164'e'#255#213#164'e'#255#213#164'e'#255#213#164'e'#255#213#164
+ +'e'#255#213#164'e'#255#213#164'e'#255#213#164'e'#255#213#164'e'#255#213#164
+ +'e'#255#173#133'R'#255#3#2#1#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#22#17#11#255#213#164'e'#255#213#164'e'#255#213#164
+ +'e'#255#213#164'e'#255#213#164'f'#255#209#158'a'#255#187#128'O'#255'yD)'#254
+ +'W4$'#241'BBB'#169'DDD1@@@'#4#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#2'FFF(W4'
+ +'$'#229'{E)'#255#191#134'T'#255#207#157'c'#255#210#160'f'#255#210#160'f'#255
+ +#210#160'f'#255#210#160'f'#255#210#160'f'#255#210#160'f'#255#210#160'f'#255
+ +#210#160'f'#255#152'tJ'#255'[E,'#255'K9$'#255'{]<'#255#196#149'_'#255#210#160
+ +'f'#255#210#160'f'#255#210#160'f'#255#210#160'f'#255#210#160'f'#255#159'yM'
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'"'
+ +#26#17#255#210#160'f'#255#210#160'f'#255#210#160'f'#255#210#160'f'#255#210
+ +#160'f'#255#209#160'e'#255#199#146']'#255#156'_;'#255'\1'#28#254'FBA'#188'FF'
+ +'FXNNN'#13#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'FFF'#11'F@=T\/'#28#253#151'\9'#255
+ +#200#147'_'#255#207#156'e'#255#207#156'e'#255#207#156'e'#255#207#156'e'#255
+ +#207#156'e'#255#207#156'e'#255#207#156'e'#255#178#135'W'#255'$'#27#17#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'N:&'#255#207#156'e'#255#207
+ +#156'e'#255#207#156'e'#255#207#156'e'#255#207#156'e'#255#3#2#1#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'uX9'#255#207#156'e'#255#207
+ +#156'e'#255#207#156'e'#255#207#156'e'#255#207#156'e'#255#207#157'e'#255#204
+ +#153'b'#255#180'wK'#255'a4'#30#254'M;3'#216'DDD'#132'==='#25#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0'CCC'#19'N9.'#159'^2'#30#254#176'rI'#255#202#150'c'#255#203
+ +#153'e'#255#203#153'f'#255#203#153'f'#255#203#153'f'#255#203#153'f'#255#203
+ +#153'f'#255#163'zQ'#255#1#1#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#29#22#15#255#203#153'f'#255#203#153'f'#255#203#153
+ +'f'#255#203#153'f'#255#14#10#7#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ ,#0#0#255#4#3#2#255#203#153'f'#255#203#153'f'#255#203#153'f'#255#203#153'f'
+ +#255#203#153'f'#255#203#153'f'#255#203#153'f'#255#203#152'e'#255#190#134'X'
+ +#255'yC)'#254'V5&'#239'DDD'#165'FFF('#128#128#128#2#0#0#0#0#0#0#0#0#0#0#0#0
+ +'GGG'#25'V4%'#212's@&'#254#186#128'U'#255#199#148'd'#255#200#148'd'#255#200
+ +#148'd'#255#200#148'd'#255#200#148'd'#255#200#148'd'#255#198#146'd'#255#12#9
+ +#6#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#138'fE'#255#200#148'd'#255#200#148'd'#255#200#148'd'#255
+ +#15#11#7#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1#0#0#255'&'#28#19#255#145'kH'#255
+ +#200#148'd'#255#200#148'd'#255#200#148'd'#255#200#148'd'#255#200#148'd'#255
+ +#200#148'd'#255#200#148'd'#255#200#148'd'#255#194#141'^'#255#146'W6'#255'[0'
+ +#28#254'EBB'#178'CCC9UUU'#6#0#0#0#0#0#0#0#0#0#0#0#0'JAA'#31'\1'#29#249#140'P'
+ +'2'#255#190#135'\'#255#196#143'c'#255#196#143'c'#255#196#143'c'#255#196#143
+ +'c'#255#196#143'c'#255#196#143'c'#255'>-'#31#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'&'
+ +#28#19#255#196#143'c'#255#196#143'c'#255#196#143'c'#255#25#18#12#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#2#2#1
+ +#255'*'#31#21#255'kM6'#255#187#137'_'#255#196#143'c'#255#196#143'c'#255#196
+ +#143'c'#255#196#143'c'#255#196#143'c'#255#196#143'c'#255#196#143'c'#255#196
+ +#143'c'#255#196#143'c'#255#196#143'c'#255#194#141'b'#255#170'kF'#255'\0'#28
+ +#254'L<5'#203'CCCH333'#10#0#0#0#0#0#0#0#0#0#0#0#1'K3+@[/'#27#255#160'`>'#255
+ +#190#136'_'#255#191#137'`'#255#191#137'`'#255#191#137'`'#255#191#137'`'#255
+ +#191#137'`'#255#189#135'`'#255#1#1#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#30#21#15#255
+ +#191#137'`'#255#191#137'`'#255#191#137'`'#255'aF1'#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#5#3#2#255#165'vS'#255#191#137'`'
+ +#255#191#137'`'#255#191#137'`'#255#191#137'`'#255#191#137'`'#255#191#137'`'
+ +#255#191#137'`'#255#191#137'`'#255#191#137'`'#255#191#137'`'#255#191#137'`'
+ +#255#191#137'`'#255#191#137'`'#255#191#136'`'#255#178'vQ'#255'h7 '#253'Q8,'
+ +#220'DDDV;;;'#13#0#0#0#0#0#0#0#0'UUU'#3'R4''^[/'#27#255#169'hF'#255#187#131
+ +']'#255#187#132'^'#255#187#132'^'#255#187#132'^'#255#187#132'^'#255#187#132
+ +'^'#255'uS;'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'{W>'#255#187#132'^'#255
+ +#187#132'^'#255#187#132'^'#255#185#130'^'#255#19#14#10#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#1#1#1#255#158'oO'#255#187#132'^'#255#187#132'^'
+ +#255#187#132'^'#255#187#132'^'#255#187#132'^'#255#187#132'^'#255#187#132'^'
+ +#255#187#132'^'#255#187#132'^'#255#187#132'^'#255#187#132'^'#255#187#132'^'
+ +#255#187#132'^'#255#187#132'^'#255#187#132'^'#255#181'{V'#255'r<"'#255'T6'''
+ +#228'BBBd@@@'#16#0#0#0#0#0#0#0#0'UUU'#6'T5''}_2'#30#253#171'kI'#255#183'}Z'
+ +#255#183'~Z'#255#183'~Z'#255#183'~Z'#255#183'~Z'#255#183'~Z'#255'. '#23#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#1#1#0#255'S9)'#255#183'~Z'#255#183'~Z'#255#183'~Z'#255#183'~Z'
+ +#255#183'~Z'#255#173'xV'#255#31#21#15#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'b'
+ +'C0'#255#183'~Z'#255#183'~Z'#255#183'~Z'#255#183'~Z'#255#183'~Z'#255#183'~Z'
+ +#255#183'~Z'#255#183'~Z'#255#183'~Z'#255#183'~Z'#255#183'~Z'#255#183'~Z'#255
+ +#183'~Z'#255#183'~Z'#255#183'~Z'#255#183'~Z'#255#181'zV'#255'zA%'#255'X4$'
+ +#237'DDDqCCC'#19#0#0#0#0#0#0#0#0'@@@'#8'U4%'#149'f5'#31#252#172'mK'#255#180
+ +'yX'#255#180'yX'#255#180'yX'#255#180'yX'#255#180'yX'#255#180'yX'#255#6#4#3
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#19#13#9#255#153'gK'#255#180'yX'#255#180'yX'#255#180'yX'#255#180'yX'
+ +#255#180'yX'#255#180'yX'#255#180'yX'#255#180'yX'#255'{S<'#255'+'#29#21#255#7
+ +#4#3#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1#1#1
+ +#255'gF3'#255#180'yX'#255#180'yX'#255#180'yX'#255#139']D'#255'+'#29#21#255#8
+ +#6#4#255#8#6#4#255#16#11#8#255'W:*'#255#178'wV'#255#180'yX'#255#180'yX'#255
+ +#180'yX'#255#180'yX'#255#180'yX'#255#180'yX'#255#180'yX'#255#179'yV'#255#131
+ +'F+'#255'[3!'#245'CCCyIII'#21#0#0#0#0#0#0#0#0'UUU'#6'X3"'#165'n:"'#253#172'p'
+ +'O'#255#177'wW'#255#177'wW'#255#177'wW'#255#177'wW'#255#177'wW'#255#173'uU'
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1
+ +#0#0#255'P6'''#255#177'wW'#255#177'wW'#255#177'wW'#255#177'wW'#255#177'wW'
+ ,#255#177'wW'#255#177'wW'#255#177'wW'#255#177'wW'#255#177'wW'#255#177'wW'#255
+ +#177'wW'#255#177'wW'#255#158'jM'#255'W;+'#255''''#26#19#255'"'#23#17#255'%'
+ +#25#18#255'W:+'#255#167'qS'#255#177'wW'#255#177'wW'#255#177'wW'#255'@+'#31
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#3#2#1#255
+ +#149'dI'#255#177'wW'#255#177'wW'#255#177'wW'#255#177'wW'#255#177'wW'#255#177
+ +'wW'#255#177'vV'#255#139'M0'#255'[1'#30#250'DDDpCCC'#19#0#0#0#0#0#0#0#0'UUU'
+ +#3'Y1'#31#182'v>%'#255#172'oQ'#255#175'tW'#255#175'tW'#255#175'tW'#255#175't'
+ +'W'#255#175'tW'#255'}S?'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#26#17#13#255#150'cK'#255#175'tW'#255#175'tW'#255#175'tW'#255
+ +#175'tW'#255#175'tW'#255#175'tW'#255#175'tW'#255#175'tW'#255#175'tW'#255#175
+ +'tW'#255#175'tW'#255#175'tW'#255#175'tW'#255#175'tW'#255#175'tW'#255#175'tW'
+ +#255#175'tW'#255#175'tW'#255#175'tW'#255#175'tW'#255#175'tW'#255#175'tW'#255
+ +#175'tW'#255'dC2'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#9#6#4#255#169'pU'#255#175'tW'#255#175'tW'#255#175't'
+ +'W'#255#175'tW'#255#175'tW'#255#174'sU'#255#145'S6'#255']0'#28#254'DBBd@@@'
+ +#16#0#0#0#0#0#0#0#0#0#0#0#0'Z0'#30#175'v=%'#255#171'nP'#255#174'rV'#255#174
+ +'rV'#255#174'rV'#255#174'rV'#255#174'rV'#255'L2&'#255#0#0#0#255'/'#31#23#255
+ +'}R>'#255' '#21#16#255'!'#22#17#255#139'[E'#255#174'rV'#255#174'rV'#255#174
+ +'rV'#255#174'rV'#255#174'rV'#255#174'rV'#255#174'rV'#255#174'rV'#255#174'rV'
+ +#255#174'rV'#255#174'rV'#255#174'rV'#255#174'rV'#255#174'rV'#255#174'rV'#255
+ +#174'rV'#255#174'rV'#255#174'rV'#255#174'rV'#255#174'rV'#255#174'rV'#255#174
+ +'rV'#255#174'rV'#255#174'rV'#255#174'rV'#255'?*'#31#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'6#'#27
+ +#255#174'rV'#255#174'rV'#255#174'rV'#255#174'rV'#255#174'rV'#255#173'qT'#255
+ +#145'S7'#255'\1'#29#254'AAAV;;;'#13#0#0#0#0#0#0#0#0#0#0#0#0'Z1'#30#150'n;$'
+ +#252#169'jM'#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255
+ +#149'bI'#255'@* '#255#170'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'
+ +#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255
+ +#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#172
+ +'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'
+ +#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255
+ +'G/#'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#24#16#12#255#172'qU'#255#172'qU'#255#172'qU'#255#172
+ +'qU'#255#172'qU'#255#171'oS'#255#138'N3'#255'\2'#31#249'DDDG999'#9#0#0#0#0#0
+ +#0#0#0#0#0#0#0'X1!|g7#'#250#167'gI'#255#172'pT'#255#172'qU'#255#172'qU'#255
+ +#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#172
+ +'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'
+ +#255#172'qU'#255'P5('#255')'#27#20#255#27#18#13#255'5#'#26#255'pJ8'#255#172
+ +'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'
+ +#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255
+ +#172'qU'#255#172'qU'#255#162'jO'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#9#6#4#255#172'qU'#255#172
+ +'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#170'mR'#255#131'I.'#255'[4"'#241
+ +'FFF7UUU'#6#0#0#0#0#0#0#0#0#0#0#0#0'Y1!`b5 '#251#164'cG'#255#172'pU'#255#173
+ +'rW'#255#173'rW'#255#173'rW'#255#173'rW'#255#173'rW'#255#173'rW'#255#173'rW'
+ +#255#173'rW'#255#173'rW'#255#173'rW'#255#173'rW'#255#173'rW'#255#173'rW'#255
+ +#173'rW'#255'}S?'#255#9#6#5#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#16#11#8#255#152'dM'#255#173'rW'#255#173'rW'#255#173'rW'#255#173'rW'#255
+ +#173'rW'#255#173'rW'#255#173'rW'#255#173'rW'#255#173'rW'#255#173'rW'#255#173
+ +'rW'#255#173'rW'#255#173'rW'#255#173'rW'#255'$'#24#18#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#4#3#2#255#173'r'
+ +'W'#255#173'rW'#255#173'rW'#255#173'rW'#255#173'rW'#255#170'mQ'#255'|C*'#255
+ +'W4$'#229'CCC&'#0#0#0#2#0#0#0#0#0#0#0#0#0#0#0#0'X5!A^2'#31#254#162'bE'#255
+ +#173'rV'#255#175'tY'#255#175'tY'#255#175'tY'#255#175'tY'#255#175'tY'#255#175
+ +'tY'#255#175'tY'#255#175'tY'#255#175'tY'#255#175'tY'#255#175'tY'#255#175'tY'
+ +#255#175'tY'#255'{Q?'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#14#9#7#255#173'tY'#255#175'tY'#255#175'tY'#255
+ +#175'tY'#255#175'tY'#255#175'tY'#255#175'tY'#255#175'tY'#255#175'tY'#255#175
+ +'tY'#255#175'tY'#255#175'tY'#255#175'tY'#255#175'tY'#255#132'XC'#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#21
+ +#14#11#255#175'tY'#255#175'tY'#255#175'tY'#255#175'tY'#255#174'tY'#255#170'm'
+ +'P'#255't?('#254'U5&'#203'@@@'#24#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'X0'#24' ^2'
+ +#31#255#156'\A'#255#175'v\'#255#177'y`'#255#177'y`'#255#177'y`'#255#177'y`'
+ +#255#177'y`'#255#177'y`'#255#177'y`'#255#177'y`'#255#177'y`'#255#177'y`'#255
+ ,#177'y`'#255#177'y`'#255#177'y`'#255#11#8#6#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#136']J'#255#177
+ +'y`'#255#177'y`'#255'7%'#30#255#9#6#5#255#13#9#7#255#16#11#9#255#26#18#14#255
+ +#139'_K'#255#177'y`'#255#177'y`'#255#177'y`'#255#177'y`'#255#177'y`'#255#177
+ +'y`'#255#18#12#9#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255'<)!'#255#177'y`'#255#177'y`'#255#177'y`'#255#177'y`'#255#176
+ +'x^'#255#169'kP'#255'j<&'#253'U4%'#168';;;'#13#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0'^2'#29#234#136'O4'#255#176'x^'#255#180'~f'#255#180'~f'#255#180'~f'
+ +#255#180'~f'#255#180'~f'#255#180'~f'#255#180'~f'#255#180'~f'#255#180'~f'#255
+ +#180'~f'#255#180'~f'#255#180'~f'#255#146'gS'#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#139'bO'#255#170'x`'#255#20#14#11#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255']A4'#255#180'~f'#255#180'~f'#255#180'~f'#255#180'~f'#255
+ +#180'~f'#255'qO@'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#1#1#0#255#165't^'#255#180'~f'#255#180'~f'#255#180'~f'#255#180'~f'#255
+ +#178'zb'#255#162'dH'#255'_3'#31#254'R6)c@@@'#4#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0'[/'#29#153'r?)'#252#174'sZ'#255#182#129'j'#255#183#131'l'#255#183
+ +#131'l'#255#183#131'l'#255#183#131'l'#255#183#131'l'#255#183#131'l'#255#183
+ +#131'l'#255#183#131'l'#255#183#131'l'#255#183#131'l'#255#183#131'l'#255'ZA5'
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#5#3#3#255#179#127'j'#255'uTE'#255#0#0#0#255#0#0#0#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'{XI'#255#183#131'l'
+ +#255#183#131'l'#255#183#131'l'#255#183#131'l'#255#183#131'l'#255#20#15#12#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255':)"'#255#183#131'l'#255
+ +#183#131'l'#255#183#131'l'#255#183#131'l'#255#183#131'l'#255#179'|c'#255#140
+ +'R9'#255'\2'#31#248'@@6'#28#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +'[/'#29'E`5 '#252#166'iO'#255#183#131'l'#255#186#136'q'#255#186#136'q'#255
+ +#186#136'q'#255#186#136'q'#255#186#136'q'#255#186#136'q'#255#186#136'q'#255
+ +#186#136'q'#255#186#136'q'#255#186#136'q'#255#186#136'q'#255'\D8'#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255'oQC'#255#186#136'q'#255'X@6'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#12#9#7#255#186#136'q'#255#186
+ +#136'q'#255#186#136'q'#255#186#136'q'#255#186#136'q'#255#148'lZ'#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#169'|g'#255#186#136'q'#255#186
+ +#136'q'#255#186#136'q'#255#186#136'q'#255#185#134'q'#255#177'y`'#255'tB+'#254
+ +'W2!'#194'III'#14#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'@@'#0#4'^3'
+ +#30#245#144'W='#255#184#134'o'#255#189#141'x'#255#189#141'x'#255#189#141'x'
+ +#255#189#141'x'#255#189#141'x'#255#189#141'x'#255#189#141'x'#255#189#141'x'
+ +#255#189#141'x'#255#189#141'x'#255#189#141'x'#255'tWJ'#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'('#30#26#255
+ +#189#141'x'#255#189#141'x'#255'?/('#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#187#139'v'#255#189#141
+ +'x'#255#189#141'x'#255#189#141'x'#255#189#141'x'#255#189#141'x'#255#172#128
+ +'m'#255'_G<'#255#1#0#0#255#0#0#0#255'-"'#28#255#189#141'x'#255#189#141'x'#255
+ +#189#141'x'#255#189#141'x'#255#189#141'x'#255#186#137's'#255#171'oU'#255'a6"'
+ +#253'T5$jUUU'#3#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'\/'
+ +#27#170'vD,'#252#181#128'h'#255#190#144'{'#255#192#146'~'#255#192#146'~'#255
+ +#192#146'~'#255#192#146'~'#255#192#146'~'#255#192#146'~'#255#192#146'~'#255
+ +#192#146'~'#255#192#146'~'#255#192#146'~'#255#186#142'z'#255#1#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#2#1#1#255#186#142'z'
+ +#255#192#146'~'#255#192#146'~'#255'=.('#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#192#146'~'#255#192
+ +#146'~'#255#192#146'~'#255#192#146'~'#255#192#146'~'#255#192#146'~'#255#192
+ +#146'~'#255#192#146'~'#255#0#0#0#255#0#0#0#255#167#127'n'#255#192#146'~'#255
+ +#192#146'~'#255#192#146'~'#255#192#146'~'#255#191#145'}'#255#186#137's'#255
+ +#149'[A'#255'^1'#31#250'F:.'#22#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0'\.'#28'H`5 '#252#164'jP'#255#190#143'z'#255#194#151#131
+ +#255#194#151#131#255#194#151#131#255#194#151#131#255#194#151#131#255#194#151
+ +#131#255#194#151#131#255#194#151#131#255#194#151#131#255#194#151#131#255#194
+ +#151#131#255#27#21#18#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255' '#25#21#255#194#151#131#255#194#151#131#255#194#151#131#255'7*%'
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#12#9#8#255#194#151#131#255#194#151#131#255#194#151#131#255#194#151
+ +#131#255#194#151#131#255#194#151#131#255#194#151#131#255#190#149#129#255#0#0
+ ,#0#255'0% '#255#194#151#131#255#194#151#131#255#194#151#131#255#194#151#131
+ +#255#194#151#131#255#192#147#127#255#180'~f'#255'q@+'#252'Z0'#29#180#0#0#0#2
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0']0'
+ +#28#199'{H2'#252#184#134'o'#255#196#153#134#255#197#156#137#255#197#156#137
+ +#255#197#156#137#255#197#156#137#255#197#156#137#255#197#156#137#255#197#156
+ +#137#255#197#156#137#255#197#156#137#255#197#156#137#255'G81'#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'WE='#255#197#156#137#255#197
+ +#156#137#255#191#152#133#255#1#1#1#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#135'k^'#255#197#156#137#255#197
+ +#156#137#255#197#156#137#255#197#156#137#255#197#156#137#255#197#156#137#255
+ +#197#156#137#255#197#156#137#255#16#12#11#255#174#138'y'#255#197#156#137#255
+ +#197#156#137#255#197#156#137#255#197#156#137#255#197#155#136#255#191#145'|'
+ +#255#151'_F'#255'^3'#31#253'T2!-'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[0'#29'5_4 '#254#161'hP'#255#195#152#132
+ +#255#200#161#143#255#200#161#144#255#200#161#144#255#200#161#144#255#200#161
+ +#144#255#200#161#144#255#200#161#144#255#200#161#144#255#200#161#144#255#200
+ +#161#144#255'xaW'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1#1#1
+ +#255#171#138'{'#255#200#161#144#255#200#161#144#255#127'f\'#255#0#0#0#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255')!'#30#255
+ +#200#161#144#255#200#161#144#255#200#161#144#255#200#161#144#255#200#161#144
+ +#255#200#161#144#255#200#161#144#255#200#161#144#255#200#161#144#255#153'{n'
+ +#255#200#161#144#255#200#161#144#255#200#161#144#255#200#161#144#255#200#161
+ +#144#255#198#156#138#255#181#128'h'#255'l>*'#252'Z1'#30#159#0#0#0#1#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0'^0'#27#173'uE/'#249#186#136'r'#255#201#162#145#255#203#165#150#255#203#165
+ +#150#255#203#165#150#255#203#165#150#255#203#165#150#255#203#165#150#255#203
+ +#165#150#255#203#165#150#255#203#165#150#255#163#132'x'#255#0#0#0#255#0#0#0
+ +#255#26#21#19#255',$!'#255'-%!'#255#156'~s'#255#203#165#150#255#203#165#150
+ +#255#203#165#150#255'@4/'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#4#3#3#255#186#151#138#255#203#165#150#255#203#165
+ +#150#255#203#165#150#255#203#165#150#255#203#165#150#255#203#165#150#255#203
+ +#165#150#255#203#165#150#255#203#165#150#255#203#165#150#255#203#165#150#255
+ +#203#165#150#255#203#165#150#255#203#165#150#255#203#164#149#255#195#152#132
+ +#255#146'\D'#255'_3'#31#247'R3'#30#25#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'Z-'#30'"^4 '#252#155
+ +'cK'#255#196#153#136#255#206#169#155#255#207#171#156#255#207#171#156#255#207
+ +#171#156#255#207#171#156#255#207#171#156#255#207#171#156#255#207#171#156#255
+ +#207#171#156#255#203#167#152#255#0#0#0#255#0#0#0#255#193#159#145#255#207#171
+ +#156#255#207#171#156#255#207#171#156#255#207#171#156#255#207#171#156#255#207
+ +#171#156#255'E94'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#15#12#11#255#182#150#137#255#207#171#156#255#207#171#156#255#207#171#156
+ +#255#207#171#156#255#207#171#156#255#207#171#156#255#207#171#156#255#207#171
+ +#156#255#207#171#156#255#207#171#156#255#207#171#156#255#207#171#156#255#207
+ +#171#156#255#207#171#156#255#206#170#155#255#201#162#145#255#178'}f'#255'h<('
+ +#250'[0'#28#129#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0']1'#29#130'f:&'#250#171'u'
+ +'^'#255#202#164#148#255#210#176#163#255#210#177#164#255#210#177#164#255#210
+ +#177#164#255#210#177#164#255#210#177#164#255#210#177#164#255#210#177#164#255
+ +#210#177#164#255#2#1#1#255#27#22#21#255#210#177#164#255#210#177#164#255#210
+ +#177#164#255#210#177#164#255#210#177#164#255#210#177#164#255#210#177#164#255
+ +#210#177#164#255'I=8'#255#6#5#4#255#0#0#0#255#0#0#0#255#0#0#0#255'''!'#31#255
+ +#206#175#162#255#210#177#164#255#210#177#164#255#210#177#164#255#210#177#164
+ +#255#210#177#164#255#210#177#164#255#210#177#164#255#210#177#164#255#210#177
+ +#164#255#210#177#164#255#210#177#164#255#210#177#164#255#210#177#164#255#210
+ +#177#164#255#210#176#163#255#206#170#155#255#188#139'w'#255'zI4'#252'^2'#29
+ +#222']/'#23#11#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'^1'#29#181'oA-'
+ +#249#182#132'n'#255#208#173#159#255#213#182#169#255#213#183#170#255#213#183
+ +#170#255#213#183#170#255#213#183#170#255#213#183#170#255#213#183#170#255#213
+ +#183#170#255#12#10#9#255#159#136#127#255#213#183#170#255#213#183#170#255#213
+ +#183#170#255#213#183#170#255#213#183#170#255#213#183#170#255#213#183#170#255
+ +#213#183#170#255#213#183#170#255#139'xo'#255#0#0#0#255#0#0#0#255'% '#30#255
+ +#213#183#170#255#213#183#170#255#213#183#170#255#213#183#170#255#213#183#170
+ +#255#213#183#170#255#213#183#170#255#213#183#170#255#213#183#170#255#213#183
+ ,#170#255#213#183#170#255#213#183#170#255#213#183#170#255#213#183#170#255#213
+ +#183#170#255#213#183#170#255#211#178#165#255#196#152#134#255#136'T?'#254'`1 '
+ +#243'U+'#28'$'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'U+'#21#12
+ +']2'#30#218'zK5'#251#192#146#127#255#212#180#168#255#216#187#176#255#217#188
+ +#177#255#217#188#177#255#217#188#177#255#217#188#177#255#217#188#177#255#217
+ +#188#177#255'o`Z'#255#217#188#177#255#217#188#177#255#217#188#177#255#217#188
+ +#177#255#217#188#177#255#217#188#177#255#217#188#177#255#217#188#177#255#217
+ +#188#177#255#217#188#177#255#27#24#22#255#0#0#0#255#9#8#7#255#209#180#171#255
+ +#217#188#177#255#217#188#177#255#217#188#177#255#217#188#177#255#217#188#177
+ +#255#217#188#177#255#217#188#177#255#217#188#177#255#217#188#177#255#217#188
+ +#177#255#217#188#177#255#217#188#177#255#217#188#177#255#217#188#177#255#217
+ +#188#177#255#215#185#173#255#202#163#147#255#152'cM'#255'`5 '#252'X.'#27'B'#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'].'#23'!_'
+ +'3 '#241#135'V@'#254#197#155#137#255#215#185#173#255#219#193#183#255#220#194
+ +#184#255#220#194#184#255#220#194#184#255#220#194#184#255#220#194#184#255#220
+ +#194#184#255#220#194#184#255#220#194#184#255#220#194#184#255#220#194#184#255
+ +#220#194#184#255#220#194#184#255#220#194#184#255#220#194#184#255#220#194#184
+ +#255#220#194#184#255#4#4#4#255#13#11#11#255#197#173#164#255#220#194#184#255
+ +#220#194#184#255#220#194#184#255#220#194#184#255#220#194#184#255#220#194#184
+ +#255#220#194#184#255#220#194#184#255#220#194#184#255#220#194#184#255#220#194
+ +#184#255#220#194#184#255#220#194#184#255#220#194#184#255#220#194#183#255#218
+ +#190#179#255#205#169#154#255#165'pY'#255'b8$'#252'[/'#27'h'#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'Y1'#28'?_'
+ +'3!'#249#132'T?'#252#193#148#130#255#215#186#174#255#223#198#189#255#223#200
+ +#191#255#223#200#191#255#223#200#191#255#223#200#191#255#223#200#191#255#223
+ +#200#191#255#223#200#191#255#223#200#191#255#223#200#191#255#223#200#191#255
+ +#223#200#191#255#223#200#191#255#223#200#191#255#223#200#191#255#223#200#191
+ +#255#199#179#171#255#215#192#183#255#223#200#191#255#223#200#191#255#223#200
+ +#191#255#223#200#191#255#223#200#191#255#223#200#191#255#223#200#191#255#223
+ +#200#191#255#223#200#191#255#223#200#191#255#223#200#191#255#223#200#191#255
+ +#223#200#191#255#223#200#191#255#223#199#190#255#219#192#183#255#203#165#150
+ +#255#158'kS'#255'c9%'#251']0'#30#147#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'Z-'#25'3_3'#30
+ +#234'wI5'#250#185#138'v'#255#215#186#174#255#225#203#194#255#227#205#197#255
+ +#227#205#197#255#227#205#197#255#227#205#197#255#227#205#197#255#227#205#197
+ +#255#227#205#197#255#227#205#197#255#227#205#197#255#227#205#197#255#227#205
+ +#197#255#227#205#197#255#227#205#197#255#227#205#197#255#227#205#197#255#227
+ +#205#197#255#227#205#197#255#227#205#197#255#227#205#197#255#227#205#197#255
+ +#227#205#197#255#227#205#197#255#227#205#197#255#227#205#197#255#227#205#197
+ +#255#227#205#197#255#227#205#197#255#227#205#197#255#227#205#197#255#226#204
+ +#196#255#220#194#183#255#200#159#143#255#144'_H'#254'a6"'#253'\1'#30'y'#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'\3'#31#25'^2'#29#207'nB.'#249#175'~i'#255
+ +#213#182#169#255#225#202#193#255#230#209#203#255#230#211#205#255#230#211#205
+ +#255#230#211#205#255#230#211#205#255#230#211#205#255#230#211#205#255#230#211
+ +#205#255#230#211#205#255#230#211#205#255#230#211#205#255#230#211#205#255#230
+ +#211#205#255#230#211#205#255#230#211#205#255#230#211#205#255#230#211#205#255
+ +#230#211#205#255#230#211#205#255#230#211#205#255#230#211#205#255#230#211#205
+ +#255#230#211#205#255#230#211#205#255#230#211#205#255#230#211#205#255#230#210
+ +#204#255#227#205#198#255#219#191#181#255#193#149#131#255#131'R='#251'_4 '#247
+ +'Z0'#26'O'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'` '#8']0'
+ +#28#169'e:'''#250#148'aL'#255#196#153#136#255#220#193#183#255#229#209#202#255
+ +#233#216#210#255#234#216#211#255#234#216#211#255#234#216#211#255#234#216#211
+ +#255#234#216#211#255#234#216#211#255#234#216#211#255#234#216#211#255#234#216
+ +#211#255#234#216#211#255#234#216#211#255#234#216#211#255#234#216#211#255#234
+ +#216#211#255#234#216#211#255#234#216#211#255#234#216#211#255#234#216#211#255
+ +#234#216#211#255#234#216#211#255#234#216#211#255#233#216#211#255#231#212#206
+ ,#255#224#200#192#255#207#171#156#255#168'va'#255'rE1'#249'^3'#31#230'Y,'#28
+ +'.'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0'^1'#29'h`3'#31#237'nA/'#249#158'mW'#255#203#165#150#255#224#201#192
+ +#255#232#213#208#255#235#219#215#255#237#222#218#255#237#222#218#255#237#222
+ +#218#255#237#222#218#255#237#222#218#255#237#222#218#255#237#222#218#255#237
+ +#222#218#255#237#222#218#255#237#222#218#255#237#222#218#255#237#222#218#255
+ +#237#222#218#255#237#222#218#255#237#222#218#255#237#222#218#255#237#222#218
+ +#255#236#220#216#255#233#216#211#255#228#206#200#255#213#182#170#255#177#131
+ +'n'#255'}M:'#250'a6"'#253']1'#29#155'U1'#24#21#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'].'#23#11
+ +']1'#29'~`5!'#246'tF5'#249#166'u`'#255#202#164#148#255#221#195#186#255#230
+ +#210#203#255#234#218#213#255#238#224#220#255#240#227#224#255#240#227#225#255
+ +#240#227#225#255#240#227#225#255#240#227#225#255#240#227#225#255#240#227#225
+ +#255#240#227#225#255#240#227#225#255#240#227#225#255#240#227#225#255#239#225
+ +#222#255#236#220#215#255#232#213#207#255#225#203#194#255#210#176#164#255#183
+ +#138'u'#255#133'UA'#252'c9&'#254'^2'#30#178'\.'#26''''#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'U1'#24#21']0'#30#147'`7"'#251'jA-'#249#133'UA'
+ +#253#169'zf'#255#201#162#146#255#220#194#184#255#230#211#205#255#233#215#210
+ +#255#234#217#212#255#236#220#215#255#237#222#218#255#238#223#220#255#237#222
+ +#219#255#236#220#216#255#234#219#213#255#233#216#211#255#231#213#206#255#225
+ +#203#194#255#209#174#160#255#181#136'u'#255#145'`L'#255'sG4'#249'c9&'#255'_2'
+ +#30#198'].'#28'7'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0'U+'#28#18'\.'#27'^_1'#30#179'c7$'#248'h?,'#251#127
+ +'Q;'#251#148'dN'#255#163't_'#255#175#129'n'#255#186#143'~'#255#198#157#141
+ +#255#204#167#151#255#201#161#145#255#191#149#132#255#179#135'u'#255#167'ye'
+ +#255#153'iT'#255#136'WC'#254'pE2'#249'c9&'#255'_3'#31#212'Z/'#27'|].'#29','#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'U9'#28#9'\.'#26'N^0'#29#157'`'
+ +'4 '#203'c6#'#230'c7%'#249'd:('#255'f=*'#255'i?-'#252'g>+'#255'e;('#255'd9&'
+ +#253'b7$'#237'a5!'#214'_1'#30#180'\/'#26'lX,'#26#29#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0'`0 '#16'[1'#24'*].'#27'B]1'#29'4\3'#31#25'UU'#0#3#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#255#255#255#248#15#255
+ +#255#255#255#255#254#0#0#127#255#255#255#255#240#0#0#7#255#255#255#255#192#0
+ +#0#1#255#255#255#255#0#0#0#0#255#255#255#252#0#0#0#0'?'#255#255#248#0#0#0#0
+ +#31#255#255#240#0#0#0#0#7#255#255#192#0#0#0#0#3#255#255#128#0#0#0#0#1#255#255
+ +#128#0#0#0#0#0#255#255#0#0#0#0#0#0#127#254#0#0#0#0#0#0#127#252#0#0#0#0#0#0'?'
+ +#252#0#0#0#0#0#0#31#248#0#0#0#0#0#0#31#248#0#0#0#0#0#0#15#240#0#0#0#0#0#0#15
+ ,#240#0#0#0#0#0#0#7#224#0#0#0#0#0#0#7#224#0#0#0#0#0#0#7#224#0#0#0#0#0#0#3#192
+ +#0#0#0#0#0#0#3#192#0#0#0#0#0#0#3#192#0#0#0#0#0#0#1#192#0#0#0#0#0#0#1#192#0#0
+ +#0#0#0#0#1#128#0#0#0#0#0#0#1#128#0#0#0#0#0#0#1#128#0#0#0#0#0#0#1#128#0#0#0#0
+ +#0#0#1#128#0#0#0#0#0#0#1#128#0#0#0#0#0#0#1#192#0#0#0#0#0#0#1#192#0#0#0#0#0#0
+ +#1#192#0#0#0#0#0#0#1#192#0#0#0#0#0#0#1#192#0#0#0#0#0#0#3#192#0#0#0#0#0#0#3
+ +#224#0#0#0#0#0#0#3#224#0#0#0#0#0#0#7#224#0#0#0#0#0#0#7#224#0#0#0#0#0#0#7#240
+ +#0#0#0#0#0#0#15#240#0#0#0#0#0#0#15#248#0#0#0#0#0#0#31#248#0#0#0#0#0#0#31#252
+ +#0#0#0#0#0#0'?'#252#0#0#0#0#0#0#127#254#0#0#0#0#0#0#127#254#0#0#0#0#0#0#255
+ +#255#0#0#0#0#0#1#255#255#128#0#0#0#0#3#255#255#192#0#0#0#0#7#255#255#224#0#0
+ +#0#0#15#255#255#240#0#0#0#0#31#255#255#248#0#0#0#0'?'#255#255#254#0#0#0#0#127
+ +#255#255#255#0#0#0#1#255#255#255#255#192#0#0#7#255#255#255#255#240#0#0#31#255
+ +#255#255#255#254#0#0#255#255#255#255#255#255#248#31#255#255#255#255#255#255
+ +#255#255#255#255#255'('#0#0#0'0'#0#0#0'`'#0#0#0#1#0' '#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0'UUU'#3'333'#5'UUU'#6'III'#7'@@@'#8'@@@'#8'III'#7
+ +'UUU'#6'333'#5'UUU'#3#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'@@@'
+ +#4'@@@'#8'@@@'#16'DDD1BBBMCCC_FCCrDBB'#129'FDD'#133'CCCvCCCcDDDRDDD('#240'l@!'#252'qE!'
+ +#253'yJ$'#252#129'R&'#252#138'X)'#253#134'T('#253'}N%'#252'uG#'#252'oC"'#253
+ +'h=#'#248'Z>.'#230'OC;'#211'FEC'#198'DDC'#187'BBB|CCC&999'#9#0#0#0#1#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#2'<<<'#17'CCCWEED'#170'OB9'#211'd=&'#244'qE"'#253#137'V)'#253
+ +#164'h.'#255#186'y3'#255#194#130'5'#255#198#135'6'#255#203#140'7'#255#207#145
+ +'8'#255#205#143'7'#255#201#137'7'#255#196#132'6'#255#192#127'5'#255#177'r1'
+ +#255#152'_+'#254'{L%'#252'k?"'#251'[>-'#233'IEA'#203'EDD'#184'DDDq<<<'#30'@@'
+ +'@'#4#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0'@@@'#4'BBB#EDD'#146'KB<'#205'a='''#242'yK&'#252#166'i/'#255#192#128'6'
+ +#255#205#143'9'#255#217#159'<'#255#226#169'>'#255#230#173'>'#255#232#176'>'
+ +#255#235#180'?'#255#237#182'@'#255#236#181'?'#255#234#178'>'#255#231#175'>'
+ +#255#228#171'>'#255#223#165'<'#255#211#150':'#255#199#136'8'#255#182'v5'#255
+ +#146'\,'#253'k@"'#252'W?1'#227'GFE'#199'CCC'#171'???=@@@'#8#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'III'#7'DDD8ECB'#170'[>,'#234'sF$'
+ +#252#160'e0'#255#196#133';'#255#216#158'@'#255#227#170'A'#255#234#180'C'#255
+ +#241#189'D'#255#245#193'E'#255#246#195'F'#255#247#195'F'#255#247#196'E'#255
+ +#248#197'F'#255#248#197'E'#255#247#195'F'#255#247#194'F'#255#246#194'E'#255
+ +#244#192'E'#255#238#184'C'#255#230#176'C'#255#223#166'A'#255#207#147'='#255
+ +#182'w7'#255#138'V+'#253'h>#'#250'NA9'#215'CCC'#186'@@@[;;;'#13#0#0#0#1#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'@@@'#8'EEENGC?'#189'b;%'#245#139'W-'#253#190
+ +#127';'#255#212#153'B'#255#227#172'F'#255#239#186'I'#255#242#191'J'#255#244
+ +#193'K'#255#246#195'K'#255#247#196'K'#255#247#196'K'#255#247#196'L'#255#247
+ +#196'L'#255#247#196'L'#255#247#196'L'#255#247#196'L'#255#247#196'K'#255#247
+ +#196'K'#255#246#196'K'#255#245#195'J'#255#243#193'J'#255#242#190'J'#255#234
+ +#180'H'#255#221#165'E'#255#202#142'@'#255#173'o5'#255'oC$'#252'T?3'#225'CCC'
+ +#193'AAAy@@@'#16#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'+++'#6'DDD@K@<'#198'g<"'#250#154
+ +'a2'#254#200#141'B'#255#222#168'J'#255#234#183'N'#255#239#189'P'#255#242#192
+ +'P'#255#242#193'P'#255#243#193'P'#255#243#193'P'#255#243#193'P'#255#243#193
+ +'P'#255#243#193'P'#255#243#193'P'#255#243#193'P'#255#243#193'P'#255#243#193
+ ,'P'#255#243#193'P'#255#243#193'P'#255#243#193'P'#255#243#193'P'#255#242#193
+ +'P'#255#242#193'P'#255#241#191'P'#255#238#187'N'#255#229#176'L'#255#214#158
+ +'G'#255#183'y;'#255'yJ)'#252'[=,'#236'CCB'#195'EEEoFFF'#11#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'UUU'#3
+ +'CCC.J?;'#190'g=#'#252#167'k7'#255#205#147'H'#255#226#173'P'#255#235#186'T'
+ +#255#238#189'T'#255#239#190'U'#255#239#190'U'#255#239#190'U'#255#239#190'U'
+ +#255#239#190'U'#255#239#190'U'#255#191#152'D'#255'A4'#23#255'>1'#22#255'D6'
+ +#24#255'H9'#26#255'RA'#29#255#146's4'#255#228#182'Q'#255#239#190'U'#255#239
+ +#190'U'#255#239#190'U'#255#239#190'U'#255#239#190'U'#255#238#190'U'#255#237
+ +#187'T'#255#232#182'S'#255#217#162'M'#255#191#129'B'#255#132'R-'#253'[9('#240
+ +'DDD'#191'CCCW@@@'#8#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#1'>>>'#29'F@='#169'd9#'#250#165'i8'#255#208#151'L'#255
+ +#226#174'U'#255#233#184'Y'#255#235#186'Y'#255#235#187'Y'#255#235#187'Y'#255
+ +#235#187'Y'#255#235#187'Y'#255#235#187'Y'#255#235#187'Y'#255'<0'#23#255#1#1#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1#1#0#255#0#0#0#255#6
+ +#5#2#255'*!'#16#255'w^-'#255#227#181'W'#255#235#187'Y'#255#235#187'Y'#255#235
+ +#186'Y'#255#234#186'Y'#255#231#181'X'#255#218#164'Q'#255#194#133'E'#255'{J*'
+ +#252'U=/'#230'CCC'#186'EEE?@@@'#4#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0'333'#10'DAAw_9%'#244#150'^4'#254#204#148'N'#255#225#175
+ +'Y'#255#230#181'\'#255#231#183'\'#255#231#183'\'#255#231#183'\'#255#231#183
+ +'\'#255#231#183'\'#255#231#183'\'#255#231#183'\'#255'hR*'#255#1#1#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#1#1#0#255#1#1#0#255'*!'#17#255#164#130'B'#255#231#183'\'
+ +#255#231#183'\'#255#231#182']'#255#228#179'['#255#217#165'V'#255#185'|C'#255
+ +'nA'''#252'N>5'#219'CCC'#163'@@@'#20#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#128#128#128#2'@@@,W8*'#227#132'P/'#253#196#139'M'#255#220
+ +#170'['#255#226#179'_'#255#227#179'_'#255#227#179'_'#255#227#179'_'#255#227
+ +#179'_'#255#227#179'_'#255#227#179'_'#255#227#179'_'#255#227#179'_'#255#4#3#2
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1#1#0
+ +#255#7#6#3#255#178#141'J'#255#227#179'_'#255#227#179'_'#255#225#176'^'#255
+ +#211#158'U'#255#174'q?'#255'c9"'#252'GA>'#203'BBB]III'#7#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0'FFF'#11'H>:'#150'e:#'#252#186'~H'#255#214#164'\'
+ +#255#222#174'a'#255#223#175'b'#255#223#175'b'#255#223#175'b'#255#223#175'b'
+ +#255#223#175'b'#255#223#175'b'#255#223#175'b'#255#223#175'b'#255#188#148'S'
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#1#1#1#255#154'yC'#255#223#175'b'#255#223#175'a'#255
+ +#220#171'`'#255#204#150'U'#255#145'Y5'#254'Y8('#238'CCC'#175'FFF'#29#0#0#0#1
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'UUU'#3'AAA3Z7'''#236#148'\6'#255#207#154'Z'
+ +#255#218#170'b'#255#219#171'd'#255#219#171'd'#255#219#171'd'#255#219#171'd'
+ +#255#219#171'd'#255#219#171'd'#255#219#171'd'#255#219#171'd'#255#219#171'd'
+ +#255#211#165'`'#255#6#5#3#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#2#2#1#255#219#171'd'#255#219
+ +#171'd'#255#219#171'd'#255#215#166'`'#255#189#129'M'#255'h=$'#252'H>;'#207'E'
+ +'EEhIII'#7#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'III'#7'K<5'#137'h;$'#252#188#130
+ +'O'#255#213#164'b'#255#215#167'd'#255#215#167'd'#255#215#167'd'#255#215#167
+ +'d'#255#215#167'd'#255#215#167'd'#255#215#167'd'#255#215#167'd'#255#215#167
+ +'d'#255#215#167'd'#255#215#167'd'#255#168#130'N'#255#1#1#1#255#0#0#0#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#200#155']'#255#215#167'd'#255#215#167'd'#255#215#166'd'#255#205#153']'
+ +#255#153'`:'#255'[6$'#243'CCC'#164';;;'#13#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'7'
+ +'77'#14'Z5%'#229#150'[8'#255#203#150'^'#255#211#162'e'#255#211#162'e'#255#211
+ +#162'e'#255#211#162'e'#255#211#162'e'#255#211#162'e'#255#211#162'e'#255#211
+ +#162'e'#255#211#162'e'#255#211#162'e'#255#211#162'e'#255#211#162'e'#255#211
+ +#162'e'#255#142'mD'#255#1#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#1#1#0#255#145'pF'#255#211#162'e'#255#211#162
+ +'e'#255#211#162'e'#255#210#159'd'#255#189#131'R'#255'f9#'#252'I@;'#202'===.'
+ +#128#128#128#2#0#0#0#0#0#0#0#0#128#128#128#2'D??4]3'#30#252#181'yM'#255#206
+ +#155'd'#255#207#157'f'#255#207#157'f'#255#207#157'f'#255#207#157'f'#255#205
+ +#155'f'#255'S?('#255#1#1#1#255#1#0#0#255#3#2#1#255#15#11#7#255#169#128'S'#255
+ ,#207#157'f'#255#207#157'f'#255#207#157'f'#255#16#12#8#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1#0#0#255#186#141'\'
+ +#255#207#157'f'#255#207#157'f'#255#207#157'f'#255#207#157'e'#255#201#148'`'
+ +#255#135'O0'#254'R9-'#226'BBBeIII'#7#0#0#0#0#0#0#0#0'UUU'#6'O8/'#141'o>'''
+ +#251#193#139'['#255#203#151'e'#255#203#152'e'#255#203#152'e'#255#203#152'e'
+ +#255#203#152'e'#255#23#17#11#255#1#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0
+ +#0#255#1#1#1#255#153'rL'#255#203#152'e'#255#203#152'e'#255',!'#22#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1#0#0#255' '#24#16
+ +#255#203#152'e'#255#203#152'e'#255#203#152'e'#255#203#152'e'#255#203#152'e'
+ +#255#202#150'd'#255#165'jC'#255'\3!'#247'DDD'#151'MMM'#10#0#0#0#0#0#0#0#0'@@'
+ +'@'#8'Z6%'#206#142'T5'#255#195#142'a'#255#198#145'c'#255#198#145'c'#255#198
+ +#145'c'#255#198#145'c'#255'W@,'#255#1#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255'%'#27#19#255#198#145'c'#255#198#145'c'#255'U>+'
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1#0#0#255#1#1#1#255#27#20#13#255'vW;'
+ +#255#198#145'c'#255#198#145'c'#255#198#145'c'#255#198#145'c'#255#198#145'c'
+ +#255#198#145'c'#255#198#145'c'#255#184'}S'#255'`4 '#252'FA>'#183'@@@'#12#0#0
+ +#0#0#0#0#0#0'999'#9']2'#30#243#166'gD'#255#192#138'`'#255#192#139'a'#255#192
+ +#139'a'#255#192#139'a'#255#190#137'a'#255#1#1#1#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#8#6#4#255#192#139'a'#255#192#139
+ +'a'#255#129']B'#255#1#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1#0#0#255'Q;)'#255#192#139'a'
+ +#255#192#139'a'#255#192#139'a'#255#192#139'a'#255#192#139'a'#255#192#139'a'
+ +#255#192#139'a'#255#192#139'a'#255#192#139'a'#255#192#139'a'#255#188#132'['
+ +#255'u@'''#252'M;3'#212'999'#18#0#0#0#0#0#0#0#0'FFF'#11'^1'#29#250#174'oK'
+ +#255#186#131'\'#255#186#131'\'#255#186#131'\'#255#186#131'\'#255'vS:'#255#1#1
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1#0#0#255
+ +'S:)'#255#186#131'\'#255#186#131'\'#255#184#129'\'#255'('#28#20#255#1#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255'Q9('#255#186#131'\'#255#186#131'\'#255#186#131'\'#255#186#131'\'#255#186
+ +#131'\'#255#186#131'\'#255#186#131'\'#255#186#131'\'#255#186#131'\'#255#186
+ +#131'\'#255#186#131'\'#255#186#130'['#255#131'I-'#255'Q9-'#221'FFF!'#0#0#0#1
+ +#0#0#0#0'M33'#20'_2'#30#251#173'pN'#255#180'{X'#255#180'{X'#255#180'{X'#255
+ +#180'{X'#255'-'#30#22#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#2#1#1#255'dE1'#255#180'{X'#255#180'{X'#255#180'{X'#255#180'{X'#255
+ +#180'{X'#255'O6&'#255#2#1#1#255#1#1#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255'G0#'#255#180'{X'#255#180'{X'#255#178'{X'#255'hH3'#255'U:)'#255
+ +'mK5'#255#180'{X'#255#180'{X'#255#180'{X'#255#180'{X'#255#180'{X'#255#180'{X'
+ +#255#180'{X'#255#139'P3'#255'U7)'#231'BBB2UUU'#3#0#0#0#0'T1&,c5 '#249#174'rQ'
+ +#255#178'wW'#255#178'wW'#255#178'wW'#255#178'wW'#255#8#5#4#255#0#0#0#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#1#0#0#255#27#18#13#255#164'nQ'#255#178'wW'#255#178
+ +'wW'#255#178'wW'#255#178'wW'#255#178'wW'#255#178'wW'#255#178'wW'#255#178'wW'
+ +#255#142'_F'#255'H0#'#255#20#13#10#255#25#16#12#255'9'''#28#255'lI5'#255#178
+ +'wW'#255#178'wW'#255'kG4'#255#1#1#1#255#1#1#0#255#1#0#0#255#1#0#0#255#3#2#1
+ +#255'zQ<'#255#178'wW'#255#178'wW'#255#178'wW'#255#178'wW'#255#178'wW'#255#149
+ +'W9'#255'Z5%'#238'DDD-'#128#128#128#2#0#0#0#0'Y3 Bj8#'#248#173'qS'#255#175't'
+ +'W'#255#175'tW'#255#175'tW'#255#175'tW'#255#1#0#0#255#1#1#1#255#0#0#0#255#0#0
+ +#0#255#5#3#3#255'cB2'#255#175'tW'#255#175'tW'#255#175'tW'#255#175'tW'#255#175
+ +'tW'#255#175'tW'#255#175'tW'#255#175'tW'#255#175'tW'#255#175'tW'#255#175'tW'
+ +#255#175'tW'#255#175'tW'#255#175'tW'#255#175'tW'#255#175'tW'#255#175'tW'#255
+ +#173'rU'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#2#1
+ +#1#255#152'eL'#255#175'tW'#255#175'tW'#255#175'tW'#255#175'tW'#255#155'[>'
+ +#255'\4"'#244'@@@'#28#0#0#0#1#0#0#0#0'X0!3g7"'#246#172'oR'#255#174'rV'#255
+ +#174'rV'#255#174'rV'#255#166'lR'#255#7#5#3#255#131'VA'#255#155'fM'#255'oI7'
+ +#255#174'rV'#255#174'rV'#255#174'rV'#255#174'rV'#255#174'rV'#255#174'rV'#255
+ +#174'rV'#255#174'rV'#255#174'rV'#255#174'rV'#255#174'rV'#255#174'rV'#255#174
+ +'rV'#255#174'rV'#255#174'rV'#255#174'rV'#255#174'rV'#255#174'rV'#255#174'rV'
+ +#255#153'dL'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255'<'''#29#255#174'rV'#255#174'rV'#255#174'rV'#255#173'qU'#255#151'Y'
+ +'='#255']6%'#239'333'#15#0#0#0#0#0#0#0#0'O1'''#25'b3'#31#247#168'jN'#255#172
+ +'oU'#255#172'oU'#255#172'oU'#255#172'oU'#255#172'oU'#255#172'oU'#255#172'oU'
+ +#255#172'oU'#255#172'oU'#255#172'oU'#255#172'oU'#255#172'oU'#255#136'XD'#255
+ ,'U7*'#255'^=/'#255'kE5'#255#170'oU'#255#172'oU'#255#172'oU'#255#172'oU'#255
+ +#172'oU'#255#172'oU'#255#172'oU'#255#172'oU'#255#172'oU'#255#172'oU'#255#172
+ +'oU'#255#172'oU'#255#5#3#2#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255'!'#21#16#255#172'oU'#255#172'oU'#255#172'oU'#255#172'oT'#255
+ +#143'R7'#255'Y6('#225'@@@'#12#0#0#0#0#0#0#0#0'333'#5'_2'#31#248#167'hL'#255
+ +#172'qW'#255#172'qX'#255#172'qX'#255#172'qX'#255#172'qX'#255#172'qX'#255#172
+ +'qX'#255#172'qX'#255#172'qX'#255#172'qX'#255#172'qX'#255':&'#30#255#1#0#0#255
+ +#1#1#0#255#1#1#1#255#1#1#0#255#4#2#2#255#133'WD'#255#172'qX'#255#172'qX'#255
+ +#172'qX'#255#172'qX'#255#172'qX'#255#172'qX'#255#172'qX'#255#172'qX'#255#172
+ +'qX'#255#172'qX'#255'E.$'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#30#20#15#255#172'qX'#255#172'qX'#255#172'qX'#255#172'pV'#255
+ +#134'K2'#255'V8)'#199'999'#9#0#0#0#0#0#0#0#0#0#0#0#1'_3'#30#239#164'fJ'#255
+ +#175'w]'#255#175'w^'#255#175'w^'#255#175'w^'#255#175'w^'#255#175'w^'#255#175
+ +'w^'#255#175'w^'#255#175'w^'#255#175'w^'#255'hF7'#255#1#0#0#255#0#0#0#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#7#5#4#255#175'w^'#255#175'w^'#255'{TB'
+ +#255'X;/'#255']?2'#255#127'VD'#255#175'w^'#255#175'w^'#255#175'w^'#255#175'w'
+ +'^'#255#165'qY'#255#1#1#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1#1#1
+ +#255'fF7'#255#175'w^'#255#175'w^'#255#175'w^'#255#175'v\'#255'{D-'#253'S5('
+ +#154'333'#5#0#0#0#0#0#0#0#0#0#0#0#0'a3'#30#200#149'Z?'#255#179'|c'#255#179'}'
+ +'e'#255#179'}e'#255#179'}e'#255#179'}e'#255#179'}e'#255#179'}e'#255#179'}e'
+ +#255#179'}e'#255#179'}e'#255#19#13#11#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#2#1#1#255#179'}e'#255'E0'''#255#1#0#0#255#1#1#0#255
+ +#1#1#0#255#0#0#0#255'R:/'#255#179'}e'#255#179'}e'#255#179'}e'#255#179'}e'#255
+ +'.!'#26#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1#1#1#255#177'}e'#255#179
+ +'}e'#255#179'}e'#255#179'}e'#255#175'v\'#255'g8$'#251'W7*O'#0#0#0#1#0#0#0#0#0
+ +#0#0#0#0#0#0#0'[0'#29'lyD-'#249#181#128'i'#255#183#131'l'#255#183#131'l'#255
+ +#183#131'l'#255#183#131'l'#255#183#131'l'#255#183#131'l'#255#183#131'l'#255
+ +#183#131'l'#255#183#131'l'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255'"'#25#20#255#183#131'l'#255#0#0#0#255#0#0#0#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255'B/'''#255#183#131'l'#255#183#131'l'#255
+ +#183#131'l'#255#169'yd'#255#1#1#1#255#0#0#0#255#0#0#0#255#0#0#0#255'#'#25#21
+ +#255#183#131'l'#255#183#131'l'#255#183#131'l'#255#183#131'l'#255#167'lQ'#255
+ +'^3'#31#248'@@@'#12#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'Y1'#30#26'b5 '#244#178'z'
+ +'c'#255#187#138't'#255#187#138'u'#255#187#138'u'#255#187#138'u'#255#187#138
+ +'u'#255#187#138'u'#255#187#138'u'#255#187#138'u'#255#187#138'u'#255#2#2#1#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1#1#0#255#170'~j'#255#177
+ +#130'o'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#4#3#3
+ +#255#187#138'u'#255#187#138'u'#255#187#138'u'#255#187#138'u'#255'jNB'#255#11
+ +#8#7#255#0#0#0#255#0#0#0#255#152'p`'#255#187#138'u'#255#187#138'u'#255#187
+ +#138'u'#255#186#136'r'#255#144'W?'#255']6#'#193'333'#5#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0'`4'#31#217#160'gN'#255#190#143'{'#255#191#145'}'#255#191
+ +#145'}'#255#191#145'}'#255#191#145'}'#255#191#145'}'#255#191#145'}'#255#191
+ +#145'}'#255#191#145'}'#255#19#14#12#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255'7*$'#255#191#145'}'#255#164'|k'#255#1#1#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#2#2#1#255#191#145'}'#255#191#145'}'#255
+ +#191#145'}'#255#191#145'}'#255#191#145'}'#255#191#145'}'#255#0#0#0#255#30#23
+ +#20#255#191#145'}'#255#191#145'}'#255#191#145'}'#255#191#145'}'#255#187#138
+ +'t'#255'p>('#249'Y2#U'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27
+ +'huB+'#244#190#142'z'#255#195#152#132#255#195#152#132#255#195#152#132#255#195
+ +#152#132#255#195#152#132#255#195#152#132#255#195#152#132#255#195#152#132#255
+ +'A3,'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1#0#0#255#183#142'|'#255
+ +#195#152#132#255#138'k]'#255#1#1#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#9#7#6#255#195#152#132#255#195#152#132#255#195#152#132#255#195
+ +#152#132#255#195#152#132#255#195#152#132#255#1#1#1#255#160'}m'#255#195#152
+ +#132#255#195#152#132#255#195#152#132#255#194#150#131#255#167'pW'#255'`4 '#240
+ +'M33'#10#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'@@'#0#4'`3'#30#229
+ +#164'nU'#255#197#156#137#255#199#159#141#255#199#159#141#255#199#159#141#255
+ +#199#159#141#255#199#159#141#255#199#159#141#255#199#159#141#255'x`U'#255#1#1
+ +#1#255#0#0#0#255#0#0#0#255#0#0#0#255#18#14#13#255#199#159#141#255#199#159#141
+ +#255' '#26#23#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1#1#0#255
+ +#139'oc'#255#199#159#141#255#199#159#141#255#199#159#141#255#199#159#141#255
+ +#199#159#141#255#199#159#141#255'^KC'#255#199#159#141#255#199#159#141#255#199
+ +#159#141#255#199#159#141#255#192#147#127#255'rB-'#249'\1 k'#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'\.'#28'Sn>('#243#194#149#131
+ ,#255#202#165#148#255#203#165#149#255#203#165#149#255#203#165#149#255#203#165
+ +#149#255#203#165#149#255#203#165#149#255#169#138'|'#255#0#0#0#255#1#1#1#255
+ +#16#13#11#255#23#19#17#255#171#139'~'#255#203#165#149#255#203#165#149#255#3#3
+ +#2#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1#0#0#255'*"'#31#255#203#165
+ +#149#255#203#165#149#255#203#165#149#255#203#165#149#255#203#165#149#255#203
+ +#165#149#255#203#165#149#255#203#165#149#255#203#165#149#255#203#165#149#255
+ +#203#165#149#255#201#162#145#255#163'mU'#255'_3'#31#227'U'#0#0#3#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'a3'#30#213#153
+ +'eM'#254#204#167#151#255#207#172#158#255#207#172#158#255#207#172#158#255#207
+ +#172#158#255#207#172#158#255#207#172#158#255#205#170#156#255#0#0#0#255'<1.'
+ +#255#207#172#158#255#207#172#158#255#207#172#158#255#207#172#158#255#207#172
+ +#158#255#20#16#15#255#1#0#0#255#0#0#0#255#0#0#0#255#1#0#0#255'?40'#255#207
+ +#172#158#255#207#172#158#255#207#172#158#255#207#172#158#255#207#172#158#255
+ +#207#172#158#255#207#172#158#255#207#172#158#255#207#172#158#255#207#172#158
+ +#255#207#172#158#255#207#171#156#255#192#147#127#255'k<'''#244'Z.'#29'L'#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +'^/'#27'&b5!'#240#174'{f'#255#209#176#162#255#212#180#167#255#212#180#167#255
+ +#212#180#167#255#212#180#167#255#212#180#167#255#212#180#167#255#6#5#5#255
+ +#179#151#140#255#212#180#167#255#212#180#167#255#212#180#167#255#212#180#167
+ +#255#212#180#167#255#212#180#167#255'gXR'#255#0#0#0#255#0#0#0#255'gXR'#255
+ +#212#180#167#255#212#180#167#255#212#180#167#255#212#180#167#255#212#180#167
+ +#255#212#180#167#255#212#180#167#255#212#180#167#255#212#180#167#255#212#180
+ +#167#255#212#180#167#255#211#179#166#255#202#162#146#255#127'M7'#248'`2'#31
+ +#169#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0'[/'#26'Fg:#'#242#190#145#127#255#214#184#172#255#216
+ +#187#176#255#216#187#176#255#216#187#176#255#216#187#176#255#216#187#176#255
+ +'k]X'#255#216#187#176#255#216#187#176#255#216#187#176#255#216#187#176#255#216
+ +#187#176#255#216#187#176#255#216#187#176#255'E<8'#255#0#0#0#255'>63'#255#216
+ +#187#176#255#216#187#176#255#216#187#176#255#216#187#176#255#216#187#176#255
+ +#216#187#176#255#216#187#176#255#216#187#176#255#216#187#176#255#216#187#176
+ +#255#216#187#176#255#216#187#175#255#210#176#163#255#147'_H'#252'`4'#31#210
+ +'U++'#6#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'\0'#29'trB-'#242#198#157#140#255#218#191
+ +#180#255#221#195#185#255#221#195#185#255#221#195#185#255#221#195#185#255#221
+ +#195#185#255#221#195#185#255#221#195#185#255#221#195#185#255#221#195#185#255
+ +#221#195#185#255#221#195#185#255#221#195#185#255',''%'#255'920'#255#221#195
+ +#185#255#221#195#185#255#221#195#185#255#221#195#185#255#221#195#185#255#221
+ +#195#185#255#221#195#185#255#221#195#185#255#221#195#185#255#221#195#185#255
+ +#221#195#185#255#220#194#184#255#213#183#170#255#162'oW'#255'b5 '#232'].'#23
+ +#22#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'_1'#30#138'l>)'#242#187#143'|'
+ +#255#221#196#186#255#225#202#193#255#225#203#194#255#225#203#194#255#225#203
+ +#194#255#225#203#194#255#225#203#194#255#225#203#194#255#225#203#194#255#225
+ +#203#194#255#225#203#194#255#225#203#194#255#225#203#194#255#225#203#194#255
+ +#225#203#194#255#225#203#194#255#225#203#194#255#225#203#194#255#225#203#194
+ +#255#225#203#194#255#225#203#194#255#225#203#194#255#225#203#194#255#225#203
+ +#194#255#224#201#192#255#212#180#168#255#149'aK'#252'a5!'#230']2'#25')'#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#28'\d9$'#241#172
+ +'|h'#255#222#197#187#255#228#206#200#255#230#209#203#255#230#209#203#255#230
+ +#209#203#255#230#209#203#255#230#209#203#255#230#209#203#255#230#209#203#255
+ +#230#209#203#255#230#209#203#255#230#209#203#255#230#209#203#255#230#209#203
+ +#255#230#209#203#255#230#209#203#255#230#209#203#255#230#209#203#255#230#209
+ +#203#255#230#209#203#255#230#209#203#255#229#209#202#255#226#204#197#255#208
+ +#173#159#255#131'R;'#245'a3'#31#207'Y3'#26#20#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'].'#28'7a5!'#236#137'WB'#248#201
+ +#163#148#255#229#210#202#255#233#215#210#255#234#217#212#255#234#217#212#255
+ +#234#217#212#255#234#217#212#255#234#217#212#255#234#217#212#255#234#217#212
+ +#255#234#217#212#255#234#217#212#255#234#217#212#255#234#217#212#255#234#217
+ +#212#255#234#217#212#255#234#217#212#255#234#217#212#255#234#216#211#255#231
+ +#212#206#255#221#195#185#255#174#128'm'#255'm>*'#242'`1'#29#163'f33'#5#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ ,#0#0#0#0#0'b'''#20#13'`2'#29#140'd8$'#241#151'hR'#251#211#179#167#255#233#215
+ +#210#255#236#220#215#255#237#222#219#255#238#225#221#255#238#225#221#255#238
+ +#225#221#255#238#225#221#255#238#225#221#255#238#225#221#255#238#225#221#255
+ +#238#225#221#255#238#225#221#255#238#223#220#255#236#221#217#255#234#219#213
+ +#255#227#205#198#255#188#146#128#255'wH2'#242'b5 '#219'].'#27'B'#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'X1'#29#26'a3'#30#168'f:$'#242#134'T?'
+ +#246#179#136'v'#255#214#183#172#255#235#218#214#255#238#225#221#255#239#226
+ +#223#255#240#227#224#255#240#227#225#255#240#227#225#255#239#226#223#255#239
+ +#225#222#255#238#224#220#255#226#204#196#255#199#161#145#255#158'o['#254'rD-'
+ +#239'b4"'#232'^2'#30'\'#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0'`+ '#24']/'#30'fd6#'#197'c8#'#243'vE0'#240#140'ZF'
+ +#247#156'mY'#255#171#127'm'#255#184#143#127#255#178#136'v'#255#164'wd'#255
+ +#148'dP'#252#130'Q;'#243'l<('#239'b6"'#234'b5!'#151'Z-'#29'>UU'#0#3#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0'].'#23#11'Z/'#29'G^4 fa4!'#130'd6!'#166'd7#'#194
+ +'d7"'#182'c6"'#150'_3'#31's\0'#29'YY/'#30'+'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#255#255#224#3#255#255#255
+ +#255#255#254#0#0#127#255#255#255#255#248#0#0#31#255#255#255#255#224#0#0#7#255
+ +#255#255#255#192#0#0#3#255#255#255#255#128#0#0#1#255#255#255#255#0#0#0#0#127
+ +#255#255#254#0#0#0#0#127#255#255#252#0#0#0#0'?'#255#255#248#0#0#0#0#31#255
+ +#255#240#0#0#0#0#15#255#255#240#0#0#0#0#15#255#255#224#0#0#0#0#7#255#255#224
+ +#0#0#0#0#3#255#255#192#0#0#0#0#3#255#255#192#0#0#0#0#3#255#255#192#0#0#0#0#1
+ +#255#255#128#0#0#0#0#1#255#255#128#0#0#0#0#1#255#255#128#0#0#0#0#1#255#255
+ +#128#0#0#0#0#1#255#255#128#0#0#0#0#0#255#255#128#0#0#0#0#0#255#255#128#0#0#0
+ +#0#0#255#255#128#0#0#0#0#0#255#255#128#0#0#0#0#1#255#255#128#0#0#0#0#1#255
+ +#255#128#0#0#0#0#1#255#255#128#0#0#0#0#1#255#255#192#0#0#0#0#1#255#255#192#0
+ +#0#0#0#3#255#255#192#0#0#0#0#3#255#255#224#0#0#0#0#7#255#255#224#0#0#0#0#7
+ +#255#255#224#0#0#0#0#15#255#255#240#0#0#0#0#15#255#255#248#0#0#0#0#31#255#255
+ +#248#0#0#0#0'?'#255#255#252#0#0#0#0'?'#255#255#254#0#0#0#0#127#255#255#255#0
+ +#0#0#0#255#255#255#255#128#0#0#1#255#255#255#255#192#0#0#3#255#255#255#255
+ +#224#0#0#15#255#255#255#255#248#0#0#31#255#255#255#255#254#0#0#127#255#255
+ +#255#255#255#192#7#255#255#255#255#255#255#255#255#255#255#255#255'('#0#0#0
+ +' '#0#0#0'@'#0#0#0#1#0' '#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#2'CCC'#19'FFF'#22'UUU'#3#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0'@@@'#12'EAAGDDB'#133'DDC'#181'HC?'#205'LA;'#213
+ +'JB='#212'FC@'#204'EED'#185'DDC'#145'DDDSFFF'#22#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'III'#14'EEBoLA;'#208'eE-'#235'xK('
+ +#246#131'R)'#250#139'W*'#251#149'_,'#252#145'\+'#252#136'V*'#250#128'Q('#249
+ +'rI)'#244'\D2'#227'FB?'#207'CCC'#134'DDD'#30#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0'EEENMA9'#206'oF)'#245#147']-'#252#187'}4'#255#211#150'9'#255#224
+ +#167';'#255#230#174'='#255#234#179'>'#255#233#178'>'#255#228#171'='#255#221
+ +#163'<'#255#205#143'8'#255#175'r2'#255#131'R*'#250'eC,'#238'FB?'#205'CCCoUUU'
+ +#3#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0'@@@'#4'GEA|dB+'#239#142'[.'#252#198#137'<'#255#227#172'C'#255
+ +#236#183'E'#255#242#190'F'#255#246#195'G'#255#248#198'G'#255#249#199'H'#255
+ +#249#198'H'#255#247#196'G'#255#245#193'G'#255#240#188'F'#255#234#180'D'#255
+ +#220#163'A'#255#183'y8'#255'}O*'#250'WA4'#225'CCC'#152'<<<'#17#0#0#0#0#0#0#0
+ ,#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'G@='#148
+ +'lD*'#245#175'u8'#254#221#166'I'#255#234#182'M'#255#242#193'P'#255#243#194'O'
+ +#255#244#195'O'#255#244#195'P'#255#244#195'P'#255#244#195'P'#255#244#195'P'
+ +#255#244#195'P'#255#244#195'P'#255#243#194'O'#255#243#194'O'#255#240#190'O'
+ +#255#230#179'L'#255#212#155'F'#255#148'^1'#252'`A.'#234'CCC'#171'@@@'#12#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'FA>vmB)'#247#189
+ +#130'A'#255#224#172'P'#255#236#187'U'#255#238#189'W'#255#238#190'V'#255#238
+ +#190'V'#255#238#190'V'#255'fQ%'#255#17#14#6#255#17#13#6#255#16#13#6#255',#'
+ +#16#255#155'|8'#255#238#190'V'#255#238#190'V'#255#238#189'V'#255#238#189'W'
+ +#255#233#184'U'#255#217#163'M'#255#164'l8'#254'_>+'#238'DDD'#147#128#128#128
+ +#2#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'FDD=e?*'#243#183'}B'#255
+ +#223#171'W'#255#232#183'['#255#232#183'\'#255#232#183'\'#255#232#183'\'#255
+ +#232#183'\'#255'>1'#25#255#1#1#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#1#1#1#255#5#4#2#255#22#17#9#255'pX,'#255#218#171'V'#255#232#183'\'#255#230
+ +#182'['#255#217#164'T'#255#152'a7'#252'V=1'#228'DDDb'#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#128#128#128#2'Z<-'#215#163'k='#254#217#166'['#255#226#178'`'
+ +#255#226#179'a'#255#226#179'a'#255#226#179'a'#255#226#179'a'#255#226#179'a'
+ +#255#5#4#2#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#3#3#1#255',#'#19#255#226#179'a'#255#225#177'_'
+ +#255#208#154'T'#255#129'O1'#251'H?;'#205'@@@'#20#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0'J@<[vF,'#249#206#153'Y'#255#220#172'b'#255#220#172'c'#255#220#172'c'#255
+ +#220#172'c'#255#220#172'c'#255#220#172'c'#255#205#160']'#255#4#3#2#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#1#0#0#255'.$'#21#255#220#172'c'#255#218#170'a'#255#190#132
+ +'N'#255'c=)'#242'CCCz'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'\9('#218#177'vG'#255
+ +#213#164'c'#255#214#166'e'#255#214#166'e'#255#214#166'e'#255#214#166'e'#255
+ +#214#166'e'#255#214#166'e'#255#214#166'e'#255'v\8'#255#2#2#1#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#11#9#5#255#214#166'e'#255#214#166'e'#255#209#159'a'#255#139'Y'
+ +'6'#252'K>7'#206'333'#5#0#0#0#0#0#0#0#0'?;9'#19'mA+'#247#201#148'^'#255#209
+ +#159'e'#255#209#159'e'#255#209#159'e'#255#146'oF'#255#18#14#9#255#21#16#10
+ +#255'O<&'#255#209#159'e'#255#209#159'e'#255'$'#27#17#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#11#8#5#255#209#159'e'#255#209#159'e'#255#208#158'e'#255#185#128'Q'#255
+ +'^9)'#240'BBB6'#0#0#0#0#0#0#0#0'P8-q'#144'Z:'#252#201#150'd'#255#202#151'd'
+ +#255#202#151'd'#255'uW:'#255#2#1#1#255#0#0#0#255#0#0#0#255#1#0#0#255'-!'#22
+ +#255#202#151'd'#255'ZC-'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#1#1#0#255#5#4#3#255'gM3'#255#202#151'd'
+ +#255#202#151'd'#255#202#151'd'#255#197#145'`'#255'l@*'#248'CCBo'#0#0#0#0#0#0
+ +#0#0'^7$'#194#171'pK'#255#194#140'a'#255#194#140'a'#255#194#140'a'#255#6#4#3
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#7#5#4#255#194#140'a'#255#139'eE'
+ +#255#1#1#1#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#13
+ +#9#6#255'wV<'#255#192#138'a'#255#194#140'a'#255#194#140'a'#255#194#140'a'#255
+ +#194#140'a'#255#193#140'a'#255#137'T7'#252'K=6'#158#0#0#0#0#0#0#0#0'a6#'#220
+ +#177'uQ'#255#185#129'['#255#185#129'['#255#127'Y>'#255#1#1#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#2#1#1#255'8'''#27#255#185#129'['#255#185#129'['#255'+'#30
+ +#21#255#2#1#1#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#13#9#6#255#179'}Y'
+ +#255#185#129'['#255#185#129'['#255#185#129'['#255#185#129'['#255#185#129'['
+ +#255#185#129'['#255#185#129'['#255#152'^>'#255'P:1'#190#0#0#0#0#0#0#0#0'c7#'
+ +#227#175'sS'#255#178'xW'#255#178'xW'#255','#30#21#255#0#0#0#255#0#0#0#255#0#0
+ +#0#255#5#4#3#255'uO:'#255#178'xW'#255#178'xW'#255#178'xW'#255#178'xW'#255'xP'
+ +':'#255'('#26#19#255#10#7#5#255#10#7#5#255#28#19#13#255#168'rS'#255#163'nO'
+ +#255#25#17#12#255#6#4#3#255#17#11#8#255'bB/'#255#178'xW'#255#178'xW'#255#178
+ +'xW'#255#158'aB'#255'V9,'#210#0#0#0#0#0#0#0#0'f7"'#227#173'sT'#255#175'tW'
+ +#255#175'tW'#255#15#10#7#255#13#8#6#255#5#4#3#255'+'#29#21#255#169'pU'#255
+ +#175'tW'#255#175'tW'#255#175'tW'#255#175'tW'#255#175'tW'#255#175'tW'#255#175
+ +'tW'#255#175'tW'#255#175'tW'#255#175'tW'#255#175'tW'#255#17#11#8#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#2#2#1#255#136'ZD'#255#175'tW'#255#175'tW'#255#161'd'
+ +'G'#255'[8('#211#0#0#0#0#0#0#0#0'e6"'#218#171'nR'#255#173'qV'#255#173'qV'#255
+ +#136'YC'#255#173'qV'#255#173'qV'#255#173'qV'#255#173'qV'#255#173'qV'#255'sK9'
+ +#255'uM:'#255#159'gN'#255#173'qV'#255#173'qV'#255#173'qV'#255#173'qV'#255#173
+ +'qV'#255#173'qV'#255#173'qV'#255'5"'#27#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0
+ +#0#255'H/$'#255#173'qV'#255#173'qV'#255#153'^D'#255'Y8*'#188#0#0#0#0#0#0#0#0
+ +'c5 '#203#170'kQ'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'
+ ,#255#174'sY'#255#164'mU'#255#11#7#6#255#1#1#1#255#1#1#1#255#5#3#2#255#127'TA'
+ +#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255
+ +#128'UA'#255#2#1#1#255#0#0#0#255#0#0#0#255#0#0#0#255'J1&'#255#174'sY'#255#174
+ +'sY'#255#147'X?'#255'S8,'#140#0#0#0#0#0#0#0#0'd4'#30#153#162'gM'#255#178'{c'
+ +#255#178'{c'#255#178'{c'#255#178'{c'#255#178'{c'#255#178'{c'#255'A-$'#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#20#14#11#255'xSB'#255#6#4#3#255#5#4#3
+ +#255#18#12#10#255#170'u_'#255#178'{c'#255#178'{c'#255#9#6#5#255#0#0#0#255#0#0
+ +#0#255#3#2#2#255#166's]'#255#178'{c'#255#178'{c'#255#131'P8'#252'S3$>'#0#0#0
+ +#0#0#0#0#0'[/'#27'3'#137'T='#247#184#134'o'#255#184#134'o'#255#184#134'o'#255
+ +#184#134'o'#255#184#134'o'#255#184#134'o'#255#14#10#9#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#1#1#1#255'\C7'#255#14#10#8#255#0#0#0#255#0#0#0#255#0#0#0#255#14#10
+ +#8#255#184#134'o'#255#184#134'o'#255'xWI'#255#2#1#1#255#0#0#0#255#18#14#11
+ +#255#184#134'o'#255#184#134'o'#255#183#131'l'#255'h:&'#240#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0'n<%'#218#189#140'x'#255#190#143'z'#255#190#143'z'#255#190#143
+ +'z'#255#190#143'z'#255#190#143'z'#255',!'#28#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#9#7#6#255#190#143'z'#255#9#7#6#255#0#0#0#255#0#0#0#255#0#0#0#255#5#4#3
+ +#255#190#143'z'#255#190#143'z'#255#190#143'z'#255#159'xe'#255#0#0#0#255#140
+ +'jZ'#255#190#143'z'#255#190#143'z'#255#175'yc'#255'b6"'#193#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0'd4'#30#151#167's\'#254#196#154#135#255#196#154#135#255#196#154
+ +#135#255#196#154#135#255#196#154#135#255'qYN'#255#0#0#0#255#0#0#0#255#1#1#1
+ +#255'v]R'#255#194#152#133#255#5#4#4#255#0#0#0#255#0#0#0#255#0#0#0#255#10#8#7
+ +#255#196#154#135#255#196#154#135#255#196#154#135#255#196#154#135#255'"'#27#24
+ +#255#196#154#135#255#196#154#135#255#196#154#135#255#131'R<'#248'^1'#28'1'#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#14'o>('#224#198#157#140#255#202#163#146
+ +#255#202#163#146#255#202#163#146#255#202#163#146#255#170#138'{'#255#0#0#0#255
+ +#8#6#6#255#26#21#19#255#202#163#146#255#143'th'#255#1#1#1#255#0#0#0#255#0#0#0
+ +#255#2#2#2#255#143'sg'#255#202#163#146#255#202#163#146#255#202#163#146#255
+ +#202#163#146#255#191#155#138#255#202#163#146#255#202#163#146#255#183#135'r'
+ +#255'd5 '#193#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'd3'#30'{'#156
+ +'jS'#248#209#174#160#255#209#174#160#255#209#174#160#255#209#174#160#255#209
+ +#174#160#255#2#2#2#255#205#172#158#255#209#174#160#255#209#174#160#255#169
+ +#140#129#255#11#9#9#255#1#1#0#255#4#3#3#255#132'oe'#255#209#174#160#255#209
+ +#174#160#255#209#174#160#255#209#174#160#255#209#174#160#255#209#174#160#255
+ +#209#174#160#255#205#167#152#255'yG3'#235'[/'#27'"'#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'd4'#30#181#179#134'r'#254#215#185#173#255#215
+ +#185#173#255#215#185#173#255#215#185#173#255'm^X'#255#215#185#173#255#215#185
+ +#173#255#215#185#173#255#215#185#173#255#133'sk'#255#0#0#0#255#156#134'}'#255
+ +#215#185#173#255#215#185#173#255#215#185#173#255#215#185#173#255#215#185#173
+ +#255#215#185#173#255#215#185#173#255#214#183#172#255#143'^I'#243'b3'#29'`'#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#8'f6 '
+ +#205#189#148#131#254#222#197#187#255#222#197#187#255#222#197#187#255#222#197
+ +#187#255#222#197#187#255#222#197#187#255#222#197#187#255#222#197#187#255#127
+ +'qk'#255#134'wq'#255#222#197#187#255#222#197#187#255#222#197#187#255#222#197
+ +#187#255#222#197#187#255#222#197#187#255#222#197#187#255#220#193#183#255#159
+ +'o['#247'd3'#30#147#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0'[/'#27#15'c3'#30#193#176#132'q'#248#228#206#199#255
+ +#228#208#201#255#228#208#201#255#228#208#201#255#228#208#201#255#228#208#201
+ +#255#228#208#201#255#228#208#201#255#228#208#201#255#228#208#201#255#228#208
+ +#201#255#228#208#201#255#228#208#201#255#228#208#201#255#228#208#201#255#221
+ +#196#186#255#141']I'#237'c3'#29#129#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#2'c3'#29#150
+ +#135'XD'#231#208#176#164#255#235#219#215#255#235#219#215#255#235#219#215#255
+ +#235#219#215#255#235#219#215#255#235#219#215#255#235#219#215#255#235#219#215
+ +#255#235#219#215#255#235#219#215#255#235#219#215#255#232#214#209#255#189#149
+ +#133#253'qA+'#220'a2'#29'O'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27
+ +'"e4'#30#185#144'cO'#235#195#158#144#254#230#209#203#255#242#231#229#255#242
+ +#231#229#255#242#231#229#255#242#231#229#255#242#231#229#255#241#230#226#255
+ +#220#193#184#255#180#141'|'#251'zK6'#226'd3'#30#142'[/'#27#10#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#28'b3'#29'{g5'#30
+ +#198'xH2'#218#137']J'#229#156'r`'#236#151'mZ'#234#132'VB'#227'q?)'#213'f4'#30
+ +#182'_1'#28'W[/'#27#11#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ ,#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#5'[/'
+ +#27#30'[/'#27#22'[/'#27#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#255#252'?'#255
+ +#255#192#3#255#255#0#0#255#254#0#0'?'#248#0#0#31#240#0#0#15#240#0#0#7#224#0#0
+ +#7#192#0#0#3#192#0#0#3#192#0#0#1#128#0#0#1#128#0#0#1#128#0#0#1#128#0#0#1#128
+ +#0#0#1#128#0#0#1#128#0#0#1#128#0#0#1#128#0#0#1#128#0#0#3#192#0#0#3#192#0#0#3
+ +#192#0#0#7#224#0#0#7#240#0#0#15#240#0#0#31#248#0#0'?'#252#0#0#127#255#0#0#255
+ +#255#192#3#255#255#252'?'#255'('#0#0#0#16#0#0#0' '#0#0#0#1#0' '#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +';;;'#13'ICB7M=4zL>6xFBA;@@@'#16#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0'III'#7'W;,'#171'nC('#245#145'`+'#250#181#127'2'#253#175
+ +'z1'#253#139'\*'#250'h?&'#244'P=3'#159'@@@'#12#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0'K921d;'''#235#191#137'7'#254#249#198'E'#255#251#199'F'#255#251#200
+ +'F'#255#251#200'F'#255#251#199'F'#255#246#194'E'#255#173'y3'#253'\9)'#229'E>'
+ +';2'#0#0#0#0#0#0#0#0#0#0#0#0'>2,'#7'nC'''#238#223#171'N'#255#239#191'U'#255
+ +#240#192'U'#255#164#131':'#255'@3'#23#255'J;'#26#255'~e-'#255#196#157'E'#255
+ +#239#191'U'#255#212#159'J'#255'a<('#231'MMM'#10#0#0#0#0#0#0#0#0'[7('#183#195
+ +#145'N'#254#228#180'_'#255#228#180'_'#255#228#180'_'#255''#25#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#4#3#1#255'9-'#24#255#205#163'U'#255#175'~E'#253'Q:0'#168
+ +#0#0#0#0'[/'#27#10#143'd@'#248#219#174'l'#255#219#173'l'#255#159'~N'#255#206
+ +#163'f'#255'qY7'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1#1#0#255#152'x'
+ +'K'#255#218#172'k'#255'zQ5'#246'UUU'#3'W4$H'#178#134'_'#254#213#169'x'#255'Y'
+ +'F2'#255#0#0#0#255'L<+'#255#200#158'p'#255#8#6#4#255#0#0#0#255#0#0#0#255#18
+ +#15#10#255'pY?'#255#213#169'x'#255#213#169'x'#255#157'tR'#251'M=74^6$'#154
+ +#193#151'x'#255#179#144's'#255#6#5#4#255#27#21#17#255#155'|c'#255#206#165#132
+ +#255#130'hS'#255'=1'''#255':/%'#255#170#137'm'#255#141'q['#255#166#133'j'#255
+ +#206#165#132#255#178#135'l'#253'Q8,{c5 '#167#195#154#133#255#163#130'q'#255
+ +#153'zj'#255#192#152#132#255#199#159#138#255#200#159#138#255#201#160#139#255
+ +#201#160#139#255#201#160#139#255#154'zj'#255#1#1#1#255#29#23#20#255#197#157
+ +#136#255#181#139'v'#255'X5%|_1'#28'V'#176#132'r'#254#199#159#141#255#199#159
+ +#141#255#184#147#130#255'#'#28#25#255#27#22#19#255#167#133'v'#255#127'fZ'#255
+ +#172#137'z'#255#197#157#139#255' '#26#23#255#15#12#11#255#187#150#133#255#156
+ +'tb'#251'W1 0[/'#27#30#160'zk'#246#210#176#163#255#210#176#163#255#154#129'x'
+ +#255#0#0#0#255' '#27#25#255#152#128'v'#255#4#3#3#255'>40'#255#210#176#163#255
+ +#148'|s'#255'RD?'#255#210#176#163#255#140'fW'#243'[/'#27#2#0#0#0#0'tI6'#209
+ +#216#188#178#255#221#195#185#255#213#188#178#255'$'#31#30#255#131'sn'#255'sf'
+ +'`'#255#0#0#0#255'eYU'#255#221#195#185#255#221#195#185#255#204#180#170#255
+ +#207#178#166#255'k>+'#182#0#0#0#0#0#0#0#0'[/'#27#31#156'xi'#240#232#213#207
+ +#255#232#213#207#255#180#165#161#255#232#213#207#255#182#167#162#255'ICA'#255
+ +#226#207#201#255#232#213#207#255#232#213#207#255#231#213#206#255#134'_O'#233
+ +'[/'#27#12#0#0#0#0#0#0#0#0#0#0#0#0'd3'#30'e'#171#139'~'#240#239#226#224#255
+ +#242#231#229#255#242#231#229#255#240#229#227#255#242#231#229#255#242#231#229
+ +#255#242#231#229#255#235#221#216#255#153'uh'#236'a2'#29'?'#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0'\0'#27'*'#131'\I'#215#212#191#183#252#239#229#226#255
+ +#253#250#252#255#253#249#250#255#236#223#220#255#204#180#172#250'yM;'#196'[/'
+ +#27#23#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#3'[/'
+ +#27'>c3'#29#131'uI4'#190'oA-'#183'b2'#29'v[/'#27'4'#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#248#31#172'A'#224#7#172'A'#192#3#172'A'#128#1#172'A'#128#1#172
+ +'A'#0#0#172'A'#0#0#172'A'#0#0#172'A'#0#0#172'A'#0#0#172'A'#0#0#172'A'#128#1
+ +#172'A'#128#1#172'A'#192#3#172'A'#224#7#172'A'#240#31#172'A'
+]);
+
diff --git a/branches/script-component/Projects/MufasaTests/project1.manifest b/branches/script-component/Projects/MufasaTests/project1.manifest
new file mode 100644
index 0000000..07fb624
--- /dev/null
+++ b/branches/script-component/Projects/MufasaTests/project1.manifest
@@ -0,0 +1,17 @@
+
+
+
+ Your application description here.
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/branches/script-component/Projects/MufasaTests/project1.rc b/branches/script-component/Projects/MufasaTests/project1.rc
new file mode 100644
index 0000000..783815b
--- /dev/null
+++ b/branches/script-component/Projects/MufasaTests/project1.rc
@@ -0,0 +1,7 @@
+#define RT_MANIFEST 24
+#define CREATEPROCESS_MANIFEST_RESOURCE_ID 1
+#define ISOLATIONAWARE_MANIFEST_RESOURCE_ID 2
+#define ISOLATIONAWARE_NOSTATICIMPORT_MANIFEST_RESOURCE_ID 3
+
+CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "project1.manifest"
+MAINICON ICON "project1.ico"
diff --git a/branches/script-component/Projects/OCRBench/project1.ico b/branches/script-component/Projects/OCRBench/project1.ico
new file mode 100644
index 0000000..0341321
Binary files /dev/null and b/branches/script-component/Projects/OCRBench/project1.ico differ
diff --git a/branches/script-component/Projects/OCRBench/project1.lpi b/branches/script-component/Projects/OCRBench/project1.lpi
new file mode 100644
index 0000000..ecec126
--- /dev/null
+++ b/branches/script-component/Projects/OCRBench/project1.lpi
@@ -0,0 +1,369 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/branches/script-component/Projects/OCRBench/project1.lpr b/branches/script-component/Projects/OCRBench/project1.lpr
new file mode 100644
index 0000000..d75af6c
--- /dev/null
+++ b/branches/script-component/Projects/OCRBench/project1.lpr
@@ -0,0 +1,21 @@
+program project1;
+
+{$mode objfpc}{$H+}
+
+uses
+ {$IFDEF UNIX}{$IFDEF UseCThreads}
+ cthreads,
+ {$ENDIF}{$ENDIF}
+ Interfaces, // this includes the LCL widgetset
+ Forms, Unit1, LResources, fontloader
+ { you can add units after this };
+
+{$IFDEF WINDOWS}{$R project1.rc}{$ENDIF}
+
+begin
+ {$I project1.lrs}
+ Application.Initialize;
+ Application.CreateForm(TForm1, Form1);
+ Application.Run;
+end.
+
diff --git a/branches/script-component/Projects/OCRBench/project1.lrs b/branches/script-component/Projects/OCRBench/project1.lrs
new file mode 100644
index 0000000..2747aa9
--- /dev/null
+++ b/branches/script-component/Projects/OCRBench/project1.lrs
@@ -0,0 +1,5237 @@
+LazarusResources.Add('MAINICON','ICO',[
+ #0#0#1#0#6#0#0#0#0#0#1#0' '#0#226#145#0#0'f'#0#0#0#128#128#0#0#1#0' '#0'('#8#1
+ +#0'H'#146#0#0'@@'#0#0#1#0' '#0'(B'#0#0'p'#154#1#0'00'#0#0#1#0' '#0#168'%'#0#0
+ +#152#220#1#0' '#0#0#1#0' '#0#168#16#0#0'@'#2#2#0#16#16#0#0#1#0' '#0'h'#4#0#0
+ +#232#18#2#0#137'PNG'#13#10#26#10#0#0#0#13'IHDR'#0#0#1#0#0#0#1#0#8#6#0#0#0'\r'
+ +#168'f'#0#0#145#169'IDATx'#218#236']'#5#128#28#245#213#127#235'n'#231'w9I.N'
+ +#136#144#4#139#17#220'['#220#221#138';!'#184'|'#180#148#2#197'Kq'#13'R('#20
+ +'(V'#180#197#3#9'!'#144#144#16#187#156#219#202#173#251'~'#239#253'gfo'#246'r'
+ +'~'#187';{'#242#131#201#236#173#204#204#202#251#253#159'?'#25#140'a'#12'c'#24
+ +#181#144'I}'#1'c'#24#195#24#164#195#24#1#140'a'#12#163#24'c'#4'0'#134'1'#140
+ +'b'#140#17#192#24#198'0'#138'1F'#0'c'#24#195'('#198#24#1#140'"'#140#155'}2}'
+ +#223#6#220'L'#184#25'q'#11#227#230#161#173#225#167#21#17#169#175'o'#12#217
+ +#199#24#1#12'c'#160'@'#155'q7'#21#183'i'#184'M'#198#173#8'8'#225'N'#217'd2'
+ +#153'p'#155#132#191#167#239'<'#132#155''''#145'H0B'#224'7'#175#232'v'#7'n'
+ +#219'p'#219#128#219'F'#220'j'#145'4'#18'R'#127#6'c'#24#26#198#8' '#199#129'B'
+ +'.'#199#221'x'#224#132'|'#170#176#161'P'#211#223'%='#189'N'#214#195'7+'#235
+ +#230'+O@'#207'r'#156#232#249#161#0#146#197'&'#232'$'#132#228#134#196#224#145
+ +#250's'#27'C'#255'0F'#0'9'#6#20'x'#18#234#189'q'#219#7#183'=P'#208'ie'#215
+ +#136#159'#'#22'nA'#160'e'#194#157#226#199'DO'#20'nwG'#12'b!O'#240#127'$R'#238
+ +#236#230'q'#209#157']I'#2#159#211#136#187#181#184'}'#198'o'#171#145#20'bR'
+ +#127#182'c'#216#17'c'#4' 1P'#224#11'p'#183#20'8'#161#223#27#5'u'#186#240'X'
+ +#167'L'#239'('#228't'#155#219#0#228#244#12#185#140'{'#158#140'{'#157#140#191
+ +'!'#235#250'|'#232'<'#166' '#196#130#252#146'ps'#27'pRM'#255#203#184#191#197
+ +#143#209#235#196#247'AbGb'#232'B'#10#29#248#248#255#160#147#16'~'#26'3'#31'r'
+ +#3'c'#4#144'e'#160#192'[p'#183#23#240#171'<'#10#229'L'#224#191#7#177#192#203
+ +'8)'#6#185'\'#158#20'h'#185#156#187'_.'#227#4#158#30#163#219#10'z'#142#188
+ +#203#227#252#30'D'#247#201#21#10#220'+AF{P@\'#22#135'D,'#134#194#26#131'8'
+ +#238#227#241#24'/'#216'qn'#31'O'#0#222#194#251#241#223'8@'#28#255#137#199#185
+ +#191#227#137#4#187#157#224#239'#'#2#136''''#186''''#134'nH'#193#129#247#127
+ +#14''#193#238#139#11'['#146'(R'#9#161#139#217'A&'
+ +#195#10#220#158'G2'#248'E'#234#239'k4a'#140#0'2'#4#20'z%'#238#246#7'N'#232
+ +#127#143'{'#29#221'/'#172#230#226#21'^,'#240'$'#172'$'#224'J'#165#2#148#180
+ +'W)A'#163#214'3'#1#215#144#176'ku'#160#209#242'B'#175'V'#129#10#159#175'T'
+ +#202#217's'#233'u'#10#185'p'#172'.'#26#129#130'3'#21#184#251#216#149'p'#23
+ +#202'Vn'#224'Vo'#129#4#226#156#128#198'x'#1#142#197'8'#161#142'E'#19#16'E!'
+ +#143'D'#227#16'Eb'#8'!'#9#132#131'~n'#11's'#251#16'#'#135'0>/'#134#207#225'6'
+ +#129#16#24'A'#136#8#129#206#215'U;'#192#251#215#224#238#5#220'^B2h'#150#250
+ +'{'#28#233#24'#'#128'4'#3#5#127'.'#238'N'#197#237'D'#20#190'b'#186'O,'#244
+ +#130#170#174#144#209'*.c'#2#175#228#133'^'#173'T'#162'P'#171'Ao'#178#130'^o'
+ +#3#157#209#10'Z'#29#10#187'J'#129#171'=nL'#208#233#182#156#221'V)'#21#201'=#'
+ +#11'%G'#0'D$r9g'#247#211#185#146'&'#3#179#8'd)'#206'AnE'#134#20'5'#30'e'#149
+ +#187#29#231'6"'#128'h'#156#132'9'#158'$'#128'H'#132#246'1'#238#182'h'#31#198
+ +'}8'#24#130#128#175#3#252'^'''#248'}N'#8#5'}'#236'1'#129#16#162#177#174#132
+ +#16'g'#218#1#153#24#220'5'#177']'#12#175#225'c'#224#200#224'M$'#3#191#212#223
+ +#237'H'#196#24#1#164#1'('#244#21#184';'#25#183'SQ'#184'v'#162#251#186#21'z~'
+ +#133#231'Vv'#18'^'#20'x'#149#10#244'('#232'z'#163#13#12#6#220#27#204#184#226
+ +#227#170#175'Q'#130'V'#173'`'#194'O'#127#171'U'#188#192#171':'#133'^'#197#142
+ +#195#173#254't'#31'g&p'#171#127#210#148#160#235#224#29#132#130#250#159#18#9
+ +#224#205#0#178#245#133#21#153#217#251#252#223'$'#155'$'#160#209'8'#183#250'w'
+ +#146#0#10'2'#145#0#222#14'G8'#2#160'=m'#161'H'#20#205#132#24#4#195#220#237'@'
+ +' '#0'~'#143#139#145#1#145'B'#136#204#8#188#159'#'#131#24'gJ'#224'qbq'#193
+ +#223#176#131#153#224'E2'#248'''pd@>'#131#184#212#223#249'H'#193#24#1#12#1'('
+ +#248#243'pw='#10#219#17#192'-'#174#12'rN'#210'8'#149'\&O'#170#244'*'#21#9#178
+ +#146#9#188#193'd'#195'}'#30'nf'#208'jT'#160#19#132#30'7'#29#19'~%G'#4'<'#9
+ +#168#149#220#202'O'#171'<'#169#253#10#165#12#148'ra'#213#167's'#164#10'>]'#2
+ +'wA'#188#192#11#209#129'D*'#1'$U'#239#164'g'#159#255#139#183#215#227#188'3P'
+ +#16#206'(o'#14#16#9#196#4'2Hj'#5#164#1#160#208#147#224#135#163'l'#31#8'E!('
+ +#222'P'#240#253'>'#31#4#188'.'#240'!'#25#248'<'#14'4'#27#130#248#218'(#'#5'F'
+ +#4#140#12'x"'#232#226'3'#192#191')'#25#233'/'#184'='#131'D'#16#146#250'70'
+ +#220'1F'#0#131#0#10#254'"'#220#221#128#194'v'#16#253#157'\'#237'y'#207''#198#147'BLl'#30#136#136#0#133'>'#16'N%'#1#250
+ +';'#16#196'-'#20#129'` '#2#30#183#3'<'#174'f'#240'x'#218'Q;'#8'32 '#13'C'#236
+ +'d'#20'L'#4#17#17#144#227#240'^'#220#30'C"'#240'I'#253#155#24#174#24'#'#128#1
+ +#0#5#159#156'z7'#162'0-'#161#191#185#24'<-'#181#220'j'#159'j'#203#163'0'#235
+ +'t`'#182#20#131#201'V'#2'F'#147#25#244'Z'#21#24'p'#163#189'^G'#130#174'b'#194
+ +#175#21'V|'#141#130#9'='#17#6#19#252#164#131#143#183#229#153#195#16'D6='''
+ +#224#178#174#241#254'.'#215'-'#147#13#236'k'#22''''#1#137's'#4#128#251#159'#'
+ +#2#193'THtF'#16#146#132'@'#26'B$'#158'4'#11'B'#145'N'#141' '#200#147'A '#24#1
+ +'?'#146#128#31'I'#192#239#167#219#184#5#130#224'v'#181#129#219#217#194'i'#6
+ +','#242#16'c'#14#199#164#137#16#139#167'h'#5'x'#187#29'/'#233'~'#220#30'F"'
+ +#232#144#250'72'#220'0F'#0'}'#128'/'#160#249#29'p+'#254#174't'#31#23'^'#239
+ +#12#209'1!Ur'#234#189'V'#171#1#147#165#136#173#244'&K'#30'/'#236'j0'#232'T'
+ +#201'M'#199#147#128'V'#195#169#248#156#208'+83A'#201#31'O.'#178#231'{'#17'v'
+ +#254'&'#183#239'A'#208#7'"'#255'='#165#254'v%'#133'D'#167#154#176#3')p^'#255
+ +#4#243#27#196'D'#142'C'#210#10#194#188'_'#128#153#7'A'#142#8'|'#129'0n'#17
+ +#182#249'i'#143'Z'#128#23#205#4#15#18#1#145#129#223#239#193#215'E'#153'f'#192
+ +#162#11#188#19#177#139#175#128#146#141#30#193#253'}H'#4#237'R'#255'n'#134#11
+ +#198#8#160#7#240'9'#248#199#1'g'#227'S'#178#206#14#130#175#18#236'z\'#189#13
+ +'&+X'#243#199#161#224#23#162#144#235'P'#232'U`'#228#5#158#8#192#168#231#132
+ +'^'''#8'>'#9#189'Z'#145't'#230'q'#26#132'8'#254'/J'#254#17'.'#170#15'u>['#232
+ +#202#17']'#201#128#249#14#4#13'A'#228'?`'#209#4'2'#17'b'#228','#140'32 '#159
+ +#0#167#13#136#8#0'5'#2'/'#146#130#159#255#219#227'qA'#135#179#25':'#28#141'h'
+ +'R'#132'92Hj'#5';'#16#129#31#207#255#24#238#239'A"h'#148#224#227#25'V'#24'#'
+ +#128'n'#128#194#191#27#238#30'EA'#163#144'^'#138#224'+yU_'#141'6'#188#6'7'
+ +#163'9'#15'l'#133#149'`'#177#230#163#176#227'J'#143#130'n'#212#171#217'mN'
+ +#232#213'('#244'h'#235'k95_'#205'<'#250#188#7'_'#217#25#183#239'N'#173'g'#231
+ +#22'.j8|S]'#202#7'RR'#135'E'#230'B,'#193#231#20#240#161'Cf"'#136'|'#3'$'#244
+ +'^A+'#240#163'6 '#236'}~p'#180#213'!'#17'4'#224#243#130#140#8':#'#9#169'D'
+ +#128#231#14#224'%'#220#137#219'_'#198#156#133'=c8'#252#172#178#6#20#252'<'
+ +#220#221#137#194'w.'#240'2'#152'"'#248#188#154#175'A'#219#221'd)`'#130'oE5'
+ +#223'hP3'#161'7'#25'4L'#232#13#188#202#159#180#241#153#224#139#156'y'#188'z/'
+ +#8#190'8'#127'?'#165#208'g'#128#182'{'#174#161''''#167'b2'#225#136'O2'#226
+ +#180#2'!'#140'H>'#130'X'#167#143#0#137#192'C'#194#207#8' '#12'n'#220'{'#188
+ +'~p'#182#215#131#203'^'#15'A'#127#144#249#10'z!'#2#170'X'#188#24'I'#224'?R'
+ +#127#30#185#136#225#253#11'K'#19'x;'#255','#220#238'B'#161#203#23#156'{2'#133
+ +#160#234's+'#183#22'W|'#147#181#8#242#138'+'#193'l'#182#129#137#9'='''#248'&'
+ +'#'#238'Q'#240'uL'#229'W'#177#24#190#134'9'#243'RU|qr'#14#8#222'z'#254':d#'
+ +#248#235#216#161'z0'#25'f'#228'3'#17#197'&'#2'i'#5'Q^+ '#18#8'F'#152#22#224
+ +#245#133#192'C$'#224'#R'#8#129#215#27#0#167#189#1#156#168#21'P'#174'A('#140
+ +'D@9'#9'T'#215#192';'#11#227#157#213#141#175#225#238#10'$'#130#6#169'?'#139
+ +'\'#194#200#253#197#245#19'('#252#187#224#238'o('#152'{'#136#195'y,'#227#142
+ +'6'#18'|T'#227'-'#214#18#176#21'U'#160#224'['#153#208#155'I'#232'y'#225'g'#26
+ +#128#150#19'|q'#248'N'#156#158'+'#8'>'#147#249#212'z'#222#209#9'Q'#232'1'#233
+ +'7'#224#137#128#204#132#8#159'tDQ'#0#166#17#132#200'9'#136#155#143#211#8#220
+ +'H'#6'D'#4#28')'#4#145#8#26#145#8'j'#193#239#247'!qt'#18#1#167'm'#196#5'm'
+ +#128#26#156#220#138#219#3'H'#4'Q'#169'?'#130'\'#192'h'#253#249#9'Uyw'#160'0^'
+ +#128'{'#133#160#238#179'"'#27#222#185'G'#9':'#228#205'/('#169'F'#193'71a'#239
+ +'I'#240#5#199#30'K'#203'U'#202'S'#236'zN'#232#187#177#235#199#176'C'#30'BB'
+ +#172#25#176#236'CN+'#8'G'#163#157'D'#192#251#4'8m'#128'#'#2#143'@'#4'm'#13
+ +#224'h'#169'A'#205'!'#192#136' '#194#155#6']'#204#2'*8'#186#16'I'#224#11#169
+ +#223#191#212#24#149#191'E'#20#254'Spw'#15#229#234'''Km'#21'|J-+'#190'A;'#222
+ +'hB'#193#159#4#182#252'"&'#244'f#'''#252'f^'#240#13#188'W_'#219'e'#197'O&'
+ +#231#240'R'#223#25#162#147#250']'#231'>D'#193#4'n/'#242#21'$S'#144'{'#210#8
+ +#188'!'#232' '#18#160'}'#135#23#218#155#183#130#203#217#4#193'`'#152#249#21
+ +#136#8#226#172#246' %'#153#232'y'#220']'#141'D'#208'&'#245'{'#151#10#163#234
+ +'g'#137#130'O'#141'0'#31'G'#193'?'#145#254#22'Vh'#5#191#234#171'U*'#180#225
+ +'5'#204#185'WP2'#30','#6#29'XL'#26#176#24'9'#2#160'U'#159#9#190'F'#136#225'+'
+ +'9'#167#30#139#219#11'y'#255'\'#213']'#231'''<'#170'>'#226#244'A'#228'@L@gM'
+ +#2#249#9'"'#2#17#136#162#6#130'Y'#208#225#9'22'#160#205#225'h'#135#246#166'M'
+ +'H'#10#29#156'6'#192#242#8#226#156#127#160'S'#27#160'P'#225#137'H'#2#255#147
+ +#250'-K'#129'Q'#243#235'D'#225#159#141#187#127#160#144'N'#17'V}'#5#159'i'#199
+ ,#169#251'h'#215'['#11#160#176't2'#218#251'f&'#244'V'#163#22#204'D'#0#6'-S'
+ +#251'){'#143#4#159#203#244#227#146'u'#196'e'#183'];'#248#140'a'#232#16#151#11
+ +#11#230'A,'#193#167#30'G'#184#228'"'#230','#196#205#195#155#5#29#222' '#18'A'
+ +#136#237#221'H'#8#237#173#181#224'l'#217#14#254'`'#16'B'#225'0'#159'f'#28'Oj'
+ +#24#192'U'#30#222#130#251';G['#161#209#168#248#165#162#240#159#135#187#7'PH'
+ +#181'2'#190#6'_H'#217#165#144#158#222'`'#196#21#127'"'#228#229#151#178#149
+ +#158'V}+['#249'9'#193'7'#232#213'l'#213#167#172'='#242#234's'#9';\'#201#173
+ +'Pp'#195'>'#204'Q'#241'iJ'#131#206'DDn'#229'N'#166#31#147'F'#16#229#170#16')'
+ +#143#128#210#138#189#188'I'#224#18#17'A'#135#219#11'mM'#155#161#195#209#130
+ +'&'#4#146#0'%'#19#9#209#130'Nm'#224'#<'#193')H'#2#173'R'#191#223'laD'#255'd'
+ +#249'N<'#143#137'U~'#193#214#167'D'#30#29#174#250'yE'#168#238#23'O'#0#179'Y'
+ +#199#4'>'#185#242#27'9[_H'#217'e'#169#186#138#212#226#155#222#26'm'#142'!3'
+ +#224#139#21#147#14#195'd>A'#148'K7'#230'2'#11'9"'#224#28#132'H'#4'n$'#0#242
+ +#13#144'Y`o'#133#246#230'M'#224#243'x:'#181#129'h\'#28')h'#194'3'#156#140'$'
+ +#240#153#212#239'5'#27#24#177'?]^'#229#127#141#186#234#138'='#252#172#180'VE'
+ +'N>#'#148#148#239#4'V[>'#191#226'k'#25#1#144#202'O'#241'}'#178#245'uj~'#213
+ +#23'j'#237'E^}'#246#225#141#216'O/'#247#145'$'#2#232#236'AH)'#199'Q'#190#0
+ +#137#10#142#168#208#200#231#227#136#128#132#223#229#9'2'#31'A'#135''''#0#173
+ +#13#191#177#208'a'#144'O-'#142'&C'#134#236#200#184'K'#220#142#251#255#27#233
+ +'&'#193#136#252#9#163#240#255#1'w'#247#139'U~'#174#147#14#197#244'U`'#177#21
+ +'Cq'#249'4'#176#153#13'('#252'Z&'#252#164#242's'#153'|\'#234'.'#173#250'\5'
+ +#30#223'aG&'#235'6'#23#127#12#210'"'#145'd'#1#224#27#152#242'D'#16#137#179
+ +#162'#"'#2#31#239'$'#228#132'?'#4'N'#158#8#236'm'#13#208#214#248#27'j'#11'A'
+ +#150'D$D'#10'D&'#193#167#192'i'#3'#'#182'5'#217#136#250'%'#243'*?y'#249'O'
+ +#160#191#197'*'#191'FM'#130#173#129#252#210'j(,'#169'bj'#190#213#162#5#155'I'
+ +#155#12#241#137#227#249'B'#18'Ogn>$k'#236#199#144'['#160#214#229#157#185#4
+ +#188'Y'#192#218#152'qY'#133#212#153'('#192#215#23'0'#223#0#145#128';'#128#166
+ +#1#238#157'Nh'#169'_'#15'^O'#7#231#27#216#209'$h'#1#206'/'#240#177#212#239'3'
+ +#19#24'1'#191'f'#20'~'#26#139#245#30#10#255#188#174'I=\\'#159'T'#254#25'`'
+ +#203#207'c+'#190#205#164#3#171'Y'#203#135#247#212#172'XGH'#221'e'#13'7'#146
+ +#234#190'h'#229#151#250'M'#142#161'G'#136'|'#132#220','#131'8'#223#201'('#193
+ +'7)'#9'sNB'#210#6#220#188'9@'#190#1#167#155#246#254#164'I'#16#224#27#146'DY'
+ +#155#244'$'#9'P'#214#224#217'H'#2#207'K'#253'>'#211#141#17#241#155'F'#225#159
+ +#128#187#255#160#240'O'#18#132#159'b'#243#228#229'gi'#188#182'"T'#249#167#163
+ +#192#163#202#143'B'#159#135#155#133'_'#249#141'|}'#190#154'o'#192'A'#141':'
+ +#229'2Q'#231#220#17#241#9#141'B'#240#13'L'#200#128#23'Z'#153#9#185#3'T['#224
+ +#241#134#185'('#1'j'#1#14#212#6#220#168#21#180#183#212'C['#243'&'#214#152#132
+ +#202#142#133#156#1#222'/'#128'<'#144'X'#134'$p'#143#212'o-'#157#24#246'?o'
+ +#222#217#247#1#10#127#137#216#222#167#226#29#157'V'#203#210'x'#11'H'#229''';'
+ +#223#204#169#252't'#155'e'#243#233':='#252#201#10'='#161':O'#234'76'#134#161
+ +'#'#193#165#26#11'-'#200#163#188#147#144#186#19#177#188#1'_8'#169#13'8'#153
+ +'F'#16'@'#147#160#3'Z'#234#214'1'#147#128#146#135'('#5'YD'#2't'#172#187'qw'
+ +#237'H'#153'l4'#172#127#231'('#252'4a'#231'-'#20'~'#139' '#252','#163#143'T~'
+ +#131#1#138'+f@^^A'#167#224#155#185'0'#31#9'?+'#213#229#227#250'B'#231#29#232
+ +'R'#142';'#134#145#1'q'#163#211'd'#164' '#202#165#19#11#225'Br'#14':'#220#28
+ +#9#208#214'Z'#191#1'\'#246'&'#212#24#194','#170#16''''#191#0'$M'#130#231#240
+ +#128#231#140#132#130#162'a'#251'sG'#225'?'#10'w/'#161#240'k'#132#240#28#169
+ +#252'j'#170#213'7'#153#160#164'r6'#216'lff'#235#219#204#218#164#189'/'#180
+ +#228'R'#243#173#183#200#209''''#212#225#143#9#255#200#133#144'H'#148'lJ'#130
+ +'&A'#24#237#252#16'_n'#204#162#4'nN'#27' '#147#128#162#4'-'#13#155#192#209'Z'
+ +#203#234#9'('#162' '#174'%@'#18#248'7'#30#238'8$'#129#128#212#239'm('#24#150
+ +'?y>'#204'G%'#188'r'#193#211'/8'#251#168#15'_i'#213'L'#176'YM'#144'G'#206'>'
+ +#139'.'#25#226#211#179'&'#29#202'd'#223'='#161'D'#151#251' '#134#229'G1'#134
+ +#1'B<'#216'Th^J+'#188'@'#2'd'#18#144'c'#208#217#17'`'#251#182#230#237#208#214
+ +#180#9#130#129'03'#7#186'D'#8#190#194'C'#30#142'$'#224#148#250'}'#13#22#195
+ +#238'W'#143#194#127'3'#10#238'mt['#16'~5_'#193'g'#177#22'@i'#229'L'#176'Z'
+ +#245'L'#240#137#0#200#233#199#132#159'o'#201'%'#30#160#193'>'#128#177'e'#127
+ +#212'A<'#2']'#156''
+ +#129#253#135#147'c0'#231#197#1#133#159#198'o'#189#141#178#175#18#219#252':'
+ +#173#26#10#203#166'@Aq%'#243#240''''#133#159'<'#253'$'#252#201#10'>'#174'tW6'
+ +#22#219#135#223#29'0'#11#2#254#29#167'hi'#181':'#184#231#161#151'`'#234#244
+ +'YR_'#162'd'#224'9 '#233#23#136'D'#184#209'f'#228#28'd'#21#133#148''''#208#17
+ +'d'#161'B'#167#203#141'$'#240#19'x<'#29#221#145#192';x'#168'#'#145#4'bR'#191
+ +#167#254' '#167'e'#130#239#207#255')'#10#191'A,'#252#180#242#23#148'N'#130
+ +#162#210#241'I'#225#23'r'#250#5#225#231'Fi'#203'E='#249'r'#250#173'f'#5''''
+ +#31#181#16#218#219#186#175'kQ('#148'p'#239'#'#175#192#244#25#187'H}'#153#146
+ +'AhP'#10#2#9'D'#185#225'%b'#18'pv'#8#155#27#154'j'#214#128#215#227'fm'#201
+ +#187'8'#6#159'F'#2'8['#234#247#211#31#228#172'T'#160#240'O'#193#221'W('#184#5
+ +'B'#146#143' '#252#249'EU'#156#205#207#132#159#203#235'gi'#189'z.'#179#143#28
+ +#131#138#148#148'^'#24#157'F'#127#23','#191#252#20#248'i'#245#183'=>N$p'#215
+ +#131'/'#194#140#153#243#165#190'T'#233#144#28'f'#2#201#129#167'D'#2#212#127
+ +#144#230#18#8'$@'#230#128#195#233'B'#18#248#17'|>'#127'2:'#192'&'#21'q'#14
+ +#198'?#'#9'\'''#245#219#233#11'9)'#21'('#252#165#184#251#26#133#127#188'8'
+ +#195#143'9'#252#10#199'AI'#197'N,'#185''''#143#247#246#179#236'>'#157#154#13
+ +#215'd'#194'/j'#211#149#179'oR'#2#216#219'Z'#224#180#227#150#224#15#180#231
+ +#18'w'#185'B'#1'w'#222#251'<'#204#156#179#155#212#151'+'#9#196#195'P'#133#206
+ +'CD'#2'!VC'#16'e'#221#135#133'""'#202#21' '#199' i'#2#1#170#31#160#241#230
+ +#204#28'H'#8'$@s'#8#238#151#250'='#245#134#156#147#13#190']'#247#255'Pxg%'
+ +#133#31#127#148#26#190#168#167#140#226#252#164#242'S'#156#223',R'#251#213'JP'
+ +#170#184'>}c!'#190#158'q'#255']'#215#194''''#31#190#217#235's'#228'r'#5#252
+ +#249#129#21'h'#14#204#149#250'r%'#133#16'*'#20'r'#5'h'#132#25#149#21#139#205
+ +#1#210#4#236#237#173#208#178#253'g'#8#132#130#140'('#132#218#129#4'7R'#249
+ +#148#134#159'^zI'#234#247#210#19'rJJP'#248#201#21#253#17#141#223#22#170#250
+ +#148'|'#134#159#217#146#7'%'#19'fC'#158#201#0'6'#171#150#197#250#217#202#143
+ +#194#175#213'(S'#187#246#228#212#187#202'-'#196#227'Q8'#254#176'y'#16#194#31
+ +'ko'#208'hu'#240#220'k_'#130'^o'#148#250#146'%'#133#216'1('#152#3#204''''#224
+ +#237'L'#27'&'#231' '#151','#180#129#235'0'#20'I!'#129#8#30#225'0$'#129#156#28
+ +'M'#150'S'#162#130#4#240#16#10#255#197#226#146'^'#141#138'r'#251'-P:a'#23'\'
+ +#249#141'l'#213'g'#194'o'#226'V~-'#133#250'D'#243#246'r'#234#13#229'('#222
+ +#254#231#179#240#244#223#255#220#231#243#202'+'#171#225#225#167#222#147#250
+ +'r%Grr'#17#175#9#4#187#144#128#144''''#208#218'T'#3#246#166#205#157'$'#208
+ +#217'O'#192#145'H'#196'vi\'#251'J'#173#212#239#165'+rF^'#248#226#158#127#138
+ +#19'}'#168'A'#7'5'#242'('#173#154#11'y63W'#213#199#215#242#147#195#143'*'#250
+ +#132#129#28#178#177#149#127'@8'#251#132'%'#224't'#244'='#15'c'#191#131#143
+ +#133#11#175#184']'#234#203#149#28'B1'#17'9'#249'"|'#187'1.O '#204'J'#137#137
+ +#4':P'#19'hi'#220#4#246#214#237#16#162#198'"'#169'ME'#190#142#4#28'K['#127'{'
+ +'?"'#245'{'#17'#''D'#134'o'#232#241'#'#149#245#10#225'>'#18'~'#157'^'#15#165
+ +#227'w'#1#155#205#154't'#248'Y'#153#218#175#225#235#248';'#213'~!'#183#127#12
+ +#253#195'/?}'#7#183',;'#163'_'#207#189#234#134#251'`'#193#146#131#164#190'd'
+ +#201#145#28'Y'#22#227#204#1#210#4'|B'#155#177'dw'#161' 4'#213#173#131#14#190
+ +#148'85<'#24#191#27'M'#129'k!e'#144#186#180#144'\jx'#187#255'K'#20#254']'#187
+ +#134#251#138'+w'#134#130#130#210'd'#172#191#179'}'#151#138#235#207#207#183
+ +#232#22#6'}'#140'a`8'#239#228#165#168#5#244#221#2#159#194#131#15'='#253#1#20
+ +#22#149'I}'#201#146#131'K'#27#230'5'#1#190#185#8'M.'#166#218#1#18'~'#135''''
+ +#192'Z'#140'5m'#253#17''
+ +#202#242'3'#25#185#149#159#230#241'q'#133'=\'#168'Oj'#6#251#237#215#31#225
+ +#230'kNM'#185#143'H'#224#222#199#222#134#210#210'*'#137#175#174'wl\'#183#26
+ +'n'#185#246#180'~?'#127#238#174'{'#193#178'['#30#145#250#178's'#2#180'|s-'
+ +#200#169#187#16#154#3'An"'#17#235','#212#17#20#149#17#175'Ov'#27#22#249#3#190
+ ,#12'y['#246'n'#223#242#177#228#29#133'$'#147#31#20'~'#146#14#178#251'm'#226
+ +'4_='#218#253'e'#19#230#161#221'oa'#130#207'9'#253'h'#229'W'#179#22'^\I'#175
+ +'<9r[j'#220'y'#243'y'#240#243#143#223#236'p'#127'qi'#5#220#247'xnz'#208#219
+ +'['#155#224#213#23#30#128'5?|'#1'>'#175'{@'#175'='#243#130#27'`'#255'CN'#144
+ +#250'-H'#14'![0'#193#135#7'I'#192'i"'#145#208'^'#140'5'#20'Am'#160#185#238'W'
+ +'p'#182#215'C8'#196'u'#26'&'#194#224#15'pg'#253'O+n'#0#137'M'#1'ID'#8#133'_'
+ +#5'\'#178#207#30#226'L?'#157'F'#3'E'#21';'#163#250'_'#146'l'#229'%T'#246'Q3'
+ +#15#214#194'K)'#227#166#239#230#130#244'#'#206'8z.D#;:v'#149'J'#21'<'#251#198
+ +'j'#169'//'#137'p8'#12#239#188#254#4#252#247#227'7'#193#209#222'2'#232#227
+ +#200#240#187':'#253#188#235'`'#191'1'#18'H'#166#13#11#227#203'Y'#162#144'P7'
+ +#144#236'%'#224'GS`5x'#221#174#29#252#1'h1'#30'R'#183'f'#197#135' !'#9'HE'#0
+ +'w'#161#240'/'#163#219#10#161#139#175'F'#9#249#133#227#161#168'|2o'#247'wv'
+ +#239'e'#225#190'd'''#159#220'q'#248#213'l^'#15'7]'#221#179' <'#241#202#183
+ +#160#213#234'%'#189#198'`'#208#15#127#185#245#15#176'y'#227#207#189#166#0#15
+ +#20#147#167#205#134#229#183'?'#1'j'#181'V'#210#247'''5'#18#162'a'#165'\'#142
+ +#0'?{'#128'H'#128#138#134'<\'#205'@'#179#216#31#208'i'#10#180'i'#212#138#217
+ +'['#191#127#190#25'$"'#129#172'K'#18#10#255#28#220#253#128#4#160#16#199#251
+ +#141'f'#206#238#183#176#6#158#188#221'o'#224'j'#250#233'q*'#238#145#201'd9'
+ +#21#239#127#255'_'#207#193'+'#207#253#181#199#199#175#189#237'q'#216'i'#214
+ +#238#146']'#223#166#13'?'#193#221'('#252#161'Pf'#202#211#213#26'-\t'#245#221
+ +'0g'#254#18#201#222#163#212'H$'''#18#9#21#132#220'\'#194'dk1'#26'C'#198'g'#10
+ +#182'5n`'#13'F'#187#148#15#191#220#240#211#10#234'w'#193#15'8'#203'.'#178'*J'
+ +'('#252't'#190#175#197#170#191'`'#247#151#140'G'#187#223'jN'#246#239#167'Q]'
+ +#212#193'W'#173#22'M'#229#205#21#201#231#241#183'{'#151#193#247'_'#247#156
+ +#225'y'#197#13#15#195#172#185#139'$'#185#182#230#198#237'p'#253#165'G'#166'u'
+ +#213#239#9#187'.'#216#31'.'#188#234'nI'#222'g'#174'@('#30'bN'#193#8#231#15
+ +#160'Qd'#212'i'#216#201#166#19#147'?`='#184#218#27'v('#26#146#203#18#251#213
+ +#173'y'#137#166#17'g'#157#4#178'M'#0#231#2'7'#187#143#169#254#148#234#171'U'
+ +#171'Q'#237#223#9#237#254'q,'#212'G'#4'@'#19'z'#141#186'N'#187'_'#220#202'+'
+ +#151'p'#203'U'#199'A}'#237#166#30#31'?'#245#188#27'a'#233#254'GKrm'#203'/:'
+ +#12'W'#157#236#181#168'3'#154#173'p'#205#205#143'Cy'#213'dI'#222'o.@p'#10'F'
+ +#226#220'(2'#214'iX(!&'#18#240#248#161'q'#235#15#224#247'y'#216'0R'#145')'
+ +#176#161#208#28#223'e'#205#23'/'#135'`'#164#18#0#10#127#1#238'6'#162#240#231
+ +#145',+'#168#194#15#5#220'l-'#130#210#170#217#220#136'nQ'#129#15#169#254#201
+ +#210#222#28#136#245'w'#135#171#207';'#0':\'#237'=>>{'#222#18#184#248#218#236
+ +'W'#131#174#250#246#19#248#251'_'#175#201#250'y'#169#148#248#162'k'#254#138
+ +'Z'#207#226#172#159';W@>'#129'x'#12#152#199#159':'#10#249#168#183#160#159's'
+ +#10#18#17#216#219'['#160#165'v-'#155':'#20#21'B'#131'@?'#239#196#245'{L'#14
+ +#255#229#181#215'^'#139'C'#22'I '#155#4#240'4'#10#255#153'B'#194#15'e'#242'i'
+ +#181#26'('#171#222#21'l'#22'+X-'#26#150#227'o'#210#11#241'~E'#206'W'#247']y'
+ +#206#190#224#245#184'z|'#220'`'#180#192'}O}'#154#245#235'z'#230'o'#183#192'7'
+ +#255#253#183'$'#159#9'iw'''#156#185#12#246'>0'#247#19#161'2'#1'nE'#231'z'#11
+ +'R'#166' '#181#26'gIB'#194'@R'#26'8R'#251#11#184#28'M]K'#135'}'#10'Yd'#230'Y'
+ +'G'#236#180#253#214'[o'#205#154')'#144#21#209'B'#225'_'#136#187'/'#196'M=)'
+ +#225''''#191'x'#2#20#150'M'#228#236'~'#190#159#31#27#209#205''''#251#200#20
+ +'|'#154'o'#142#142#228#190#242#156#165'L'#157#235#13#203'n'#127#22#170''''
+ +#207#204#234'u'#253#241#186#147#160#174'f'#163#148#31#13#236'{'#200#201'p'
+ +#236#169'WJz'#13'R!'#217'e'#152'2'#5'Q'#19#160#162'!'#174#155#16'_='#232'rC'
+ +#211#214#239'!'#16#12'tI'#16#138#191'5'#217#214'x'#204#231#159#127'.h'#1#25
+ +''''#129#140'K'#22#10#191#18'w'#171'Q'#246'g'#138#29#127#6#163#9'W'#255#221
+ +'P'#232'u'#220#234'o'#20'B~'#156#221#175#148'Q?'#191#172'\'#226#160'q'#229'Y'
+ +'KX'#152#173'7L'#156':'#27#174#186#229')v'#155#190#232#141#235#190#135'_~'
+ +#252#2'j6'#255#2#173'-u'#16#14#5#161#176#184#28'f'#238#178#24#150#236#127','
+ +#216#242#139#135'|]w\{<4'#214'm'#145#250#227#129'='#150#28#6#167#157#127#171
+ +#212#151'!'#13'(*'#144#224#187#9#133'R'#203#135'iko'#222#14#237'M'#155' '#28
+ +#230'M'#1#222'!'#168#144#197#143#216'}r'#244#223#217'2'#5#178'A'#0#201'~'#254
+ +#130#227#143'V'#255#226#138'Y'#144'_X'#194#170#251#204#204#235#175'f3'#251'4'
+ +#194#164'^'#5#191#242#231#174#252#195#21'g.'#198'/0'#216#231#243'*''L'#135
+ +#246#214#6'^['#232#253';'#173#154'8'#3'.^'#246' '#232#141#230'A_'#215#223#239
+ +#189#18'~^'#253#133#212#31#15#195#137'g]'#7#139#246'=J'#234#203#200':'#196
+ +#249#1#194#172#1#242#7'P4'#192#229#14#129#27'I'#160'q'#219#15#204#132#236#146
+ +#27#176#173#196#26#155'S]'#20#243'e'#131#4'2*^('#252#229#184#251#21#133#223
+ +'(8'#254'h'#245'7'#219#138#161#164'r&'#179#249#201#243'o'#22#169#254#148#240
+ +#195#138'j'#134#193#140#238'+'#206'\'#4#209'H8'#237#199#165#234#187#227#207
+ ,#188#22#246'\'#250#251'A'#189#254#173#151#31#130#143#223'}A'#234#143#135#129
+ +'4'#190#229#127'Z'#1#165#229#19#165#190#148#172'#9'#131#144'R'#133#249#209'c'
+ +'n'#26'I'#206#180#128#16'8'#236'm'#208'R'#187#134#213#10#136#27#138#202'e'
+ +#137'?'#21')6'#222#186'j'#213'*j-'#158'QS '#211#4#240','#238'N'#231#194'x\'
+ +#165#159'N'#167#129#210#9#187#162#218'o'#6'3o'#247#155'x'#213'_'#165'Rt'#198
+ +#251's\'#248#9'W'#158#177'p'#135'A'#27#233#2'}'#6'W'#160#233'@'#26#193'@'#225
+ +#180#183#192#173#151#255'N'#234#143''''#9#157#222#8'w<'#244'>(G'#227#240#145
+ +#132#184#167' '#167#5#176#198#162#158#16#155'@'#220'Z'#255'+t8'#26#152'C0'#22
+ +#139#9#164#17#210'(";W'#154'[k>'#255#252's'#129#4'2'#130#140#137#25'_'#236
+ +#179#25#127#200#202'd'#147#15'\'#225#243'J&Aa'#201#4'&'#248#22'>'#219#143#188
+ +#254'B'#194#143#208#214'K6'#28'4'#128'3'#22#160#234#150#185#249#15#148'F'#252
+ +#199'G>'#4#165'j'#224#130#243#199'k'#143#131#214#166#237'R~<)'#168#24'?'#13
+ +#174#190#253'9'#169'/#'#171'H'#206#31#20'G'#5#130'\'#150' E'#5#152'&'#224#246
+ +'A'#211#182#149#16#240#7#146#25#130'd6'#160#22#240#216#30#147'#'#151#226#203
+ +'c'#153'4'#5'2I'#0#127#195#221#5#194#234'O'#171#187#222'`'#198#213#127'>'#174
+ +#252#186#164#234'O1'#127#13#175#250#11#173#188's5'#236#215#21'W"'#1'd:'#211
+ +'n'#206'n'#251#194#233#23#253'q'#192#175'['#245#205#135#240#226#223'o'#145
+ +#234#163#233#22'{'#29'x'#2#28'q'#210#229'R_FV'#145'L'#21'&_'#0#223'T4'#16#226
+ +#18#132'H'#3' "ho'#169#5'{'#211#198#174'a'#193#160'Y'#23#157#174#143'ln'#200
+ +#164')'#144#17'Q'#227#251#250'oCa'#214#8#171#191#150#194'~'#227'v'#130#130
+ +#194'q,'#233#135'R}'#169#198#159#10'}'#146#173#189#134'Y['#175#171#207'^'#136
+ +'_lf'#9'@'#173#209#193#157#127#31'\.'#193'u'#231#239#3#225#12#213#1#12#22#231
+ +'^y'#31'L'#155#185#135#212#151#145'u'#136'G'#145'S'#130#16#171#21#224'K'#135
+ +'I'#19' -'#192#231#245'$'#147#131#226#156'/'#224#129#137#214#198#229#133#133
+ +#133#145'Li'#1#153'"'#128'{pw'#149#216#246'7'#24'q'#245#175#222#21'W}m'#146#0
+ +'('#215'_'#163'Q'#138'r'#253'3'#253'5'#164#23#203#206'Y'#196#190#172'L'#131
+ +#132'f'#234#206#3'/*'#250#199'3'#127#130#149'_H'#147#16#212#19#242#10'J'#225
+ +#250#191#252'S'#234#203#200':'#132#4'!'#161'V'#128#229#6#8#166'@W-'#128#250#8
+ +#178'(B'#194'k'#209#248#166#203'|'#155'Z'#143'='#246#216'h&'#18#132#210'.r('
+ +#252#249#184#219'.'#158#231'G*~~'#233'4(('#174'`'#182#191'9'#153#238#171'J'
+ +#233#231'?'#220#176#252#188#197#25#245#1#8#152#188#211#174'H'#2#15#12#248'u~'
+ +#159#27'n'#187#252#224#164'-'#154'+'#184#244#198#167#161'|'#252'4'#169'/#'
+ +#235'`i'#194#162#178'a'#214'U'#152#143#10'Px'#176'i'#203'w'#224#247#251#152
+ +#22' D'#4#20#178#248'_'#198#233'jn'#213'h4'#145'L8'#4'3A'#0#255#135#187#27
+ +#133#184'?'#173#254'z'#189#1#202'&'#238#193#4#159'<'#255#20#243#167#176#31
+ +#149#249#178'b'#31#190#189#207'p'#226#128#166#186#205'p'#255'm'#167'g'#229'\'
+ +'&K>'#220'xo'#255'z'#247'u'#197#227#247'\'#10'[6'#172#202#230'G'#211'''*'#171
+ +'w'#134#139#174#127'L'#234#203'H'#162'v'#235'z'#248#224#141#191#179'U'#248
+ +#202#219'^'#4'm'#6#134#161#236'P6LZ'#0's'#8#134'Xkq'#242#7#216'['#182#131#189
+ +'y'#19#203#11#16'E'#4':'#10#13#222#25#165#150'p'#187#209'h'#140#166#219#20'H'
+ +#171#200#161#240'S'#246#10#173#254#214'd'#193#15#10'y^'#233#20#200'/'#170'd'
+ +#4'`'#225'+'#253#132#213'_.'#204#241'K'#251'G'#158'Y<'#245#192#149#176'i'#221
+ +#202#172#156#139#138'l'#254#244#232#127#7#245'Z'#183#171#13#238#188#246#168
+ +#156#210#2'hq'#184#225#158'w'#192'h'#178'Jz'#29'?'#175#250#12#222'z'#233#175
+ +#224#245'8'#147#247'Yl'#133'p'#237#157#175#225'oR'#153#246#243#9'#'#200#147
+ +#29#132#216#188#193#8'x'#242#5'P'#181#224'w'#16#164#136'@'#172'S'#11
+ +'P'#202#227#255'7'#181#208'~'#151#221'n'#15#167#219'!'#152'n'#2#184#30'w'#127
+ +#20#175#254#172#183#127#245#238#184#234#235'p'#245'Ws'#157'}'#249'b'#159'd'
+ +#216'o8-'#253#192#133'tn'#190'x'#31#136'g('#7#160';\'#247#151#183#152'&0'#24
+ +';d'#213'_'#204#156#191#15#156'x'#174#180#3'G'#222'|'#225'.'#248
+ +#254#203'wv'#184#191'x\5\v'#243#243#25'9'#167'0'#130'<'#22#19#194#130#145'd'
+ +#243#16#210#4#218#155#183#130#179'uk'#215'r'#225#246#170'<'#255',u'#194#233
+ +'L'#183'C0m'#146#135#194'O'#189#175'jP'#152#11#133#156#127'J'#249#205'+'#158
+ +#4#249#197#227'q'#245'Ws'#131'6'#127#209#225'p'#196')'#203'2r^'#241#152'1'#234'#'#232#167
+ +#228' >*@Z@'#211#150'o!'#24#10'B4'#210'Y#'#160'R'#196'o'#24#167#171'}'#200
+ +#229'r'#133#210#233#16'L'''#1'\'#134#187#251#133#22#223'JV'#238#171#195#213
+ +#127#15'0'#25#185')'#190#228#249#215#137'W'#255'af'#247#11#248#203'uG'#130
+ +#167#195#158#213's'#206#156#191'/'#28'w'#214#224#227#250#143#254#249'\h'#172
+ +#149#182'B'#176'+'#14':'#234'"X'#184#223#241#146#157#127#235#198#213#168#29
+ +'u'#159#151' '#147#201#225#218#187#254#5#6'cf'#204#148#148#185#2'4v<'#16#6
+ +#143#151'#'#129#246#166#205#224'j'#171'I'#169#17#192#127#154'&'#216#218#230
+ ,'DC'#30'O:'#29#130#233'$'#128#159#196'#'#189')'#231#223'VT'#13#249'%'#213','
+ +#219#143'y'#254'u'#157#147'|'#5#219#127#184#161#177#246'7x'#236#174's'#179'~'
+ +#222#130#226'J'#184#228#230#193#231#247'?'#250#167#179#160#185'A'#250#10'A1'
+ +#170#167#205#131#211'/'#249#235#208#15'4H'#4#253'^'#184#243#154'C{|'#188'j'
+ +#210'l8'#235#138#7'3rn'#161'N'#128#204#0'J'#14#242#5#195#172'd'#152#204#0#183
+ +#199#11#205#219'V'#162#22#16'Ji'#29#166'SFO'#221'i\'#224'-$'#128#208#140#25
+ +'3'#210#162#5#164'E'#2#199#205':q'#14#200#228'?'#166#14#248'PC'#217#196'='
+ +#193'h'#212'%'#195'~]m'#127'v'#1#195'L'#5'x'#246#129#203#160'f'#211#154#172
+ +#159'W'#161'T'#193'M'#247#127'<'#232#215'?p'#203#9#224#180'7e'#253#186'{'#131
+ +#209#156#15'W'#255#233#13'I'#175#225#214'K'#150'v'#186#232#187#193'y'#203#158
+ +#128#178#202')i='#167'`'#138'u'#230#5#196'Y#Qj'#28'Bu'#2#20#26'lk'#218#8#238
+ +#246':'#22'-'#16#210#131#21#242#196#191''''#231#181#156#145#151#151#231'okkK'
+ +#139#22#144#30#2#152'}'#242#189#184#187'R'#156#248'c'#206'+'#133#162#242#25
+ +'l'#245#167#141'l'#255#174#5'?'#195'L'#246#25#238#184'|'#191#140#21#0#245#133
+ +#195'O'#186#6#230#238'y'#232#160'^{'#207#245'G0_@.'#129'4'#197#155#30#200'~'
+ +#199'$1'#250#250'>+&'#236#12'g]'#249#240#0#142#216'?'#8#26'@gD'#160#179#135
+ +' +'#22'r9'#160#173'v'#245#14'EB'#165'F'#215#156'Bs'#188#209'h4'#6#211#161#5
+ +#12'Y'#4#11'&'#238#167#212#24#139#235'P'#160'K'#196#206#191#194#242'Y`'#205
+ +'+J'#18#0'7'#211'O'#148#243#159#246#143'4'#243#168#223#182#14#158#185#255'b'
+ +#201#206'o+('#131#139'oZ1'#168#215#222'u'#237#161#16#238#163'y'#137#20#184
+ +#225#222#143'@'#174#148#206#17'x'#247#242#195'!'#24#240#246#248'8'#249#2#150
+ +#223#243'>.j'#233#175'd'#20#198#139#209#198':'#9#135'"\'#15'A$'#0'2'#7#154'k'
+ +#190'g'#201'\bg'#160'F'#17#185'~'#130#205#254'x'#186#180#128'!'#203#225#184
+ +#217''''#29#130#135'yW'#172#254#235'tz('#157#184#7#152#244#26#214#229#135'e'
+ +#253#241#171'?'#169#255#220#7#155#246#207'3'#227'xg'#197#159'a'#237#247#255
+ +#25#250#129#134#128'E'#7#158#10'{'#29'|'#230#128'_'#247#231#171#15'D{2'#167
+ +'F'#211'3\q'#199#27#160#207#144#163#173'?x'#232#182#19#192#237#236'}B'#242
+ +#194#253'N'#130#165#135#157#147#145#243''''#135#138#196'83'#128#178#3'='#188
+ +')`o'#169#1'g'#203#230'd'#219'0'#190'Jp'#213#228#188#230#223#163#6#224'N'#135
+ +'/`'#168'b(C'#245#255'%'#220#159' '#174#250#179#20'TAA'#233'd'#182#242#147
+ +#240#179#156#127'a'#180#215'0'#140#251#11'x'#152'~,'#174#190#199'ig'#18#244
+ +#217#157'q'#249'#PZ9'#176'T'#218';'#175#220'/+3'#2#6#138#11#174#127#1'l'#133
+ +#227'$;'#255'S'#247#156#7'-'#13#155'{}'#142#193'd'#131#203'n'#207'L'#253#2
+ +#203#11#192#175'%'#154#156'''@y'#1'\'#207#0#143#199#3#205#219#190#235'j'#6'$'
+ +#242#180#158#189#139#140#190'_'#210#161#5#12'I'#18'Kw>'#214'"W'#168#155#240
+ +'G'#169#19'w'#252')'#170#154#7#22#139#141#9#191#208#231'O'#205#175#254#178'a'
+ +#24#247#23'p'#215'5'#251'g'#188#250#175'?'#208'h'#13'p'#217'mo'#12'Hu'#206
+ +#149'k'#239#138#11'oz'#5#204#214'B'#201#206#255#226#195#151#161'i'#247'K'#159
+ +#207';'#227#138'G'#161#164'<'#189#206'@'#1#226'J'#193#0#211#2#194'L'#11' 3'
+ +#160#165'n'#13#248#220#246#20'3@'#173#136'>2)'#223#241''''#157'N'#231#25#170
+ +#22'0'#20'I'#148#141#155'u'#210'Y('#205'O'#138'c'#255':'#189#25'J&'#236#202
+ +'B~F'#3#183#250'k'#133#138'?'#129#0'2'#242'1f'#30'w]'#189#159#212#151#144'DE'
+ +#245',8'#233#194#254#135#208#238'^v@V*'#23#7#2#250#221','#187#251#163#172#159
+ +#215#209'V'#7#171#190#252#23'4'#213'n'#128#182#230'm'#253'j'#235'V5i'#23'8'
+ +#225#252#244'O?'#18'$'#150#141#26#143'u:'#3'}'#228#12'D"p'#182'7'#128#189#241
+ +#215#20'3@&K'#212'M'#201'k'#222#27'??'#215'P'#181#128#161#17#192#236#147'?'
+ +#199#253#18'.'#166#207'M'#248#181#22'q'#153#127'$'#248#194'`O'#173#134'k'#244
+ +#169#16#226#254#195'P'#3#8#6#189#240#208'MGH}'#25')'#216#231'w'#23#194#188
+ +#197#253'k'#184'y'#239#181#7'f'#165'rq '#160'^'#7#151#221#241#206#208#15#212
+ +#7#162#209'0'#252#188#242#3#216#176#230'S'#166#238'G'#250#209#200#181'+'#228
+ +'r'#5'\q'#231#251#236'w'#158'v'#240#209#0#193#25#200'B'#130#188'/'#192#231#11
+ +'@'#243#214'o'#184#190#129#157'f'#0'X'#181#129'S'#202#173#190'OQ'#3#240'644'
+ +#4#15'?'#252#240#216'`'#180#128'AKb'#217#204#227#170'er'#21#181#252#146#137
+ +#213#255#226#234#221#209#246'7'#166#172#254#164#254#211#7''''#31#198#234#127
+ +'['#211'Vx'#238#190'?H}'#25') '#15#245'YW?'#133'6ty'#159#207#253#235#242#131
+ +'r'#142#0#242#138'*'#217#245'g'#18#159#189#243'wX'#245#5#229#26#12'='#13'z'
+ +#241'Ag'#194#238#251#156#148#145#235'$'#225#23#18#131#184'"!./'#128#234#4#218
+ +#234#215#131#167#163#169'Kjp'#236#141')'#5#142#171'U*'#149#203#135',1'#216#26
+ +#129#193'J'#163#172'|'#246#201'7'#226#153'n'#23'{'#255#141#230#2'('#172#152
+ +#205#173#254'z'#21#232#209#12#160'6'#223'*'#149#144#246';<'#133#159#176'm'
+ +#195'w'#240#230#179'7I}'#25';'#128'<'#232#231#223#248#143'>'#159'w'#255#13
+ +#135'd'#181'x'#169'?'#216#251#240#11'`'#151#133'Gf'#236#248#219'6'#174#132'7'
+ +#159#185'1m'#199#179#228#149#194#217#203'2'#211#215'P'#152'+'#200':'#8'G'#185
+ +#225#162'>'#161'i'#136#179#21#218#235#215#166'$'#5#201' '#209'19'#191'u'#145
+ ,'\'#150'h'#195#197#215'+'#170#20#28#144#157'7h'#2'@'#245#159#234'S'#23#139'+'
+ +#255#242'J'#167#131'-'#191#12#244'zU2'#244#199#138'~'#134'q'#222#191#128#159
+ +#191#127#31'>~#'#251's'#254#250#131'I;/'#130#195'O'#238#157#156#30#188#241'P'
+ +#201#18#152#186#3#149'8_v'#251#191'I'#183#206#200#241#253'^'#23''#232#163'7|'#247#217#10#248#230#163#204
+ +#148#136#166#3#135#156'p=L'#153#181'W'#143#143'?q'#231#137#224#243'8'#164#190
+ +#204'$'#170'&'#207#131'#'#207#252'S'#198#142#255#244#221#167#129#219#217#146
+ +#246#227#238#182#247#137#176'`'#255'3'#210'~\'#241' '#145#168#168'y('#133#4
+ +'I'#19'ho\'#7#30'gsJm'#128'^'#21'y'#180#210'b'#191#31'I'#193#129'&'#128'o0'
+ +#206#192'A'#17'@'#197#156#147#247#195#235#252#143'X'#253#215#234#200#251'?'
+ +#159#9#190#1'5'#0#193#249#199#133#254#134'o'#234#175#128#207#223'y'#4#214'~'
+ +#155'y'#135#213'`'#161'Ti'#224#194'['#223#234#241#241#247'^'#186#3'6'#175#251
+ +'R'#234#203#228#175'U'#13#231','#127'%c+'#233#251#175#222#9#155#214#14#174
+ +#129'J'#223#215#174#129#243'o~3#'#206'@ae'#167'h@'#152#31'$B'#137'AD'#0'N{=8'
+ +#155'6'#166#180#11'S'#202'c'#223'O'#202'k;'#7#175#165'='#18#137#184'='#30'Oh'
+ +#160#13'C'#6'E'#0'h'#255#255#9#143#190'\'#28#254'3'#219'*'#209#4#152#204#236
+ +#127#218'h'#188#183'Z'#24#243'5'#12#171#254#186#226#235#15#159#130#213'_'#190
+ +'.'#245'e'#244#138#5#7#156#9's'#23'w?'#149'w'#203#250#175#224#253#151#239#144
+ +#250#18#25#14';'#229'6'#24'?u'#183#140#28';'#232'w'#195#147#127'>'#161#215#2
+ +#159#161'b'#202#172#189#225#128'c3'#215'+'#128#181#12#19#204#0#158#0'|^/'#180
+ +#212'|'#151','#17#230#252#0#16#156'\'#208#182#31#138'Y'#227'`'#157#129#3#149
+ +'L'#217#173#183#222'*{'#226#205'M_'#225#237'='#196#197'?y'#227'v'#6#171#173
+ +#152#23'~n'#245#231#188#255#178'a'#217#240#179'+'#182#172#255#18'>x%s*k:'#160
+ +#213#153#224#236#235'^'#237#254'A'#252#209#252#237#182#195'%o'#10'2e'#246#222
+ +#176#255#209#215'd'#236#248#159#188'q/lX'#243'IF'#223#3'-|''_'#246'$s'#10#166
+ +#27'I3 '#206#153#1','''#0#9#128#136#128#8' '#24#240#165#248#1#10#244#254'K'
+ +#11#13#158#143'Q'#11#176'SH'#16#181#128#240'@'#204#128#1#19#192#148#221'N2'
+ +#251'B'#178'v'#154#248#211'i'#255#171#160#164'zO'#208#235'u'#172#232#135#156
+ +#127'Z>'#245'W>'#12#219'}w'#7'ZY'#158#185#235'D'#169'/'#163'O'#236'{'#212#213
+ +'L'#200#186#195#11#247#158#14'^w'#187'd'#215'V4n2'#28'}^f'#29#169'O'#220'q'
+ +#20'D#'#161#140#191#23'K'#254'88'#233#210#199#211'~'#220#174#237#195')'#26'@'
+ +'$'#16' ?@'#211#6#240'8'#27#187#250#1'^'#172'0'#183#223#135'ZA'#171'N'#167's'
+ +#15#180'Jp'#160#162')/'#159'}'#226'!'#9#144#191'#'#216#244#20#255#215#27#172
+ +'PX9'#151#9'?'#249#0#152#250#175'$'#239#191#208#244'cd'#144#192'cl'#5#205#173
+ +'l'#186#174'(.'#159#6'G'#158'so'#183#143#173#252#228'9X'#253'E'#223'!'#195'L'
+ +' '#191'x'#2#28'{A'#250#203'j'#197#248'u'#213#7#240#223'w'#30#202#218'{Zt'
+ +#240#249#176#243#238#135#167#245#152'|'#247#31#212#0#184'nA'#194'hq6^'#220
+ +#209#4#142#166'_'#187#250#1#214'M'#206'o?'#31#9#160#9#205#0'g('#20#242#15#196
+ +#12#24#136'X2I.'#159's'#242#221'x'#222'+'#197#14'@s~%'#235#253'G'#194#175'G'
+ +#225#167'a'#31'D'#0'r'#133'l'#216#135#255#196'x'#225#222'S'#193#239'u'#14#253
+ +'@'#25#132'Zk'#128'3'#175'}'#181#199#199#223'x'#252'rhk'#218'<'#128'#'#14#29
+ +#214#130'r8'#254'"'#154#20#151#153#144#159#128#151#30'8'#27'<'#174#244'{'#254
+ +'{'#2#245'5fV'#248
+ +#219#26'7'#193#191#158#186'2+'#239'I'#140#25#187#30#6#11#14'Jo'#134'hgRPg'
+ +#159#0#193#20'h'#175#253#129#245#8#16'u'#12#134'|'#157#247#230'b'#147#255'}'
+ +#148#201#22'$'#128#14'2'#3'P'#3#136'B?'#162#1#3#17'O'#249#132'9G'#230#133#19
+ +#250'f'#188#173'H'#150#255#170')'#254#191#16#237'~'#174#233#7#197#254'5|'#242
+ +#15#215#245'w'#228'0'#128#179'm;'#188#241#152't'#13'A'#250#139#197#135']'#10
+ +'S'#230#236#223#235#251'x'#243#241'K3n'#206#204'^x'#28#204#223#251#212#172
+ +#188#231#183#159#190#10'I'#224#183#172#156'K'#12#149'Z'#11#167'-{-'#189#7'Mp'
+ +'9'#1#228#8#140'D'#184'h'#128#16#18't'#182'lBS'#160'N'#1'D'#2'd'#226
+ +#216#27#215#165'8'#2'U'#242#216'&4'#3'.'#198#219#13']'#204#128'>'#163#1#253
+ +'&'#0'R'#255#191#217#164#186')'#145#144#221'"'#216#255'4'#247#207#156'?'#30
+ +#172'E'#19#152#240#147#243#143'&'#1#177#220#127#249#200#178#255#5'|'#251#225
+ +'c'#240#235#170#247#164#190#140'^ '#195#21#233#31'h'#154#245#175#133#213#170
+ +#207'_'#128'u+'#223#198#31'T'#223'%'#177'}'#158#25'5'#194#9#211#23#194'B'#212
+ +'@2'#209'B'#171'''|'#242#250#157'P'#251#219#183'Y;_W'#152'l%p'#204#5#233#27
+ +'u&D'#2#132#226' V'#27#16#138'23 '#16#8'B'#203#182#175#240#251#138''''#29#129
+ +'2Y'#194'7'#173#160#245'd4'#11#234'('#26'`6'#155';'#182'l'#217#18'Z'#183'n'
+ +#29#153#1#189#170'y'#253'&'#128#165'K'#151'*6'#187#198#189#128#231';A'#236#0
+ +#180#149'L'#7#147#181#132#9'?'#167#254'wv'#254'aC?F'#152#6#16#143'Ga'#5'j'#1
+ +#180#207'E'#232#12'68'#238#146'g'#7#250#174#224#251'O'#158#133#223#214'|0@'
+ +#141'@'#198#178#250'4:3'#20#148'N'#130#5#7'_'#12'jm'#250#231#234#245'z'#229
+ +#236#251'8N'#210'JG'#146#135#211#174#253'WZ'#143#201'R'#131'y?'#0#155#29#128
+ +#4'@'#27#17'A'#235#182#239' '#28#246#167#248#1#198'['#237#231'j'#20#225#245
+ +'J'#165#178#9'W'#127#167'N'#167#11#244#167'6'#160#191#210')'#159'7o'#158#162
+ +'9:'#141'hv'#174#152#0#10'*'#230#130#201'le'#194#175#213't'#134#255#134's'
+ +#235#175#190#240#213'{'#15#194#230#28'u'#6#142#199#21'x'#175#223#15'>'#209
+ +#134#242#29#234'6}'#7'M'#219#215#178'N4'#241'X'#132'U'#17#146#160#145#160'['
+ +#242#203#153#176#23'W'#236#4#230'<'#233'Zy'#9#248#254#147#167'a'#253#247#131
+ +#27#156#154'N,='#234'Z'#168#154#178'g'#218#142#215'u'#132#24'5'#10#9#242'Z@{'
+ +#253'Oh'#246#216'S'#8#160#216#232#249#147'M'#235#251#24#239'k'#196#191#237
+ +#161'P'#200#215#159#1'"'#253#145'Pf'#255#31'|'#240#193#170#181#141'ymx'#219
+ +'$'#142#0#20'MX'#8#6#157#134'['#253#133#226#31#249#200'I'#0#234#14'$'#12#175
+ +'=tF'#214'<'#233#253#6'~'#224'G'#254#225'Q0Z'#138#165#190#146#172#225#229#191
+ +#158#136'Z'#203#192#27'|'#164#27#21#147'wC'#18#184'.m'#199'K'#13#7'v'#18#0
+ +#141#21'w4'#253#6'^WC'#151#6'!'#254#23#139#244#174#151#209#254#175#139'F'#163
+ +'mj'#181#218#211#159#18#225'~'#17#0#217#255#171'6'#199'+Cq'#237#214#164#3#16
+ +#237'='#181'F'#143#4#176#27#203#250'c'#171#191'Z'#193#186#2')'#21'#'''#249
+ +#167''''#216'['#182#192#7'/,'#203'h'#206#249'@Q9e'#15'X'#252#251#204#228#168
+ +#231'"6'#253#248#1#172#252'8'#253#217'x'#131#129'Vo'#129#163'/z&'#173#199#20
+ +#210#130#201#214''''#2#16#162#1#29#246':'#232'h'#221#156#18#9'0'#168'C'#159
+ +'UZ\'#15#163'|'#214#14'$'#28#216#31#17#149#163#253'/'#175'q'#151#238#23#137
+ +#201#223'O'#137#0#24#242'!'#191'b'#22#155#3'@'#177#127'F'#0#138#206#8#192'H'
+ +#199#154#255#189#0#235'W'#190')'#245'e0'#144#231#253#152'K^'#204#170#243'Mj'
+ +#188#249#232#217#16#240#229'Fb'#150#12#127#240'''^'#153#222'b1a'#148'x'#140
+ +#207#7' '#2#8#134'#'#224#235#176#131#189#241#231#148'H'#128'F'#25#253#181#218
+ +'f'#191#3#229's;'#254#221#20#12#6#157'J'#165#178#207#226#160'~'#17#192#140#25
+ +'3'#148'n'#213#172#11#226#9#249#253'b'#2'0'#217#202#193'V<'#25'U'#255'N'#2'H'
+ +#142#252#30#225#26#128#128#207'^'#191#29#154'j'#178'?*L'#12#242#190#239'}'
+ +#204'MPR5['#234#143'#kh'#220#182#26'>'#255'gnT7'#10'8'#225#242'W@'#158'&'#2
+ +'f'#170'='#223'#@'#240#3#176'~'#129#148#16#228#247'B'#235#246#149')'#4#160
+ +#148#199#237#147#242'Z'#175'E'#185#164#9#221#13#129'@'#192#238#247#251'}&'
+ +#147#169#215#226#160#190'D'#148#169#255'^'#175'W'#249'K'#147#237#190'xBv'#129
+ +#152#0#172#197'S'#192#130'$'#160#161#8#128'J!'#234#254#3#204#30#29#13#4'@'
+ +#248#238#195'G`'#235'/'#210'8'#5#233#251'Xr'#228#245'P6a'#174#212#31'CV'#241
+ +#239#167'/'#6#143'3'#183'f'#29#238'{'#252#237'l'#28'^'#186#144#236#15' '#26
+ +'%N&@'#24'5'#129#230'-_B4'#18'I'#18#0'">5'#191#229'r'#20#203#173#248'w]8'#28
+ +#166'Va'#30'Q'#143#128'n'#253#0#253'"'#128#182#182'6'#213'fW'#217';'#137#132
+ +'l?q'#17'P'#222#184#153'`4'#23#178#213#159#171#254#235','#0#26'%'#178#159#196
+ +'/'#223#252#3#183'W'#135'~'#160#1#128':'#213'.8'#236'*('#159#180#187#212'o?'
+ +#171'p'#182'l'#133#15'Wd'#174#164'x'#176#152#179#228't'#152'6'#255'wi;'#30'_'
+ +#23#196'|'#0#177'(?D'#20'M'#0'r'#6#182'm'#255#1#194'A/'#171#9#16#136#162#210
+ +#226#252#139'A'#29#254#142#252#0#161'P'#168#197'`0t'#212#214#214#6'{'#203#7
+ +#232#147#0'('#254#143'j'#132#250#199'Z'#243'z'#27#205#196#146'wv'#1'RB'#209#132'E'#160#165#236'?u'#151#177#223#195#184
+ +#253#247'PA'#171#211#234'O'#30#3'G3'#253'@'#211'O'#4'*'#181#30'v^t'#18'L'#154
+ +'s'#176#212'oU'#18#248#221'm'#240#238#147#231'K}'#25#221'b'#210#156#131'`'
+ +#151'}'#206'M'#235'1'#217'b'#194#143#14#139#242'&'#0#249#1'\'#246'm'#224'm'
+ ,#175'I!'#0#139'6'#240'q'#153#201'M'#163#250#182#225#223#141#184'''?'#128#191
+ +#188#188'<g'#255
+ +#167'$'#0#201'G'#141#237#223#27#130'~'#23#172#254#244'Ih'#216#250'=2'#248#208
+ +#179#212#244'hj'#237#188#231#9'0~'#250'^C>'#214'p'#198#127#223#248'?h'#169
+ +#253'I'#234#203#232#22'S'#230#30#206#204#128'tB'#136#4'P80'#18#163'\'#0#218
+ +'"'#172'1'#136#171'ecJ2'#16#170#255'?V'#152#29#143#201#229#242'mx'#127'='#154
+ +#233#237'}u'#9#234'MTY'#251#175#239#190#251'N'#245'['#171'q~0'#170#254'R'#198
+ +#229#246'2'#2#208#26#242#160#160'|6'#18#0'7'#248'S'#171#230#186#255#202'y'
+ +#239#255#232#243#2't'#15#250#130'~'#254#250'%'#168#221#240'?'#22#178#234'o'#5
+ +#30'y'#246#13#150'"('#169#154#3#147#231#28#2'f'#155#244'YwR#'#26#14#194#27
+ +#143#158'"y['#179#158'0}'#215#163'`'#214#194#147#211'v'#248'1'#228#14#254#249#192#9'h'#3#167's'#208'gzA+'#255'A'
+ +#167#167#127#230'A'#178',8'#193'E'#148#136#0'hX('#245#5'h'#221#250#5#27#248
+ +'*Z'#145#187#141'N'#20'*'#13#28'}'#233#203#25
+ +';'#190#160#248'PYp'#8'5'#0#31#18#128'?D3'#2'VA$'#232'N!'#128#234'<'#251#11
+ +#26'Et='#222#220#138#191#231#237'h'#2#244#26#10#236#145#0'('#4'XXX'#168'B3'
+ +#192#248'K'#147#237#159#241#132'l1{@ '#128'q'#179#193'h'#202#7#147#137''''#0
+ +#26#3#206#183#1#207#4#9#188#243#216#185#224#239'E'#160#199#207#216#27'v?'#248
+ +#18#230')^'#245#241#19#3'N'#191'U'#170#180#176#199'!'#151#193#184#201#163#171
+ +#178'n8'#128'l'#223#215#239';6g3'#0#231#238's6'#211'&3'#5'!'#29#152'"'#1#212
+ ,#25#200#235#11#177'\'#0'J'#4#10#251#157')'#4'0'#222#234#248#135'N'#21'YK&'#0
+ +#229#2#224#234'O'#205'A\'#212'$t'#247#221'w'#143#12#136#0'('#7' '#20#10#25
+ +#127'm-x'#27#9#128'IF'''#1#204#5#163#217#10'f'#163#22#180'H'#0#212#9'H'#166
+ +#200'\'#15#128#143'W,'#7'{'#227#198#30#31'''/l'#193#184'i'#208'Z'#251#243#144
+ +#206'SX1'#3#150#28'u#j'#19#218#204#188#145'1'#12#10#239'>q'#1'x]'#205'R_'#198
+ +#14#160#26#141#195#255#144#217#182'd'#9'^d'#217#192#208'p'#20'<^'#158#0#234
+ +#215'B8`O!'#128'J'#139#227#13#189'*L'#197#18#201'\'#0#212#226#157'H'#6#221
+ +#230#2#244'J'#0'j'#181'Z'#19#139#197#140#155#28'E'#175#196#226#242#165#236#1
+ +#222#203'o+'#157#131'&@>'#243#1'P$@'#145't'#2'f'#134#1'V~'#240' l'#203'R'#211
+ +#13#5#146#201#220#253#206#131#234#153#251#15#253'`cH'#11#214'|'#254'LN'#166#1
+ +#31'p'#234'=`+'#158#148#209's'#8#233#192'q'#158#0#220'D'#0#254'0'#18#192#26
+ +'4'#1'\)'#4'0'#193#230'x]'#171#140#172#3'>'#27#144#186#4#247'6-'#168'O'#2#8
+ +#135#195#166'm'#29#165'OF'#227'r'#166#227#8#4'`)'#153#9'f['#17#24'y'#2#160'f'
+ +' '#178#12'N'#2'j'#174'Y'#3#255'}'#237#214#140'~'#208']a+'#158#8'K'#143#187
+ +'-'#235#189#238#199#176'#'#130#254#14'x'#251'og'#230#212't'#230#146#9#187#192
+ +'^'#199#220#146#241#243#8'EAqf'#2'D'#192#235#14#129#151#8#160'n'#21'DB'#30
+ +#238'9<'#1'L'#180#181#189#162'R'#196'6Q='#128#208#30#12'I'#192#209'S2PO'#210
+ +#154#204#2'D'#152'6'#180#218#238#143#198#21#201'('#0#17#128#185#136#250#194
+ +#151#128#201#164#3#131'^'#197#17'@'#134#235#0'^'#187#247'('#180#131#178#251#3
+ +#144#203#149'0{'#233#25'0y'#222'aY='#239#24'v'#196#166#213#239#194#143#159'<'
+ +'!'#245'e0'#208#140#132'C'#207#251'{'#210#241#156#13#196#248'T`'#143''''#8'>'
+ +'$'#0'J'#5#142#133#131')'#190#145')'#249'-+'#208#26#175#1'>'#25#8#247#13'('
+ +#252#164#1#248#186#235#11#208''''#1#168'T*'#243'f{'#254#31#195'1'#197#25#236
+ +#5'<'#1#152#10#166#176'D '#179'Y'#139#4#160'a'#4#192'f'#1'f'#144#4#200#14#244
+ +'8'#26#135'~'#160'A'#192'RP'#9'{'#31#127#27'h'#141'y'#146#156#127#12#28'>}'
+ +#233#6'h'#173#251'E'#210'k'#208#155#242#225#16#18#254',u`f&@'#28'X'#243#15'J'
+ +#0'r'#187#3#204#7#208'F'#169#192#209#136#152#0#18#211#11'[^'#196#191#235'I'#3
+ +'P('#20#219'"'#145'H'#3#222#223'>h'#2'@5'#194'R'#227'*'#188'>'#20'S^'#200'^'
+ +#192#11#184')'#127'"'#152#11#171#192'l'#210#128#209#160#3#165#138'k'#6#154
+ +#201'>'#0#171'>~'#156#173#2'R'#129'Z?'#239#188#240'$'#152#177'gzK>'#135#27
+ +#220#246'zh'#216#252#29#11#183#6'|.'#8#5#220#172'V_'#165#214#129'Zg'#2#173
+ +#222#12'Fk)TN['#12'zsAZ'#207'MCY'#222#127'J'#186#134#160#244#190#14'9'#231'a'
+ +#166#25'f'#11#156#15#144'/'#7#14'F'#160#163'#'#192#178#1#219#182#254#143'/'
+ +#20#226#228'Y.KDP'#3'x'#149'R'#128#129#171#5'`'#233#192#184#136#183#187'\.ow'
+ +#147#130'z%'#0#170#3#192#23'['#234#189#197#151#6'"'#202'd'#23'F"'#1#131#181
+ +#10#172'%'#19#193'd'#208#130#201#172'I'#154#0#178#12#134#210'i '#194#7'OH?'
+ +#158#219'd+'#133#165''''#252#31#232'-'#133'R_J'#198'A'#130']'#187#225'Kh'#218
+ +#242#3'ks'#22#244#216#7'4'#135#143#134#148#26#172#197'P1u'#1#236#180#240#184
+ +#180#9#206#215'o'#221#13'u'#191'~'#153#213#207#194'Z4'#30#14'<'#235'>'#188
+ +#149#253'|'#17#166#1#160#249#27'@'#193'w'#185#209#4#240#5#161'}'#235#23#220
+ +'c<'#1'('#229#241#224#164#188#214#127#226'M'#154#18'L'#234#255#214#190':'#3
+ +#245'J'#0#227#198#141#211#6#131'Ak'#141#211'r'#182'/'#172'Nz;H'#208#245#214
+ +'r'#176'P='#0#154#0'&'#147'6'#217#15' '#211'x'#253#158'c'#210'2'#201'v'#168
+ +#160#228#163'Is'#15#129#185#251#159''''#245#165#164#21'm'#245#235#161'n'#195
+ +'W'#208'^'#183#142#173#178#209'4'#142'B'#167#207#172#160'b'''#152#179#247#153
+ +#144'W:y'#200#199#219#188#250'='#248#241#227'''3>'#168#149#186'/O'#158#127'8'
+ +#204#217#231#172#140#158#167'W$'#184#17'a'#1#180#253']'#164#1'x}`'#223#254#13
+ +#255#16''''#207'*E'#204';)'#175#157#6'%'#146#218#207'4'#0#154#24'L#'#195#245
+ +'z'#189#167#191#4#192#10#129#208'VPVVVjc'#177#152'e'#187#211'|'#162'7'#172
+ +#185'+'#249#4'j'#9'f*'#5'['#201'4\'#253#181','#23'@'#165'Qr'#149#128#221#229
+ +'j'#164#145#23#254#243#236#149',3,W@'#17#130'='#127'w5'#148'T'#15#207#190#252
+ +'q$'#211#205'?~'#0'5'#235'>'#135#142#182#154'n'#11#174'2'#129#252#178#169#176
+ +#232#152#27#217'H'#173'!]?'#10#255#143#31'?'#1'['#127#250#152#13'2M+'#240'w^'
+ +'>y'#15#216#253#176'+'#178#155#23#210#141#12'%d'#192'f'#3#4#252'!'#232'p'#5
+ +#192#235'q'#131#163'ne'#138#3'P'#163#140'vT'#219#236'4'#187#190#129#132#159
+ +'6'#165'RY'#135'2'#220'6h'#2#136'D"'#214#6#183#249'w'#238#144#238'!'#241#147
+ +#180#166'b'#176#149#206'`y'#0'&'#139#142'M'#7'b'#29#129'2'#252#217#172#251
+ +#250#31#240#243#127'_'#200#222#151#209'O'#20#148'O'#135'%'#199#222'<,B'#134
+ +'^\'#217'7'#174#252#23#218#241#223#131#223#211'.Y'#145#13#249'T'#166#237'~$'
+ +#139#178#12#29'qX'#243#201'3Hd'#255'e'#205'C'#134#2#133#146#146#202#166#163
+ +#224'_'#206#18'}r'#1'T'#13#24#141#198'P'#245#15#129#219#229#7#175#219#1#206
+ +#134#31'S'#8'@'#167#140#216#171#172#246#143#128#215#0#168'"'#16#247#140#0#240
+ +#182#183#187#138#192'~'#17'@'#179#199#184#175'3hxZ'#252'$'#141#161#0#242#198
+ +#237#12'F'#163#14#205#0#29'k'#14#154#169'^'#0'b'#208'D'#222'7'#239#203#205
+ ,#194#16#25#170#138';-8'#22'v^'#156#190#198#144#233'BG{'#29#252#244#233#211
+ +#208#142'*~$'#228#151#250'rR`-'#154#0#251#159'y'#127#218'j1(g`'#195'7'#175'C'
+ +#253#198#175#193#215'A'#3#173#251'&8r`'#22'V'#238#12'Sw;'#2#138#170'fI'#253
+ +#145#236#0'z'#7#17'j'#7#230#9#162#9#224#199#247#213#14#206#198#212#238#200'z'
+ +'U'#184#165#210#226#248#12':}'#0#228#4#172#29#18#1#144#9#208#234#209#237#209
+ +#230'7'#254'#'#229#3#211'Z!'#191'b'#14#24'P'#253#183#152#245#172''''#0'u'#4
+ +#202'F3'#208#127#221'w'#18#251#146's'#21'Z'#163#13#22#163'z'#155'?n'#154#212
+ +#151#2#174#214#26#248#238#223#247#129#179')w'#204#166#238'@'#159#217'!'#231
+ +#254#13#212#250#244#14':!'#19#193#217#188#21':Z'#183#129#27'I'#208#227'jfu"F'
+ +'['#25'X'#11'+Y'#178#151#165#184':'#183#11#193'X'#166#31#215#11#192#235#13
+ +#176'('#128#199#209#12#238#150'u)O3'#170'C'#141#21#22#215#127#249'N@d'#2'l'
+ +#29#148#9'@'#155#216#9#232#244#171'f6z'#172')'#241'7'#133'J'#7#5'U'#187#131
+ +#193#160#1'3'#154#0':'#150#11' '#239#182#31'X'#186')'#225#203#127#222#153'u'
+ +#15#240'`0e'#215#195'a'#222#129#210#12#177#8#251#221#240#217#203'7'#131#163
+ +'i'#147#212#31'C'#191'A'#5'Y'#135#156#255'(k'#135'>'#154#209#157#190'B'#9'pa'
+ +'>'#9#168#3'M'#0'w'#251'v'#240#218'S'#167'#Y'#180#193#154'2S'#7'y'#6#27#248
+ +'$ F'#0#209'ht@N@BJ'#24'P'#169'R'#149'nh-'#250#2'_'#165'I>'#3#5#189'p'#194'"'
+ +'$'#0#29'X'#172'z'#208#27'5'#172'5x'#159'y'#0'i`'#131#230'mk'#224#211#23#174
+ +#207#202#151'1T'#152#11'*'#224#128#179#238#205#170'o`'#235#154#255#192#202'w'
+ +#31#206#154'C/'#157#160'<'#130#163#174'x!mSv'#135#5#250#180'P'#184#28#128'`0'
+ +#2#30'w'#0#220#168#1#184'Z6@'#160'#5)'#174#208#224']W'#160#247#253'D'#137'@d'
+ +#2#240#142#192#186'A'#135#1#137#0#240#133#164#147#21'ov'#20#191#30'K'#200''''
+ +'$'#159#129#4#144'W1'#15'L'#22#27'j'#0#6'V'#19#160#226'C'#129']'#223'O&'#140
+ +#130'W'#238'8l@'#241'h)A'#177#240#189'N'#184'%+'#145#130'O'#158'_'#14'-5'#185
+ +'99'#167#191#176#20#141#135'C'#207#127'T'#234#203#144#4'='#5#209'('#2#16#12
+ +#132'Q'#248#253#168#5#4#192'Q'#207#149#2#139'Qnv'#174'D3`'#19'%'#255#8#26#128
+ +#144#8#132#154#128'o'#192#4' '#164#2#227#193#138#183'8'#10#30#12#199#20#139
+ +#196#151'E]'#129','#249'e`'#178#234#192'd'#212#129'ZC~'#128#236#204#5'x'#239
+ +#209#11#192#217#178'-+'#231'J'#23#166#237'q$'#204';(}'#195'#S'#128'6'#226'{'
+ +#127#191'h'#216'}&=a'#194#236'}a'#193#145#185'7'#1'X'#10'P'#18#16'E'#0'('#4
+ +#200#17'@'#16#218#183'}'#3#177'h0'#229'y'#19#243#218'>U+'#226#164#254#215#163
+ +#224'3'' j'#2#245#129'@'#192#142'f'#128'w'#208#181#0#248'wQ'#141#211'v'#173
+ +'?'#162'Jq'#191#27#242#171#217#20#27#179'Y'#159#12#5#210'x'#176#158'k'#12#211
+ +#247#161#172#253#244'yX'#251#249#138#236#127#27'C'#196'n'#135']'#12'Sv;<'#189
+ +#7'E'#251#240#237#135#207'cN'#174#145#3#25#28'~'#201'c`)'#172#146#250'B'#178
+ +#131'^'#204#0'j'#6#18#165'n'#192'>'#206#254#247'z'#252#208#182#245#139#148#16
+ +#160'\'#150#136'N'#201'o'#249#8#5#159#194#30'uB'#30#0'nD'#8#246#129#214#2'$'
+ +#203#129#241#128'fd'#143#194'F'#143#229#20'wH'#151'B'#201'ZS'#9#228#143#155#1
+ +'&'#179#14#204'V=h'#132#178#224',('#1'>W'#11#188'q'#239#169#153'?Q'#154'AYeG'
+ +']'#189#2't'#166#244#21#21#189#247#247'K'#192#222#176'q'#232#7#202'1'#152#242
+ +#199#193#17#151'?#'#245'eH'#10'a&'#0#245#1#240'y'#3','#7#192#237'p'#160#9#240
+ +'Cj'#18#144'"'#234#169#206#179#127#129#247#181#161#204#210'J'#192'f'#3#12#182
+ +#28'8'#165#31#0#218#15#133#142#128'ai'#139#215#248#160#248'Ij'#141#5#10#198
+ +#207#3'#O'#0','#18#160'R'#176#142'A'#137','#12#7'}'#233#214'Cr"-x'#160'`?'
+ +#236'+'#158'K'#203#177'H'#19#250#9#183#145#138'='#143#184#10'&'#205#31#157
+ +#163#208'9$ '#30#163#8#0#239#0't'#250#193#213#214#0#238#214#245')'#4#128#182
+ +#127'K'#133#197#245#3#222'l%'#199#31#240#229#192#168#193#147#167'pp'#13'A'
+ +#168'%'#152#223#239'7!'#131#20'D'#19#170#201'['#157#133'o'#136'_'#163'P*'#161
+ +#176'z1K'#6#162'H'#128#206#168'ERP'#246'/'#23' '#13#252#240#206#131#231#177
+ +#24#239'p'#196#188#131#207#131#25#139#143#27#210'1'#236#13#191#193'{'#127#187
+ +'(g{'#229#165#3'r'#133#18#142#185#246#21#208#26#173'R_J'#250#209#143#175#141
+ +'u'#2'B'#251#159#28#128#140#0'P'#3'p6o'#1#175'c[J'#6'g'#158#206#191#173#200
+ +#224#166#196#128'VJ'#254#17'z'#2#146#6'0'#232#150'`BO@T'#31#10#240'GV'#190
+ +#201'Q'#242'J}'#246'F)'#191#167'A'#129'j'#227#207#184
+ +#251#179'A'#189'6'#28#244#195#138#27'G'#167'c'#172#176'r''8'#248#194#7'Xr'
+ +#213#136'@'#143#250'?O'#0#188#253'O+'#191#199#229'C'#18'p'#130#189'v%'#211#12
+ +#4'('#229#177#224#228#252#246#175#240#249#2#1#212#0#231#4#164#209'`-h'#198
+ +#187#131#136#1'M'#6#18#15#7#141'F'#163'6'#180'%J'#28'~'#221#190'->'#243#29
+ +#226''''#170#212'z('#172#222#19#140'&'#29#152'mD'#0'\B'#144#208'&<'#27'j'#192
+ +#11#215#31#8#145'P'#250#26'Wd'#3#244#3'>'#253#174#143#7#245#218'_'#254#251'*'
+ +#172'|{'#244#14'DUi'#13#176#223#153#127'd~'#148#145#138#4'_'#0'D'#241#255#160
+ +'?'#4#30#180#255#189#184'9[j'#192#221#250'['#138#227#215#160#14#219'+'#204
+ +#142#213'('#252#14#138#251#211'<'#0'>'#19#144'*'#1'['#7'3'#28#148' G'#155#129
+ +'U'#4#250'|>'#139'F'#163')'#142#199'a'#194'F{'#225#243#137#132','#217#29#129
+ +#170#168#24#1'X,'#204#15'`'#160#210'`'#230#7'P$'#29#129';'#156'-'#205'N'#235
+ +'_'#191'z'#19#190#249#231'_%'#249#162#6#11's'#193'88'#230#250#193#141#147#254
+ +#247#131#23'@k'#141#180#141'1s'#1'TA8m'#193#239'a'#206#1#167'g'#181'G_Z'#209
+ +#131#134'L+<'#133#255#200#254#15#160#253'/'#16'@{'#221'Z'#8#186'[S'#8#160#208
+ +#224#221'R'#160#247'Q'#185'g;'#17'@'#127#235#0#196#167#239#14';d'#3#226'V'
+ +#185#197#158#255#167'PL1#'#249'$'#20'rK'#241'N`-'#174#0#147'U'#143#4'`'#0#173
+ +'A'#13'*%'#154#1#138#204#205#10#236#138'Wn;'#10'|'#206#214#236#156','#13#152
+ +'0go'#216#231#140#255#27#212'k'#159'_~'#0'D'#130#185'U'#211'/%'#168#15'C'#233
+ +#164']'#160'z'#151'}'#161'j'#230#226'a'#31'2dFz'#156'S'#255'#A'#222#254#167
+ +#30#0#184'o'#222#252#5#196'#'#225#20#2#24'o'#181#175#210#169#162'-x'#179#29#6
+ +#144#5#200'>'#187#222'>W'#241't d'#146'B4'#5'*'#154#188#182#179#221'!'#237
+ +#209#201'''Q'#131'PK)'#228'W'#206'dQ'#0#163#197#0':'#147#150#21#6#201#149#217
+ +#233#15'@h'#217#250#19#252#251#129#225#227'%^t'#194'r'#152#186#231#224'R'#130
+ +#159#185'b'#201#176')'#132#146#2#148';'#160'3'#231#225#162'4'#30'J'#170'g'
+ +#195#196'y'#251#131#9'5'#174'a'#131#4'7'#9#184#211#254#199#213#159'e'#0#182
+ +#131#189#230#7'6"L'#144'c'#133'<'#30#153#146#223#246'5'#10#186#7'e'#141'V@'
+ +#178#251#5#2'h'#196#197#219#217'S'#18#16#161'W'#2#16'&'#4#163#253'o'#212#233
+ +'t'#249#241'x'#188#188'#'#168']'#220#232#177#220#156'|'#18#10#184'R'#163#131
+ +#226#137#11#153#31#192'h3'#128#158#18#130#180#252#184#176#12'N'#12#238#138
+ +#183#239#251#3#180'n'#27#218'l'#192'l'#225#212'?'#127#0#154'A6'#191'x'#242
+ +#210#133#144'v;j'#132#131'HAo)'#128#252#242')P>mw'#152#186#224#240#156'4'#27
+ +#216#234#159#224#212#255'('#170#255'd'#255#147#240'3'#251#191'y+'#218#255#155
+ +'Xn'#128#0#163':'#212'^aq'#145'='#216#129#178#216#140#143#17#1#176#8#0'.'#220
+ +#212';'#189#199#193#160#132'>'#9'@'#28#10#196#251#202#240#160#213#155#28'%'
+ +#143#196#19'2'#29'{'#18'k'#5'.'#135#194#9'{'#128#201'f'#227#205#0#174'.@AZ'#0
+ +#171#14#236'>)'#168#219#147#14#225#195#11#184#29#240#210#141#135#231'|^@~'
+ +#197'T8r'#217#179#131'z-E'#0#158#191'f_'#169#223#194#176#135'J'#171#135#165
+ +#167#222#2'U'#179#150'd'#252'\'#253#253#221#211#243'h'#177#140#199'x'#245'?'
+ +#20#129#128'7'#136#194#239#227#226#255#219#127#132#128#167'-%'#2'Pd'#240'l'
+ +#201#211#249#182#163#28#186#144'8'#154#132'$ '#218#227#202#223'b0'#24'X'#8'p'
+ +#221#186'u'#20'7'#140'ww'#222#30#175#137'"'#1#223'}'#247#157'*'#16#8#232#208
+ +#20#176#161#9'P'#138'D0~'#155'3'#255#250'`T9C8'#4#249#1#172#165#211'Q'#229
+ +#170#2#163'@'#0'z'#13#168#132'h@'#182'T'#0#196#202#127'='#12'k?z1k'#231#27'('
+ +#232#179'8'#254#246'7'#192#152'W:'#168#215#7#189'Nx'#241#218#209#25#2#204#4
+ +#138#170'g'#194#129#23#220';hm,'#221'`'#222#127'Z'#253#163'Q'#8#163#250'O'
+ +#246#191#151'%'#0#249#161#5#237#255'h'#23#251#191#218#214#190'J'#173#136'R'
+ +#248#207#129#127'6R'#8#144#239#7'H'#154'@k$'#18'q{<'#158'Pw!@B'#175#4'@'#155
+ +#16#9#160#230#160#212#23#0#239#171'j'#246'ZNv'#5'uG'#8'O$'#2#208'['#202' '
+ +#175'b&'#18#0#154#1'f'#3'W'#23'@'#141'B'#217#200'0'#25'd'#205#14'@'#188#255
+ +#224'%'#208#176'ae'#214#206'7'#16'L'#156#191'?'#236'}'#214#29'C:'#198#147#23
+ +#238'.'#245#219#24'Q '#243'`'#223's'#239#204#138'6'#208#27'HB'#168#244'7'#30
+ +'E'#2#8#161#250#31#8#129#223#205#169#255'n{+'#180'o_'#197'Z'#131'u'#14#2#137
+ +#133'&'#229#181'}'#143#194#239#195'?'#237'|'#8#144#217#255#168#181#215#247
+ +#214#12'T|'#206'^?'#27#161'3'#144'^'#175'7'#1#31#9#240#132#212'{'#214'uX'#151
+ +''''#15'"''?'#128#22#138'''.b'#171'?e'#4#234'L|8'#144#175#13'`'#166'B'#22'?'
+ ,#204'Wo>'#10#220'm'#245'Y'#3'p;'#202#27#253#221#209'S'#17#144#128'~'#17#0#213#4'x<'#30
+ +#180#2#244'Vr'#4'"'#17'T5{'#244'G8'#2#198'dA;'#9#184'Zg'#132#162#137'{2'#2' '
+ +#13'@'#199#178#2'5'#172'6@'#208#2#178#146#27',B'#243#230'5'#240#254'}'#23'B4'
+ +#18#202#234'y'#197#216#237#168'K`'#246'Ag'#164#237'x/\'#181#31#174#6'C'#155
+ +'~3'#134#238'A'#157#154'N'#185#247#163#172#159#151#171#252#227#212#255'p0'#12
+ +'Ao'#144#9'?'#173#254'T'#244#229'j'#222#200#156#131#130#253#175'VD'#253#19
+ +#243#236'?'#226#223#148#17#230'@'#18'`'#14'@'#222#254#167#134' }:'#0#9#253
+ +#145'F9'#146#128#18'I'#128#210#127#205'h'#10#20'#'#9'T'#198#19#138')'#155#157
+ +#133#183''''#18'2V'#149'A'#194'M'#13'B'#10'*'#231#161#25'P'#8#6#19#18#0#211#2
+ +#136#0'T'#160#16'*'#4'3gK'#198#223#195'h'#197#180'%G'#193#226#211'o'#202#206
+ +#201#184#170#31#142#0#248#216#127#208#23'd'#130#207#212#127#167#19#9#224';'
+ +#212#12'"b'#251'?1)'#191'}'#21#170#255#228#8'"'#251#159#26#129#214'R'#248#15
+ +#23'h'#234#1#208#136#194#239#232#203#254''''#244'G'#10#153'#'#16#15#166'"?'#0
+ +#10'p>'#158#168#140#252#0#206#128'vi'#179#215#194#21'h'#147'#PFf'#128#14#205
+ +#128#5#140#0'H'#3#224#162#1#252#244'`j'#24'*'#151'u'#27#17#200#240'P'#225'$'
+ +#26#127']'#9#31'>|%D'#130#190'L|'#157'L'#203#153#186#232#8'Xr'#234#13'd'#23
+ +'e'#228#28'O'#253'a7'#246#131#24'Cf`*('#131#19#239'zw'#200#199#233#235'7-<'
+ +#206#21#254#196#208'LE'#2' '#231#31#18'@'#160#131'['#253#157'M'#155#192'M'
+ +#222#255'h4'#169#254#235'U'#225#142'J'#139'c'#29#202'Q'#0#239's'#1#215#4#164
+ +'V'#176#255'qk'#17#154#128#160#240'G'#249'S'#13#158#0#186#250#1#144'eJ'#240
+ +'~'#234#215'\'#189#201'Q'#180'<'#22#151'S'#136#144#17#0'e'#255#217#202'g'#130
+ +#185#176#140'#'#1'3o'#6'h'#133#204#192#206'nA;'#148'Bw'#185#154'L'#182#186
+ +#219#248#191'7'#224#199'w'#159#2'O['#250'Zj'#149'M'#155#15#251'^xOF'#139'Q'
+ +#234#214'~'#9#31#220'?z:'#1'I'#1'J_?'#231#137#31#134'D'#224#221')'#184']'#127
+ +#207','#251'/'#193'y'#254#185#213'?'#138#230'j'#136'y'#255'I'#253#15'P'#243
+ +#143'-'#223'@'#200#239'I'#137#255#151#24#221'[l'#186#0#165#249#250#241'>'#150
+ +#0'$'#148#0#227#177#234'PKo'#235#143#253'/\C'#127#192#252#0#168#5'h'#220'n'
+ +#183#5#217#165#8'OXIf@'#131#219'r'#130';'#164#221#141#29#140#198#131'+'#20
+ +#172'8('#175'j&o'#6#232#144#0't'#160#210#169#147'Z'#128#16#17#200#5'8'#27#182
+ +#194#183'/'#255#5#26'~]'#201#134'F'#14#4'T'#133'f-'#29#15#19#230#239#15';'
+ +#239#127'2h'#12#153#207'&{'#239#238'?@'#195#250'o'#165#250#184'F'#13#246#189
+ +#240'n'#168#222#245#128#140#158'#!'#168#255#148#249#23#137'B4'#200#169#255'd'
+ +#255#7#220'T'#252#211#10#142#237#171'!'#134#143#197#249#231#202'e'#137#216
+ +#228#252#182#213'2'#136#7#248#248'?9'#131'X'#252#31#229#170#6'o7'#160#156#182
+ +'['#173'V__'#246'?'#161#223#4#128'f'#128'\'#156#15#128#251'rd'#155#9#193#152
+ +'v'#238'v'#151#237'\v02'#3'P'#184#149#26'5'#20#146#25'`6'#161#9#192#145#128
+ +'Z'#199#229#4#144'/@&'#242#5#236#176#234#15#225'"'#135#2'R'#177#234'~'#254#10
+ +#26#214'}'#11'm'#219#214'1'#205#128'&'#203#138#175#130'VvKq'#5's'#16#149'M'
+ +#159#15'e;e?#'#239#233'sw'#131'hX'#186#136#198'hA'#213'.K'#225#192#203#31#24
+ +#212'k'#251'j'#132#155'L'#250#137'sC?c'#164#254#211#234#31#8'A'#136#188#255
+ ,'l'#245'G'#245#191'a=x'#237#245')'#225'?'#179'&'#216'^fr'#209#196'W'#26#11
+ +#228#22'*'#0#137#0#132#30#128#129'@'#192#137#230'z'#159#246#127'w'#215#214
+ +#227#243#132'|'#0#178#1#168'0('#26#141#150'Q8'#16#31#155#176#197#145#127'a8'
+ +#166','#226#252#0'\4'#192'R6'#13#204'EU,$H~'#0#202#9' -@'#201#198#135')'#144
+ +#4#184#196#160#28'Q'#4#134#5'>z'#248'*'#216#246'}'#246'CT'#163#17#182#242'Ip'
+ +#236#31#223#200#216#241')'#233''''#17#3'V'#214'M+'#249'C'#250#15#156#224#226#254'@'#158#255'8'#231#249#143#6#195','#243
+ +#143#169#255#168#250#19#9#216'kV'#163#25'`gY'#172#130#250'o'#211#249#27'K'
+ +#140#30'R'#247#131'|'#250'/'#27#3'F'#241#127'R'#255#169#1#8#154#19#142#190
+ +#242#255#197#24#136#228'%'#195#129'V'#171#213#24#12#6#169'Sp'#25#17#0#238#171
+ +'j'#156'yg'#4#162#170'*'#193#12#160#162#10#163#173#4'l'#21#179#144#0#180'<'#9
+ +'hy_'#128#154'9'#3#169'T'#24'dBX'#176#135#14#194#144'$'#205'~^e'#250#191'3)A'
+ +'~'#136#215#151#31#1#174#198#209#212#2'\zP'#133#224'9'#207#241'c'#214#135#26
+ +#141#226#139#253#19#252#129#216#234#207'l'#127#170#250#139#176#208#31'9'#255
+ +'H'#240#131'H'#0'>G'#27'8jWC$'#28'I'#241#254'O'#176#182#175#213#170'b'#30'R'
+ +#255#241'O'#23'5'#0#1#222#254''''#239'?'#223#16#164#163#183#6' '#221']Z'#191
+ +#223#134#16#14#164#254#0#248#183#21'U'#13#150#21'H='#2':'#130#186#5#141#30'3'
+ +'+'#17'f'#177'~'#185#2'Tj5'#20'T'#239#10'z'#139#141'E'#2#136#0'4d'#10#176'f!'
+ +'*'#166#5'0_'#128#140#159'(<'#194#132'w'#168#160#130#159#215#151#253#14#127
+ +#16'cI?'#217#134'B'#165#129#179#158']'#157#222#131#242#131'>'#133#142'?'#204
+ +#246'G'#2#8'3'#225#231#9#0#247#142#186#159#192#239'la'#142'iA'#253#215#169'"'
+ +#238#241'V'#199#175#188#250'O'#9'@'#164#254#179#240#31'%'#255#144#250'O'#225
+ +'?\'#160'='#253#9#255#9#24#16#1#208'&'#152#1#8#19#153#1#148#21'H'#4#128#143
+ +'Umu'#22#156#25#142')'#11#133'.A'#20#247'7'#228#149#129'm'#220#206'I-@C$@CDY'
+ +#179#16'!/'#128'F'#137'e?E8'#151'AQ'#136'7'#174';r'#172#234'O"'#168'tF8'#227
+ +#201#244#246#148#16#135#253'('#238'O'#158#255'H'#16'U'#127'"'#0#15'n>'#170
+ +#254#179#163#250#191#10#205#189'0'#243#15#8#234#127#185#217#185#193#168#14
+ +#145#211#143#169#255#192#13#1#173#23#17'@'#147#160#254#163'lF'#250#10#255#9
+ +#24#168#196'13'#160#176#176'PE#'#195#168':'#144#6#134#224#133'T'#145')'#224
+ +#10#234#23'4{'#205#7#2#175#210'S'#21' '#211#2#198#239#14':'#139#5'4F'#29's'
+ +#10#170#13'|'#207'@'#181#138'=G!'#231'g'#9#202#248'K'#234'O'#154#224'`'#223
+ +#193'0@'#235#166#159#224#223#183#159'6,'''#31#143#20'h'#205'yp'#234'c_u'#255
+ +'`_b'#213#205#239#151#21#251#240#163#190'H'#176#227#201#213#191#211#249'G'
+ +#171#191#179#254'g\'#253#155'8'#231#31#175#254'k'#149#17#239'x'#171'}='#10'{'
+ +#132#138#127#200#251'O'#237#191#240#200#181'|'#2#16#169#255#164'&v'#168'T'
+ +#170'`w3'#0#251'{'#169'}>_0'#3'('#26#128#127'['#168'K'#16#158#188#130#8#0#168
+ +'m'#184#179#240#244'HLa'#21'j'#3#148#168#234#27#243#202#193':n:'#168'Q'#11
+ +#160#193'!D'#4'j'#22#18'$'#18'P'#240'aA9?V|'#16'W5'#130#176#229#235#247#224
+ +#243'G'#174'a'#182#223#24#164#3#133#1#143#190#251#157#244#28#140#15#252'S.'
+ +#127'"'#202#175#254'h'#223'G'#130'a^'#253#15#176#172#191'@'#135#19'W'#255#239
+ +#185#213'?'#130'$'#193'1'#7#140'3w'#252'f'#214#4')'#244#23'F'#185#242#240#201
+ +'?'#228#253#167#240'_'#13#202'"'#205#4'l'#31#136#247'_'#192'`D-'#165'8'#8#184
+ +#193#161#204#25'H'#154#128'#`X'#208#234'3-'#21'F'#131#145'3P'#169#209'@'#225
+ +#132#221'@k'#178'0'#19#128#242#2'Th'#6#8'Z'#0#171#20'Lv'#16#150'%'#157'&'#253
+ +'m$:R'#176#254'?+'#224#235'g'#239#200'l'#14#244#24#250#133#233#251#159#8#11
+ +#207#186'eP'#175'M'#249#221#242'!?'#230#253#143'q'#5'?'#156#237#31#134#8#31
+ +#250#163#212'_'#218';'#27#214#129#223#209#8#209'H$'#25#251#215'('#162#254#9
+ +#182'v'#234#250'K1}'#10#3'Q'#247#223#22'~'#213#175#193#191'k)'#249#167#175
+ +#246#223#189']'#235#128#223#159#208'-'#24'm'#13'='#178#143#141#204#0#188#191
+ +#146'i'#1'2Y'#229#22'{'#193'I'#145#184#194#196'r'#2#228#10'P'#170#149'`'#200
+ +#175#2'k'#233'T\'#253#181'H'#2#168#5#232#185#196' V)H'#179#4'),'#168#232#140
+ +#10#176#19#245#148'" zk'#178#228'?'#195#27#171'^{'#8'V'#191#254#176#212#151
+ +'1'#6#30#135#223#186#2'J'#166#207#239#246#177#148#223'_/'#191#189#4#223#232
+ ,'#E'#245#167#213'?'#24'a5'#255#17'?'#231#252#11#177#216#127#7#180'o['#9'Q$'#6
+ +'z'#14#181#6#163#215#149#153':'#182'X'#180'A'#154#248#19#225'{'#255#145'&@+>'
+ +#9'>'#133#255#234'q'#223#170#211#233#220'='#13#0#237#13#131'"'#0'J'#10'B'#150
+ +'a'#205'B'#3#129#128#153'J'#132'c'#177'X'#5'e'#6'rZ'#128#17#181#0#227#158#130
+ +'3'#144'T|'#138#255#231'O'#216#3'W'#127#19'G'#2#212'4T'#207#151#10#147'CP'
+ +#221#233#16#148#241#166#128'l'#7#233#30#204#202#152#251#236#240#213#147#183
+ +#192#175#31#189','#245'e'#140#129#7#253#6#207'~'#249#215#129#190'Jt;'#145#12
+ +']'''#189#254'd'#207'Gx'#199#31#173#254#254'P'#210#251'O{W'#227#175#224'u'
+ +#212#177'~'#0#148#31'@i'#194'jE4Pmk'#251#5#229'!'#138#199#160#252'o'#15'nT'
+ +#250'['#207''''#255'lG'#217'#2p'#244#167#246#191#175#171#30#208#187'%g'#160
+ +#201'dR'#163#218'a'#196#191'Yj0'#229#3#224#237'*|'#175#228#11'8>'#154'P'#232
+ +#153'3'#16'Ww'#188'P0'#20#146#22'0'#133'9'#1'Y8'#144'6=_)H)'#194'h'#6'P'#18
+ +#145'L('#22#202#206'lQIa'#175#217#0'o.'#251#157#212#151'1'#6#17'J'#166#205
+ +#135#195'n'#127'iH'#199#232'n'#245#143#161#240#179#184#127'0'#196'9'#255'|A'
+ +#206#1#232'qC{'#205'w'#168#25#132'x'#207'?'#183#250#151#24#221#219#172'Z'#127
+ +#155#200#249#151','#253'%'#225'GY'#169'C'#185'k'#182'Z'#173'.'#148#195#192'@'
+ +#156#127#2#6'M'#0#130'3'#16#153'G'#231'r'#185#200#233'W'#140#23'T'#1'\'#153
+ +'pe'#155#207#184#208#30'0'#206'Kj'#1'H'#2'*'#141#22#242'(='#216'bE'#2#208'$'
+ +#137#128#180#3#133'P($T'#11#138#251#6#140'`'#22'x'#251#250'c'#161'u'#211#26
+ +#169'/c'#12'"'#28'q'#215#155'PP'#189#243#160'_'#207#249#252'D'#141'>H'#168'#'
+ +#188#227'/'#192#173#254'L'#248'}AF'#4#174'z'#180#253#157'h'#251'S'#211#15'z.'
+ +#190'T%'#139#134'&'#230#183#255','#227'l'#255#16#18#0#139#253#163'l4'#144#240
+ +#227'mr'#0#178#206'?]b'#255#253'V'#255#9#131'&'#0#232#146#19#128#23'H'#163
+ +#195'h'#0'[%nU1'#210#2#28#133#199#198'P'#180#217#160'p'#210#2'P'#192'u'#150
+ +'"'#176'U'#204'fu'#1'I'#2'`'#14'A$'#1'V.'#204#153#2#192'L'#7#254#242'Fh'#170
+ +#176#223#217#10'/'#159#183'p'#204#233#151'C0'#20#148#194#9#127#255'b'#208#175
+ +#151#241#169#190#204#8#136'w'#198#252#185#130#31'A'#245#199#205#31'`'#197'?'
+ +#1#23'e'#253#173#225'<'#255#209#206#213#191#216#232#169#177'i}'#173#252#234
+ +'O'#153#127#212#5#150'B}'#245'T'#246'KN@Z'#253#145#0#156'~D'#127'S'#127'w'
+ +#184#222'!|V'#201#10'A'#179#217#172'#g '#222#199'B'#130#184#175#162'=j'#1#11
+ +#218#253#134#185#204#169'Ge'#194'D'#2'j'#13'X'#199#205#0'}~)S'#255#213#6#29
+ +#211#6'Tz'#13#31#22#228'{'#6'$'#253#1#248#142'd'#217'm)'#158'-|'#244#231's'
+ +#161#246#135'O'#165#190#140'1'#136'p'#240#205#207'C'#217#172#133#131'|5'#159
+ +#236#203#219#253'B'#177'O'#156#217#254#188#234'O'#4#224#193#149'?'#192#217
+ +#254#142#237'?@'#200#211#193'&'#1'1'#2#192#255'T'#242'hp'#162#205#142#182#127
+ +'"'#202#135#254#216#234'/'#196#254#129#235#250'['#143'2'#215'N'#206'?'#170
+ +#252#235#173#243'oo'#24#18#1#144'3p'#221#186'u'#172'QH '#16'0'#161#6'P'#128
+ +#23'Im'#195#153#22#128'W2n'#155#179#224#247#225#184#202'"h'#1#148#2#172#209
+ +#27#208#20#216#13#212#148#19' '#242#5'(u'#184'Qr'#16#159#27' h'#2'2'#161#157
+ +'xOq'#193#158#222'E'#142'/'#172#207#158#176#19#174#12'c'#181#253#185#130#202
+ +#249#251#192#254#215'='#193#253'1'#136#223#148'X'#248'i'#229#135'8'#151#238
+ +'K'#142'='#177#227'/B'#234'?'#222#246#180#214#128#167'e'#243#14#171#127#185
+ +#197#181#209#168#10'R'#184#143#250#190#177#208#31'n'#173'(_'#245'|'#209#15'%'
+ +#0'5S'#230#31'j'#224#254#193'8'#255#4#12'uYMf'#6':'#28#14#189'R'#169#180#225
+ +'E'#22#227'F'#137'AL'#11#240#133'5'#211#235#220#182'}'#4'-@'#193#180#0'5'#24
+ +#11''''#128#185'x"'#175#5'p$'#192#180#0#161'u'#24#223'>'#172#147#4#248#203#29
+ +'A'#138#192'sD'#0'c'#21'~9'#1#26#22'z'#242#243#171'Q'#251'T'#15#238#0#188#25
+ +#215#185#242#243#170#127#152's'#252#145#131#143#179#253#3#16#246'"'#17'x=,'
+ +#233''''#18#12'B'#140#250#253'E'#185#196#31#20'|G'#133#197#181#5#15#21#19'V'
+ +#127#161#237#23#169#253#192#245#252'k'#224#203'~'#221'}'#245#253#239#11'C&'#0
+ +'A'#11#160#182#225#168#9#144'/'#160#0#137#128#249#2#144#8'H'#19'(k'#240#216
+ +#246#246#132#181#149'r'#150#29#168'`5'#0#10#10#11'V'#206#3#141#201#10#26'#g'
+ +#10#168#146#17#1'5'#243#7#176'b!'#218#152'#'#145'+'#27#30'I'#166#192#138#211
+ +'v'#129#144#215'%'#245'e'#140'zP'#225#218#161'w'#188#10'E'#211#230#13#234#245
+ +#9#174#212#143#247#250#199#217'l'#191#4#223#230'+'#30#140'$W'#127#138#251'3'
+ +#199#31#222'v5'#252#2'AWK'#202#234'/C'#218#168'F'#213'_)'#143#134'zZ'#253#5
+ +#207'?n'#142#254#182#253#234#245#189#167#227#243#19#215#7'h4'#26#214'4'#148
+ +'O'#15#166#188#128#242'h\^'#177#213'Yxp'#2#215'uA'#11'P'#168#212#160#181#20
+ +#176'ra'#181#174'S'#3'P'#11'Z'#0#229#6#8'Q'#1#190#155'0'#136#202#134'G'#130
+ +'_'#240#213's'#22#130#175#189'Q'#234#203#24#213#160#197'e'#191#27#158#132#10
+ +'T'#255#7#140#132'x'#166#31#231#244'#Afv?'#173#252#225#8'K'#250#137#6'B'#172
+ +#221'W'#132#247#250'S'#165#159#139#154'}'#160#240#211' '#16'a'#245'/'#212'{'
+ +#234#10#244'>'#10#243'u]'#253'i'#236'7'#181#253#222#142#130#223'@U'#127'H'#8
+ +#238#129#230#253'w'#251#254#211#241#25'v'#213#2#240#194#10#132#136#128#160#5
+ ,'8'#2#198'9'#173'~'#211'l'#210#2'@'#161'`'#14'A'#5#154#2#150#178#157'@'#159
+ +'W'#202#146#130#152#240#147#22#160#227'H'#128#181#15'S'#241#237#196'EY'#130
+ +'2y'#186'.]Z'#252#235#210#3#193'Y'#187'Q'#234#203#24#189#192#223#210#146#203
+ +#255#10#19#247#26#194#236#6#22#231#7#214#224#143#229#250#243'N'#191'X'#132#19
+ +#254#8#175#250'G|'#156#6#16#246#243#142'?'#159#155#21#4#9'q'#127#149'<'#26
+ +#168#206'k_'#143#199#139#241#171'?y'#254'Y'#213#31#173#254#184#175'U('#20#181
+ +#180#250'k'#181'Z'#7#146#192#144'W'#127#246#17#164#235#163#236'N'#11' _'#0'p'
+ +#17#1#26'$R'#180#213#153#191#127'8'#166#178#10#217#129'$'#220'j'#189#145#229
+ +#6#168#13'z.)'#136'O'#17'V'#178#220#0#222#20'`'#141'D'#249#14'Bra'#196#24'$'
+ +#213#128#225'J'#5#31#222'r24'#174#249'R'#234#203#24#149' '#13't'#191#27#159
+ +#134#178'9'#139#7#252'Za'#213#231#179'}x'#187#159#19'~Z'#209'i'#245#143#133
+ +'"'#201#176#31#229#252'GI'#248'q'#239'i'#217#10#222#214'm'#140' '#152#237'O9'
+ +#255#248'_'#165#217#177#193#160#14'S'#166#31#9'4y'#134#133#145#223'Md'#251
+ +#147#240#163'L'#213#167's'#245''''#164#141#0#186#243#5#0'7H'#180#146#15#13
+ +#150#249'#'#234#9#181#238#252'%l'#29'Wt'#154#2#134#252'r0'#151'N'#229'j'#3
+ +#152#6' r'#8'R'#247' '#149#146'+'#24#18#154#137#178','#193#225#239#24'l\'#243
+ +#5#252#231#230#147#165#190#140'Q'#7'CA'#25#28'~'#223#187'h'#130#230#15#252
+ +#197#157#195'y:'#139'|'#226#156#205'O'#182'?'#173#234'L'#245#167#132#31'a'
+ +#245#199'-'#26#8#254#127'{_'#22'kYv'#158#181#246'x'#230's'#238'XsWwW'#187#219
+ +'v'#187#227')'#241#0'v'#136#193#145#8#194'F'#8#5#148#4')'#145#176'P'#132#132
+ +#20#241#18'!9'#188#0'/H'#188'!'#224#1'x'#2#9#17#144#128'XHH$`x'#128#7#144#172
+ +'$'#216#198#221#158#186'k'#174'[w:'#243#176#7#254#239'_'#255'Z{'#237'}'#207
+ +#173#186#213']w'#170#190'K'#218'w'#15#247#12#251#236#189#191#239#159#255#165
+ +#166#253'='#181#243#222'wT2'#155#209'k'#23'\'#25#8#159'A;'#158'n'#223#232#238
+ +#161#229#19#192#159#152#184'?:'#254#162#230'_'#233'Y'#127'n/'#145#254#0#255#7
+ +'*'#27'}'#158#208')E'#4#136#173'V'#137#165'.'#139#22#128#174'A'#215'Q:|o'#208
+ +#251'b'#127#214'x'#153'+'#255'B"'#129' d'#144#247#174#146')'#176'zUH@'#8#160
+ +#225#248#3#184'V@'#155#2'l'#14#248#158'T'#15#150#127'I'#158#23'?'#201#243#206
+ +'x'#28#144#198#191#254#181'O'#169#217#197'D'#159'''3'#232'ay'#245#203'_S'#191
+ +#240#219#255#248'H/_'#250','#229#198#225'/'#137'>'#22#252#186#208''''#227'2_'
+ +'m'#247'c'#129#218#191#24'C'#19#152'p'#155#175#249#184#207#182#191'Q'#253'=z'
+ +#247'k'#171'['#127#28'x)'#138'}JY'#127#180#127'_<'#255'h'#251'u'#239'yK'#127
+ +#254']'#207#243#242'.'#203#11#160#31'q'#21'~'#0#163#5'dyp'#229'G{'#27#191#152
+ +#229'~'#13#0#246'E'#11#136#234#13#181#242#210'gT'#173#211#213'&'#128#144#0
+ +#182#131'Z'#173'0'#5#196#31'P'#174#28'<'#191'Z'#192'w'#254#229'?P'#127#244
+ +#187#23'U'#128#199'=z/}D'#253#153'o'#254#11#213#189'~'#235#253#127#8'W'#248
+ +#228',ssW'#242'['#187#159'l'#250#217'\K'#127'V'#253#167'"'#253#231'j'#255#222
+ +#247#213'd'#239'>{'#253'a&(N'#249'e'#199#223'{'#235#205#17'z'#251'C'#250#163
+ +#3#12#247#251#163#5'Y'#128','#253#197#7#240'p>'#159#239':'#158#255#15','#253
+ +'1'#158'7ll'#227'Pd'#7#146#22#128'9'#178'.!'#18' Q'#1#172'/'#239'Oko'#220#31
+ +#174'~'#206#19#135#160'1'#5#226#246#138'Z}'#233#211'l'#2'@'#250'G-q'#8'J'#243
+ +#16'?'#150'Ta3'#211#176';'#229#184#167'='#186#207#214'A'#244#244'G'#150#204
+ +#213#191#250'K'#175'?'#243#172'D'#23#227'h'#163#181'y]'#253#220'_'#251#166'z'
+ +#229#231#223'g'#193#149#17#252'z'#30#175#178#211#15#246#187#145#252'H'#248
+ +#129#228'g'#2#152#217#176#31'r'#255'G'#219'w'#200#246#127#135'$'#255#140'I"O'
+ +'u'#185'o=\'#244'_'#233'm'#191#157#231#252#137'\'#239'o'#26'~@'#250#211#254
+ +'m4'#251#132#244#199#12#192#181'Z'#13'>'#130#217'Q'#27'~'#30'e'#251#6'x'
+ +#138'/'#237#248#203'otw'#223'i'#199'3'#132#249#172#227#143#176#129#164#159'-'
+ +'H|'#241#252#179#227#143'0'#180'3'#164#177#183#183'7{'#214#134#31'O'#27#199
+ ,'B'#0'J*'#5#209'6'#140#206#187#213'h4`'#10'\VZ'#250#223#148#245#165'E'#26'\!'
+ +#18#248'R'#166#194#136'I'#128#147'~"'#235#15#136#219#29#173#1#136'C'#16#25
+ +#130'a='#226#181'o'#138#134'l'#142#128#152#3'b'#18#148#148#128'e'#191#242#164
+ +#177#246#148'+'#253'?'#255#225'o'#169#31#253#193#191'='#225#147'z1'#6#188#249
+ +#31#251#139#127']'#253#204'_'#254#155#207'>'#163#239#147#158#13#145#250#182
+ +#194#207#218#252#162#250'/t'#184#143#19'z&s'#209#0'D'#253#167#237'>'#236#254
+ +#253#251#252#154''#174
+ +#230#163#254'i'#159#202#185#25'+/'#127'T}'#246#27#127'G]'#255#220'W'#223#215
+ +#251#151#206'>g5'#254#188'P'#251#179'\l~'#29#235#207#165#188'W'#199#251#181
+ +#218#159#10#248#19'&'#130#153#26'o'#223'S'#253#135'?`'#211' [,'#172#215#191
+ +#17#206#251'/'#147#221'/'#223#4#213#31'&'#192#152#22#132#130#224#12#180#170
+ +'?-'#152#231#15#14#193#145#211#236#243#185'I'#127#251#155#143'iX'#135' &'#20
+ +'%'#192'cZ'#241'Mt'#14#130'/'#0#166#0#189#230#10'-k'#15'G'#189#183'v'''#205
+ +#151#141'w_;'#250'b'#213'\'#135'?'#224'u'#21#213'$1'#168#17'["'#240'M[q'#19
+ +#30#180'='#5'i'#9#138#217#134'r'#201#21'8'#15'n'#129'{'#255#231#191#169#255
+ +#250';'#191'z'#218#167'q'#166'Gs'#253#138'z'#233#203'_S?'#243'+'#191#165#234
+ +#171#155#207#245#179'M#'#15'//'#8#0#21'}'#153#16#0#219#253#146#230#11#149#30
+ +'E> '#0#150#254#0#255'Tk'#1#179#193#158#218#187#253#135#244#191#194#238'W'
+ +#176#251#189'd'#241#234#202#246#247'B'#178#255#149#168#254#180'L'#137#4'0'
+ +#203'/:'#253#222#147'f'#159'w$'#1'h'#219'8'#254#158'W'#216#175':'#142#149#0
+ +#224#16#252#214#183#190#197'MC'#136#201'Z'#244#195'`'#152']'#22'-'#0'$pM!J'
+ +#160#188#149'w'#247#214#190'0Kk=eH'#0#210#157'H'#160's'#249'5'#186#233'/IRP'
+ +#205'j'#1#8#13#194#28#240'b'#157'#'#160#195#131#18'"4'#25#131#158''''#10#192
+ +#249#9#19#254#254#223#254'e'#245#240'";'#176'4'#26'kW'#212#205#159#255#154'z'
+ +#235#24'@_'#26#206#196#157'6'#209'G&'#241#204#165#161'g.'#177'~V'#253#167#218
+ +#238'O'#5#252')'#183#249#30#178#211'o1'#30'j'#233#159'&'#186'4'#152#237#254
+ +#189'w'#218#209#180'oT'#127'z>9'#230'Ok4'#250#228'f'#31' '#0#244#249#203#178
+ +#12#190#128#253#227'p'#252#185#227#184'aa'#29#130#244#163'j'#164#1'tMn'#0'H@'
+ +#136#0#29#133#215#147'<'#218#248#233#222#250#23'3'#130#189'q'#10#194#31#0'{'
+ +#191's'#245#227#170#209#187','#192#143#181'?'#192'5'#7'b]>\'#20#14'A'#11#208
+ +'D'#144#151#10#136#156#159#251#164'_~'#18#254#129'C'#190#31's'#1#254#222#175
+ +#127'A'#141#30#221'9'#129#147'8'#187#163#177'vYK'#250'_'#251'['#31#12#244'O{'
+ +#194#141#202#159#231#142#237'o'#192#159#217#226#158'\'#178#252'8'#140'7[X'
+ +#192'C'#242#167'Sc'#255#143#9#252#127#164'f'#163'}Q'#253#19#235'7Xo'#142#238
+ +'m6'#251#144#240#244'Hz'#166#216'g'#12#144'#'#227'O'#21#210#255'.'#225#4#181
+ +#254#187#180' '#230'?'#251#250#215#191#158'>O'#199#223#179'\'#158#231#241#249
+ +#236#16#188'v'#237'ZD?'#166'I?'#142'M'#1':~]'#242#2#224#16#132'V'#176#218#159
+ +'7n'#222#31#174'|'#138#253#1#220#16'$'#212#243#6#196#177#234'^{K'#213'z'#235
+ +'L'#0'69'#168')'#249#1'5m'#10#232'D'#161'P'#207'1`'#252#2#158'8'#6#13#1'x:'
+ +#195#235','#155#4#217'|'#170#254#227'o|^M'#182#31#156#246#169#156#232#208#160
+ +#255#243#234#19#4'zl'#31#247'0A'#23#207#216#251#210#196#147#255'!'#192'5Y~'
+ +#185#128#31#146'?'#19#181#127'!$'#144'Ng'#236#245#239#223#253#174#154#13'w4'
+ +#248#209#223#15#170#127#134'x?'#236#254#157#183#229#27'!'#253#145#245'7'#161
+ +#239#178'1'#127'I'#246'A'#143'?T'#254'm#'#227#143#204#229#217'q8'#254#220'q'
+ +#18'0`-'#128#214#193#189'{'#247'0'#181'x'#11#141'C'#148#6#189'!'#1#248#5'6i{'
+ +'e{'#210'}'#227#241#164#253#154'.'#24#242#25#208' '#129#176#214'P'#221#171'o'
+ +'q'#255#128'@'#204#129#192#248#3#140'S'#208'!'#1#27#29'p'#27#140'B#p'#253#1
+ +'v6'#226#167'\'#134#147'L)'#150's'#193#148#224#223#250#245#159'S'#211#189#173
+ +#147#251#238#19#30'A\S'#221#151'^W'#215#190#240#139#234#245#191#240#13#213'X'
+ +#127'N'#160'?'#202#253't<'#253'&'#191'7wm'#254#212'H'#254#2#252#25#131'_'''
+ +#251'X'#181#31#14#192#217'L'#245#31'|_M'#247#183#216''#239#186#170#127#179#217#156#16
+ +'^'#22#199#225#248'+]'#138#227#248#208'e'#223'cL'#1#218#174#199'q'#220'Y,'#22
+ +'k'#196'vp'#2#26#18#192#246#6#189#180#247'`'#216'{s'#127#214#188'a'#253#1'a'
+ +#164'g'#24#170#183'T'#239#198'[*nuu'#211#16'h'#2#13#153'h'#148#246#217#31'P3'
+ +#230'@A'#2'z'#242'Q_'#151#17'{^'#209'r'#251#6#242#202#229#240'N'#185#167'X'
+ +'Bv'#228#127#250#198#159'T'#227#199#247'O'#245'<'#158#215#128'F'#215#190#246
+ +#138#186#242#179#127'Z}'#228'k'#191#161'z/'#127#244#216#190#235'i'#247#210
+ +#230#243#155'F'#30#166#176'G'#156'}'#214#219#15#135'_R'#128#159#157'~'#211'"'
+ ,#236#135#253#193#131#183#9#252#247#11#143'?'#252#4'Y'#170'B/'#153#223'$'#240
+ +#199'~2sC~2'#193#7#167#251'*'#173#250#223#145'\'#255'GF'#245''''#201#143#196
+ +#160#244'8'#165#191#190'.''3'#216#20#248#202'W'#190#226#147#25#16#175#172#172
+ +'4'#8#252']'#250#161#27'2'#185'('#204#0#16#1'G'#5#8#176#157#187#131#149'O'#14
+ +#231#141'K'#202')'#29#230#28#129'f['#245#174#127#146#236#255#150#245#9'0'#17
+ +#196#146#31' '#154#128'I'#27'6'#181#3#158#211'_'#176#152's@'#251#8#220'^'#131
+ +'O'#157#233#229#20#198'w'#254#233'7'#213';'#255#254#159')'#253#12#157#159#1
+ +#226'mn^W'#151'>'#253'e'#245#234'/'#253'U'#181#249#214#23#143#241#203#158#208
+ +#198'/'#175#188#206'H{'''#179'O'#247#242'3'#224#207'X'#234'g'#21#201#207#241
+ +'~'#2'}'#6'{_'#136#0#165#189#147#157#247#24#252#186#181#151#158#212#211#207
+ +#210#228#229#149#237#31#212#130#197#196#181#251#149#14#249#193#238#223#18#213
+ +#31's'#252'q'#200#143#182'w'#8#15#195#231'Y'#236's'#132#203'vb'#195#166#9'_'
+ +#191'~'#29#154'@'#11#181#2#240#7#208#15#191'*aA'#204'1'#8'=p5'#247#252#206
+ +#157#254#234#167#198'I}'#213#23#167#160#23#232','#192#184#217'c'#18#8#26'uM'
+ +#0'l'#18'D'#146')'#136#16#161'4'#18'A'#152#208#180#21#243#29#18'0'#221#133'<'
+ +'!'#0#229#2#255'9D'#12#142'a6'#227#225#253#159#168#255#254#219#191#172#134
+ +#247'~z'#130#183#236#217#6#8#186#190#178#169#214'>'#254#179#234#213'?'#251'+'
+ +#234#218#159#248#165#163#191#249#176'k'#246'<'#158'PG'#218'kG'#191#201#231
+ +#207'm#'#143#194#230'/'#210'{y'#153#27#169#191#208#192#135#148#135#250'O'#132
+ +'0'#217#190#163'F[?"'#146#152'Ks'#15']'#223#143'?7'#187'{o7'#194#217#208#177
+ +#251#231#244'l'#163#197#23#18'='#182'%'#215#159#193'O8'#128#25#176#141#132
+ +#159#157#157#157#169'x'#253#13#248'_'#24#2#224#239's'#19#132#8#248#173'$I'
+ +#216#31'@'#11'B'#130#208#4#216#31'@'#235#149'\'#249#157'w'#247#214'?='#205
+ +#162#14#146#132#152#4#184'7'#0#145'@gMu'#174#189'%'#229#194#162#1#152#252#0
+ +'h'#1#146'-X8'#6#203#154'@a'#18#248#197#228'#N1'#209'Y'#237'='#248#255#254
+ +#205'?R?'#248'w'#255'DMw'#30#158#234'y'#4#245#166'jn\S+'#175'}'#130'$'#252
+ +#159'R7'#190#244#231'T}'#253#202'i_'#158#202#200#203#210'_Rz='#227#236#147'r'
+ +'^'#6#191#163#246'['#240#139#202#15#224#179'z'#207'*'#191#246#1#204'v'#31#168
+ +#193#195#183#233'usn'#238#193#239'Cyo'#154#229'W'#187'{?'#236#196#147#190#168
+ +'l'#214#238#23#167#223'.'#236'~ZX'#245#135#211#143'0'#240#152#222#187'O'#166
+ +#241#4#9'?'#199#233#245#175#142#211'x'#202'}'#152#2#180#6#9'X'#127#0#217'?'
+ +#151#29'S'#0#26#1#252#1#221'$'#243#187#239#246#215'?'#179#200#163#134'o'#204
+ +#1#216#247'$'#233#153#4#174'|'#156'H'#160'nA'#207'f'#128'h'#4'L'#2#145'&'#1
+ +#21#233#168#2#147'@h'#8'@r'#5'|'#129';'#214'2)'#225'Y'#159#166'|'#240#222#219
+ +#234#143#255#249#223'W'#15#254#247#31#208'C99'#190'/'#162'k'#17#183'{'#170'u'
+ +#245'e'#181#250#209#207#168'+'#159#251#170#186#250#249#175#210#245#175#159
+ +#246'%x'#250'03L'#219#130#30'c'#231#23#253#251#140#167#223'H~V'#225#231'I'#1
+ +'x'#6#255#156#155'{'#178'&@'#255#155#238#222'U'#163'G'#210#206'{Q'#168#253' '
+ +#146#203#173'}L'#231#181#131'/q'#156'~H'#245'E'#188#127#15#133'='#180#141'F'
+ +#144'P'#251#225#244'{D'#207#245#222'I'#218#253#238'8'#141'G|'#169'?@f'#22'b'
+ +#167#160#210'Z'#0#182#215#233#1#236#204#147'`'#229#189#254#250#167#19#21#198
+ +''#28#234'#p'#231'R'#217#151'I'
+ +#184#15#142'>'#14#251#137#31'`'#188#253#30'-'#239'jR'#224'i'#188'S'#142#22#0
+ +#252#27#205#193#237#245#198#240#145#11'~z'#182#140#221#15#240'o'#153'J?z'#230
+ +#239#201'4'#223#232#240#131#6' '#199#150#237#247','#151#242#196#190#215#245#7
+ +#208#197'h'#18#248'{'#164#10'm'#18#192#175'Hx'#144#179#4'iY'#3#9#204#210'x'
+ +#237#246#254#250'''3'#207#15'Yr#<'#24'j'#18#8#27'm'#213'!'#18#136#154#29#2'~'
+ +'h'#181#0#228#8'x'#236#20',H'#128#181#129'J'#152#208#212#17#24#18'`'#231' t'
+ +#148#220#153#144#164'`'#132#234#147#246#244'+y'#10#4'1'#219'{'#172#230#253#29
+ +'5'#31#236#210'zO-'#134#251'\9'#217'}'#249#13#213#185#249#250#217#149#224'G'
+ +#189#142'K'#239'C'#17#222's[u'#219#16#159#11#254#170#212#151#220#254'L'#154
+ +'z'#148#9'@K'#255#209#214#143#213'd'#239#30#189'n'#206#145#1'~'#159#228#248
+ +#175#214'F'#15#174#180#251'w'#243#2#252#200#244#131#221#15#240#195#238#127','
+ +'!'#191'{R'#223#15#27'n{:'#157#14#136#0#160#194'%''e'#247#31#245'r'#31#251'w'
+ +'W'#243#3#200#28'@3'#209'Md'#10'*'#237#16#196#26'$'#176'J m'#141#23#181#205
+ +#187#253#213#183#136#4#2'm'#207#11#9'p'#4#160#201#230'@D'#234#170#213#4#156
+ +#181#23#11#17#24'M'#128'L'#2#21'j'#191#130'2s'#17#26's'#192'M'#30'2UEn'#163
+ +#145'3l'#26'|'#232'F^'#10#226#8#224'M'#21#159#210#158'}'#137#239#187'i'#189
+ +#218#230#215#128#207#13#248#173#228'_0'#200#217#241'7'#211#161#190#225#163
+ ,#183#213#172#255'H'#146'|'#140#218#175'k'#251#187#209'd'#235'zw'#239'=m]d'
+ +#153'x'#252#145#236#3#240'#'#151#127'['#233'y'#253#24#252#216'F'#178#207'I'
+ +#198#251#15#27#167#253'('#151'R'#133'I'#11'h#'#25#136#180#128'K'#208#4'h'#31
+ +'Z'#0'H'#0#164#176'B@lM'#147'x'#237'N'#127#245#19#169#23#198#218#179'/>'#1
+ +#174#12#172#17#9'|L'#197#157'uM'#10#198#15'`'#192'/m'#198'=!'#2'_z'#10'('#19
+ +'%'#16#231#160'2'#230#128#239#21#4'`'#174#214#139'>]'#241'y'#25'.'#234']sGl|'
+ +'O'#202'wm'#3#143#170#179#207'8'#250#0'f'#212#243'/'#28#240#27#231#31#175#167
+ +'j'#240#240#7#164'ImK'#140'?'#209#196#145'j'#240#175#213'F'#247'/'#183#145
+ +#226'k'#193#159'I'#154'/g'#250')]'#226#251'H'#230#245#131#228#199#164#30#143
+ +'1'#171#207'|>'#31#31'w'#170#239'Q.'#227'i'#223'F'#207'8'#5#209'@'#4']'#132
+ +#208'P'#212#9#15'"O'#224#138#201#20#4#9'$y'#220#189#189#191#250#214'BE'#245
+ +#18#9#136's'#176's'#249#13#21'w/'#177'/'#192'3'#181#2#177#244#16#176'&A'#164
+ +#253#2'b'#14#168#208'/'#146#134#140'i '#13'F'#172'F`'#175#152#163#10#156#159
+ +':'#163#23'f'#148#146'xl'#171'.}'#140#193#159'i'#201'oc'#251#169'n'#226#1#240
+ +'+'''#204#151'K'#190'>'#171#244'3'#241#250#211#177'\B'#127#201't'#162#6#247
+ +#191#175#18#228#246'''s'#157#21#232#128#127#163'1'#184#189#217#28'>'#210#138
+ +'F'#150';'#146#31'*={'#252#149#238#237#7#240#223#151'p'#223'cH'#254#197'b1'
+ +#186'v'#237#26#156#131''''#234#244#171#142#179#240#236'Z'#18#232't:1'#177'b'
+ +#157'.T'#27#149#131#232'$'#4#2'0$ '#173#198'A'#2#205'L'#133#237#219#253#181
+ +'7gY'#220#214'}'#0#196#174#143't)qk'#243#150'j'#172'^'#215#146#222#1#189#217
+ +'f-'#160#166#147#139'8Dh'#219#142#7#133's0'#240#10#141#192'I rs'#137#205'f~'
+ +#224'''='#225#10'?'#211#173'>'#175']'#130#142#248'h='#245#250','#191#178#185
+ +#211#151#223#5#191#246#238#235#248#190'J'#181#202#175#4#176#156#155#159':'
+ +#246#254'\'#131'?'#183'j'#191'd'#242#17#25'$'#147#161#234#223#255#158'Ji]H~'
+ +#157#225#167#210','#191#220#217#255#201'j<'#217#21#193'o'#193#175#138#190'~'
+ +#166#190#255#1#164#191#132#254#30#163#190#159#198#168#209'h'#204#143';'#207
+ +#255'9'#222#165#227'?'#15'S:'#140#162#161#241'x'#140#134#162#29#169#25#184'd'
+ +'4'#1#165#251#7#160#177'H'#143#174'X'#147#16#218#188#211'_'#251#216'8'#173
+ +#173'x2'#239#160#206#254#211#18#191#190'rU'#181#214'oiM'#192#250#1'B'#157',$'
+ +'d'#224'I%'#161#138#138#190#2#166#152'Hq'#132#192#244#23#240#203#145#2#167
+ +#243'P.'#161#195#234#21#245#202#127#158'q'#228'O'#220'='#179#195'{'#234#129
+ +#167#255#238'|'#201#207#21#144#27#129#175#14#11#237'9'#133'<*-b'#251#197#162
+ +#129#207#210#127#190#144'p'#223'B'#180#129#5#255'o>'#216'a'#155'?'#157#142'u'
+ +''''#31'Z'#148#128#223'#'#241#127#181#187#247#163'n8'#27','#3#191#210#225'>'
+ +#128#31'-'#188#31#144'&'#203#14'?'#228#248'#'#220'G'#175#27#161#200'G'#157
+ +#146#211#239#131#222#157'c='#23#248#3'~'#252#227#31#251'h%F'#154'@'#195#228#8
+ +'`V!'#164#12#131#8'h'#141#164'!4'#26#237#210'Uk'#17#240#234#247#6'k'#175#15
+ +#23#245#13'c'#14'0'#17'DP'#241#145':'#220'Sm2'#9'PG'#224'K?'#193#2#252#142'6'
+ +#192#254#0'c'#14#232'm'#155'8Ti9f'#195#134#158#201'(tr'#207#171#253#7#204#173
+ +'=KW'#250','#143#202#245#202#157#166#156'%'#208#27#162#200#164'eW'#150#29'H'
+ +#231'Ui'#1'z'#227#237'O%'#212#151#207#231#142#195'O|'#0'D'#2#147#221#219'j'
+ +#178#253#158#222'w$?>'#223#167#15#184#222#219'{'#167#21#204#199'K'#192'ob'
+ +#253'h'#234#137'4_+'#249#233#153'}L'#160#223#165#231#23'5'#0' '#137'3'#1'~'
+ +#231'2'#159#153#193'$'#240#189#239'}/@x'#16'$@Z@W'#26#137#184#154#0'"'#3#235
+ +'('#28#162#27#129#18#227#248#254#160'wko'#222#188#234'['#245']k'#2#200#26#244
+ +#227#26#153#4#31'Q'#181#206#166#150#248#174#244#23#223#128#206#17'0'#249#2
+ +#129#205#30'TN'#6#161#237'@'#236#251#5#1'8m'#201#221#26#3#235#164#170#22#27
+ +#157#181'+~F'#134'Wr'#228#185#155#249#1#240'k'''#159'H'#251#180#144#250#165
+ +'t^'#168#251#137#238#215#175#9'@<'#254#226#237'7'#26#0#19#0#166#233#154'N'
+ +#213#136#164#254'|'#180#171#227#251'IR'#2#127#160#146#217'K'#221#221#31#214
+ +#131#197'T'#192'o'#28'~F'#242's'#129#15'r'#252#209#220#3#146#31#26#0#212#254
+ +'('#138'v'#7#131#193#136#180#218#19'M'#243'='#210'u?'#237#19'XvN&<'#184#181
+ +#181#21#211'Ek'#208#5'4$'#128'lA'#180#24#135')'#192'$@'#251']'#248#4#232'X'
+ +#237#209#168#243#210#246#180'}SO8bH@2'#0#137#8#234#189#171#170#185#241'*'#131
+ +#222's'#181#129'H'#147#129'''-'#199#149'q'#14'F'#21'm'#192'u'#16#154'z'#2'&'
+ +#3'eg)'#202#29'2p'#181#255#220'!'#133#15'f'#26#188'(C'#210'u\'#137#159#23#181
+ +#249#202'sT}'#199#201'W'#168#249'"'#245#197#214#231'2'#222#180'p'#242'1'#232
+ +#165#148#215'z'#252#141#234'/'#170'>'#219#254#201'B-'#250#187'j'#184#245#14
+ +#29#27#219#200#128#174#229#151#137';'#189#249#228#165#238#222#15#185#170#143
+ +#235#8'l'#168#143'S|'#149'd'#249')'#237#224'C'#184#15'R'#255#1#212'~'#178#249
+ +'w'#233#249#29'6'#155#205')i'#183#201'iz'#252#151#141#179#250#4#150'H'#160'A'
+ +'c2'#153#160#145#8#155#3'B'#2' '#3#209#4'T'#151#128#136#190#131#181#253'Yc'
+ +#243#225#168#251'Z'#166#194'PKn'#169'!'#8'C1'#9#186#164#13#188#193#213#132#0
+ +'>'#28#129#158'D'#4#220#16#161#155'9'#168#156'Z'#2#229#18#129#231#23#179#22
+ ,#251#198'I'#232'j'#3'E'#30'a'#238#148#25'z'#213#146#195#3#153'mg'#245#182#188
+ +#223#187#249#4#127#134#233#191#167#156#198#28'|'#188#2'zP'#168#3'~'#211#173
+ +#135'U}'#9#239')'#167'O?'#188#245#249#28#251#11'+'#249's)'#238#201'%'#207'?'
+ +''''#240#143'wn'#171')-'#153'y]*R_f'#238'iG'#147#237#171#173#253#219#129#151
+ +'&:'#151'(3e'#189#240#246'3'#248#149#206#242'CO?'#246#248#195#230'G'#168#15
+ +#224#167'eH'#166#236#20#177#254#179#6'~}'#205#207#238#176#133'C'#4#254#136'.'
+ +'b'#147'L'#130'.H@:'#10']6'#225'A%$'#128#16'!H`'#158#133#237#187#131#222#235
+ +#179#172#214#230'y'#3#140'o'#192#132#10#163#186'j_zM'#197#221#205#2#248'f1'#4
+ +#16'W'#142#7#186#211#144#178#243#19#6'em@'#26#143#148'#'#6#158#149#244#172#29
+ +','#137#30#152#249#11#142'zG'#206#204#147#227#222#168#167#189' ?'#252#128'i'
+ +#197#229'y'#14#248'3'''#150#175#28#27#223'Q'#247'y'#31#182#190#27#222'K'#11
+ +#137#159#27#208''':'#181'7/'#145'@'#194#245#19'#'#146#250#243#225#142'h'#11
+ +':'#188#167#138#30'~'#217#165'F'#255#246'Zc'#244#152'S{%'#212#167'tz/O'#223
+ +'-s'#248'A'#237'7'#137'>'#15#207#19#248#143't'#239'N'#251#252#12#9#244#251
+ +#253#184#213'j5'#232#226#162#197#248#154#132#4#225#16#188#12#173'@i'#18#232
+ +'1'#9'('#175#158#7'~'#252'p'#208#189#185'?o]-'#146'|t'#184#15'&'#129'oL'#130
+ +#245'W'#8#236#177#205#9#240'L'#5'a'#172'5'#6#171#9'p'#10'qPT'#21#210':'#15
+ +#220')'#202#140'V'#224#21'D'#160#138#237'"JP'#172'K%'#200#206'f^9'#236'='#235
+ +#173'z'#158'w'#245#153#31#215#188#152'>'#219'='#149#188#188#145';/'#178#245
+ +#249'n'#18#143#177#243'MG^'#145#250'*u$'#191'c'#235#27'/?'#219#237#12#244'E'
+ +#161#254#207#11'R'#192#255#23#240#242'?'#254'!i'#1#19#177#247'u|'#223'|n'#228
+ +'/&'#215#218'{?i'#132's'#174#229#23'G'#4#236'}'#147#222';'#145'P'#31#171#253
+ +'J'#194'}'#178'F'#169#239#222'y'#0#127#233#254#156#209#193#231'W%'#1'd'#12'"'
+ +'Y'#136'.'#178'!'#1#152#5#151'0'#247#128#210'y'#2'm'#186#212'u'#146#184#241
+ +'p'#222'X{0^'#185#149#145#236#215'@-'#155#4'H!'#6#9#196#157#13#201#7#144#136
+ +#128#1#191')$'#10'+$ '#11#147#138'h'#6#156'N,'#145#130'\'#162#6'V'#27'x'#26
+ +#17'8'#221#137'rG;'#240#202'^'#196''''#220#177#147#184#149#249#225#135'+'#167
+ +'i'#140'{'#175#244'6'#167'<'#23#0'WO'#0'~^'#150#248#202#22#239'8N>c'#239#187
+ +'v'#191#149#252#139#18#240'Y'#19#152'N'#213'd'#251#167'j6'#220'b'#130'@'#179
+ +#15'+'#241'3=__'''#154'<'#190#210#234#223'!'#149'?'#205'm'#147'@]'#210#235'd'
+ +#248#245#165#178#15#222#254'G'#146#215#255'H4'#129'}8'#252'666'#206'<'#248
+ +#237#253'9'#227#195#146#128#18#159#128#146'2b"'#130#21'h'#2#146'%h'#178#5'9Y'
+ +#136'$r'#155#192#211#160';'#23'''Y'#212#184';'#236#189'6Kk'#29'S'#0'd'#27#140
+ +#8#184#163#214#26#19'APo'#21#17#1#167#138#208's'#251#10'<'#137#8#220#148'b'
+ +#153#194#220#134#14#205#196'%'#165')'#204#202'k7'#132'h'#230'4'#176#135#14
+ +#132#20#143'n:<'#151'q'#152'*o'#156'v'#246#144#145#236#230#127#249#146#216
+ +#189'~'#157#14#227'I'#230#158'!'#2'k'#227'/Q'#247'S'#145#248#2'|'#181#208#149
+ +'|J'#236'w'#215#222'7'#206'?E'#251#147#254'=5'#221#189#173#19#127#210'%*?}'
+ +#209#229#198#224#189#149#198'h'#199#203'MI'#143#14#243')'#1'?'#173#199#180
+ +#223#151#154'~4k'#132#196'GE'#31#182#183'I('#161#145'''{'#251#201'\=s'#14#191
+ +'e'#227'<'#16#128'=OC'#2#251#251#251#17']'#228':]x'#174#29#136#162'h'#157#246
+ +'a'#6'\'#18''''#225#134#212#14'th'#27'}'#4'b'#210#0#162'G'#195#206'K{U'#147
+ +' '#212#201'C'#138#171#11'#U'#235']S'#245#181#27#156'M'#200#14'@'#199#4#0#1
+ +'(''Dh'#136#192#148#24'+'#153#181'X'#249#229#198'#'#182#21'Y%'#179'P'#231#15
+ +'-'''#3#207#209#255#139#222#4#166#151#161'{UN'#136#4#170#143#176#19#182'+m'
+ +#229#5'Y'#149'CxN'#165#158#27#198'3N='''#150'oA'#159#154'm'#0'>#b'#0#160'u'
+ +#17#143'Z'#20#13';'#173#199'?IJ>'#0#132#0#147#209#158#154#236#252'D-&'#131'B'
+ +#213#135#169#128#207'pU'#254#238#238'O'#234'^2'#245't'#229'@'#213#211'?'#147
+ +#22#222#168#234#219'q'#193#15'O'#127#24#134#232#235#223'_,'#22#227#25#141#243
+ +#2'~'#140#243'B'#0#246'\'#221'<'#1'8'#252#232#194#183#232'p'#143'.'#254#186
+ +'8'#7'A'#4#156','#132'V'#227'$'#129';$u'#27#180'_#'#240'E'#131'i}'#237#193
+ +#164#247'j'#150#235#249#7#180#147'0`'#21#222#244#16#132'Y'#208'X{'#133#139
+ +#138#188#208#137#6#200#220#3#134#8'4q'#4#162#29#136'&`{'#13'8]'#137#131#138
+ +#163'P'#8#161'hF"'#19#152#28'H76'#161#195#162','#185#240#15'T='#3'G'#200'1'
+ +#248#160'%'#203'y^yi'#25#240'z'#229'4'#218'TE|'#159'%'#189#153'l'#195#190#230
+ +#160#154#207#246'~'#154#149#218'r+'#150#250#153#6#173#0'_'#137'='#175#164#131
+ +#143'2'#4#144'h'#239#127':''u'#127#231']5'#239'?'#210#173#186'L'#26'p'#146#10
+ +#209'h'#149#31#149'|'#151'['#253#187'P'#249'9'#188#143#254'}'#160'!m'#239#219
+ +#24#191#1#191#210'e'#189#15'e'#198#222#199'R'#207'? '#1'4>K'#25'~G'#29#231
+ +#137#0#236'9'#155#180'a'#218#142#26#141'F'#13#17#2#164#7#27#231#160'8'#5'/'
+ +#217#218#1#29'&'#132's'#176#6#147' Sa'#252'h'#220'~'#169'?onz@'#166#137#20
+ +#216'f!Z'#226#195',h'#192', B'#176'R'#223#1#188'Bd '#22'B'#16'M@9'#25#132#214
+ +'I'#24'>A+8'#204'GP'#154#242#188#186'v:'#26'['#13#193#161#130#165#190#130'CB'
+ +#143'O'#200#187#183#160'.%'#224#23#26'H.'#234'})Q'#199'%'#0#215#147'/'#158'}'
+ ,#163#226#219'p'#158'q'#240'Y'#208#167'b'#231';'#158'}l'#11#192#181#202#175
+ +#215':'#175#223'8'#2'%vO'#235#217#222'}5'#222#131#186'?'#211#199#229'3y'#157
+ +#167'"'#245#147#201#149#230#254#237'f<'#27'z'#26#247'8'#15#146#250'%{'#223'&'
+ +#248#208#178'C'#210#254'1'#9#153'G'#210#213'g'#155#128#191'K'#160#31#160#149
+ +#23#13#152#8#231#10#252'K'#158#138's3,'#9#208#197#15'k4'#200#12'h"B'#16#4#193
+ +#170#227#23#128'F'#0#18'X'#5'A B &A'#148#19#196''''#139#176#253'p'#178#242
+ +#202','#141'ZE'#235#240#162'('#200#147'9'#10'k'#221'+'#170#182'rM'#5'h'#162
+ +#17#154'y'#8#3#199#28'pM'#3#9#17#134'RK`'#10#140'l'#14'A Z'#129#201'$t'#218
+ +#146'U'#137#160'j*'#148#202#146'+'#21#137#21'G'#162';'#242''''#146'A'#165#216
+ +'f'#217'c'#235'Jw'#222#168#172'e;7'#137'<'#153#27#190'3'#137'<'#142#164'wc'
+ +#249#2'|'#29#203'/'#192#175#137#192#9#241#217't^'#13'r'#237#3'H'#10''' -'#139
+ +#225#14#219#249#9#171#251#186'I'#167#146'L>'#179#246#232#207'j}t'#127#189'1x'
+ +#228#177#180#207'3'#147#214#171'$'#190'O'#203'\j'#249#135#226#233#135's'#15
+ +#210#30#249#252'['#178#191'O'#207#220#160#223#239'O'#187#221#238#156#8' =o'
+ +#224#175'>'#9#231'm'#148'J'#137'I'#19#136'%u'#152#157#131't'#140#181#1#144#0
+ +#250#11#210'z'#141#253#2#202'k#}'#152#182'czDc rw'#218#186#180'=m_'#207'H'
+ +#164#235#226#31#237'$'#132'fP'#168#249#145#170#181'/'#169#6#17#129#31'7'#180
+ +#244'7j'#191'k'#14#24#127'@'#224#164#17#187#166#129#201'!p'#29#133#198'<'#176
+ +#4#224'W'#18#139#180'G'#192#246'.'#180'='#11#141'iP'#152#3'n'#194'Q'#217';'
+ +#239#29'XU"s'#202'Az'#217#181#144#187#161'='#137#215#231'y'#197#214#151'B'#29
+ +#163#226'gy'#145#167'oSu'#139')'#183'\'#201'_H'#253#20'M5'#197'VO-'#9#184'a'
+ +#190#220#170#251#198'!H'#18#127#184#173#166'{wU:'#27#22'f'#129#11'~'#241')'
+ +#180#162#217'.I'#253';'#152#156#211'C/`}n'#172#242'+'#221#187#207#228#244#143
+ +#140#167#159#182#183#197#219#191'Ej'#254'6'#9#24'h'#2'}'#147#215#239#244#241
+ +'3'#192'?7'#224'w'#30#135's;,'#9#16#1#4#8#19#18#27#195'9'#216#154#205'f=h'#3
+ +#244#127#244#26'D'#171'1h'#2#240#11#160'r'#144#211#135#17'% '#192'D'#244#17
+ +'A'#146#249#241#163'I'#247#230'`'#214'X'#247'l'#241'O'#1'^?0 '#142#184#166#0
+ +#206'B'#244#211'3'#166#0#167#13'['#208#23#161'A'#27'!'#136#180#244#207#131
+ +#224'@wb'#235'#p*'#15#11'"P:'#164'h'#211#139#165']'#153'*L'#4#151#24#150'^"'
+ +#175'r'#197#170#26#192'!'#14#190#18#15#184#245#246#216#204#242#146#189'o5'#0
+ +'7W'#223#128#221'z'#244#141#202'/'#246'~'#166#167#219'V'#226#228#179#128#183
+ +#29'{'#202#224#183#197'='#236#253'_'#168#217'`K'#205#246#239#17#240#199#146
+ +#16#148'X'#147#1#251'J:'#246'D^2'#187#212#26#220'n'#215#166'}'#248#28'<'#143
+ +'U~V'#252#233#146#177#163'Oz'#247'Me'#178'Nk'#239'C'#237#151#153'{9'#190#15
+ +#149#159#20#206'1b'#252#245'z'#29#164'a'#234#249#237'U:O'#227#188#19#128#249
+ +#13'H'#24#194#154'#'#4'p'#14#18#1'4E'#27'X5'#190#1'!'#1'6'#9'h'#191#7#191#0
+ +'m'#195'A'#8'm'#128#222#231#251#163'$'#238'>'#28'uo.'#178#168#233#154#5#202
+ +'I+V'#226''''#136#219#27#170#222#187#174#130'F'#235#160#212'7'#170#191'C'#4
+ +#134'L'#148'K'#2#2'z'#229'U'#157#133#14')x'#166#10'Q9~'#130'J7cq$'#30#152#241
+ +#232#176#154#3'[m'#231#188#196'm'#180'a6'#189'B+'#240#158#2'zW'#213#247'*'
+ +#222'|'#29#215#207#172'Df'#7'`R'#168#251#158#1'}'#226'H~'#163#13'd'#134#8'2'
+ +#142#223#207#6#143#24#248#217'bb'#237'~'#227#216#203'\u'#159#132#252'J}'#252
+ +'p'#179'9x'#224#209#142#199#165#130#224#29#218'f%'#198':'#250'f'#210#187#207
+ +'t'#238#133#167#223#130#31#19'v'#160#137#7#254#143#254'}'#163#209'h^'#241#244
+ +'+u'#14#193#127#200#147'q.'#135#141#16#160#156#248#214#173'['#225#214#214'V'
+ +#141#14#213#137#173#17'*'#236#145#250#134'b'#162'u''u'#24#251#200'#hC'#27#160
+ +#237#26#251#6''#204'r'#143#204#130#246#229#221'Y'#243'J'#154#135#145'1'#11
+ +#236':'#8#172#175#0'N'#191#184#181#166#234'+D'#4#245'N'#17#1'p{'#10#28#0#190
+ +#16#131#235#24'tk'#11'l'#152'R'#230'3t'#29#134'Nv!k'#7'jIU'#162'\'#17#175#148
+ +'\T'#190#213#182#143'A'#245'B'#26#233'_r'#240')I'#218#145'}3}'#182#19#194#179
+ +#224#183#251#6#240'N"O'#213#203'/'#241'}'#227#236'c'#144#27#147'@r'#251#141
+ +'6'#144'%s'#246#232'O'#25#248'3'#171#254'g'#198#163#239'F'#17'h'#187'I'#234
+ +#254#229'F'#255'^'#28#192'3O'#146#158#5'>'#199#245'3'#201#231#183'R'#159#22
+ +#19#226'c'#149#31#160#199#2#149'_'#8#1#29'|'#198#244#182')'#217#253' '#140
+ +#132#180#206#236'<'#132#249#142#4#156#23'h'#176's'#240#219#223#254'6'#251#5
+ +#232#166'E'#4#234':'#28#132'259'#155#4'XD'#27'0$'#208#165#183#146'>'#175#26#4
+ +#167#24'f'#1#129'='#160#199'%'#220#157#183'6'#247'&'#173#203#137#10#226#3'D'
+ +#224#23#246'>4'#130#176#209'!'#173'`'#147#8'a]'#249'a,m'#198#140#3#240'0'#167
+ +#224'!'#5'F'#146'3'#224#149'|'#3#166#23'A1'#169#137'%'#2#153#224#196'LuV'#10
+ +#18#10'7'#148#156#132#14#3'xF'#210'Wd'#153#145#246#7#28'{N'#252#222#149#252
+ +#182'B'#207#237#200'c'#192'/'#132#160'\'#167#159#149#242#142#211#207#233#224
+ +#131#255'-'#166#251'j1'#220#162'e'#155'I w'#205#128','#147#150'_'#236#220#195
+ +'~'#222#138'g'#187#27#141#193#131'Z'#184#152#150#212'}'#199#214#151#182']'
+ +#166'c/l'#249'}i'#226#193#158'~Z?Fl'#159#164#252'>='''#3'2/'#199#244','#205
+ ,'{'#189#30#192#127'n'#237#253#165#128'9'#237#19'8'#166#223'T2'#9'h N'#211'di'
+ +'O'#128#167#155'j'#137'@'#204#3#236#19#9#168#14#1#174'A'#251'u:'#30#25#179
+ +#128'@'#21#236#205'Z'#27#187#227#230#229#133#10#235#218'F'#247#203#211#141#17
+ +#1'('#223#183'ZA'#173#177#170'""'#131#176#185#162#163#4#230#181#142'3'#208'H'
+ +'~'#255'0-'#192#152#8'&'#147#208#248#7#248#23'V2'#12#221#28#130#220#137#12#8
+ +#27#152#196#220#131#209#130'Jz'#174#167#172'j/'#255'V'#226#245'+Iyc'#227#27
+ +'{'#223'4'#227#176'Z'#128#1#186#172#165#192#166't'#220'M'#237'u'#215'('#203
+ +#157#13#31'3'#240'S'#132#242'2'']W'#166#220#206'e'#209#192'O'#243'vm'#182#189
+ +#217#24'>'#140'|H|'#28#23#191'>'#171#251#220'%'#208#205#232#227#240#30#242
+ +#249'i'#189'/'#237#187#182#205'"'#206'?'#28#199'k'#166'F'#229''''#205'2;'#207
+ +#246#254'a`y'#17'G'#201'$@'#168#176#213'j'#197#2'lT'#12'v'#197#25#184'J'#140
+ +#143#232#0#22#248#5'D'#27'P-!'#2#152#5'a'#206'd'#128#174#225#190#191'7k'#174
+ +#237#142'[W'#230'y'#216#176#206':'#3'|'#207'H'#242#162#2#17#154'@'#212#222' '
+ +#173'`C'#5#141#142#227#252#11#184#231#160#231'8'#2#139#168'@u'#10'3'#207#2
+ +#222'F'#5#2#209#4'\'#237#192#151#144#161#149#252'U'#7'`%'#159#192#12#183#149
+ +'6'#239'+'#235#28#176#213'zF'#229'O'#171#234'~&fA'#230'T'#234#21#206'?~'#189
+ +#209#0'*a'#191#18#9','#230'j6'#218'f'#208''''#211'A'#161'!'#152'L@'#199'l0}'
+ +#0#16#210#235#198#147#199#27#4'|x'#246'M'#190#241#19#212'}k'#235#211#210#151
+ +#238'='#12'~'#186#207#144#254#216#222#15#130#128#19'{h'#153#145#244'_ '#196
+ +#247#162#168#252'K'#129#242#2#15'k'#18' J'#128#178'b'#186#185'54'#25'!R@'#227
+ +'Q'#152#5'+ '#1#133'Y'#137'5'#9'@'#27#232#209#210#17#179#160#238'{~Lk'#16'A'
+ +#8'"'#240#9'}'#251#179#250#234#206#164'ue'#150'!'#135#192#128#177#144#218#5
+ +#176#3'K'#10'a'#212'Tq'#7'Z'#193#154#10'j'#141'2'#184#157#210'bo'#9'!'#184#9
+ +'C'#133#25#224#21'~'#2'''R`o'#173'u'#11'H'#180#192'M$'#146'W'#185'~'#128#210
+ +#172#185#178'*'#194'}'#174#244#207#156#233#180#225#240#203'd'#178#205#138#183
+ +#191'*'#245#179#188#18#1'H'#212'b'#178#175#230'P'#241#199#187#156#216#147';6'
+ +#189#251'~K '#244'}>1B'#183'6f'#224#7#200#15'6'#192#231#138#221'2'#240#149#6
+ +'?'#128#143'N'#189'#'#201#229#223#23#240#195#185#135#25'y'#25#248#240#240'+M'
+ +#14#211'N'#167'3G'#3#143'7'#223'|'#243#133'R'#249#15#0#228#180'O'#224#132'~#'
+ +#155#4#208#6'h;Z]]'#141#160#13#200#140'D0'#11'z'#162#17#172#233#244'aM'#4#180
+ +'&'#18'Pm'#186#235#220'l'#4'&'#129'o'#136' '#131'F'#224'y'#195#164#209#219
+ +#153'4/O'#211'Z'#7#200#180#192'tH'#160'4'#231#128#152#0#232'I'#16#212'z*jt'
+ +#201#168#232#210'~'#173#210'[`I'#231'!G'#213'/'#171#254'x'#173#18#159#128#241
+ +#234'{'#182#152#168#8#4'x'#149#181'*7'#222'PE'#218#190#178#13'8'#157#146#221
+ +#204#13#241#21#234#190'w'#192#23'P'#201#233'7'#145#0#2'v2'#27#170#20'v'#253
+ +#164'O'#219#131'"'#219#207'x'#239#197#137#231#153#254'~v;'#231'p^'#167'6'#217
+ +'^'#175#143#182'|'#143'sy'#213'2'#224';'#237#185#173#147'O'#233#9':'#160#214
+ +#239#25#240#3#248'$'#12#246#200#222#135#3#16'z'#254#132'l'#253#217#139#230
+ +#232'{'#26'8>,'#227#128'6P'#171#213'bz^0G'#22#166'*G'#159#129#30#28#133#240
+ +#17#28#212#6'T'#211#152#5#4#180#18#17'(.'#25#11#163#253'yc}0k'#172#205#210
+ +#168'Y'#0#180#172#198#27#245'>'#247#202#196#0'B'#8#27'+*'#170'wT'#0'B'#128#19
+ +#209'!'#0#27#14#148#162#162'jc'#210#146#9#224'4"'#177'w'#185#218#140'D'#194
+ +'~n'#233'n)'#12#232'j'#2#198#9#232#168#251'n'#184'/'#207'+I?yA'#0'H'#206'I'
+ +#166'}'#150#244#201'tH'#255'J'#10''' '#155#20'i)4'#200'Q'#0'K&'#184#184'Y'
+ +#138#4#158#149#218'x'#167#25#209#135'i'#204#231#154#160#24#248#0'<'#235#252
+ +'b'#231'/*'#234#254'H'#226#250#198#214'G'#136'oW'#188#251'}'#186#215'C'#168
+ +#251#176#245'www'#23'd'#231'sl'#255#19#159#248'D'#254#162#131#223'yB>4'#163
+ +#164#13#192'7'#176#178#178#18#17#25#208'f'#204'}'#6'h'#1#216#225'(\1'#218#128
+ +#210#26#2#250#18'"'#164'h'#136#0'Y'#132'1a.'#160'g=dg!'#20'r'#210#11#166'i'
+ +#220#216#155'5'#215'G'#179#218'Z'#162#130#200'S'#5#25#20#146#220#169#7#240
+ +#141#243#207#28#15#148#31'7Y;'#8#226#22'}B'#131#9#130#29#141#202'5'#3#156#181
+ +#141#18#136#170#159#171#194'$'#200#171#209#1'U'#16#130#155#244#227'6'#222'4'
+ +#7#149#201#4#212'$'#192' u'#18'}'#12#232#177'dp'#188#211#146'/'#198'l'#199'c'
+ +#201#200'4/'#1#190#186'm'#181#137#204#250#20'`'#195'7'#195'y'#191'S'#159#236
+ +'t'#163#233#158#199'I'#5'b'#143#232#188#131'Ll|l'#1#244#236#224's'#128#143
+ +#134#29'#'#153#153#135#195'{'#198#222'7'#14'>'#216#249't'#175#199't'#159#167
+ +'('#224'[b'#235';W'#224#197#29#31'6'#2#176#191#217'h'#3#155#155#155#254't:'
+ +#13'1S1'#252#3'0'#11#232#223'-'#178#7#225#12'D6'#225#138'8'#7'W'#196'y'#168
+ +#157#132#158#215#164#199#177'A'#159'V;@'#4#30#224#166'Q:'#152#215#187#253'Yc'
+ +'}'#148#196'+'#185#22#233'V'#133'7)'#191'E'#135#225#162#243#176'K'#8#185#152
+ +#0#164'x'#16#25#212#153#28#130#176#206')'#201'>'#214'd>'#148#10#139'J'#191
+ +#244'`'#219#242'"G'#160#236#237#247'Jf@^$'#7#25'3'#1#248'K'#209'H'#19'@'#159
+ +'p'#197']'#150#152#245#212#206#198#163#242#195#0#15#252'f%'#147#1#239'1'#251
+ +#181'`1&'#21#127#167'GK'#232#193'!'#160'L'#237'0'#147'B'#154'iu'#223#177#241
+ ,#171#18#223#216#249#3#1'?'#146'w'#0'~^'#144#194'K'#210#30#197';'#172#238'w'
+ +#187#221#217#214#214'V'#226'x'#248'_X['#255#176#241'a$'#128#210'o_f'#22#208
+ +#225#26#217#130#28'6$'#2#128'F'#208's'#23#209#6#208'k'#160'm'#136#128#128#140
+ +'(CL'#251#16#211'Rc'#204#157#238'|'#180'*O'#9#206#251#179#198#234'h^'#235'M'
+ +#211#168#157#230#162#25#24#199#158'r'#10#131'J'#132'`'#156#127#190'>ig'#187
+ +#152#199#16']'#144#27'*'#8'"q:'#134'tX"'#17#158#164'"'#243#233#232#181'/Z'
+ +#134#150#190#137#216#218'R)'#151'9'#139's'#28#146#28#18#158'_'#207#225'7'#7
+ +#196#182#196#183#240#1#184#0'W'#165#130' 1#8T'#167#242#154#191#24#213#163#249
+ +#176'G*>Zn'#23#17#8#145#246'8'#3#2'>x'#18#206'}''o'#223#134#244#164'K'#207
+ +#184#2'|'#187#208'=d'#224'#'#172#135'L>"'#2#246#238'#'#149#151#8' '#251#176
+ +'I}w|'#152#9#192#140#3'f'#1'B'#127#244'p'#196#198'QH'#255'o'#9#216#187#244' '
+ +#245#184#150#128#136'@4'#2'v'#20'*'#204'T'#164#188':4'#2')4'#10#173'V'#224'#'
+ +#29'E'#251#10#176#13#208#18#9#212#137#12#186#147'E'#220#157'$q'#139#224#16#26
+ +'S'#161#232''''#232';'#205'D+'#246#190#152#2#150','#148#155'*l~'#150#252'@.'
+ +#30':$$'#232#216#255#182'EW'#169'1'#191#201#250'S'#165'\'#0'['#221#167#138
+ +#148'`'#6'u'#166'T'#158'/'#7'<'#214#181' '#25#215#131#249#176#25#207#251#237
+ +'h6'#242#149'8'#243'<61'#140'moA'#175't'#202'.'#24#133#213'|Y'#230#198#179'o'
+ +'T}'#19#211#151#5#158#254'>'#128'OD>'#140#162'h'#12#137'O'#199#167't'#127#23
+ +'t<'#249'0'#170#251#203#198#5#1#20#195's'#205#130';w'#238#4#198'?'#128'9'#7
+ +#232'!B'#205'@'#203#241#19#244'$'#140#200'k'#248#7#20'"'#6'9W'#26#214#161#209
+ +#18#216#17'm@BQ'#24#248#30#200' '#160'c>'#180'^F'#165'/'#229'<'#244'wL$@'#132
+ +#208#153'.'#162#206'4'#141#219#153#14#8#138#237'^T'#4#22'e'#194#170#168#10'T'
+ +#254'R'#240#219#191'U'#207#127#241#207'J'#246'_'#197#7'`Gn'#205#0#3'z'#183
+ +#145'g'#225'G(^g'#0#31#251#201#164#22#206#135#173'h>h'#147#164#15#252'4)^c'
+ +#153#197#128'^Y'#21#255#160#180'/'#169#250#144#248'p'#224')'#1#187#164#242
+ +#150#164#189#1'~'#171#213#154#141'F#'#246#236#147#169#151'~X'#213#253'e'#227
+ +#130#0#202#227#128#127#192#16#1'=H'#28':'#164#127's2'#17#173'['#244#0#162#216
+ +#168'+'#26#129#171#13#176#143#0#175#229#228'#'#223#135'Ya'#200' 8@'#6#128#174
+ +#158'`'#132'a'#142'|<"'#132#246'x'#17#183#146'4'#168#207#179#176#190'H'#131
+ +'Z'#170#160#219'k'#251#221'8'#245#140'K'#191'T'#13#184'$'#239#223#141#8#228
+ +#203'~t5'#20'h'#134'['#251#239#185#210#221#253#191#6'n'#228#167#211#208#207
+ +'fQ'#144#204#234#225'bL'#18'~'#16'.'#3#188#233#18'"'#182'C'#174#127#145#168
+ +#248'E'#214#30'-'#11'g'#218'-'#171#234'+'#157#190#203#224#167'{'#224#18#192
+ +#144'#'#179'I'#194#210#254#2#248'O'#31#23#4#176'|,%'#2'Z'#135#244'@'#177'F'#0
+ +'`'#211#186'I*f'#139#236'J'#214#10#132#16#12#9'X"@'#19#18#218#6'y'#212'@'#6
+ +' '#2#218#14#133#12'|'#218#151#194#2#206#177#169#16#130#178#128'N'#179' '#154
+ +'fQm'#158#16')'#164'!'#19'C'#146#250#181'E'#22#214'r'#195#2'y'#17#247#207#221
+ +#219#235#29#248'y2'#242#165#155#252#170'R'#11'0'#253'7'#240#178'E'#236#167
+ +#179#200'O'#166'Q'#152#206#226' '#153#214'BZ'#252'd^'#10#31#28#4#188#212#222
+ +#235#20']Ro'#178#220#168#19#185'JM'''#30'U'#150#246'('#207#157'J?>'#11'|'#168
+ +#251't'#157#135#0#191#0#30'j>&'#221#132'I0E'#6#159#249#172'%'#192'_'#242'K?'
+ +#188#227#130#0#158'<'#150#18#1'|'#4#237'6'#201#183#217#140';'#20#19#1#160#203
+ +#144#169'5h'#201#186'm'#246#141#198#0#243'@i'#13#2#4#2'2`"'#144#133#181#2'!'
+ +#4#175'B'#8#162#229#235'F'#0'E*'#191#201#243#247#2'"'#129'('#205#252' '#205
+ +#149#159#229'~'#0#19'"'#203#184#160')'#160#181#143#207'&'#158#241#233'8'#142
+ +#249'x'#15' '#233'{y'#202#139#162'Wy'#10#219#153'g'#142'y'#244#137'~'#158#6#4
+ +'N'#218'N#?K0C'#14#127#181#237#249#167#247#204'1}Z'#185#20#11'j'#213#222#145
+ +#240#12'B'#237#197#183'q{+'#237'Mi'#174#210#192#159'HW'#158#145'*'#128#15#169
+ +#143#184'='#239#147#186#143#10#189'1'#173'!'#241#209#140'snl'#252'G'#143#30
+ +'e'#23#192#127#250#184' '#128#163#13'K'#4#223#253#238'w=4%'#5#25#208#161#144
+ +#164'N'#212'l6'#1'd'#214#10#232#129'lxz'#174'B'#180'('#3#240#153#4'h'#223#144
+ +'C'#211#209#10'jB'#6#136#30'DJG'#16't'#20'A'#19#2#242#10#8#139#220#2'Dr'#130
+ +#217'y^'#164#249#225#143#239#219'm'#140#220'sN'#250#224#207#240#14#252'#?'
+ +#176#225#202#240#138#242' '#249#0'z;/'#210#133'9'#25#152#147'!3'#237'P'#212
+ +#21'x'#158#199#217#3'.'#224#233'X"'#221'vy'#150#29#167'@'#7#224#7#152'a'#223
+ +#143' '#229#165' '#135#215't|'#4#208'C'#210#3#244#240#230'c!'#2'^'#192#171'O'
+ +#199#211#11#224'?'#219#184' '#128'g'#27'%"@'#212#224#210#165'K>I'#164#144#30
+ +'D&'#3#180''''#4#168#145'a'#8'2'#192#2'2P'#152#202#220'Y'#132#8#140'i'#192
+ +#230#1'k'#5#30';'#14']B`2'#160'c'#1'b'#8#162#29'0'#17#152#22' '#24'y'#145#223
+ +#167'r'#183#11'`'#165#17#192#129'y'#9#151#254'J'#227#225'We'#253'_)'#227#164
+ +#211'h'#215'L$'#130']'#25#231#157#150#242#136#238#231'6Vo='#248#6#240'R'#142
+ +'k'#194'x'#0#255'd'#137#212#231'E'#18'vX'#189#23#21#127#14#208'c'#166']'#196
+ +#241'WVV2x'#245#137#148#243#11#224'?'#219#184' '#128#247'7l^-'#194#135#244#16
+ +'z'#198'<'#160#135#18#128'E'#143'B6'#17#224'/'#160'}'#16'B'#131#164#22#8#129
+ ,'5'#0#172'}'#157'Q'#216#144'F'#165'L'#4'R'#177#200#239#177'D'#160#29#136#161
+ +#199'A}'#144#129'v '#210#182#246#31'(]'#151' '#219#170#152'}'#132#165's'#209
+ +'4'#200#156#244'!, '#160'Vy^v'#3'j'#183#164'W'#184#253#10'U>7'#157't'#217#129
+ +''''#222'{'#165#165#188#5#190'S'#127#207'^|'#165#165'=/p'#236#161#209#6#253
+ +'~'#168#243#19#172'%'#166'?!'#160'c'#31#196'0C=>'#169#247' '#142#132#142'!y'
+ +#7#128#207#156'8'#190#156#253#5#232#159'e\'#16#192#7#27#150#8#240#0#186'Z'#1
+ +'I'#168'`gg'#7'R;'#132#137#0#243#20'd'#0'p'#139#218'_'#23#240'#'#215#192#128
+ +#159'5'#2'G30D`4'#3#215'g`'#9'Ai'#13#1'$'#16'pI?'#231#28's'#242#156'''`'#247
+ +#12#17'('#19';8D'#19'p'#192#207#0'/'#8'AK~'#165'{'#230#27#213'>'#173#0#222
+ +#196#233#141#138'o'#156'y'#0#191#241#228'O'#5#220'v'#27#199#1'~'#243#127#168
+ +#245'x}'#20'Es'#0#31#210#30#234'='#17'jz'#227#198#141#20#160#135#180'w'#242
+ +#245#249'|O'#251'a8'#143#227#130#0#158#223'8'#160#21#12#6#3#175#211#233#4#180
+ +#248#244#0#179#153#0'I'#14'S'#129#30#234#152#30'n'#164#31'C'#202#215#232'X'
+ +#141#142#25'S'#192#152#5#150#4#232#189#186'eY'#161#21#132'UBP'#154#20'x'#246
+ +'$!'#4#156#147'/'#224#247'DK'#176#219#149#243#182#170#188'2'#210#221#181#225
+ +'s''>/'#210']z'#234#25#208'/'#28#208'W'#213'|+'#245'E'#221#231#181#144#194#12
+ +'*=IwH'#249#5'@O@_'#200'g&'#0'=T|c'#219#11#232#205'y'#186#235#139#241'>'#198
+ +#5#1#28#207'Xj"'#208#218#7#25'@3'#160#7#157'M'#5','#4'nL'#127#142#233#206'"'
+ +#151#16'|'#157'?`4'#6#248#22'P'#189#24#11#17'D'#134#16'@*'#244#186'RD'#1'D@'
+ +#175'E'#196#194#19'2`"'#192#182#28#243#212#146'x`'#201#142'/'#0#159#27#21'_'
+ +#21'j=7'#212#196'B'#223#195#192#167#207#157#211#246#1#2#192'B'#191'k'#230#2
+ +#158#200#14#210#29#239'Y@'#194#131'H'#232'xj$'#189#1'=]'#175#188#162#226#187
+ +#235#139#241#1#199#5#1#28#239#176#215#215'8'#14#141'f'#0'3aoo'#143#9'!@i'#218
+ +'`'#16#192'l'#160#151#134' '#3#172'A'#8' '#7':'#206'k'#128#158'^'#202'k9'#30
+ +#154#227'J'#252#4#202'1'#13#180'I'#192'f'#128'oH'#0#231#148'!.X'#144'@q'#178
+ +#5#208'sQ'#237'-'#240#177#166#247'X'#201#175#196#161''''#4#176'0'#251#134#0
+ +'d!<'''#6#228#144#236#176#223#23'Fk'#0#224#137#3#210#181#181#181#148'~?'#212
+ +#250#140'L'#168#28#160#191'p'#232#157#204#184' '#128#147#27#165'D\'#233'Y'
+ +#168'@'#8#208#12'n'#222#188#233'-#'#4#12#2'M '#160#14#5#212'au'#219#172#149
+ +'&'#14#214#0'0'#0'v'#1'k6'#155#217't:'#205#232#156#243'e'#18'~'#9#224#171#219#23#227#152
+ +#199#5#1#156#141'Q'#186#15#198'\'#192#182'1'#25#8'H'#30'H'#129'H'#192'#py'
+ +#134#24#8#148#30#200#129#128#232#25'r'#160'}'#143'@j'#23':'#206#128#199'6>'
+ +#19#219#4'V'#187#141#181#207#253'L'#148'"'#0#27#192#243'>}/o'#155#133#190'?'
+ +#7#208#137'Dr'#128#156#190'+'#235#247#251'9'#129#222#2#29#146#189#221'n'#231
+ +#6#236#248#156#11#192#159#205'qA'#0'gsT'#239#139''''#192'Q.1`'#13'r'#184'u'
+ +#235#150'7'#28#14'-9'#224'8'#8#2'k'#179'O'#192#230'5'#8#3#235#245#245'u'#187
+ +'m'#6#128#140'5Iy'#11'J'#2';o'#3#220'X?~'#252'8'#199'6@'#142#253'e@'#199#250
+ +#16#176'/'#219#191#24#167'8.'#8#224'|'#141'e'#247#235#0'9`'#24#130'0'#3'D'
+ +#177#236#3#161'Y`]'#175#215#15#0#211#128#218#29#6#224#24#0'9'#214#135#0#253
+ +#176'c'#23#227#12#141#11#2'x1'#198#179#220#199#163#190#246#168#224#189#0#249
+ +'9'#30#23#4'p1.'#198#135'x'#252#127'p'#251'ut'#3#215#244'"'#0#0#0#0'IEND'#174
+ +'B`'#130'('#0#0#0#128#0#0#0#0#1#0#0#1#0' '#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#1#0#0#0#1#0#0#0#1#0#0#0#1#0#0#0#1#0#0#0#1#0#0#0#1#0#0
+ +#0#1#0#0#0#1#0#0#0#1#0#0#0#1#0#0#0#1#0#0#0#1#0#0#0#1#0#0#0#1#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ ,#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#1#0#0#0#1#0#0#0#2#128#128#128#2'UUU'#3'@@@'#4'333'#5'III'#7'@@@'#8
+ +'999'#9'999'#9'MMM'#10'FFF'#11'FFF'#11'FFF'#11'MMM'#10'999'#9'@@@'#8'@@@'#8
+ +'UUU'#6'333'#5'UUU'#3#128#128#128#2#0#0#0#2#0#0#0#1#0#0#0#1#0#0#0#1#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#1#0#0#0#1#128#128#128#2'UUU'#3'UUU'#6'@@@'#8'FFF'#11'III'#14'<<'
+ +'<'#17'III'#21'EEE'#26'DDD'#30'DDD"EEE%AAA''DDD)AAA+AAA+AAA+DDD)AAA''GGG$FFF'
+ +'!DDD'#30'==='#25'@@@'#20'@@@'#16';;;'#13'FFF'#11'@@@'#8'333'#5'UUU'#3#128
+ +#128#128#2#0#0#0#1#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1#0#0#0
+ +#2'UUU'#3'+++'#6'999'#9'NNN'#13'CCC'#19'BBB'#27'GGG$DDD-CCC5DDD'#211'SC6'#219'W@0'#227'[>+'#235']<('#238'^<'''#240
+ +'_<%'#243'`<#'#245'a;"'#247'a:!'#248'a;"'#246'`<$'#245'_<%'#242'^='''#240'\='
+ +')'#237'Z=,'#233'V@1'#225'RD8'#217'NG?'#210'JHD'#204'IHC'#204'HHD'#204'GEC'
+ +#203'FEC'#202'EED'#198'EED'#195'DDC'#190'DDC'#183'DDD'#172'DDD'#157'DDD'#138
+ +'DDDtCCC\DDDDCCC.@@@'#28'DDD'#15'III'#7'UUU'#3#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'UUU'#3'@@'
+ +'@'#8'KKK'#17'HHH CCC5CCCPDDDlCCC'#134'DDC'#156'EED'#172'FEC'#185'GFD'#193'G'
+ +'FC'#198'HFC'#202'IGD'#203'PE;'#213'VA0'#227']<('#239'a;#'#246'd9'#30#254'g:'
+ +#29#255'g:'#30#255'i<'#30#255'j='#31#255'j>'#30#255'k>'#30#255'l?'#31#255'l@'
+ +#31#255'mA'#31#255'nA'#31#255'm@'#31#255'l@'#31#255'l?'#31#255'k>'#30#255'j>'
+ +#30#255'j='#31#255'i<'#30#255'g:'#30#255'f:'#29#255'd9'#31#252'`<#'#245'[=*'
+ +#236'UA3'#223'MF?'#210'IHC'#204'HFD'#204'FFC'#203'FFE'#200'DDC'#197'EED'#191
+ +'DCC'#182'DDD'#170'CCC'#152'CCC'#129'DDDfDDDKDDD1FFF'#29'@@@'#16'III'#7'UUU'
+ +#3#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'UUU'#3'II'
+ +'I'#7'@@@'#16'@@@ FFF7DDDRCCCoCCC'#140'DDC'#163'EED'#180'EED'#191'FFC'#198'I'
+ +'GD'#201'ME?'#208'UA2'#224'\<('#238'b9 '#250'f:'#29#255'h;'#30#255'j>'#30#255
+ +'m@'#31#255'oB '#255'qD '#255'sF '#255'uH!'#255'|L#'#255#128'O$'#255#133'Q%'
+ +#255#136'S&'#255#139'V'''#255#143'X('#255#145'Y)'#255#142'W('#255#139'U'''
+ +#255#135'S&'#255#131'Q%'#255#128'O$'#255'yK"'#255'tG!'#255'rE '#255'pD '#255
+ +'nA '#255'l@'#31#255'j='#31#255'g;'#30#255'e9'#29#255'a;!'#247'Z=+'#234'RB5'
+ +#221'JGC'#207'HFD'#204'FEC'#203'FFE'#200'EED'#196'DDC'#189'DDD'#177'CCC'#159
+ +'DDD'#135'CCCjBBBMBBB2FFF'#29'III'#14'UUU'#6#128#128#128#2#0#0#0#1#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#2'333'#5';;;'#13'BBB'#27'AAA3BBBQDDDqDDD'#142'EED'#165
+ +'EDB'#183'FEC'#194'HFD'#200'IFB'#205'SA3'#223'^;&'#242'e8'#29#255'g;'#30#255
+ +'j>'#31#255'mA'#31#255'pD!'#255'tG!'#255'~M#'#255#141'W('#255#151']*'#255#160
+ +'c-'#255#169'i0'#255#178'n1'#255#181'q2'#255#182's3'#255#183't3'#255#184't3'
+ +#255#184'v3'#255#185'v4'#255#186'w3'#255#185'v3'#255#184'u3'#255#184't3'#255
+ +#183't3'#255#182'r3'#255#181'q2'#255#175'l1'#255#166'h/'#255#158'a,'#255#149
+ ,'\*'#255#138'U('#255'zK"'#255'sF '#255'pC '#255'l@'#31#255'i='#31#255'g;'#30
+ +#255'c8'#31#252'[<*'#237'RC8'#218'IGD'#205'HFD'#204'EED'#201'DDC'#198'EED'
+ +#191'DDD'#179'CCC'#161'DDD'#136'CCCkEEEJDDD-@@@'#24'FFF'#11'@@@'#4#0#0#0#1#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#1'UUU'#3'999'#9'FFF'#22'CCC*DDDGDDDiCCC'#138'EED'#165'FEC'#184'FEC'#194
+ +'HHD'#200'QC9'#216'[<*'#237'c8'#31#253'g;'#30#255'j>'#31#255'nA '#255'sF!'
+ +#255'|M#'#255#141'W('#255#158'a,'#255#173'k1'#255#181'r3'#255#185'v4'#255#187
+ +'y4'#255#189'{4'#255#191'~5'#255#193#129'5'#255#195#131'5'#255#196#132'6'#255
+ +#197#134'6'#255#198#134'6'#255#199#136'6'#255#200#136'6'#255#200#137'6'#255
+ +#199#136'6'#255#198#135'6'#255#198#134'6'#255#197#133'5'#255#196#132'6'#255
+ +#195#131'5'#255#193#128'5'#255#191'~4'#255#188'z4'#255#186'x4'#255#184'u3'
+ +#255#181'q2'#255#168'i/'#255#153'_+'#255#137'T'''#255'yJ"'#255'rE '#255'm@'
+ +#31#255'i<'#31#255'f:'#30#255'b9!'#249'X>.'#232'MD>'#212'HFD'#204'EED'#202'E'
+ +'ED'#198'EED'#192'CCC'#180'CCC'#160'DDD'#132'DDDbCCCACCC&CCC'#19'@@@'#8'UUU'
+ +#3#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'333'#5
+ +'III'#14'>>>!DDD'#255
+ +#232#177'>'#255#234#179'?'#255#236#181'>'#255#236#182'?'#255#237#183'?'#255
+ ,#237#183'?'#255#238#183'@'#255#238#184'?'#255#238#185'?'#255#238#184'?'#255
+ +#238#183'@'#255#237#182'?'#255#237#183'?'#255#236#182'?'#255#236#181'>'#255
+ +#234#179'>'#255#232#176'>'#255#230#175'>'#255#229#172'='#255#227#169'='#255
+ +#224#167'='#255#220#161'<'#255#217#157'<'#255#213#153';'#255#209#148':'#255
+ +#204#142'9'#255#198#135'8'#255#193#129'7'#255#188'{6'#255#183't5'#255#171'k2'
+ +#255#142'W)'#255'tH"'#255'nA '#255'h<'#31#255'd7'#30#255'[:('#240'KD?'#211'G'
+ +'FD'#204'DDC'#201'EDD'#195'CCC'#182'CCC'#159'CCC}EEEUBBB2@@@'#24'999'#9'UUU'
+ +#3#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#1'333'#5'III'#14'BBB#EEECCCCkEEE'#145'DDC'#174'FFE'#192'KE@'#206'Z;)'
+ +#238'c8'#30#255'i<'#31#255'oB!'#255'|M%'#255#153'_-'#255#178'o4'#255#186'x6'
+ +#255#192#128'7'#255#198#135'9'#255#204#142':'#255#209#149';'#255#214#155'='
+ +#255#219#161'>'#255#223#167'>'#255#227#170'>'#255#230#174'?'#255#232#177'@'
+ +#255#235#181'A'#255#237#183'A'#255#238#185'A'#255#240#187'A'#255#241#188'A'
+ +#255#242#189'B'#255#243#190'A'#255#244#191'B'#255#244#192'B'#255#244#191'B'
+ +#255#244#192'B'#255#244#192'B'#255#245#193'A'#255#244#192'B'#255#244#192'B'
+ +#255#244#191'B'#255#244#192'B'#255#244#191'B'#255#243#190'A'#255#242#189'B'
+ +#255#240#187'A'#255#239#186'A'#255#238#184'@'#255#237#183'A'#255#235#179'@'
+ +#255#232#176'?'#255#229#173'?'#255#226#169'?'#255#223#165'>'#255#218#160'='
+ +#255#213#153'<'#255#208#147';'#255#202#140':'#255#196#133'9'#255#190'~7'#255
+ +#184'v6'#255#173'l3'#255#145'Y+'#255'uH$'#255'm@ '#255'g;'#31#255'b7'#31#253
+ +'U>/'#230'IEC'#206'FFE'#202'EED'#199'CCC'#189'DDD'#170'DDD'#139'BBBdCCC=BBB'
+ +#31'@@@'#12'UUU'#3#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#1'UUU'#6'KKK'#17'DDD)EEENDDDxDCC'#157'DDC'#182'GGC'#197'T=1'#225'a7 '
+ +#252'g;'#31#255'l@ '#255'wI$'#255#154'^.'#255#179'o6'#255#186'x7'#255#193#128
+ +'9'#255#200#137':'#255#207#146'<'#255#212#153'>'#255#217#159'>'#255#222#166
+ +'?'#255#227#170'@'#255#231#175'A'#255#234#180'B'#255#236#182'B'#255#238#185
+ +'B'#255#240#187'B'#255#242#190'D'#255#243#191'C'#255#244#192'D'#255#245#193
+ +'C'#255#246#194'D'#255#247#194'D'#255#247#196'E'#255#247#196'D'#255#247#196
+ +'D'#255#248#197'D'#255#248#197'D'#255#248#197'D'#255#248#197'D'#255#248#197
+ +'D'#255#248#197'D'#255#248#196'D'#255#247#196'D'#255#247#196'D'#255#247#195
+ +'E'#255#246#195'D'#255#245#193'D'#255#245#193'C'#255#244#192'D'#255#243#191
+ +'C'#255#242#189'C'#255#240#186'C'#255#238#184'C'#255#236#182'B'#255#233#179
+ +'B'#255#230#174'A'#255#226#169'@'#255#221#164'?'#255#216#157'>'#255#211#151
+ +'='#255#205#143'<'#255#198#135':'#255#191#127'8'#255#184'w7'#255#174'l4'#255
+ +#144'X+'#255'rE"'#255'j> '#255'e9'#30#255'_8"'#247'O@8'#219'GFD'#204'DDC'#201
+ +'CCC'#194'CCC'#178'DDD'#151'DDDqDDDGGGG$III'#14'@@@'#4#0#0#0#1#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#2'III'#7'@@@'#20'CCC.DDDVCCC'#130'EED'#165'DDC'#189
+ +'LB='#207']7$'#244'd7'#31#255'j> '#255'qE"'#255#140'W+'#255#174'l5'#255#186
+ +'x8'#255#193#129':'#255#200#138'<'#255#207#146'>'#255#213#155'?'#255#220#163
+ +'@'#255#225#169'A'#255#229#174'B'#255#233#179'D'#255#236#182'D'#255#239#185
+ +'D'#255#241#189'E'#255#242#190'E'#255#244#192'E'#255#245#194'E'#255#246#195
+ +'F'#255#247#195'F'#255#247#196'G'#255#247#197'F'#255#248#197'F'#255#248#197
+ +'F'#255#249#198'F'#255#249#198'G'#255#249#198'G'#255#249#198'G'#255#249#198
+ +'G'#255#249#198'G'#255#249#198'G'#255#249#198'G'#255#249#198'G'#255#249#198
+ +'G'#255#249#198'G'#255#249#198'G'#255#249#198'F'#255#248#197'F'#255#248#197
+ +'F'#255#247#196'F'#255#247#196'F'#255#247#195'F'#255#246#194'F'#255#244#193
+ +'F'#255#243#191'E'#255#242#190'E'#255#240#188'E'#255#238#185'D'#255#235#181
+ +'D'#255#232#178'C'#255#228#172'C'#255#223#167'B'#255#218#161'@'#255#212#153
+ +'?'#255#205#144'='#255#198#135';'#255#191#127'9'#255#183'u7'#255#167'g3'#255
+ +#130'P('#255'oB"'#255'h< '#255'c7'#30#255'X:*'#237'HFB'#207'EEE'#202'DCC'#197
+ +'DDD'#184'CCC'#160'CCCzEEENFFF(@@@'#16'333'#5#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ ,#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#2
+ +'III'#7'FFF'#22'BBB2CCC\DDD'#136'DDC'#171'EED'#192'Q?5'#219'a6'#31#252'f:'#31
+ +#255'mA!'#255#127'N'''#255#164'f3'#255#182'u8'#255#190#127':'#255#199#138'='
+ +#255#207#147'?'#255#213#155'A'#255#220#163'B'#255#225#170'D'#255#230#177'E'
+ +#255#234#181'E'#255#237#184'F'#255#240#188'G'#255#242#189'G'#255#243#192'G'
+ +#255#244#193'H'#255#245#194'H'#255#246#195'H'#255#247#196'H'#255#247#197'H'
+ +#255#247#197'H'#255#248#198'H'#255#248#198'H'#255#248#197'H'#255#248#198'H'
+ +#255#248#198'I'#255#249#198'I'#255#249#198'I'#255#249#198'I'#255#249#198'I'
+ +#255#249#198'I'#255#249#198'I'#255#249#198'I'#255#249#198'I'#255#249#198'I'
+ +#255#249#198'I'#255#249#198'I'#255#248#198'I'#255#248#198'H'#255#248#198'H'
+ +#255#248#198'H'#255#248#198'H'#255#247#197'H'#255#247#196'I'#255#247#195'H'
+ +#255#246#195'H'#255#245#195'H'#255#244#193'H'#255#243#191'G'#255#241#189'G'
+ +#255#239#186'G'#255#236#183'F'#255#233#180'F'#255#229#175'D'#255#224#168'D'
+ +#255#218#161'B'#255#211#153'@'#255#205#144'?'#255#196#134'='#255#188'{:'#255
+ +#180'r8'#255#155'_/'#255'wJ$'#255'j? '#255'e8'#30#255']8#'#246'LB<'#213'FEE'
+ +#203'EED'#199'DDD'#188'DDD'#165'DDD'#128'DDDSFFF,GGG'#18'+++'#6#0#0#0#1#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#2'III'#7'CCC'#23'BBB6DDDaCCC'#141'DDC'#174'GDB'#196'V:+'#233'c7'#30#255'h; '
+ +#255'pC#'#255#146'Z-'#255#179'p7'#255#187'{;'#255#196#133'='#255#204#144'?'
+ +#255#212#154'B'#255#219#163'E'#255#225#170'E'#255#230#176'G'#255#234#181'H'
+ +#255#238#185'I'#255#240#189'I'#255#242#190'J'#255#243#192'J'#255#244#193'J'
+ +#255#245#195'J'#255#246#195'J'#255#246#196'J'#255#247#196'K'#255#247#196'K'
+ +#255#247#197'K'#255#247#197'K'#255#247#197'K'#255#247#197'J'#255#247#197'J'
+ +#255#247#198'J'#255#247#198'J'#255#247#198'J'#255#247#198'J'#255#247#198'J'
+ +#255#247#198'J'#255#247#198'J'#255#247#198'J'#255#247#198'J'#255#247#198'J'
+ +#255#247#198'J'#255#247#198'J'#255#247#198'J'#255#247#198'J'#255#247#197'J'
+ +#255#247#197'J'#255#247#197'J'#255#247#197'K'#255#247#197'K'#255#247#197'K'
+ +#255#247#196'K'#255#246#196'K'#255#246#196'J'#255#246#195'J'#255#245#195'J'
+ +#255#244#194'J'#255#243#191'I'#255#241#189'I'#255#239#188'I'#255#236#184'H'
+ +#255#233#180'H'#255#228#174'G'#255#223#168'E'#255#217#160'C'#255#210#151'B'
+ +#255#202#141'?'#255#193#130'<'#255#185'x:'#255#174'm6'#255#134'S*'#255'mA"'
+ +#255'f:'#31#255'a6'#30#253'R>4'#224'FFE'#203'EED'#200'CCC'#190'DDD'#169'CCC'
+ +#133'CCCXAAA/CCC'#19'+++'#6#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#1'III'#7'CCC'#23'BBB6CCCcCCC'#144'EED'#177'JC>'#202
+ +'[6"'#244'c8'#31#255'j?!'#255'xI&'#255#162'd2'#255#183'u:'#255#192#129'='#255
+ +#200#140'@'#255#209#150'B'#255#217#160'E'#255#223#169'G'#255#229#176'H'#255
+ +#233#181'J'#255#236#185'J'#255#239#188'K'#255#241#190'K'#255#242#192'K'#255
+ +#243#193'L'#255#244#194'L'#255#245#195'L'#255#245#195'L'#255#245#195'L'#255
+ +#246#196'L'#255#246#196'L'#255#246#196'L'#255#246#196'L'#255#246#196'M'#255
+ +#246#196'M'#255#246#197'M'#255#246#197'M'#255#246#197'M'#255#246#197'M'#255
+ +#246#197'M'#255#246#197'M'#255#246#197'M'#255#246#197'M'#255#246#197'M'#255
+ +#246#197'M'#255#246#197'M'#255#246#197'M'#255#246#197'M'#255#246#197'M'#255
+ +#246#197'M'#255#246#197'M'#255#246#197'M'#255#246#197'M'#255#246#196'M'#255
+ +#246#196'M'#255#246#196'M'#255#246#196'L'#255#246#196'L'#255#246#196'L'#255
+ +#246#196'L'#255#245#195'L'#255#245#196'L'#255#244#195'M'#255#244#194'L'#255
+ +#243#193'L'#255#242#192'L'#255#241#190'K'#255#238#188'K'#255#236#184'J'#255
+ +#232#179'I'#255#228#173'H'#255#222#166'F'#255#215#158'E'#255#207#148'B'#255
+ +#198#137'?'#255#190'~<'#255#180'r9'#255#150']/'#255'qE$'#255'h< '#255'b6'#30
+ +#255'W9*'#235'GED'#204'DDC'#201'DDD'#192'CCC'#172'CCC'#137'DDDZAAA/GGG'#18'3'
+ +'33'#5#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'+++'#6'II'
+ +'I'#21'CCC5DDDbCCC'#145'DDC'#178'LB;'#206'^6 '#249'd8'#31#255'l@!'#255#131'Q'
+ +'*'#255#172'k7'#255#186'z;'#255#196#133'?'#255#205#146'C'#255#213#156'E'#255
+ +#220#165'G'#255#227#173'I'#255#232#180'K'#255#236#184'L'#255#238#187'L'#255
+ ,#240#189'N'#255#241#191'N'#255#242#192'N'#255#243#193'N'#255#244#194'N'#255
+ +#244#194'N'#255#244#194'O'#255#244#195'O'#255#244#195'O'#255#244#195'O'#255
+ +#244#195'O'#255#244#195'O'#255#244#195'O'#255#244#195'O'#255#244#195'O'#255
+ +#244#195'O'#255#244#195'O'#255#244#195'O'#255#244#195'O'#255#244#195'O'#255
+ +#244#195'O'#255#244#195'O'#255#244#195'O'#255#244#195'O'#255#244#195'O'#255
+ +#244#195'O'#255#244#195'O'#255#244#195'O'#255#244#195'O'#255#244#195'O'#255
+ +#244#195'O'#255#244#195'O'#255#244#195'O'#255#244#195'O'#255#244#195'O'#255
+ +#244#195'O'#255#244#195'O'#255#244#195'O'#255#244#195'O'#255#244#195'O'#255
+ +#244#195'O'#255#244#195'O'#255#244#194'O'#255#244#195'N'#255#244#194'N'#255
+ +#243#193'N'#255#242#192'M'#255#241#190'N'#255#240#189'M'#255#237#186'M'#255
+ +#235#182'L'#255#230#178'K'#255#225#171'I'#255#219#163'G'#255#211#153'D'#255
+ +#202#143'B'#255#192#130'>'#255#183'u:'#255#164'f4'#255'yK&'#255'i=!'#255'c7'
+ +#30#255'Z8%'#241'GEC'#205'DDC'#201'CCC'#193'DDD'#173'DDD'#136'BBBYDDD-KKK'#17
+ +'333'#5#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'333'#5'CCC'#19'BBB2CCC_DD'
+ +'D'#143'DDC'#178'M@8'#211'_5'#31#251'e9'#31#255'lA"'#255#144'Y/'#255#179'r9'
+ +#255#188'}='#255#198#138'B'#255#208#149'D'#255#217#161'H'#255#223#170'K'#255
+ +#229#177'L'#255#234#181'M'#255#236#186'N'#255#239#188'O'#255#240#190'P'#255
+ +#241#191'P'#255#242#192'P'#255#242#192'P'#255#242#193'P'#255#243#193'P'#255
+ +#243#194'P'#255#243#194'P'#255#243#194'P'#255#243#194'P'#255#243#194'P'#255
+ +#243#194'P'#255#243#194'P'#255#243#194'P'#255#243#194'P'#255#243#194'P'#255
+ +#243#194'P'#255#243#194'P'#255#243#194'P'#255#243#194'P'#255#243#194'P'#255
+ +#243#194'P'#255#243#194'P'#255#243#194'P'#255#243#194'P'#255#243#194'P'#255
+ +#243#194'P'#255#243#194'P'#255#243#194'P'#255#243#194'P'#255#243#194'P'#255
+ +#243#194'P'#255#243#194'P'#255#243#194'P'#255#243#194'P'#255#243#194'P'#255
+ +#243#194'P'#255#243#194'P'#255#243#194'P'#255#243#194'P'#255#243#194'P'#255
+ +#243#194'P'#255#243#194'P'#255#243#194'P'#255#243#194'P'#255#243#193'P'#255
+ +#242#193'P'#255#242#192'O'#255#242#192'P'#255#241#192'P'#255#240#190'P'#255
+ +#238#188'O'#255#236#185'N'#255#232#180'M'#255#228#175'L'#255#222#167'I'#255
+ +#215#159'H'#255#205#147'D'#255#196#134'@'#255#186'y<'#255#173'm7'#255#130'O*'
+ +#255'j?!'#255'c8'#31#255'[7#'#245'HDA'#208'DDC'#201'CCC'#193'CCC'#172'CCC'
+ +#134'AAAVAAA+@@@'#16'@@@'#4#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'@@@'#4'<<<'#17'CCC.CC'
+ +'C[CCC'#140'EED'#176'O>5'#213'_5'#30#253'e9'#31#255'nB#'#255#151'\1'#255#181
+ +'s:'#255#191#129'@'#255#201#142'C'#255#211#154'G'#255#219#164'K'#255#226#173
+ +'M'#255#231#179'O'#255#234#184'P'#255#237#187'Q'#255#239#189'Q'#255#240#190
+ +'R'#255#240#191'Q'#255#241#192'R'#255#241#192'R'#255#241#192'R'#255#242#192
+ +'R'#255#242#192'R'#255#242#193'R'#255#242#193'R'#255#242#193'R'#255#242#193
+ +'R'#255#242#193'R'#255#242#193'R'#255#242#193'R'#255#242#193'R'#255#242#193
+ +'R'#255#242#193'R'#255#242#193'R'#255#242#193'R'#255#242#193'R'#255#242#193
+ +'R'#255#242#193'R'#255#242#193'R'#255#242#193'R'#255#242#193'R'#255#242#193
+ +'R'#255#242#193'R'#255#242#193'R'#255#242#193'R'#255#242#193'R'#255#242#193
+ +'R'#255#242#193'R'#255#242#193'R'#255#242#193'R'#255#242#193'R'#255#242#193
+ +'R'#255#242#193'R'#255#242#193'R'#255#242#193'R'#255#242#193'R'#255#242#193
+ +'R'#255#242#193'R'#255#242#193'R'#255#242#193'R'#255#242#193'R'#255#242#193
+ +'R'#255#242#192'R'#255#242#192'R'#255#241#192'R'#255#241#192'R'#255#241#192
+ +'R'#255#240#191'Q'#255#240#190'R'#255#238#189'Q'#255#236#186'P'#255#234#182
+ +'O'#255#230#177'N'#255#224#171'L'#255#217#162'J'#255#208#150'F'#255#198#138
+ +'C'#255#188'}>'#255#177'o:'#255#136'S,'#255'k?"'#255'c8'#31#255'\6!'#248'JC?'
+ +#211'DCC'#201'CCC'#193'CCC'#171'BBB'#131'DDDRAAA''777'#14'UUU'#3#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +'UUU'#3';;;'#13'AAA''CCCTBBB'#135'DDC'#174'N=5'#213'`4'#29#254'e9'#31#255'oC'
+ +'$'#255#156'`3'#255#181'u<'#255#193#131'A'#255#204#146'E'#255#213#157'I'#255
+ +#221#167'M'#255#227#175'O'#255#232#180'Q'#255#235#184'R'#255#237#187'S'#255
+ +#238#189'S'#255#239#190'S'#255#240#191'T'#255#240#191'T'#255#240#191'T'#255
+ +#240#191'T'#255#240#191'T'#255#240#191'T'#255#240#191'T'#255#240#191'T'#255
+ +#240#191'T'#255#240#191'T'#255#240#191'T'#255#240#191'T'#255#240#191'T'#255
+ +#240#191'T'#255#240#191'T'#255#240#191'T'#255#240#191'T'#255#240#191'T'#255
+ ,#240#191'T'#255#240#191'T'#255#240#191'T'#255#240#191'T'#255#240#191'T'#255
+ +#234#187'R'#255#202#161'G'#255#232#185'R'#255#240#191'T'#255#240#191'T'#255
+ +#240#191'T'#255#240#191'T'#255#240#191'T'#255#240#191'T'#255#240#191'T'#255
+ +#240#191'T'#255#240#191'T'#255#240#191'T'#255#240#191'T'#255#240#191'T'#255
+ +#240#191'T'#255#240#191'T'#255#240#191'T'#255#240#191'T'#255#240#191'T'#255
+ +#240#191'T'#255#240#191'T'#255#240#191'T'#255#240#191'T'#255#240#191'T'#255
+ +#240#191'T'#255#240#191'T'#255#240#191'T'#255#240#191'T'#255#240#191'T'#255
+ +#239#189'S'#255#238#188'R'#255#236#186'R'#255#234#184'Q'#255#231#179'Q'#255
+ +#226#173'O'#255#219#165'L'#255#211#154'H'#255#201#142'E'#255#190#128'@'#255
+ +#179'q:'#255#140'V.'#255'l@"'#255'c8'#31#255'\4'#31#250'JC>'#211'CCC'#201'DD'
+ +'D'#192'CCC'#168'CCC~DDDKFFF!MMM'#10#128#128#128#2#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#128#128#128#2'333'#10'@@@ EEE'
+ +'JCCC~EDD'#169'L?8'#208'^4'#30#253'd8 '#255'pD%'#255#159'b4'#255#182'v='#255
+ +#194#132'C'#255#205#147'H'#255#215#160'L'#255#222#169'O'#255#228#176'Q'#255
+ +#232#181'S'#255#235#185'T'#255#236#187'T'#255#237#188'U'#255#238#189'U'#255
+ +#238#190'U'#255#238#190'U'#255#238#191'U'#255#239#190'U'#255#239#190'U'#255
+ +#239#190'U'#255#239#190'U'#255#239#190'U'#255#239#190'U'#255#239#190'U'#255
+ +#239#190'U'#255#239#190'U'#255#239#190'U'#255#239#190'U'#255#239#190'U'#255
+ +#239#190'U'#255#239#190'U'#255#239#190'U'#255#239#190'U'#255#181#144'@'#255
+ +';/'#21#255#21#16#7#255#9#7#3#255#2#2#1#255#0#0#0#255#0#0#0#255#0#0#0#255#1#1
+ +#1#255#7#6#3#255#17#14#6#255#31#25#11#255'2'''#18#255'SB'#29#255#157'}8'#255
+ +#233#186'S'#255#239#190'U'#255#239#190'U'#255#239#190'U'#255#239#190'U'#255
+ +#239#190'U'#255#239#190'U'#255#239#190'U'#255#239#190'U'#255#239#190'U'#255
+ +#239#190'U'#255#239#190'U'#255#239#190'U'#255#239#190'U'#255#239#190'U'#255
+ +#239#190'U'#255#239#190'U'#255#239#190'U'#255#238#190'U'#255#238#190'U'#255
+ +#238#190'U'#255#238#189'U'#255#237#188'U'#255#236#186'T'#255#234#184'T'#255
+ +#231#180'S'#255#226#175'Q'#255#220#166'N'#255#212#156'K'#255#202#143'F'#255
+ +#190#129'A'#255#179'r<'#255#145'Y0'#255'k?"'#255'c7'#31#255'[4 '#248'IC@'#209
+ +'DDD'#200'CCC'#190'CCC'#163'DDDtCCCAEEE'#26'III'#7#0#0#0#1#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'III'#7'==='#25'AAA?CCCsBBB'
+ +#162'K?;'#202'^4'#30#252'c8 '#255'oB%'#255#160'b5'#255#183'v>'#255#194#134'D'
+ +#255#205#148'J'#255#215#161'M'#255#223#171'Q'#255#228#177'T'#255#232#182'U'
+ +#255#234#185'V'#255#236#187'V'#255#236#187'V'#255#237#188'W'#255#237#189'W'
+ +#255#237#188'W'#255#237#188'W'#255#237#188'W'#255#237#188'W'#255#237#188'W'
+ +#255#237#188'W'#255#237#188'W'#255#237#188'W'#255#237#188'W'#255#237#188'W'
+ +#255#237#188'W'#255#237#188'W'#255#237#188'W'#255#237#188'W'#255#237#188'W'
+ +#255#237#188'W'#255#237#188'W'#255#159'~:'#255#16#13#6#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1#0#0#255#16#13#6
+ +#255'9-'#21#255'y`,'#255#208#165'M'#255#237#188'W'#255#237#188'W'#255#237#188
+ +'W'#255#237#188'W'#255#237#188'W'#255#237#188'W'#255#237#188'W'#255#237#188
+ +'W'#255#237#188'W'#255#237#188'W'#255#237#188'W'#255#237#188'W'#255#237#188
+ +'W'#255#237#188'W'#255#237#188'W'#255#237#188'W'#255#237#189'W'#255#237#188
+ +'W'#255#236#187'V'#255#235#186'V'#255#234#184'U'#255#231#180'U'#255#227#175
+ +'R'#255#221#169'Q'#255#213#157'L'#255#202#144'H'#255#191#129'C'#255#180's='
+ +#255#145'X0'#255'j>#'#255'b6'#31#255'Z5#'#245'GDB'#206'DDD'#200'CCC'#186'DDD'
+ +#154'EEEhBBB6@@@'#20'333'#5#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#1'@@@'#4'GGG'#18'AAA3DDDfCCC'#152'IA>'#195'\4 '#250'c7'#31#255'm@#'#255
+ +#156'_5'#255#182'v?'#255#194#134'E'#255#206#148'K'#255#215#161'O'#255#223#171
+ +'S'#255#228#178'V'#255#232#182'V'#255#233#185'X'#255#234#186'X'#255#235#187
+ +'X'#255#236#187'X'#255#236#188'X'#255#236#188'X'#255#236#188'X'#255#236#188
+ +'X'#255#236#188'X'#255#236#188'X'#255#236#188'X'#255#236#188'X'#255#236#188
+ +'X'#255#236#188'X'#255#236#188'X'#255#236#188'X'#255#236#188'X'#255#236#188
+ +'X'#255#236#188'X'#255#236#188'X'#255#236#188'X'#255#236#188'X'#255'9-'#21
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#6
+ +#5#2#255'$'#29#14#255'ZH"'#255#169#135'@'#255#234#186'X'#255#236#188'X'#255
+ ,#236#188'X'#255#236#188'X'#255#236#188'X'#255#236#188'X'#255#236#188'X'#255
+ +#236#188'X'#255#236#188'X'#255#236#188'X'#255#236#188'X'#255#236#188'X'#255
+ +#236#188'X'#255#236#187'X'#255#235#187'Y'#255#235#186'X'#255#234#186'X'#255
+ +#233#184'W'#255#231#180'W'#255#227#176'T'#255#221#169'R'#255#213#158'N'#255
+ +#203#145'J'#255#192#130'D'#255#179's='#255#139'U/'#255'i="'#255'a5'#30#255'X'
+ +'7%'#242'FDC'#204'CCC'#198'DDD'#180'CCC'#144'CCC[AAA+III'#14'UUU'#3#0#0#0#1#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#128#128#128#2'@@@'#12'AAA''CCCWCCC'#140'GB?'
+ +#185'Z4!'#247'a6'#30#255'j?"'#255#151']2'#255#181't>'#255#194#133'F'#255#206
+ +#149'M'#255#215#161'Q'#255#223#170'T'#255#228#178'W'#255#231#181'Y'#255#232
+ +#183'Y'#255#233#185'Z'#255#234#185'Y'#255#234#186'Y'#255#234#186'Y'#255#234
+ +#186'Z'#255#234#186'Z'#255#234#186'Z'#255#234#186'Z'#255#234#186'Z'#255#234
+ +#186'Z'#255#234#186'Z'#255#234#186'Z'#255#234#186'Z'#255#234#186'Z'#255#234
+ +#186'Z'#255#234#186'Z'#255#234#186'Z'#255#234#186'Z'#255#234#186'Z'#255#234
+ +#186'Z'#255#234#186'Z'#255'C5'#26#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#1#1#1#255#20#16#8#255'K;'#29#255#189#150'I'#255#234#186'Z'#255#234#186
+ +'Z'#255#234#186'Z'#255#234#186'Z'#255#234#186'Z'#255#234#186'Z'#255#234#186
+ +'Z'#255#234#186'Z'#255#234#186'Z'#255#234#186'Z'#255#234#186'Y'#255#234#186
+ +'Y'#255#234#185'Y'#255#233#185'Z'#255#232#183'Y'#255#230#181'X'#255#226#176
+ +'W'#255#221#169'T'#255#213#159'O'#255#203#145'K'#255#190#129'D'#255#178'p='
+ +#255#134'Q-'#255'g;"'#255'`4'#29#255'U7('#238'CCC'#202'DDD'#195'DDD'#173'BBB'
+ +#131'CCCL@@@ 999'#9#0#0#0#2#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'III'#7'BBB'#27'CC'
+ +'CEDDD|DDD'#170'V6%'#238'`5'#30#255'h<"'#255#145'Y1'#255#179's?'#255#192#132
+ +'F'#255#205#148'M'#255#215#161'R'#255#222#171'U'#255#227#176'X'#255#230#181
+ +'Z'#255#231#183'Z'#255#232#183'['#255#232#184'['#255#233#185'['#255#233#185
+ +'['#255#233#185'['#255#233#185'['#255#233#185'['#255#233#185'['#255#233#185
+ +'['#255#233#185'['#255#233#185'['#255#233#185'['#255#233#185'['#255#233#185
+ +'['#255#233#185'['#255#233#185'['#255#233#185'['#255#233#185'['#255#233#185
+ +'['#255#233#185'['#255#233#185'['#255#127'd1'#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#13#11#5
+ +#255'N>'#31#255#193#153'L'#255#233#185'['#255#233#185'['#255#233#185'['#255
+ +#233#185'['#255#233#185'['#255#233#185'['#255#233#185'['#255#233#185'['#255
+ +#233#185'['#255#233#184'['#255#232#184'['#255#232#183'Z'#255#231#182'Z'#255
+ +#229#180'Y'#255#226#175'X'#255#220#168'U'#255#213#158'R'#255#201#144'K'#255
+ +#189#127'D'#255#175'n<'#255#128'N+'#255'e9 '#255'_3'#29#255'Q;1'#227'CCC'#201
+ +'CCC'#191'CCC'#163'CCCrAAA;FFF'#22'333'#5#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'@@@'#4'<<<'
+ +#17'AAA3EEEhCCC'#156'R:/'#220'_3'#29#255'e: '#255#134'Q-'#255#178'p>'#255#190
+ +#130'F'#255#203#145'M'#255#213#161'S'#255#221#170'W'#255#226#176'Z'#255#229
+ +#180'Z'#255#230#182'\'#255#231#182'\'#255#231#183'\'#255#231#183'\'#255#231
+ +#183'\'#255#231#183'\'#255#231#183'\'#255#231#183'\'#255#231#183'\'#255#231
+ +#183'\'#255#231#183'\'#255#231#183'\'#255#231#183'\'#255#231#183'\'#255#231
+ +#183'\'#255#231#183'\'#255#231#183'\'#255#231#183'\'#255#231#183'\'#255#231
+ +#183'\'#255#231#183'\'#255#231#183'\'#255#180#142'G'#255#1#1#1#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#15#12#6#255'VE"'#255#215#171'V'#255
+ +#231#183'\'#255#231#183'\'#255#231#183'\'#255#231#183'\'#255#231#183'\'#255
+ +#231#183'\'#255#231#183'\'#255#231#183'\'#255#231#183'\'#255#231#182'\'#255
+ +#230#181'['#255#228#178'['#255#225#175'Y'#255#219#168'W'#255#211#156'Q'#255
+ +#200#142'K'#255#187'|D'#255#172'k<'#255'wF('#255'c7 '#255'^1'#30#254'K@:'#214
+ +'DDD'#199'CCC'#184'CCC'#148'AAA^GGG+NNN'#13'UUU'#3#0#0#0#0#0#0#0#0#0#0#0#0#0
+ ,#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#2'MMM'#10'@'
+ +'@@$DDDSDDD'#139'L?8'#197'^1'#29#254'c7 '#255'wG)'#255#173'l<'#255#188#127'E'
+ +#255#201#144'N'#255#212#158'T'#255#220#169'X'#255#225#175'['#255#228#179'\'
+ +#255#229#180'\'#255#230#181']'#255#230#181']'#255#230#182']'#255#230#182']'
+ +#255#230#182']'#255#230#182']'#255#230#182']'#255#230#182']'#255#230#182']'
+ +#255#230#182']'#255#230#182']'#255#230#182']'#255#230#182']'#255#230#182']'
+ +#255#230#182']'#255#230#182']'#255#230#182']'#255#230#182']'#255#230#182']'
+ +#255#230#182']'#255#230#182']'#255#221#175'Y'#255#10#8#4#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1#1#1#255'4'
+ +')'#21#255#184#146'J'#255#230#182']'#255#230#182']'#255#230#182']'#255#230
+ +#182']'#255#230#182']'#255#230#182']'#255#230#182']'#255#230#181']'#255#229
+ +#182']'#255#228#180']'#255#227#178'\'#255#224#174'['#255#218#166'W'#255#209
+ +#155'R'#255#198#139'K'#255#184'zC'#255#162'd8'#255'l@$'#255'a5'#30#255'Z3 '
+ +#249'FBA'#206'DDD'#196'CCC'#174'CCC'#129'BBBIFFF'#29'@@@'#8#0#0#0#1#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'333'#5'FF'
+ +'F'#22'BBB>CCCvFA?'#174'Z3'#31#248'`5'#30#255'l@$'#255#163'd9'#255#184'{D'
+ +#255#199#142'N'#255#210#156'T'#255#218#167'Y'#255#223#174'\'#255#226#177'^'
+ +#255#228#179'^'#255#228#179'^'#255#228#180'_'#255#228#180'_'#255#228#180'_'
+ +#255#228#180'_'#255#228#180'_'#255#228#180'_'#255#228#180'_'#255#228#180'_'
+ +#255#228#180'_'#255#228#180'_'#255#228#180'_'#255#228#180'_'#255#228#180'_'
+ +#255#228#180'_'#255#228#180'_'#255#228#180'_'#255#228#180'_'#255#228#180'_'
+ +#255#228#180'_'#255#228#180'_'#255#228#180'_'#255'bM)'#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#27#21#11#255#140'o;'#255#228#180'_'#255#228#180
+ +'_'#255#228#180'_'#255#228#180'_'#255#228#180'_'#255#228#180'_'#255#228#180
+ +'_'#255#228#179'^'#255#227#179'^'#255#226#176']'#255#222#172'['#255#216#164
+ +'X'#255#207#152'R'#255#195#137'K'#255#181'tA'#255#149'Z3'#255'g<"'#255'_3'#29
+ +#255'V6'''#239'CCC'#201'CCC'#190'CCC'#159'CCCkCCC5GGG'#18'@@@'#4#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#2'@@@'#12'CCC'
+ +'*DDD^DDD'#150'U6('#230'^2'#28#255'f:!'#255#149'Z3'#255#181'uB'#255#195#137
+ +'K'#255#208#154'T'#255#216#165'Y'#255#221#172']'#255#225#176'^'#255#226#178
+ +'_'#255#227#178'_'#255#227#178'_'#255#227#179'_'#255#227#179'_'#255#227#179
+ +'_'#255#227#179'_'#255#227#179'_'#255#227#179'_'#255#227#179'_'#255#227#179
+ +'_'#255#227#179'_'#255#227#179'_'#255#227#179'_'#255#227#179'_'#255#227#179
+ +'_'#255#227#179'_'#255#227#179'_'#255#227#179'_'#255#227#179'_'#255#227#179
+ +'_'#255#227#179'_'#255#227#179'_'#255#227#179'_'#255#13#10#6#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'&'#30#16#255#208#164
+ +'W'#255#227#179'_'#255#227#179'_'#255#227#179'_'#255#227#179'_'#255#227#178
+ +'_'#255#227#178'_'#255#226#179'`'#255#226#177'_'#255#224#176'^'#255#220#170
+ +'\'#255#214#162'X'#255#205#149'R'#255#191#131'I'#255#177'p?'#255#131'O.'#255
+ +'c7 '#255']1'#29#255'N;3'#222'DDD'#199'DDD'#181'CCC'#140'DDDSDDD"999'#9#0#0#0
+ +#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'+++'#6'@@@'#24
+ +'EEECCCC~K=7'#193']0'#28#255'b6'#31#255#129'M,'#255#177'o@'#255#191#131'J'
+ +#255#204#149'S'#255#214#163'Z'#255#220#171']'#255#223#174'_'#255#225#176'`'
+ +#255#225#177'`'#255#226#177'`'#255#226#177'`'#255#226#177'`'#255#226#177'`'
+ +#255#226#177'`'#255#226#177'`'#255#226#177'`'#255#226#177'`'#255#226#177'`'
+ +#255#226#177'`'#255#226#177'`'#255#226#177'`'#255#226#177'`'#255#226#177'`'
+ ,#255#226#177'`'#255#226#177'`'#255#226#177'`'#255#226#177'`'#255#226#177'`'
+ +#255#226#177'`'#255#226#177'`'#255#226#177'`'#255#161'~D'#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#4#3#2
+ +#255#134'i9'#255#226#177'`'#255#226#177'`'#255#226#177'`'#255#226#177'`'#255
+ +#226#177'`'#255#225#178'`'#255#225#177'`'#255#224#176'_'#255#222#174'^'#255
+ +#219#169']'#255#212#159'X'#255#200#144'Q'#255#187'~G'#255#170'j<'#255'qB%'
+ +#255'`5'#30#255'Z2'#31#250'FBA'#205'CCC'#193'DDD'#166'CCCsCCC9CCC'#19'@@@'#4
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#2'@@@'#12'AAA+BBB'
+ +'aDBB'#155'Y3!'#244'_3'#29#255'l?$'#255#167'f;'#255#186'}H'#255#200#144'R'
+ +#255#211#158'Y'#255#218#168']'#255#221#172'`'#255#223#174'a'#255#223#176'a'
+ +#255#224#176'b'#255#224#176'b'#255#224#176'b'#255#224#176'b'#255#224#176'b'
+ +#255#224#176'b'#255#224#176'b'#255#224#176'b'#255#224#176'b'#255#224#176'b'
+ +#255#224#176'b'#255#224#176'b'#255#224#176'b'#255#224#176'b'#255#224#176'b'
+ +#255#224#176'b'#255#224#176'b'#255#224#176'b'#255#224#176'b'#255#224#176'b'
+ +#255#224#176'b'#255#224#176'b'#255#224#176'b'#255'hR.'#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255'qY2'#255#224#176'b'#255#224#176'b'#255#224#176'b'#255#224#176
+ +'b'#255#224#176'b'#255#224#176'b'#255#223#176'a'#255#223#174'`'#255#221#172
+ +'_'#255#217#166']'#255#208#155'W'#255#196#139'O'#255#182'wE'#255#152'\5'#255
+ +'e9!'#255'^2'#29#255'S7*'#233'DDD'#200'CCC'#183'DDD'#143'EEEUDDD"UUU'#9#0#0#0
+ +#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'333'#5'@@@'#24'DDDDCCC~P8-'
+ +#211']0'#29#255'c8!'#255#144'V2'#255#180'uD'#255#196#138'P'#255#207#155'X'
+ +#255#215#165']'#255#220#171'`'#255#221#173'b'#255#222#174'a'#255#222#175'b'
+ +#255#222#175'b'#255#222#175'b'#255#222#175'b'#255#222#175'b'#255#222#175'b'
+ +#255#222#175'b'#255#222#175'b'#255#222#175'b'#255#222#175'b'#255#222#175'b'
+ +#255#222#175'b'#255#222#175'b'#255#222#175'b'#255#222#175'b'#255#222#175'b'
+ +#255#222#175'b'#255#222#175'b'#255#222#175'b'#255#222#175'b'#255#222#175'b'
+ +#255#222#175'b'#255#222#175'b'#255#222#175'b'#255'VD&'#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#1#1#0#255#166#132'J'#255#222#175'b'#255#222#175'b'#255#222#175
+ +'b'#255#222#175'b'#255#222#175'b'#255#222#175'b'#255#222#174'a'#255#221#173
+ +'a'#255#219#170'`'#255#213#163'\'#255#205#150'V'#255#192#132'M'#255#176'oA'
+ +#255'}K,'#255'a5'#31#255'\0'#28#254'I?;'#212'CCC'#194'DDD'#166'CCCrDDD8GGG'
+ +#18'@@@'#4#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#2'FFF'#11'DDD)BBB`G@<'
+ +#164'[1'#29#252'_3'#29#255'uD)'#255#174'l?'#255#189#130'L'#255#204#150'V'#255
+ +#213#162'^'#255#217#168'`'#255#220#172'b'#255#221#173'b'#255#221#173'c'#255
+ +#221#173'c'#255#221#173'c'#255#221#173'c'#255#221#173'c'#255#221#173'c'#255
+ +#221#173'c'#255#221#173'c'#255#221#173'c'#255#221#173'c'#255#221#173'c'#255
+ +#221#173'c'#255#221#173'c'#255#221#173'c'#255#221#173'c'#255#221#173'c'#255
+ +#221#173'c'#255#221#173'c'#255#221#173'c'#255#221#173'c'#255#221#173'c'#255
+ +#221#173'c'#255#221#173'c'#255#221#173'c'#255#221#173'c'#255'gQ.'#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ ,#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#8#6#4#255#207#163']'#255#221#173'c'#255
+ +#221#173'c'#255#221#173'c'#255#221#173'c'#255#221#173'c'#255#221#173'c'#255
+ +#221#172'b'#255#219#171'b'#255#217#167'`'#255#211#159'['#255#200#145'T'#255
+ +#185'{H'#255#164'd;'#255'h<#'#255'^1'#29#255'X3#'#244'DDD'#200'CCC'#183'DDD'
+ +#142'DDDSFFF!@@@'#8#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'@@@'#4'III'#21'EEE?DD'
+ +'D|S5'''#222'\1'#28#255'c8!'#255#158'_8'#255#183'yH'#255#198#142'S'#255#209
+ +#158'\'#255#215#166'`'#255#218#170'b'#255#219#171'c'#255#219#171'd'#255#219
+ +#172'd'#255#219#172'd'#255#219#172'd'#255#219#172'd'#255#219#172'd'#255#219
+ +#172'd'#255#219#172'd'#255#219#172'd'#255#219#172'd'#255#219#172'd'#255#219
+ +#172'd'#255#219#172'd'#255#219#172'd'#255#219#172'd'#255#219#172'd'#255#219
+ +#172'd'#255#219#172'd'#255#219#172'd'#255#219#172'd'#255#219#172'd'#255#219
+ +#172'd'#255#219#172'd'#255#219#172'd'#255#219#172'd'#255#219#172'd'#255#213
+ +#168'b'#255#3#3#1#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'M<#'#255#219#172
+ +'d'#255#219#172'd'#255#219#172'd'#255#219#172'd'#255#219#172'd'#255#219#172
+ +'d'#255#219#171'd'#255#219#170'c'#255#217#168'b'#255#214#164'`'#255#207#153
+ +'Z'#255#194#136'P'#255#178'rD'#255#139'R1'#255'a4'#31#255'\0'#28#255'L<5'#219
+ +'CCC'#193'DDD'#164'CCCoCCC5@@@'#16'UUU'#3#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'@@@'#8
+ +'BBB#CCCWHA='#158'\0'#28#253'_3'#29#255'~I+'#255#175'nB'#255#191#133'O'#255
+ +#205#151'Z'#255#213#163'a'#255#216#167'c'#255#217#169'c'#255#218#170'd'#255
+ +#218#170'd'#255#218#170'd'#255#218#170'd'#255#218#170'd'#255#218#170'd'#255
+ +#218#170'd'#255#218#170'd'#255#218#170'd'#255#218#170'd'#255#218#170'd'#255
+ +#218#170'd'#255#218#170'd'#255#218#170'd'#255#218#170'd'#255#218#170'd'#255
+ +#218#170'd'#255#218#170'd'#255#218#170'd'#255#218#170'd'#255#218#170'd'#255
+ +#218#170'd'#255#218#170'd'#255#218#170'd'#255#218#170'd'#255#218#170'd'#255
+ +#218#170'd'#255#218#170'd'#255'YF)'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#15#12#7#255#218#170'd'#255#218#170'd'#255#218#170'd'#255#218#170'd'#255
+ +#218#170'd'#255#218#170'd'#255#218#170'd'#255#218#169'c'#255#217#168'c'#255
+ +#215#166'b'#255#211#160'_'#255#201#147'W'#255#187#127'L'#255#169'h>'#255'l=$'
+ +#255'^1'#29#255'W3"'#244'DDD'#199'DDD'#180'DDD'#136'DDDKBBB'#27'UUU'#6#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0'UUU'#3'DDD'#15'EEE4BBBpS6)'#215'\1'#28#255'b7!'#255#158'_9'
+ +#255#184'{J'#255#199#144'W'#255#209#158'_'#255#214#165'c'#255#216#168'd'#255
+ +#217#168'd'#255#217#168'd'#255#217#168'd'#255#217#168'd'#255#217#168'd'#255
+ +#217#168'd'#255#217#168'd'#255#217#168'd'#255#217#168'd'#255#217#168'd'#255
+ +#217#168'd'#255#217#168'd'#255#217#168'd'#255#217#168'd'#255#217#168'd'#255
+ +#217#168'd'#255#217#168'd'#255#217#168'd'#255#217#168'd'#255#217#168'd'#255
+ +#217#168'd'#255#217#168'd'#255#217#168'd'#255#217#168'd'#255#217#168'd'#255
+ +#217#168'd'#255#217#168'd'#255#217#168'd'#255#217#168'd'#255#217#168'd'#255
+ +'YD)'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#189#147'W'#255#217#168'd'
+ +#255#217#168'd'#255#217#168'd'#255#217#168'd'#255#217#168'd'#255#217#168'd'
+ +#255#217#168'd'#255#216#168'd'#255#215#167'c'#255#213#164'a'#255#207#154']'
+ +#255#195#138'S'#255#179'tF'#255#139'R1'#255'`5'#30#255'\0'#28#255'K=7'#216'D'
+ +'DD'#191'DDD'#157'CCCcAAA+FFF'#11#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ ,#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'+++'#6'EEE'#26'BBBIE?='
+ +#144'Z0'#28#252'^2'#29#255'zF*'#255#174'mB'#255#192#135'R'#255#205#152'\'#255
+ +#211#161'b'#255#214#165'd'#255#215#166'd'#255#215#166'd'#255#215#166'd'#255
+ +#215#166'd'#255#215#166'd'#255#215#166'd'#255#215#166'd'#255#215#166'd'#255
+ +#215#166'd'#255#215#166'd'#255#215#166'd'#255#215#166'd'#255#215#166'd'#255
+ +#215#166'd'#255#215#166'd'#255#215#166'd'#255#215#166'd'#255#215#166'd'#255
+ +#215#166'd'#255#215#166'd'#255#215#166'd'#255#215#166'd'#255#215#166'd'#255
+ +#215#166'd'#255#215#166'd'#255#215#166'd'#255#215#166'd'#255#215#166'd'#255
+ +#215#166'd'#255#215#166'd'#255#215#166'd'#255#215#166'd'#255'jR1'#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255'fN/'#255#215#166'd'#255#215#166'd'#255#215#166'd'
+ +#255#215#166'd'#255#215#166'd'#255#215#166'd'#255#215#166'd'#255#215#166'd'
+ +#255#215#167'e'#255#214#164'c'#255#210#159'a'#255#202#148'Z'#255#187#128'N'
+ +#255#168'f='#255'i;#'#255'\1'#28#255'V3#'#242'CCC'#197'DDD'#173'BBB{FFF>@@@'
+ +#20'@@@'#4#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#1'MMM'#10'FFF(CCC_R6*'#206'\0'#28#255'`5'#31#255#154'\8'
+ +#255#182'yJ'#255#199#144'Y'#255#208#156'`'#255#212#163'd'#255#213#165'd'#255
+ +#214#165'e'#255#214#165'e'#255#214#165'e'#255#214#165'e'#255#214#165'e'#255
+ +#214#165'e'#255#214#165'e'#255#214#165'e'#255#214#165'e'#255#214#165'e'#255
+ +#214#165'e'#255#214#165'e'#255#214#165'e'#255#214#165'e'#255#214#165'e'#255
+ +#214#165'e'#255#214#165'e'#255#214#165'e'#255#214#165'e'#255#214#165'e'#255
+ +#214#165'e'#255#214#165'e'#255#214#165'e'#255#214#165'e'#255#214#165'e'#255
+ +#214#165'e'#255#214#165'e'#255#214#165'e'#255#214#165'e'#255#214#165'e'#255
+ +#214#165'e'#255#214#165'e'#255#214#165'e'#255#135'h@'#255#2#1#1#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'b'
+ +'L/'#255#214#165'e'#255#214#165'e'#255#214#165'e'#255#214#165'e'#255#214#165
+ +'e'#255#214#165'e'#255#214#165'e'#255#214#165'e'#255#213#165'e'#255#213#164
+ +'d'#255#211#161'c'#255#206#154'^'#255#194#139'U'#255#177'sF'#255#135'P/'#255
+ +'^3'#29#255'[/'#27#255'J>9'#213'DDD'#185'CCC'#144'DDDSHHH III'#7#0#0#0#1#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'UUU'#3
+ +'<<<'#17'DDD8DBAyZ0'#29#248'\1'#28#255'uB'''#255#172'lA'#255#190#132'Q'#255
+ +#203#151'^'#255#209#160'c'#255#211#162'e'#255#212#163'e'#255#212#163'e'#255
+ +#212#163'e'#255#212#163'e'#255#212#163'e'#255#212#163'e'#255#212#163'e'#255
+ +#212#163'e'#255#212#163'e'#255#212#163'e'#255#212#163'e'#255#212#163'e'#255
+ +#212#163'e'#255#212#163'e'#255#212#163'e'#255#212#163'e'#255#212#163'e'#255
+ +#212#163'e'#255#212#163'e'#255#212#163'e'#255#212#163'e'#255#212#163'e'#255
+ +#212#163'e'#255#212#163'e'#255#212#163'e'#255#212#163'e'#255#212#163'e'#255
+ +#212#163'e'#255#212#163'e'#255#212#163'e'#255#212#163'e'#255#212#163'e'#255
+ +#212#163'e'#255#212#163'e'#255#212#163'e'#255#156'xK'#255#1#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'jQ2'#255#212
+ +#163'e'#255#212#163'e'#255#212#163'e'#255#212#163'e'#255#212#163'e'#255#212
+ +#163'e'#255#212#163'e'#255#212#163'e'#255#212#163'e'#255#212#162'e'#255#211
+ +#162'd'#255#208#158'b'#255#200#147'['#255#186'~M'#255#165'd<'#255'd8!'#255'\'
+ +'0'#28#255'T5'''#237'CCC'#193'DDD'#162'CCCjCCC.@@@'#12#0#0#0#2#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'333'#5'GGG'#25'BB'
+ +'BIN:1'#174'[/'#27#255'^2'#29#255#145'T3'#255#180'vI'#255#196#142'Y'#255#206
+ +#155'a'#255#209#161'e'#255#211#162'e'#255#211#162'e'#255#211#162'e'#255#211
+ +#162'e'#255#211#162'e'#255#211#162'e'#255#211#162'e'#255#211#162'e'#255#211
+ +#162'e'#255#211#162'e'#255#211#162'e'#255#211#162'e'#255#211#162'e'#255#211
+ ,#162'e'#255#211#162'e'#255#211#162'e'#255#211#162'e'#255#211#162'e'#255#211
+ +#162'e'#255#211#162'e'#255#211#162'e'#255#211#162'e'#255#211#162'e'#255#211
+ +#162'e'#255#211#162'e'#255#211#162'e'#255#211#162'e'#255#211#162'e'#255#211
+ +#162'e'#255#211#162'e'#255#211#162'e'#255#211#162'e'#255#211#162'e'#255#211
+ +#162'e'#255#211#162'e'#255#211#162'e'#255#211#162'e'#255'O=&'#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'sX7'#255#211
+ +#162'e'#255#211#162'e'#255#211#162'e'#255#211#162'e'#255#211#162'e'#255#211
+ +#162'e'#255#211#162'e'#255#211#162'e'#255#211#162'e'#255#211#162'e'#255#210
+ +#161'f'#255#209#159'd'#255#204#153'`'#255#192#135'U'#255#175'pE'#255'~H+'#255
+ +']0'#29#255'Z0'#28#253'FBA'#201'DDD'#176'CCC~FFF>CCC'#19'@@@'#4#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'999'#9'EEE%CCC[V3'
+ +'$'#222'\0'#27#255'f7!'#255#167'd>'#255#187#128'Q'#255#200#148'^'#255#207#156
+ +'d'#255#209#159'e'#255#209#160'e'#255#209#160'e'#255#209#160'e'#255#209#160
+ +'e'#255#209#160'e'#255#209#160'e'#255#209#160'e'#255#209#160'e'#255#209#160
+ +'e'#255#209#160'e'#255#209#160'e'#255#209#160'e'#255#209#160'e'#255#209#160
+ +'e'#255#209#160'e'#255#209#160'e'#255#151'tI'#255'2&'#25#255#27#21#13#255#15
+ +#12#7#255#7#5#3#255#7#5#3#255' '#25#16#255'P='''#255#151'tI'#255#209#160'e'
+ +#255#209#160'e'#255#209#160'e'#255#209#160'e'#255#209#160'e'#255#209#160'e'
+ +#255#209#160'e'#255#209#160'e'#255#209#160'e'#255#209#160'e'#255#209#160'e'
+ +#255#209#160'e'#255#209#160'e'#255#6#5#3#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#146'pF'#255#209#160'e'#255#209#160'e'#255
+ +#209#160'e'#255#209#160'e'#255#209#160'e'#255#209#160'e'#255#209#160'e'#255
+ +#209#160'e'#255#209#160'e'#255#209#160'e'#255#209#160'e'#255#209#159'e'#255
+ +#206#155'c'#255#198#143'['#255#182'zM'#255#151'Y6'#255'^3'#29#255'[/'#27#255
+ +'N:1'#222'DDD'#185'DDD'#142'DDDOIII'#28'+++'#6#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#2';;;'#13'DDD1F@=x[/'#28#253'\1'#28
+ +#255'~G+'#255#174'oE'#255#193#137'X'#255#203#151'b'#255#207#156'e'#255#207
+ +#158'f'#255#208#158'f'#255#208#158'f'#255#208#158'f'#255#208#158'f'#255#208
+ +#158'f'#255#208#158'f'#255#208#158'f'#255#208#158'f'#255#208#158'f'#255#208
+ +#158'f'#255#208#158'f'#255#208#158'f'#255#208#158'f'#255#208#158'f'#255'x[;'
+ +#255#15#12#8#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#4#3#2#255'bJ0'#255#208#158'f'#255#208#158'f'
+ +#255#208#158'f'#255#208#158'f'#255#208#158'f'#255#208#158'f'#255#208#158'f'
+ +#255#208#158'f'#255#208#158'f'#255#208#158'f'#255#208#158'f'#255'3'''#25#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#2#2#1#255#208#158'f'
+ +#255#208#158'f'#255#208#158'f'#255#208#158'f'#255#208#158'f'#255#208#158'f'
+ +#255#208#158'f'#255#208#158'f'#255#208#158'f'#255#208#158'f'#255#208#158'f'
+ +#255#208#158'f'#255#207#158'e'#255#206#156'd'#255#201#149'_'#255#189#131'T'
+ +#255#169'h@'#255'j:#'#255'\0'#28#255'V3#'#242'DDD'#191'CCC'#156'BBB`AAA''333'
+ +#10#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'@@@'#4'C'
+ +'CC'#19'EEE?Q7+'#179'[/'#27#255'^1'#29#255#152'X6'#255#181'yM'#255#197#144']'
+ +#255#204#153'c'#255#206#155'f'#255#206#156'e'#255#206#156'e'#255#206#156'e'
+ +#255#206#156'e'#255#206#156'e'#255#206#156'e'#255#206#156'e'#255#206#156'e'
+ +#255#206#156'e'#255#206#156'e'#255#206#156'e'#255#206#156'e'#255#206#156'e'
+ +#255#202#154'c'#255'6)'#27#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#14#10#7#255#178#135'W'#255#206#156'e'#255#206#156'e'#255#206#156'e'
+ +#255#206#156'e'#255#206#156'e'#255#206#156'e'#255#206#156'e'#255#206#156'e'
+ +#255#206#156'e'#255'WB+'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ ,#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#29#22#14#255#206#156'e'#255#206#156'e'#255#206#156'e'#255#206#156'e'
+ +#255#206#156'e'#255#206#156'e'#255#206#156'e'#255#206#156'e'#255#206#156'e'
+ +#255#206#156'e'#255#206#156'e'#255#206#156'e'#255#206#156'e'#255#205#156'e'
+ +#255#203#151'c'#255#194#139'Z'#255#176'qH'#255#131'K-'#255'\1'#28#255'[/'#27
+ +#255'HA='#204'DDD'#169'DDDqEEE4III'#14#128#128#128#2#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'+++'#6'BBB'#27'EEENW2!'#228'[/'#27#255'i9!'
+ +#255#168'e?'#255#187#130'T'#255#200#147'`'#255#203#153'e'#255#205#154'e'#255
+ +#205#154'e'#255#205#154'e'#255#205#154'e'#255#205#154'e'#255#205#154'e'#255
+ +#205#154'e'#255#205#154'e'#255#205#154'e'#255#205#154'e'#255#205#154'e'#255
+ +#205#154'e'#255#205#154'e'#255#199#150'a'#255#19#14#9#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#7#6#4#255#178#133'W'
+ +#255#205#154'e'#255#205#154'e'#255#205#154'e'#255#205#154'e'#255#205#154'e'
+ +#255#205#154'e'#255#205#154'e'#255#205#154'e'#255'S>)'#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#128'a?'#255#205#154'e'#255#205#154'e'
+ +#255#205#154'e'#255#205#154'e'#255#205#154'e'#255#205#154'e'#255#205#154'e'
+ +#255#205#154'e'#255#205#154'e'#255#205#154'e'#255#205#154'e'#255#205#154'e'
+ +#255#205#154'e'#255#204#154'e'#255#203#152'd'#255#197#145'^'#255#182'zO'#255
+ +#157'Z8'#255']1'#29#255'[/'#27#255'P9.'#226'CCC'#179'CCC'#129'CCCA@@@'#20'@@'
+ +'@'#4#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'999'#9'EEE%EA?'
+ +'b[/'#27#253'\0'#27#255#127'F*'#255#173'nG'#255#191#136'Z'#255#200#149'c'#255
+ +#202#152'e'#255#202#152'e'#255#202#153'e'#255#202#153'e'#255#202#153'e'#255
+ +#202#153'e'#255#202#153'e'#255#202#153'e'#255#202#153'e'#255#202#153'e'#255
+ +#202#153'e'#255#202#153'e'#255#202#153'e'#255#202#153'e'#255#31#24#16#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#11#8#6#255#200#151'e'#255#202#153'e'#255#202#153'e'#255#202
+ +#153'e'#255#202#153'e'#255#202#153'e'#255#202#153'e'#255#202#153'e'#255'O;'''
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255''''#29#19#255#202#153'e'#255
+ +#202#153'e'#255#202#153'e'#255#202#153'e'#255#202#153'e'#255#202#153'e'#255
+ +#202#153'e'#255#202#153'e'#255#202#153'e'#255#202#153'e'#255#202#153'e'#255
+ +#202#153'e'#255#202#153'e'#255#202#153'e'#255#202#152'e'#255#202#151'd'#255
+ +#199#147'b'#255#188#130'U'#255#168'e@'#255'k:"'#255'[/'#27#255'V3$'#241'CCC'
+ +#186'BBB'#142'EEENBBB'#27'+++'#6#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#2'@@@'#12'DDD-O:0'#146'[/'#27#255'\0'#28#255#145'R2'#255#179'wM'
+ +#255#194#141'^'#255#200#148'c'#255#201#150'e'#255#201#150'e'#255#201#150'e'
+ +#255#201#150'e'#255#201#150'e'#255#201#150'e'#255#201#150'e'#255#201#150'e'
+ +#255#201#150'e'#255#201#150'e'#255#201#150'e'#255#201#150'e'#255#201#150'e'
+ +#255';,'#30#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'S>*'#255#201#150'e'
+ +#255#201#150'e'#255#201#150'e'#255#201#150'e'#255#201#150'e'#255#201#150'e'
+ +#255#201#150'e'#255'K8&'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#29#22#14#255
+ +#184#138']'#255#201#150'e'#255#201#150'e'#255#201#150'e'#255#201#150'e'#255
+ ,#201#150'e'#255#201#150'e'#255#201#150'e'#255#201#150'e'#255#201#150'e'#255
+ +#201#150'e'#255#201#150'e'#255#201#150'e'#255#201#150'e'#255#201#150'e'#255
+ +#201#150'e'#255#200#149'd'#255#199#148'c'#255#191#136'['#255#173'mG'#255'}D('
+ +#255'\0'#27#255'Z0'#28#253'DBB'#192'CCC'#152'DDDZBBB#@@@'#8#0#0#0#1#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#128#128#128#2'III'#14'CCC5T5'''#190'[/'#27#255
+ +'_2'#29#255#162'^:'#255#184'}S'#255#195#142'`'#255#198#147'd'#255#199#148'd'
+ +#255#199#148'd'#255#199#148'd'#255#199#148'd'#255#199#148'd'#255#199#148'd'
+ +#255#199#148'd'#255#199#148'd'#255#199#148'd'#255#199#148'd'#255#199#148'd'
+ +#255#199#148'd'#255#147'mJ'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#3#2#1#255#195#144'b'#255#199#148'd'#255#199#148'd'#255#199#148'd'#255
+ +#199#148'd'#255#199#148'd'#255#199#148'd'#255'H6$'#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#3#2#1#255#23#17#12
+ +#255'qT8'#255#199#148'd'#255#199#148'd'#255#199#148'd'#255#199#148'd'#255#199
+ +#148'd'#255#199#148'd'#255#199#148'd'#255#199#148'd'#255#199#148'd'#255#199
+ +#148'd'#255#199#148'd'#255#199#148'd'#255#199#148'd'#255#199#148'd'#255#199
+ +#148'd'#255#199#148'd'#255#199#148'd'#255#199#148'd'#255#198#146'c'#255#193
+ +#140'^'#255#178'uN'#255#143'O1'#255'\0'#28#255'[/'#27#255'J=7'#208'CCC'#161
+ +'DDDfAAA+FFF'#11#0#0#0#2#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'UUU'#3'<<<'
+ +#17'CCC=X1 '#227'[/'#27#255'm:"'#255#167'eA'#255#187#130'X'#255#195#143'a'
+ +#255#196#144'c'#255#197#145'c'#255#197#145'c'#255#197#145'c'#255#197#145'c'
+ +#255#197#145'c'#255#197#145'c'#255#197#145'c'#255#197#145'c'#255#197#145'c'
+ +#255#197#145'c'#255#197#145'c'#255#197#145'c'#255#19#14#10#255#0#0#0#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#135'cD'#255#197#145'c'#255#197
+ +#145'c'#255#197#145'c'#255#197#145'c'#255#197#145'c'#255#197#145'c'#255'I5$'
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#19#14#10#255'4&'#26#255'cI2'#255
+ +#161'vP'#255#197#145'c'#255#197#145'c'#255#197#145'c'#255#197#145'c'#255#197
+ +#145'c'#255#197#145'c'#255#197#145'c'#255#197#145'c'#255#197#145'c'#255#197
+ +#145'c'#255#197#145'c'#255#197#145'c'#255#197#145'c'#255#197#145'c'#255#197
+ +#145'c'#255#197#145'c'#255#197#145'c'#255#197#145'c'#255#197#145'c'#255#197
+ +#145'c'#255#197#145'b'#255#196#144'c'#255#194#140'`'#255#182'|S'#255#159'\:'
+ +#255']2'#28#255'[/'#27#255'Q8-'#226'DDD'#168'DDDqAAA3NNN'#13#128#128#128#2#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'@@@'#4':::'#22'G@/[/'#27
+ +#254'[/'#27#255'}A&'#255#167'gD'#255#180'zW'#255#181'|Y'#255#181'|Y'#255#181
+ +'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'
+ +#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#136']C'#255#0#0#0#255#0#0#0#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#19#13#9#255#151'gJ'#255#181'|Y'#255#181'|Y'#255#181
+ +'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'
+ +#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#171'vU'#255'1"'#24#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1#0#0#255'}V>'#255
+ +#181'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#181
+ +'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'
+ +#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'#255
+ +#181'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#181
+ +'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'
+ +#255#181'|Y'#255#181'|Y'#255#178'wT'#255#161'];'#255'k8 '#255'[/'#27#255'V3#'
+ +#238'DDD'#151'CCCWFFF!@@@'#8#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#2'FFF'#11
+ +'K:3?[/'#27#255'[/'#27#255#131'F*'#255#169'iH'#255#179'xV'#255#180'zW'#255
+ +#180'{W'#255#180'{W'#255#180'{W'#255#180'{W'#255#180'{W'#255#180'{W'#255#180
+ +'{W'#255#180'{W'#255#180'{W'#255#180'{W'#255#180'{W'#255'<)'#29#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#1#1#1#255'O6&'#255#180'{W'#255#180'{W'#255#180'{W'#255#180
+ +'{W'#255#180'{W'#255#180'{W'#255#180'{W'#255#180'{W'#255#180'{W'#255#180'{W'
+ +#255#180'{W'#255#180'{W'#255#180'{W'#255#180'{W'#255#180'{W'#255#180'{W'#255
+ +#180'{W'#255#142'aE'#255#27#19#13#255#2#1#1#255#0#0#0#255#0#0#0#255#0#0#0#255
+ ,#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#8#5#4#255
+ +#135']A'#255#180'{W'#255#180'{W'#255#180'{W'#255#180'{W'#255#180'{W'#255#180
+ +'{W'#255#180'{W'#255#180'{W'#255#180'{W'#255'pL6'#255'+'#29#20#255'('#28#19
+ +#255'*'#28#20#255'+'#29#21#255'-'#30#21#255'fF2'#255#180'{W'#255#180'{W'#255
+ +#180'{W'#255#180'{W'#255#180'{W'#255#180'{W'#255#180'{W'#255#180'{W'#255#180
+ +'{W'#255#180'{W'#255#180'{W'#255#180'{W'#255#180'{W'#255#180'{W'#255#180'{W'
+ +#255#180'{W'#255#180'{W'#255#180'{W'#255#180'zX'#255#178'vU'#255#163'_>'#255
+ +'r<"'#255'[/'#27#255'X2!'#243'CCC'#152'BBBYDDD"@@@'#8#0#0#0#1#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#2'FFF'#11'N8.J[/'#27#255'[/'#27#255#135'H,'#255#170'kI'#255
+ +#178'wV'#255#179'yX'#255#179'yX'#255#179'yX'#255#179'yX'#255#179'yX'#255#179
+ +'yX'#255#179'yX'#255#179'yX'#255#179'yX'#255#179'yX'#255#179'yX'#255#179'yX'
+ +#255#16#11#8#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#19#13#10#255#150'fJ'#255#179'yX'#255#179
+ +'yX'#255#179'yX'#255#179'yX'#255#179'yX'#255#179'yX'#255#179'yX'#255#179'yX'
+ +#255#179'yX'#255#179'yX'#255#179'yX'#255#179'yX'#255#179'yX'#255#179'yX'#255
+ +#179'yX'#255#179'yX'#255#179'yX'#255#179'yX'#255#179'yX'#255#179'yX'#255#179
+ +'yX'#255'~V>'#255'=)'#30#255#19#13#9#255#1#1#1#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255'$'#24#17#255#172'uT'#255#179'yX'#255#179'yX'#255#179'yX'
+ +#255#179'yX'#255#179'yX'#255#179'yX'#255#179'yX'#255#158'kN'#255'=)'#30#255#6
+ +#4#3#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#6#4#3#255'?+'#31#255#164'oP'#255#179'yX'#255#179'yX'#255#179'yX'#255#179
+ +'yX'#255#179'yX'#255#179'yX'#255#179'yX'#255#179'yX'#255#179'yX'#255#179'yX'
+ +#255#179'yX'#255#179'yX'#255#179'yX'#255#179'yX'#255#179'yX'#255#179'yX'#255
+ +#177'uU'#255#164'b@'#255'v?%'#255'[/'#27#255'Y1'#31#246'CCC'#152'BBBYDDD"@@@'
+ +#8#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'FFF'#11'Q7+U[/'#27#255'\0'#28#255
+ +#139'J-'#255#171'lL'#255#177'wW'#255#178'wV'#255#178'wV'#255#178'wV'#255#178
+ +'wV'#255#178'wV'#255#178'wV'#255#178'wV'#255#178'wV'#255#178'wV'#255#178'wV'
+ +#255#178'wV'#255#172'sT'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1#1#1#255'O5&'#255#178'wV'#255#178'wV'
+ +#255#178'wV'#255#178'wV'#255#178'wV'#255#178'wV'#255#178'wV'#255#178'wV'#255
+ +#178'wV'#255#178'wV'#255#178'wV'#255#178'wV'#255#178'wV'#255#178'wV'#255#178
+ +'wV'#255#178'wV'#255#178'wV'#255#178'wV'#255#178'wV'#255#178'wV'#255#178'wV'
+ +#255#178'wV'#255#178'wV'#255#178'wV'#255#178'wV'#255#178'wV'#255#176'wV'#255
+ +'vO9'#255'7%'#27#255#16#10#8#255#1#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0
+ +#0#255#0#0#0#255#11#8#6#255'9&'#28#255#137'\C'#255#178'wV'#255#178'wV'#255
+ +#178'wV'#255#178'wV'#255#178'wV'#255#178'wV'#255#178'wV'#255#178'wV'#255'M3%'
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1#0#0#255'4"'#25#255#178'wV'
+ +#255#178'wV'#255#178'wV'#255#178'wV'#255#178'wV'#255#178'wV'#255#178'wV'#255
+ +#178'wV'#255#178'wV'#255#178'wV'#255#178'wV'#255#178'wV'#255#178'wV'#255#178
+ +'wV'#255#178'wV'#255#176'tT'#255#165'cC'#255'yA'''#255'[/'#27#255'Z0'#29#250
+ +'DDD'#150'CCCWFFF!III'#7#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'MMM'#10'R4'
+ +'''^[/'#27#255'\0'#28#255#142'M.'#255#171'nN'#255#177'uV'#255#177'wX'#255#177
+ +'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'
+ +#255#177'wX'#255#177'wX'#255#177'wX'#255'gF3'#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#23#16#12#255#152'fK'#255#177
+ +'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'
+ +#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255
+ +#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#177
+ +'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'
+ +#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#173'uV'#255
+ +#136'\D'#255#133'YB'#255#131'XA'#255#128'V@'#255#153'gL'#255#177'wX'#255#177
+ +'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'
+ +#255#177'wX'#255#177'wX'#255'S8)'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255'"'#23#17#255#175'wX'#255#177'wX'#255#177
+ +'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'
+ +#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#175'tU'#255
+ +#166'eE'#255'}B)'#255'\0'#28#255'[/'#28#253'CCC'#148'CCCTBBB'#31'III'#7#0#0#0
+ ,#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'999'#9'V4%h[/'#27#255'\0'#28#255#145'O0'
+ +#255#171'mN'#255#175'sU'#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255
+ +#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175
+ +'uW'#255'*'#29#21#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#2
+ +#1#1#255'X;,'#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255
+ +#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175
+ +'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'
+ +#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255
+ +#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175
+ +'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'
+ +#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255
+ +#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255'^?/'#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255'$'#24#18#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255
+ +#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175
+ +'uW'#255#175'uW'#255#175'uW'#255#175'sT'#255#166'eE'#255#128'D*'#255'\0'#28
+ +#255'[/'#27#255'ECB'#149'CCCP@@@'#28'UUU'#6#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#1'@@@'#8'W3#q[/'#27#255'\1'#29#255#150'Q1'#255#171'mN'#255#174'sU'#255
+ +#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175
+ +'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#15#10#8#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#4#3#2#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#29#19#14#255#156'iM'#255#175'uV'#255
+ +#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175
+ +'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'
+ +#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255
+ +#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175
+ +'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'
+ +#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255
+ +#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175
+ +'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#11#7#6#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255'sM9'#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255
+ +#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175
+ +'tV'#255#174'rS'#255#167'fG'#255#131'G,'#255'\0'#28#255'[/'#27#255'GA?'#150
+ +'CCCLGGG'#25'333'#5#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'III'#7'W3#k[/'#27
+ +#255'\1'#29#255#149'P2'#255#169'lM'#255#174'qT'#255#175'tV'#255#175'tV'#255
+ +#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175
+ +'tV'#255#175'tV'#255#175'tV'#255#9#6#4#255#0#0#0#255#0#0#0#255#0#0#0#255#136
+ +'ZC'#255'T8*'#255#1#1#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#7#5#3#255
+ +'bA0'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'
+ +#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255
+ +#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175
+ +'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'
+ +#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255
+ +#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175
+ +'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'
+ +#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255
+ +#165'nR'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#10#7#5#255#175'tV'#255#175
+ +'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'
+ +#255#175'tV'#255#175'tV'#255#175'tV'#255#174'sU'#255#173'qR'#255#166'eG'#255
+ +#131'F,'#255'\0'#28#255'[/'#27#255'EA?'#145'DDDGFFF'#22'@@@'#4#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#1'333'#5'W3#\[/'#27#255'\1'#29#255#146'P3'#255#168
+ +'jM'#255#173'pT'#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'
+ +#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255
+ +#4#3#2#255#0#0#0#255#0#0#0#255#21#14#10#255#173'rU'#255#173'rU'#255#152'dK'
+ +#255'dB1'#255'A+ '#255'D-!'#255#141']E'#255#173'rU'#255#173'rU'#255#173'rU'
+ +#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255
+ +#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173
+ +'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'
+ ,#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255
+ +#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173
+ +'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'
+ +#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255
+ +#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#169'pS'#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#139'\D'#255#173'rU'#255#173'rU'
+ +#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255
+ +#173'rU'#255#173'rU'#255#173'qT'#255#172'oR'#255#165'cF'#255#128'E+'#255'\0'
+ +#28#255'[/'#27#255'CBA'#132'DDD@CCC'#19'UUU'#3#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0'@@@'#4'U2"L[/'#27#255'\1'#29#255#143'N3'#255#168'hK'#255#172'oT'
+ +#255#173'qU'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255
+ +#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#1#1#1#255#0#0#0
+ +#255#0#0#0#255'nI7'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173
+ +'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'
+ +#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255
+ +#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173
+ +'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'
+ +#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255
+ +#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173
+ +'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'
+ +#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255
+ +#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#2#1#1#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255'H0$'#255#173'rV'#255#173'rV'#255#173'rV'
+ +#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255
+ +#173'rV'#255#173'qU'#255#171'nQ'#255#165'dF'#255'~D+'#255'\1'#29#255'Z0'#28
+ +#252'CCCzCCC9@@@'#16#128#128#128#2#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'U'
+ +'UU'#3'T2#=[/'#27#255'\1'#29#255#140'N1'#255#166'gI'#255#171'oR'#255#173'qU'
+ +#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255
+ +#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#1#1#1#255#27#18#13#255'a@0'
+ +#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255
+ +#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173
+ +'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'
+ +#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255
+ +#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173
+ +'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'
+ +#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255
+ +#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173
+ +'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'
+ +#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255'$'#24#18#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#31#20#15#255#173'qU'#255#173'qU'#255#173'qU'#255
+ +#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173
+ +'qU'#255#172'pT'#255#169'lP'#255#164'aD'#255'{C*'#255'\1'#29#255'Y0'#30#247
+ +'CCCoBBB2;;;'#13#0#0#0#2#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#128#128#128
+ +#2'V6''-[/'#27#255'\1'#29#255#137'L0'#255#165'fH'#255#170'mQ'#255#172'pT'#255
+ +#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172
+ +'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#166'lS'#255#172'pU'#255#172'pU'
+ +#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255
+ +#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172
+ +'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'
+ +#255#172'pU'#255#172'pU'#255#172'pU'#255#168'nS'#255#134'WB'#255'b@0'#255'tK'
+ +'9'#255#166'lS'#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'
+ +#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255
+ +#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172
+ +'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'
+ +#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255
+ +#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#129'T@'#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ ,#255#0#0#0#255#0#0#0#255#22#14#11#255#172'pU'#255#172'pU'#255#172'pU'#255#172
+ +'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'
+ +#255#172'oT'#255#170'mP'#255#163'`C'#255'xB*'#255'\1'#29#255'Y1'#31#241'BBBd'
+ +'CCC*MMM'#10#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#2'T7*'#29
+ +'[/'#27#255'\1'#29#255#134'J0'#255#165'dG'#255#169'lQ'#255#171'pU'#255#172'q'
+ +'W'#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'
+ +#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255
+ +#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172
+ +'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'
+ +#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255
+ +#135'YD'#255'$'#24#18#255#3#2#2#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#8#5#4#255#30#20#16#255'xO='#255#172'qW'#255#172'qW'#255#172'qW'#255
+ +#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172
+ +'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'
+ +#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255
+ +#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172
+ +'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#14#9#7#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#20#13#10#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'
+ +#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#171'oT'#255
+ +#169'jM'#255#162'_A'#255's>'''#255'\1'#29#255'X2 '#234'CCCXDDD"@@@'#8#0#0#0#1
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'C><'#9'[/'#27#247'\1'#29#255
+ +'}F-'#255#164'bE'#255#169'lO'#255#171'pT'#255#172'qV'#255#172'qV'#255#172'qV'
+ +#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255
+ +#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255#172
+ +'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'
+ +#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255
+ +#172'qV'#255#172'qV'#255#154'eM'#255#22#15#11#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#25#17#13#255#136'ZE'#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'
+ +#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255
+ +#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255#172
+ +'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'
+ +#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255
+ +#172'qV'#255'U7*'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#17#11#9#255#172'qV'#255#172
+ +'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'
+ +#255#172'qV'#255#172'qV'#255#171'oT'#255#168'jM'#255#161'^@'#255'k;%'#255'\0'
+ +#28#255'V3#'#220'CCCLEEE'#26'333'#5#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0'+++'#6'[/'#28#214'\1'#29#255't@)'#255#162'`B'#255#168'jO'#255
+ +#172'pV'#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#173
+ +'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'
+ +#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255
+ +#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#173
+ +'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#144'_I'#255#6#4#3
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'Z;-'#255
+ +#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#173
+ +'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'
+ +#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255
+ +#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#173
+ +'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#171'pV'#255#3#2#1#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255'!'#22#17#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'
+ +#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#172'qX'#255#171'oU'#255
+ +#167'hM'#255#160'[>'#255'b5!'#255'\0'#28#255'S5'''#196'EEE?CCC'#19'@@@'#4#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'UUU'#3'Z0'#29#176'\1'#29
+ +#255'k:%'#255#162'^A'#255#169'jN'#255#173'qV'#255#174'sY'#255#174'sY'#255#174
+ +'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'
+ +#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255
+ +#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174
+ ,'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'
+ +#255#151'dM'#255#4#2#2#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#1#1#1#255#136'YF'#255#174'sY'#255#174'sY'#255#174's'
+ +'Y'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'
+ +#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255
+ +#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174
+ +'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'
+ +#255#174'sY'#255'5#'#27#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'G.$'#255#174'sY'#255#174'sY'#255
+ +#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174
+ +'sY'#255#174'sY'#255#172'pV'#255#167'gK'#255#153'X:'#255'^3'#31#255'\0'#28
+ +#255'Q7+'#166'BBB2777'#14#0#0#0#2#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#2'Z0'#29#137'\0'#28#255'a5!'#255#160']>'#255#168'jN'#255
+ +#173'sY'#255#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255#175
+ +'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'
+ +#255#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255
+ +#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255#175
+ +'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255#29#20#15#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#8
+ +#5#4#255#169'rX'#255#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'
+ +#255#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255
+ +#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255#175
+ +'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'
+ +#255#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255#156'jR'#255#1#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255'yQ?'#255#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255
+ +#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255#174'u['#255#172'qV'#255#166
+ +'gJ'#255#143'S6'#255'^2'#31#255'[/'#27#255'O;2'#130'CCC&999'#9#0#0#0#1#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'Z0'#29'a\0'#28#255
+ +'^3'#31#255#153'W;'#255#168'jN'#255#174'tZ'#255#176'x_'#255#176'y_'#255#176
+ +'y_'#255#176'y_'#255#176'y_'#255#176'y_'#255#176'y_'#255#176'y_'#255#176'y_'
+ +#255#176'y_'#255#176'y_'#255#176'y_'#255#176'y_'#255#176'y_'#255#176'y_'#255
+ +#176'y_'#255#176'y_'#255#176'y_'#255#176'y_'#255#176'y_'#255#176'y_'#255#176
+ +'y_'#255#176'y_'#255#176'y_'#255#176'y_'#255#176'y_'#255#176'y_'#255'oL='#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255']@2'#255#176'y_'#255#176'y_'#255#176
+ +'y_'#255#176'y_'#255#176'y_'#255#176'y_'#255'Z=1'#255')'#28#22#255#26#18#14
+ +#255#14#10#8#255#10#7#5#255#23#16#12#255'+'#30#23#255'E0&'#255#138'_J'#255
+ +#176'y_'#255#176'y_'#255#176'y_'#255#176'y_'#255#176'y_'#255#176'y_'#255#176
+ +'y_'#255#176'y_'#255#176'y_'#255#176'y_'#255#176'y_'#255#176'y_'#255#176'y_'
+ +#255#176'y_'#255'#'#24#19#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#172'w]'#255#176'y_'#255#176'y_'#255
+ +#176'y_'#255#176'y_'#255#176'y_'#255#176'y_'#255#176'y_'#255#176'y_'#255#176
+ +'y_'#255#175'w^'#255#172'rW'#255#165'fI'#255#134'K2'#255']1'#30#255'[/'#27
+ +#255'H?:ZBBB'#27'+++'#6#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0'X/'#29'7[/'#27#255'^2'#31#255#141'P5'#255#167'hK'#255#174
+ +'sY'#255#177'x_'#255#177'za'#255#177'za'#255#177'za'#255#177'za'#255#177'za'
+ +#255#177'za'#255#177'za'#255#177'za'#255#177'za'#255#177'za'#255#177'za'#255
+ +#177'za'#255#177'za'#255#177'za'#255#177'za'#255#177'za'#255#177'za'#255#177
+ +'za'#255#177'za'#255#177'za'#255#177'za'#255#177'za'#255#177'za'#255#177'za'
+ +#255#177'za'#255#177'za'#255#9#6#5#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255'%'#25#20#255#177'za'#255#177'za'#255#177'za'#255#177'za'#255'bD6'#255#8
+ +#6#4#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255'>+"'#255#175'za'#255#177'za'#255#177'za'#255#177'za'
+ +#255#177'za'#255#177'za'#255#177'za'#255#177'za'#255#177'za'#255#177'za'#255
+ +#177'za'#255#177'za'#255#177'za'#255#136'^K'#255#0#0#0#255#0#0#0#255#0#0#0
+ ,#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#16#11#9#255#177'za'#255#177
+ +'za'#255#177'za'#255#177'za'#255#177'za'#255#177'za'#255#177'za'#255#177'za'
+ +#255#177'za'#255#177'za'#255#176'x^'#255#172'qV'#255#164'cF'#255'{E,'#255']1'
+ +#30#255'Z0'#29#245'DDD'#255
+ +'`5!'#255'\0'#28#255'T5'''#155'DDD'#30'III'#7#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'Z/'#28'w\0'#28#255
+ +'`5!'#255#157'\?'#255#172'pU'#255#179'}d'#255#181#129'i'#255#182#129'j'#255
+ +#182#129'j'#255#182#129'j'#255#182#129'j'#255#182#129'j'#255#182#129'j'#255
+ +#182#129'j'#255#182#129'j'#255#182#129'j'#255#182#129'j'#255#182#129'j'#255
+ +#182#129'j'#255#182#129'j'#255#182#129'j'#255#182#129'j'#255#182#129'j'#255
+ +#182#129'j'#255#182#129'j'#255#182#129'j'#255#182#129'j'#255#182#129'j'#255
+ +#182#129'j'#255#182#129'j'#255#182#129'j'#255'.!'#27#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#2#1#1#255#166'va'#255#182#129'j'#255#182#129'j'#255'A.&'
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#9#6#5#255#170'yd'#255#182#129'j'#255#182#129'j'#255#182#129'j'#255#182
+ +#129'j'#255#182#129'j'#255#182#129'j'#255#182#129'j'#255#182#129'j'#255#182
+ +#129'j'#255#182#129'j'#255#182#129'j'#255#8#6#5#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#135'`O'#255#182#129'j'#255#182#129'j'#255#182#129'j'#255
+ +#182#129'j'#255#182#129'j'#255#182#129'j'#255#182#129'j'#255#182#129'j'#255
+ +#182#129'j'#255#182#129'j'#255#181#128'h'#255#177'za'#255#169'kP'#255#139'Q7'
+ +#255'^3'#31#255'\0'#28#255'N9/\GGG'#18'UUU'#3#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'X.'#26'4\0'#28#255
+ ,'^3'#31#255#141'S8'#255#170'mQ'#255#179'|c'#255#182#130'k'#255#184#132'm'#255
+ +#184#132'm'#255#184#132'm'#255#184#132'm'#255#184#132'm'#255#184#132'm'#255
+ +#184#132'm'#255#184#132'm'#255#184#132'm'#255#184#132'm'#255#184#132'm'#255
+ +#184#132'm'#255#184#132'm'#255#184#132'm'#255#184#132'm'#255#184#132'm'#255
+ +#184#132'm'#255#184#132'm'#255#184#132'm'#255#184#132'm'#255#184#132'm'#255
+ +#184#132'm'#255#184#132'm'#255#184#132'm'#255#20#15#12#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255'N8.'#255#184#132'm'#255#184#132'm'#255#184#132'm'
+ +#255#22#16#13#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#21#15#13#255#182#130'm'#255#184#132'm'#255#184#132
+ +'m'#255#184#132'm'#255#184#132'm'#255#184#132'm'#255#184#132'm'#255#184#132
+ +'m'#255#184#132'm'#255#184#132'm'#255#184#132'm'#255'N8.'#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#23#17#13#255#184#132'm'#255#184#132'm'#255#184#132'm'#255
+ +#184#132'm'#255#184#132'm'#255#184#132'm'#255#184#132'm'#255#184#132'm'#255
+ +#184#132'm'#255#184#132'm'#255#183#131'l'#255#182#129'j'#255#177'x_'#255#167
+ +'hK'#255'zG/'#255']1'#30#255'Z0'#28#241'@@@(MMM'#10#0#0#0#1#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'='#31
+ +#18#3'[/'#27#238']1'#30#255'{G/'#255#167'hL'#255#177'za'#255#183#131'l'#255
+ +#185#134'p'#255#185#134'p'#255#185#134'p'#255#185#134'p'#255#185#134'p'#255
+ +#185#134'p'#255#185#134'p'#255#185#134'p'#255#185#134'p'#255#185#134'p'#255
+ +#185#134'p'#255#185#134'p'#255#185#134'p'#255#185#134'p'#255#185#134'p'#255
+ +#185#134'p'#255#185#134'p'#255#185#134'p'#255#185#134'p'#255#185#134'p'#255
+ +#185#134'p'#255#185#134'p'#255#185#134'p'#255#185#134'p'#255#26#19#16#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#12#9#7#255#185#134'p'#255#185#134'p'#255#185#134'p'
+ +#255#185#134'p'#255#3#2#2#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'U>4'#255#185#134'p'#255#185
+ +#134'p'#255#185#134'p'#255#185#134'p'#255#185#134'p'#255#185#134'p'#255#185
+ +#134'p'#255#185#134'p'#255#185#134'p'#255#185#134'p'#255#185#134'p'#255#25#18
+ +#15#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255'xWI'#255#185#134'p'#255#185#134'p'#255#185#134
+ +'p'#255#185#134'p'#255#185#134'p'#255#185#134'p'#255#185#134'p'#255#185#134
+ +'p'#255#185#134'p'#255#185#134'p'#255#184#134'o'#255#182#129'j'#255#175'v\'
+ +#255#165'dG'#255'h;&'#255'\1'#29#255'X2 '#193'==='#25'+++'#6#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0'[/'#27#170'\1'#29#255'f9%'#255#164'bG'#255#175'v]'#255#183#131
+ +'l'#255#186#135'r'#255#186#137's'#255#186#137's'#255#186#137's'#255#186#137
+ +'s'#255#186#137's'#255#186#137's'#255#186#137's'#255#186#137's'#255#186#137
+ +'s'#255#186#137's'#255#186#137's'#255#186#137's'#255#186#137's'#255#186#137
+ +'s'#255#186#137's'#255#186#137's'#255#186#137's'#255#186#137's'#255#186#137
+ +'s'#255#186#137's'#255#186#137's'#255#186#137's'#255#186#137's'#255'$'#27#23
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#129'_P'#255#186#137's'#255#186#137's'#255
+ +#186#137's'#255#186#137's'#255#1#1#1#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255' '#23#19#255#186
+ +#137's'#255#186#137's'#255#186#137's'#255#186#137's'#255#186#137's'#255#186
+ +#137's'#255#186#137's'#255#186#137's'#255#186#137's'#255#186#137's'#255#186
+ +#137's'#255#172#127'j'#255#7#5#4#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#12#9#7#255#186#137's'#255#186#137's'
+ +#255#186#137's'#255#186#137's'#255#186#137's'#255#186#137's'#255#186#137's'
+ +#255#186#137's'#255#186#137's'#255#186#137's'#255#186#137's'#255#185#135'q'
+ +#255#181#129'i'#255#173'qW'#255#149'X='#255'`5!'#255'\0'#28#255'V4%'#127'333'
+ +#15#0#0#0#3#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'Z/'#27'O\0'#28#255'_4 '#255#144'U:'
+ +#255#172'qV'#255#182#130'k'#255#187#137't'#255#188#139'u'#255#188#140'v'#255
+ +#188#140'v'#255#188#140'v'#255#188#140'v'#255#188#140'v'#255#188#140'v'#255
+ +#188#140'v'#255#188#140'v'#255#188#140'v'#255#188#140'v'#255#188#140'v'#255
+ ,#188#140'v'#255#188#140'v'#255#188#140'v'#255#188#140'v'#255#188#140'v'#255
+ +#188#140'v'#255#188#140'v'#255#188#140'v'#255#188#140'v'#255#188#140'v'#255
+ +#188#140'v'#255'1$'#31#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255':+$'#255#188#140'v'#255#188#140
+ +'v'#255#188#140'v'#255#188#140'v'#255#188#140'v'#255#1#1#1#255#0#0#0#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#4#3#3#255#188#140'v'#255#188#140'v'#255#188#140'v'#255#188#140'v'#255
+ +#188#140'v'#255#188#140'v'#255#188#140'v'#255#188#140'v'#255#188#140'v'#255
+ +#188#140'v'#255#188#140'v'#255#188#140'v'#255#188#140'v'#255'}]N'#255'6("'
+ +#255#14#11#9#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'S>5'#255
+ +#188#140'v'#255#188#140'v'#255#188#140'v'#255#188#140'v'#255#188#140'v'#255
+ +#188#140'v'#255#188#140'v'#255#188#140'v'#255#188#140'v'#255#188#140'v'#255
+ +#188#139'u'#255#186#136'r'#255#180'~f'#255#169'kP'#255'|H1'#255'^2'#31#255'['
+ +'/'#27#249'L=6+III'#7#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#5'[/'#27#235
+ +']1'#30#255'wD/'#255#169'jO'#255#180#127'g'#255#187#137'u'#255#189#141'x'#255
+ +#189#142'y'#255#189#142'y'#255#189#142'y'#255#189#142'y'#255#189#142'y'#255
+ +#189#142'y'#255#189#142'y'#255#189#142'y'#255#189#142'y'#255#189#142'y'#255
+ +#189#142'y'#255#189#142'y'#255#189#142'y'#255#189#142'y'#255#189#142'y'#255
+ +#189#142'y'#255#189#142'y'#255#189#142'y'#255#189#142'y'#255#189#142'y'#255
+ +#189#142'y'#255#189#142'y'#255'J7/'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#16#12#11#255#187#140'y'#255
+ +#189#142'y'#255#189#142'y'#255#189#142'y'#255#189#142'y'#255#189#142'y'#255#1
+ +#1#1#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#181#136'u'#255#189#142'y'#255#189#142
+ +'y'#255#189#142'y'#255#189#142'y'#255#189#142'y'#255#189#142'y'#255#189#142
+ +'y'#255#189#142'y'#255#189#142'y'#255#189#142'y'#255#189#142'y'#255#189#142
+ +'y'#255#189#142'y'#255#189#142'y'#255#189#142'y'#255#11#8#7#255#0#0#0#255#0#0
+ +#0#255#0#0#0#255#1#1#1#255#181#136's'#255#189#142'y'#255#189#142'y'#255#189
+ +#142'y'#255#189#142'y'#255#189#142'y'#255#189#142'y'#255#189#142'y'#255#189
+ +#142'y'#255#189#142'y'#255#189#142'y'#255#189#141'x'#255#186#136'q'#255#177
+ +'za'#255#164'dG'#255'f:&'#255'\1'#29#255'Y1'#31#186'@@@'#16'UUU'#3#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'Z/'#27#147'\1'#29#255'b8$'#255#160'bF'#255
+ +#177'y`'#255#186#137's'#255#190#143'z'#255#191#145'|'#255#191#145'|'#255#191
+ +#145'|'#255#191#145'|'#255#191#145'|'#255#191#145'|'#255#191#145'|'#255#191
+ +#145'|'#255#191#145'|'#255#191#145'|'#255#191#145'|'#255#191#145'|'#255#191
+ +#145'|'#255#191#145'|'#255#191#145'|'#255#191#145'|'#255#191#145'|'#255#191
+ +#145'|'#255#191#145'|'#255#191#145'|'#255#191#145'|'#255#191#145'|'#255#162
+ +'{i'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#1#1#1#255#162'{i'#255#191#145'|'#255#191#145'|'#255#191#145'|'#255
+ +#191#145'|'#255#191#145'|'#255#191#145'|'#255#2#1#1#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1
+ +#1#1#255#191#145'|'#255#191#145'|'#255#191#145'|'#255#191#145'|'#255#191#145
+ +'|'#255#191#145'|'#255#191#145'|'#255#191#145'|'#255#191#145'|'#255#191#145
+ +'|'#255#191#145'|'#255#191#145'|'#255#191#145'|'#255#191#145'|'#255#191#145
+ +'|'#255#191#145'|'#255#5#4#3#255#0#0#0#255#0#0#0#255#0#0#0#255'&'#29#25#255
+ +#191#145'|'#255#191#145'|'#255#191#145'|'#255#191#145'|'#255#191#145'|'#255
+ +#191#145'|'#255#191#145'|'#255#191#145'|'#255#191#145'|'#255#191#145'|'#255
+ +#191#145'|'#255#189#142'y'#255#184#134'o'#255#174'sY'#255#143'U;'#255'`5!'
+ +#255'\0'#28#255'U3$`@@@'#8#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0'Z.'#27'5\0'#28#255'_4 '#255#137'Q8'#255#173'rX'#255#184#134'o'#255#190#144
+ +'{'#255#192#147#127#255#192#147#127#255#192#147#127#255#192#147#127#255#192
+ +#147#127#255#192#147#127#255#192#147#127#255#192#147#127#255#192#147#127#255
+ +#192#147#127#255#192#147#127#255#192#147#127#255#192#147#127#255#192#147#127
+ +#255#192#147#127#255#192#147#127#255#192#147#127#255#192#147#127#255#192#147
+ +#127#255#192#147#127#255#192#147#127#255#192#147#127#255#192#147#127#255#14
+ ,#11#9#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255' '
+ +#24#21#255#192#147#127#255#192#147#127#255#192#147#127#255#192#147#127#255
+ +#192#147#127#255#192#147#127#255#192#147#127#255#4#3#3#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#8#6#5#255#192#147#127#255#192#147#127#255#192#147#127#255#192#147#127
+ +#255#192#147#127#255#192#147#127#255#192#147#127#255#192#147#127#255#192#147
+ +#127#255#192#147#127#255#192#147#127#255#192#147#127#255#192#147#127#255#192
+ +#147#127#255#192#147#127#255#192#147#127#255#1#1#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#137'iZ'#255#192#147#127#255#192#147#127#255#192#147#127#255#192#147
+ +#127#255#192#147#127#255#192#147#127#255#192#147#127#255#192#147#127#255#192
+ +#147#127#255#192#147#127#255#192#146'~'#255#189#142'y'#255#182#129'j'#255#169
+ +'lP'#255'uD.'#255'^2'#31#255'[/'#28#237'NFB'#21'UUU'#3#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#211']1'#30#255'l>)'#255#167'iM'
+ +#255#181#127'g'#255#190#143'z'#255#193#148#128#255#194#149#130#255#194#149
+ +#130#255#194#149#130#255#194#149#130#255#194#149#130#255#194#149#130#255#194
+ +#149#130#255#194#149#130#255#194#149#130#255#194#149#130#255#194#149#130#255
+ +#194#149#130#255#194#149#130#255#194#149#130#255#194#149#130#255#194#149#130
+ +#255#194#149#130#255#194#149#130#255#194#149#130#255#194#149#130#255#194#149
+ +#130#255#194#149#130#255'G60'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255'ZE<'#255#194#149#130#255#194#149#130#255#194#149#130#255
+ +#194#149#130#255#194#149#130#255#194#149#130#255#194#149#130#255#7#6#5#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#23#17#15#255#194#149#130#255#194#149#130#255#194#149#130
+ +#255#194#149#130#255#194#149#130#255#194#149#130#255#194#149#130#255#194#149
+ +#130#255#194#149#130#255#194#149#130#255#194#149#130#255#194#149#130#255#194
+ +#149#130#255#194#149#130#255#194#149#130#255#179#137'x'#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255'-#'#30#255#194#149#130#255#194#149#130#255#194#149#130#255#194
+ +#149#130#255#194#149#130#255#194#149#130#255#194#149#130#255#194#149#130#255
+ +#194#149#130#255#194#149#130#255#194#149#130#255#192#147#127#255#188#140'v'
+ +#255#177'za'#255#156'_D'#255'a6#'#255'\1'#29#255'Y1'#31#153'@@@'#8#0#0#0#1#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'Z/'#27']\0'#28#255
+ +'`5!'#255#143'V='#255#175'v]'#255#187#138'u'#255#193#149#129#255#195#152#132
+ +#255#195#152#133#255#195#152#133#255#195#152#133#255#195#152#133#255#195#152
+ +#133#255#195#152#133#255#195#152#133#255#195#152#133#255#195#152#133#255#195
+ +#152#133#255#195#152#133#255#195#152#133#255#195#152#133#255#195#152#133#255
+ +#195#152#133#255#195#152#133#255#195#152#133#255#195#152#133#255#195#152#133
+ +#255#195#152#133#255#195#152#133#255#170#133't'#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#172#133'u'#255#195#152#133#255#195#152
+ +#133#255#195#152#133#255#195#152#133#255#195#152#133#255#195#152#133#255#146
+ +'rd'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'_JA'#255#195#152#133#255#195#152#133
+ +#255#195#152#133#255#195#152#133#255#195#152#133#255#195#152#133#255#195#152
+ +#133#255#195#152#133#255#195#152#133#255#195#152#133#255#195#152#133#255#195
+ +#152#133#255#195#152#133#255#195#152#133#255#195#152#133#255#140'm`'#255#0#0
+ +#0#255#0#0#0#255#6#5#4#255#186#145#127#255#195#152#133#255#195#152#133#255
+ +#195#152#133#255#195#152#133#255#195#152#133#255#195#152#133#255#195#152#133
+ +#255#195#152#133#255#195#152#133#255#195#152#133#255#195#152#132#255#192#147
+ +#127#255#185#134'p'#255#172'pU'#255'|I2'#255'^3'#31#255'\0'#28#250'R5()UUU'#3
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#3
+ +'[/'#27#221']1'#30#255'oA,'#255#169'lP'#255#183#131'l'#255#192#147#127#255
+ +#196#154#135#255#197#155#136#255#197#155#136#255#197#155#136#255#197#155#136
+ +#255#197#155#136#255#197#155#136#255#197#155#136#255#197#155#136#255#197#155
+ +#136#255#197#155#136#255#197#155#136#255#197#155#136#255#197#155#136#255#197
+ +#155#136#255#197#155#136#255#197#155#136#255#197#155#136#255#197#155#136#255
+ +#197#155#136#255#197#155#136#255#197#155#136#255#197#155#136#255#26#20#18#255
+ ,#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#8#6#5#255#197#155#136#255#197
+ +#155#136#255#197#155#136#255#197#155#136#255#197#155#136#255#197#155#136#255
+ +#197#155#136#255#28#22#19#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#4#3#3#255#193#153#134#255
+ +#197#155#136#255#197#155#136#255#197#155#136#255#197#155#136#255#197#155#136
+ +#255#197#155#136#255#197#155#136#255#197#155#136#255#197#155#136#255#197#155
+ +#136#255#197#155#136#255#197#155#136#255#197#155#136#255#197#155#136#255#197
+ +#155#136#255#182#143'~'#255'=0*'#255#7#5#5#255#130'fY'#255#197#155#136#255
+ +#197#155#136#255#197#155#136#255#197#155#136#255#197#155#136#255#197#155#136
+ +#255#197#155#136#255#197#155#136#255#197#155#136#255#197#155#136#255#196#154
+ +#136#255#195#152#133#255#190#144'{'#255#180'~f'#255#159'bG'#255'c8%'#255'\1'
+ +#29#255'Z0'#30#163'III'#7#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27'g\0'#28#255'a6#'#255#147'Y@'#255#177
+ +'za'#255#190#143'z'#255#196#154#135#255#198#157#139#255#198#157#139#255#198
+ +#157#139#255#198#157#139#255#198#157#139#255#198#157#139#255#198#157#139#255
+ +#198#157#139#255#198#157#139#255#198#157#139#255#198#157#139#255#198#157#139
+ +#255#198#157#139#255#198#157#139#255#198#157#139#255#198#157#139#255#198#157
+ +#139#255#198#157#139#255#198#157#139#255#198#157#139#255#198#157#139#255#198
+ +#157#139#255'<0+'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'*!'#29#255
+ +#198#157#139#255#198#157#139#255#198#157#139#255#198#157#139#255#198#157#139
+ +#255#198#157#139#255#164#130's'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'?2,'#255#198
+ +#157#139#255#198#157#139#255#198#157#139#255#198#157#139#255#198#157#139#255
+ +#198#157#139#255#198#157#139#255#198#157#139#255#198#157#139#255#198#157#139
+ +#255#198#157#139#255#198#157#139#255#198#157#139#255#198#157#139#255#198#157
+ +#139#255#198#157#139#255#198#157#139#255#198#157#139#255#198#157#139#255#198
+ +#157#139#255#198#157#139#255#198#157#139#255#198#157#139#255#198#157#139#255
+ +#198#157#139#255#198#157#139#255#198#157#139#255#198#157#139#255#198#157#139
+ +#255#198#157#139#255#198#156#138#255#195#152#132#255#187#138't'#255#173'sY'
+ +#255#127'L5'#255'^3'#31#255'\0'#28#252'U3$,'#128#128#128#2#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#7
+ +'[/'#27#229'^2'#31#255'qB.'#255#171'nS'#255#185#134'p'#255#194#151#131#255
+ +#198#158#140#255#200#160#142#255#200#160#142#255#200#160#142#255#200#160#142
+ +#255#200#160#142#255#200#160#142#255#200#160#142#255#200#160#142#255#200#160
+ +#142#255#200#160#142#255#200#160#142#255#200#160#142#255#200#160#142#255#200
+ +#160#142#255#200#160#142#255#200#160#142#255#200#160#142#255#200#160#142#255
+ +#200#160#142#255#200#160#142#255#200#160#142#255'9.)'#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255'hSJ'#255#200#160#142#255#200#160#142#255#200#160#142
+ +#255#200#160#142#255#200#160#142#255#200#160#142#255'6+'''#255#0#0#0#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#6#5#5#255#184#148#131#255#200#160#142#255#200#160#142#255#200#160#142
+ +#255#200#160#142#255#200#160#142#255#200#160#142#255#200#160#142#255#200#160
+ +#142#255#200#160#142#255#200#160#142#255#200#160#142#255#200#160#142#255#200
+ +#160#142#255#200#160#142#255#200#160#142#255#200#160#142#255#200#160#142#255
+ +#200#160#142#255#200#160#142#255#200#160#142#255#200#160#142#255#200#160#142
+ +#255#200#160#142#255#200#160#142#255#200#160#142#255#200#160#142#255#200#160
+ +#142#255#200#160#142#255#200#160#142#255#199#159#141#255#198#157#139#255#192
+ +#147#127#255#181#127'g'#255#161'dI'#255'd:&'#255'\1'#29#255'Z0'#29#171'@@@'#4
+ +#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27'q\1'#29#255'a6#'#255#143'W?'#255#177'za'#255
+ +#191#144'|'#255#198#157#139#255#200#161#144#255#201#162#145#255#201#163#145
+ +#255#201#163#145#255#201#163#145#255#201#163#145#255#201#163#145#255#201#163
+ +#145#255#201#163#145#255#201#163#145#255#201#163#145#255#201#163#145#255#201
+ +#163#145#255#201#163#145#255#201#163#145#255#201#163#145#255#201#163#145#255
+ +#201#163#145#255#201#163#145#255#201#163#145#255#201#163#145#255'=2,'#255#0#0
+ ,#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255'!'#27#24#255#197#161#143#255#201#163#145#255
+ +#201#163#145#255#201#163#145#255#201#163#145#255#201#163#145#255#197#161#143
+ +#255#3#2#2#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#1#1#1#255#149'zl'#255#201#163#145#255#201#163#145
+ +#255#201#163#145#255#201#163#145#255#201#163#145#255#201#163#145#255#201#163
+ +#145#255#201#163#145#255#201#163#145#255#201#163#145#255#201#163#145#255#201
+ +#163#145#255#201#163#145#255#201#163#145#255#201#163#145#255#201#163#145#255
+ +#201#163#145#255#201#163#145#255#201#163#145#255#201#163#145#255#201#163#145
+ +#255#201#163#145#255#201#163#145#255#201#163#145#255#201#163#145#255#201#163
+ +#145#255#201#163#145#255#201#163#145#255#201#163#145#255#201#162#145#255#200
+ +#161#143#255#197#155#136#255#187#138'u'#255#173'rX'#255'|I3'#255'_4 '#255'\0'
+ +#28#253'W1 2'#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#6'\0'#28#216'^2'#31#255
+ +'i=)'#255#165'jP'#255#184#133'n'#255#196#152#134#255#201#162#145#255#202#164
+ +#148#255#202#165#148#255#202#165#148#255#202#165#148#255#202#165#148#255#202
+ +#165#148#255#202#165#148#255#202#165#148#255#202#165#148#255#202#165#148#255
+ +#202#165#148#255#202#165#148#255#202#165#148#255#202#165#148#255#202#165#148
+ +#255#202#165#148#255#202#165#148#255#202#165#148#255#202#165#148#255#202#165
+ +#148#255'E82'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#2#2#2#255#1#1#1#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'.&"'#255#202#165#148#255#202#165#148
+ +#255#202#165#148#255#202#165#148#255#202#165#148#255#202#165#148#255#202#165
+ +#148#255#146'wk'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'eRI'#255#202#165#148#255#202#165#148
+ +#255#202#165#148#255#202#165#148#255#202#165#148#255#202#165#148#255#202#165
+ +#148#255#202#165#148#255#202#165#148#255#202#165#148#255#202#165#148#255#202
+ +#165#148#255#202#165#148#255#202#165#148#255#202#165#148#255#202#165#148#255
+ +#202#165#148#255#202#165#148#255#202#165#148#255#202#165#148#255#202#165#148
+ +#255#202#165#148#255#202#165#148#255#202#165#148#255#202#165#148#255#202#165
+ +#148#255#202#165#148#255#202#165#148#255#202#165#148#255#202#165#148#255#202
+ +#164#147#255#200#160#143#255#193#148#128#255#180'~f'#255#151'^D'#255'a7$'#255
+ +'\1'#29#255'Z0'#28#156'UUU'#3#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27
+ +'D\0'#28#255'`5!'#255#128'N8'#255#175'v]'#255#190#143'{'#255#200#159#142#255
+ +#203#165#150#255#204#167#151#255#204#167#151#255#204#167#151#255#204#167#151
+ +#255#204#167#151#255#204#167#151#255#204#167#151#255#204#167#151#255#204#167
+ +#151#255#204#167#151#255#204#167#151#255#204#167#151#255#204#167#151#255#204
+ +#167#151#255#204#167#151#255#204#167#151#255#204#167#151#255#204#167#151#255
+ +#204#167#151#255'N?9'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'vaW'#255
+ +#204#167#151#255#160#131'w'#255'cRI'#255'WG@'#255#168#137'|'#255#204#167#151
+ +#255#204#167#151#255#204#167#151#255#204#167#151#255#204#167#151#255#204#167
+ +#151#255#204#167#151#255#204#167#151#255#145'wk'#255#0#0#0#255#0#0#0#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'G:4'#255#204#167
+ +#151#255#204#167#151#255#204#167#151#255#204#167#151#255#204#167#151#255#204
+ +#167#151#255#204#167#151#255#204#167#151#255#204#167#151#255#204#167#151#255
+ +#204#167#151#255#204#167#151#255#204#167#151#255#204#167#151#255#204#167#151
+ +#255#204#167#151#255#204#167#151#255#204#167#151#255#204#167#151#255#204#167
+ +#151#255#204#167#151#255#204#167#151#255#204#167#151#255#204#167#151#255#204
+ +#167#151#255#204#167#151#255#204#167#151#255#204#167#151#255#204#167#151#255
+ +#204#167#151#255#204#167#150#255#202#165#148#255#198#155#138#255#186#137's'
+ +#255#171'nU'#255'oB.'#255'^2'#31#255'\0'#28#235'V2"'#21#0#0#0#1#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#169'\1'#29#255'c9&'#255#155'aH'#255
+ +#182#128'j'#255#195#152#133#255#202#164#148#255#205#169#154#255#206#169#155
+ +#255#206#169#155#255#206#169#155#255#206#169#155#255#206#169#155#255#206#169
+ +#155#255#206#169#155#255#206#169#155#255#206#169#155#255#206#169#155#255#206
+ +#169#155#255#206#169#155#255#206#169#155#255#206#169#155#255#206#169#155#255
+ +#206#169#155#255#206#169#155#255#206#169#155#255'VGA'#255#0#0#0#255#0#0#0#255
+ ,#0#0#0#255#5#4#4#255#206#169#155#255#206#169#155#255#206#169#155#255#206#169
+ +#155#255#206#169#155#255#206#169#155#255#206#169#155#255#206#169#155#255#206
+ +#169#155#255#206#169#155#255#206#169#155#255#206#169#155#255#206#169#155#255
+ +#206#169#155#255#152'}r'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#2#1#1#255'vaY'#255#206#169#155#255#206#169#155#255#206#169
+ +#155#255#206#169#155#255#206#169#155#255#206#169#155#255#206#169#155#255#206
+ +#169#155#255#206#169#155#255#206#169#155#255#206#169#155#255#206#169#155#255
+ +#206#169#155#255#206#169#155#255#206#169#155#255#206#169#155#255#206#169#155
+ +#255#206#169#155#255#206#169#155#255#206#169#155#255#206#169#155#255#206#169
+ +#155#255#206#169#155#255#206#169#155#255#206#169#155#255#206#169#155#255#206
+ +#169#155#255#206#169#155#255#206#169#155#255#206#169#155#255#206#169#155#255
+ +#205#167#152#255#201#162#145#255#192#147#127#255#177'za'#255#138'T='#255'`6"'
+ +#255'\1'#29#255'[0'#29'e'#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0'[/'#27#27'\0'#28#243'^3'#31#255'pC/'#255#171'oU'#255#188#138'u'
+ +#255#199#158#141#255#205#169#154#255#207#171#157#255#207#172#158#255#207#172
+ +#158#255#207#172#158#255#207#172#158#255#207#172#158#255#207#172#158#255#207
+ +#172#158#255#207#172#158#255#207#172#158#255#207#172#158#255#207#172#158#255
+ +#207#172#158#255#207#172#158#255#207#172#158#255#207#172#158#255#207#172#158
+ +#255#207#172#158#255'~i`'#255#0#0#0#255#0#0#0#255#0#0#0#255#22#18#16#255#207
+ +#172#158#255#207#172#158#255#207#172#158#255#207#172#158#255#207#172#158#255
+ +#207#172#158#255#207#172#158#255#207#172#158#255#207#172#158#255#207#172#158
+ +#255#207#172#158#255#207#172#158#255#207#172#158#255#207#172#158#255#207#172
+ +#158#255'/''$'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#9#7#7#255
+ +#164#136'~'#255#207#172#158#255#207#172#158#255#207#172#158#255#207#172#158
+ +#255#207#172#158#255#207#172#158#255#207#172#158#255#207#172#158#255#207#172
+ +#158#255#207#172#158#255#207#172#158#255#207#172#158#255#207#172#158#255#207
+ +#172#158#255#207#172#158#255#207#172#158#255#207#172#158#255#207#172#158#255
+ +#207#172#158#255#207#172#158#255#207#172#158#255#207#172#158#255#207#172#158
+ +#255#207#172#158#255#207#172#158#255#207#172#158#255#207#172#158#255#207#172
+ +#158#255#207#172#158#255#207#172#158#255#207#172#158#255#207#171#157#255#204
+ +#167#151#255#196#153#136#255#183#131'l'#255#160'fK'#255'f;('#255']1'#30#255
+ +'[/'#27#199'te^'#3#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0'[/'#27'q\0'#28#255'`6"'#255#130'P9'#255#177'x`'#255#192#146
+ +#127#255#203#164#149#255#208#173#159#255#209#175#161#255#209#175#161#255#209
+ +#175#161#255#209#175#161#255#209#175#161#255#209#175#161#255#209#175#161#255
+ +#209#175#161#255#209#175#161#255#209#175#161#255#209#175#161#255#209#175#161
+ +#255#209#175#161#255#209#175#161#255#209#175#161#255#209#175#161#255#209#175
+ +#161#255#199#167#153#255#0#0#0#255#0#0#0#255#0#0#0#255'.'#255#209#175#161
+ +#255#209#175#161#255#209#175#161#255#209#175#161#255#209#175#161#255#209#175
+ +#161#255#209#175#161#255#209#175#161#255#209#175#161#255#209#175#161#255#209
+ +#175#161#255#209#175#161#255#209#175#161#255#209#175#161#255#209#175#161#255
+ +#209#175#161#255'*$!'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'"'#28#26#255#197#165#153#255
+ +#209#175#161#255#209#175#161#255#209#175#161#255#209#175#161#255#209#175#161
+ +#255#209#175#161#255#209#175#161#255#209#175#161#255#209#175#161#255#209#175
+ +#161#255#209#175#161#255#209#175#161#255#209#175#161#255#209#175#161#255#209
+ +#175#161#255#209#175#161#255#209#175#161#255#209#175#161#255#209#175#161#255
+ +#209#175#161#255#209#175#161#255#209#175#161#255#209#175#161#255#209#175#161
+ +#255#209#175#161#255#209#175#161#255#209#175#161#255#209#175#161#255#209#175
+ +#161#255#209#175#161#255#209#175#161#255#209#174#160#255#207#171#157#255#200
+ +#160#144#255#188#139'w'#255#171'pV'#255'rD0'#255'^3'#31#255'\0'#28#250'\2'#30
+ +'1'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0'[/'#27#1'[/'#27#184']1'#30#255'c9&'#255#148'^E'#255#182#128'j'#255#197
+ +#154#136#255#206#170#155#255#210#176#163#255#211#178#164#255#211#178#165#255
+ +#211#178#165#255#211#178#165#255#211#178#165#255#211#178#165#255#211#178#165
+ +#255#211#178#165#255#211#178#165#255#211#178#165#255#211#178#165#255#211#178
+ ,#165#255#211#178#165#255#211#178#165#255#211#178#165#255#211#178#165#255#211
+ +#178#165#255#12#10#9#255#0#0#0#255#0#0#0#255'MA<'#255#211#178#165#255#211#178
+ +#165#255#211#178#165#255#211#178#165#255#211#178#165#255#211#178#165#255#211
+ +#178#165#255#211#178#165#255#211#178#165#255#211#178#165#255#211#178#165#255
+ +#211#178#165#255#211#178#165#255#211#178#165#255#211#178#165#255#211#178#165
+ +#255#211#178#165#255#178#150#139#255'D95'#255#9#7#7#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'VIC'#255#211#178#165#255#211#178#165
+ +#255#211#178#165#255#211#178#165#255#211#178#165#255#211#178#165#255#211#178
+ +#165#255#211#178#165#255#211#178#165#255#211#178#165#255#211#178#165#255#211
+ +#178#165#255#211#178#165#255#211#178#165#255#211#178#165#255#211#178#165#255
+ +#211#178#165#255#211#178#165#255#211#178#165#255#211#178#165#255#211#178#165
+ +#255#211#178#165#255#211#178#165#255#211#178#165#255#211#178#165#255#211#178
+ +#165#255#211#178#165#255#211#178#165#255#211#178#165#255#211#178#165#255#211
+ +#178#165#255#211#178#165#255#211#178#164#255#209#176#162#255#204#167#151#255
+ +#193#148#129#255#177'x`'#255#129'P9'#255'`6"'#255'\0'#28#255'[0'#28't'#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0'[/'#27#21'\0'#28#229'^2'#31#255'i?+'#255#163'jP'#255#186#136
+ +'s'#255#200#160#144#255#209#174#160#255#212#180#167#255#213#181#169#255#213
+ +#181#169#255#213#181#169#255#213#181#169#255#213#181#169#255#213#181#169#255
+ +#213#181#169#255#213#181#169#255#213#181#169#255#213#181#169#255#213#181#169
+ +#255#213#181#169#255#213#181#169#255#213#181#169#255#213#181#169#255#213#181
+ +#169#255'.''%'#255#0#0#0#255',%#'#255#200#170#159#255#213#181#169#255#213#181
+ +#169#255#213#181#169#255#213#181#169#255#213#181#169#255#213#181#169#255#213
+ +#181#169#255#213#181#169#255#213#181#169#255#213#181#169#255#213#181#169#255
+ +#213#181#169#255#213#181#169#255#213#181#169#255#213#181#169#255#213#181#169
+ +#255#213#181#169#255#213#181#169#255#213#181#169#255#139'vo'#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'.''$'#255#213#181#169#255#213#181#169
+ +#255#213#181#169#255#213#181#169#255#213#181#169#255#213#181#169#255#213#181
+ +#169#255#213#181#169#255#213#181#169#255#213#181#169#255#213#181#169#255#213
+ +#181#169#255#213#181#169#255#213#181#169#255#213#181#169#255#213#181#169#255
+ +#213#181#169#255#213#181#169#255#213#181#169#255#213#181#169#255#213#181#169
+ +#255#213#181#169#255#213#181#169#255#213#181#169#255#213#181#169#255#213#181
+ +#169#255#213#181#169#255#213#181#169#255#213#181#169#255#213#181#169#255#213
+ +#181#169#255#213#181#169#255#212#180#168#255#211#178#165#255#207#171#157#255
+ +#197#155#137#255#182#128'j'#255#148']E'#255'c9&'#255']1'#30#255'[/'#27#179#0
+ +#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27'?\0'#28#252'_4 '#255'tF1'#255#172
+ +'sY'#255#190#142'z'#255#203#165#150#255#211#178#164#255#213#183#170#255#214
+ +#184#172#255#214#184#172#255#214#184#172#255#214#184#172#255#214#184#172#255
+ +#214#184#172#255#214#184#172#255#214#184#172#255#214#184#172#255#214#184#172
+ +#255#214#184#172#255#214#184#172#255#214#184#172#255#214#184#172#255#214#184
+ +#172#255#127'ng'#255'{ib'#255#214#184#172#255#214#184#172#255#214#184#172#255
+ +#214#184#172#255#214#184#172#255#214#184#172#255#214#184#172#255#214#184#172
+ +#255#214#184#172#255#214#184#172#255#214#184#172#255#214#184#172#255#214#184
+ +#172#255#214#184#172#255#214#184#172#255#214#184#172#255#214#184#172#255#214
+ +#184#172#255#214#184#172#255#214#184#172#255#214#184#172#255' '#28#26#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#14#12#11#255#209#180#168#255#214#184#172
+ +#255#214#184#172#255#214#184#172#255#214#184#172#255#214#184#172#255#214#184
+ +#172#255#214#184#172#255#214#184#172#255#214#184#172#255#214#184#172#255#214
+ +#184#172#255#214#184#172#255#214#184#172#255#214#184#172#255#214#184#172#255
+ +#214#184#172#255#214#184#172#255#214#184#172#255#214#184#172#255#214#184#172
+ +#255#214#184#172#255#214#184#172#255#214#184#172#255#214#184#172#255#214#184
+ +#172#255#214#184#172#255#214#184#172#255#214#184#172#255#214#184#172#255#214
+ +#184#172#255#214#184#172#255#214#184#172#255#213#182#169#255#209#176#161#255
+ +#200#161#143#255#186#135'q'#255#161'gO'#255'h=*'#255'^2'#31#255'\0'#28#226'W'
+ +'-'#26#19#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27'}\1'#29#255'`6"'
+ +#255'|M8'#255#175'x^'#255#192#147#127#255#205#170#154#255#213#181#169#255#215
+ ,#185#173#255#216#187#175#255#216#187#175#255#216#187#175#255#216#187#175#255
+ +#216#187#175#255#216#187#175#255#216#187#175#255#216#187#175#255#216#187#175
+ +#255#216#187#175#255#216#187#175#255#216#187#175#255#216#187#175#255#216#187
+ +#175#255#216#187#175#255#216#187#175#255#216#187#175#255#216#187#175#255#216
+ +#187#175#255#216#187#175#255#216#187#175#255#216#187#175#255#216#187#175#255
+ +#216#187#175#255#216#187#175#255#216#187#175#255#216#187#175#255#216#187#175
+ +#255#216#187#175#255#216#187#175#255#216#187#175#255#216#187#175#255#216#187
+ +#175#255#216#187#175#255#216#187#175#255#216#187#175#255#187#162#151#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#2#2#2#255#180#156#146#255#216#187#175
+ +#255#216#187#175#255#216#187#175#255#216#187#175#255#216#187#175#255#216#187
+ +#175#255#216#187#175#255#216#187#175#255#216#187#175#255#216#187#175#255#216
+ +#187#175#255#216#187#175#255#216#187#175#255#216#187#175#255#216#187#175#255
+ +#216#187#175#255#216#187#175#255#216#187#175#255#216#187#175#255#216#187#175
+ +#255#216#187#175#255#216#187#175#255#216#187#175#255#216#187#175#255#216#187
+ +#175#255#216#187#175#255#216#187#175#255#216#187#175#255#216#187#175#255#216
+ +#187#175#255#216#187#175#255#216#187#175#255#215#185#173#255#211#179#166#255
+ +#202#165#148#255#188#139'w'#255#167'mU'#255'nC/'#255'^3'#31#255'\0'#28#251'Z'
+ +'.'#27';'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#2'[/'#27
+ +#170'\1'#29#255'a7$'#255#130'Q<'#255#178'{c'#255#195#151#132#255#208#173#159
+ +#255#215#185#173#255#217#189#178#255#217#189#178#255#217#189#178#255#217#189
+ +#178#255#217#189#178#255#217#189#178#255#217#189#178#255#217#189#178#255#217
+ +#189#178#255#217#189#178#255#217#189#178#255#217#189#178#255#217#189#178#255
+ +#217#189#178#255#217#189#178#255#217#189#178#255#217#189#178#255#217#189#178
+ +#255#217#189#178#255#217#189#178#255#217#189#178#255#217#189#178#255#217#189
+ +#178#255#217#189#178#255#217#189#178#255#217#189#178#255#217#189#178#255#217
+ +#189#178#255#217#189#178#255#217#189#178#255#217#189#178#255#217#189#178#255
+ +#217#189#178#255#217#189#178#255#217#189#178#255#217#189#178#255'.(&'#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#128'oi'#255#217#189#178#255#217#189#178
+ +#255#217#189#178#255#217#189#178#255#217#189#178#255#217#189#178#255#217#189
+ +#178#255#217#189#178#255#217#189#178#255#217#189#178#255#217#189#178#255#217
+ +#189#178#255#217#189#178#255#217#189#178#255#217#189#178#255#217#189#178#255
+ +#217#189#178#255#217#189#178#255#217#189#178#255#217#189#178#255#217#189#178
+ +#255#217#189#178#255#217#189#178#255#217#189#178#255#217#189#178#255#217#189
+ +#178#255#217#189#178#255#217#189#178#255#217#189#178#255#217#189#178#255#217
+ +#189#178#255#217#189#178#255#217#188#177#255#213#183#170#255#205#168#153#255
+ +#191#144'|'#255#170'rZ'#255'sF2'#255'`5!'#255'\0'#28#255'Z/'#27'g'#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#6'[/'#27
+ +#188']1'#30#255'c9&'#255#136'V?'#255#180'~g'#255#197#154#136#255#209#176#162
+ +#255#216#187#176#255#219#192#181#255#219#192#182#255#219#193#183#255#219#193
+ +#183#255#219#193#183#255#219#193#183#255#219#193#183#255#219#193#183#255#219
+ +#193#183#255#219#193#183#255#219#193#183#255#219#193#183#255#219#193#183#255
+ +#219#193#183#255#219#193#183#255#219#193#183#255#219#193#183#255#219#193#183
+ +#255#219#193#183#255#219#193#183#255#219#193#183#255#219#193#183#255#219#193
+ +#183#255#219#193#183#255#219#193#183#255#219#193#183#255#219#193#183#255#219
+ +#193#183#255#219#193#183#255#219#193#183#255#219#193#183#255#219#193#183#255
+ +#219#193#183#255#219#193#183#255#158#138#131#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#1#1#1#255#131'sm'#255#219#193#183#255#219#193#183#255#219#193#183#255
+ +#219#193#183#255#219#193#183#255#219#193#183#255#219#193#183#255#219#193#183
+ +#255#219#193#183#255#219#193#183#255#219#193#183#255#219#193#183#255#219#193
+ +#183#255#219#193#183#255#219#193#183#255#219#193#183#255#219#193#183#255#219
+ +#193#183#255#219#193#183#255#219#193#183#255#219#193#183#255#219#193#183#255
+ +#219#193#183#255#219#193#183#255#219#193#183#255#219#193#183#255#219#193#183
+ +#255#219#193#183#255#219#193#183#255#219#193#183#255#219#193#183#255#219#192
+ +#182#255#218#191#180#255#215#185#173#255#207#172#156#255#193#147#128#255#174
+ +'v^'#255'wJ6'#255'`6"'#255'\1'#29#255'[/'#27'~'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ ,#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#12'[/'#27#203
+ +']1'#30#255'c:'''#255#141'YC'#255#181#128'h'#255#198#155#138#255#210#177#164
+ +#255#217#190#178#255#220#194#184#255#221#195#185#255#221#196#186#255#221#196
+ +#186#255#221#196#186#255#221#196#186#255#221#196#186#255#221#196#186#255#221
+ +#196#186#255#221#196#186#255#221#196#186#255#221#196#186#255#221#196#186#255
+ +#221#196#186#255#221#196#186#255#221#196#186#255#221#196#186#255#221#196#186
+ +#255#221#196#186#255#221#196#186#255#221#196#186#255#221#196#186#255#221#196
+ +#186#255#221#196#186#255#221#196#186#255#221#196#186#255#221#196#186#255#221
+ +#196#186#255#221#196#186#255#221#196#186#255#221#196#186#255#221#196#186#255
+ +#221#196#186#255're_'#255#0#0#0#255#0#0#0#255#4#4#4#255#160#142#134#255#221
+ +#196#186#255#221#196#186#255#221#196#186#255#221#196#186#255#221#196#186#255
+ +#221#196#186#255#221#196#186#255#221#196#186#255#221#196#186#255#221#196#186
+ +#255#221#196#186#255#221#196#186#255#221#196#186#255#221#196#186#255#221#196
+ +#186#255#221#196#186#255#221#196#186#255#221#196#186#255#221#196#186#255#221
+ +#196#186#255#221#196#186#255#221#196#186#255#221#196#186#255#221#196#186#255
+ +#221#196#186#255#221#196#186#255#221#196#186#255#221#196#186#255#221#196#186
+ +#255#221#196#186#255#221#196#186#255#221#195#185#255#219#193#183#255#216#187
+ +#175#255#207#172#158#255#194#148#130#255#176'x_'#255'{M8'#255'a6#'#255'\1'#29
+ +#255'[/'#27#148#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#21'\0'#28#217']1'#30#255'c:'''
+ +#255#138'XB'#255#181#127'h'#255#197#156#137#255#211#178#164#255#218#191#180
+ +#255#221#196#187#255#222#198#188#255#223#198#189#255#223#198#189#255#223#198
+ +#189#255#223#198#189#255#223#198#189#255#223#198#189#255#223#198#189#255#223
+ +#198#189#255#223#198#189#255#223#198#189#255#223#198#189#255#223#198#189#255
+ +#223#198#189#255#223#198#189#255#223#198#189#255#223#198#189#255#223#198#189
+ +#255#223#198#189#255#223#198#189#255#223#198#189#255#223#198#189#255#223#198
+ +#189#255#223#198#189#255#223#198#189#255#223#198#189#255#223#198#189#255#223
+ +#198#189#255#223#198#189#255#223#198#189#255#223#198#189#255#221#196#187#255
+ +#6#6#5#255#10#9#8#255#188#167#159#255#223#198#189#255#223#198#189#255#223#198
+ +#189#255#223#198#189#255#223#198#189#255#223#198#189#255#223#198#189#255#223
+ +#198#189#255#223#198#189#255#223#198#189#255#223#198#189#255#223#198#189#255
+ +#223#198#189#255#223#198#189#255#223#198#189#255#223#198#189#255#223#198#189
+ +#255#223#198#189#255#223#198#189#255#223#198#189#255#223#198#189#255#223#198
+ +#189#255#223#198#189#255#223#198#189#255#223#198#189#255#223#198#189#255#223
+ +#198#189#255#223#198#189#255#223#198#189#255#223#198#189#255#223#198#189#255
+ +#222#198#188#255#221#196#186#255#217#188#177#255#208#173#159#255#193#149#129
+ +#255#174'w^'#255'zM8'#255'a7$'#255'\1'#29#255'[/'#27#170'[/'#27#2#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0'[/'#27' \0'#28#223']1'#30#255'c:'''#255#132'T?'#255#180
+ +'~g'#255#197#155#136#255#211#178#164#255#219#193#181#255#223#198#189#255#224
+ +#201#192#255#224#201#192#255#224#201#192#255#224#201#192#255#224#201#192#255
+ +#224#201#192#255#224#201#192#255#224#201#192#255#224#201#192#255#224#201#192
+ +#255#224#201#192#255#224#201#192#255#224#201#192#255#224#201#192#255#224#201
+ +#192#255#224#201#192#255#224#201#192#255#224#201#192#255#224#201#192#255#224
+ +#201#192#255#224#201#192#255#224#201#192#255#224#201#192#255#224#201#192#255
+ +#224#201#192#255#224#201#192#255#224#201#192#255#224#201#192#255#224#201#192
+ +#255#224#201#192#255#224#201#192#255#134'xr'#255#205#184#176#255#224#201#192
+ +#255#224#201#192#255#224#201#192#255#224#201#192#255#224#201#192#255#224#201
+ +#192#255#224#201#192#255#224#201#192#255#224#201#192#255#224#201#192#255#224
+ +#201#192#255#224#201#192#255#224#201#192#255#224#201#192#255#224#201#192#255
+ +#224#201#192#255#224#201#192#255#224#201#192#255#224#201#192#255#224#201#192
+ +#255#224#201#192#255#224#201#192#255#224#201#192#255#224#201#192#255#224#201
+ +#192#255#224#201#192#255#224#201#192#255#224#201#192#255#224#201#192#255#224
+ +#201#192#255#224#201#192#255#223#200#191#255#222#197#187#255#217#189#178#255
+ +#207#172#158#255#192#147#127#255#171'u\'#255'vI6'#255'a6#'#255'\1'#29#255'[/'
+ +#27#179'[/'#27#6#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ ,#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#25'\'
+ +'0'#28#209']1'#30#255'c9&'#255#128'Q='#255#177'{c'#255#195#151#133#255#209
+ +#176#162#255#219#192#181#255#223#200#191#255#225#203#194#255#226#204#196#255
+ +#226#204#196#255#226#204#196#255#226#204#196#255#226#204#196#255#226#204#196
+ +#255#226#204#196#255#226#204#196#255#226#204#196#255#226#204#196#255#226#204
+ +#196#255#226#204#196#255#226#204#196#255#226#204#196#255#226#204#196#255#226
+ +#204#196#255#226#204#196#255#226#204#196#255#226#204#196#255#226#204#196#255
+ +#226#204#196#255#226#204#196#255#226#204#196#255#226#204#196#255#226#204#196
+ +#255#226#204#196#255#226#204#196#255#226#204#196#255#226#204#196#255#226#204
+ +#196#255#226#204#196#255#226#204#196#255#226#204#196#255#226#204#196#255#226
+ +#204#196#255#226#204#196#255#226#204#196#255#226#204#196#255#226#204#196#255
+ +#226#204#196#255#226#204#196#255#226#204#196#255#226#204#196#255#226#204#196
+ +#255#226#204#196#255#226#204#196#255#226#204#196#255#226#204#196#255#226#204
+ +#196#255#226#204#196#255#226#204#196#255#226#204#196#255#226#204#196#255#226
+ +#204#196#255#226#204#196#255#226#204#196#255#226#204#196#255#226#204#196#255
+ +#226#204#196#255#226#204#196#255#226#203#195#255#225#202#193#255#222#198#188
+ +#255#217#188#177#255#206#169#155#255#191#144'|'#255#168'qY'#255'rG3'#255'`6"'
+ +#255'\1'#29#255'[/'#27#159'[/'#27#4#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0'[/'#27#15'\0'#28#193']1'#30#255'b8%'#255'yM8'#255#170
+ +'u\'#255#192#146'~'#255#207#171#156#255#217#189#178#255#223#200#191#255#226
+ +#205#197#255#227#206#198#255#228#207#199#255#228#207#199#255#228#207#199#255
+ +#228#207#199#255#228#207#199#255#228#207#199#255#228#207#199#255#228#207#199
+ +#255#228#207#199#255#228#207#199#255#228#207#199#255#228#207#199#255#228#207
+ +#199#255#228#207#199#255#228#207#199#255#228#207#199#255#228#207#199#255#228
+ +#207#199#255#228#207#199#255#228#207#199#255#228#207#199#255#228#207#199#255
+ +#228#207#199#255#228#207#199#255#228#207#199#255#228#207#199#255#228#207#199
+ +#255#228#207#199#255#228#207#199#255#228#207#199#255#228#207#199#255#228#207
+ +#199#255#228#207#199#255#228#207#199#255#228#207#199#255#228#207#199#255#228
+ +#207#199#255#228#207#199#255#228#207#199#255#228#207#199#255#228#207#199#255
+ +#228#207#199#255#228#207#199#255#228#207#199#255#228#207#199#255#228#207#199
+ +#255#228#207#199#255#228#207#199#255#228#207#199#255#228#207#199#255#228#207
+ +#199#255#228#207#199#255#228#207#199#255#228#207#199#255#228#207#199#255#228
+ +#207#199#255#228#207#199#255#227#206#198#255#226#204#196#255#222#198#188#255
+ +#215#185#173#255#202#165#148#255#187#137'u'#255#159'jR'#255'nD0'#255'`6"'#255
+ +'\1'#29#255'[/'#27#137#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#8'[/'#27#175'\1'#29#255'`6"'#255'n'
+ +'D0'#255#158'iR'#255#187#137'u'#255#202#165#148#255#215#186#174#255#223#199
+ +#190#255#227#205#198#255#229#208#201#255#229#209#202#255#229#210#202#255#229
+ +#210#202#255#229#210#202#255#229#210#202#255#229#210#202#255#229#210#202#255
+ +#229#210#202#255#229#210#202#255#229#210#202#255#229#210#202#255#229#210#202
+ +#255#229#210#202#255#229#210#202#255#229#210#202#255#229#210#202#255#229#210
+ +#202#255#229#210#202#255#229#210#202#255#229#210#202#255#229#210#202#255#229
+ +#210#202#255#229#210#202#255#229#210#202#255#229#210#202#255#229#210#202#255
+ +#229#210#202#255#229#210#202#255#229#210#202#255#229#210#202#255#229#210#202
+ +#255#229#210#202#255#229#210#202#255#229#210#202#255#229#210#202#255#229#210
+ +#202#255#229#210#202#255#229#210#202#255#229#210#202#255#229#210#202#255#229
+ +#210#202#255#229#210#202#255#229#210#202#255#229#210#202#255#229#210#202#255
+ +#229#210#202#255#229#210#202#255#229#210#202#255#229#210#202#255#229#210#202
+ +#255#229#210#202#255#229#210#202#255#229#210#202#255#229#210#202#255#229#209
+ +#202#255#228#207#201#255#226#204#197#255#221#196#187#255#212#180#168#255#198
+ +#157#140#255#183#130'l'#255#143'^G'#255'g>+'#255'_4 '#255'\1'#29#254'[/'#27
+ +'q'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ ,#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#3'[/'#27#132'\1'#29#254'_4 '#255'g>+'
+ +#255#140'[F'#255#181#129'j'#255#198#155#138#255#211#178#165#255#221#195#185
+ +#255#227#204#197#255#230#209#203#255#230#212#205#255#231#212#206#255#231#212
+ +#206#255#231#212#206#255#231#212#206#255#231#212#206#255#231#212#206#255#231
+ +#212#206#255#231#212#206#255#231#212#206#255#231#212#206#255#231#212#206#255
+ +#231#212#206#255#231#212#206#255#231#212#206#255#231#212#206#255#231#212#206
+ +#255#231#212#206#255#231#212#206#255#231#212#206#255#231#212#206#255#231#212
+ +#206#255#231#212#206#255#231#212#206#255#231#212#206#255#231#212#206#255#231
+ +#212#206#255#231#212#206#255#231#212#206#255#231#212#206#255#231#212#206#255
+ +#231#212#206#255#231#212#206#255#231#212#206#255#231#212#206#255#231#212#206
+ +#255#231#212#206#255#231#212#206#255#231#212#206#255#231#212#206#255#231#212
+ +#206#255#231#212#206#255#231#212#206#255#231#212#206#255#231#212#206#255#231
+ +#212#206#255#231#212#206#255#231#212#206#255#231#212#206#255#231#212#206#255
+ +#231#212#206#255#231#211#206#255#230#211#205#255#229#209#201#255#225#203#194
+ +#255#219#191#181#255#208#173#159#255#193#149#129#255#173'w`'#255'~Q='#255'c:'
+ +''''#255'^2'#31#255'\0'#28#238'[/'#27'O'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0'[/'#27'F\0'#28#234'^2'#31#255'c:'''#255'zN:'#255#168's['#255
+ +#190#143'{'#255#205#167#152#255#217#187#177#255#225#201#193#255#229#209#202
+ +#255#232#213#207#255#232#214#209#255#233#215#210#255#233#215#210#255#233#215
+ +#210#255#233#215#210#255#233#215#210#255#233#215#210#255#233#215#210#255#233
+ +#215#210#255#233#215#210#255#233#215#210#255#233#215#210#255#233#215#210#255
+ +#233#215#210#255#233#215#210#255#233#215#210#255#233#215#210#255#233#215#210
+ +#255#233#215#210#255#233#215#210#255#233#215#210#255#233#215#210#255#233#215
+ +#210#255#233#215#210#255#233#215#210#255#233#215#210#255#233#215#210#255#233
+ +#215#210#255#233#215#210#255#233#215#210#255#233#215#210#255#233#215#210#255
+ +#233#215#210#255#233#215#210#255#233#215#210#255#233#215#210#255#233#215#210
+ +#255#233#215#210#255#233#215#210#255#233#215#210#255#233#215#210#255#233#215
+ +#210#255#233#215#210#255#233#215#210#255#233#215#210#255#233#215#210#255#233
+ +#215#210#255#232#215#209#255#232#214#208#255#231#212#206#255#228#207#201#255
+ +#223#198#189#255#213#182#170#255#200#160#144#255#186#136'r'#255#158'iR'#255
+ +'pE2'#255'a7$'#255']1'#30#255'\0'#28#201'[/'#27#31#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#26'\0'#28#193']1'#30#255'`'
+ +'6"'#255'iA.'#255#142']H'#255#179#128'h'#255#196#153#135#255#210#176#163#255
+ +#220#194#184#255#227#205#198#255#231#212#206#255#233#216#211#255#234#217#212
+ +#255#234#218#213#255#234#218#213#255#234#218#213#255#234#218#213#255#234#218
+ +#213#255#234#218#213#255#234#218#213#255#234#218#213#255#234#218#213#255#234
+ +#218#213#255#234#218#213#255#234#218#213#255#234#218#213#255#234#218#213#255
+ +#234#218#213#255#234#218#213#255#234#218#213#255#234#218#213#255#234#218#213
+ +#255#234#218#213#255#234#218#213#255#234#218#213#255#234#218#213#255#234#218
+ +#213#255#234#218#213#255#234#218#213#255#234#218#213#255#234#218#213#255#234
+ +#218#213#255#234#218#213#255#234#218#213#255#234#218#213#255#234#218#213#255
+ +#234#218#213#255#234#218#213#255#234#218#213#255#234#218#213#255#234#218#213
+ +#255#234#218#213#255#234#218#213#255#234#218#213#255#234#218#213#255#234#217
+ +#212#255#234#216#211#255#233#215#210#255#230#211#205#255#226#203#195#255#218
+ +#190#179#255#206#170#155#255#192#146#127#255#172'v`'#255#129'S?'#255'e<)'#255
+ +'_4 '#255'\1'#29#255'[/'#27#143'[/'#27#5#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#3'[/'#27#127'\0'#28
+ +#248'^3'#31#255'c:'''#255'sI6'#255#158'kT'#255#186#136's'#255#200#160#143#255
+ ,#213#180#169#255#222#197#187#255#229#208#201#255#232#214#209#255#234#218#213
+ +#255#235#219#215#255#236#220#215#255#236#220#216#255#236#220#216#255#236#220
+ +#216#255#236#220#216#255#236#220#216#255#236#220#216#255#236#220#216#255#236
+ +#220#216#255#236#220#216#255#236#220#216#255#236#220#216#255#236#220#216#255
+ +#236#220#216#255#236#220#216#255#236#220#216#255#236#220#216#255#236#220#216
+ +#255#236#220#216#255#236#220#216#255#236#220#216#255#236#220#216#255#236#220
+ +#216#255#236#220#216#255#236#220#216#255#236#220#216#255#236#220#216#255#236
+ +#220#216#255#236#220#216#255#236#220#216#255#236#220#216#255#236#220#216#255
+ +#236#220#216#255#236#220#216#255#236#220#216#255#236#220#216#255#236#220#216
+ +#255#236#220#216#255#236#220#215#255#235#219#215#255#234#217#212#255#232#213
+ +#207#255#227#205#198#255#219#193#183#255#209#176#162#255#196#153#136#255#181
+ +#129'l'#255#145'`K'#255'lB0'#255'a7$'#255']1'#30#255'\0'#28#231'[/'#27'O'#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27'$\0'#28#185'\1'#29#255'`5!'#255
+ +'f=*'#255#128'S>'#255#166'r['#255#188#139'v'#255#201#161#145#255#213#181#169
+ +#255#223#197#189#255#229#209#202#255#233#216#210#255#235#219#215#255#236#221
+ +#217#255#237#222#219#255#238#223#220#255#238#223#220#255#238#223#220#255#238
+ +#223#220#255#238#223#220#255#238#223#220#255#238#223#220#255#238#223#220#255
+ +#238#223#220#255#238#223#220#255#238#223#220#255#238#223#220#255#238#223#220
+ +#255#238#223#220#255#238#223#220#255#238#223#220#255#238#223#220#255#238#223
+ +#220#255#238#223#220#255#238#223#220#255#238#223#220#255#238#223#220#255#238
+ +#223#220#255#238#223#220#255#238#223#220#255#238#223#220#255#238#223#220#255
+ +#238#223#220#255#238#223#220#255#238#223#220#255#238#223#220#255#238#223#220
+ +#255#237#222#219#255#237#222#218#255#236#221#217#255#235#218#214#255#232#214
+ +#208#255#228#206#199#255#220#193#184#255#210#176#163#255#197#155#137#255#184
+ +#134'o'#255#155'iR'#255'uI7'#255'c:'''#255'^3'#31#255'\1'#29#252'[/'#27#144
+ +'[/'#27#14#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'['
+ +'/'#27'U\0'#28#228']1'#30#255'`6"'#255'g>,'#255#127'R?'#255#164'qZ'#255#188
+ +#139'v'#255#200#159#144#255#211#179#166#255#220#194#184#255#228#206#199#255
+ +#232#214#209#255#235#219#215#255#237#222#219#255#238#225#221#255#239#225#222
+ +#255#239#225#222#255#239#226#223#255#239#226#223#255#239#226#223#255#239#226
+ +#223#255#239#226#223#255#239#226#223#255#239#226#223#255#239#226#223#255#239
+ +#226#223#255#239#226#223#255#239#226#223#255#239#226#223#255#239#226#223#255
+ +#239#226#223#255#239#226#223#255#239#226#223#255#239#226#223#255#239#226#223
+ +#255#239#226#223#255#239#226#223#255#239#226#223#255#239#226#223#255#239#226
+ +#223#255#239#226#223#255#239#226#223#255#239#225#222#255#238#225#221#255#238
+ +#224#220#255#237#222#218#255#235#218#214#255#231#212#206#255#226#203#195#255
+ +#218#191#180#255#209#174#160#255#197#154#136#255#184#132'o'#255#154'hR'#255
+ +'uK8'#255'e;('#255'_4 '#255'\1'#29#255'\0'#28#197'[/'#27'/'#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27
+ +#12'[/'#27#134'\0'#28#242'^2'#31#255'a5#'#255'g>+'#255'|Q='#255#160'lV'#255
+ +#184#133'p'#255#196#152#134#255#207#170#156#255#216#187#175#255#224#200#192
+ +#255#230#210#203#255#234#216#211#255#236#220#216#255#238#224#220#255#239#226
+ +#223#255#240#227#225#255#240#228#225#255#240#228#225#255#241#229#226#255#241
+ +#229#226#255#241#229#226#255#241#229#226#255#241#229#227#255#241#229#227#255
+ +#241#229#227#255#241#229#227#255#241#229#227#255#241#229#227#255#241#229#227
+ +#255#241#229#227#255#241#229#227#255#241#229#226#255#241#229#226#255#241#229
+ ,#226#255#241#229#226#255#240#228#225#255#240#228#225#255#240#227#224#255#239
+ +#225#222#255#238#223#220#255#236#220#215#255#233#215#210#255#228#207#201#255
+ +#222#196#187#255#213#183#170#255#204#166#150#255#192#147#127#255#179#127'i'
+ +#255#150'fO'#255'tI7'#255'e;('#255'`5!'#255']1'#30#255'\0'#28#223'[/'#27'`[/'
+ +#27#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#17'[/'#27#127'\0'#28#238']1'
+ +#30#255'`6"'#255'e<)'#255'rI6'#255#142'_J'#255#170'wa'#255#188#140'w'#255#199
+ +#158#141#255#208#173#159#255#216#186#175#255#222#196#187#255#227#206#198#255
+ +#232#213#208#255#235#219#214#255#237#222#218#255#238#224#220#255#239#226#223
+ +#255#240#227#225#255#241#229#226#255#242#230#228#255#242#230#228#255#242#231
+ +#229#255#242#231#229#255#242#231#229#255#242#231#229#255#242#231#229#255#242
+ +#231#229#255#242#231#229#255#242#230#228#255#241#229#227#255#241#229#226#255
+ +#240#227#225#255#239#225#222#255#238#224#220#255#236#221#217#255#234#218#213
+ +#255#231#211#206#255#226#204#196#255#220#194#184#255#214#183#171#255#206#169
+ +#155#255#196#153#135#255#185#135'r'#255#162'q['#255#134'XD'#255'lC1'#255'c:'
+ +''''#255'_4 '#255']0'#30#255'\0'#28#217'[/'#27'`[/'#27#4#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#13'[/'#27'w\0'#28#233
+ +']1'#30#255'_4 '#255'b8%'#255'h?-'#255'zN;'#255#149'dP'#255#170'xa'#255#187
+ +#137't'#255#194#150#131#255#202#164#148#255#210#176#163#255#216#187#175#255
+ +#220#194#184#255#224#200#192#255#228#207#199#255#231#212#206#255#234#217#211
+ +#255#236#220#215#255#236#222#217#255#237#222#219#255#238#223#220#255#238#223
+ +#220#255#238#224#220#255#238#223#220#255#237#223#219#255#237#223#218#255#236
+ +#221#217#255#235#219#215#255#233#216#210#255#230#211#204#255#227#204#197#255
+ +#223#199#190#255#219#192#183#255#215#185#173#255#208#173#159#255#200#160#144
+ +#255#192#146#127#255#183#133'o'#255#164's\'#255#142']J'#255'rI7'#255'f=*'#255
+ +'a6#'#255'^3'#31#255'\1'#29#255'\0'#28#210'[/'#27'X[/'#27#2#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0'[/'#27#5'[/'#27'P\0'#28#173'\1'#29#249']1'#30#255'`5!'#255'c9&'#255'g'
+ +'>,'#255'qH6'#255#133'YE'#255#153'iT'#255#172'yd'#255#186#136'q'#255#191#144
+ +'}'#255#196#153#136#255#202#162#146#255#207#171#156#255#211#178#165#255#214
+ +#183#171#255#216#186#175#255#217#188#177#255#218#190#179#255#219#191#182#255
+ +#219#192#182#255#219#192#181#255#218#189#179#255#217#187#177#255#215#185#173
+ +#255#213#182#169#255#210#176#163#255#205#169#154#255#200#160#144#255#195#151
+ +#133#255#190#142'z'#255#183#132'o'#255#167'u_'#255#148'eP'#255#127'S@'#255'm'
+ +'E2'#255'f=*'#255'b7%'#255'_4 '#255']1'#30#255'\0'#28#235'[/'#27#147'[/'#27
+ +'5'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'['
+ ,'/'#27#18'[/'#27'i\0'#28#199'\1'#29#254']1'#30#255'_4 '#255'a6#'#255'd9('#255
+ +'g>,'#255'oF3'#255'}Q>'#255#138'[G'#255#149'fQ'#255#160'oZ'#255#170'xa'#255
+ +#176'}h'#255#180#128'l'#255#183#133'p'#255#186#136's'#255#188#138'u'#255#188
+ +#139'v'#255#187#138'u'#255#186#135'r'#255#183#132'n'#255#178#128'j'#255#174
+ +'|e'#255#168'v`'#255#158'mW'#255#146'bN'#255#133'YE'#255'yM;'#255'mC1'#255'g'
+ +'>+'#255'c9&'#255'`6"'#255'^3'#31#255']1'#30#255'\0'#28#248'\0'#28#173'[/'#27
+ +'O[/'#27#5#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#20'[/'#27'V\0'#28#153
+ +'\0'#28#220'\1'#29#255']1'#30#255'^3'#31#255'`5!'#255'a7$'#255'c9&'#255'e;('
+ +#255'f=*'#255'g>,'#255'i@.'#255'jB0'#255'mE2'#255'qH5'#255'tJ7'#255'qG5'#255
+ +'lC1'#255'jA0'#255'h?-'#255'g>+'#255'e<)'#255'd:('#255'c9&'#255'a6#'#255'`5!'
+ +#255'^2'#31#255']1'#30#255'\1'#29#252'\0'#28#201'[/'#27#134'[/'#27'C[/'#27#8
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0'[/'#27#31'[/'#27'_[/'#27#138'\0'#28#176'\0'#28#213'\0'#28
+ +#248'\1'#29#255'\1'#29#255'\1'#29#255']1'#30#255'^2'#31#255'^2'#31#255'^3'#31
+ +#255'^3'#31#255'^3'#31#255'^2'#31#255']1'#30#255']1'#30#255'\1'#29#255'\1'#29
+ +#255'\1'#29#255'\0'#28#241'\0'#28#203'\0'#28#165'[/'#27#127'[/'#27'N[/'#27#15
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0'[/'#27#2'[/'#27'![/'#27'E[/'#27'U[/'#27'a[/'#27'm[/'#27'y[/'#27
+ +#134'\0'#29#141'[/'#27#130'[/'#27'v[/'#27'j[/'#27'^[/'#27'Q[/'#27'=[/'#27#23
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ ,#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#255#255#255#255#255#255#255#128#0#255#255
+ +#255#255#255#255#255#255#255#255#255#255#255#224#0#0#3#255#255#255#255#255
+ +#255#255#255#255#255#255#254#0#0#0#0'?'#255#255#255#255#255#255#255#255#255
+ +#255#240#0#0#0#0#7#255#255#255#255#255#255#255#255#255#255#128#0#0#0#0#0#255
+ +#255#255#255#255#255#255#255#255#254#0#0#0#0#0#0'?'#255#255#255#255#255#255
+ +#255#255#248#0#0#0#0#0#0#15#255#255#255#255#255#255#255#255#224#0#0#0#0#0#0#3
+ +#255#255#255#255#255#255#255#255#128#0#0#0#0#0#0#0#255#255#255#255#255#255
+ +#255#254#0#0#0#0#0#0#0#0'?'#255#255#255#255#255#255#252#0#0#0#0#0#0#0#0#31
+ +#255#255#255#255#255#255#240#0#0#0#0#0#0#0#0#7#255#255#255#255#255#255#224#0
+ +#0#0#0#0#0#0#0#3#255#255#255#255#255#255#128#0#0#0#0#0#0#0#0#1#255#255#255
+ +#255#255#255#0#0#0#0#0#0#0#0#0#0#127#255#255#255#255#254#0#0#0#0#0#0#0#0#0#0
+ +'?'#255#255#255#255#252#0#0#0#0#0#0#0#0#0#0#31#255#255#255#255#248#0#0#0#0#0
+ +#0#0#0#0#0#15#255#255#255#255#240#0#0#0#0#0#0#0#0#0#0#7#255#255#255#255#224#0
+ +#0#0#0#0#0#0#0#0#0#3#255#255#255#255#192#0#0#0#0#0#0#0#0#0#0#1#255#255#255
+ +#255#128#0#0#0#0#0#0#0#0#0#0#0#255#255#255#255#0#0#0#0#0#0#0#0#0#0#0#0#127
+ +#255#255#254#0#0#0#0#0#0#0#0#0#0#0#0#127#255#255#254#0#0#0#0#0#0#0#0#0#0#0#0
+ +'?'#255#255#252#0#0#0#0#0#0#0#0#0#0#0#0#31#255#255#248#0#0#0#0#0#0#0#0#0#0#0
+ +#0#15#255#255#240#0#0#0#0#0#0#0#0#0#0#0#0#7#255#255#240#0#0#0#0#0#0#0#0#0#0#0
+ +#0#7#255#255#224#0#0#0#0#0#0#0#0#0#0#0#0#3#255#255#192#0#0#0#0#0#0#0#0#0#0#0
+ +#0#3#255#255#192#0#0#0#0#0#0#0#0#0#0#0#0#1#255#255#128#0#0#0#0#0#0#0#0#0#0#0
+ +#0#1#255#255#128#0#0#0#0#0#0#0#0#0#0#0#0#0#255#255#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#255#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#127#254#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#127#254#0#0#0#0#0#0#0#0#0#0#0#0#0#0'?'#254#0#0#0#0#0#0#0#0#0#0#0#0#0#0'?'
+ +#252#0#0#0#0#0#0#0#0#0#0#0#0#0#0'?'#252#0#0#0#0#0#0#0#0#0#0#0#0#0#0#31#252#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#31#248#0#0#0#0#0#0#0#0#0#0#0#0#0#0#15#248#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#15#248#0#0#0#0#0#0#0#0#0#0#0#0#0#0#15#240#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#7#240#0#0#0#0#0#0#0#0#0#0#0#0#0#0#7#240#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#7#224#0#0#0#0#0#0#0#0#0#0#0#0#0#0#7#224#0#0#0#0#0#0#0#0#0#0#0#0#0#0#3
+ +#224#0#0#0#0#0#0#0#0#0#0#0#0#0#0#3#224#0#0#0#0#0#0#0#0#0#0#0#0#0#0#3#224#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#3#224#0#0#0#0#0#0#0#0#0#0#0#0#0#0#3#192#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#3#192#0#0#0#0#0#0#0#0#0#0#0#0#0#0#3#192#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#1#192#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1#192#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#1#192#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1#192#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1#192#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#1#192#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1#192#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#1#192#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1#192#0#0#0#0#0#0#0#0#0
+ ,#0#0#0#0#0#1#192#0#0#0#0#0#0#0#0#0#0#0#0#0#0#3#192#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#3#224#0#0#0#0#0#0#0#0#0#0#0#0#0#0#3#224#0#0#0#0#0#0#0#0#0#0#0#0#0#0#3#224
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#3#224#0#0#0#0#0#0#0#0#0#0#0#0#0#0#3#224#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#3#240#0#0#0#0#0#0#0#0#0#0#0#0#0#0#7#240#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#7#240#0#0#0#0#0#0#0#0#0#0#0#0#0#0#7#240#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#15#248#0#0#0#0#0#0#0#0#0#0#0#0#0#0#15#248#0#0#0#0#0#0#0#0#0#0#0#0#0#0#15
+ +#248#0#0#0#0#0#0#0#0#0#0#0#0#0#0#15#252#0#0#0#0#0#0#0#0#0#0#0#0#0#0#31#252#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#31#252#0#0#0#0#0#0#0#0#0#0#0#0#0#0'?'#254#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0'?'#254#0#0#0#0#0#0#0#0#0#0#0#0#0#0'?'#254#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#127#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#127#255#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#255#255#128#0#0#0#0#0#0#0#0#0#0#0#0#0#255#255#128#0#0#0#0#0#0#0#0
+ +#0#0#0#0#1#255#255#128#0#0#0#0#0#0#0#0#0#0#0#0#1#255#255#192#0#0#0#0#0#0#0#0
+ +#0#0#0#0#3#255#255#192#0#0#0#0#0#0#0#0#0#0#0#0#3#255#255#224#0#0#0#0#0#0#0#0
+ +#0#0#0#0#7#255#255#224#0#0#0#0#0#0#0#0#0#0#0#0#15#255#255#240#0#0#0#0#0#0#0#0
+ +#0#0#0#0#15#255#255#248#0#0#0#0#0#0#0#0#0#0#0#0#31#255#255#248#0#0#0#0#0#0#0
+ +#0#0#0#0#0'?'#255#255#252#0#0#0#0#0#0#0#0#0#0#0#0#127#255#255#252#0#0#0#0#0#0
+ +#0#0#0#0#0#0#255#255#255#254#0#0#0#0#0#0#0#0#0#0#0#0#255#255#255#255#0#0#0#0
+ +#0#0#0#0#0#0#0#1#255#255#255#255#128#0#0#0#0#0#0#0#0#0#0#3#255#255#255#255
+ +#128#0#0#0#0#0#0#0#0#0#0#7#255#255#255#255#192#0#0#0#0#0#0#0#0#0#0#15#255#255
+ +#255#255#224#0#0#0#0#0#0#0#0#0#0#31#255#255#255#255#240#0#0#0#0#0#0#0#0#0#0
+ +#31#255#255#255#255#248#0#0#0#0#0#0#0#0#0#0'?'#255#255#255#255#252#0#0#0#0#0
+ +#0#0#0#0#0#127#255#255#255#255#254#0#0#0#0#0#0#0#0#0#1#255#255#255#255#255
+ +#255#0#0#0#0#0#0#0#0#0#3#255#255#255#255#255#255#128#0#0#0#0#0#0#0#0#7#255
+ +#255#255#255#255#255#224#0#0#0#0#0#0#0#0#15#255#255#255#255#255#255#240#0#0#0
+ +#0#0#0#0#0#31#255#255#255#255#255#255#248#0#0#0#0#0#0#0#0#127#255#255#255#255
+ +#255#255#254#0#0#0#0#0#0#0#0#255#255#255#255#255#255#255#255#128#0#0#0#0#0#0
+ +#3#255#255#255#255#255#255#255#255#192#0#0#0#0#0#0#7#255#255#255#255#255#255
+ +#255#255#240#0#0#0#0#0#0#31#255#255#255#255#255#255#255#255#252#0#0#0#0#0#0
+ +#127#255#255#255#255#255#255#255#255#255#0#0#0#0#0#3#255#255#255#255#255#255
+ +#255#255#255#255#224#0#0#0#0#15#255#255#255#255#255#255#255#255#255#255#252#0
+ +#0#0#0#127#255#255#255#255#255#255#255#255#255#255#255#192#0#0#7#255#255#255
+ +#255#255#255#255#255#255#255#255#255#254#0#1#255#255#255#255#255#255#255#255
+ +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
+ +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
+ +#255#255#255#255#255#255#255#255#255'('#0#0#0'@'#0#0#0#128#0#0#0#1#0' '#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'@@@'#4'III'#7'III'#7
+ +'333'#5#128#128#128#2#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'UUU'#6'DDD'
+ +#15'FFF'#22'EEE'#26'DDD'#30'III#GGG/DDD'#30#255'j>'#31#253'g>#'#249'[>+'#235'PB8'#218'HE'
+ +'C'#203'FEC'#195'EED'#184'DDD'#166'DDDqEEE4@@@'#20'@@@'#4#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1
+ +'999'#9'BBB'#31'CCCPEDD'#143'FFE'#182'NB:'#211'Z?-'#231'g>#'#249'l?'#31#255
+ +'zK$'#253#150']*'#255#165'h.'#255#172'm0'#255#180's2'#255#186'x4'#255#189'{4'
+ +#255#192#127'5'#255#190'|4'#255#187'x4'#255#182'u3'#255#175'p1'#255#167'j/'
+ +#255#156'b+'#255#131'R&'#254'oB '#255'i>!'#253'_>)'#238'S@6'#222'FEB'#203'DD'
+ +'C'#190'DDD'#164'CCCkCCC.PPP'#16'UUU'#3#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#128#128#128#2'CCC'#19'BBBBDDD'#136'EED'#179'LA9'
+ +#209'`=&'#243'k?'#31#255#127'N&'#254#154'`,'#255#176'q1'#255#191'~5'#255#200
+ +#138'7'#255#207#145'8'#255#210#149'9'#255#213#153'9'#255#217#157':'#255#219
+ +#160';'#255#221#162';'#255#220#162':'#255#217#158':'#255#215#155':'#255#211
+ +#151'9'#255#208#146'8'#255#203#141'8'#255#194#129'6'#255#183'v4'#255#163'f.'
+ +#255#137'U('#254'qC"'#254'f'
+ +'>>!+++'#6#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'@@@'#4'BBB'#27'CC'
+ +'C[CCB'#165'LD='#203']<('#238'j> '#255#135'R('#254#176'p3'#255#193#128'7'#255
+ +#202#139'9'#255#211#151';'#255#220#162'<'#255#227#170'>'#255#232#176'?'#255
+ +#234#180'?'#255#237#182'?'#255#239#185'@'#255#241#187'@'#255#242#188'A'#255
+ +#241#187'@'#255#240#185'A'#255#238#183'@'#255#235#180'@'#255#233#178'?'#255
+ +#229#173'>'#255#222#165'='#255#215#156'<'#255#205#144':'#255#196#133'8'#255
+ +#185'x5'#255#152'^-'#255'oC"'#254'd<#'#247'QA7'#220'FFE'#200'CCC'#180'CCC}AA'
+ +'A/UUU'#9#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'III'#7'CCC&DDDpECC'#180'X<,'#232'i='
+ +'!'#254#128'O('#254#170'l3'#255#194#130':'#255#210#150'>'#255#220#163'?'#255
+ +#227#171'A'#255#234#180'B'#255#240#187'D'#255#242#190'D'#255#244#193'E'#255
+ +#246#194'D'#255#247#195'E'#255#248#197'E'#255#249#197'E'#255#249#198'E'#255
+ +#249#197'E'#255#248#196'E'#255#247#195'E'#255#246#195'E'#255#245#194'D'#255
+ +#243#191'D'#255#240#188'C'#255#236#183'C'#255#230#174'B'#255#223#165'@'#255
+ +#215#156'?'#255#200#137';'#255#182'u6'#255#146'[,'#255'm@!'#254'`:%'#244'KA;'
+ +#211'CCC'#189'CCC'#144'BBB>PPP'#16#128#128#128#2#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'999'#9'@@@4CCC'#133
+ +'HD@'#192'_9$'#244'rE%'#254#164'h3'#255#191#127';'#255#206#146'?'#255#219#163
+ +'C'#255#232#178'F'#255#238#185'G'#255#241#189'H'#255#244#193'H'#255#246#195
+ +'I'#255#247#196'I'#255#247#197'J'#255#247#197'I'#255#247#198'I'#255#248#198
+ +'I'#255#248#198'I'#255#248#197'I'#255#248#198'I'#255#248#198'I'#255#248#198
+ +'I'#255#247#197'I'#255#247#197'I'#255#247#196'I'#255#246#196'I'#255#245#194
+ +'H'#255#242#190'H'#255#239#187'H'#255#235#182'G'#255#224#168'D'#255#211#153
+ +'A'#255#196#134'='#255#177'q7'#255#133'Q)'#254'e: '#253'N?7'#218'DDC'#195'CC'
+ +'C'#160'FFFP@@@'#20#0#0#0#2#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0'III'#7'FFF3CCC'#145'LB;'#204'd:"'#250'|L('#254#180's9'#255
+ +#202#143'A'#255#216#159'F'#255#228#174'I'#255#236#184'K'#255#241#191'L'#255
+ +#243#193'M'#255#244#194'M'#255#244#195'M'#255#245#196'M'#255#245#195'M'#255
+ +#245#195'M'#255#245#195'M'#255#245#195'M'#255#245#195'M'#255#245#195'M'#255
+ +#245#195'M'#255#245#195'M'#255#245#195'M'#255#245#195'M'#255#245#195'M'#255
+ +#245#195'M'#255#245#195'M'#255#245#196'M'#255#245#195'M'#255#244#194'M'#255
+ +#243#194'M'#255#242#192'M'#255#238#186'L'#255#232#179'J'#255#220#165'F'#255
+ +#208#150'C'#255#190#127'<'#255#147'[.'#255'h< '#255'S=1'#228'EED'#199'DDD'
+ +#168'BBBUGGG'#18#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +'@@@'#4'FFF(EEE'#134'P?5'#212'e:!'#254#137'U,'#254#186'z='#255#208#150'E'#255
+ +#224#171'L'#255#233#181'O'#255#238#187'P'#255#240#191'P'#255#242#192'Q'#255
+ +#242#193'Q'#255#242#193'Q'#255#242#193'P'#255#242#193'Q'#255#242#193'Q'#255
+ +#242#193'Q'#255#242#193'Q'#255#242#193'Q'#255#242#193'Q'#255#242#193'Q'#255
+ ,#242#193'Q'#255#242#193'Q'#255#242#193'Q'#255#242#193'Q'#255#242#193'Q'#255
+ +#242#193'Q'#255#242#193'Q'#255#242#193'Q'#255#242#193'Q'#255#242#193'Q'#255
+ +#242#193'Q'#255#242#193'Q'#255#241#192'Q'#255#239#189'P'#255#234#184'O'#255
+ +#228#175'M'#255#215#159'I'#255#194#132'@'#255#160'd3'#255'k?"'#254'X:*'#236
+ +'FDC'#201'CCC'#164'AAAG;;;'#13#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'U'
+ +'UU'#3'BBB'#31'CCCvO=3'#211'f:'#31#255#150']2'#255#190#128'A'#255#211#155'I'
+ +#255#226#175'Q'#255#234#185'S'#255#237#188'T'#255#238#190'T'#255#239#191'U'
+ +#255#239#191'U'#255#239#191'U'#255#239#191'U'#255#239#191'U'#255#239#191'U'
+ +#255#239#191'U'#255#239#191'U'#255#235#189'S'#255'|d,'#255'N>'#28#255'4*'#19
+ +#255'=1'#22#255'WE'#31#255'w_*'#255#173#139'='#255#239#191'U'#255#239#191'U'
+ +#255#239#191'U'#255#239#191'U'#255#239#191'U'#255#239#191'U'#255#239#191'U'
+ +#255#239#191'U'#255#239#191'U'#255#239#190'T'#255#238#189'U'#255#236#187'S'
+ +#255#230#179'R'#255#217#162'L'#255#198#138'D'#255#170'l8'#255'pC$'#254'Z8'''
+ +#240'DBB'#197'CCC'#153'FFF:@@@'#8#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#2'FFF'#22
+ +'BBBeJ?9'#195'b8 '#254#150']2'#255#194#133'E'#255#213#158'N'#255#226#176'T'
+ +#255#233#185'W'#255#236#187'W'#255#236#188'X'#255#236#188'X'#255#236#188'X'
+ +#255#236#188'X'#255#236#188'X'#255#236#188'X'#255#236#188'X'#255#236#188'X'
+ +#255#236#188'X'#255'cO%'#255#4#3#1#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#1#1#0#255#18#14#7#255'A4'#24#255#134'k2'
+ +#255#218#174'R'#255#236#188'X'#255#236#188'X'#255#236#188'X'#255#236#188'X'
+ +#255#236#188'X'#255#236#188'X'#255#236#187'W'#255#234#186'W'#255#229#180'U'
+ +#255#218#165'P'#255#201#143'H'#255#173'o<'#255'k>#'#254'S;-'#231'CCC'#193'CC'
+ +'C'#141'DDD-fff'#5#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'@@@'#12'DDDKFA='#179'`7 '#251#137'S-'
+ +#255#192#131'E'#255#214#161'Q'#255#226#176'W'#255#231#183'Y'#255#233#185'['
+ +#255#233#186'['#255#234#185'Z'#255#234#185'Z'#255#234#185'Z'#255#234#185'Z'
+ +#255#234#185'Z'#255#234#185'Z'#255#234#185'Z'#255#234#185'Z'#255'L<'#29#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#8#7#3#255'P'
+ +'?'#31#255#203#161'N'#255#234#185'Z'#255#234#185'Z'#255#234#185'Z'#255#234
+ +#185'Z'#255#233#186'['#255#232#183'Z'#255#228#178'Y'#255#219#167'T'#255#201
+ +#143'K'#255#163'g8'#255'f: '#255'O=4'#222'DDD'#188'CCCzBBB'#27#0#0#0#1#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'U'
+ +'UU'#3'GGG$D@@'#147'\6#'#245'{I*'#254#185'{C'#255#211#157'R'#255#225#175'Z'
+ +#255#229#181'\'#255#230#183']'#255#230#183']'#255#230#183']'#255#230#183']'
+ +#255#230#183']'#255#230#183']'#255#230#183']'#255#230#183']'#255#230#183']'
+ +#255#230#183']'#255#138'm8'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#24#20#10#255'x_0'
+ +#255#226#181'['#255#230#183']'#255#230#183']'#255#230#183']'#255#230#181'\'
+ +#255#227#177'['#255#217#165'V'#255#196#136'J'#255#151']4'#255'b8 '#254'K@9'
+ +#214'CCC'#175'AAAJ...'#11#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0'@@@'#16'CCC\V6'''#228'nA&'#254#178'tA'#255#205
+ +#151'R'#255#221#172'\'#255#226#179'_'#255#228#180'_'#255#228#180'_'#255#228
+ +#180'_'#255#228#180'_'#255#228#180'_'#255#228#180'_'#255#228#180'_'#255#228
+ +#180'_'#255#228#180'_'#255#228#180'_'#255#228#180'_'#255#17#13#7#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#2#1#1#255'H9'#30#255#224#178']'
+ +#255#228#180'_'#255#228#180'_'#255#227#179'^'#255#224#175']'#255#213#160'W'
+ +#255#190#129'H'#255#137'T/'#255'^4 '#252'FB?'#201'CCC'#140'DDD"'#0#0#0#3#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'@@@'#4'FFF,J=7'
+ +#175'`4'#30#255#165'g;'#255#200#144'Q'#255#217#166'\'#255#223#176'`'#255#225
+ +#177'`'#255#225#177'a'#255#225#177'a'#255#225#177'a'#255#225#177'a'#255#225
+ +#177'a'#255#225#177'a'#255#225#177'a'#255#225#177'a'#255#225#177'a'#255#225
+ +#177'a'#255#218#171'^'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#11#9#5#255#196#154'U'#255#225#177'a'#255#225#177
+ +'`'#255#224#177'a'#255#220#171'^'#255#208#154'W'#255#184'{F'#255'nA%'#254'T8'
+ +'*'#233'DDD'#180'CCCX333'#15#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0'CCC'#19'CCCjY5#'#239'~J,'#254#191#132'M'#255#213#162']'#255
+ ,#220#171'a'#255#221#173'c'#255#222#174'b'#255#222#174'b'#255#222#174'b'#255
+ +#222#174'b'#255#222#174'b'#255#222#174'b'#255#222#174'b'#255#222#174'b'#255
+ +#222#174'b'#255#222#174'b'#255#222#174'b'#255#154'yC'#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#15#11#6
+ +#255#218#172'`'#255#222#174'b'#255#222#174'b'#255#221#173'b'#255#217#167'_'
+ +#255#202#146'T'#255#156'a9'#255'^4'#30#254'G@='#206'DDD'#151'>>>)@@@'#4#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'UUU'#3'AAA+L;4'#188'b6 '#254#170
+ +'l@'#255#206#152'Z'#255#217#168'b'#255#219#171'd'#255#219#171'd'#255#219#171
+ +'d'#255#219#171'd'#255#219#171'd'#255#219#171'd'#255#219#171'd'#255#219#171
+ +'d'#255#219#171'd'#255#219#171'd'#255#219#171'd'#255#219#171'd'#255#219#171
+ +'d'#255#219#171'd'#255#26#20#12#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'oW3'#255#219#171'd'#255#219
+ +#171'd'#255#219#171'd'#255#218#169'c'#255#212#161'_'#255#187#127'L'#255'uD)'
+ +#254'W6('#238'CCC'#182'CCC[III'#14#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0'@@@'#12'EBBS[3'#31#244#134'O/'#255#192#134'Q'#255#212#162'b'#255#215
+ +#167'd'#255#216#168'd'#255#216#168'd'#255#216#168'd'#255#216#168'd'#255#216
+ +#168'd'#255#216#168'd'#255#216#168'd'#255#216#168'd'#255#216#168'd'#255#216
+ +#168'd'#255#216#168'd'#255#216#168'd'#255#216#168'd'#255#216#168'd'#255#198
+ +#154'\'#255#5#4#2#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255'!'#25#15#255#216#168'd'#255#216#168'd'#255#216#168
+ +'d'#255#216#168'd'#255#214#166'd'#255#202#147'Y'#255#161'e='#255'^2'#29#255
+ +'J?:'#208'CCC'#137'EEE'#26#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'C'
+ +'CC'#23'O9/'#171'`3'#31#254#174'pD'#255#203#150']'#255#212#163'e'#255#213#164
+ +'e'#255#213#164'e'#255#213#164'e'#255#213#164'e'#255#213#164'e'#255#213#164
+ +'e'#255#213#164'e'#255#213#164'e'#255#213#164'e'#255#213#164'e'#255#213#164
+ +'e'#255#213#164'e'#255#213#164'e'#255#213#164'e'#255#213#164'e'#255#213#164
+ +'e'#255#173#133'R'#255#3#2#1#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#22#17#11#255#213#164'e'#255#213#164'e'#255#213#164
+ +'e'#255#213#164'e'#255#213#164'f'#255#209#158'a'#255#187#128'O'#255'yD)'#254
+ +'W4$'#241'BBB'#169'DDD1@@@'#4#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#2'FFF(W4'
+ +'$'#229'{E)'#255#191#134'T'#255#207#157'c'#255#210#160'f'#255#210#160'f'#255
+ +#210#160'f'#255#210#160'f'#255#210#160'f'#255#210#160'f'#255#210#160'f'#255
+ +#210#160'f'#255#152'tJ'#255'[E,'#255'K9$'#255'{]<'#255#196#149'_'#255#210#160
+ +'f'#255#210#160'f'#255#210#160'f'#255#210#160'f'#255#210#160'f'#255#159'yM'
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'"'
+ +#26#17#255#210#160'f'#255#210#160'f'#255#210#160'f'#255#210#160'f'#255#210
+ +#160'f'#255#209#160'e'#255#199#146']'#255#156'_;'#255'\1'#28#254'FBA'#188'FF'
+ +'FXNNN'#13#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'FFF'#11'F@=T\/'#28#253#151'\9'#255
+ +#200#147'_'#255#207#156'e'#255#207#156'e'#255#207#156'e'#255#207#156'e'#255
+ +#207#156'e'#255#207#156'e'#255#207#156'e'#255#178#135'W'#255'$'#27#17#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'N:&'#255#207#156'e'#255#207
+ +#156'e'#255#207#156'e'#255#207#156'e'#255#207#156'e'#255#3#2#1#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'uX9'#255#207#156'e'#255#207
+ +#156'e'#255#207#156'e'#255#207#156'e'#255#207#156'e'#255#207#157'e'#255#204
+ +#153'b'#255#180'wK'#255'a4'#30#254'M;3'#216'DDD'#132'==='#25#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0'CCC'#19'N9.'#159'^2'#30#254#176'rI'#255#202#150'c'#255#203
+ +#153'e'#255#203#153'f'#255#203#153'f'#255#203#153'f'#255#203#153'f'#255#203
+ +#153'f'#255#163'zQ'#255#1#1#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#29#22#15#255#203#153'f'#255#203#153'f'#255#203#153
+ +'f'#255#203#153'f'#255#14#10#7#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ ,#0#0#255#4#3#2#255#203#153'f'#255#203#153'f'#255#203#153'f'#255#203#153'f'
+ +#255#203#153'f'#255#203#153'f'#255#203#153'f'#255#203#152'e'#255#190#134'X'
+ +#255'yC)'#254'V5&'#239'DDD'#165'FFF('#128#128#128#2#0#0#0#0#0#0#0#0#0#0#0#0
+ +'GGG'#25'V4%'#212's@&'#254#186#128'U'#255#199#148'd'#255#200#148'd'#255#200
+ +#148'd'#255#200#148'd'#255#200#148'd'#255#200#148'd'#255#198#146'd'#255#12#9
+ +#6#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#138'fE'#255#200#148'd'#255#200#148'd'#255#200#148'd'#255
+ +#15#11#7#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1#0#0#255'&'#28#19#255#145'kH'#255
+ +#200#148'd'#255#200#148'd'#255#200#148'd'#255#200#148'd'#255#200#148'd'#255
+ +#200#148'd'#255#200#148'd'#255#200#148'd'#255#194#141'^'#255#146'W6'#255'[0'
+ +#28#254'EBB'#178'CCC9UUU'#6#0#0#0#0#0#0#0#0#0#0#0#0'JAA'#31'\1'#29#249#140'P'
+ +'2'#255#190#135'\'#255#196#143'c'#255#196#143'c'#255#196#143'c'#255#196#143
+ +'c'#255#196#143'c'#255#196#143'c'#255'>-'#31#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'&'
+ +#28#19#255#196#143'c'#255#196#143'c'#255#196#143'c'#255#25#18#12#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#2#2#1
+ +#255'*'#31#21#255'kM6'#255#187#137'_'#255#196#143'c'#255#196#143'c'#255#196
+ +#143'c'#255#196#143'c'#255#196#143'c'#255#196#143'c'#255#196#143'c'#255#196
+ +#143'c'#255#196#143'c'#255#196#143'c'#255#194#141'b'#255#170'kF'#255'\0'#28
+ +#254'L<5'#203'CCCH333'#10#0#0#0#0#0#0#0#0#0#0#0#1'K3+@[/'#27#255#160'`>'#255
+ +#190#136'_'#255#191#137'`'#255#191#137'`'#255#191#137'`'#255#191#137'`'#255
+ +#191#137'`'#255#189#135'`'#255#1#1#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#30#21#15#255
+ +#191#137'`'#255#191#137'`'#255#191#137'`'#255'aF1'#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#5#3#2#255#165'vS'#255#191#137'`'
+ +#255#191#137'`'#255#191#137'`'#255#191#137'`'#255#191#137'`'#255#191#137'`'
+ +#255#191#137'`'#255#191#137'`'#255#191#137'`'#255#191#137'`'#255#191#137'`'
+ +#255#191#137'`'#255#191#137'`'#255#191#136'`'#255#178'vQ'#255'h7 '#253'Q8,'
+ +#220'DDDV;;;'#13#0#0#0#0#0#0#0#0'UUU'#3'R4''^[/'#27#255#169'hF'#255#187#131
+ +']'#255#187#132'^'#255#187#132'^'#255#187#132'^'#255#187#132'^'#255#187#132
+ +'^'#255'uS;'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'{W>'#255#187#132'^'#255
+ +#187#132'^'#255#187#132'^'#255#185#130'^'#255#19#14#10#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#1#1#1#255#158'oO'#255#187#132'^'#255#187#132'^'
+ +#255#187#132'^'#255#187#132'^'#255#187#132'^'#255#187#132'^'#255#187#132'^'
+ +#255#187#132'^'#255#187#132'^'#255#187#132'^'#255#187#132'^'#255#187#132'^'
+ +#255#187#132'^'#255#187#132'^'#255#187#132'^'#255#181'{V'#255'r<"'#255'T6'''
+ +#228'BBBd@@@'#16#0#0#0#0#0#0#0#0'UUU'#6'T5''}_2'#30#253#171'kI'#255#183'}Z'
+ +#255#183'~Z'#255#183'~Z'#255#183'~Z'#255#183'~Z'#255#183'~Z'#255'. '#23#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#1#1#0#255'S9)'#255#183'~Z'#255#183'~Z'#255#183'~Z'#255#183'~Z'
+ +#255#183'~Z'#255#173'xV'#255#31#21#15#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'b'
+ +'C0'#255#183'~Z'#255#183'~Z'#255#183'~Z'#255#183'~Z'#255#183'~Z'#255#183'~Z'
+ +#255#183'~Z'#255#183'~Z'#255#183'~Z'#255#183'~Z'#255#183'~Z'#255#183'~Z'#255
+ +#183'~Z'#255#183'~Z'#255#183'~Z'#255#183'~Z'#255#181'zV'#255'zA%'#255'X4$'
+ +#237'DDDqCCC'#19#0#0#0#0#0#0#0#0'@@@'#8'U4%'#149'f5'#31#252#172'mK'#255#180
+ +'yX'#255#180'yX'#255#180'yX'#255#180'yX'#255#180'yX'#255#180'yX'#255#6#4#3
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#19#13#9#255#153'gK'#255#180'yX'#255#180'yX'#255#180'yX'#255#180'yX'
+ +#255#180'yX'#255#180'yX'#255#180'yX'#255#180'yX'#255'{S<'#255'+'#29#21#255#7
+ +#4#3#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1#1#1
+ +#255'gF3'#255#180'yX'#255#180'yX'#255#180'yX'#255#139']D'#255'+'#29#21#255#8
+ +#6#4#255#8#6#4#255#16#11#8#255'W:*'#255#178'wV'#255#180'yX'#255#180'yX'#255
+ +#180'yX'#255#180'yX'#255#180'yX'#255#180'yX'#255#180'yX'#255#179'yV'#255#131
+ +'F+'#255'[3!'#245'CCCyIII'#21#0#0#0#0#0#0#0#0'UUU'#6'X3"'#165'n:"'#253#172'p'
+ +'O'#255#177'wW'#255#177'wW'#255#177'wW'#255#177'wW'#255#177'wW'#255#173'uU'
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1
+ +#0#0#255'P6'''#255#177'wW'#255#177'wW'#255#177'wW'#255#177'wW'#255#177'wW'
+ ,#255#177'wW'#255#177'wW'#255#177'wW'#255#177'wW'#255#177'wW'#255#177'wW'#255
+ +#177'wW'#255#177'wW'#255#158'jM'#255'W;+'#255''''#26#19#255'"'#23#17#255'%'
+ +#25#18#255'W:+'#255#167'qS'#255#177'wW'#255#177'wW'#255#177'wW'#255'@+'#31
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#3#2#1#255
+ +#149'dI'#255#177'wW'#255#177'wW'#255#177'wW'#255#177'wW'#255#177'wW'#255#177
+ +'wW'#255#177'vV'#255#139'M0'#255'[1'#30#250'DDDpCCC'#19#0#0#0#0#0#0#0#0'UUU'
+ +#3'Y1'#31#182'v>%'#255#172'oQ'#255#175'tW'#255#175'tW'#255#175'tW'#255#175't'
+ +'W'#255#175'tW'#255'}S?'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#26#17#13#255#150'cK'#255#175'tW'#255#175'tW'#255#175'tW'#255
+ +#175'tW'#255#175'tW'#255#175'tW'#255#175'tW'#255#175'tW'#255#175'tW'#255#175
+ +'tW'#255#175'tW'#255#175'tW'#255#175'tW'#255#175'tW'#255#175'tW'#255#175'tW'
+ +#255#175'tW'#255#175'tW'#255#175'tW'#255#175'tW'#255#175'tW'#255#175'tW'#255
+ +#175'tW'#255'dC2'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#9#6#4#255#169'pU'#255#175'tW'#255#175'tW'#255#175't'
+ +'W'#255#175'tW'#255#175'tW'#255#174'sU'#255#145'S6'#255']0'#28#254'DBBd@@@'
+ +#16#0#0#0#0#0#0#0#0#0#0#0#0'Z0'#30#175'v=%'#255#171'nP'#255#174'rV'#255#174
+ +'rV'#255#174'rV'#255#174'rV'#255#174'rV'#255'L2&'#255#0#0#0#255'/'#31#23#255
+ +'}R>'#255' '#21#16#255'!'#22#17#255#139'[E'#255#174'rV'#255#174'rV'#255#174
+ +'rV'#255#174'rV'#255#174'rV'#255#174'rV'#255#174'rV'#255#174'rV'#255#174'rV'
+ +#255#174'rV'#255#174'rV'#255#174'rV'#255#174'rV'#255#174'rV'#255#174'rV'#255
+ +#174'rV'#255#174'rV'#255#174'rV'#255#174'rV'#255#174'rV'#255#174'rV'#255#174
+ +'rV'#255#174'rV'#255#174'rV'#255#174'rV'#255'?*'#31#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'6#'#27
+ +#255#174'rV'#255#174'rV'#255#174'rV'#255#174'rV'#255#174'rV'#255#173'qT'#255
+ +#145'S7'#255'\1'#29#254'AAAV;;;'#13#0#0#0#0#0#0#0#0#0#0#0#0'Z1'#30#150'n;$'
+ +#252#169'jM'#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255
+ +#149'bI'#255'@* '#255#170'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'
+ +#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255
+ +#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#172
+ +'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'
+ +#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255
+ +'G/#'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#24#16#12#255#172'qU'#255#172'qU'#255#172'qU'#255#172
+ +'qU'#255#172'qU'#255#171'oS'#255#138'N3'#255'\2'#31#249'DDDG999'#9#0#0#0#0#0
+ +#0#0#0#0#0#0#0'X1!|g7#'#250#167'gI'#255#172'pT'#255#172'qU'#255#172'qU'#255
+ +#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#172
+ +'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'
+ +#255#172'qU'#255'P5('#255')'#27#20#255#27#18#13#255'5#'#26#255'pJ8'#255#172
+ +'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'
+ +#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255
+ +#172'qU'#255#172'qU'#255#162'jO'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#9#6#4#255#172'qU'#255#172
+ +'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#170'mR'#255#131'I.'#255'[4"'#241
+ +'FFF7UUU'#6#0#0#0#0#0#0#0#0#0#0#0#0'Y1!`b5 '#251#164'cG'#255#172'pU'#255#173
+ +'rW'#255#173'rW'#255#173'rW'#255#173'rW'#255#173'rW'#255#173'rW'#255#173'rW'
+ +#255#173'rW'#255#173'rW'#255#173'rW'#255#173'rW'#255#173'rW'#255#173'rW'#255
+ +#173'rW'#255'}S?'#255#9#6#5#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#16#11#8#255#152'dM'#255#173'rW'#255#173'rW'#255#173'rW'#255#173'rW'#255
+ +#173'rW'#255#173'rW'#255#173'rW'#255#173'rW'#255#173'rW'#255#173'rW'#255#173
+ +'rW'#255#173'rW'#255#173'rW'#255#173'rW'#255'$'#24#18#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#4#3#2#255#173'r'
+ +'W'#255#173'rW'#255#173'rW'#255#173'rW'#255#173'rW'#255#170'mQ'#255'|C*'#255
+ +'W4$'#229'CCC&'#0#0#0#2#0#0#0#0#0#0#0#0#0#0#0#0'X5!A^2'#31#254#162'bE'#255
+ +#173'rV'#255#175'tY'#255#175'tY'#255#175'tY'#255#175'tY'#255#175'tY'#255#175
+ +'tY'#255#175'tY'#255#175'tY'#255#175'tY'#255#175'tY'#255#175'tY'#255#175'tY'
+ +#255#175'tY'#255'{Q?'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#14#9#7#255#173'tY'#255#175'tY'#255#175'tY'#255
+ +#175'tY'#255#175'tY'#255#175'tY'#255#175'tY'#255#175'tY'#255#175'tY'#255#175
+ +'tY'#255#175'tY'#255#175'tY'#255#175'tY'#255#175'tY'#255#132'XC'#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#21
+ +#14#11#255#175'tY'#255#175'tY'#255#175'tY'#255#175'tY'#255#174'tY'#255#170'm'
+ +'P'#255't?('#254'U5&'#203'@@@'#24#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'X0'#24' ^2'
+ +#31#255#156'\A'#255#175'v\'#255#177'y`'#255#177'y`'#255#177'y`'#255#177'y`'
+ +#255#177'y`'#255#177'y`'#255#177'y`'#255#177'y`'#255#177'y`'#255#177'y`'#255
+ ,#177'y`'#255#177'y`'#255#177'y`'#255#11#8#6#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#136']J'#255#177
+ +'y`'#255#177'y`'#255'7%'#30#255#9#6#5#255#13#9#7#255#16#11#9#255#26#18#14#255
+ +#139'_K'#255#177'y`'#255#177'y`'#255#177'y`'#255#177'y`'#255#177'y`'#255#177
+ +'y`'#255#18#12#9#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255'<)!'#255#177'y`'#255#177'y`'#255#177'y`'#255#177'y`'#255#176
+ +'x^'#255#169'kP'#255'j<&'#253'U4%'#168';;;'#13#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0'^2'#29#234#136'O4'#255#176'x^'#255#180'~f'#255#180'~f'#255#180'~f'
+ +#255#180'~f'#255#180'~f'#255#180'~f'#255#180'~f'#255#180'~f'#255#180'~f'#255
+ +#180'~f'#255#180'~f'#255#180'~f'#255#146'gS'#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#139'bO'#255#170'x`'#255#20#14#11#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255']A4'#255#180'~f'#255#180'~f'#255#180'~f'#255#180'~f'#255
+ +#180'~f'#255'qO@'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#1#1#0#255#165't^'#255#180'~f'#255#180'~f'#255#180'~f'#255#180'~f'#255
+ +#178'zb'#255#162'dH'#255'_3'#31#254'R6)c@@@'#4#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0'[/'#29#153'r?)'#252#174'sZ'#255#182#129'j'#255#183#131'l'#255#183
+ +#131'l'#255#183#131'l'#255#183#131'l'#255#183#131'l'#255#183#131'l'#255#183
+ +#131'l'#255#183#131'l'#255#183#131'l'#255#183#131'l'#255#183#131'l'#255'ZA5'
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#5#3#3#255#179#127'j'#255'uTE'#255#0#0#0#255#0#0#0#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'{XI'#255#183#131'l'
+ +#255#183#131'l'#255#183#131'l'#255#183#131'l'#255#183#131'l'#255#20#15#12#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255':)"'#255#183#131'l'#255
+ +#183#131'l'#255#183#131'l'#255#183#131'l'#255#183#131'l'#255#179'|c'#255#140
+ +'R9'#255'\2'#31#248'@@6'#28#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +'[/'#29'E`5 '#252#166'iO'#255#183#131'l'#255#186#136'q'#255#186#136'q'#255
+ +#186#136'q'#255#186#136'q'#255#186#136'q'#255#186#136'q'#255#186#136'q'#255
+ +#186#136'q'#255#186#136'q'#255#186#136'q'#255#186#136'q'#255'\D8'#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255'oQC'#255#186#136'q'#255'X@6'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#12#9#7#255#186#136'q'#255#186
+ +#136'q'#255#186#136'q'#255#186#136'q'#255#186#136'q'#255#148'lZ'#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#169'|g'#255#186#136'q'#255#186
+ +#136'q'#255#186#136'q'#255#186#136'q'#255#185#134'q'#255#177'y`'#255'tB+'#254
+ +'W2!'#194'III'#14#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'@@'#0#4'^3'
+ +#30#245#144'W='#255#184#134'o'#255#189#141'x'#255#189#141'x'#255#189#141'x'
+ +#255#189#141'x'#255#189#141'x'#255#189#141'x'#255#189#141'x'#255#189#141'x'
+ +#255#189#141'x'#255#189#141'x'#255#189#141'x'#255'tWJ'#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'('#30#26#255
+ +#189#141'x'#255#189#141'x'#255'?/('#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#187#139'v'#255#189#141
+ +'x'#255#189#141'x'#255#189#141'x'#255#189#141'x'#255#189#141'x'#255#172#128
+ +'m'#255'_G<'#255#1#0#0#255#0#0#0#255'-"'#28#255#189#141'x'#255#189#141'x'#255
+ +#189#141'x'#255#189#141'x'#255#189#141'x'#255#186#137's'#255#171'oU'#255'a6"'
+ +#253'T5$jUUU'#3#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'\/'
+ +#27#170'vD,'#252#181#128'h'#255#190#144'{'#255#192#146'~'#255#192#146'~'#255
+ +#192#146'~'#255#192#146'~'#255#192#146'~'#255#192#146'~'#255#192#146'~'#255
+ +#192#146'~'#255#192#146'~'#255#192#146'~'#255#186#142'z'#255#1#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#2#1#1#255#186#142'z'
+ +#255#192#146'~'#255#192#146'~'#255'=.('#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#192#146'~'#255#192
+ +#146'~'#255#192#146'~'#255#192#146'~'#255#192#146'~'#255#192#146'~'#255#192
+ +#146'~'#255#192#146'~'#255#0#0#0#255#0#0#0#255#167#127'n'#255#192#146'~'#255
+ +#192#146'~'#255#192#146'~'#255#192#146'~'#255#191#145'}'#255#186#137's'#255
+ +#149'[A'#255'^1'#31#250'F:.'#22#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0'\.'#28'H`5 '#252#164'jP'#255#190#143'z'#255#194#151#131
+ +#255#194#151#131#255#194#151#131#255#194#151#131#255#194#151#131#255#194#151
+ +#131#255#194#151#131#255#194#151#131#255#194#151#131#255#194#151#131#255#194
+ +#151#131#255#27#21#18#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255' '#25#21#255#194#151#131#255#194#151#131#255#194#151#131#255'7*%'
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#12#9#8#255#194#151#131#255#194#151#131#255#194#151#131#255#194#151
+ +#131#255#194#151#131#255#194#151#131#255#194#151#131#255#190#149#129#255#0#0
+ ,#0#255'0% '#255#194#151#131#255#194#151#131#255#194#151#131#255#194#151#131
+ +#255#194#151#131#255#192#147#127#255#180'~f'#255'q@+'#252'Z0'#29#180#0#0#0#2
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0']0'
+ +#28#199'{H2'#252#184#134'o'#255#196#153#134#255#197#156#137#255#197#156#137
+ +#255#197#156#137#255#197#156#137#255#197#156#137#255#197#156#137#255#197#156
+ +#137#255#197#156#137#255#197#156#137#255#197#156#137#255'G81'#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'WE='#255#197#156#137#255#197
+ +#156#137#255#191#152#133#255#1#1#1#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#135'k^'#255#197#156#137#255#197
+ +#156#137#255#197#156#137#255#197#156#137#255#197#156#137#255#197#156#137#255
+ +#197#156#137#255#197#156#137#255#16#12#11#255#174#138'y'#255#197#156#137#255
+ +#197#156#137#255#197#156#137#255#197#156#137#255#197#155#136#255#191#145'|'
+ +#255#151'_F'#255'^3'#31#253'T2!-'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[0'#29'5_4 '#254#161'hP'#255#195#152#132
+ +#255#200#161#143#255#200#161#144#255#200#161#144#255#200#161#144#255#200#161
+ +#144#255#200#161#144#255#200#161#144#255#200#161#144#255#200#161#144#255#200
+ +#161#144#255'xaW'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1#1#1
+ +#255#171#138'{'#255#200#161#144#255#200#161#144#255#127'f\'#255#0#0#0#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255')!'#30#255
+ +#200#161#144#255#200#161#144#255#200#161#144#255#200#161#144#255#200#161#144
+ +#255#200#161#144#255#200#161#144#255#200#161#144#255#200#161#144#255#153'{n'
+ +#255#200#161#144#255#200#161#144#255#200#161#144#255#200#161#144#255#200#161
+ +#144#255#198#156#138#255#181#128'h'#255'l>*'#252'Z1'#30#159#0#0#0#1#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0'^0'#27#173'uE/'#249#186#136'r'#255#201#162#145#255#203#165#150#255#203#165
+ +#150#255#203#165#150#255#203#165#150#255#203#165#150#255#203#165#150#255#203
+ +#165#150#255#203#165#150#255#203#165#150#255#163#132'x'#255#0#0#0#255#0#0#0
+ +#255#26#21#19#255',$!'#255'-%!'#255#156'~s'#255#203#165#150#255#203#165#150
+ +#255#203#165#150#255'@4/'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#4#3#3#255#186#151#138#255#203#165#150#255#203#165
+ +#150#255#203#165#150#255#203#165#150#255#203#165#150#255#203#165#150#255#203
+ +#165#150#255#203#165#150#255#203#165#150#255#203#165#150#255#203#165#150#255
+ +#203#165#150#255#203#165#150#255#203#165#150#255#203#164#149#255#195#152#132
+ +#255#146'\D'#255'_3'#31#247'R3'#30#25#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'Z-'#30'"^4 '#252#155
+ +'cK'#255#196#153#136#255#206#169#155#255#207#171#156#255#207#171#156#255#207
+ +#171#156#255#207#171#156#255#207#171#156#255#207#171#156#255#207#171#156#255
+ +#207#171#156#255#203#167#152#255#0#0#0#255#0#0#0#255#193#159#145#255#207#171
+ +#156#255#207#171#156#255#207#171#156#255#207#171#156#255#207#171#156#255#207
+ +#171#156#255'E94'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#15#12#11#255#182#150#137#255#207#171#156#255#207#171#156#255#207#171#156
+ +#255#207#171#156#255#207#171#156#255#207#171#156#255#207#171#156#255#207#171
+ +#156#255#207#171#156#255#207#171#156#255#207#171#156#255#207#171#156#255#207
+ +#171#156#255#207#171#156#255#206#170#155#255#201#162#145#255#178'}f'#255'h<('
+ +#250'[0'#28#129#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0']1'#29#130'f:&'#250#171'u'
+ +'^'#255#202#164#148#255#210#176#163#255#210#177#164#255#210#177#164#255#210
+ +#177#164#255#210#177#164#255#210#177#164#255#210#177#164#255#210#177#164#255
+ +#210#177#164#255#2#1#1#255#27#22#21#255#210#177#164#255#210#177#164#255#210
+ +#177#164#255#210#177#164#255#210#177#164#255#210#177#164#255#210#177#164#255
+ +#210#177#164#255'I=8'#255#6#5#4#255#0#0#0#255#0#0#0#255#0#0#0#255'''!'#31#255
+ +#206#175#162#255#210#177#164#255#210#177#164#255#210#177#164#255#210#177#164
+ +#255#210#177#164#255#210#177#164#255#210#177#164#255#210#177#164#255#210#177
+ +#164#255#210#177#164#255#210#177#164#255#210#177#164#255#210#177#164#255#210
+ +#177#164#255#210#176#163#255#206#170#155#255#188#139'w'#255'zI4'#252'^2'#29
+ +#222']/'#23#11#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'^1'#29#181'oA-'
+ +#249#182#132'n'#255#208#173#159#255#213#182#169#255#213#183#170#255#213#183
+ +#170#255#213#183#170#255#213#183#170#255#213#183#170#255#213#183#170#255#213
+ +#183#170#255#12#10#9#255#159#136#127#255#213#183#170#255#213#183#170#255#213
+ +#183#170#255#213#183#170#255#213#183#170#255#213#183#170#255#213#183#170#255
+ +#213#183#170#255#213#183#170#255#139'xo'#255#0#0#0#255#0#0#0#255'% '#30#255
+ +#213#183#170#255#213#183#170#255#213#183#170#255#213#183#170#255#213#183#170
+ +#255#213#183#170#255#213#183#170#255#213#183#170#255#213#183#170#255#213#183
+ ,#170#255#213#183#170#255#213#183#170#255#213#183#170#255#213#183#170#255#213
+ +#183#170#255#213#183#170#255#211#178#165#255#196#152#134#255#136'T?'#254'`1 '
+ +#243'U+'#28'$'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'U+'#21#12
+ +']2'#30#218'zK5'#251#192#146#127#255#212#180#168#255#216#187#176#255#217#188
+ +#177#255#217#188#177#255#217#188#177#255#217#188#177#255#217#188#177#255#217
+ +#188#177#255'o`Z'#255#217#188#177#255#217#188#177#255#217#188#177#255#217#188
+ +#177#255#217#188#177#255#217#188#177#255#217#188#177#255#217#188#177#255#217
+ +#188#177#255#217#188#177#255#27#24#22#255#0#0#0#255#9#8#7#255#209#180#171#255
+ +#217#188#177#255#217#188#177#255#217#188#177#255#217#188#177#255#217#188#177
+ +#255#217#188#177#255#217#188#177#255#217#188#177#255#217#188#177#255#217#188
+ +#177#255#217#188#177#255#217#188#177#255#217#188#177#255#217#188#177#255#217
+ +#188#177#255#215#185#173#255#202#163#147#255#152'cM'#255'`5 '#252'X.'#27'B'#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'].'#23'!_'
+ +'3 '#241#135'V@'#254#197#155#137#255#215#185#173#255#219#193#183#255#220#194
+ +#184#255#220#194#184#255#220#194#184#255#220#194#184#255#220#194#184#255#220
+ +#194#184#255#220#194#184#255#220#194#184#255#220#194#184#255#220#194#184#255
+ +#220#194#184#255#220#194#184#255#220#194#184#255#220#194#184#255#220#194#184
+ +#255#220#194#184#255#4#4#4#255#13#11#11#255#197#173#164#255#220#194#184#255
+ +#220#194#184#255#220#194#184#255#220#194#184#255#220#194#184#255#220#194#184
+ +#255#220#194#184#255#220#194#184#255#220#194#184#255#220#194#184#255#220#194
+ +#184#255#220#194#184#255#220#194#184#255#220#194#184#255#220#194#183#255#218
+ +#190#179#255#205#169#154#255#165'pY'#255'b8$'#252'[/'#27'h'#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'Y1'#28'?_'
+ +'3!'#249#132'T?'#252#193#148#130#255#215#186#174#255#223#198#189#255#223#200
+ +#191#255#223#200#191#255#223#200#191#255#223#200#191#255#223#200#191#255#223
+ +#200#191#255#223#200#191#255#223#200#191#255#223#200#191#255#223#200#191#255
+ +#223#200#191#255#223#200#191#255#223#200#191#255#223#200#191#255#223#200#191
+ +#255#199#179#171#255#215#192#183#255#223#200#191#255#223#200#191#255#223#200
+ +#191#255#223#200#191#255#223#200#191#255#223#200#191#255#223#200#191#255#223
+ +#200#191#255#223#200#191#255#223#200#191#255#223#200#191#255#223#200#191#255
+ +#223#200#191#255#223#200#191#255#223#199#190#255#219#192#183#255#203#165#150
+ +#255#158'kS'#255'c9%'#251']0'#30#147#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'Z-'#25'3_3'#30
+ +#234'wI5'#250#185#138'v'#255#215#186#174#255#225#203#194#255#227#205#197#255
+ +#227#205#197#255#227#205#197#255#227#205#197#255#227#205#197#255#227#205#197
+ +#255#227#205#197#255#227#205#197#255#227#205#197#255#227#205#197#255#227#205
+ +#197#255#227#205#197#255#227#205#197#255#227#205#197#255#227#205#197#255#227
+ +#205#197#255#227#205#197#255#227#205#197#255#227#205#197#255#227#205#197#255
+ +#227#205#197#255#227#205#197#255#227#205#197#255#227#205#197#255#227#205#197
+ +#255#227#205#197#255#227#205#197#255#227#205#197#255#227#205#197#255#226#204
+ +#196#255#220#194#183#255#200#159#143#255#144'_H'#254'a6"'#253'\1'#30'y'#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'\3'#31#25'^2'#29#207'nB.'#249#175'~i'#255
+ +#213#182#169#255#225#202#193#255#230#209#203#255#230#211#205#255#230#211#205
+ +#255#230#211#205#255#230#211#205#255#230#211#205#255#230#211#205#255#230#211
+ +#205#255#230#211#205#255#230#211#205#255#230#211#205#255#230#211#205#255#230
+ +#211#205#255#230#211#205#255#230#211#205#255#230#211#205#255#230#211#205#255
+ +#230#211#205#255#230#211#205#255#230#211#205#255#230#211#205#255#230#211#205
+ +#255#230#211#205#255#230#211#205#255#230#211#205#255#230#211#205#255#230#210
+ +#204#255#227#205#198#255#219#191#181#255#193#149#131#255#131'R='#251'_4 '#247
+ +'Z0'#26'O'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'` '#8']0'
+ +#28#169'e:'''#250#148'aL'#255#196#153#136#255#220#193#183#255#229#209#202#255
+ +#233#216#210#255#234#216#211#255#234#216#211#255#234#216#211#255#234#216#211
+ +#255#234#216#211#255#234#216#211#255#234#216#211#255#234#216#211#255#234#216
+ +#211#255#234#216#211#255#234#216#211#255#234#216#211#255#234#216#211#255#234
+ +#216#211#255#234#216#211#255#234#216#211#255#234#216#211#255#234#216#211#255
+ +#234#216#211#255#234#216#211#255#234#216#211#255#233#216#211#255#231#212#206
+ ,#255#224#200#192#255#207#171#156#255#168'va'#255'rE1'#249'^3'#31#230'Y,'#28
+ +'.'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0'^1'#29'h`3'#31#237'nA/'#249#158'mW'#255#203#165#150#255#224#201#192
+ +#255#232#213#208#255#235#219#215#255#237#222#218#255#237#222#218#255#237#222
+ +#218#255#237#222#218#255#237#222#218#255#237#222#218#255#237#222#218#255#237
+ +#222#218#255#237#222#218#255#237#222#218#255#237#222#218#255#237#222#218#255
+ +#237#222#218#255#237#222#218#255#237#222#218#255#237#222#218#255#237#222#218
+ +#255#236#220#216#255#233#216#211#255#228#206#200#255#213#182#170#255#177#131
+ +'n'#255'}M:'#250'a6"'#253']1'#29#155'U1'#24#21#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'].'#23#11
+ +']1'#29'~`5!'#246'tF5'#249#166'u`'#255#202#164#148#255#221#195#186#255#230
+ +#210#203#255#234#218#213#255#238#224#220#255#240#227#224#255#240#227#225#255
+ +#240#227#225#255#240#227#225#255#240#227#225#255#240#227#225#255#240#227#225
+ +#255#240#227#225#255#240#227#225#255#240#227#225#255#240#227#225#255#239#225
+ +#222#255#236#220#215#255#232#213#207#255#225#203#194#255#210#176#164#255#183
+ +#138'u'#255#133'UA'#252'c9&'#254'^2'#30#178'\.'#26''''#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'U1'#24#21']0'#30#147'`7"'#251'jA-'#249#133'UA'
+ +#253#169'zf'#255#201#162#146#255#220#194#184#255#230#211#205#255#233#215#210
+ +#255#234#217#212#255#236#220#215#255#237#222#218#255#238#223#220#255#237#222
+ +#219#255#236#220#216#255#234#219#213#255#233#216#211#255#231#213#206#255#225
+ +#203#194#255#209#174#160#255#181#136'u'#255#145'`L'#255'sG4'#249'c9&'#255'_2'
+ +#30#198'].'#28'7'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0'U+'#28#18'\.'#27'^_1'#30#179'c7$'#248'h?,'#251#127
+ +'Q;'#251#148'dN'#255#163't_'#255#175#129'n'#255#186#143'~'#255#198#157#141
+ +#255#204#167#151#255#201#161#145#255#191#149#132#255#179#135'u'#255#167'ye'
+ +#255#153'iT'#255#136'WC'#254'pE2'#249'c9&'#255'_3'#31#212'Z/'#27'|].'#29','#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'U9'#28#9'\.'#26'N^0'#29#157'`'
+ +'4 '#203'c6#'#230'c7%'#249'd:('#255'f=*'#255'i?-'#252'g>+'#255'e;('#255'd9&'
+ +#253'b7$'#237'a5!'#214'_1'#30#180'\/'#26'lX,'#26#29#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0'`0 '#16'[1'#24'*].'#27'B]1'#29'4\3'#31#25'UU'#0#3#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#255#255#255#248#15#255
+ +#255#255#255#255#254#0#0#127#255#255#255#255#240#0#0#7#255#255#255#255#192#0
+ +#0#1#255#255#255#255#0#0#0#0#255#255#255#252#0#0#0#0'?'#255#255#248#0#0#0#0
+ +#31#255#255#240#0#0#0#0#7#255#255#192#0#0#0#0#3#255#255#128#0#0#0#0#1#255#255
+ +#128#0#0#0#0#0#255#255#0#0#0#0#0#0#127#254#0#0#0#0#0#0#127#252#0#0#0#0#0#0'?'
+ +#252#0#0#0#0#0#0#31#248#0#0#0#0#0#0#31#248#0#0#0#0#0#0#15#240#0#0#0#0#0#0#15
+ ,#240#0#0#0#0#0#0#7#224#0#0#0#0#0#0#7#224#0#0#0#0#0#0#7#224#0#0#0#0#0#0#3#192
+ +#0#0#0#0#0#0#3#192#0#0#0#0#0#0#3#192#0#0#0#0#0#0#1#192#0#0#0#0#0#0#1#192#0#0
+ +#0#0#0#0#1#128#0#0#0#0#0#0#1#128#0#0#0#0#0#0#1#128#0#0#0#0#0#0#1#128#0#0#0#0
+ +#0#0#1#128#0#0#0#0#0#0#1#128#0#0#0#0#0#0#1#192#0#0#0#0#0#0#1#192#0#0#0#0#0#0
+ +#1#192#0#0#0#0#0#0#1#192#0#0#0#0#0#0#1#192#0#0#0#0#0#0#3#192#0#0#0#0#0#0#3
+ +#224#0#0#0#0#0#0#3#224#0#0#0#0#0#0#7#224#0#0#0#0#0#0#7#224#0#0#0#0#0#0#7#240
+ +#0#0#0#0#0#0#15#240#0#0#0#0#0#0#15#248#0#0#0#0#0#0#31#248#0#0#0#0#0#0#31#252
+ +#0#0#0#0#0#0'?'#252#0#0#0#0#0#0#127#254#0#0#0#0#0#0#127#254#0#0#0#0#0#0#255
+ +#255#0#0#0#0#0#1#255#255#128#0#0#0#0#3#255#255#192#0#0#0#0#7#255#255#224#0#0
+ +#0#0#15#255#255#240#0#0#0#0#31#255#255#248#0#0#0#0'?'#255#255#254#0#0#0#0#127
+ +#255#255#255#0#0#0#1#255#255#255#255#192#0#0#7#255#255#255#255#240#0#0#31#255
+ +#255#255#255#254#0#0#255#255#255#255#255#255#248#31#255#255#255#255#255#255
+ +#255#255#255#255#255'('#0#0#0'0'#0#0#0'`'#0#0#0#1#0' '#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0'UUU'#3'333'#5'UUU'#6'III'#7'@@@'#8'@@@'#8'III'#7
+ +'UUU'#6'333'#5'UUU'#3#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'@@@'
+ +#4'@@@'#8'@@@'#16'DDD1BBBMCCC_FCCrDBB'#129'FDD'#133'CCCvCCCcDDDRDDD('#240'l@!'#252'qE!'
+ +#253'yJ$'#252#129'R&'#252#138'X)'#253#134'T('#253'}N%'#252'uG#'#252'oC"'#253
+ +'h=#'#248'Z>.'#230'OC;'#211'FEC'#198'DDC'#187'BBB|CCC&999'#9#0#0#0#1#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#2'<<<'#17'CCCWEED'#170'OB9'#211'd=&'#244'qE"'#253#137'V)'#253
+ +#164'h.'#255#186'y3'#255#194#130'5'#255#198#135'6'#255#203#140'7'#255#207#145
+ +'8'#255#205#143'7'#255#201#137'7'#255#196#132'6'#255#192#127'5'#255#177'r1'
+ +#255#152'_+'#254'{L%'#252'k?"'#251'[>-'#233'IEA'#203'EDD'#184'DDDq<<<'#30'@@'
+ +'@'#4#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0'@@@'#4'BBB#EDD'#146'KB<'#205'a='''#242'yK&'#252#166'i/'#255#192#128'6'
+ +#255#205#143'9'#255#217#159'<'#255#226#169'>'#255#230#173'>'#255#232#176'>'
+ +#255#235#180'?'#255#237#182'@'#255#236#181'?'#255#234#178'>'#255#231#175'>'
+ +#255#228#171'>'#255#223#165'<'#255#211#150':'#255#199#136'8'#255#182'v5'#255
+ +#146'\,'#253'k@"'#252'W?1'#227'GFE'#199'CCC'#171'???=@@@'#8#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'III'#7'DDD8ECB'#170'[>,'#234'sF$'
+ +#252#160'e0'#255#196#133';'#255#216#158'@'#255#227#170'A'#255#234#180'C'#255
+ +#241#189'D'#255#245#193'E'#255#246#195'F'#255#247#195'F'#255#247#196'E'#255
+ +#248#197'F'#255#248#197'E'#255#247#195'F'#255#247#194'F'#255#246#194'E'#255
+ +#244#192'E'#255#238#184'C'#255#230#176'C'#255#223#166'A'#255#207#147'='#255
+ +#182'w7'#255#138'V+'#253'h>#'#250'NA9'#215'CCC'#186'@@@[;;;'#13#0#0#0#1#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'@@@'#8'EEENGC?'#189'b;%'#245#139'W-'#253#190
+ +#127';'#255#212#153'B'#255#227#172'F'#255#239#186'I'#255#242#191'J'#255#244
+ +#193'K'#255#246#195'K'#255#247#196'K'#255#247#196'K'#255#247#196'L'#255#247
+ +#196'L'#255#247#196'L'#255#247#196'L'#255#247#196'L'#255#247#196'K'#255#247
+ +#196'K'#255#246#196'K'#255#245#195'J'#255#243#193'J'#255#242#190'J'#255#234
+ +#180'H'#255#221#165'E'#255#202#142'@'#255#173'o5'#255'oC$'#252'T?3'#225'CCC'
+ +#193'AAAy@@@'#16#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'+++'#6'DDD@K@<'#198'g<"'#250#154
+ +'a2'#254#200#141'B'#255#222#168'J'#255#234#183'N'#255#239#189'P'#255#242#192
+ +'P'#255#242#193'P'#255#243#193'P'#255#243#193'P'#255#243#193'P'#255#243#193
+ +'P'#255#243#193'P'#255#243#193'P'#255#243#193'P'#255#243#193'P'#255#243#193
+ ,'P'#255#243#193'P'#255#243#193'P'#255#243#193'P'#255#243#193'P'#255#242#193
+ +'P'#255#242#193'P'#255#241#191'P'#255#238#187'N'#255#229#176'L'#255#214#158
+ +'G'#255#183'y;'#255'yJ)'#252'[=,'#236'CCB'#195'EEEoFFF'#11#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'UUU'#3
+ +'CCC.J?;'#190'g=#'#252#167'k7'#255#205#147'H'#255#226#173'P'#255#235#186'T'
+ +#255#238#189'T'#255#239#190'U'#255#239#190'U'#255#239#190'U'#255#239#190'U'
+ +#255#239#190'U'#255#239#190'U'#255#191#152'D'#255'A4'#23#255'>1'#22#255'D6'
+ +#24#255'H9'#26#255'RA'#29#255#146's4'#255#228#182'Q'#255#239#190'U'#255#239
+ +#190'U'#255#239#190'U'#255#239#190'U'#255#239#190'U'#255#238#190'U'#255#237
+ +#187'T'#255#232#182'S'#255#217#162'M'#255#191#129'B'#255#132'R-'#253'[9('#240
+ +'DDD'#191'CCCW@@@'#8#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#1'>>>'#29'F@='#169'd9#'#250#165'i8'#255#208#151'L'#255
+ +#226#174'U'#255#233#184'Y'#255#235#186'Y'#255#235#187'Y'#255#235#187'Y'#255
+ +#235#187'Y'#255#235#187'Y'#255#235#187'Y'#255#235#187'Y'#255'<0'#23#255#1#1#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1#1#0#255#0#0#0#255#6
+ +#5#2#255'*!'#16#255'w^-'#255#227#181'W'#255#235#187'Y'#255#235#187'Y'#255#235
+ +#186'Y'#255#234#186'Y'#255#231#181'X'#255#218#164'Q'#255#194#133'E'#255'{J*'
+ +#252'U=/'#230'CCC'#186'EEE?@@@'#4#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0'333'#10'DAAw_9%'#244#150'^4'#254#204#148'N'#255#225#175
+ +'Y'#255#230#181'\'#255#231#183'\'#255#231#183'\'#255#231#183'\'#255#231#183
+ +'\'#255#231#183'\'#255#231#183'\'#255#231#183'\'#255'hR*'#255#1#1#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#1#1#0#255#1#1#0#255'*!'#17#255#164#130'B'#255#231#183'\'
+ +#255#231#183'\'#255#231#182']'#255#228#179'['#255#217#165'V'#255#185'|C'#255
+ +'nA'''#252'N>5'#219'CCC'#163'@@@'#20#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#128#128#128#2'@@@,W8*'#227#132'P/'#253#196#139'M'#255#220
+ +#170'['#255#226#179'_'#255#227#179'_'#255#227#179'_'#255#227#179'_'#255#227
+ +#179'_'#255#227#179'_'#255#227#179'_'#255#227#179'_'#255#227#179'_'#255#4#3#2
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1#1#0
+ +#255#7#6#3#255#178#141'J'#255#227#179'_'#255#227#179'_'#255#225#176'^'#255
+ +#211#158'U'#255#174'q?'#255'c9"'#252'GA>'#203'BBB]III'#7#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0'FFF'#11'H>:'#150'e:#'#252#186'~H'#255#214#164'\'
+ +#255#222#174'a'#255#223#175'b'#255#223#175'b'#255#223#175'b'#255#223#175'b'
+ +#255#223#175'b'#255#223#175'b'#255#223#175'b'#255#223#175'b'#255#188#148'S'
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#1#1#1#255#154'yC'#255#223#175'b'#255#223#175'a'#255
+ +#220#171'`'#255#204#150'U'#255#145'Y5'#254'Y8('#238'CCC'#175'FFF'#29#0#0#0#1
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'UUU'#3'AAA3Z7'''#236#148'\6'#255#207#154'Z'
+ +#255#218#170'b'#255#219#171'd'#255#219#171'd'#255#219#171'd'#255#219#171'd'
+ +#255#219#171'd'#255#219#171'd'#255#219#171'd'#255#219#171'd'#255#219#171'd'
+ +#255#211#165'`'#255#6#5#3#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#2#2#1#255#219#171'd'#255#219
+ +#171'd'#255#219#171'd'#255#215#166'`'#255#189#129'M'#255'h=$'#252'H>;'#207'E'
+ +'EEhIII'#7#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'III'#7'K<5'#137'h;$'#252#188#130
+ +'O'#255#213#164'b'#255#215#167'd'#255#215#167'd'#255#215#167'd'#255#215#167
+ +'d'#255#215#167'd'#255#215#167'd'#255#215#167'd'#255#215#167'd'#255#215#167
+ +'d'#255#215#167'd'#255#215#167'd'#255#168#130'N'#255#1#1#1#255#0#0#0#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#200#155']'#255#215#167'd'#255#215#167'd'#255#215#166'd'#255#205#153']'
+ +#255#153'`:'#255'[6$'#243'CCC'#164';;;'#13#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'7'
+ +'77'#14'Z5%'#229#150'[8'#255#203#150'^'#255#211#162'e'#255#211#162'e'#255#211
+ +#162'e'#255#211#162'e'#255#211#162'e'#255#211#162'e'#255#211#162'e'#255#211
+ +#162'e'#255#211#162'e'#255#211#162'e'#255#211#162'e'#255#211#162'e'#255#211
+ +#162'e'#255#142'mD'#255#1#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#1#1#0#255#145'pF'#255#211#162'e'#255#211#162
+ +'e'#255#211#162'e'#255#210#159'd'#255#189#131'R'#255'f9#'#252'I@;'#202'===.'
+ +#128#128#128#2#0#0#0#0#0#0#0#0#128#128#128#2'D??4]3'#30#252#181'yM'#255#206
+ +#155'd'#255#207#157'f'#255#207#157'f'#255#207#157'f'#255#207#157'f'#255#205
+ +#155'f'#255'S?('#255#1#1#1#255#1#0#0#255#3#2#1#255#15#11#7#255#169#128'S'#255
+ ,#207#157'f'#255#207#157'f'#255#207#157'f'#255#16#12#8#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1#0#0#255#186#141'\'
+ +#255#207#157'f'#255#207#157'f'#255#207#157'f'#255#207#157'e'#255#201#148'`'
+ +#255#135'O0'#254'R9-'#226'BBBeIII'#7#0#0#0#0#0#0#0#0'UUU'#6'O8/'#141'o>'''
+ +#251#193#139'['#255#203#151'e'#255#203#152'e'#255#203#152'e'#255#203#152'e'
+ +#255#203#152'e'#255#23#17#11#255#1#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0
+ +#0#255#1#1#1#255#153'rL'#255#203#152'e'#255#203#152'e'#255',!'#22#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1#0#0#255' '#24#16
+ +#255#203#152'e'#255#203#152'e'#255#203#152'e'#255#203#152'e'#255#203#152'e'
+ +#255#202#150'd'#255#165'jC'#255'\3!'#247'DDD'#151'MMM'#10#0#0#0#0#0#0#0#0'@@'
+ +'@'#8'Z6%'#206#142'T5'#255#195#142'a'#255#198#145'c'#255#198#145'c'#255#198
+ +#145'c'#255#198#145'c'#255'W@,'#255#1#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255'%'#27#19#255#198#145'c'#255#198#145'c'#255'U>+'
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1#0#0#255#1#1#1#255#27#20#13#255'vW;'
+ +#255#198#145'c'#255#198#145'c'#255#198#145'c'#255#198#145'c'#255#198#145'c'
+ +#255#198#145'c'#255#198#145'c'#255#184'}S'#255'`4 '#252'FA>'#183'@@@'#12#0#0
+ +#0#0#0#0#0#0'999'#9']2'#30#243#166'gD'#255#192#138'`'#255#192#139'a'#255#192
+ +#139'a'#255#192#139'a'#255#190#137'a'#255#1#1#1#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#8#6#4#255#192#139'a'#255#192#139
+ +'a'#255#129']B'#255#1#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1#0#0#255'Q;)'#255#192#139'a'
+ +#255#192#139'a'#255#192#139'a'#255#192#139'a'#255#192#139'a'#255#192#139'a'
+ +#255#192#139'a'#255#192#139'a'#255#192#139'a'#255#192#139'a'#255#188#132'['
+ +#255'u@'''#252'M;3'#212'999'#18#0#0#0#0#0#0#0#0'FFF'#11'^1'#29#250#174'oK'
+ +#255#186#131'\'#255#186#131'\'#255#186#131'\'#255#186#131'\'#255'vS:'#255#1#1
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1#0#0#255
+ +'S:)'#255#186#131'\'#255#186#131'\'#255#184#129'\'#255'('#28#20#255#1#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255'Q9('#255#186#131'\'#255#186#131'\'#255#186#131'\'#255#186#131'\'#255#186
+ +#131'\'#255#186#131'\'#255#186#131'\'#255#186#131'\'#255#186#131'\'#255#186
+ +#131'\'#255#186#131'\'#255#186#130'['#255#131'I-'#255'Q9-'#221'FFF!'#0#0#0#1
+ +#0#0#0#0'M33'#20'_2'#30#251#173'pN'#255#180'{X'#255#180'{X'#255#180'{X'#255
+ +#180'{X'#255'-'#30#22#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#2#1#1#255'dE1'#255#180'{X'#255#180'{X'#255#180'{X'#255#180'{X'#255
+ +#180'{X'#255'O6&'#255#2#1#1#255#1#1#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255'G0#'#255#180'{X'#255#180'{X'#255#178'{X'#255'hH3'#255'U:)'#255
+ +'mK5'#255#180'{X'#255#180'{X'#255#180'{X'#255#180'{X'#255#180'{X'#255#180'{X'
+ +#255#180'{X'#255#139'P3'#255'U7)'#231'BBB2UUU'#3#0#0#0#0'T1&,c5 '#249#174'rQ'
+ +#255#178'wW'#255#178'wW'#255#178'wW'#255#178'wW'#255#8#5#4#255#0#0#0#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#1#0#0#255#27#18#13#255#164'nQ'#255#178'wW'#255#178
+ +'wW'#255#178'wW'#255#178'wW'#255#178'wW'#255#178'wW'#255#178'wW'#255#178'wW'
+ +#255#142'_F'#255'H0#'#255#20#13#10#255#25#16#12#255'9'''#28#255'lI5'#255#178
+ +'wW'#255#178'wW'#255'kG4'#255#1#1#1#255#1#1#0#255#1#0#0#255#1#0#0#255#3#2#1
+ +#255'zQ<'#255#178'wW'#255#178'wW'#255#178'wW'#255#178'wW'#255#178'wW'#255#149
+ +'W9'#255'Z5%'#238'DDD-'#128#128#128#2#0#0#0#0'Y3 Bj8#'#248#173'qS'#255#175't'
+ +'W'#255#175'tW'#255#175'tW'#255#175'tW'#255#1#0#0#255#1#1#1#255#0#0#0#255#0#0
+ +#0#255#5#3#3#255'cB2'#255#175'tW'#255#175'tW'#255#175'tW'#255#175'tW'#255#175
+ +'tW'#255#175'tW'#255#175'tW'#255#175'tW'#255#175'tW'#255#175'tW'#255#175'tW'
+ +#255#175'tW'#255#175'tW'#255#175'tW'#255#175'tW'#255#175'tW'#255#175'tW'#255
+ +#173'rU'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#2#1
+ +#1#255#152'eL'#255#175'tW'#255#175'tW'#255#175'tW'#255#175'tW'#255#155'[>'
+ +#255'\4"'#244'@@@'#28#0#0#0#1#0#0#0#0'X0!3g7"'#246#172'oR'#255#174'rV'#255
+ +#174'rV'#255#174'rV'#255#166'lR'#255#7#5#3#255#131'VA'#255#155'fM'#255'oI7'
+ +#255#174'rV'#255#174'rV'#255#174'rV'#255#174'rV'#255#174'rV'#255#174'rV'#255
+ +#174'rV'#255#174'rV'#255#174'rV'#255#174'rV'#255#174'rV'#255#174'rV'#255#174
+ +'rV'#255#174'rV'#255#174'rV'#255#174'rV'#255#174'rV'#255#174'rV'#255#174'rV'
+ +#255#153'dL'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255'<'''#29#255#174'rV'#255#174'rV'#255#174'rV'#255#173'qU'#255#151'Y'
+ +'='#255']6%'#239'333'#15#0#0#0#0#0#0#0#0'O1'''#25'b3'#31#247#168'jN'#255#172
+ +'oU'#255#172'oU'#255#172'oU'#255#172'oU'#255#172'oU'#255#172'oU'#255#172'oU'
+ +#255#172'oU'#255#172'oU'#255#172'oU'#255#172'oU'#255#172'oU'#255#136'XD'#255
+ ,'U7*'#255'^=/'#255'kE5'#255#170'oU'#255#172'oU'#255#172'oU'#255#172'oU'#255
+ +#172'oU'#255#172'oU'#255#172'oU'#255#172'oU'#255#172'oU'#255#172'oU'#255#172
+ +'oU'#255#172'oU'#255#5#3#2#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255'!'#21#16#255#172'oU'#255#172'oU'#255#172'oU'#255#172'oT'#255
+ +#143'R7'#255'Y6('#225'@@@'#12#0#0#0#0#0#0#0#0'333'#5'_2'#31#248#167'hL'#255
+ +#172'qW'#255#172'qX'#255#172'qX'#255#172'qX'#255#172'qX'#255#172'qX'#255#172
+ +'qX'#255#172'qX'#255#172'qX'#255#172'qX'#255#172'qX'#255':&'#30#255#1#0#0#255
+ +#1#1#0#255#1#1#1#255#1#1#0#255#4#2#2#255#133'WD'#255#172'qX'#255#172'qX'#255
+ +#172'qX'#255#172'qX'#255#172'qX'#255#172'qX'#255#172'qX'#255#172'qX'#255#172
+ +'qX'#255#172'qX'#255'E.$'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#30#20#15#255#172'qX'#255#172'qX'#255#172'qX'#255#172'pV'#255
+ +#134'K2'#255'V8)'#199'999'#9#0#0#0#0#0#0#0#0#0#0#0#1'_3'#30#239#164'fJ'#255
+ +#175'w]'#255#175'w^'#255#175'w^'#255#175'w^'#255#175'w^'#255#175'w^'#255#175
+ +'w^'#255#175'w^'#255#175'w^'#255#175'w^'#255'hF7'#255#1#0#0#255#0#0#0#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#7#5#4#255#175'w^'#255#175'w^'#255'{TB'
+ +#255'X;/'#255']?2'#255#127'VD'#255#175'w^'#255#175'w^'#255#175'w^'#255#175'w'
+ +'^'#255#165'qY'#255#1#1#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1#1#1
+ +#255'fF7'#255#175'w^'#255#175'w^'#255#175'w^'#255#175'v\'#255'{D-'#253'S5('
+ +#154'333'#5#0#0#0#0#0#0#0#0#0#0#0#0'a3'#30#200#149'Z?'#255#179'|c'#255#179'}'
+ +'e'#255#179'}e'#255#179'}e'#255#179'}e'#255#179'}e'#255#179'}e'#255#179'}e'
+ +#255#179'}e'#255#179'}e'#255#19#13#11#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#2#1#1#255#179'}e'#255'E0'''#255#1#0#0#255#1#1#0#255
+ +#1#1#0#255#0#0#0#255'R:/'#255#179'}e'#255#179'}e'#255#179'}e'#255#179'}e'#255
+ +'.!'#26#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1#1#1#255#177'}e'#255#179
+ +'}e'#255#179'}e'#255#179'}e'#255#175'v\'#255'g8$'#251'W7*O'#0#0#0#1#0#0#0#0#0
+ +#0#0#0#0#0#0#0'[0'#29'lyD-'#249#181#128'i'#255#183#131'l'#255#183#131'l'#255
+ +#183#131'l'#255#183#131'l'#255#183#131'l'#255#183#131'l'#255#183#131'l'#255
+ +#183#131'l'#255#183#131'l'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255'"'#25#20#255#183#131'l'#255#0#0#0#255#0#0#0#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255'B/'''#255#183#131'l'#255#183#131'l'#255
+ +#183#131'l'#255#169'yd'#255#1#1#1#255#0#0#0#255#0#0#0#255#0#0#0#255'#'#25#21
+ +#255#183#131'l'#255#183#131'l'#255#183#131'l'#255#183#131'l'#255#167'lQ'#255
+ +'^3'#31#248'@@@'#12#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'Y1'#30#26'b5 '#244#178'z'
+ +'c'#255#187#138't'#255#187#138'u'#255#187#138'u'#255#187#138'u'#255#187#138
+ +'u'#255#187#138'u'#255#187#138'u'#255#187#138'u'#255#187#138'u'#255#2#2#1#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1#1#0#255#170'~j'#255#177
+ +#130'o'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#4#3#3
+ +#255#187#138'u'#255#187#138'u'#255#187#138'u'#255#187#138'u'#255'jNB'#255#11
+ +#8#7#255#0#0#0#255#0#0#0#255#152'p`'#255#187#138'u'#255#187#138'u'#255#187
+ +#138'u'#255#186#136'r'#255#144'W?'#255']6#'#193'333'#5#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0'`4'#31#217#160'gN'#255#190#143'{'#255#191#145'}'#255#191
+ +#145'}'#255#191#145'}'#255#191#145'}'#255#191#145'}'#255#191#145'}'#255#191
+ +#145'}'#255#191#145'}'#255#19#14#12#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255'7*$'#255#191#145'}'#255#164'|k'#255#1#1#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#2#2#1#255#191#145'}'#255#191#145'}'#255
+ +#191#145'}'#255#191#145'}'#255#191#145'}'#255#191#145'}'#255#0#0#0#255#30#23
+ +#20#255#191#145'}'#255#191#145'}'#255#191#145'}'#255#191#145'}'#255#187#138
+ +'t'#255'p>('#249'Y2#U'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27
+ +'huB+'#244#190#142'z'#255#195#152#132#255#195#152#132#255#195#152#132#255#195
+ +#152#132#255#195#152#132#255#195#152#132#255#195#152#132#255#195#152#132#255
+ +'A3,'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1#0#0#255#183#142'|'#255
+ +#195#152#132#255#138'k]'#255#1#1#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#9#7#6#255#195#152#132#255#195#152#132#255#195#152#132#255#195
+ +#152#132#255#195#152#132#255#195#152#132#255#1#1#1#255#160'}m'#255#195#152
+ +#132#255#195#152#132#255#195#152#132#255#194#150#131#255#167'pW'#255'`4 '#240
+ +'M33'#10#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'@@'#0#4'`3'#30#229
+ +#164'nU'#255#197#156#137#255#199#159#141#255#199#159#141#255#199#159#141#255
+ +#199#159#141#255#199#159#141#255#199#159#141#255#199#159#141#255'x`U'#255#1#1
+ +#1#255#0#0#0#255#0#0#0#255#0#0#0#255#18#14#13#255#199#159#141#255#199#159#141
+ +#255' '#26#23#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1#1#0#255
+ +#139'oc'#255#199#159#141#255#199#159#141#255#199#159#141#255#199#159#141#255
+ +#199#159#141#255#199#159#141#255'^KC'#255#199#159#141#255#199#159#141#255#199
+ +#159#141#255#199#159#141#255#192#147#127#255'rB-'#249'\1 k'#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'\.'#28'Sn>('#243#194#149#131
+ ,#255#202#165#148#255#203#165#149#255#203#165#149#255#203#165#149#255#203#165
+ +#149#255#203#165#149#255#203#165#149#255#169#138'|'#255#0#0#0#255#1#1#1#255
+ +#16#13#11#255#23#19#17#255#171#139'~'#255#203#165#149#255#203#165#149#255#3#3
+ +#2#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1#0#0#255'*"'#31#255#203#165
+ +#149#255#203#165#149#255#203#165#149#255#203#165#149#255#203#165#149#255#203
+ +#165#149#255#203#165#149#255#203#165#149#255#203#165#149#255#203#165#149#255
+ +#203#165#149#255#201#162#145#255#163'mU'#255'_3'#31#227'U'#0#0#3#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'a3'#30#213#153
+ +'eM'#254#204#167#151#255#207#172#158#255#207#172#158#255#207#172#158#255#207
+ +#172#158#255#207#172#158#255#207#172#158#255#205#170#156#255#0#0#0#255'<1.'
+ +#255#207#172#158#255#207#172#158#255#207#172#158#255#207#172#158#255#207#172
+ +#158#255#20#16#15#255#1#0#0#255#0#0#0#255#0#0#0#255#1#0#0#255'?40'#255#207
+ +#172#158#255#207#172#158#255#207#172#158#255#207#172#158#255#207#172#158#255
+ +#207#172#158#255#207#172#158#255#207#172#158#255#207#172#158#255#207#172#158
+ +#255#207#172#158#255#207#171#156#255#192#147#127#255'k<'''#244'Z.'#29'L'#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +'^/'#27'&b5!'#240#174'{f'#255#209#176#162#255#212#180#167#255#212#180#167#255
+ +#212#180#167#255#212#180#167#255#212#180#167#255#212#180#167#255#6#5#5#255
+ +#179#151#140#255#212#180#167#255#212#180#167#255#212#180#167#255#212#180#167
+ +#255#212#180#167#255#212#180#167#255'gXR'#255#0#0#0#255#0#0#0#255'gXR'#255
+ +#212#180#167#255#212#180#167#255#212#180#167#255#212#180#167#255#212#180#167
+ +#255#212#180#167#255#212#180#167#255#212#180#167#255#212#180#167#255#212#180
+ +#167#255#212#180#167#255#211#179#166#255#202#162#146#255#127'M7'#248'`2'#31
+ +#169#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0'[/'#26'Fg:#'#242#190#145#127#255#214#184#172#255#216
+ +#187#176#255#216#187#176#255#216#187#176#255#216#187#176#255#216#187#176#255
+ +'k]X'#255#216#187#176#255#216#187#176#255#216#187#176#255#216#187#176#255#216
+ +#187#176#255#216#187#176#255#216#187#176#255'E<8'#255#0#0#0#255'>63'#255#216
+ +#187#176#255#216#187#176#255#216#187#176#255#216#187#176#255#216#187#176#255
+ +#216#187#176#255#216#187#176#255#216#187#176#255#216#187#176#255#216#187#176
+ +#255#216#187#176#255#216#187#175#255#210#176#163#255#147'_H'#252'`4'#31#210
+ +'U++'#6#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'\0'#29'trB-'#242#198#157#140#255#218#191
+ +#180#255#221#195#185#255#221#195#185#255#221#195#185#255#221#195#185#255#221
+ +#195#185#255#221#195#185#255#221#195#185#255#221#195#185#255#221#195#185#255
+ +#221#195#185#255#221#195#185#255#221#195#185#255',''%'#255'920'#255#221#195
+ +#185#255#221#195#185#255#221#195#185#255#221#195#185#255#221#195#185#255#221
+ +#195#185#255#221#195#185#255#221#195#185#255#221#195#185#255#221#195#185#255
+ +#221#195#185#255#220#194#184#255#213#183#170#255#162'oW'#255'b5 '#232'].'#23
+ +#22#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'_1'#30#138'l>)'#242#187#143'|'
+ +#255#221#196#186#255#225#202#193#255#225#203#194#255#225#203#194#255#225#203
+ +#194#255#225#203#194#255#225#203#194#255#225#203#194#255#225#203#194#255#225
+ +#203#194#255#225#203#194#255#225#203#194#255#225#203#194#255#225#203#194#255
+ +#225#203#194#255#225#203#194#255#225#203#194#255#225#203#194#255#225#203#194
+ +#255#225#203#194#255#225#203#194#255#225#203#194#255#225#203#194#255#225#203
+ +#194#255#224#201#192#255#212#180#168#255#149'aK'#252'a5!'#230']2'#25')'#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#28'\d9$'#241#172
+ +'|h'#255#222#197#187#255#228#206#200#255#230#209#203#255#230#209#203#255#230
+ +#209#203#255#230#209#203#255#230#209#203#255#230#209#203#255#230#209#203#255
+ +#230#209#203#255#230#209#203#255#230#209#203#255#230#209#203#255#230#209#203
+ +#255#230#209#203#255#230#209#203#255#230#209#203#255#230#209#203#255#230#209
+ +#203#255#230#209#203#255#230#209#203#255#229#209#202#255#226#204#197#255#208
+ +#173#159#255#131'R;'#245'a3'#31#207'Y3'#26#20#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'].'#28'7a5!'#236#137'WB'#248#201
+ +#163#148#255#229#210#202#255#233#215#210#255#234#217#212#255#234#217#212#255
+ +#234#217#212#255#234#217#212#255#234#217#212#255#234#217#212#255#234#217#212
+ +#255#234#217#212#255#234#217#212#255#234#217#212#255#234#217#212#255#234#217
+ +#212#255#234#217#212#255#234#217#212#255#234#217#212#255#234#216#211#255#231
+ +#212#206#255#221#195#185#255#174#128'm'#255'm>*'#242'`1'#29#163'f33'#5#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ ,#0#0#0#0#0'b'''#20#13'`2'#29#140'd8$'#241#151'hR'#251#211#179#167#255#233#215
+ +#210#255#236#220#215#255#237#222#219#255#238#225#221#255#238#225#221#255#238
+ +#225#221#255#238#225#221#255#238#225#221#255#238#225#221#255#238#225#221#255
+ +#238#225#221#255#238#225#221#255#238#223#220#255#236#221#217#255#234#219#213
+ +#255#227#205#198#255#188#146#128#255'wH2'#242'b5 '#219'].'#27'B'#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'X1'#29#26'a3'#30#168'f:$'#242#134'T?'
+ +#246#179#136'v'#255#214#183#172#255#235#218#214#255#238#225#221#255#239#226
+ +#223#255#240#227#224#255#240#227#225#255#240#227#225#255#239#226#223#255#239
+ +#225#222#255#238#224#220#255#226#204#196#255#199#161#145#255#158'o['#254'rD-'
+ +#239'b4"'#232'^2'#30'\'#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0'`+ '#24']/'#30'fd6#'#197'c8#'#243'vE0'#240#140'ZF'
+ +#247#156'mY'#255#171#127'm'#255#184#143#127#255#178#136'v'#255#164'wd'#255
+ +#148'dP'#252#130'Q;'#243'l<('#239'b6"'#234'b5!'#151'Z-'#29'>UU'#0#3#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0'].'#23#11'Z/'#29'G^4 fa4!'#130'd6!'#166'd7#'#194
+ +'d7"'#182'c6"'#150'_3'#31's\0'#29'YY/'#30'+'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#255#255#224#3#255#255#255
+ +#255#255#254#0#0#127#255#255#255#255#248#0#0#31#255#255#255#255#224#0#0#7#255
+ +#255#255#255#192#0#0#3#255#255#255#255#128#0#0#1#255#255#255#255#0#0#0#0#127
+ +#255#255#254#0#0#0#0#127#255#255#252#0#0#0#0'?'#255#255#248#0#0#0#0#31#255
+ +#255#240#0#0#0#0#15#255#255#240#0#0#0#0#15#255#255#224#0#0#0#0#7#255#255#224
+ +#0#0#0#0#3#255#255#192#0#0#0#0#3#255#255#192#0#0#0#0#3#255#255#192#0#0#0#0#1
+ +#255#255#128#0#0#0#0#1#255#255#128#0#0#0#0#1#255#255#128#0#0#0#0#1#255#255
+ +#128#0#0#0#0#1#255#255#128#0#0#0#0#0#255#255#128#0#0#0#0#0#255#255#128#0#0#0
+ +#0#0#255#255#128#0#0#0#0#0#255#255#128#0#0#0#0#1#255#255#128#0#0#0#0#1#255
+ +#255#128#0#0#0#0#1#255#255#128#0#0#0#0#1#255#255#192#0#0#0#0#1#255#255#192#0
+ +#0#0#0#3#255#255#192#0#0#0#0#3#255#255#224#0#0#0#0#7#255#255#224#0#0#0#0#7
+ +#255#255#224#0#0#0#0#15#255#255#240#0#0#0#0#15#255#255#248#0#0#0#0#31#255#255
+ +#248#0#0#0#0'?'#255#255#252#0#0#0#0'?'#255#255#254#0#0#0#0#127#255#255#255#0
+ +#0#0#0#255#255#255#255#128#0#0#1#255#255#255#255#192#0#0#3#255#255#255#255
+ +#224#0#0#15#255#255#255#255#248#0#0#31#255#255#255#255#254#0#0#127#255#255
+ +#255#255#255#192#7#255#255#255#255#255#255#255#255#255#255#255#255'('#0#0#0
+ +' '#0#0#0'@'#0#0#0#1#0' '#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#2'CCC'#19'FFF'#22'UUU'#3#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0'@@@'#12'EAAGDDB'#133'DDC'#181'HC?'#205'LA;'#213
+ +'JB='#212'FC@'#204'EED'#185'DDC'#145'DDDSFFF'#22#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'III'#14'EEBoLA;'#208'eE-'#235'xK('
+ +#246#131'R)'#250#139'W*'#251#149'_,'#252#145'\+'#252#136'V*'#250#128'Q('#249
+ +'rI)'#244'\D2'#227'FB?'#207'CCC'#134'DDD'#30#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0'EEENMA9'#206'oF)'#245#147']-'#252#187'}4'#255#211#150'9'#255#224
+ +#167';'#255#230#174'='#255#234#179'>'#255#233#178'>'#255#228#171'='#255#221
+ +#163'<'#255#205#143'8'#255#175'r2'#255#131'R*'#250'eC,'#238'FB?'#205'CCCoUUU'
+ +#3#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0'@@@'#4'GEA|dB+'#239#142'[.'#252#198#137'<'#255#227#172'C'#255
+ +#236#183'E'#255#242#190'F'#255#246#195'G'#255#248#198'G'#255#249#199'H'#255
+ +#249#198'H'#255#247#196'G'#255#245#193'G'#255#240#188'F'#255#234#180'D'#255
+ +#220#163'A'#255#183'y8'#255'}O*'#250'WA4'#225'CCC'#152'<<<'#17#0#0#0#0#0#0#0
+ ,#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'G@='#148
+ +'lD*'#245#175'u8'#254#221#166'I'#255#234#182'M'#255#242#193'P'#255#243#194'O'
+ +#255#244#195'O'#255#244#195'P'#255#244#195'P'#255#244#195'P'#255#244#195'P'
+ +#255#244#195'P'#255#244#195'P'#255#243#194'O'#255#243#194'O'#255#240#190'O'
+ +#255#230#179'L'#255#212#155'F'#255#148'^1'#252'`A.'#234'CCC'#171'@@@'#12#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'FA>vmB)'#247#189
+ +#130'A'#255#224#172'P'#255#236#187'U'#255#238#189'W'#255#238#190'V'#255#238
+ +#190'V'#255#238#190'V'#255'fQ%'#255#17#14#6#255#17#13#6#255#16#13#6#255',#'
+ +#16#255#155'|8'#255#238#190'V'#255#238#190'V'#255#238#189'V'#255#238#189'W'
+ +#255#233#184'U'#255#217#163'M'#255#164'l8'#254'_>+'#238'DDD'#147#128#128#128
+ +#2#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'FDD=e?*'#243#183'}B'#255
+ +#223#171'W'#255#232#183'['#255#232#183'\'#255#232#183'\'#255#232#183'\'#255
+ +#232#183'\'#255'>1'#25#255#1#1#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#1#1#1#255#5#4#2#255#22#17#9#255'pX,'#255#218#171'V'#255#232#183'\'#255#230
+ +#182'['#255#217#164'T'#255#152'a7'#252'V=1'#228'DDDb'#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#128#128#128#2'Z<-'#215#163'k='#254#217#166'['#255#226#178'`'
+ +#255#226#179'a'#255#226#179'a'#255#226#179'a'#255#226#179'a'#255#226#179'a'
+ +#255#5#4#2#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#3#3#1#255',#'#19#255#226#179'a'#255#225#177'_'
+ +#255#208#154'T'#255#129'O1'#251'H?;'#205'@@@'#20#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0'J@<[vF,'#249#206#153'Y'#255#220#172'b'#255#220#172'c'#255#220#172'c'#255
+ +#220#172'c'#255#220#172'c'#255#220#172'c'#255#205#160']'#255#4#3#2#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#1#0#0#255'.$'#21#255#220#172'c'#255#218#170'a'#255#190#132
+ +'N'#255'c=)'#242'CCCz'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'\9('#218#177'vG'#255
+ +#213#164'c'#255#214#166'e'#255#214#166'e'#255#214#166'e'#255#214#166'e'#255
+ +#214#166'e'#255#214#166'e'#255#214#166'e'#255'v\8'#255#2#2#1#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#11#9#5#255#214#166'e'#255#214#166'e'#255#209#159'a'#255#139'Y'
+ +'6'#252'K>7'#206'333'#5#0#0#0#0#0#0#0#0'?;9'#19'mA+'#247#201#148'^'#255#209
+ +#159'e'#255#209#159'e'#255#209#159'e'#255#146'oF'#255#18#14#9#255#21#16#10
+ +#255'O<&'#255#209#159'e'#255#209#159'e'#255'$'#27#17#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#11#8#5#255#209#159'e'#255#209#159'e'#255#208#158'e'#255#185#128'Q'#255
+ +'^9)'#240'BBB6'#0#0#0#0#0#0#0#0'P8-q'#144'Z:'#252#201#150'd'#255#202#151'd'
+ +#255#202#151'd'#255'uW:'#255#2#1#1#255#0#0#0#255#0#0#0#255#1#0#0#255'-!'#22
+ +#255#202#151'd'#255'ZC-'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#1#1#0#255#5#4#3#255'gM3'#255#202#151'd'
+ +#255#202#151'd'#255#202#151'd'#255#197#145'`'#255'l@*'#248'CCBo'#0#0#0#0#0#0
+ +#0#0'^7$'#194#171'pK'#255#194#140'a'#255#194#140'a'#255#194#140'a'#255#6#4#3
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#7#5#4#255#194#140'a'#255#139'eE'
+ +#255#1#1#1#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#13
+ +#9#6#255'wV<'#255#192#138'a'#255#194#140'a'#255#194#140'a'#255#194#140'a'#255
+ +#194#140'a'#255#193#140'a'#255#137'T7'#252'K=6'#158#0#0#0#0#0#0#0#0'a6#'#220
+ +#177'uQ'#255#185#129'['#255#185#129'['#255#127'Y>'#255#1#1#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#2#1#1#255'8'''#27#255#185#129'['#255#185#129'['#255'+'#30
+ +#21#255#2#1#1#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#13#9#6#255#179'}Y'
+ +#255#185#129'['#255#185#129'['#255#185#129'['#255#185#129'['#255#185#129'['
+ +#255#185#129'['#255#185#129'['#255#152'^>'#255'P:1'#190#0#0#0#0#0#0#0#0'c7#'
+ +#227#175'sS'#255#178'xW'#255#178'xW'#255','#30#21#255#0#0#0#255#0#0#0#255#0#0
+ +#0#255#5#4#3#255'uO:'#255#178'xW'#255#178'xW'#255#178'xW'#255#178'xW'#255'xP'
+ +':'#255'('#26#19#255#10#7#5#255#10#7#5#255#28#19#13#255#168'rS'#255#163'nO'
+ +#255#25#17#12#255#6#4#3#255#17#11#8#255'bB/'#255#178'xW'#255#178'xW'#255#178
+ +'xW'#255#158'aB'#255'V9,'#210#0#0#0#0#0#0#0#0'f7"'#227#173'sT'#255#175'tW'
+ +#255#175'tW'#255#15#10#7#255#13#8#6#255#5#4#3#255'+'#29#21#255#169'pU'#255
+ +#175'tW'#255#175'tW'#255#175'tW'#255#175'tW'#255#175'tW'#255#175'tW'#255#175
+ +'tW'#255#175'tW'#255#175'tW'#255#175'tW'#255#175'tW'#255#17#11#8#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#2#2#1#255#136'ZD'#255#175'tW'#255#175'tW'#255#161'd'
+ +'G'#255'[8('#211#0#0#0#0#0#0#0#0'e6"'#218#171'nR'#255#173'qV'#255#173'qV'#255
+ +#136'YC'#255#173'qV'#255#173'qV'#255#173'qV'#255#173'qV'#255#173'qV'#255'sK9'
+ +#255'uM:'#255#159'gN'#255#173'qV'#255#173'qV'#255#173'qV'#255#173'qV'#255#173
+ +'qV'#255#173'qV'#255#173'qV'#255'5"'#27#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0
+ +#0#255'H/$'#255#173'qV'#255#173'qV'#255#153'^D'#255'Y8*'#188#0#0#0#0#0#0#0#0
+ +'c5 '#203#170'kQ'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'
+ ,#255#174'sY'#255#164'mU'#255#11#7#6#255#1#1#1#255#1#1#1#255#5#3#2#255#127'TA'
+ +#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255
+ +#128'UA'#255#2#1#1#255#0#0#0#255#0#0#0#255#0#0#0#255'J1&'#255#174'sY'#255#174
+ +'sY'#255#147'X?'#255'S8,'#140#0#0#0#0#0#0#0#0'd4'#30#153#162'gM'#255#178'{c'
+ +#255#178'{c'#255#178'{c'#255#178'{c'#255#178'{c'#255#178'{c'#255'A-$'#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#20#14#11#255'xSB'#255#6#4#3#255#5#4#3
+ +#255#18#12#10#255#170'u_'#255#178'{c'#255#178'{c'#255#9#6#5#255#0#0#0#255#0#0
+ +#0#255#3#2#2#255#166's]'#255#178'{c'#255#178'{c'#255#131'P8'#252'S3$>'#0#0#0
+ +#0#0#0#0#0'[/'#27'3'#137'T='#247#184#134'o'#255#184#134'o'#255#184#134'o'#255
+ +#184#134'o'#255#184#134'o'#255#184#134'o'#255#14#10#9#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#1#1#1#255'\C7'#255#14#10#8#255#0#0#0#255#0#0#0#255#0#0#0#255#14#10
+ +#8#255#184#134'o'#255#184#134'o'#255'xWI'#255#2#1#1#255#0#0#0#255#18#14#11
+ +#255#184#134'o'#255#184#134'o'#255#183#131'l'#255'h:&'#240#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0'n<%'#218#189#140'x'#255#190#143'z'#255#190#143'z'#255#190#143
+ +'z'#255#190#143'z'#255#190#143'z'#255',!'#28#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#9#7#6#255#190#143'z'#255#9#7#6#255#0#0#0#255#0#0#0#255#0#0#0#255#5#4#3
+ +#255#190#143'z'#255#190#143'z'#255#190#143'z'#255#159'xe'#255#0#0#0#255#140
+ +'jZ'#255#190#143'z'#255#190#143'z'#255#175'yc'#255'b6"'#193#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0'd4'#30#151#167's\'#254#196#154#135#255#196#154#135#255#196#154
+ +#135#255#196#154#135#255#196#154#135#255'qYN'#255#0#0#0#255#0#0#0#255#1#1#1
+ +#255'v]R'#255#194#152#133#255#5#4#4#255#0#0#0#255#0#0#0#255#0#0#0#255#10#8#7
+ +#255#196#154#135#255#196#154#135#255#196#154#135#255#196#154#135#255'"'#27#24
+ +#255#196#154#135#255#196#154#135#255#196#154#135#255#131'R<'#248'^1'#28'1'#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#14'o>('#224#198#157#140#255#202#163#146
+ +#255#202#163#146#255#202#163#146#255#202#163#146#255#170#138'{'#255#0#0#0#255
+ +#8#6#6#255#26#21#19#255#202#163#146#255#143'th'#255#1#1#1#255#0#0#0#255#0#0#0
+ +#255#2#2#2#255#143'sg'#255#202#163#146#255#202#163#146#255#202#163#146#255
+ +#202#163#146#255#191#155#138#255#202#163#146#255#202#163#146#255#183#135'r'
+ +#255'd5 '#193#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'd3'#30'{'#156
+ +'jS'#248#209#174#160#255#209#174#160#255#209#174#160#255#209#174#160#255#209
+ +#174#160#255#2#2#2#255#205#172#158#255#209#174#160#255#209#174#160#255#169
+ +#140#129#255#11#9#9#255#1#1#0#255#4#3#3#255#132'oe'#255#209#174#160#255#209
+ +#174#160#255#209#174#160#255#209#174#160#255#209#174#160#255#209#174#160#255
+ +#209#174#160#255#205#167#152#255'yG3'#235'[/'#27'"'#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'd4'#30#181#179#134'r'#254#215#185#173#255#215
+ +#185#173#255#215#185#173#255#215#185#173#255'm^X'#255#215#185#173#255#215#185
+ +#173#255#215#185#173#255#215#185#173#255#133'sk'#255#0#0#0#255#156#134'}'#255
+ +#215#185#173#255#215#185#173#255#215#185#173#255#215#185#173#255#215#185#173
+ +#255#215#185#173#255#215#185#173#255#214#183#172#255#143'^I'#243'b3'#29'`'#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#8'f6 '
+ +#205#189#148#131#254#222#197#187#255#222#197#187#255#222#197#187#255#222#197
+ +#187#255#222#197#187#255#222#197#187#255#222#197#187#255#222#197#187#255#127
+ +'qk'#255#134'wq'#255#222#197#187#255#222#197#187#255#222#197#187#255#222#197
+ +#187#255#222#197#187#255#222#197#187#255#222#197#187#255#220#193#183#255#159
+ +'o['#247'd3'#30#147#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0'[/'#27#15'c3'#30#193#176#132'q'#248#228#206#199#255
+ +#228#208#201#255#228#208#201#255#228#208#201#255#228#208#201#255#228#208#201
+ +#255#228#208#201#255#228#208#201#255#228#208#201#255#228#208#201#255#228#208
+ +#201#255#228#208#201#255#228#208#201#255#228#208#201#255#228#208#201#255#221
+ +#196#186#255#141']I'#237'c3'#29#129#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#2'c3'#29#150
+ +#135'XD'#231#208#176#164#255#235#219#215#255#235#219#215#255#235#219#215#255
+ +#235#219#215#255#235#219#215#255#235#219#215#255#235#219#215#255#235#219#215
+ +#255#235#219#215#255#235#219#215#255#235#219#215#255#232#214#209#255#189#149
+ +#133#253'qA+'#220'a2'#29'O'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27
+ +'"e4'#30#185#144'cO'#235#195#158#144#254#230#209#203#255#242#231#229#255#242
+ +#231#229#255#242#231#229#255#242#231#229#255#242#231#229#255#241#230#226#255
+ +#220#193#184#255#180#141'|'#251'zK6'#226'd3'#30#142'[/'#27#10#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#28'b3'#29'{g5'#30
+ +#198'xH2'#218#137']J'#229#156'r`'#236#151'mZ'#234#132'VB'#227'q?)'#213'f4'#30
+ +#182'_1'#28'W[/'#27#11#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ ,#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#5'[/'
+ +#27#30'[/'#27#22'[/'#27#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#255#252'?'#255
+ +#255#192#3#255#255#0#0#255#254#0#0'?'#248#0#0#31#240#0#0#15#240#0#0#7#224#0#0
+ +#7#192#0#0#3#192#0#0#3#192#0#0#1#128#0#0#1#128#0#0#1#128#0#0#1#128#0#0#1#128
+ +#0#0#1#128#0#0#1#128#0#0#1#128#0#0#1#128#0#0#1#128#0#0#3#192#0#0#3#192#0#0#3
+ +#192#0#0#7#224#0#0#7#240#0#0#15#240#0#0#31#248#0#0'?'#252#0#0#127#255#0#0#255
+ +#255#192#3#255#255#252'?'#255'('#0#0#0#16#0#0#0' '#0#0#0#1#0' '#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +';;;'#13'ICB7M=4zL>6xFBA;@@@'#16#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0'III'#7'W;,'#171'nC('#245#145'`+'#250#181#127'2'#253#175
+ +'z1'#253#139'\*'#250'h?&'#244'P=3'#159'@@@'#12#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0'K921d;'''#235#191#137'7'#254#249#198'E'#255#251#199'F'#255#251#200
+ +'F'#255#251#200'F'#255#251#199'F'#255#246#194'E'#255#173'y3'#253'\9)'#229'E>'
+ +';2'#0#0#0#0#0#0#0#0#0#0#0#0'>2,'#7'nC'''#238#223#171'N'#255#239#191'U'#255
+ +#240#192'U'#255#164#131':'#255'@3'#23#255'J;'#26#255'~e-'#255#196#157'E'#255
+ +#239#191'U'#255#212#159'J'#255'a<('#231'MMM'#10#0#0#0#0#0#0#0#0'[7('#183#195
+ +#145'N'#254#228#180'_'#255#228#180'_'#255#228#180'_'#255''#25#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#4#3#1#255'9-'#24#255#205#163'U'#255#175'~E'#253'Q:0'#168
+ +#0#0#0#0'[/'#27#10#143'd@'#248#219#174'l'#255#219#173'l'#255#159'~N'#255#206
+ +#163'f'#255'qY7'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1#1#0#255#152'x'
+ +'K'#255#218#172'k'#255'zQ5'#246'UUU'#3'W4$H'#178#134'_'#254#213#169'x'#255'Y'
+ +'F2'#255#0#0#0#255'L<+'#255#200#158'p'#255#8#6#4#255#0#0#0#255#0#0#0#255#18
+ +#15#10#255'pY?'#255#213#169'x'#255#213#169'x'#255#157'tR'#251'M=74^6$'#154
+ +#193#151'x'#255#179#144's'#255#6#5#4#255#27#21#17#255#155'|c'#255#206#165#132
+ +#255#130'hS'#255'=1'''#255':/%'#255#170#137'm'#255#141'q['#255#166#133'j'#255
+ +#206#165#132#255#178#135'l'#253'Q8,{c5 '#167#195#154#133#255#163#130'q'#255
+ +#153'zj'#255#192#152#132#255#199#159#138#255#200#159#138#255#201#160#139#255
+ +#201#160#139#255#201#160#139#255#154'zj'#255#1#1#1#255#29#23#20#255#197#157
+ +#136#255#181#139'v'#255'X5%|_1'#28'V'#176#132'r'#254#199#159#141#255#199#159
+ +#141#255#184#147#130#255'#'#28#25#255#27#22#19#255#167#133'v'#255#127'fZ'#255
+ +#172#137'z'#255#197#157#139#255' '#26#23#255#15#12#11#255#187#150#133#255#156
+ +'tb'#251'W1 0[/'#27#30#160'zk'#246#210#176#163#255#210#176#163#255#154#129'x'
+ +#255#0#0#0#255' '#27#25#255#152#128'v'#255#4#3#3#255'>40'#255#210#176#163#255
+ +#148'|s'#255'RD?'#255#210#176#163#255#140'fW'#243'[/'#27#2#0#0#0#0'tI6'#209
+ +#216#188#178#255#221#195#185#255#213#188#178#255'$'#31#30#255#131'sn'#255'sf'
+ +'`'#255#0#0#0#255'eYU'#255#221#195#185#255#221#195#185#255#204#180#170#255
+ +#207#178#166#255'k>+'#182#0#0#0#0#0#0#0#0'[/'#27#31#156'xi'#240#232#213#207
+ +#255#232#213#207#255#180#165#161#255#232#213#207#255#182#167#162#255'ICA'#255
+ +#226#207#201#255#232#213#207#255#232#213#207#255#231#213#206#255#134'_O'#233
+ +'[/'#27#12#0#0#0#0#0#0#0#0#0#0#0#0'd3'#30'e'#171#139'~'#240#239#226#224#255
+ +#242#231#229#255#242#231#229#255#240#229#227#255#242#231#229#255#242#231#229
+ +#255#242#231#229#255#235#221#216#255#153'uh'#236'a2'#29'?'#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0'\0'#27'*'#131'\I'#215#212#191#183#252#239#229#226#255
+ +#253#250#252#255#253#249#250#255#236#223#220#255#204#180#172#250'yM;'#196'[/'
+ +#27#23#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#3'[/'
+ +#27'>c3'#29#131'uI4'#190'oA-'#183'b2'#29'v[/'#27'4'#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#248#31#172'A'#224#7#172'A'#192#3#172'A'#128#1#172'A'#128#1#172
+ +'A'#0#0#172'A'#0#0#172'A'#0#0#172'A'#0#0#172'A'#0#0#172'A'#0#0#172'A'#128#1
+ +#172'A'#128#1#172'A'#192#3#172'A'#224#7#172'A'#240#31#172'A'
+]);
+
diff --git a/branches/script-component/Projects/OCRBench/project1.rc b/branches/script-component/Projects/OCRBench/project1.rc
new file mode 100644
index 0000000..a452b4a
--- /dev/null
+++ b/branches/script-component/Projects/OCRBench/project1.rc
@@ -0,0 +1 @@
+MAINICON ICON "project1.ico"
diff --git a/branches/script-component/Projects/OCRBench/unit1.lfm b/branches/script-component/Projects/OCRBench/unit1.lfm
new file mode 100644
index 0000000..ec494f3
--- /dev/null
+++ b/branches/script-component/Projects/OCRBench/unit1.lfm
@@ -0,0 +1,71 @@
+object Form1: TForm1
+ Left = 474
+ Height = 306
+ Top = 430
+ Width = 609
+ ActiveControl = BitmapButton
+ Caption = 'Form1'
+ ClientHeight = 306
+ ClientWidth = 609
+ OnCreate = FormCreate
+ LCLVersion = '0.9.29'
+ object OCRButton: TButton
+ Left = 512
+ Height = 25
+ Top = 255
+ Width = 88
+ Caption = 'OCR Filter!'
+ OnClick = OCRButtonClick
+ TabOrder = 0
+ end
+ object Image1: TImage
+ Left = 16
+ Height = 264
+ Top = 16
+ Width = 480
+ end
+ object BitmapButton: TButton
+ Left = 512
+ Height = 25
+ Top = 32
+ Width = 88
+ Caption = 'Set Bitmap'
+ OnClick = BitmapButtonClick
+ TabOrder = 1
+ end
+ object PathButton: TButton
+ Left = 512
+ Height = 25
+ Top = 72
+ Width = 88
+ Caption = 'Set Path'
+ OnClick = PathButtonClick
+ TabOrder = 2
+ end
+ object FShadow: TCheckBox
+ Left = 507
+ Height = 22
+ Top = 112
+ Width = 81
+ Caption = 'Shadow?'
+ TabOrder = 3
+ end
+ object ClientButton: TToggleBox
+ Left = 512
+ Height = 23
+ Top = 144
+ Width = 88
+ Caption = 'Set Client'
+ OnMouseDown = SelectClient
+ TabOrder = 4
+ end
+ object OCRFileOpen: TOpenDialog
+ Filter = '.bmp'
+ left = 416
+ top = 277
+ end
+ object UpCharsDialog: TSelectDirectoryDialog
+ left = 448
+ top = 277
+ end
+end
diff --git a/branches/script-component/Projects/OCRBench/unit1.pas b/branches/script-component/Projects/OCRBench/unit1.pas
new file mode 100644
index 0000000..e0cb9ae
--- /dev/null
+++ b/branches/script-component/Projects/OCRBench/unit1.pas
@@ -0,0 +1,170 @@
+unit Unit1;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+ Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
+ StdCtrls, ExtCtrls, Client, MufasaTypes, Bitmaps, ocr, windowselector,window;
+
+type
+
+ { TForm1 }
+
+ TForm1 = class(TForm)
+ BitmapButton: TButton;
+ FShadow: TCheckBox;
+ PathButton: TButton;
+ OCRButton: TButton;
+ Image1: TImage;
+ OCRFileOpen: TOpenDialog;
+ ClientButton: TToggleBox;
+ UpCharsDialog: TSelectDirectoryDialog;
+ procedure BitmapButtonClick(Sender: TObject);
+ procedure FormCreate(Sender: TObject);
+ procedure OCRButtonClick(Sender: TObject);
+ procedure PathButtonClick(Sender: TObject);
+ procedure SelectClient(Sender: TObject; Button: TMouseButton;
+ Shift: TShiftState; X, Y: Integer);
+ private
+ BitmapPath: String;
+ FontPath: String;
+
+ CliW: TMWindow;
+ UseClient: Boolean;
+ { private declarations }
+ public
+ { public declarations }
+ end;
+
+var
+ Form1: TForm1;
+
+implementation
+
+uses
+ lclintf, lcltype;
+
+{ TForm1 }
+
+procedure TForm1.OCRButtonClick(Sender: TObject);
+Var
+ C: TClient;
+ bmp: TMufasaBitmap;
+ x,y: integer;
+ s: string;
+ Shadow: boolean;
+ t: dword;
+
+begin
+ if not FileExists(BitmapPath) and not UseClient then
+ begin
+ MessageBox(0,pchar('You did not set a valid bitmap'), Pchar('Bitmap Error'),
+ MB_OK);
+ if OCRFileOpen.Execute then
+ BitmapPath := OCRFileOpen.FileName;
+ Exit;
+ end;
+ if not DirectoryExists(FontPath) then
+ begin
+ MessageBox(0,pchar('You did not set a FontPath' ), Pchar('Path Error'),
+ MB_OK);
+ if UpCharsDialog.Execute then
+ FontPath := UpCharsDialog.FileName;
+ Exit;
+ end;
+
+ Form1.Image1.Canvas.Brush.Color := 0;
+ Form1.Image1.Canvas.Rectangle(0, 0, Form1.Image1.Canvas.Width, Form1.Image1.Canvas.Height);
+
+ // create and init client
+ C := TClient.Create;
+ bmp := TMufasaBitmap.Create;
+ if UseClient then
+ C.MWindow.SetWindow(CliW)
+ else
+ begin
+ bmp.LoadFromFile(BitmapPath);
+ C.MWindow.SetTarget(bmp);
+ end;
+
+ Shadow :=FShadow.Checked;
+
+ // DS + .. + DS because InitOCR wants the directory of the Fonts, not UpChars
+ // only.
+ C.MOCR.InitTOCR(FontPath + DS);
+ C.MOCR.SetFonts(C.MOCR.GetFonts);
+
+
+ t:=gettickcount;
+
+ s := C.MOCR.GetUpTextAtEx(7, 7, Shadow);
+
+ writeln(inttostr(gettickcount-t));
+
+
+ // write to debugbmp
+ {$IFDEF OCRDEBUG}
+ for y := 0 to C.MOCR.debugbmp.Height - 1 do
+ for x := 0 to C.MOCR.debugbmp.Width -1 do
+ Form1.Image1.Canvas.Pixels[x,y] := C.MOCR.debugbmp.FastGetPixel(x,y);
+ // print ocr'ed text
+
+ Form1.Image1.Canvas.Font.Color:=clRed;
+ Form1.Image1.Canvas.TextOut(0, C.MOCR.debugbmp.Height, s);
+
+ C.MOCR.debugbmp.Free;
+ {$ELSE}
+ Form1.Image1.Canvas.Font.Color:=clRed;
+ Form1.Image1.Canvas.TextOut(0, 0, s);
+ {$ENDIF}
+ {$IFDEF OCRDEBUG}
+ Form1.Image1.Picture.SaveToFile(OCRDebugPath + 'ocrbench.bmp');
+ {$ENDIF}
+
+ bmp.Free;
+ C.Free;
+ Application.ProcessMessages;
+end;
+
+procedure TForm1.BitmapButtonClick(Sender: TObject);
+begin
+ if OCRFileOpen.Execute then
+ begin
+ BitmapPath := OCRFileOpen.FileName;
+ UseClient:=False;
+ end;
+end;
+
+procedure TForm1.FormCreate(Sender: TObject);
+begin
+ UseClient := False;
+ {BitmapPath := '/home/merlijn/Programs/mufasa/pics/uptext4.bmp'; }
+ FontPath := '/home/merlijn/Programs/mufasa/Fonts/';
+end;
+
+procedure TForm1.PathButtonClick(Sender: TObject);
+begin
+ if UpCharsDialog.Execute then
+ FontPath := UpCharsDialog.FileName;
+end;
+
+procedure TForm1.SelectClient(Sender: TObject; Button: TMouseButton;
+ Shift: TShiftState; X, Y: Integer);
+
+Var
+ WS: TMWindowSelector;
+begin
+ UseClient := True;
+ if not assigned(CliW) then
+ CliW := TMWindow.Create;
+ WS := TMWindowSelector.Create(CliW);
+ CliW.SetTarget(WS.Drag{$IFDEF WINDOWS},w_Window{$ENDIF});
+end;
+
+initialization
+ {$I unit1.lrs}
+
+end.
+
diff --git a/branches/script-component/Projects/PStest/project1.lpi b/branches/script-component/Projects/PStest/project1.lpi
new file mode 100644
index 0000000..9b1a215
--- /dev/null
+++ b/branches/script-component/Projects/PStest/project1.lpi
@@ -0,0 +1,220 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/branches/script-component/Projects/PStest/project1.lpr b/branches/script-component/Projects/PStest/project1.lpr
new file mode 100644
index 0000000..c5fbf91
--- /dev/null
+++ b/branches/script-component/Projects/PStest/project1.lpr
@@ -0,0 +1,22 @@
+program project1;
+
+{$mode objfpc}{$H+}
+
+uses
+ {$IFDEF UNIX}{$IFDEF UseCThreads}
+ cthreads,
+ {$ENDIF}{$ENDIF}
+ Interfaces, // this includes the LCL widgetset
+ Forms
+ { you can add units after this }, Unit1, LResources;
+
+{$IFDEF WINDOWS}{$R project1.rc}{$ENDIF}
+
+begin
+ Application.Title:='TestApp';
+ {$I project1.lrs}
+ Application.Initialize;
+ Application.CreateForm(TForm1, Form1);
+ Application.Run;
+end.
+
diff --git a/branches/script-component/Projects/PStest/project1.lrs b/branches/script-component/Projects/PStest/project1.lrs
new file mode 100644
index 0000000..2747aa9
--- /dev/null
+++ b/branches/script-component/Projects/PStest/project1.lrs
@@ -0,0 +1,5237 @@
+LazarusResources.Add('MAINICON','ICO',[
+ #0#0#1#0#6#0#0#0#0#0#1#0' '#0#226#145#0#0'f'#0#0#0#128#128#0#0#1#0' '#0'('#8#1
+ +#0'H'#146#0#0'@@'#0#0#1#0' '#0'(B'#0#0'p'#154#1#0'00'#0#0#1#0' '#0#168'%'#0#0
+ +#152#220#1#0' '#0#0#1#0' '#0#168#16#0#0'@'#2#2#0#16#16#0#0#1#0' '#0'h'#4#0#0
+ +#232#18#2#0#137'PNG'#13#10#26#10#0#0#0#13'IHDR'#0#0#1#0#0#0#1#0#8#6#0#0#0'\r'
+ +#168'f'#0#0#145#169'IDATx'#218#236']'#5#128#28#245#213#127#235'n'#231'w9I.N'
+ +#136#144#4#139#17#220'['#220#221#138';!'#184'|'#180#148#2#197'Kq'#13'R('#20
+ +'(V'#180#197#3#9'!'#144#144#16#187#156#219#202#173#251'~'#239#253'gfo'#246'r'
+ +'~'#187';{'#242#131#201#236#173#204#204#202#251#253#159'?'#25#140'a'#12'c'#24
+ +#181#144'I}'#1'c'#24#195#24#164#195#24#1#140'a'#12#163#24'c'#4'0'#134'1'#140
+ +'b'#140#17#192#24#198'0'#138'1F'#0'c'#24#195'('#198#24#1#140'"'#140#155'}2}'
+ +#223#6#220'L'#184#25'q'#11#227#230#161#173#225#167#21#17#169#175'o'#12#217
+ +#199#24#1#12'c'#160'@'#155'q7'#21#183'i'#184'M'#198#173#8'8'#225'N'#217'd2'
+ +#153'p'#155#132#191#167#239'<'#132#155''''#145'H0B'#224'7'#175#232'v'#7'n'
+ +#219'p'#219#128#219'F'#220'j'#145'4'#18'R'#127#6'c'#24#26#198#8' '#199#129'B'
+ +'.'#199#221'x'#224#132'|'#170#176#161'P'#211#223'%='#189'N'#214#195'7+'#235
+ +#230'+O@'#207'r'#156#232#249#161#0#146#197'&'#232'$'#132#228#134#196#224#145
+ +#250's'#27'C'#255'0F'#0'9'#6#20'x'#18#234#189'q'#219#7#183'=P'#208'ie'#215
+ +#136#159'#'#22'nA'#160'e'#194#157#226#199'DO'#20'nwG'#12'b!O'#240#127'$R'#238
+ +#236#230'q'#209#157']I'#2#159#211#136#187#181#184'}'#198'o'#171#145#20'bR'
+ +#127#182'c'#216#17'c'#4' 1P'#224#11'p'#183#20'8'#161#223#27#5'u'#186#240'X'
+ +#167'L'#239'('#228't'#155#219#0#228#244#12#185#140'{'#158#140'{'#157#140#191
+ +'!'#235#250'|'#232'<'#166' '#196#130#252#146'ps'#27'pRM'#255#203#184#191#197
+ +#143#209#235#196#247'AbGb'#232'B'#10#29#248#248#255#160#147#16'~'#26'3'#31'r'
+ +#3'c'#4#144'e'#160#192'[p'#183#23#240#171'<'#10#229'L'#224#191#7#177#192#203
+ +'8)'#6#185'\'#158#20'h'#185#156#187'_.'#227#4#158#30#163#219#10'z'#142#188
+ +#203#227#252#30'D'#247#201#21#10#220'+AF{P@\'#22#135'D,'#134#194#26#131'8'
+ +#238#227#241#24'/'#216'qn'#31'O'#0#222#194#251#241#223'8@'#28#255#137#199#185
+ +#191#227#137#4#187#157#224#239'#'#2#136''''#186''''#134'nH'#193#129#247#127
+ +#14''#193#238#139#11'['#146'(R'#9#161#139#217'A&'
+ +#195#10#220#158'G2'#248'E'#234#239'k4a'#140#0'2'#4#20'z%'#238#246#7'N'#232
+ +#127#143'{'#29#221'/'#172#230#226#21'^,'#240'$'#172'$'#224'J'#165#2#148#180
+ +'W)A'#163#214'3'#1#215#144#176'ku'#160#209#242'B'#175'V'#129#10#159#175'T'
+ +#202#217's'#233'u'#10#185'p'#172'.'#26#129#130'3'#21#184#251#216#149'p'#23
+ +#202'Vn'#224'Vo'#129#4#226#156#128#198'x'#1#142#197'8'#161#142'E'#19#16'E!'
+ +#143'D'#227#16'Eb'#8'!'#9#132#131'~n'#11's'#251#16'#'#135'0>/'#134#207#225'6'
+ +#129#16#24'A'#136#8#129#206#215'U;'#192#251#215#224#238#5#220'^B2h'#150#250
+ +'{'#28#233#24'#'#128'4'#3#5#127'.'#238'N'#197#237'D'#20#190'b'#186'O,'#244
+ +#130#170#174#144#209'*.c'#2#175#228#133'^'#173'T'#162'P'#171'Ao'#178#130'^o'
+ +#3#157#209#10'Z'#29#10#187'J'#129#171'=nL'#208#233#182#156#221'V)'#21#201'=#'
+ +#11'%G'#0'D$r9g'#247#211#185#146'&'#3#179#8'd)'#206'AnE'#134#20'5'#30'e'#149
+ +#187#29#231'6"'#128'h'#156#132'9'#158'$'#128'H'#132#246'1'#238#182'h'#31#198
+ +'}8'#24#130#128#175#3#252'^'''#248'}N'#8#5'}'#236'1'#129#16#162#177#174#132
+ +#16'g'#218#1#153#24#220'5'#177']'#12#175#225'c'#224#200#224'M$'#3#191#212#223
+ +#237'H'#196#24#1#164#1'('#244#21#184';'#25#183'SQ'#184'v'#162#251#186#21'z~'
+ +#133#231'Vv'#18'^'#20'x'#149#10#244'('#232'z'#163#13#12#6#220#27#204#184#226
+ +#227#170#175'Q'#130'V'#173'`'#194'O'#127#171'U'#188#192#171':'#133'^'#197#142
+ +#195#173#254't'#31'g&p'#171#127#210#148#160#235#224#29#132#130#250#159#18#9
+ +#224#205#0#178#245#133#21#153#217#251#252#223'$'#155'$'#160#209'8'#183#250'w'
+ +#146#0#10'2'#145#0#222#14'G8'#2#160'=m'#161'H'#20#205#132#24#4#195#220#237'@'
+ +' '#0'~'#143#139#145#1#145'B'#136#204#8#188#159'#'#131#24'gJ'#224'qbq'#193
+ +#223#176#131#153#224'E2'#248'''pd@>'#131#184#212#223#249'H'#193#24#1#12#1'('
+ +#248#243'pw='#10#219#17#192'-'#174#12'rN'#210'8'#149'\&O'#170#244'*'#21#9#178
+ +#146#9#188#193'd'#195'}'#30'nf'#208'jT'#160#19#132#30'7'#29#19'~%G'#4'<'#9
+ +#168#149#220#202'O'#171'<'#169#253#10#165#12#148'ra'#213#167's'#164#10'>]'#2
+ +'wA'#188#192#11#209#129'D*'#1'$U'#239#164'g'#159#255#139#183#215#227#188'3P'
+ +#16#206'(o'#14#16#9#196#4'2Hj'#5#164#1#160#208#147#224#135#163'l'#31#8'E!('
+ +#222'P'#240#253'>'#31#4#188'.'#240'!'#25#248'<'#14'4'#27#130#248#218'(#'#5'F'
+ +#4#140#12'x"'#232#226'3'#192#191')'#25#233'/'#184'='#131'D'#16#146#250'70'
+ +#220'1F'#0#131#0#10#254'"'#220#221#128#194'v'#16#253#157'\'#237'y'#207''#198#147'BLl'#30#136#136#0#133'>'#16'N%'#1#250
+ +';'#16#196'-'#20#129'` '#2#30#183#3'<'#174'f'#240'x'#218'Q;'#8'32 '#13'C'#236
+ +'d'#20'L'#4#17#17#144#227#240'^'#220#30'C"'#240'I'#253#155#24#174#24'#'#128#1
+ +#0#5#159#156'z7'#162'0-'#161#191#185#24'<-'#181#220'j'#159'j'#203#163'0'#235
+ +'t`'#182#20#131#201'V'#2'F'#147#25#244'Z'#21#24'p'#163#189'^G'#130#174'b'#194
+ +#175#21'V|'#141#130#9'='#17#6#19#252#164#131#143#183#229#153#195#16'D6='''
+ +#224#178#174#241#254'.'#215'-'#147#13#236'k'#22''''#1#137's'#4#128#251#159'#'
+ +#2#193'THtF'#16#146#132'@'#26'B$'#158'4'#11'B'#145'N'#141' '#200#147'A '#24#1
+ +'?'#146#128#31'I'#192#239#167#219#184#5#130#224'v'#181#129#219#217#194'i'#6
+ +','#242#16'c'#14#199#164#137#16#139#167'h'#5'x'#187#29'/'#233'~'#220#30'F"'
+ +#232#144#250'72'#220'0F'#0'}'#128'/'#160#249#29'p+'#254#174't'#31#23'^'#239
+ +#12#209'1!Ur'#234#189'V'#171#1#147#165#136#173#244'&K'#30'/'#236'j0'#232'T'
+ +#201'M'#199#147#128'V'#195#169#248#156#208'+83A'#201#31'O.'#178#231'{'#17'v'
+ +#254'&'#183#239'A'#208#7'"'#255'='#165#254'v%'#133'D'#167#154#176#3')p^'#255
+ +#4#243#27#196'D'#142'C'#210#10#194#188'_'#128#153#7'A'#142#8'|'#129'0n'#17
+ +#182#249'i'#143'Z'#128#23#205#4#15#18#1#145#129#223#239#193#215'E'#153'f'#192
+ +#162#11#188#19#177#139#175#128#146#141#30#193#253'}H'#4#237'R'#255'n'#134#11
+ +#198#8#160#7#240'9'#248#199#1'g'#227'S'#178#206#14#130#175#18#236'z\'#189#13
+ +'&+X'#243#199#161#224#23#162#144#235'P'#232'U`'#228#5#158#8#192#168#231#132
+ +'^'''#8'>'#9#189'Z'#145't'#230'q'#26#132'8'#254'/J'#254#17'.'#170#15'u>['#232
+ +#202#17']'#201#128#249#14#4#13'A'#228'?`'#209#4'2'#17'b'#228','#140'32 '#159
+ +#0#167#13#136#8#0'5'#2'/'#146#130#159#255#219#227'qA'#135#179#25':'#28#141'h'
+ +'R'#132'92Hj'#5';'#16#129#31#207#255#24#238#239'A"h'#148#224#227#25'V'#24'#'
+ +#128'n'#128#194#191#27#238#30'EA'#163#144'^'#138#224'+yU_'#141'6'#188#6'7'
+ +#163'9'#15'l'#133#149'`'#177#230#163#176#227'J'#143#130'n'#212#171#217'mN'
+ +#232#213'('#244'h'#235'k95_'#205'<'#250#188#7'_'#217#25#183#239'N'#173'g'#231
+ +#22'.j8|S]'#202#7'RR'#135'E'#230'B,'#193#231#20#240#161'Cf"'#136'|'#3'$'#244
+ +'^A+'#240#163'6 '#236'}~p'#180#213'!'#17'4'#224#243#130#140#8':#'#9#169'D'
+ +#128#231#14#224'%'#220#137#219'_'#198#156#133'=c8'#252#172#178#6#20#252'<'
+ +#220#221#137#194'w.'#240'2'#152'"'#248#188#154#175'A'#219#221'd)`'#130'oE5'
+ +#223'hP3'#161'7'#25'4L'#232#13#188#202#159#180#241#153#224#139#156'y'#188'z/'
+ +#8#190'8'#127'?'#165#208'g'#128#182'{'#174#161''''#167'b2'#225#136'O2'#226
+ +#180#2'!'#140'H>'#130'X'#167#143#0#137#192'C'#194#207#8' '#12'n'#220'{'#188
+ +'~p'#182#215#131#203'^'#15'A'#127#144#249#10'z!'#2#170'X'#188#24'I'#224'?R'
+ +#127#30#185#136#225#253#11'K'#19'x;'#255','#220#238'B'#161#203#23#156'{2'#133
+ +#160#234's+'#183#22'W|'#147#181#8#242#138'+'#193'l'#182#129#137#9'='''#248'&'
+ +'#'#238'Q'#240'uL'#229'W'#177#24#190#134'9'#243'RU|qr'#14#8#222'z'#254':d#'
+ +#248#235#216#161'z0'#25'f'#228'3'#17#197'&'#2'i'#5'Q^+ '#18#8'F'#152#22#224
+ +#245#133#192'C$'#224'#R'#8#129#215#27#0#167#189#1#156#168#21'P'#174'A('#140
+ +'D@9'#9'T'#215#192';'#11#227#157#213#141#175#225#238#10'$'#130#6#169'?'#139
+ +'\'#194#200#253#197#245#19'('#252#187#224#238'o('#152'{'#136#195'y,'#227#142
+ +'6'#18'|T'#227'-'#214#18#176#21'U'#160#224'['#153#208#155'I'#232'y'#225'g'#26
+ +#128#150#19'|q'#248'N'#156#158'+'#8'>'#147#249#212'z'#222#209#9'Q'#232'1'#233
+ +'7'#224#137#128#204#132#8#159'tDQ'#0#166#17#132#200'9'#136#155#143#211#8#220
+ +'H'#6'D'#4#28')'#4#145#8#26#145#8'j'#193#239#247'!qt'#18#1#167'm'#196#5'm'
+ +#128#26#156#220#138#219#3'H'#4'Q'#169'?'#130'\'#192'h'#253#249#9'Uyw'#160'0^'
+ +#128'{'#133#160#238#179'"'#27#222#185'G'#9':'#228#205'/('#169'F'#193'71a'#239
+ +'I'#240#5#199#30'K'#203'U'#202'S'#236'zN'#232#187#177#235#199#176'C'#30'BB'
+ +#172#25#176#236'CN+'#8'G'#163#157'D'#192#251#4'8m'#128'#'#2#143'@'#4'm'#13
+ +#224'h'#169'A'#205'!'#192#136' '#194#155#6']'#204#2'*8'#186#16'I'#224#11#169
+ +#223#191#212#24#149#191'E'#20#254'Spw'#15#229#234'''Km'#21'|J-+'#190'A;'#222
+ +'hB'#193#159#4#182#252'"&'#244'f#'''#252'f^'#240#13#188'W_'#219'e'#197'O&'
+ +#231#240'R'#223#25#162#147#250']'#231'>D'#193#4'n/'#242#21'$S'#144'{'#210#8
+ +#188'!'#232' '#18#160'}'#135#23#218#155#183#130#203#217#4#193'`'#152#249#21
+ +#136#8#226#172#246' %'#153#232'y'#220']'#141'D'#208'&'#245'{'#151#10#163#234
+ +'g'#137#130'O'#141'0'#31'G'#193'?'#145#254#22'Vh'#5#191#234#171'U*'#180#225
+ +'5'#204#185'WP2'#30','#6#29'XL'#26#176#24'9'#2#160'U'#159#9#190'F'#136#225'+'
+ +'9'#167#30#139#219#11'y'#255'\'#213']'#231'''<'#170'>'#226#244'A'#228'@L@gM'
+ +#2#249#9'"'#2#17#136#162#6#130'Y'#208#225#9'22'#160#205#225'h'#135#246#166'M'
+ +'H'#10#29#156'6'#192#242#8#226#156#127#160'S'#27#160'P'#225#137'H'#2#255#147
+ +#250'-K'#129'Q'#243#235'D'#225#159#141#187#127#160#144'N'#17'V}'#5#159'i'#199
+ ,#169#251'h'#215'['#11#160#176't2'#218#251'f&'#244'V'#163#22#204'D'#0#6'-S'
+ +#251'){'#143#4#159#203#244#227#146'u'#196'e'#183'];'#248#140'a'#232#16#151#11
+ +#11#230'A,'#193#167#30'G'#184#228'"'#230','#196#205#195#155#5#29#222' '#18'A'
+ +#136#237#221'H'#8#237#173#181#224'l'#217#14#254'`'#16'B'#225'0'#159'f'#28'Oj'
+ +#24#192'U'#30#222#130#251';G['#161#209#168#248#165#162#240#159#135#187#7'PH'
+ +#181'2'#190#6'_H'#217#165#144#158#222'`'#196#21#127'"'#228#229#151#178#149
+ +#158'V}+['#249'9'#193'7'#232#213'l'#213#167#172'='#242#234's'#9';\'#201#173
+ +'Pp'#195'>'#204'Q'#241'iJ'#131#206'DDn'#229'N'#166#31#147'F'#16#229#170#16')'
+ +#143#128#210#138#189#188'I'#224#18#17'A'#135#219#11'mM'#155#161#195#209#130
+ +'&'#4#146#0'%'#19#9#209#130'Nm'#224'#<'#193')H'#2#173'R'#191#223'laD'#255'd'
+ +#249'N<'#143#137'U~'#193#214#167'D'#30#29#174#250'yE'#168#238#23'O'#0#179'Y'
+ +#199#4'>'#185#242#27'9[_H'#217'e'#169#186#138#212#226#155#222#26'm'#142'!3'
+ +#224#139#21#147#14#195'd>A'#148'K7'#230'2'#11'9"'#224#28#132'H'#4'n$'#0#242
+ +#13#144'Y`o'#133#246#230'M'#224#243'x:'#181#129'h\'#28')h'#194'3'#156#140'$'
+ +#240#153#212#239'5'#27#24#177'?]^'#229#127#141#186#234#138'='#252#172#180'VE'
+ +'N>#'#148#148#239#4'V[>'#191#226'k'#25#1#144#202'O'#241'}'#178#245'uj~'#213
+ +#23'j'#237'E^}'#246#225#141#216'O/'#247#145'$'#2#232#236'AH)'#199'Q'#190#0
+ +#137#10#142#168#208#200#231#227#136#128#132#223#229#9'2'#31'A'#135''''#0#173
+ +#13#191#177#208'a'#144'O-'#142'&C'#134#236#200#184'K'#220#142#251#255#27#233
+ +'&'#193#136#252#9#163#240#255#1'w'#247#139'U~'#174#147#14#197#244'U`'#177#21
+ +'Cq'#249'4'#176#153#13'('#252'Z&'#252#164#242's'#153'|\'#234'.'#173#250'\5'
+ +#30#223'aG&'#235'6'#23#127#12#210'"'#145'd'#1#224#27#152#242'D'#16#137#179
+ +#162'#"'#2#31#239'$'#228#132'?'#4'N'#158#8#236'm'#13#208#214#248#27'j'#11'A'
+ +#150'D$D'#10'D&'#193#167#192'i'#3'#'#182'5'#217#136#250'%'#243'*?y'#249'O'
+ +#160#191#197'*'#191'FM'#130#173#129#252#210'j(,'#169'bj'#190#213#162#5#155'I'
+ +#155#12#241#137#227#249'B'#18'Ogn>$k'#236#199#144'['#160#214#229#157#185#4
+ +#188'Y'#192#218#152'qY'#133#212#153'('#192#215#23'0'#223#0#145#128';'#128#166
+ +#1#238#157'Nh'#169'_'#15'^O'#7#231#27#216#209'$h'#1#206'/'#240#177#212#239'3'
+ +#19#24'1'#191'f'#20'~'#26#139#245#30#10#255#188#174'I=\\'#159'T'#254#25'`'
+ +#203#207'c+'#190#205#164#3#171'Y'#203#135#247#212#172'XGH'#221'e'#13'7'#146
+ +#234#190'h'#229#151#250'M'#142#161'G'#136'|'#132#220','#131'8'#223#201'('#193
+ +'7)'#9'sNB'#210#6#220#188'9@'#190#1#167#155#246#254#164'I'#16#224#27#146'DY'
+ +#155#244'$'#9'P'#214#224#217'H'#2#207'K'#253'>'#211#141#17#241#155'F'#225#159
+ +#128#187#255#160#240'O'#18#132#159'b'#243#228#229'gi'#188#182'"T'#249#167#163
+ +#192#163#202#143'B'#159#135#155#133'_'#249#141'|}'#190#154'o'#192'A'#141':'
+ +#229'2Q'#231#220#17#241#9#141'B'#240#13'L'#200#128#23'Z'#153#9#185#3'T['#224
+ +#241#134#185'('#1'j'#1#14#212#6#220#168#21#180#183#212'C['#243'&'#214#152#132
+ +#202#142#133#156#1#222'/'#128'<'#144'X'#134'$p'#143#212'o-'#157#24#246'?o'
+ +#222#217#247#1#10#127#137#216#222#167#226#29#157'V'#203#210'x'#11'H'#229''';'
+ +#223#204#169#252't'#155'e'#243#233':='#252#201#10'='#161':O'#234'76'#134#161
+ +'#'#193#165#26#11'-'#200#163#188#147#144#186#19#177#188#1'_8'#169#13'8'#153
+ +'F'#16'@'#147#160#3'Z'#234#214'1'#147#128#146#135'('#5'YD'#2't'#172#187'qw'
+ +#237'H'#153'l4'#172#127#231'('#252'4a'#231'-'#20'~'#139' '#252','#163#143'T~'
+ +#131#1#138'+f@^^A'#167#224#155#185'0'#31#9'?+'#213#229#227#250'B'#231#29#232
+ +'R'#142';'#134#145#1'q'#163#211'd'#164' '#202#165#19#11#225'Br'#14':'#220#28
+ +#9#208#214'Z'#191#1'\'#246'&'#212#24#194','#170#16''''#191#0'$M'#130#231#240
+ +#128#231#140#132#130#162'a'#251'sG'#225'?'#10'w/'#161#240'k'#132#240#28#169
+ +#252'j'#170#213'7'#153#160#164'r6'#216'lff'#235#219#204#218#164#189'/'#180
+ +#228'R'#243#173#183#200#209''''#212#225#143#9#255#200#133#144'H'#148'lJ'#130
+ +'&A'#24#237#252#16'_n'#204#162#4'nN'#27' '#147#128#162#4'-'#13#155#192#209'Z'
+ +#203#234#9'('#162' '#174'%@'#18#248'7'#30#238'8$'#129#128#212#239'm('#24#150
+ +'?y>'#204'G%'#188'r'#193#211'/8'#251#168#15'_i'#213'L'#176'YM'#144'G'#206'>'
+ +#139'.'#25#226#211#179'&'#29#202'd'#223'='#161'D'#151#251' '#134#229'G1'#134
+ +#1'B<'#216'Th^J+'#188'@'#2'd'#18#144'c'#208#217#17'`'#251#182#230#237#208#214
+ +#180#9#130#129'03'#7#186'D'#8#190#194'C'#30#142'$'#224#148#250'}'#13#22#195
+ +#238'W'#143#194#127'3'#10#238'mt['#16'~5_'#193'g'#177#22'@i'#229'L'#176'Z'
+ +#245'L'#240#137#0#200#233#199#132#159'o'#201'%'#30#160#193'>'#128#177'e'#127
+ +#212'A<'#2']'#156''
+ +#129#253#135#147'c0'#231#197#1#133#159#198'o'#189#141#178#175#18#219#252':'
+ +#173#26#10#203#166'@Aq%'#243#240''''#133#159'<'#253'$'#252#201#10'>'#174'tW6'
+ +#22#219#135#223#29'0'#11#2#254#29#167'hi'#181':'#184#231#161#151'`'#234#244
+ +'YR_'#162'd'#224'9 '#233#23#136'D'#184#209'f'#228#28'd'#21#133#148''''#208#17
+ +'d'#161'B'#167#203#141'$'#240#19'x<'#29#221#145#192';x'#168'#'#145#4'bR'#191
+ +#167#254' '#167'e'#130#239#207#255')'#10#191'A,'#252#180#242#23#148'N'#130
+ +#162#210#241'I'#225#23'r'#250#5#225#231'Fi'#203'E='#249'r'#250#173'f'#5''''
+ +#31#181#16#218#219#186#175'kQ('#148'p'#239'#'#175#192#244#25#187'H}'#153#146
+ +'AhP'#10#2#9'D'#185#225'%b'#18'pv'#8#155#27#154'j'#214#128#215#227'fm'#201
+ +#187'8'#6#159'F'#2'8['#234#247#211#31#228#172'T'#160#240'O'#193#221'W('#184#5
+ +'B'#146#143' '#252#249'EU'#156#205#207#132#159#203#235'gi'#189'z.'#179#143#28
+ +#131#138#148#148'^'#24#157'F'#127#23','#191#252#20#248'i'#245#183'=>N$p'#215
+ +#131'/'#194#140#153#243#165#190'T'#233#144#28'f'#2#201#129#167'D'#2#212#127
+ +#144#230#18#8'$@'#230#128#195#233'B'#18#248#17'|>'#127'2:'#192'&'#21'q'#14
+ +#198'?#'#9'\'''#245#219#233#11'9)'#21'('#252#165#184#251#26#133#127#188'8'
+ +#195#143'9'#252#10#199'AI'#197'N,'#185''''#143#247#246#179#236'>'#157#154#13
+ +#215'd'#194'/j'#211#149#179'oR'#2#216#219'Z'#224#180#227#150#224#15#180#231
+ +#18'w'#185'B'#1'w'#222#251'<'#204#156#179#155#212#151'+'#9#196#195'P'#133#206
+ +'CD'#2'!VC'#16'e'#221#135#133'""'#202#21' '#199' i'#2#1#170#31#160#241#230
+ +#204#28'H'#8'$@s'#8#238#151#250'='#245#134#156#147#13#190']'#247#255'Pxg%'
+ +#133#31#127#148#26#190#168#167#140#226#252#164#242'S'#156#223',R'#251#213'JP'
+ +#170#184'>}c!'#190#158'q'#255']'#215#194''''#31#190#217#235's'#228'r'#5#252
+ +#249#129#21'h'#14#204#149#250'r%'#133#16'*'#20'r'#5'h'#132#25#149#21#139#205
+ +#1#210#4#236#237#173#208#178#253'g'#8#132#130#140'('#132#218#129#4'7R'#249
+ +#148#134#159'^zI'#234#247#210#19'rJJP'#248#201#21#253#17#141#223#22#170#250
+ +#148'|'#134#159#217#146#7'%'#19'fC'#158#201#0'6'#171#150#197#250#217#202#143
+ +#194#175#213'(S'#187#246#228#212#187#202'-'#196#227'Q8'#254#176'y'#16#194#31
+ +'ko'#208'hu'#240#220'k_'#130'^o'#148#250#146'%'#133#216'1('#152#3#204''''#224
+ +#237'L'#27'&'#231' '#151','#180#129#235'0'#20'I!'#129#8#30#225'0$'#129#156#28
+ +'M'#150'S'#162#130#4#240#16#10#255#197#226#146'^'#141#138'r'#251'-P:a'#23'\'
+ +#249#141'l'#213'g'#194'o'#226'V~-'#133#250'D'#243#246'r'#234#13#229'('#222
+ +#254#231#179#240#244#223#255#220#231#243#202'+'#171#225#225#167#222#147#250
+ +'r%Grr'#17#175#9#4#187#144#128#144''''#208#218'T'#3#246#166#205#157'$'#208
+ +#217'O'#192#145'H'#196'vi\'#251'J'#173#212#239#165'+rF^'#248#226#158#127#138
+ +#19'}'#168'A'#7'5'#242'('#173#154#11'y63W'#213#199#215#242#147#195#143'*'#250
+ +#132#129#28#178#177#149#127'@8'#251#132'%'#224't'#244'='#15'c'#191#131#143
+ +#133#11#175#184']'#234#203#149#28'B1'#17'9'#249'"|'#187'1.O '#204'J'#137#137
+ +#4':P'#19'hi'#220#4#246#214#237#16#162#198'"'#169'ME'#190#142#4#28'K['#127'{'
+ +'?"'#245'{'#17'#''D'#134'o'#232#241'#'#149#245#10#225'>'#18'~'#157'^'#15#165
+ +#227'w'#1#155#205#154't'#248'Y'#153#218#175#225#235#248';'#213'~!'#183#127#12
+ +#253#195'/?}'#7#183',;'#163'_'#207#189#234#134#251'`'#193#146#131#164#190'd'
+ +#201#145#28'Y'#22#227#204#1#210#4'|B'#155#177'dw'#161' 4'#213#173#131#14#190
+ +#148'85<'#24#191#27'M'#129'k!e'#144#186#180#144'\jx'#187#255'K'#20#254']'#187
+ +#134#251#138'+w'#134#130#130#210'd'#172#191#179'}'#151#138#235#207#207#183
+ +#232#22#6'}'#140'a`8'#239#228#165#168#5#244#221#2#159#194#131#15'='#253#1#20
+ +#22#149'I}'#201#146#131'K'#27#230'5'#1#190#185#8'M.'#166#218#1#18'~'#135''''
+ +#192'Z'#140'5m'#253#17''
+ +#202#242'3'#25#185#149#159#230#241'q'#133'=\'#168'Oj'#6#251#237#215#31#225
+ +#230'kNM'#185#143'H'#224#222#199#222#134#210#210'*'#137#175#174'wl\'#183#26
+ +'n'#185#246#180'~?'#127#238#174'{'#193#178'['#30#145#250#178's'#2#180'|s-'
+ +#200#169#187#16#154#3'An"'#17#235','#212#17#20#149#17#175'Ov'#27#22#249#3#190
+ ,#12'y['#246'n'#223#242#177#228#29#133'$'#147#31#20'~'#146#14#178#251'm'#226
+ +'4_='#218#253'e'#19#230#161#221'oa'#130#207'9'#253'h'#229'W'#179#22'^\I'#175
+ +'<9r[j'#220'y'#243'y'#240#243#143#223#236'p'#127'qi'#5#220#247'xnz'#208#219
+ +'['#155#224#213#23#30#128'5?|'#1'>'#175'{@'#175'='#243#130#27'`'#255'CN'#144
+ +#250'-H'#14'![0'#193#135#7'I'#192'i"'#145#208'^'#140'5'#20'Am'#160#185#238'W'
+ +'p'#182#215'C8'#196'u'#26'&'#194#224#15'pg'#253'O+n'#0#137'M'#1'ID'#8#133'_'
+ +#5'\'#178#207#30#226'L?'#157'F'#3'E'#21';'#163#250'_'#146'l'#229'%T'#246'Q3'
+ +#15#214#194'K)'#227#166#239#230#130#244'#'#206'8z.D#;:v'#149'J'#21'<'#251#198
+ +'j'#169'//'#137'p8'#12#239#188#254#4#252#247#227'7'#193#209#222'2'#232#227
+ +#200#240#187':'#253#188#235'`'#191'1'#18'H'#166#13#11#227#203'Y'#162#144'P7'
+ +#144#236'%'#224'GS`5x'#221#174#29#252#1'h1'#30'R'#183'f'#197#135' !'#9'HE'#0
+ +'w'#161#240'/'#163#219#10#161#139#175'F'#9#249#133#227#161#168'|2o'#247'wv'
+ +#239'e'#225#190'd'''#159#220'q'#248#213'l^'#15'7]'#221#179' <'#241#202#183
+ +#160#213#234'%'#189#198'`'#208#15#127#185#245#15#176'y'#227#207#189#166#0#15
+ +#20#147#167#205#134#229#183'?'#1'j'#181'V'#210#247'''5'#18#162'a'#165'\'#142
+ +#0'?{'#128'H'#128#138#134'<\'#205'@'#179#216#31#208'i'#10#180'i'#212#138#217
+ +'['#191#127#190#25'$"'#129#172'K'#18#10#255#28#220#253#128#4#160#16#199#251
+ +#141'f'#206#238#183#176#6#158#188#221'o'#224'j'#250#233'q*'#238#145#201'd9'
+ +#21#239#127#255'_'#207#193'+'#207#253#181#199#199#175#189#237'q'#216'i'#214
+ +#238#146']'#223#166#13'?'#193#221'('#252#161'Pf'#202#211#213#26'-\t'#245#221
+ +'0g'#254#18#201#222#163#212'H$'''#18#9#21#132#220'\'#194'dk1'#26'C'#198'g'#10
+ +#182'5n`'#13'F'#187#148#15#191#220#240#211#10#234'w'#193#15'8'#203'.'#178'*J'
+ +'('#252't'#190#175#197#170#191'`'#247#151#140'G'#187#223'jN'#246#239#167'Q]'
+ +#212#193'W'#173#22'M'#229#205#21#201#231#241#183'{'#151#193#247'_'#247#156
+ +#225'y'#197#13#15#195#172#185#139'$'#185#182#230#198#237'p'#253#165'G'#166'u'
+ +#213#239#9#187'.'#216#31'.'#188#234'nI'#222'g'#174'@('#30'bN'#193#8#231#15
+ +#160'Qd'#212'i'#216#201#166#19#147'?`='#184#218#27'v('#26#146#203#18#251#213
+ +#173'y'#137#166#17'g'#157#4#178'M'#0#231#2'7'#187#143#169#254#148#234#171'U'
+ +#171'Q'#237#223#9#237#254'q,'#212'G'#4'@'#19'z'#141#186'N'#187'_'#220#202'+'
+ +#151'p'#203'U'#199'A}'#237#166#30#31'?'#245#188#27'a'#233#254'GKrm'#203'/:'
+ +#12'W'#157#236#181#168'3'#154#173'p'#205#205#143'Cy'#213'dI'#222'o.@p'#10'F'
+ +#226#220'(2'#214'iX(!&'#18#240#248#161'q'#235#15#224#247'y'#216'0R'#145')'
+ +#176#161#208#28#223'e'#205#23'/'#135'`'#164#18#0#10#127#1#238'6'#162#240#231
+ +#145',+'#168#194#15#5#220'l-'#130#210#170#217#220#136'nQ'#129#15#169#254#201
+ +#210#222#28#136#245'w'#135#171#207';'#0':\'#237'=>>{'#222#18#184#248#218#236
+ +'W'#131#174#250#246#19#248#251'_'#175#201#250'y'#169#148#248#162'k'#254#138
+ +'Z'#207#226#172#159';W@>'#129'x'#12#152#199#159':'#10#249#168#183#160#159's'
+ +#10#18#17#216#219'['#160#165'v-'#155':'#20#21'B'#131'@?'#239#196#245'{L'#14
+ +#255#229#181#215'^'#139'C'#22'I '#155#4#240'4'#10#255#153'B'#194#15'e'#242'i'
+ +#181#26'('#171#222#21'l'#22'+X-'#26#150#227'o'#210#11#241'~E'#206'W'#247']y'
+ +#206#190#224#245#184'z|'#220'`'#180#192'}O}'#154#245#235'z'#230'o'#183#192'7'
+ +#255#253#183'$'#159#9'iw'''#156#185#12#246'>0'#247#19#161'2'#1'nE'#231'z'#11
+ +'R'#166' '#181#26'gIB'#194'@R'#26'8R'#251#11#184#28'M]K'#135'}'#10'Yd'#230'Y'
+ +'G'#236#180#253#214'[o'#205#154')'#144#21#209'B'#225'_'#136#187'/'#196'M=)'
+ +#225''''#191'x'#2#20#150'M'#228#236'~'#190#159#31#27#209#205''''#251#200#20
+ +'|'#154'o'#142#142#228#190#242#156#165'L'#157#235#13#203'n'#127#22#170''''
+ +#207#204#234'u'#253#241#186#147#160#174'f'#163#148#31#13#236'{'#200#201'p'
+ +#236#169'WJz'#13'R!'#217'e'#152'2'#5'Q'#19#160#162'!'#174#155#16'_='#232'rC'
+ +#211#214#239'!'#16#12'tI'#16#138#191'5'#217#214'x'#204#231#159#127'.h'#1#25
+ +''''#129#140'K'#22#10#191#18'w'#171'Q'#246'g'#138#29#127#6#163#9'W'#255#221
+ +'P'#232'u'#220#234'o'#20'B~'#156#221#175#148'Q?'#191#172'\'#226#160'q'#229'Y'
+ +'KX'#152#173'7L'#156':'#27#174#186#229')v'#155#190#232#141#235#190#135'_~'
+ +#252#2'j6'#255#2#173'-u'#16#14#5#161#176#184#28'f'#238#178#24#150#236#127','
+ +#216#242#139#135'|]w\{<4'#214'm'#145#250#227#129'='#150#28#6#167#157#127#171
+ +#212#151'!'#13'(*'#144#224#187#9#133'R'#203#135'iko'#222#14#237'M'#155' '#28
+ +#230'M'#1#222'!'#168#144#197#143#216'}r'#244#223#217'2'#5#178'A'#0#201'~'#254
+ +#130#227#143'V'#255#226#138'Y'#144'_X'#194#170#251#204#204#235#175'f3'#251'4'
+ +#194#164'^'#5#191#242#231#174#252#195#21'g.'#198'/0'#216#231#243'*''L'#135
+ +#246#214#6'^['#232#253';'#173#154'8'#3'.^'#246' '#232#141#230'A_'#215#223#239
+ +#189#18'~^'#253#133#212#31#15#195#137'g]'#7#139#246'=J'#234#203#200':'#196
+ +#249#1#194#172#1#242#7'P4'#192#229#14#129#27'I'#160'q'#219#15#204#132#236#146
+ +#27#176#173#196#26#155'S]'#20#243'e'#131#4'2*^('#252#229#184#251#21#133#223
+ +'(8'#254'h'#245'7'#219#138#161#164'r&'#179#249#201#243'o'#22#169#254#148#240
+ +#195#138'j'#134#193#140#238'+'#206'\'#4#209'H8'#237#199#165#234#187#227#207
+ ,#188#22#246'\'#250#251'A'#189#254#173#151#31#130#143#223'}A'#234#143#135#129
+ +'4'#190#229#127'Z'#1#165#229#19#165#190#148#172'#9'#131#144'R'#133#249#209'c'
+ +'n'#26'I'#206#180#128#16'8'#236'm'#208'R'#187#134#213#10#136#27#138#202'e'
+ +#137'?'#21')6'#222#186'j'#213'*j-'#158'QS '#211#4#240','#238'N'#231#194'x\'
+ +#165#159'N'#167#129#210#9#187#162#218'o'#6'3o'#247#155'x'#213'_'#165'Rt'#198
+ +#251's\'#248#9'W'#158#177'p'#135'A'#27#233#2'}'#6'W'#160#233'@'#26#193'@'#225
+ +#180#183#192#173#151#255'N'#234#143''''#9#157#222#8'w<'#244'>(G'#227#240#145
+ +#132#184#167' '#167#5#176#198#162#158#16#155'@'#220'Z'#255'+t8'#26#152'C0'#22
+ +#139#9#164#17#210'(";W'#154'[k>'#255#252's'#129#4'2'#130#140#137#25'_'#236
+ +#179#25#127#200#202'd'#147#15'\'#225#243'J&Aa'#201#4'&'#248#22'>'#219#143#188
+ +#254'B'#194#143#208#214'K6'#28'4'#128'3'#22#160#234#150#185#249#15#148'F'#252
+ +#199'G>'#4#165'j'#224#130#243#199'k'#143#131#214#166#237'R~<)'#168#24'?'#13
+ +#174#190#253'9'#169'/#'#171'H'#206#31#20'G'#5#130'\'#150' E'#5#152'&'#224#246
+ +'A'#211#182#149#16#240#7#146#25#130'd6'#160#22#240#216#30#147'#'#151#226#203
+ +'c'#153'4'#5'2I'#0#127#195#221#5#194#234'O'#171#187#222'`'#198#213#127'>'#174
+ +#252#186#164#234'O1'#127#13#175#250#11#173#188's5'#236#215#21'W"'#1'd:'#211
+ +'n'#206'n'#251#194#233#23#253'q'#192#175'['#245#205#135#240#226#223'o'#145
+ +#234#163#233#22'{'#29'x'#2#28'q'#210#229'R_FV'#145'L'#21'&_'#0#223'T4'#16#226
+ +#18#132'H'#3' "ho'#169#5'{'#211#198#174'a'#193#160'Y'#23#157#174#143'ln'#200
+ +#164')'#144#17'Q'#227#251#250'oCa'#214#8#171#191#150#194'~'#227'v'#130#130
+ +#194'q,'#233#135'R}'#169#198#159#10'}'#146#173#189#134'Y['#175#171#207'^'#136
+ +'_lf'#9'@'#173#209#193#157#127#31'\.'#193'u'#231#239#3#225#12#213#1#12#22#231
+ +'^y'#31'L'#155#185#135#212#151#145'u'#136'G'#145'S'#130#16#171#21#224'K'#135
+ +'I'#19' -'#192#231#245'$'#147#131#226#156'/'#224#129#137#214#198#229#133#133
+ +#133#145'Li'#1#153'"'#128'{pw'#149#216#246'7'#24'q'#245#175#222#21'W}m'#146#0
+ +'('#215'_'#163'Q'#138'r'#253'3'#253'5'#164#23#203#206'Y'#196#190#172'L'#131
+ +#132'f'#234#206#3'/*'#250#199'3'#127#130#149'_H'#147#16#212#19#242#10'J'#225
+ +#250#191#252'S'#234#203#200':'#132#4'!'#161'V'#128#229#6#8#166'@W-'#128#250#8
+ +#178'(B'#194'k'#209#248#166#203'|'#155'Z'#143'='#246#216'h&'#18#132#210'.r('
+ +#252#249#184#219'.'#158#231'G*~~'#233'4(('#174'`'#182#191'9'#153#238#171'J'
+ +#233#231'?'#220#176#252#188#197#25#245#1#8#152#188#211#174'H'#2#15#12#248'u~'
+ +#159#27'n'#187#252#224#164'-'#154'+'#184#244#198#167#161'|'#252'4'#169'/#'
+ +#235'`i'#194#162#178'a'#214'U'#152#143#10'Px'#176'i'#203'w'#224#247#251#152
+ +#22' D'#4#20#178#248'_'#198#233'jn'#213'h4'#145'L8'#4'3A'#0#255#135#187#27
+ +#133#184'?'#173#254'z'#189#1#202'&'#238#193#4#159'<'#255#20#243#167#176#31
+ +#149#249#178'b'#31#190#189#207'p'#226#128#166#186#205'p'#255'm'#167'g'#229'\'
+ +'&K>'#220'xo'#255'z'#247'u'#197#227#247'\'#10'[6'#172#202#230'G'#211'''*'#171
+ +'w'#134#139#174#127'L'#234#203'H'#162'v'#235'z'#248#224#141#191#179'U'#248
+ +#202#219'^'#4'm'#6#134#161#236'P6LZ'#0's'#8#134'Xkq'#242#7#216'['#182#131#189
+ +'y'#19#203#11#16'E'#4':'#10#13#222#25#165#150'p'#187#209'h'#140#166#219#20'H'
+ +#171#200#161#240'S'#246#10#173#254#214'd'#193#15#10'y^'#233#20#200'/'#170'd'
+ +#4'`'#225'+'#253#132#213'_.'#204#241'K'#251'G'#158'Y<'#245#192#149#176'i'#221
+ +#202#172#156#139#138'l'#254#244#232#127#7#245'Z'#183#171#13#238#188#246#168
+ +#156#210#2'hq'#184#225#158'w'#192'h'#178'Jz'#29'?'#175#250#12#222'z'#233#175
+ +#224#245'8'#147#247'Yl'#133'p'#237#157#175#225'oR'#153#246#243#9'#'#200#147
+ +#29#132#216#188#193#8'x'#242#5'P'#181#224'w'#16#164#136'@'#172'S'#11
+ +'P'#202#227#255'7'#181#208'~'#151#221'n'#15#167#219'!'#152'n'#2#184#30'w'#127
+ +#20#175#254#172#183#127#245#238#184#234#235'p'#245'Ws'#157'}'#249'b'#159'd'
+ +#216'o8-'#253#192#133'tn'#190'x'#31#136'g('#7#160';\'#247#151#183#152'&0'#24
+ +';d'#213'_'#204#156#191#15#156'x'#174#180#3'G'#222'|'#225'.'#248
+ +#254#203'wv'#184#191'x\5\v'#243#243#25'9'#167'0'#130'<'#22#19#194#130#145'd'
+ +#243#16#210#4#218#155#183#130#179'uk'#215'r'#225#246#170'<'#255',u'#194#233
+ +'L'#183'C0m'#146#135#194'O'#189#175'jP'#152#11#133#156#127'J'#249#205'+'#158
+ +#4#249#197#227'q'#245'Ws'#131'6'#127#209#225'p'#196')'#203'2r^'#241#152'1'#234'#'#232#167
+ +#228' >*@Z@'#211#150'o!'#24#10'B4'#210'Y#'#160'R'#196'o'#24#167#171'}'#200
+ +#229'r'#133#210#233#16'L'''#1'\'#134#187#251#133#22#223'JV'#238#171#195#213
+ +#127#15'0'#25#185')'#190#228#249#215#137'W'#255'af'#247#11#248#203'uG'#130
+ +#167#195#158#213's'#206#156#191'/'#28'w'#214#224#227#250#143#254#249'\h'#172
+ +#149#182'B'#176'+'#14':'#234'"X'#184#223#241#146#157#127#235#198#213#168#29
+ +'u'#159#151' '#147#201#225#218#187#254#5#6'cf'#204#148#148#185#2'4v<'#16#6
+ +#143#151'#'#129#246#166#205#224'j'#171'I'#169#17#192#127#154'&'#216#218#230
+ ,'DC'#30'O:'#29#130#233'$'#128#159#196'#'#189')'#231#223'VT'#13#249'%'#213','
+ +#219#143'y'#254'u'#157#147'|'#5#219#127#184#161#177#246'7x'#236#174's'#179'~'
+ +#222#130#226'J'#184#228#230#193#231#247'?'#250#167#179#160#185'A'#250#10'A1'
+ +#170#167#205#131#211'/'#249#235#208#15'4H'#4#253'^'#184#243#154'C{|'#188'j'
+ +#210'l8'#235#138#7'3rn'#161'N'#128#204#0'J'#14#242#5#195#172'd'#152#204#0#183
+ +#199#11#205#219'V'#162#22#16'Ji'#29#166'SFO'#221'i\'#224'-$'#128#208#140#25
+ +'3'#210#162#5#164'E'#2#199#205':q'#14#200#228'?'#166#14#248'PC'#217#196'='
+ +#193'h'#212'%'#195'~]m'#127'v'#1#195'L'#5'x'#246#129#203#160'f'#211#154#172
+ +#159'W'#161'T'#193'M'#247#127'<'#232#215'?p'#203#9#224#180'7e'#253#186'{'#131
+ +#209#156#15'W'#255#233#13'I'#175#225#214'K'#150'v'#186#232#187#193'y'#203#158
+ +#128#178#202')i='#167'`'#138'u'#230#5#196'Y#Qj'#28'Bu'#2#20#26'lk'#218#8#238
+ +#246':'#22'-'#16#210#131#21#242#196#191''''#231#181#156#145#151#151#231'okkK'
+ +#139#22#144#30#2#152'}'#242#189#184#187'R'#156#248'c'#206'+'#133#162#242#25
+ +'l'#245#167#141'l'#255#174#5'?'#195'L'#246#25#238#184'|'#191#140#21#0#245#133
+ +#195'O'#186#6#230#238'y'#232#160'^{'#207#245'G0_@.'#129'4'#197#155#30#200'~'
+ +#199'$1'#250#250'>+&'#236#12'g]'#249#240#0#142#216'?'#8#26'@gD'#160#179#135
+ +' +'#22'r9'#160#173'v'#245#14'EB'#165'F'#215#156'Bs'#188#209'h4'#6#211#161#5
+ +#12'Y'#4#11'&'#238#167#212#24#139#235'P'#160'K'#196#206#191#194#242'Y`'#205
+ +'+J'#18#0'7'#211'O'#148#243#159#246#143'4'#243#168#223#182#14#158#185#255'b'
+ +#201#206'o+('#131#139'oZ1'#168#215#222'u'#237#161#16#238#163'y'#137#20#184
+ +#225#222#143'@'#174#148#206#17'x'#247#242#195'!'#24#240#246#248'8'#249#2#150
+ +#223#243'>.j'#233#175'd'#20#198#139#209#198':'#9#135'"\'#15'A$'#0'2'#7#154'k'
+ +#190'g'#201'\bg'#160'F'#17#185'~'#130#205#254'x'#186#180#128'!'#203#225#184
+ +#217''''#29#130#135'yW'#172#254#235'tz('#157#184#7#152#244#26#214#229#135'e'
+ +#253#241#171'?'#169#255#220#7#155#246#207'3'#227'xg'#197#159'a'#237#247#255
+ +#25#250#129#134#128'E'#7#158#10'{'#29'|'#230#128'_'#247#231#171#15'D{2'#167
+ +'F'#211'3\q'#199#27#160#207#144#163#173'?x'#232#182#19#192#237#236'}B'#242
+ +#194#253'N'#130#165#135#157#147#145#243''''#135#138#196'83'#128#178#3'='#188
+ +')`o'#169#1'g'#203#230'd'#219'0'#190'Jp'#213#228#188#230#223#163#6#224'N'#135
+ +'/`'#168'b(C'#245#255'%'#220#159' '#174#250#179#20'TAA'#233'd'#182#242#147
+ +#240#179#156#127'a'#180#215'0'#140#251#11'x'#152'~,'#174#190#199'ig'#18#244
+ +#217#157'q'#249'#PZ9'#176'T'#218';'#175#220'/+3'#2#6#138#11#174#127#1'l'#133
+ +#227'$;'#255'S'#247#156#7'-'#13#155'{}'#142#193'd'#131#203'n'#207'L'#253#2
+ +#203#11#192#175'%'#154#156'''@y'#1'\'#207#0#143#199#3#205#219#190#235'j'#6'$'
+ +#242#180#158#189#139#140#190'_'#210#161#5#12'I'#18'Kw>'#214'"W'#168#155#240
+ +'G'#169#19'w'#252')'#170#154#7#22#139#141#9#191#208#231'O'#205#175#254#178'a'
+ +#24#247#23'p'#215'5'#251'g'#188#250#175'?'#208'h'#13'p'#217'mo'#12'Hu'#206
+ +#149'k'#239#138#11'oz'#5#204#214'B'#201#206#255#226#195#151#161'i'#247'K'#159
+ +#207';'#227#138'G'#161#164'<'#189#206'@'#1#226'J'#193#0#211#2#194'L'#11' 3'
+ +#160#165'n'#13#248#220#246#20'3@'#173#136'>2)'#223#241''''#157'N'#231#25#170
+ +#22'0'#20'I'#148#141#155'u'#210'Y('#205'O'#138'c'#255':'#189#25'J&'#236#202
+ +'B~F'#3#183#250'k'#133#138'?'#129#0'2'#242'1f'#30'w]'#189#159#212#151#144'DE'
+ +#245',8'#233#194#254#135#208#238'^v@V*'#23#7#2#250#221','#187#251#163#172#159
+ +#215#209'V'#7#171#190#252#23'4'#213'n'#128#182#230'm'#253'j'#235'V5i'#23'8'
+ +#225#252#244'O?'#18'$'#150#141#26#143'u:'#3'}'#228#12'D"p'#182'7'#128#189#241
+ +#215#20'3@&K'#212'M'#201'k'#222#27'??'#215'P'#181#128#161#17#192#236#147'?'
+ +#199#253#18'.'#166#207'M'#248#181#22'q'#153#127'$'#248#194'`O'#173#134'k'#244
+ +#169#16#226#254#195'P'#3#8#6#189#240#208'MGH}'#25')'#216#231'w'#23#194#188
+ +#197#253'k'#184'y'#239#181#7'f'#165'rq '#160'^'#7#151#221#241#206#208#15#212
+ +#7#162#209'0'#252#188#242#3#216#176#230'S'#166#238'G'#250#209#200#181'+'#228
+ +'r'#5'\q'#231#251#236'w'#158'v'#240#209#0#193#25#200'B'#130#188'/'#192#231#11
+ +'@'#243#214'o'#184#190#129#157'f'#0'X'#181#129'S'#202#173#190'OQ'#3#240'644'
+ +#4#15'?'#252#240#216'`'#180#128'AKb'#217#204#227#170'er'#21#181#252#146#137
+ +#213#255#226#234#221#209#246'7'#166#172#254#164#254#211#7''''#31#198#234#127
+ +'['#211'Vx'#238#190'?H}'#25') '#15#245'YW?'#133'6ty'#159#207#253#235#242#131
+ +'r'#142#0#242#138'*'#217#245'g'#18#159#189#243'wX'#245#5#229#26#12'='#13'z'
+ +#241'Ag'#194#238#251#156#148#145#235'$'#225#23#18#131#184'"!./'#128#234#4#218
+ +#234#215#131#167#163#169'Kjp'#236#141')'#5#142#171'U*'#149#203#135',1'#216#26
+ +#129#193'J'#163#172'|'#246#201'7'#226#153'n'#23'{'#255#141#230#2'('#172#152
+ +#205#173#254'z'#21#232#209#12#160'6'#223'*'#149#144#246';<'#133#159#176'm'
+ +#195'w'#240#230#179'7I}'#25';'#128'<'#232#231#223#248#143'>'#159'w'#255#13
+ +#135'd'#181'x'#169'?'#216#251#240#11'`'#151#133'Gf'#236#248#219'6'#174#132'7'
+ +#159#185'1m'#199#179#228#149#194#217#203'2'#211#215'P'#152'+'#200':'#8'G'#185
+ +#225#162'>'#161'i'#136#179#21#218#235#215#166'$'#5#201' '#209'19'#191'u'#145
+ ,'\'#150'h'#195#197#215'+'#170#20#28#144#157'7h'#2'@'#245#159#234'S'#23#139'+'
+ +#255#242'J'#167#131'-'#191#12#244'zU2'#244#199#138'~'#134'q'#222#191#128#159
+ +#191#127#31'>~#'#251's'#254#250#131'I;/'#130#195'O'#238#157#156#30#188#241'P'
+ +#201#18#152#186#3#149'8_v'#251#191'I'#183#206#200#241#253'^'#23''#232#163'7|'#247#217#10#248#230#163#204
+ +#148#136#166#3#135#156'p=L'#153#181'W'#143#143'?q'#231#137#224#243'8'#164#190
+ +#204'$'#170'&'#207#131'#'#207#252'S'#198#142#255#244#221#167#129#219#217#146
+ +#246#227#238#182#247#137#176'`'#255'3'#210'~\'#241' '#145#168#168'y('#133#4
+ +'I'#19'ho\'#7#30'gsJm'#128'^'#21'y'#180#210'b'#191#31'I'#193#129'&'#128'o0'
+ +#206#192'A'#17'@'#197#156#147#247#195#235#252#143'X'#253#215#234#200#251'?'
+ +#159#9#190#1'5'#0#193#249#199#133#254#134'o'#234#175#128#207#223'y'#4#214'~'
+ +#155'y'#135#213'`'#161'Ti'#224#194'['#223#234#241#241#247'^'#186#3'6'#175#251
+ +'R'#234#203#228#175'U'#13#231','#127'%c+'#233#251#175#222#9#155#214#14#174
+ +#129'J'#223#215#174#129#243'o~3#'#206'@ae'#167'h@'#152#31'$B'#137'AD'#0'N{=8'
+ +#155'6'#166#180#11'S'#202'c'#223'O'#202'k;'#7#175#165'='#18#137#184'='#30'Oh'
+ +#160#13'C'#6'E'#0'h'#255#255#9#143#190'\'#28#254'3'#219'*'#209#4#152#204#236
+ +#127#218'h'#188#183'Z'#24#243'5'#12#171#254#186#226#235#15#159#130#213'_'#190
+ +'.'#245'e'#244#138#5#7#156#9's'#23'w?'#149'w'#203#250#175#224#253#151#239#144
+ +#250#18#25#14';'#229'6'#24'?u'#183#140#28';'#232'w'#195#147#127'>'#161#215#2
+ +#159#161'b'#202#172#189#225#128'c3'#215'+'#128#181#12#19#204#0#158#0'|^/'#180
+ +#212'|'#151','#17#230#252#0#16#156'\'#208#182#31#138'Y'#227'`'#157#129#3#149
+ +'L'#217#173#183#222'*{'#226#205'M_'#225#237'='#196#197'?y'#227'v'#6#171#173
+ +#152#23'~n'#245#231#188#255#178'a'#217#240#179'+'#182#172#255#18'>x%s*k:'#160
+ +#213#153#224#236#235'^'#237#254'A'#252#209#252#237#182#195'%o'#10'2e'#246#222
+ +#176#255#209#215'd'#236#248#159#188'q/lX'#243'IF'#223#3'-|''_'#246'$s'#10#166
+ +#27'I3 '#206#153#1','''#0#9#128#136#128#8' '#24#240#165#248#1#10#244#254'K'
+ +#11#13#158#143'Q'#11#176'SH'#16#181#128#240'@'#204#128#1#19#192#148#221'N2'
+ +#251'B'#178'v'#154#248#211'i'#255#171#160#164'zO'#208#235'u'#172#232#135#156
+ +#127'Z>'#245'W>'#12#219'}w'#7'ZY'#158#185#235'D'#169'/'#163'O'#236'{'#212#213
+ +'L'#200#186#195#11#247#158#14'^w'#187'd'#215'V4n2'#28'}^f'#29#169'O'#220'q'
+ +#20'D#'#161#140#191#23'K'#254'88'#233#210#199#211'~'#220#174#237#195')'#26'@'
+ +'$'#16' ?@'#211#6#240'8'#27#187#250#1'^'#172'0'#183#223#135'ZA'#171'N'#167's'
+ +#15#180'Jp'#160#162')/'#159'}'#226'!'#9#144#191'#'#216#244#20#255#215#27#172
+ +'PX9'#151#9'?'#249#0#152#250#175'$'#239#191#208#244'cd'#144#192'cl'#5#205#173
+ +'l'#186#174'(.'#159#6'G'#158'so'#183#143#173#252#228'9X'#253'E'#223'!'#195'L'
+ +' '#191'x'#2#28'{A'#250#203'j'#197#248'u'#213#7#240#223'w'#30#202#218'{Zt'
+ +#240#249#176#243#238#135#167#245#152'|'#247#31#212#0#184'nA'#194'hq6^'#220
+ +#209#4#142#166'_'#187#250#1#214'M'#206'o?'#31#9#160#9#205#0'g('#20#242#15#196
+ +#12#24#136'X2I.'#159's'#242#221'x'#222'+'#197#14'@s~%'#235#253'G'#194#175'G'
+ +#225#167'a'#31'D'#0'r'#133'l'#216#135#255#196'x'#225#222'S'#193#239'u'#14#253
+ +'@'#25#132'Zk'#128'3'#175'}'#181#199#199#223'x'#252'rhk'#218'<'#128'#'#14#29
+ +#214#130'r8'#254'"'#154#20#151#153#144#159#128#151#30'8'#27'<'#174#244'{'#254
+ +'{'#2#245'5fV'#248
+ +#219#26'7'#193#191#158#186'2+'#239'I'#140#25#187#30#6#11#14'Jo'#134'hgRPg'
+ +#159#0#193#20'h'#175#253#129#245#8#16'u'#12#134'|'#157#247#230'b'#147#255'}'
+ +#148#201#22'$'#128#14'2'#3'P'#3#136'B?'#162#1#3#17'O'#249#132'9G'#230#133#19
+ +#250'f'#188#173'H'#150#255#170')'#254#191#16#237'~'#174#233#7#197#254'5|'#242
+ +#15#215#245'w'#228'0'#128#179'm;'#188#241#152't'#13'A'#250#139#197#135']'#10
+ +'S'#230#236#223#235#251'x'#243#241'K3n'#206#204'^x'#28#204#223#251#212#172
+ +#188#231#183#159#190#10'I'#224#183#172#156'K'#12#149'Z'#11#167'-{-'#189#7'Mp'
+ +'9'#1#228#8#140'D'#184'h'#128#16#18't'#182'lBS'#160'N'#1'D'#2'd'#226
+ +#216#27#215#165'8'#2'U'#242#216'&4'#3'.'#198#219#13']'#204#128'>'#163#1#253
+ +'&'#0'R'#255#191#217#164#186')'#145#144#221'"'#216#255'4'#247#207#156'?'#30
+ +#172'E'#19#152#240#147#243#143'&'#1#177#220#127#249#200#178#255#5'|'#251#225
+ +'c'#240#235#170#247#164#190#140'^ '#195#21#233#31'h'#154#245#175#133#213#170
+ +#207'_'#128'u+'#223#198#31'T'#223'%'#177'}'#158#25'5'#194#9#211#23#194'B'#212
+ +'@2'#209'B'#171'''|'#242#250#157'P'#251#219#183'Y;_W'#152'l%p'#204#5#233#27
+ +'u&D'#2#132#226' V'#27#16#138'23 '#16#8'B'#203#182#175#240#251#138''''#29#129
+ +'2Y'#194'7'#173#160#245'd4'#11#234'('#26'`6'#155';'#182'l'#217#18'Z'#183'n'
+ +#29#153#1#189#170'y'#253'&'#128#165'K'#151'*6'#187#198#189#128#231';A'#236#0
+ +#180#149'L'#7#147#181#132#9'?'#167#254'wv'#254'aC?F'#152#6#16#143'Ga'#5'j'#1
+ +#180#207'E'#232#12'68'#238#146'g'#7#250#174#224#251'O'#158#133#223#214'|0@'
+ +#141'@'#198#178#250'4:3'#20#148'N'#130#5#7'_'#12'jm'#250#231#234#245'z'#229
+ +#236#251'8N'#210'JG'#146#135#211#174#253'WZ'#143#201'R'#131'y?'#0#155#29#128
+ +#4'@'#27#17'A'#235#182#239' '#28#246#167#248#1#198'['#237#231'j'#20#225#245
+ +'J'#165#178#9'W'#127#167'N'#167#11#244#167'6'#160#191#210')'#159'7o'#158#162
+ +'9:'#141'hv'#174#152#0#10'*'#230#130#201'le'#194#175#213't'#134#255#134's'
+ +#235#175#190#240#213'{'#15#194#230#28'u'#6#142#199#21'x'#175#223#15'>'#209
+ +#134#242#29#234'6}'#7'M'#219#215#178'N4'#241'X'#132'U'#17#146#160#145#160'['
+ +#242#203#153#176#23'W'#236#4#230'<'#233'Zy'#9#248#254#147#167'a'#253#247#131
+ +#27#156#154'N,='#234'Z'#168#154#178'g'#218#142#215'u'#132#24'5'#10#9#242'Z@{'
+ +#253'Oh'#246#216'S'#8#160#216#232#249#147'M'#235#251#24#239'k'#196#191#237
+ +#161'P'#200#215#159#1'"'#253#145'Pf'#255#31'|'#240#193#170#181#141'ymx'#219
+ +'$'#142#0#20'MX'#8#6#157#134'['#253#133#226#31#249#200'I'#0#234#14'$'#12#175
+ +'=tF'#214'<'#233#253#6'~'#224'G'#254#225'Q0Z'#138#165#190#146#172#225#229#191
+ +#158#136'Z'#203#192#27'|'#164#27#21#147'wC'#18#184'.m'#199'K'#13#7'v'#18#0
+ +#141#21'w4'#253#6'^WC'#151#6'!'#254#23#139#244#174#151#209#254#175#139'F'#163
+ +'mj'#181#218#211#159#18#225'~'#17#0#217#255#171'6'#199'+Cq'#237#214#164#3#16
+ +#237'='#181'F'#143#4#176#27#203#250'c'#171#191'Z'#193#186#2')'#21'#'''#249
+ +#167''''#216'['#182#192#7'/,'#203'h'#206#249'@Q9e'#15'X'#252#251#204#228#168
+ +#231'"6'#253#248#1#172#252'8'#253#217'x'#131#129'Vo'#129#163'/z&'#173#199#20
+ +#210#130#201#214''''#2#16#162#1#29#246':'#232'h'#221#156#18#9'0'#168'C'#159
+ +'UZ\'#15#163'|'#214#14'$'#28#216#31#17#149#163#253'/'#175'q'#151#238#23#137
+ +#201#223'O'#137#0#24#242'!'#191'b'#22#155#3'@'#177#127'F'#0#138#206#8#192'H'
+ +#199#154#255#189#0#235'W'#190')'#245'e0'#144#231#253#152'K^'#204#170#243'Mj'
+ +#188#249#232#217#16#240#229'Fb'#150#12#127#240'''^'#153#222'b1a'#148'x'#140
+ +#207#7' '#2#8#134'#'#224#235#176#131#189#241#231#148'H'#128'F'#25#253#181#218
+ +'f'#191#3#229's;'#254#221#20#12#6#157'J'#165#178#207#226#160'~'#17#192#140#25
+ +'3'#148'n'#213#172#11#226#9#249#253'b'#2'0'#217#202#193'V<'#25'U'#255'N'#2'H'
+ +#142#252#30#225#26#128#128#207'^'#191#29#154'j'#178'?*L'#12#242#190#239'}'
+ +#204'MPR5['#234#143'#kh'#220#182#26'>'#255'gnT7'#10'8'#225#242'W@'#158'&'#2
+ +'f'#170'='#223'#@'#240#3#176'~'#129#148#16#228#247'B'#235#246#149')'#4#160
+ +#148#199#237#147#242'Z'#175'E'#185#164#9#221#13#129'@'#192#238#247#251'}&'
+ +#147#169#215#226#160#190'D'#148#169#255'^'#175'W'#249'K'#147#237#190'xBv'#129
+ +#152#0#172#197'S'#192#130'$'#160#161#8#128'J!'#234#254#3#204#30#29#13#4'@'
+ +#248#238#195'G`'#235'/'#210'8'#5#233#251'Xr'#228#245'P6a'#174#212#31'CV'#241
+ +#239#167'/'#6#143'3'#183'f'#29#238'{'#252#237'l'#28'^'#186#144#236#15' '#26
+ +'%N&@'#24'5'#129#230'-_B4'#18'I'#18#0'">5'#191#229'r'#20#203#173#248'w]8'#28
+ +#166'Va'#30'Q'#143#128'n'#253#0#253'"'#128#182#182'6'#213'fW'#217';'#137#132
+ +'l?q'#17'P'#222#184#153'`4'#23#178#213#159#171#254#235','#0#26'%'#178#159#196
+ +'/'#223#252#3#183'W'#135'~'#160#1#128':'#213'.8'#236'*('#159#180#187#212'o?'
+ +#171'p'#182'l'#133#15'Wd'#174#164'x'#176#152#179#228't'#152'6'#255'wi;'#30'_'
+ +#23#196'|'#0#177'(?D'#20'M'#0'r'#6#182'm'#255#1#194'A/'#171#9#16#136#162#210
+ +#226#252#139'A'#29#254#142#252#0#161'P'#168#197'`0t'#212#214#214#6'{'#203#7
+ +#232#147#0'('#254#143'j'#132#250#199'Z'#243'z'#27#205#196#146'wv'#1'RB'#209#132'E'#160#165#236'?u'#151#177#223#195#184
+ +#253#247'PA'#171#211#234'O'#30#3'G3'#253'@'#211'O'#4'*'#181#30'v^t'#18'L'#154
+ +'s'#176#212'oU'#18#248#221'm'#240#238#147#231'K}'#25#221'b'#210#156#131'`'
+ +#151'}'#206'M'#235'1'#217'b'#194#143#14#139#242'&'#0#249#1'\'#246'm'#224'm'
+ ,#175'I!'#0#139'6'#240'q'#153#201'M'#163#250#182#225#223#141#184'''?'#128#191
+ +#188#188'<g'#255
+ +#167'$'#0#201'G'#141#237#223#27#130'~'#23#172#254#244'Ih'#216#250'=2'#248#208
+ +#179#212#244'hj'#237#188#231#9'0~'#250'^C>'#214'p'#198#127#223#248'?h'#169
+ +#253'I'#234#203#232#22'S'#230#30#206#204#128'tB'#136#4'P80'#18#163'\'#0#218
+ +'"'#172'1'#136#171'ecJ2'#16#170#255'?V'#152#29#143#201#229#242'mx'#127'='#154
+ +#233#237'}u'#9#234'MTY'#251#175#239#190#251'N'#245'['#171'q~0'#170#254'R'#198
+ +#229#246'2'#2#208#26#242#160#160'|6'#18#0'7'#248'S'#171#230#186#255#202'y'
+ +#239#255#232#243#2't'#15#250#130'~'#254#250'%'#168#221#240'?'#22#178#234'o'#5
+ +#30'y'#246#13#150'"('#169#154#3#147#231#28#2'f'#155#244'YwR#'#26#14#194#27
+ +#143#158'"y['#179#158'0}'#215#163'`'#214#194#147#211'v'#248'1'#228#14#254#249#192#9'h'#3#167's'#208'gzA+'#255'A'
+ +#167#167#127#230'A'#178',8'#193'E'#148#136#0'hX('#245#5'h'#221#250#5#27#248
+ +'*Z'#145#187#141'N'#20'*'#13#28'}'#233#203#25
+ +';'#190#160#248'PYp'#8'5'#0#31#18#128'?D3'#2'VA$'#232'N!'#128#234'<'#251#11
+ +#26'Et='#222#220#138#191#231#237'h'#2#244#26#10#236#145#0'('#4'XXX'#168'B3'
+ +#192#248'K'#147#237#159#241#132'l1{@ '#128'q'#179#193'h'#202#7#147#137''''#0
+ +#26#3#206#183#1#207#4#9#188#243#216#185#224#239'E'#160#199#207#216#27'v?'#248
+ +#18#230')^'#245#241#19#3'N'#191'U'#170#180#176#199'!'#151#193#184#201#163#171
+ +#178'n8'#128'l'#223#215#239';6g3'#0#231#238's6'#211'&3'#5'!'#29#152'"'#1#212
+ ,#25#200#235#11#177'\'#0'J'#4#10#251#157')'#4'0'#222#234#248#135'N'#21'YK&'#0
+ +#229#2#224#234'O'#205'A\'#212'$t'#247#221'w'#143#12#136#0'('#7' '#20#10#25
+ +#127'm-x'#27#9#128'IF'''#1#204#5#163#217#10'f'#163#22#180'H'#0#212#9'H'#166
+ +#200'\'#15#128#143'W,'#7'{'#227#198#30#31'''/l'#193#184'i'#208'Z'#251#243#144
+ +#206'SX1'#3#150#28'u#j'#19#218#204#188#145'1'#12#10#239'>q'#1'x]'#205'R_'#198
+ +#14#160#26#141#195#255#144#217#182'd'#9'^d'#217#192#208'p'#20'<^'#158#0#234
+ +#215'B8`O!'#128'J'#139#227#13#189'*L'#197#18#201'\'#0#212#226#157'H'#6#221
+ +#230#2#244'J'#0'j'#181'Z'#19#139#197#140#155#28'E'#175#196#226#242#165#236#1
+ +#222#203'o+'#157#131'&@>'#243#1'P$@'#145't'#2'f'#134#1'V~'#240' l'#203'R'#211
+ +#13#5#146#201#220#253#206#131#234#153#251#15#253'`cH'#11#214'|'#254'LN'#166#1
+ +#31'p'#234'=`+'#158#148#209's'#8#233#192'q'#158#0#220'D'#0#254'0'#18#192#26
+ +'4'#1'\)'#4'0'#193#230'x]'#171#140#172#3'>'#27#144#186#4#247'6-'#168'O'#2#8
+ +#135#195#166'm'#29#165'OF'#227'r'#166#227#8#4'`)'#153#9'f['#17#24'y'#2#160'f'
+ +' '#178#12'N'#2'j'#174'Y'#3#255'}'#237#214#140'~'#208']a+'#158#8'K'#143#187
+ +'-'#235#189#238#199#176'#'#130#254#14'x'#251'og'#230#212't'#230#146#9#187#192
+ +'^'#199#220#146#241#243#8'EAqf'#2'D'#192#235#14#129#151#8#160'n'#21'DB'#30
+ +#238'9<'#1'L'#180#181#189#162'R'#196'6Q='#128#208#30#12'I'#192#209'S2PO'#210
+ +#154#204#2'D'#152'6'#180#218#238#143#198#21#201'('#0#17#128#185#136#250#194
+ +#151#128#201#164#3#131'^'#197#17'@'#134#235#0'^'#187#247'('#180#131#178#251#3
+ +#144#203#149'0{'#233#25'0y'#222'aY='#239#24'v'#196#166#213#239#194#143#159'<'
+ +'!'#245'e0'#208#140#132'C'#207#251'{'#210#241#156#13#196#248'T`'#143''''#8'>'
+ +'$'#0'J'#5#142#133#131')'#190#145')'#249'-+'#208#26#175#1'>'#25#8#247#13'('
+ +#252#164#1#248#186#235#11#208''''#1#168'T*'#243'f{'#254#31#195'1'#197#25#236
+ +#5'<'#1#152#10#166#176'D '#179'Y'#139#4#160'a'#4#192'f'#1'f'#144#4#200#14#244
+ +'8'#26#135'~'#160'A'#192'RP'#9'{'#31#127#27'h'#141'y'#146#156#127#12#28'>}'
+ +#233#6'h'#173#251'E'#210'k'#208#155#242#225#16#18#254',u`f&@'#28'X'#243#15'J'
+ +#0'r'#187#3#204#7#208'F'#169#192#209#136#152#0#18#211#11'[^'#196#191#235'I'#3
+ +'P('#20#219'"'#145'H'#3#222#223'>h'#2'@5'#194'R'#227'*'#188'>'#20'S^'#200'^'
+ +#192#11#184')'#127'"'#152#11#171#192'l'#210#128#209#160#3#165#138'k'#6#154
+ +#201'>'#0#171'>~'#156#173#2'R'#129'Z?'#239#188#240'$'#152#177'gzK>'#135#27
+ +#220#246'zh'#216#252#29#11#183#6'|.'#8#5#220#172'V_'#165#214#129'Zg'#2#173
+ +#222#12'Fk)TN['#12'zsAZ'#207'MCY'#222#127'J'#186#134#160#244#190#14'9'#231'a'
+ +#166#25'f'#11#156#15#144'/'#7#14'F'#160#163'#'#192#178#1#219#182#254#143'/'
+ +#20#226#228'Y.KDP'#3'x'#149'R'#128#129#171#5'`'#233#192#184#136#183#187'\.ow'
+ +#147#130'z%'#0#170#3#192#23'['#234#189#197#151#6'"'#202'd'#23'F"'#1#131#181
+ +#10#172'%'#19#193'd'#208#130#201#172'I'#154#0#178#12#134#210'i '#194#7'OH?'
+ +#158#219'd+'#133#165''''#252#31#232'-'#133'R_J'#198'A'#130']'#187#225'Kh'#218
+ +#242#3'ks'#22#244#216#7'4'#135#143#134#148#26#172#197'P1u'#1#236#180#240#184
+ +#180#9#206#215'o'#221#13'u'#191'~'#153#213#207#194'Z4'#30#14'<'#235'>'#188
+ +#149#253'|'#17#166#1#160#249#27'@'#193'w'#185#209#4#240#5#161'}'#235#23#220
+ +'c<'#1'('#229#241#224#164#188#214#127#226'M'#154#18'L'#234#255#214#190':'#3
+ +#245'J'#0#227#198#141#211#6#131'Ak'#141#211'r'#182'/'#172'Nz;H'#208#245#214
+ +'r'#176'P='#0#154#0'&'#147'6'#217#15' '#211'x'#253#158'c'#210'2'#201'v'#168
+ +#160#228#163'Is'#15#129#185#251#159''''#245#165#164#21'm'#245#235#161'n'#195
+ +'W'#208'^'#183#142#173#178#209'4'#142'B'#167#207#172#160'b'''#152#179#247#153
+ +#144'W:y'#200#199#219#188#250'='#248#241#227'''3>'#168#149#186'/O'#158#127'8'
+ +#204#217#231#172#140#158#167'W$'#184#17'a'#1#180#253']'#164#1'x}`'#223#254#13
+ +#255#16''''#207'*E'#204';)'#175#157#6'%'#146#218#207'4'#0#154#24'L#'#195#245
+ +'z'#189#167#191#4#192#10#129#208'VPVVVjc'#177#152'e'#187#211'|'#162'7'#172
+ +#185'+'#249#4'j'#9'f*'#5'['#201'4\'#253#181','#23'@'#165'Qr'#149#128#221#229
+ +'j'#164#145#23#254#243#236#149',3,W@'#17#130'='#127'w5'#148'T'#15#207#190#252
+ +'q$'#211#205'?~'#0'5'#235'>'#135#142#182#154'n'#11#174'2'#129#252#178#169#176
+ +#232#152#27#217'H'#173'!]?'#10#255#143#31'?'#1'['#127#250#152#13'2M+'#240'w^'
+ +'>y'#15#216#253#176'+'#178#155#23#210#141#12'%d'#192'f'#3#4#252'!'#232'p'#5
+ +#192#235'q'#131#163'ne'#138#3'P'#163#140'vT'#219#236'4'#187#190#129#132#159
+ +'6'#165'RY'#135'2'#220'6h'#2#136'D"'#214#6#183#249'w'#238#144#238'!'#241#147
+ +#180#166'b'#176#149#206'`y'#0'&'#139#142'M'#7'b'#29#129'2'#252#217#172#251
+ +#250#31#240#243#127'_'#200#222#151#209'O'#20#148'O'#135'%'#199#222'<,B'#134
+ +'^\'#217'7'#174#252#23#218#241#223#131#223#211'.Y'#145#13#249'T'#166#237'~$'
+ +#139#178#12#29'qX'#243#201'3Hd'#255'e'#205'C'#134#2#133#146#146#202#166#163
+ +#224'_'#206#18'}r'#1'T'#13#24#141#198'P'#245#15#129#219#229#7#175#219#1#206
+ +#134#31'S'#8'@'#167#140#216#171#172#246#143#128#215#0#168'"'#16#247#140#0#240
+ +#182#183#187#138#192'~'#17'@'#179#199#184#175'3hxZ'#252'$'#141#161#0#242#198
+ +#237#12'F'#163#14#205#0#29'k'#14#154#169'^'#0'b'#208'D'#222'7'#239#203#205
+ ,#194#16#25#170#138';-8'#22'v^'#156#190#198#144#233'BG{'#29#252#244#233#211
+ +#208#142'*~$'#228#151#250'rR`-'#154#0#251#159'y'#127#218'j1(g`'#195'7'#175'C'
+ +#253#198#175#193#215'A'#3#173#251'&8r`'#22'V'#238#12'Sw;'#2#138#170'fI'#253
+ +#145#236#0'z'#7#17'j'#7#230#9#162#9#224#199#247#213#14#206#198#212#238#200'z'
+ +'U'#184#165#210#226#248#12':}'#0#228#4#172#29#18#1#144#9#208#234#209#237#209
+ +#230'7'#254'#'#229#3#211'Z!'#191'b'#14#24'P'#253#183#152#245#172''''#0'u'#4
+ +#202'F3'#208#127#221'w'#18#251#146's'#21'Z'#163#13#22#163'z'#155'?n'#154#212
+ +#151#2#174#214#26#248#238#223#247#129#179')w'#204#166#238'@'#159#217'!'#231
+ +#254#13#212#250#244#14':!'#19#193#217#188#21':Z'#183#129#27'I'#208#227'jfu"F'
+ +'['#25'X'#11'+Y'#178#151#165#184':'#183#11#193'X'#166#31#215#11#192#235#13
+ +#176'('#128#199#209#12#238#150'u)O3'#170'C'#141#21#22#215#127#249'N@d'#2'l'
+ +#29#148#9'@'#155#216#9#232#244#171'f6z'#172')'#241'7'#133'J'#7#5'U'#187#131
+ +#193#160#1'3'#154#0':'#150#11' '#239#182#31'X'#186')'#225#203#127#222#153'u'
+ +#15#240'`0e'#215#195'a'#222#129#210#12#177#8#251#221#240#217#203'7'#131#163
+ +'i'#147#212#31'C'#191'A'#5'Y'#135#156#255'(k'#135'>'#154#209#157#190'B'#9'pa'
+ +'>'#9#168#3'M'#0'w'#251'v'#240#218'S'#167'#Y'#180#193#154'2S'#7'y'#6#27#248
+ +'$ F'#0#209'ht@N@BJ'#24'P'#169'R'#149'nh-'#250#2'_'#165'I>'#3#5#189'p'#194'"'
+ +'$'#0#29'X'#172'z'#208#27'5'#172'5x'#159'y'#0'i`'#131#230'mk'#224#211#23#174
+ +#207#202#151'1T'#152#11'*'#224#128#179#238#205#170'o`'#235#154#255#192#202'w'
+ +#31#206#154'C/'#157#160'<'#130#163#174'x!mSv'#135#5#250#180'P'#184#28#128'`0'
+ +#2#30'w'#0#220#168#1#184'Z6@'#160'#5)'#174#208#224']W'#160#247#253'D'#137'@d'
+ +#2#240#142#192#186'A'#135#1#137#0#240#133#164#147#21'ov'#20#191#30'K'#200''''
+ +'$'#159#129#4#144'W1'#15'L'#22#27'j'#0#6'V'#19#160#226'C'#129']'#223'O&'#140
+ +#130'W'#238'8l@'#241'h)A'#177#240#189'N'#184'%+'#145#130'O'#158'_'#14'-5'#185
+ +'99'#167#191#176#20#141#135'C'#207#127'T'#234#203#144#4'='#5#209'('#2#16#12
+ +#132'Q'#248#253#168#5#4#192'Q'#207#149#2#139'Qnv'#174'D3`'#19'%'#255#8#26#128
+ +#144#8#132#154#128'o'#192#4' '#164#2#227#193#138#183'8'#10#30#12#199#20#139
+ +#196#151'E]'#129','#249'e`'#178#234#192'd'#212#129'ZC~'#128#236#204#5'x'#239
+ +#209#11#192#217#178'-+'#231'J'#23#166#237'q$'#204';(}'#195'#S'#128'6'#226'{'
+ +#127#191'h'#216'}&=a'#194#236'}a'#193#145#185'7'#1'X'#10'P'#18#16'E'#0'('#4
+ +#200#17'@'#16#218#183'}'#3#177'h0'#229'y'#19#243#218'>U+'#226#164#254#215#163
+ +#224'3'' j'#2#245#129'@'#192#142'f'#128'w'#208#181#0#248'wQ'#141#211'v'#173
+ +'?'#162'Jq'#191#27#242#171#217#20#27#179'Y'#159#12#5#210'x'#176#158'k'#12#211
+ +#247#161#172#253#244'yX'#251#249#138#236#127#27'C'#196'n'#135']'#12'Sv;<'#189
+ +#7'E'#251#240#237#135#207'cN'#174#145#3#25#28'~'#201'c`)'#172#146#250'B'#178
+ +#131'^'#204#0'j'#6#18#165'n'#192'>'#206#254#247'z'#252#208#182#245#139#148#16
+ +#160'\'#150#136'N'#201'o'#249#8#5#159#194#30'uB'#30#0'nD'#8#246#129#214#2'$'
+ +#203#129#241#128'fd'#143#194'F'#143#229#20'wH'#151'B'#201'ZS'#9#228#143#155#1
+ +'&'#179#14#204'V=h'#132#178#224',('#1'>W'#11#188'q'#239#169#153'?Q'#154'AYeG'
+ +']'#189#2't'#166#244#21#21#189#247#247'K'#192#222#176'q'#232#7#202'1'#152#242
+ +#199#193#17#151'?#'#245'eH'#10'a&'#0#245#1#240'y'#3','#7#192#237'p'#160#9#240
+ +'Cj'#18#144'"'#234#169#206#179#127#129#247#181#161#204#210'J'#192'f'#3#12#182
+ +#28'8'#165#31#0#218#15#133#142#128'ai'#139#215#248#160#248'Ij'#141#5#10#198
+ +#207#3'#O'#0','#18#160'R'#176#142'A'#137','#12#7'}'#233#214'Cr"-x'#160'`?'
+ +#236'+'#158'K'#203#177'H'#19#250#9#183#145#138'='#143#184#10'&'#205#31#157
+ +#163#208'9$ '#30#163#8#0#239#0't'#250#193#213#214#0#238#214#245')'#4#128#182
+ +#127'K'#133#197#245#3#222'l%'#199#31#240#229#192#168#193#147#167'pp'#13'A'
+ +#168'%'#152#223#239'7!'#131#20'D'#19#170#201'['#157#133'o'#136'_'#163'P*'#161
+ +#176'z1K'#6#162'H'#128#206#168'ERP'#246'/'#23' '#13#252#240#206#131#231#177
+ +#24#239'p'#196#188#131#207#131#25#139#143#27#210'1'#236#13#191#193'{'#127#187
+ +'(g{'#229#165#3'r'#133#18#142#185#246#21#208#26#173'R_J'#250#209#143#175#141
+ +'u'#2'B'#251#159#28#128#140#0'P'#3'p6o'#1#175'c[J'#6'g'#158#206#191#173#200
+ +#224#166#196#128'VJ'#254#17'z'#2#146#6'0'#232#150'`BO@T'#31#10#240'GV'#190
+ +#201'Q'#242'J}'#246'F)'#191#167'A'#129'j'#227#207#184
+ +#251#179'A'#189'6'#28#244#195#138#27'G'#167'c'#172#176'r''8'#248#194#7'Xr'
+ +#213#136'@'#143#250'?O'#0#188#253'O+'#191#199#229'C'#18'p'#130#189'v%'#211#12
+ +#4'('#229#177#224#228#252#246#175#240#249#2#1#212#0#231#4#164#209'`-h'#198
+ +#187#131#136#1'M'#6#18#15#7#141'F'#163'6'#180'%J'#28'~'#221#190'->'#243#29
+ +#226''''#170#212'z('#172#222#19#140'&'#29#152'mD'#0'\B'#144#208'&<'#27'j'#192
+ +#11#215#31#8#145'P'#250#26'Wd'#3#244#3'>'#253#174#143#7#245#218'_'#254#251'*'
+ +#172'|{'#244#14'DUi'#13#176#223#153#127'd~'#148#145#138#4'_'#0'D'#241#255#160
+ +'?'#4#30#180#255#189#184'9[j'#192#221#250'['#138#227#215#160#14#219'+'#204
+ +#142#213'('#252#14#138#251#211'<'#0'>'#19#144'*'#1'['#7'3'#28#148' G'#155#129
+ +'U'#4#250'|>'#139'F'#163')'#142#199'a'#194'F{'#225#243#137#132','#217#29#129
+ +#170#168#24#1'X,'#204#15'`'#160#210'`'#230#7'P$'#29#129';'#156'-'#205'N'#235
+ +'_'#191'z'#19#190#249#231'_%'#249#162#6#11's'#193'88'#230#250#193#141#147#254
+ +#247#131#23'@k'#141#180#141'1s'#1'TA8m'#193#239'a'#206#1#167'g'#181'G_Z'#209
+ +#131#134'L+<'#133#255#200#254#15#160#253'/'#16'@{'#221'Z'#8#186'[S'#8#160#208
+ +#224#221'R'#160#247'Q'#185'g;'#17'@'#127#235#0#196#167#239#14';d'#3#226'V'
+ +#185#197#158#255#167'PL1#'#249'$'#20'rK'#241'N`-'#174#0#147'U'#143#4'`'#0#173
+ +'A'#13'*%'#154#1#138#204#205#10#236#138'Wn;'#10'|'#206#214#236#156','#13#152
+ +'0go'#216#231#140#255#27#212'k'#159'_~'#0'D'#130#185'U'#211'/%'#168#15'C'#233
+ +#164']'#160'z'#151'}'#161'j'#230#226'a'#31'2dFz'#156'S'#255'#A'#222#254#167
+ +#30#0#184'o'#222#252#5#196'#'#225#20#2#24'o'#181#175#210#169#162'-x'#179#29#6
+ +#144#5#200'>'#187#222'>W'#241't d'#146'B4'#5'*'#154#188#182#179#221'!'#237
+ +#209#201'''Q'#131'PK)'#228'W'#206'dQ'#0#163#197#0':'#147#150#21#6#201#149#217
+ +#233#15'@h'#217#250#19#252#251#129#225#227'%^t'#194'r'#152#186#231#224'R'#130
+ +#159#185'b'#201#176')'#132#146#2#148';'#160'3'#231#225#162'4'#30'J'#170'g'
+ +#195#196'y'#251#131#9'5'#174'a'#131#4'7'#9#184#211#254#199#213#159'e'#0#182
+ +#131#189#230#7'6"L'#144'c'#133'<'#30#153#146#223#246'5'#10#186#7'e'#141'V@'
+ +#178#251#5#2'h'#196#197#219#217'S'#18#16#161'W'#2#16'&'#4#163#253'o'#212#233
+ +'t'#249#241'x'#188#188'#'#168']'#220#232#177#220#156'|'#18#10#184'R'#163#131
+ +#226#137#11#153#31#192'h3'#128#158#18#130#180#252#184#176#12'N'#12#238#138
+ +#183#239#251#3#180'n'#27#218'l'#192'l'#225#212'?'#127#0#154'A6'#191'x'#242
+ +#210#133#144'v;j'#132#131'HAo)'#128#252#242')P>mw'#152#186#224#240#156'4'#27
+ +#216#234#159#224#212#255'('#170#255'd'#255#147#240'3'#251#191'y+'#218#255#155
+ +'Xn'#128#0#163':'#212'^aq'#145'='#216#129#178#216#140#143#17#1#176#8#0'.'#220
+ +#212';'#189#199#193#160#132'>'#9'@'#28#10#196#251#202#240#160#213#155#28'%'
+ +#143#196#19'2'#29'{'#18'k'#5'.'#135#194#9'{'#128#201'f'#227#205#0#174'.@AZ'#0
+ +#171#14#236'>)'#168#219#147#14#225#195#11#184#29#240#210#141#135#231'|^@~'
+ +#197'T8r'#217#179#131'z-E'#0#158#191'f_'#169#223#194#176#135'J'#171#135#165
+ +#167#222#2'U'#179#150'd'#252'\'#253#253#221#211#243'h'#177#140#199'x'#245'?'
+ +#20#129#128'7'#136#194#239#227#226#255#219#127#132#128#167'-%'#2'Pd'#240'l'
+ +#201#211#249#182#163#28#186#144'8'#154#132'$ '#218#227#202#223'b0'#24'X'#8'p'
+ +#221#186'u'#20'7'#140'ww'#222#30#175#137'"'#1#223'}'#247#157'*'#16#8#232#208
+ +#20#176#161#9'P'#138'D0~'#155'3'#255#250'`T9C8'#4#249#1#172#165#211'Q'#229
+ +#170#2#163'@'#0'z'#13#168#132'h@'#182'T'#0#196#202#127'='#12'k?z1k'#231#27'('
+ +#232#179'8'#254#246'7'#192#152'W:'#168#215#7#189'Nx'#241#218#209#25#2#204#4
+ +#138#170'g'#194#129#23#220';hm,'#221'`'#222#127'Z'#253#163'Q'#8#163#250'O'
+ +#246#191#151'%'#0#249#161#5#237#255'h'#23#251#191#218#214#190'J'#173#136'R'
+ +#248#207#129#127'6R'#8#144#239#7'H'#154'@k$'#18'q{<'#158'Pw!@B'#175#4'@'#155
+ +#16#9#160#230#160#212#23#0#239#171'j'#246'ZNv'#5'uG'#8'O$'#2#208'['#202' '
+ +#175'b&'#18#0#154#1'f'#3'W'#23'@'#141'B'#217#200'0'#25'd'#205#14'@'#188#255
+ +#224'%'#208#176'ae'#214#206'7'#16'L'#156#191'?'#236'}'#214#29'C:'#198#147#23
+ +#238'.'#245#219#24'Q '#243'`'#223's'#239#204#138'6'#208#27'HB'#168#244'7'#30
+ +'E'#2#8#161#250#31#8#129#223#205#169#255'n{+'#180'o_'#197'Z'#131'u'#14#2#137
+ +#133'&'#229#181'}'#143#194#239#195'?'#237'|'#8#144#217#255#168#181#215#247
+ +#214#12'T|'#206'^?'#27#161'3'#144'^'#175'7'#1#31#9#240#132#212'{'#214'uX'#151
+ +''''#15'"''?'#128#22#138'''.b'#171'?e'#4#234'L|8'#144#175#13'`'#166'B'#22'?'
+ ,#204'Wo>'#10#220'm'#245'Y'#3'p;'#202#27#253#221#209'S'#17#144#128'~'#17#0#213#4'x<'#30
+ +#180#2#244'Vr'#4'"'#17'T5{'#244'G8'#2#198'dA;'#9#184'Zg'#132#162#137'{2'#2' '
+ +#13'@'#199#178#2'5'#172'6@'#208#2#178#146#27',B'#243#230'5'#240#254'}'#23'B4'
+ +#18#202#234'y'#197#216#237#168'K`'#246'Ag'#164#237'x/\'#181#31#174#6'C'#155
+ +'~3'#134#238'A'#157#154'N'#185#247#163#172#159#151#171#252#227#212#255'p0'#12
+ +'Ao'#144#9'?'#173#254'T'#244#229'j'#222#200#156#131#130#253#175'VD'#253#19
+ +#243#236'?'#226#223#148#17#230'@'#18'`'#14'@'#222#254#167#134' }:'#0#9#253
+ +#145'F9'#146#128#18'I'#128#210#127#205'h'#10#20'#'#9'T'#198#19#138')'#155#157
+ +#133#183''''#18'2V'#149'A'#194'M'#13'B'#10'*'#231#161#25'P'#8#6#19#18#0#211#2
+ +#136#0'T'#160#16'*'#4'3gK'#198#223#195'h'#197#180'%G'#193#226#211'o'#202#206
+ +#201#184#170#31#142#0#248#216#127#208#23'd'#130#207#212#127#167#19#9#224';'
+ +#212#12'"b'#251'?1)'#191'}'#21#170#255#228#8'"'#251#159#26#129#214'R'#248#15
+ +#23'h'#234#1#208#136#194#239#232#203#254''''#244'G'#10#153'#'#16#15#166'"?'#0
+ +#10'p>'#158#168#140#252#0#206#128'vi'#179#215#194#21'h'#147'#PFf'#128#14#205
+ +#128#5#140#0'H'#3#224#162#1#252#244'`j'#24'*'#151'u'#27#17#200#240'P'#225'$'
+ +#26#127']'#9#31'>|%D'#130#190'L|'#157'L'#203#153#186#232#8'Xr'#234#13'd'#23
+ +'e'#228#28'O'#253'a7'#246#131#24'Cf`*('#131#19#239'zw'#200#199#233#235'7-<'
+ +#206#21#254#196#208'LE'#2' '#231#31#18'@'#160#131'['#253#157'M'#155#192'M'
+ +#222#255'h4'#169#254#235'U'#225#142'J'#139'c'#29#202'Q'#0#239's'#1#215#4#164
+ +'V'#176#255'qk'#17#154#128#160#240'G'#249'S'#13#158#0#186#250#1#144'eJ'#240
+ +'~'#234#215'\'#189#201'Q'#180'<'#22#151'S'#136#144#17#0'e'#255#217#202'g'#130
+ +#185#176#140'#'#1'3o'#6'h'#133#204#192#206'nA;'#148'Bw'#185#154'L'#182#186
+ +#219#248#191'7'#224#199'w'#159#2'O['#250'Zj'#149'M'#155#15#251'^xOF'#139'Q'
+ +#234#214'~'#9#31#220'?z:'#1'I'#1'J_?'#231#137#31#134'D'#224#221')'#184']'#127
+ +#207','#251'/'#193'y'#254#185#213'?'#138#230'j'#136'y'#255'I'#253#15'P'#243
+ +#143'-'#223'@'#200#239'I'#137#255#151#24#221'[l'#186#0#165#249#250#241'>'#150
+ +#0'$'#148#0#227#177#234'PKo'#235#143#253'/\C'#127#192#252#0#168#5'h'#220'n'
+ +#183#5#217#165#8'OXIf@'#131#219'r'#130';'#164#221#141#29#140#198#131'+'#20
+ +#172'8('#175'j&o'#6#232#144#0't'#160#210#169#147'Z'#128#16#17#200#5'8'#27#182
+ +#194#183'/'#255#5#26'~]'#201#134'F'#14#4'T'#133'f-'#29#15#19#230#239#15';'
+ +#239#127'2h'#12#153#207'&{'#239#238'?@'#195#250'o'#165#250#184'F'#13#246#189
+ +#240'n'#168#222#245#128#140#158'#!'#168#255#148#249#23#137'B4'#200#169#255'd'
+ +#255#7#220'T'#252#211#10#142#237#171'!'#134#143#197#249#231#202'e'#137#216
+ +#228#252#182#213'2'#136#7#248#248'?9'#131'X'#252#31#229#170#6'o7'#160#156#182
+ +'['#173'V__'#246'?'#161#223#4#128'f'#128'\'#156#15#128#251'rd'#155#9#193#152
+ +'v'#238'v'#151#237'\v02'#3'P'#184#149#26'5'#20#146#25'`6'#161#9#192#145#128
+ +'Z'#199#229#4#144'/@&'#242#5#236#176#234#15#225'"'#135#2'R'#177#234'~'#254#10
+ +#26#214'}'#11'm'#219#214'1'#205#128'&'#203#138#175#130'VvKq'#5's'#16#149'M'
+ +#159#15'e;e?#'#239#233'sw'#131'hX'#186#136#198'hA'#213'.K'#225#192#203#31#24
+ +#212'k'#251'j'#132#155'L'#250#137'sC?c'#164#254#211#234#31#8'A'#136#188#255
+ ,'l'#245'G'#245#191'a=x'#237#245')'#225'?'#179'&'#216'^fr'#209#196'W'#26#11
+ +#228#22'*'#0#137#0#132#30#128#129'@'#192#137#230'z'#159#246#127'w'#215#214
+ +#227#243#132'|'#0#178#1#168'0('#26#141#150'Q8'#16#31#155#176#197#145#127'a8'
+ +#166','#226#252#0'\4'#192'R6'#13#204'EU,$H~'#0#202#9' -@'#201#198#135')'#144
+ +#4#184#196#160#28'Q'#4#134#5'>z'#248'*'#216#246'}'#246'CT'#163#17#182#242'Ip'
+ +#236#31#223#200#216#241')'#233''''#17#3'V'#214'M+'#249'C'#250#15#156#224#226#254'@'#158#255'8'#231#249#143#6#195','#243
+ +#143#169#255#168#250#19#9#216'kV'#163#25'`gY'#172#130#250'o'#211#249#27'K'
+ +#140#30'R'#247#131'|'#250'/'#27#3'F'#241#127'R'#255#169#1#8#154#19#142#190
+ +#242#255#197#24#136#228'%'#195#129'V'#171#213#24#12#6#169'Sp'#25#17#0#238#171
+ +'j'#156'yg'#4#162#170'*'#193#12#160#162#10#163#173#4'l'#21#179#144#0#180'<'#9
+ +'hy_'#128#154'9'#3#169'T'#24'dBX'#176#135#14#194#144'$'#205'~^e'#250#191'3)A'
+ +'~'#136#215#151#31#1#174#198#209#212#2'\zP'#133#224'9'#207#241'c'#214#135#26
+ +#141#226#139#253#19#252#129#216#234#207'l'#127#170#250#139#176#208#31'9'#255
+ +'H'#240#131'H'#0'>G'#27'8jWC$'#28'I'#241#254'O'#176#182#175#213#170'b'#30'R'
+ +#255#241'O'#23'5'#0#1#222#254''''#239'?'#223#16#164#163#183#6' '#221']Z'#191
+ +#223#134#16#14#164#254#0#248#183#21'U'#13#150#21'H='#2':'#130#186#5#141#30'3'
+ +'+'#17'f'#177'~'#185#2'Tj5'#20'T'#239#10'z'#139#141'E'#2#136#0'4d'#10#176'f!'
+ +'*'#166#5'0_'#128#140#159'(<'#194#132'w'#168#160#130#159#215#151#253#14#127
+ +#16'cI?'#217#134'B'#165#129#179#158']'#157#222#131#242#131'>'#133#142'?'#204
+ +#246'G'#2#8'3'#225#231#9#0#247#142#186#159#192#239'la'#142'iA'#253#215#169'"'
+ +#238#241'V'#199#175#188#250'O'#9'@'#164#254#179#240#31'%'#255#144#250'O'#225
+ +'?\'#160'='#253#9#255#9#24#16#1#208'&'#152#1#8#19#153#1#148#21'H'#4#128#143
+ +'Umu'#22#156#25#142')'#11#133'.A'#20#247'7'#228#149#129'm'#220#206'I-@C$@CDY'
+ +#179#16'!/'#128'F'#137'e?E8'#151'AQ'#136'7'#174';r'#172#234'O"'#168'tF8'#227
+ +#201#244#246#148#16#135#253'('#238'O'#158#255'H'#16'U'#127'"'#0#15'n>'#170
+ +#254#179#163#250#191#10#205#189'0'#243#15#8#234#127#185#217#185#193#168#14
+ +#145#211#143#169#255#192#13#1#173#23#17'@'#147#160#254#163'lF'#250#10#255#9
+ +#24#168#196'13'#160#176#176'PE#'#195#168':'#144#6#134#224#133'T'#145')'#224
+ +#10#234#23'4{'#205#7#2#175#210'S'#21' '#211#2#198#239#14':'#139#5'4F'#29's'
+ +#10#170#13'|'#207'@'#181#138'=G!'#231'g'#9#202#248'K'#234'O'#154#224'`'#223
+ +#193'0@'#235#166#159#224#223#183#159'6,'''#31#143#20'h'#205'yp'#234'c_u'#255
+ +'`_b'#213#205#239#151#21#251#240#163#190'H'#176#227#201#213#191#211#249'G'
+ +#171#191#179#254'g\'#253#155'8'#231#31#175#254'k'#149#17#239'x'#171'}='#10'{'
+ +#132#138#127#200#251'O'#237#191#240#200#181'|'#2#16#169#255#164'&v'#168'T'
+ +#170'`w3'#0#251'{'#169'}>_0'#3'('#26#128#127'['#168'K'#16#158#188#130#8#0#168
+ +'m'#184#179#240#244'HLa'#21'j'#3#148#168#234#27#243#202#193':n:'#168'Q'#11
+ +#160#193'!D'#4'j'#22#18'$'#18'P'#240'aA9?V|'#16'W5'#130#176#229#235#247#224
+ +#243'G'#174'a'#182#223#24#164#3#133#1#143#190#251#157#244#28#140#15#252'S.'
+ +#127'"'#202#175#254'h'#223'G'#130'a^'#253#15#176#172#191'@'#135#19'W'#255#239
+ +#185#213'?'#130'$'#193'1'#7#140'3w'#252'f'#214#4')'#244#23'F'#185#242#240#201
+ +'?'#228#253#167#240'_'#13#202'"'#205#4'l'#31#136#247'_'#192'`D-'#165'8'#8#184
+ +#193#161#204#25'H'#154#128'#`X'#208#234'3-'#21'F'#131#145'3P'#169#209'@'#225
+ +#132#221'@k'#178'0'#19#128#242#2'Th'#6#8'Z'#0#171#20'Lv'#16#150'%'#157'&'#253
+ +'m$:R'#176#254'?+'#224#235'g'#239#200'l'#14#244#24#250#133#233#251#159#8#11
+ +#207#186'eP'#175'M'#249#221#242'!?'#230#253#143'q'#5'?'#156#237#31#134#8#31
+ +#250#163#212'_'#218';'#27#214#129#223#209#8#209'H$'#25#251#215'('#162#254#9
+ +#182'v'#234#250'K1}'#10#3'Q'#247#223#22'~'#213#175#193#191'k)'#249#167#175
+ +#246#223#189']'#235#128#223#159#208'-'#24'm'#13'='#178#143#141#204#0#188#191
+ +#146'i'#1'2Y'#229#22'{'#193'I'#145#184#194#196'r'#2#228#10'P'#170#149'`'#200
+ +#175#2'k'#233'T\'#253#181'H'#2#168#5#232#185#196' V)H'#179#4'),'#168#232#140
+ +#10#176#19#245#148'" zk'#178#228'?'#195#27#171'^{'#8'V'#191#254#176#212#151
+ +'1'#6#30#135#223#186#2'J'#166#207#239#246#177#148#223'_/'#191#189#4#223#232
+ ,'#E'#245#167#213'?'#24'a5'#255#17'?'#231#252#11#177#216#127#7#180'o['#9'Q$'#6
+ +'z'#14#181#6#163#215#149#153':'#182'X'#180'A'#154#248#19#225'{'#255#145'&@+>'
+ +#9'>'#133#255#234'q'#223#170#211#233#220'='#13#0#237#13#131'"'#0'J'#10'B'#150
+ +'a'#205'B'#3#129#128#153'J'#132'c'#177'X'#5'e'#6'rZ'#128#17#181#0#227#158#130
+ +'3'#144'T|'#138#255#231'O'#216#3'W'#127#19'G'#2#212'4T'#207#151#10#147'CP'
+ +#221#233#16#148#241#166#128'l'#7#233#30#204#202#152#251#236#240#213#147#183
+ +#192#175#31#189','#245'e'#140#129#7#253#6#207'~'#249#215#129#190'Jt;'#145#12
+ +']'''#189#254'd'#207'Gx'#199#31#173#254#254'P'#210#251'O{W'#227#175#224'u'
+ +#212#177'~'#0#148#31'@i'#194'jE4Pmk'#251#5#229'!'#138#199#160#252'o'#15'nT'
+ +#250'['#207''''#255'lG'#217'#2p'#244#167#246#191#175#171#30#208#187'%g'#160
+ +#201'dR'#163#218'a'#196#191'Yj0'#229#3#224#237'*|'#175#228#11'8>'#154'P'#232
+ +#153'3'#16'Ww'#188'P0'#20#146#22'0'#133'9'#1'Y8'#144'6=_)H)'#194'h'#6'P'#18
+ +#145'L('#22#202#206'lQIa'#175#217#0'o.'#251#157#212#151'1'#6#17'J'#166#205
+ +#135#195'n'#127'iH'#199#232'n'#245#143#161#240#179#184#127'0'#196'9'#255'|A'
+ +#206#1#232'qC{'#205'w'#168#25#132'x'#207'?'#183#250#151#24#221#219#172'Z'#127
+ +#155#200#249#151','#253'%'#225'GY'#169'C'#185'k'#182'Z'#173'.'#148#195#192'@'
+ +#156#127#2#6'M'#0#130'3'#16#153'G'#231'r'#185#200#233'W'#140#23'T'#1'\'#153
+ +'pe'#155#207#184#208#30'0'#206'Kj'#1'H'#2'*'#141#22#242'(='#216'bE'#2#208'$'
+ +#137#128#180#3#133'P($T'#11#138#251#6#140'`'#22'x'#251#250'c'#161'u'#211#26
+ +#169'/c'#12'"'#28'q'#215#155'PP'#189#243#160'_'#207#249#252'D'#141'>H'#168'#'
+ +#188#227'/'#192#173#254'L'#248'}AF'#4#174'z'#180#253#157'h'#251'S'#211#15'z.'
+ +#190'T%'#139#134'&'#230#183#255','#227'l'#255#16#18#0#139#253#163'l4'#144#240
+ +#227'mr'#0#178#206'?]b'#255#253'V'#255#9#131'&'#0#232#146#19#128#23'H'#163
+ +#195'h'#0'[%nU1'#210#2#28#133#199#198'P'#180#217#160'p'#210#2'P'#192'u'#150
+ +'"'#176'U'#204'fu'#1'I'#2'`'#14'A$'#1'V.'#204#153#2#192'L'#7#254#242'Fh'#170
+ +#176#223#217#10'/'#159#183'p'#204#233#151'C0'#20#148#194#9#127#255'b'#208#175
+ +#151#241#169#190#204#8#136'w'#198#252#185#130#31'A'#245#199#205#31'`'#197'?'
+ +#1#23'e'#253#173#225'<'#255#209#206#213#191#216#232#169#177'i}'#173#252#234
+ +'O'#153#127#212#5#150'B}'#245'T'#246'KN@Z'#253#145#0#156'~D'#127'S'#127'w'
+ +#184#222'!|V'#201#10'A'#179#217#172'#g '#222#199'B'#130#184#175#162'=j'#1#11
+ +#218#253#134#185#204#169'Ge'#194'D'#2'j'#13'X'#199#205#0'}~)S'#255#213#6#29
+ +#211#6'Tz'#13#31#22#228'{'#6'$'#253#1#248#142'd'#217'm)'#158'-|'#244#231's'
+ +#161#246#135'O'#165#190#140'1'#136'p'#240#205#207'C'#217#172#133#131'|5'#159
+ +#236#203#219#253'B'#177'O'#156#217#254#188#234'O'#4#224#193#149'?'#192#217
+ +#254#142#237'?@'#200#211#193'&'#1'1'#2#192#255'T'#242'hp'#162#205#142#182#127
+ +'"'#202#135#254#216#234'/'#196#254#129#235#250'['#143'2'#215'N'#206'?'#170
+ +#252#235#173#243'oo'#24#18#1#144'3p'#221#186'u'#172'QH '#16'0'#161#6'P'#128
+ +#23'Im'#195#153#22#128'W2n'#155#179#224#247#225#184#202'"h'#1#148#2#172#209
+ +#27#208#20#216#13#212#148#19' '#242#5'(u'#184'Qr'#16#159#27' h'#2'2'#161#157
+ +'xOq'#193#158#222'E'#142'/'#172#207#158#176#19#174#12'c'#181#253#185#130#202
+ +#249#251#192#254#215'='#193#253'1'#136#223#148'X'#248'i'#229#135'8'#151#238
+ +'K'#142'='#177#227'/B'#234'?'#222#246#180#214#128#167'e'#243#14#171#127#185
+ +#197#181#209#168#10'R'#184#143#250#190#177#208#31'n'#173'(_'#245'|'#209#15'%'
+ +#0'5S'#230#31'j'#224#254#193'8'#255#4#12'uYMf'#6':'#28#14#189'R'#169#180#225
+ +'E'#22#227'F'#137'AL'#11#240#133'5'#211#235#220#182'}'#4'-@'#193#180#0'5'#24
+ +#11''''#128#185'x"'#175#5'p$'#192#180#0#161'u'#24#223'>'#172#147#4#248#203#29
+ +'A'#138#192'sD'#0'c'#21'~9'#1#26#22'z'#242#243#171'Q'#251'T'#15#238#0#188#25
+ +#215#185#242#243#170#127#152's'#252#145#131#143#179#253#3#16#246'"'#17'x=,'
+ +#233''''#18#12'B'#140#250#253'E'#185#196#31#20'|G'#133#197#181#5#15#21#19'V'
+ +#127#161#237#23#169#253#192#245#252'k'#224#203'~'#221'}'#245#253#239#11'C&'#0
+ +'A'#11#160#182#225#168#9#144'/'#160#0#137#128#249#2#144#8'H'#19'(k'#240#216
+ +#246#246#132#181#149'r'#150#29#168'`5'#0#10#10#11'V'#206#3#141#201#10#26'#g'
+ +#10#168#146#17#1'5'#243#7#176'b!'#218#152'#'#145'+'#27#30'I'#166#192#138#211
+ +'v'#129#144#215'%'#245'e'#140'zP'#225#218#161'w'#188#10'E'#211#230#13#234#245
+ +#9#174#212#143#247#250#199#217'l'#191#4#223#230'+'#30#140'$W'#127#138#251'3'
+ +#199#31#222'v5'#252#2'AWK'#202#234'/C'#218#168'F'#213'_)'#143#134'zZ'#253#5
+ +#207'?n'#142#254#182#253#234#245#189#167#227#243#19#215#7'h4'#26#214'4'#148
+ +'O'#15#166#188#128#242'h\^'#177#213'Yxp'#2#215'uA'#11'P'#168#212#160#181#20
+ +#176'ra'#181#174'S'#3'P'#11'Z'#0#229#6#8'Q'#1#190#155'0'#136#202#134'G'#130
+ +'_'#240#213's'#22#130#175#189'Q'#234#203#24#213#160#197'e'#191#27#158#132#10
+ +'T'#255#7#140#132'x'#166#31#231#244'#Afv?'#173#252#225#8'K'#250#137#6'B'#172
+ +#221'W'#132#247#250'S'#165#159#139#154'}'#160#240#211' '#16'a'#245'/'#212'{'
+ +#234#10#244'>'#10#243'u]'#253'i'#236'7'#181#253#222#142#130#223'@U'#127'H'#8
+ +#238#129#230#253'w'#251#254#211#241#25'v'#213#2#240#194#10#132#136#128#160#5
+ ,'8'#2#198'9'#173'~'#211'l'#210#2'@'#161'`'#14'A'#5#154#2#150#178#157'@'#159
+ +'W'#202#146#130#152#240#147#22#160#227'H'#128#181#15'S'#241#237#196'EY'#130
+ +'2y'#186'.]Z'#252#235#210#3#193'Y'#187'Q'#234#203#24#189#192#223#210#146#203
+ +#255#10#19#247#26#194#236#6#22#231#7#214#224#143#229#250#243'N'#191'X'#132#19
+ +#254#8#175#250'G|'#156#6#16#246#243#142'?'#159#155#21#4#9'q'#127#149'<'#26
+ +#168#206'k_'#143#199#139#241#171'?y'#254'Y'#213#31#173#254#184#175'U('#20#181
+ +#180#250'k'#181'Z'#7#146#192#144'W'#127#246#17#164#235#163#236'N'#11' _'#0'p'
+ +#17#1#26'$R'#180#213#153#191#127'8'#166#178#10#217#129'$'#220'j'#189#145#229
+ +#6#168#13'z.)'#136'O'#17'V'#178#220#0#222#20'`'#141'D'#249#14'Bra'#196#24'$'
+ +#213#128#225'J'#5#31#222'r24'#174#249'R'#234#203#24#149' '#13't'#191#27#159
+ +#134#178'9'#139#7#252'Za'#213#231#179'}x'#187#159#19'~Z'#209'i'#245#143#133
+ +'"'#201#176#31#229#252'GI'#248'q'#239'i'#217#10#222#214'm'#140' '#152#237'O9'
+ +#255#248'_'#165#217#177#193#160#14'S'#166#31#9'4y'#134#133#145#223'Md'#251
+ +#147#240#163'L'#213#167's'#245''''#164#141#0#186#243#5#0'7H'#180#146#15#13
+ +#150#249'#'#234#9#181#238#252'%l'#29'Wt'#154#2#134#252'r0'#151'N'#229'j'#3
+ +#152#6' r'#8'R'#247' '#149#146'+'#24#18#154#137#178','#193#225#239#24'l\'#243
+ +#5#252#231#230#147#165#190#140'Q'#7'CA'#25#28'~'#223#187'h'#130#230#15#252
+ +#197#157#195'y:'#139'|'#226#156#205'O'#182'?'#173#234'L'#245#167#132#31'a'
+ +#245#199'-'#26#8#254#127'{_'#22'kYv'#158#181#246'x'#230's'#238'XsWwW'#187#219
+ +'v'#187#227')'#241#0'v'#136#193#145#8#194'F'#8#5#148#4')'#145#176'P'#132#132
+ +#20#241#18'!9'#188#0'/H'#188'!'#224#1'x'#2#9#17#144#128'XHH$`x'#128#7#144#172
+ +'$'#216#198#221#158#186'k'#174'[w:'#243#176#7#254#239'_'#255'Z{'#237'}'#207
+ +#173#186#213']w'#170#190'K'#218'w'#15#247#12#251#236#189#191#239#159#255#165
+ +#166#253'='#181#243#222'wT2'#155#209'k'#23'\'#25#8#159'A;'#158'n'#223#232#238
+ +#161#229#19#192#159#152#184'?:'#254#162#230'_'#233'Y'#127'n/'#145#254#0#255#7
+ +'*'#27'}'#158#208')E'#4#136#173'V'#137#165'.'#139#22#128#174'A'#215'Q:|o'#208
+ +#251'b'#127#214'x'#153'+'#255'B"'#129' d'#144#247#174#146')'#176'zUH@'#8#160
+ +#225#248#3#184'V@'#155#2'l'#14#248#158'T'#15#150#127'I'#158#23'?'#201#243#206
+ +'x'#28#144#198#191#254#181'O'#169#217#197'D'#159'''3'#232'ay'#245#203'_S'#191
+ +#240#219#255#248'H/_'#250','#229#198#225'/'#137'>'#22#252#186#208''''#227'2_'
+ +'m'#247'c'#129#218#191#24'C'#19#152'p'#155#175#249#184#207#182#191'Q'#253'=z'
+ +#247'k'#171'['#127#28'x)'#138'}JY'#127#180#127'_<'#255'h'#251'u'#239'yK'#127
+ +#254']'#207#243#242'.'#203#11#160#31'q'#21'~'#0#163#5'dyp'#229'G{'#27#191#152
+ +#229'~'#13#0#246'E'#11#136#234#13#181#242#210'gT'#173#211#213'&'#128#144#0
+ +#182#131'Z'#173'0'#5#196#31'P'#174#28'<'#191'Z'#192'w'#254#229'?P'#127#244
+ +#187#23'U'#128#199'=z/}D'#253#153'o'#254#11#213#189'~'#235#253#127#8'W'#248
+ +#228',ssW'#242'['#187#159'l'#250#217'\K'#127'V'#253#167'"'#253#231'j'#255#222
+ +#247#213'd'#239'>{'#253'a&(N'#249'e'#199#223'{'#235#205#17'z'#251'C'#250#163
+ +#3#12#247#251#163#5'Y'#128','#253#197#7#240'p>'#159#239':'#158#255#15','#253
+ +'1'#158'7ll'#227'Pd'#7#146#22#128'9'#178'.!'#18' Q'#1#172'/'#239'Oko'#220#31
+ +#174'~'#206#19#135#160'1'#5#226#246#138'Z}'#233#211'l'#2'@'#250'G-q'#8'J'#243
+ +#16'?'#150'Ta3'#211#176';'#229#184#167'='#186#207#214'A'#244#244'G'#150#204
+ +#213#191#250'K'#175'?'#243#172'D'#23#227'h'#163#181'y]'#253#220'_'#251#166'z'
+ +#229#231#223'g'#193#149#17#252'z'#30#175#178#211#15#246#187#145#252'H'#248
+ +#129#228'g'#2#152#217#176#31'r'#255'G'#219'w'#200#246#127#135'$'#255#140'I"O'
+ +'u'#185'o=\'#244'_'#233'm'#191#157#231#252#137'\'#239'o'#26'~@'#250#211#254
+ +'m4'#251#132#244#199#12#192#181'Z'#13'>'#130#217'Q'#27'~'#30'e'#251#6'x'
+ +#138'/'#237#248#203'otw'#223'i'#199'3'#132#249#172#227#143#176#129#164#159'-'
+ +'H|'#241#252#179#227#143'0'#180'3'#164#177#183#183'7{'#214#134#31'O'#27#199
+ ,'B'#0'J*'#5#209'6'#140#206#187#213'h4`'#10'\VZ'#250#223#148#245#165'E'#26'\!'
+ +#18#248'R'#166#194#136'I'#128#147'~"'#235#15#136#219#29#173#1#136'C'#16#25
+ +#130'a='#226#181'o'#138#134'l'#142#128#152#3'b'#18#148#148#128'e'#191#242#164
+ +#177#246#148'+'#253'?'#255#225'o'#169#31#253#193#191'='#225#147'z1'#6#188#249
+ +#31#251#139#127']'#253#204'_'#254#155#207'>'#163#239#147#158#13#145#250#182
+ +#194#207#218#252#162#250'/t'#184#143#19'z&s'#209#0'D'#253#167#237'>'#236#254
+ +#253#251#252#154''#174
+ +#230#163#254'i'#159#202#185#25'+/'#127'T}'#246#27#127'G]'#255#220'W'#223#215
+ +#251#151#206'>g5'#254#188'P'#251#179'\l~'#29#235#207#165#188'W'#199#251#181
+ +#218#159#10#248#19'&'#130#153#26'o'#223'S'#253#135'?`'#211' [,'#172#215#191
+ +#17#206#251'/'#147#221'/'#223#4#213#31'&'#192#152#22#132#130#224#12#180#170
+ +'?-'#152#231#15#14#193#145#211#236#243#185'I'#127#251#155#143'iX'#135' &'#20
+ +'%'#192'cZ'#241'Mt'#14#130'/'#0#166#0#189#230#10'-k'#15'G'#189#183'v'''#205
+ +#151#141'w_;'#250'b'#213'\'#135'?'#224'u'#21#213'$1'#168#17'["'#240'M[q'#19
+ +#30#180'='#5'i'#9#138#217#134'r'#201#21'8'#15'n'#129'{'#255#231#191#169#255
+ +#250';'#191'z'#218#167'q'#166'Gs'#253#138'z'#233#203'_S?'#243'+'#191#165#234
+ +#171#155#207#245#179'M#'#15'//'#8#0#21'}'#153#16#0#219#253#146#230#11#149#30
+ +'E> '#0#150#254#0#255'Tk'#1#179#193#158#218#187#253#135#244#191#194#238'W'
+ +#176#251#189'd'#241#234#202#246#247'B'#178#255#149#168#254#180'L'#137#4'0'
+ +#203'/:'#253#222#147'f'#159'w$'#1'h'#219'8'#254#158'W'#216#175':'#142#149#0
+ +#224#16#252#214#183#190#197'MC'#136#201'Z'#244#195'`'#152']'#22'-'#0'$pM!J'
+ +#160#188#149'w'#247#214#190'0Kk=eH'#0#210#157'H'#160's'#249'5'#186#233'/IRP'
+ +#205'j'#1#8#13#194#28#240'b'#157'#'#160#195#131#18'"4'#25#131#158''''#10#192
+ +#249#9#19#254#254#223#254'e'#245#240'";'#176'4'#26'kW'#212#205#159#255#154'z'
+ +#235#24'@_'#26#206#196#157'6'#209'G&'#241#204#165#161'g.'#177'~V'#253#167#218
+ +#238'O'#5#252')'#183#249#30#178#211'o1'#30'j'#233#159'&'#186'4'#152#237#254
+ +#189'w'#218#209#180'oT'#127'z>9'#230'Ok4'#250#228'f'#31' '#0#244#249#203#178
+ +#12#190#128#253#227'p'#252#185#227#184'aa'#29#130#244#163'j'#164#1'tMn'#0'H@'
+ +#136#0#29#133#215#147'<'#218#248#233#222#250#23'3'#130#189'q'#10#194#31#0'{'
+ +#191's'#245#227#170#209#187','#192#143#181'?'#192'5'#7'b]>\'#20#14'A'#11#208
+ +'D'#144#151#10#136#156#159#251#164'_~'#18#254#129'C'#190#31's'#1#254#222#175
+ +#127'A'#141#30#221'9'#129#147'8'#187#163#177'vYK'#250'_'#251'['#31#12#244'O{'
+ +#194#141#202#159#231#142#237'o'#192#159#217#226#158'\'#178#252'8'#140'7[X'
+ +#192'C'#242#167'Sc'#255#143#9#252#127#164'f'#163'}Q'#253#19#235'7Xo'#142#238
+ +'m6'#251#144#240#244'Hz'#166#216'g'#12#144'#'#227'O'#21#210#255'.'#225#4#181
+ +#254#187#180' '#230'?'#251#250#215#191#158'>O'#199#223#179'\'#158#231#241#249
+ +#236#16#188'v'#237'ZD?'#166'I?'#142'M'#1':~]'#242#2#224#16#132'V'#176#218#159
+ +'7n'#222#31#174'|'#138#253#1#220#16'$'#212#243#6#196#177#234'^{K'#213'z'#235
+ +'L'#0'69'#168')'#249#1'5m'#10#232'D'#161'P'#207'1`'#252#2#158'8'#6#13#1'x:'
+ +#195#235','#155#4#217'|'#170#254#227'o|^M'#182#31#156#246#169#156#232#208#160
+ +#255#243#234#19#4'zl'#31#247'0A'#23#207#216#251#210#196#147#255'!'#192'5Y~'
+ +#185#128#31#146'?'#19#181#127'!$'#144'Ng'#236#245#239#223#253#174#154#13'w4'
+ +#248#209#223#15#170#127#134'x?'#236#254#157#183#229#27'!'#253#145#245'7'#161
+ +#239#178'1'#127'I'#246'A'#143'?T'#254'm#'#227#143#204#229#217'q8'#254#220'q'
+ +#18'0`-'#128#214#193#189'{'#247'0'#181'x'#11#141'C'#148#6#189'!'#1#248#5'6i{'
+ +'e{'#210'}'#227#241#164#253#154'.'#24#242#25#208' '#129#176#214'P'#221#171'o'
+ +'q'#255#128'@'#204#129#192#248#3#140'S'#208'!'#1#27#29'p'#27#140'B#p'#253#1
+ +'v6'#226#167'\'#134#147'L)'#150's'#193#148#224#223#250#245#159'S'#211#189#173
+ +#147#251#238#19#30'A\S'#221#151'^W'#215#190#240#139#234#245#191#240#13#213'X'
+ +#127'N'#160'?'#202#253't<'#253'&'#191'7wm'#254#212'H'#254#2#252#25#131'_'''
+ +#251'X'#181#31#14#192#217'L'#245#31'|_M'#247#183#216''#239#186#170#127#179#217#156#16
+ +'^'#22#199#225#248'+]'#138#227#248#208'e'#223'cL'#1#218#174#199'q'#220'Y,'#22
+ +'k'#196'vp'#2#26#18#192#246#6#189#180#247'`'#216'{s'#127#214#188'a'#253#1'a'
+ +#164'g'#24#170#183'T'#239#198'[*nuu'#211#16'h'#2#13#153'h'#148#246#217#31'P3'
+ +#230'@A'#2'z'#242'Q_'#151#17'{^'#209'r'#251#6#242#202#229#240'N'#185#167'X'
+ +'Bv'#228#127#250#198#159'T'#227#199#247'O'#245'<'#158#215#128'F'#215#190#246
+ +#138#186#242#179#127'Z}'#228'k'#191#161'z/'#127#244#216#190#235'i'#247#210
+ +#230#243#155'F'#30#166#176'G'#156'}'#214#219#15#135'_R'#128#159#157'~'#211'"'
+ ,#236#135#253#193#131#183#9#252#247#11#143'?'#252#4'Y'#170'B/'#153#223'$'#240
+ +#199'~2sC~2'#193#7#167#251'*'#173#250#223#145'\'#255'GF'#245''''#201#143#196
+ +#160#244'8'#165#191#190'.''3'#216#20#248#202'W'#190#226#147#25#16#175#172#172
+ +'4'#8#252']'#250#161#27'2'#185'('#204#0#16#1'G'#5#8#176#157#187#131#149'O'#14
+ +#231#141'K'#202')'#29#230#28#129'f['#245#174#127#146#236#255#150#245#9'0'#17
+ +#196#146#31' '#154#128'I'#27'6'#181#3#158#211'_'#176#152's@'#251#8#220'^'#131
+ +'O'#157#233#229#20#198'w'#254#233'7'#213';'#255#254#159')'#253#12#157#159#1
+ +#226'mn^W'#151'>'#253'e'#245#234'/'#253'U'#181#249#214#23#143#241#203#158#208
+ +#198'/'#175#188#206'H{'''#179'O'#247#242'3'#224#207'X'#234'g'#21#201#207#241
+ +'~'#2'}'#6'{_'#136#0#165#189#147#157#247#24#252#186#181#151#158#212#211#207
+ +#210#228#229#149#237#31#212#130#197#196#181#251#149#14#249#193#238#223#18#213
+ +#31's'#252'q'#200#143#182'w'#8#15#195#231'Y'#236's'#132#203'vb'#195#166#9'_'
+ +#191'~'#29#154'@'#11#181#2#240#7#208#15#191'*aA'#204'1'#8'=p5'#247#252#206
+ +#157#254#234#167#198'I}'#213#23#167#160#23#232','#192#184#217'c'#18#8#26'uM'
+ +#0'l'#18'D'#146')'#136#16#161'4'#18'A'#152#208#180#21#243#29#18'0'#221#133'<'
+ +'!'#0#229#2#255'9D'#12#142'a6'#227#225#253#159#168#255#254#219#191#172#134
+ +#247'~z'#130#183#236#217#6#8#186#190#178#169#214'>'#254#179#234#213'?'#251'+'
+ +#234#218#159#248#165#163#191#249#176'k'#246'<'#158'PG'#218'kG'#191#201#231
+ +#207'm#'#143#194#230'/'#210'{y'#153#27#169#191#208#192#135#148#135#250'O'#132
+ +'0'#217#190#163'F[?"'#146#152'Ks'#15']'#223#143'?7'#187'{o7'#194#217#208#177
+ +#251#231#244'l'#163#197#23#18'='#182'%'#215#159#193'O8'#128#25#176#141#132
+ +#159#157#157#157#169'x'#253#13#248'_'#24#2#224#239's'#19#132#8#248#173'$I'
+ +#216#31'@'#11'B'#130#208#4#216#31'@'#235#149'\'#249#157'w'#247#214'?='#205
+ +#162#14#146#132#152#4#184'7'#0#145'@gMu'#174#189'%'#229#194#162#1#152#252#0
+ +'h'#1#146'-X8'#6#203#154'@a'#18#248#197#228'#N1'#209'Y'#237'='#248#255#254
+ +#205'?R?'#248'w'#255'DMw'#30#158#234'y'#4#245#166'jn\S+'#175'}'#130'$'#252
+ +#159'R7'#190#244#231'T}'#253#202'i_'#158#202#200#203#210'_Rz='#227#236#147'r'
+ +'^'#6#191#163#246'['#240#139#202#15#224#179'z'#207'*'#191#246#1#204'v'#31#168
+ +#193#195#183#233'usn'#238#193#239'Cyo'#154#229'W'#187'{?'#236#196#147#190#168
+ +'l'#214#238#23#167#223'.'#236'~ZX'#245#135#211#143'0'#240#152#222#187'O'#166
+ +#241#4#9'?'#199#233#245#175#142#211'x'#202'}'#152#2#180#6#9'X'#127#0#217'?'
+ +#151#29'S'#0#26#1#252#1#221'$'#243#187#239#246#215'?'#179#200#163#134'o'#204
+ +#1#216#247'$'#233#153#4#174'|'#156'H'#160'nA'#207'f'#128'h'#4'L'#2#145'&'#1
+ +#21#233#168#2#147'@h'#8'@r'#5'|'#129';'#214'2)'#225'Y'#159#166'|'#240#222#219
+ +#234#143#255#249#223'W'#15#254#247#31#208'C99'#190'/'#162'k'#17#183'{'#170'u'
+ +#245'e'#181#250#209#207#168'+'#159#251#170#186#250#249#175#210#245#175#159
+ +#246'%x'#250'03L'#219#130#30'c'#231#23#253#251#140#167#223'H~V'#225#231'I'#1
+ +'x'#6#255#156#155'{'#178'&@'#255#155#238#222'U'#163'G'#210#206'{Q'#168#253' '
+ +#146#203#173'}L'#231#181#131'/q'#156'~H'#245'E'#188#127#15#133'='#180#141'F'
+ +#144'P'#251#225#244'{D'#207#245#222'I'#218#253#238'8'#141'G|'#169'?@f'#22'b'
+ +#167#160#210'Z'#0#182#215#233#1#236#204#147'`'#229#189#254#250#167#19#21#198
+ +''#28#234'#p'#231'R'#217#151'I'
+ +#184#15#142'>'#14#251#137#31'`'#188#253#30'-'#239'jR'#224'i'#188'S'#142#22#0
+ +#252#27#205#193#237#245#198#240#145#11'~z'#182#140#221#15#240'o'#153'J?z'#230
+ +#239#201'4'#223#232#240#131#6' '#199#150#237#247','#151#242#196#190#215#245#7
+ +#208#197'h'#18#248'{'#164#10'm'#18#192#175'Hx'#144#179#4'iY'#3#9#204#210'x'
+ +#237#246#254#250'''3'#207#15'Yr#<'#24'j'#18#8#27'm'#213'!'#18#136#154#29#2'~'
+ +'h'#181#0#228#8'x'#236#20',H'#128#181#129'J'#152#208#212#17#24#18'`'#231' t'
+ +#148#220#153#144#164'`'#132#234#147#246#244'+y'#10#4'1'#219'{'#172#230#253#29
+ +'5'#31#236#210'zO-'#134#251'\9'#217'}'#249#13#213#185#249#250#217#149#224'G'
+ +#189#142'K'#239'C'#17#222's[u'#219#16#159#11#254#170#212#151#220#254'L'#154
+ +'z'#148#9'@K'#255#209#214#143#213'd'#239#30#189'n'#206#145#1'~'#159#228#248
+ +#175#214'F'#15#174#180#251'w'#243#2#252#200#244#131#221#15#240#195#238#127','
+ +'!'#191'{R'#223#15#27'n{:'#157#14#136#0#160#194'%''e'#247#31#245'r'#31#251'w'
+ +'W'#243#3#200#28'@3'#209'Md'#10'*'#237#16#196#26'$'#176'J m'#141#23#181#205
+ +#187#253#213#183#136#4#2'm'#207#11#9'p'#4#160#201#230'@D'#234#170#213#4#156
+ +#181#23#11#17#24'M'#128'L'#2#21'j'#191#130'2s'#17#26's'#192'M'#30'2UEn'#163
+ +#145'3l'#26'|'#232'F^'#10#226#8#224'M'#21#159#210#158'}'#137#239#187'i'#189
+ +#218#230#215#128#207#13#248#173#228'_0'#200#217#241'7'#211#161#190#225#163
+ ,#183#213#172#255'H'#146'|'#140#218#175'k'#251#187#209'd'#235'zw'#239'=m]d'
+ +#153'x'#252#145#236#3#240'#'#151#127'['#233'y'#253#24#252#216'F'#178#207'I'
+ +#198#251#15#27#167#253'('#151'R'#133'I'#11'h#'#25#136#180#128'K'#208#4'h'#31
+ +'Z'#0'H'#0#164#176'B@lM'#147'x'#237'N'#127#245#19#169#23#198#218#179'/>'#1
+ +#174#12#172#17#9'|L'#197#157'uM'#10#198#15'`'#192'/m'#198'=!'#2'_z'#10'('#19
+ +'%'#16#231#160'2'#230#128#239#21#4'`'#174#214#139'>]'#241'y'#25'.'#234']sGl|'
+ +'O'#202'wm'#3#143#170#179#207'8'#250#0'f'#212#243'/'#28#240#27#231#31#175#167
+ +'j'#240#240#7#164'ImK'#140'?'#209#196#145'j'#240#175#213'F'#247'/'#183#145
+ +#226'k'#193#159'I'#154'/g'#250')]'#226#251'H'#230#245#131#228#199#164#30#143
+ +'1'#171#207'|>'#31#31'w'#170#239'Q.'#227'i'#223'F'#207'8'#5#209'@'#4']'#132
+ +#208'P'#212#9#15'"O'#224#138#201#20#4#9'$y'#220#189#189#191#250#214'BE'#245
+ +#18#9#136's'#176's'#249#13#21'w/'#177'/'#192'3'#181#2#177#244#16#176'&A'#164
+ +#253#2'b'#14#168#208'/'#146#134#140'i '#13'F'#172'F`'#175#152#163#10#156#159
+ +':'#163#23'f'#148#146'xl'#171'.}'#140#193#159'i'#201'oc'#251#169'n'#226#1#240
+ +'+'''#204#151'K'#190'>'#171#244'3'#241#250#211#177'\B'#127#201't'#162#6#247
+ +#191#175#18#228#246'''s'#157#21#232#128#127#163'1'#184#189#217#28'>'#210#138
+ +'F'#150';'#146#31'*={'#252#149#238#237#7#240#223#151'p'#223'cH'#254#197'b1'
+ +#186'v'#237#26#156#131''''#234#244#171#142#179#240#236'Z'#18#232't:1'#177'b'
+ +#157'.T'#27#149#131#232'$'#4#2'0$ '#173#198'A'#2#205'L'#133#237#219#253#181
+ +'7gY'#220#214'}'#0#196#174#143't)qk'#243#150'j'#172'^'#215#146#222#1#189#217
+ +'f-'#160#166#147#139'8Dh'#219#142#7#133's0'#240#10#141#192'I rs'#137#205'f~'
+ +#224'''='#225#10'?'#211#173'>'#175']'#130#142#248'h='#245#250','#191#178#185
+ +#211#151#223#5#191#246#238#235#248#190'J'#181#202#175#4#176#156#155#159':'
+ +#246#254'\'#131'?'#183'j'#191'd'#242#17#25'$'#147#161#234#223#255#158'Ji]H~'
+ +#157#225#167#210','#191#220#217#255#201'j<'#217#21#193'o'#193#175#138#190'~'
+ +#166#190#255#1#164#191#132#254#30#163#190#159#198#168#209'h'#204#143';'#207
+ +#255'9'#222#165#227'?'#15'S:'#140#162#161#241'x'#140#134#162#29#169#25#184'd'
+ +'4'#1#165#251#7#160#177'H'#143#174'X'#147#16#218#188#211'_'#251#216'8'#173
+ +#173'x2'#239#160#206#254#211#18#191#190'rU'#181#214'oiM'#192#250#1'B'#157',$'
+ +'d'#224'I%'#161#138#138#190#2#166#152'Hq'#132#192#244#23#240#203#145#2#167
+ +#243'P.'#161#195#234#21#245#202#127#158'q'#228'O'#220'='#179#195'{'#234#129
+ +#167#255#238'|'#201#207#21#144#27#129#175#14#11#237'9'#133'<*-b'#251#197#162
+ +#129#207#210#127#190#144'p'#223'B'#180#129#5#255'o>'#216'a'#155'?'#157#142'u'
+ +''''#31'Z'#148#128#223'#'#241#127#181#187#247#163'n8'#27','#3#191#210#225'>'
+ +#128#31'-'#188#31#144'&'#203#14'?'#228#248'#'#220'G'#175#27#161#200'G'#157
+ +#146#211#239#131#222#157'c='#23#248#3'~'#252#227#31#251'h%F'#154'@'#195#228#8
+ +'`V!'#164#12#131#8'h'#141#164'!4'#26#237#210'Uk'#17#240#234#247#6'k'#175#15
+ +#23#245#13'c'#14'0'#17'DP'#241#145':'#220'Sm2'#9'PG'#224'K?'#193#2#252#142'6'
+ +#192#254#0'c'#14#232'm'#155'8Ti9f'#195#134#158#201'(tr'#207#171#253#7#204#173
+ +'=KW'#250','#143#202#245#202#157#166#156'%'#208#27#162#200#164'eW'#150#29'H'
+ +#231'Ui'#1'z'#227#237'O%'#212#151#207#231#142#195'O|'#0'D'#2#147#221#219'j'
+ +#178#253#158#222'w$?>'#223#167#15#184#222#219'{'#167#21#204#199'K'#192'ob'
+ +#253'h'#234#137'4_+'#249#233#153'}L'#160#223#165#231#23'5'#0' '#137'3'#1'~'
+ +#231'2'#159#153#193'$'#240#189#239'}/@x'#16'$@Z@W'#26#137#184#154#0'"'#3#235
+ +'('#28#162#27#129#18#227#248#254#160'wko'#222#188#234'['#245']k'#2#200#26#244
+ +#227#26#153#4#31'Q'#181#206#166#150#248#174#244#23#223#128#206#17'0'#249#2
+ +#129#205#30'TN'#6#161#237'@'#236#251#5#1'8m'#201#221#26#3#235#164#170#22#27
+ +#157#181'+~F'#134'Wr'#228#185#155#249#1#240'k'''#159'H'#251#180#144#250#165
+ +'t^'#168#251#137#238#215#175#9'@<'#254#226#237'7'#26#0#19#0#166#233#154'N'
+ +#213#136#164#254'|'#180#171#227#251'IR'#2#127#160#146#217'K'#221#221#31#214
+ +#131#197'T'#192'o'#28'~F'#242's'#129#15'r'#252#209#220#3#146#31#26#0#212#254
+ +'('#138'v'#7#131#193#136#180#218#19'M'#243'='#210'u?'#237#19'XvN&<'#184#181
+ +#181#21#211'Ek'#208#5'4$'#128'lA'#180#24#135')'#192'$@'#251']'#248#4#232'X'
+ +#237#209#168#243#210#246#180'}SO8bH@2'#0#137#8#234#189#171#170#185#241'*'#131
+ +#222's'#181#129'H'#147#129'''-'#199#149'q'#14'F'#21'm'#192'u'#16#154'z'#2'&'
+ +#3'eg)'#202#29'2p'#181#255#220'!'#133#15'f'#26#188'(C'#210'u\'#137#159#23#181
+ +#249#202'sT}'#199#201'W'#168#249'"'#245#197#214#231'2'#222#180'p'#242'1'#232
+ +#165#148#215'z'#252#141#234'/'#170'>'#219#254#201'B-'#250#187'j'#184#245#14
+ +#29#27#219#200#128#174#229#151#137';'#189#249#228#165#238#222#15#185#170#143
+ +#235#8'l'#168#143'S|'#149'd'#249')'#237#224'C'#184#15'R'#255#1#212'~'#178#249
+ +'w'#233#249#29'6'#155#205')i'#183#201'iz'#252#151#141#179#250#4#150'H'#160'A'
+ +'c2'#153#160#145#8#155#3'B'#2' '#3#209#4'T'#151#128#136#190#131#181#253'Yc'
+ +#243#225#168#251'Z'#166#194'PKn'#169'!'#8'C1'#9#186#164#13#188#193#213#132#0
+ +'>'#28#129#158'D'#4#220#16#161#155'9'#168#156'Z'#2#229#18#129#231#23#179#22
+ ,#251#198'I'#232'j'#3'E'#30'a'#238#148#25'z'#213#146#195#3#153'mg'#245#182#188
+ +#223#187#249#4#127#134#233#191#167#156#198#28'|'#188#2'zP'#168#3'~'#211#173
+ +#135'U}'#9#239')'#167'O?'#188#245#249#28#251#11'+'#249's)'#238#201'%'#207'?'
+ +''''#240#143'wn'#171')-'#153'y]*R_f'#238'iG'#147#237#171#173#253#219#129#151
+ +'&:'#151'(3e'#189#240#246'3'#248#149#206#242'CO?'#246#248#195#230'G'#168#15
+ +#224#167'eH'#166#236#20#177#254#179#6'~}'#205#207#238#176#133'C'#4#254#136'.'
+ +'b'#147'L'#130'.H@:'#10']6'#225'A%$'#128#16'!H`'#158#133#237#187#131#222#235
+ +#179#172#214#230'y'#3#140'o'#192#132#10#163#186'j_zM'#197#221#205#2#248'f1'#4
+ +#16'W'#142#7#186#211#144#178#243#19#6'em@'#26#143#148'#'#6#158#149#244#172#29
+ +','#137#30#152#249#11#142'zG'#206#204#147#227#222#168#167#189' ?'#252#128'i'
+ +#197#229'y'#14#248'3'''#150#175#28#27#223'Q'#247'y'#31#182#190#27#222'K'#11
+ +#137#159#27#208''':'#181'7/'#145'@'#194#245#19'#'#146#250#243#225#142'h'#11
+ +':'#188#167#138#30'~'#217#165'F'#255#246'Zc'#244#152'S{%'#212#167'tz/O'#223
+ +'-s'#248'A'#237'7'#137'>'#15#207#19#248#143't'#239'N'#251#252#12#9#244#251
+ +#253#184#213'j5'#232#226#162#197#248#154#132#4#225#16#188#12#173'@i'#18#232
+ +'1'#9'('#175#158#7'~'#252'p'#208#189#185'?o]-'#146'|t'#184#15'&'#129'oL'#130
+ +#245'W'#8#236#177#205#9#240'L'#5'a'#172'5'#6#171#9'p'#10'qPT'#21#210':'#15
+ +#220')'#202#140'V'#224#21'D'#160#138#237'"JP'#172'K%'#200#206'f^9'#236'='#235
+ +#173'z'#158'w'#245#153#31#215#188#152'>'#219'='#149#188#188#145';/'#178#245
+ +#249'n'#18#143#177#243'MG^'#145#250'*u$'#191'c'#235#27'/?'#219#237#12#244'E'
+ +#161#254#207#11'R'#192#255#23#240#242'?'#254'!i'#1#19#177#247'u|'#223'|n'#228
+ +'/&'#215#218'{?i'#132's'#174#229#23'G'#4#236'}'#147#222';'#145'P'#31#171#253
+ +'J'#194'}'#178'F'#169#239#222'y'#0#127#233#254#156#209#193#231'W%'#1'd'#12'"'
+ +'Y'#136'.'#178'!'#1#152#5#151'0'#247#128#210'y'#2'm'#186#212'u'#146#184#241
+ +'p'#222'X{0^'#185#149#145#236#215'@-'#155#4'H!'#6#9#196#157#13#201#7#144#136
+ +#128#1#191')$'#10'+$ '#11#147#138'h'#6#156'N,'#145#130'\'#162#6'V'#27'x'#26
+ +#17'8'#221#137'rG;'#240#202'^'#196''''#220#177#147#184#149#249#225#135'+'#167
+ +'i'#140'{'#175#244'6'#167'<'#23#0'WO'#0'~^'#150#248#202#22#239'8N>c'#239#187
+ +'v'#191#149#252#139#18#240'Y'#19#152'N'#213'd'#251#167'j6'#220'b'#130'@'#179
+ +#15'+'#241'3=__'''#154'<'#190#210#234#223'!'#149'?'#205'm'#147'@]'#210#235'd'
+ +#248#245#165#178#15#222#254'G'#146#215#255'H4'#129'}8'#252'666'#206'<'#248
+ +#237#253'9'#227#195#146#128#18#159#128#146'2b"'#130#21'h'#2#146'%h'#178#5'9Y'
+ +#136'$r'#155#192#211#160';'#23'''Y'#212#184';'#236#189'6Kk'#29'S'#0'd'#27#140
+ +#8#184#163#214#26#19'APo'#21#17#1#167#138#208's'#251#10'<'#137#8#220#148'b'
+ +#153#194#220#134#14#205#196'%'#165')'#204#202'k7'#132'h'#230'4'#176#135#14
+ +#132#20#143'n:<'#151'q'#152'*o'#156'v'#246#144#145#236#230#127#249#146#216
+ +#189'~'#157#14#227'I'#230#158'!'#2'k'#227'/Q'#247'S'#145#248#2'|'#181#208#149
+ +'|J'#236'w'#215#222'7'#206'?E'#251#147#254'=5'#221#189#173#19#127#210'%*?}'
+ +#209#229#198#224#189#149#198'h'#199#203'MI'#143#14#243')'#1'?'#173#199#180
+ +#223#151#154'~4k'#132#196'GE'#31#182#183'I('#161#145'''{'#251#201'\=s'#14#191
+ +'e'#227'<'#16#128'=OC'#2#251#251#251#17']'#228':]x'#174#29#136#162'h'#157#246
+ +'a'#6'\'#18''''#225#134#212#14'th'#27'}'#4'b'#210#0#162'G'#195#206'K{U'#147
+ +' '#212#201'C'#138#171#11'#U'#235']S'#245#181#27#156'M'#200#14'@'#199#4#0#1
+ +'(''Dh'#136#192#148#24'+'#153#181'X'#249#229#198'#'#182#21'Y%'#179'P'#231#15
+ +'-'''#3#207#209#255#139#222#4#166#151#161'{UN'#136#4#170#143#176#19#182'+m'
+ +#229#5'Y'#149'CxN'#165#158#27#198'3N='''#150'oA'#159#154'm'#0'>#b'#0#160'u'
+ +#17#143'Z'#20#13';'#173#199'?IJ>'#0#132#0#147#209#158#154#236#252'D-&'#131'B'
+ +#213#135#169#128#207'pU'#254#238#238'O'#234'^2'#245't'#229'@'#213#211'?'#147
+ +#22#222#168#234#219'q'#193#15'O'#127#24#134#232#235#223'_,'#22#227#25#141#243
+ +#2'~'#140#243'B'#0#246'\'#221'<'#1'8'#252#232#194#183#232'p'#143'.'#254#186
+ +'8'#7'A'#4#156','#132'V'#227'$'#129';$u'#27#180'_#'#240'E'#131'i}'#237#193
+ +#164#247'j'#150#235#249#7#180#147'0`'#21#222#244#16#132'Y'#208'X{'#133#139
+ +#138#188#208#137#6#200#220#3#134#8'4q'#4#162#29#136'&`{'#13'8]'#137#131#138
+ +#163'P'#8#161'hF"'#19#152#28'H76'#161#195#162','#185#240#15'T='#3'G'#200'1'
+ +#248#160'%'#203'y^yi'#25#240'z'#229'4'#218'TE|'#159'%'#189#153'l'#195#190#230
+ +#160#154#207#246'~'#154#149#218'r+'#150#250#153#6#173#0'_'#137'='#175#164#131
+ +#143'2'#4#144'h'#239#127':''u'#127#231']5'#239'?'#210#173#186'L'#26'p'#146#10
+ +#209'h'#149#31#149'|'#151'['#253#187'P'#249'9'#188#143#254'}'#160'!m'#239#219
+ +#24#191#1#191#210'e'#189#15'e'#198#222#199'R'#207'? '#1'4>K'#25'~G'#29#231
+ +#137#0#236'9'#155#180'a'#218#142#26#141'F'#13#17#2#164#7#27#231#160'8'#5'/'
+ +#217#218#1#29'&'#132's'#176#6#147' Sa'#252'h'#220'~'#169'?onz@'#166#137#20
+ +#216'f!Z'#226#195',h'#192', B'#176'R'#223#1#188'Bd '#22'B'#16'M@9'#25#132#214
+ +'I'#24'>A+8'#204'GP'#154#242#188#186'v:'#26'['#13#193#161#130#165#190#130'CB'
+ +#143'O'#200#187#183#160'.%'#224#23#26'H.'#234'})Q'#199'%'#0#215#147'/'#158'}'
+ ,#163#226#219'p'#158'q'#240'Y'#208#167'b'#231';'#158'}l'#11#192#181#202#175
+ +#215':'#175#223'8'#2'%vO'#235#217#222'}5'#222#131#186'?'#211#199#229'3y'#157
+ +#167'"'#245#147#201#149#230#254#237'f<'#27'z'#26#247'8'#15#146#250'%{'#223'&'
+ +#248#208#178'C'#210#254'1'#9#153'G'#210#213'g'#155#128#191'K'#160#31#160#149
+ +#23#13#152#8#231#10#252'K'#158#138's3,'#9#208#197#15'k4'#200#12'h"B'#16#4#193
+ +#170#227#23#128'F'#0#18'X'#5'A B &A'#148#19#196''''#139#176#253'p'#178#242
+ +#202','#141'ZE'#235#240#162'('#200#147'9'#10'k'#221'+'#170#182'rM'#5'h'#162
+ +#17#154'y'#8#3#199#28'pM'#3#9#17#134'RK`'#10#140'l'#14'A Z'#129#201'$t'#218
+ +#146'U'#137#160'j*'#148#202#146'+'#21#137#21'G'#162';'#242''''#146'A'#165#216
+ +'f'#217'c'#235'Jw'#222#168#172'e;7'#137'<'#153#27#190'3'#137'<'#142#164'wc'
+ +#249#2'|'#29#203'/'#192#175#137#192#9#241#217't^'#13'r'#237#3'H'#10''' -'#139
+ +#225#14#219#249#9#171#251#186'I'#167#146'L>'#179#246#232#207'j}t'#127#189'1x'
+ +#228#177#180#207'3'#147#214#171'$'#190'O'#203'\j'#249#135#226#233#135's'#15
+ +#210#30#249#252'['#178#191'O'#207#220#160#223#239'O'#187#221#238#156#8' =o'
+ +#224#175'>'#9#231'm'#148'J'#137'I'#19#136'%u'#152#157#131't'#140#181#1#144#0
+ +#250#11#210'z'#141#253#2#202'k#}'#152#182'czDc rw'#218#186#180'=m_'#207'H'
+ +#164#235#226#31#237'$'#132'fP'#168#249#145#170#181'/'#169#6#17#129#31'7'#180
+ +#244'7j'#191'k'#14#24#127'@'#224#164#17#187#166#129#201'!p'#29#133#198'<'#176
+ +#4#224'W'#18#139#180'G'#192#246'.'#180'='#11#141'iP'#152#3'n'#194'Q'#217';'
+ +#239#29'XU"s'#202'Az'#217#181#144#187#161'='#137#215#231'y'#197#214#151'B'#29
+ +#163#226'gy'#145#167'oSu'#139')'#183'\'#201'_H'#253#20'M5'#197'VO-'#9#184'a'
+ +#190#220#170#251#198'!H'#18#127#184#173#166'{wU:'#27#22'f'#129#11'~'#241')'
+ +#180#162#217'.I'#253';'#152#156#211'C/`}n'#172#242'+'#221#187#207#228#244#143
+ +#140#167#159#182#183#197#219#191'Ej'#254'6'#9#24'h'#2'}'#147#215#239#244#241
+ +'3'#192'?7'#224'w'#30#135's;,'#9#16#1#4#8#19#18#27#195'9'#216#154#205'f=h'#3
+ +#244#127#244#26'D'#171'1h'#2#240#11#160'r'#144#211#135#17'% '#192'D'#244#17
+ +'A'#146#249#241#163'I'#247#230'`'#214'X'#247'l'#241'O'#1'^?0 '#142#184#166#0
+ +#206'B'#244#211'3'#166#0#167#13'['#208#23#161'A'#27'!'#136#180#244#207#131
+ +#224'@wb'#235'#p*'#15#11'"P:'#164'h'#211#139#165']'#153'*L'#4#151#24#150'^"'
+ +#175'r'#197#170#26#192'!'#14#190#18#15#184#245#246#216#204#242#146#189'o5'#0
+ +'7W'#223#128#221'z'#244#141#202'/'#246'~'#166#167#219'V'#226#228#179#128#183
+ +#29'{'#202#224#183#197'='#236#253'_'#168#217'`K'#205#246#239#17#240#199#146
+ +#16#148'X'#147#1#251'J:'#246'D^2'#187#212#26#220'n'#215#166'}'#248#28'<'#143
+ +'U~V'#252#233#146#177#163'Oz'#247'Me'#178'Nk'#239'C'#237#151#153'{9'#190#15
+ +#149#159#20#206'1b'#252#245'z'#29#164'a'#234#249#237'U:O'#227#188#19#128#249
+ +#13'H'#24#194#154'#'#4'p'#14#18#1'4E'#27'X5'#190#1'!'#1'6'#9'h'#191#7#191#0
+ +'m'#195'A'#8'm'#128#222#231#251#163'$'#238'>'#28'uo.'#178#168#233#154#5#202
+ +'I+V'#226''''#136#219#27#170#222#187#174#130'F'#235#160#212'7'#170#191'C'#4
+ +#134'L'#148'K'#2#2'z'#229'U'#157#133#14')x'#166#10'Q9~'#130'J7cq$'#30#152#241
+ +#232#176#154#3'[m'#231#188#196'm'#180'a6'#189'B+'#240#158#2'zW'#213#247'*'
+ +#222'|'#29#215#207#172'Df'#7'`R'#168#251#158#1'}'#226'H~'#163#13'd'#134#8'2'
+ +#142#223#207#6#143#24#248#217'bb'#237'~'#227#216#203'\u'#159#132#252'J}'#252
+ +'p'#179'9x'#224#209#142#199#165#130#224#29#218'f%'#198':'#250'f'#210#187#207
+ +'t'#238#133#167#223#130#31#19'v'#160#137#7#254#143#254'}'#163#209'h^'#241#244
+ +'+u'#14#193#127#200#147'q.'#135#141#16#160#156#248#214#173'['#225#214#214'V'
+ +#141#14#213#137#173#17'*'#236#145#250#134'b'#162'u''u'#24#251#200'#hC'#27#160
+ +#237#26#251#6''#204'r'#143#204#130#246#229#221'Y'#243'J'#154#135#145'1'#11
+ +#236':'#8#172#175#0'N'#191#184#181#166#234'+D'#4#245'N'#17#1'p{'#10#28#0#190
+ +#16#131#235#24'tk'#11'l'#152'R'#230'3t'#29#134'Nv!k'#7'jIU'#162'\'#17#175#148
+ +'\T'#190#213#182#143'A'#245'B'#26#233'_r'#240')I'#218#145'}3}'#182#19#194#179
+ +#224#183#251#6#240'N"O'#213#203'/'#241'}'#227#236'c'#144#27#147'@r'#251#141
+ +'6'#144'%s'#246#232'O'#25#248'3'#171#254'g'#198#163#239'F'#17'h'#187'I'#234
+ +#254#229'F'#255'^'#28#192'3O'#146#158#5'>'#199#245'3'#201#231#183'R'#159#22
+ +#19#226'c'#149#31#160#199#2#149'_'#8#1#29'|'#198#244#182')'#217#253' '#140
+ +#132#180#206#236'<'#132#249#142#4#156#23'h'#176's'#240#219#223#254'6'#251#5
+ +#232#166'E'#4#234':'#28#132'259'#155#4'XD'#27'0$'#208#165#183#146'>'#175#26#4
+ +#167#24'f'#1#129'='#160#199'%'#220#157#183'6'#247'&'#173#203#137#10#226#3'D'
+ +#224#23#246'>4'#130#176#209'!'#173'`'#147#8'a]'#249'a,m'#198#140#3#240'0'#167
+ +#224'!'#5'F'#146'3'#224#149'|'#3#166#23'A1'#169#137'%'#2#153#224#196'LuV'#10
+ +#18#10'7'#148#156#132#14#3'xF'#210'Wd'#153#145#246#7#28'{N'#252#222#149#252
+ +#182'B'#207#237#200'c'#192'/'#132#160'\'#167#159#149#242#142#211#207#233#224
+ +#131#255'-'#166#251'j1'#220#162'e'#155'I w'#205#128','#147#150'_'#236#220#195
+ +'~'#222#138'g'#187#27#141#193#131'Z'#184#152#150#212'}'#199#214#151#182']'
+ +#166'c/l'#249'}i'#226#193#158'~Z?Fl'#159#164#252'>='''#3'2/'#199#244','#205
+ ,'{'#189#30#192#127'n'#237#253#165#128'9'#237#19'8'#166#223'T2'#9'h N'#211'di'
+ +'O'#128#167#155'j'#137'@'#204#3#236#19#9#168#14#1#174'A'#251'u:'#30#25#179
+ +#128'@'#21#236#205'Z'#27#187#227#230#229#133#10#235#218'F'#247#203#211#141#17
+ +#1'('#223#183'ZA'#173#177#170'""'#131#176#185#162#163#4#230#181#142'3'#208'H'
+ +'~'#255'0-'#192#152#8'&'#147#208#248#7#248#23'V2'#12#221#28#130#220#137#12#8
+ +#27#152#196#220#131#209#130'Jz'#174#167#172'j/'#255'V'#226#245'+Iyc'#227#27
+ +'{'#223'4'#227#176'Z'#128#1#186#172#165#192#166't'#220'M'#237'u'#215'('#203
+ +#157#13#31'3'#240'S'#132#242'2'']W'#166#220#206'e'#209#192'O'#243'vm'#182#189
+ +#217#24'>'#140'|H|'#28#23#191'>'#171#251#220'%'#208#205#232#227#240#30#242
+ +#249'i'#189'/'#237#187#182#205'"'#206'?'#28#199'k'#166'F'#229''''#205'2;'#207
+ +#246#254'a`y'#17'G'#201'$@'#168#176#213'j'#197#2'lT'#12'v'#197#25#184'J'#140
+ +#143#232#0#22#248#5'D'#27'P-!'#2#152#5'a'#206'd'#128#174#225#190#191'7k'#174
+ +#237#142'[W'#230'y'#216#176#206':'#3'|'#207'H'#242#162#2#17#154'@'#212#222' '
+ +#173'`C'#5#141#142#227#252#11#184#231#160#231'8'#2#139#168'@u'#10'3'#207#2
+ +#222'F'#5#2#209#4'\'#237#192#151#144#161#149#252'U'#7'`%'#159#192#12#183#149
+ +'6'#239'+'#235#28#176#213'zF'#229'O'#171#234'~&fA'#230'T'#234#21#206'?~'#189
+ +#209#0'*a'#191#18#9','#230'j6'#218'f'#208''''#211'A'#161'!'#152'L@'#199'l0}'
+ +#0#16#210#235#198#147#199#27#4'|x'#246'M'#190#241#19#212'}k'#235#211#210#151
+ +#238'='#12'~'#186#207#144#254#216#222#15#130#128#19'{h'#153#145#244'_ '#196
+ +#247#162#168#252'K'#129#242#2#15'k'#18' J'#128#178'b'#186#185'54'#25'!R@'#227
+ +'Q'#152#5'+ '#1#133'Y'#137'5'#9'@'#27#232#209#210#17#179#160#238'{~Lk'#16'A'
+ +#8'"'#240#9'}'#251#179#250#234#206#164'ue'#150'!'#135#192#128#177#144#218#5
+ +#176#3'K'#10'a'#212'Tq'#7'Z'#193#154#10'j'#141'2'#184#157#210'bo'#9'!'#184#9
+ +'C'#133#25#224#21'~'#2'''R`o'#173'u'#11'H'#180#192'M$'#146'W'#185'~'#128#210
+ +#172#185#178'*'#194'}'#174#244#207#156#233#180#225#240#203'd'#178#205#138#183
+ +#191'*'#245#179#188#18#1'H'#212'b'#178#175#230'P'#241#199#187#156#216#147';6'
+ +#189#251'~K '#244'}>1B'#183'6f'#224#7#200#15'6'#192#231#138#221'2'#240#149#6
+ +'?'#128#143'N'#189'#'#201#229#223#23#240#195#185#135#25'y'#25#248#240#240'+M'
+ +#14#211'N'#167'3G'#3#143'7'#223'|'#243#133'R'#249#15#0#228#180'O'#224#132'~#'
+ +#155#4#208#6'h;Z]]'#141#160#13#200#140'D0'#11'z'#162#17#172#233#244'aM'#4#180
+ +'&'#18'Pm'#186#235#220'l'#4'&'#129'o'#136' '#131'F'#224'y'#195#164#209#219
+ +#153'4/O'#211'Z'#7#200#180#192'tH'#160'4'#231#128#152#0#232'I'#16#212'z*jt'
+ +#201#168#232#210'~'#173#210'[`I'#231'!G'#213'/'#171#254'x'#173#18#159#128#241
+ +#234'{'#182#152#168#8#4'x'#149#181'*7'#222'PE'#218#190#178#13'8'#157#146#221
+ +#204#13#241#21#234#190'w'#192#23'P'#201#233'7'#145#0#2'v2'#27#170#20'v'#253
+ +#164'O'#219#131'"'#219#207'x'#239#197#137#231#153#254'~v;'#231'p^'#167'6'#217
+ +'^'#175#143#182'|'#143'sy'#213'2'#224';'#237#185#173#147'O'#233#9':'#160#214
+ +#239#25#240#3#248'$'#12#246#200#222#135#3#16'z'#254#132'l'#253#217#139#230
+ +#232'{'#26'8>,'#227#128'6P'#171#213'bz^0G'#22#166'*G'#159#129#30#28#133#240
+ +#17#28#212#6'T'#211#152#5#4#180#18#17'(.'#25#11#163#253'yc}0k'#172#205#210
+ +#168'Y'#0#180#172#198#27#245'>'#247#202#196#0'B'#8#27'+*'#170'wT'#0'B'#128#19
+ +#209'!'#0#27#14#148#162#162'jc'#210#146#9#224'4"'#177'w'#185#218#140'D'#194
+ +'~n'#233'n)'#12#232'j'#2#198#9#232#168#251'n'#184'/'#207'+I?yA'#0'H'#206'I'
+ +#166'}'#150#244#201'tH'#255'J'#10''' '#155#20'i)4'#200'Q'#0'K&'#184#184'Y'
+ +#138#4#158#149#218'x'#167#25#209#135'i'#204#231#154#160#24#248#0'<'#235#252
+ +'b'#231'/*'#234#254'H'#226#250#198#214'G'#136'oW'#188#251'}'#186#215'C'#168
+ +#251#176#245'www'#23'd'#231'sl'#255#19#159#248'D'#254#162#131#223'yB>4'#163
+ +#164#13#192'7'#176#178#178#18#17#25#208'f'#204'}'#6'h'#1#216#225'(\1'#218#128
+ +#210#26#2#250#18'"'#164'h'#136#0'Y'#132'1a.'#160'g=dg!'#20'r'#210#11#166'i'
+ +#220#216#155'5'#215'G'#179#218'Z'#162#130#200'S'#5#25#20#146#220#169#7#240
+ +#141#243#207#28#15#148#31'7Y;'#8#226#22'}B'#131#9#130#29#141#202'5'#3#156#181
+ +#141#18#136#170#159#171#194'$'#200#171#209#1'U'#16#130#155#244#227'6'#222'4'
+ +#7#149#201#4#212'$'#192' u'#18'}'#12#232#177'dp'#188#211#146'/'#198'l'#199'c'
+ +#201#200'4/'#1#190#186'm'#181#137#204#250#20'`'#195'7'#195'y'#191'S'#159#236
+ +'t'#163#233#158#199'I'#5'b'#143#232#188#131'Ll|l'#1#244#236#224's'#128#143
+ +#134#29'#'#153#153#135#195'{'#198#222'7'#14'>'#216#249't'#175#199't'#159#167
+ +'('#224'[b'#235';W'#224#197#29#31'6'#2#176#191#217'h'#3#155#155#155#254't:'
+ +#13'1S1'#252#3'0'#11#232#223'-'#178#7#225#12'D6'#225#138'8'#7'W'#196'y'#168
+ +#157#132#158#215#164#199#177'A'#159'V;@'#4#30#224#166'Q:'#152#215#187#253'Yc'
+ +'}'#148#196'+'#185#22#233'V'#133'7)'#191'E'#135#225#162#243#176'K'#8#185#152
+ +#0#164'x'#16#25#212#153#28#130#176#206')'#201'>'#214'd>'#148#10#139'J'#191
+ +#244'`'#219#242'"G'#160#236#237#247'Jf@^$'#7#25'3'#1#248'K'#209'H'#19'@'#159
+ +'p'#197']'#150#152#245#212#206#198#163#242#195#0#15#252'f%'#147#1#239'1'#251
+ +#181'`1&'#21#127#167'GK'#232#193'!'#160'L'#237'0'#147'B'#154'iu'#223#177#241
+ ,#171#18#223#216#249#3#1'?'#146'w'#0'~^'#144#194'K'#210#30#197';'#172#238'w'
+ +#187#221#217#214#214'V'#226'x'#248'_X['#255#176#241'a$'#128#210'o_f'#22#208
+ +#225#26#217#130#28'6$'#2#128'F'#208's'#23#209#6#208'k'#160'm'#136#128#128#140
+ +'(CL'#251#16#211'Rc'#204#157#238'|'#180'*O'#9#206#251#179#198#234'h^'#235'M'
+ +#211#168#157#230#162#25#24#199#158'r'#10#131'J'#132'`'#156#127#190'>ig'#187
+ +#152#199#16']'#144#27'*'#8'"q:'#134'tX"'#17#158#164'"'#243#233#232#181'/Z'
+ +#134#150#190#137#216#218'R)'#151'9'#139's'#28#146#28#18#158'_'#207#225'7'#7
+ +#196#182#196#183#240#1#184#0'W'#165#130' 1#8T'#167#242#154#191#24#213#163#249
+ +#176'G*>Zn'#23#17#8#145#246'8'#3#2'>x'#18#206'}''o'#223#134#244#164'K'#207
+ +#184#2'|'#187#208'=d'#224'#'#172#135'L>"'#2#246#238'#'#149#151#8' '#251#176
+ +'I}w|'#152#9#192#140#3'f'#1'B'#127#244'p'#196#198'QH'#255'o'#9#216#187#244' '
+ +#245#184#150#128#136'@4'#2'v'#20'*'#204'T'#164#188':4'#2')4'#10#173'V'#224'#'
+ +#29'E'#251#10#176#13#208#18#9#212#137#12#186#147'E'#220#157'$q'#139#224#16#26
+ +'S'#161#232''''#232';'#205'D+'#246#190#152#2#150','#148#155'*l~'#150#252'@.'
+ +#30':$$'#232#216#255#182'EW'#169'1'#191#201#250'S'#165'\'#0'['#221#167#138
+ +#148'`'#6'u'#166'T'#158'/'#7'<'#214#181' '#25#215#131#249#176#25#207#251#237
+ +'h6'#242#149'8'#243'<61'#140'moA'#175't'#202'.'#24#133#213'|Y'#230#198#179'o'
+ +'T}'#19#211#151#5#158#254'>'#128'OD>'#140#162'h'#12#137'O'#199#167't'#127#23
+ +'t<'#249'0'#170#251#203#198#5#1#20#195's'#205#130';w'#238#4#198'?'#128'9'#7
+ +#232'!B'#205'@'#203#241#19#244'$'#140#200'k'#248#7#20'"'#6'9W'#26#214#161#209
+ +#18#216#17'm@BQ'#24#248#30#200' '#160'c>'#180'^F'#165'/'#229'<'#244'wL$@'#132
+ +#208#153'.'#162#206'4'#141#219#153#14#8#138#237'^T'#4#22'e'#194#170#168#10'T'
+ +#254'R'#240#219#191'U'#207#127#241#207'J'#246'_'#197#7'`Gn'#205#0#3'z'#183
+ +#145'g'#225'G(^g'#0#31#251#201#164#22#206#135#173'h>h'#147#164#15#252'4)^c'
+ +#153#197#128'^Y'#21#255#160#180'/'#169#250#144#248'p'#224')'#1#187#164#242
+ +#150#164#189#1'~'#171#213#154#141'F#'#246#236#147#169#151'~X'#213#253'e'#227
+ +#130#0#202#227#128#127#192#16#1'=H'#28':'#164#127's2'#17#173'['#244#0#162#216
+ +#168'+'#26#129#171#13#176#143#0#175#229#228'#'#223#135'Ya'#200' 8@'#6#128#174
+ +#158'`'#132'a'#142'|<"'#132#246'x'#17#183#146'4'#168#207#179#176#190'H'#131
+ +'Z'#170#160#219'k'#251#221'8'#245#140'K'#191'T'#13#184'$'#239#223#141#8#228
+ +#203'~t5'#20'h'#134'['#251#239#185#210#221#253#191#6'n'#228#167#211#208#207
+ +'fQ'#144#204#234#225'bL'#18'~'#16'.'#3#188#233#18'"'#182'C'#174#127#145#168
+ +#248'E'#214#30'-'#11'g'#218'-'#171#234'+'#157#190#203#224#167'{'#224#18#192
+ +#144'#'#179'I'#194#210#254#2#248'O'#31#23#4#176'|,%'#2'Z'#135#244'@'#177'F'#0
+ +'`'#211#186'I*f'#139#236'J'#214#10#132#16#12#9'X"@'#19#18#218#6'y'#212'@'#6
+ +' '#2#218#14#133#12'|'#218#151#194#2#206#177#169#16#130#178#128'N'#179' '#154
+ +'fQm'#158#16')'#164'!'#19'C'#146#250#181'E'#22#214'r'#195#2'y'#17#247#207#221
+ +#219#235#29#248'y2'#242#165#155#252#170'R'#11'0'#253'7'#240#178'E'#236#167
+ +#179#200'O'#166'Q'#152#206#226' '#153#214'BZ'#252'd^'#10#31#28#4#188#212#222
+ +#235#20']Ro'#178#220#168#19#185'JM'''#30'U'#150#246'('#207#157'J?>'#11'|'#168
+ +#251't'#157#135#0#191#0#30'j>&'#221#132'I0E'#6#159#249#172'%'#192'_'#242'K?'
+ +#188#227#130#0#158'<'#150#18#1'|'#4#237'6'#201#183#217#140';'#20#19#1#160#203
+ +#144#169'5h'#201#186'm'#246#141#198#0#243'@i'#13#2#4#2'2`"'#144#133#181#2'!'
+ +#4#175'B'#8#162#229#235'F'#0'E*'#191#201#243#247#2'"'#129'('#205#252' '#205
+ +#149#159#229'~'#0#19'"'#203#184#160')'#160#181#143#207'&'#158#241#233'8'#142
+ +#249'x'#15' '#233'{y'#202#139#162'Wy'#10#219#153'g'#142'y'#244#137'~'#158#6#4
+ +'N'#218'N#?K0C'#14#127#181#237#249#167#247#204'1}Z'#185#20#11'j'#213#222#145
+ +#240#12'B'#237#197#183'q{+'#237'Mi'#174#210#192#159'HW'#158#145'*'#128#15#169
+ +#143#184'='#239#147#186#143#10#189'1'#173'!'#241#209#140'snl'#252'G'#143#30
+ +'e'#23#192#127#250#184' '#128#163#13'K'#4#223#253#238'w=4%'#5#25#208#161#144
+ +#164'N'#212'l6'#1'd'#214#10#232#129'lxz'#174'B'#180'('#3#240#153#4'h'#223#144
+ +'C'#211#209#10'jB'#6#136#30'DJG'#16't'#20'A'#19#2#242#10#8#139#220#2'Dr'#130
+ +#217'y^'#164#249#225#143#239#219'm'#140#220'sN'#250#224#207#240#14#252'#?'
+ +#176#225#202#240#138#242' '#249#0'z;/'#210#133'9'#25#152#147'!3'#237'P'#212
+ +#21'x'#158#199#217#3'.'#224#233'X"'#221'vy'#150#29#167'@'#7#224#7#152'a'#223
+ +#143' '#229#165' '#135#215't|'#4#208'C'#210#3#244#240#230'c!'#2'^'#192#171'O'
+ +#199#211#11#224'?'#219#184' '#128'g'#27'%"@'#212#224#210#165'K>I'#164#144#30
+ +'D&'#3#180''''#4#168#145'a'#8'2'#192#2'2P'#152#202#220'Y'#132#8#140'i'#192
+ +#230#1'k'#5#30';'#14']B`2'#160'c'#1'b'#8#162#29'0'#17#152#22' '#24'y'#145#223
+ +#167'r'#183#11'`'#165#17#192#129'y'#9#151#254'J'#227#225'We'#253'_)'#227#164
+ +#211'h'#215'L$'#130']'#25#231#157#150#242#136#238#231'6Vo='#248#6#240'R'#142
+ +'k'#194'x'#0#255'd'#137#212#231'E'#18'vX'#189#23#21#127#14#208'c'#166']'#196
+ +#241'WVV2x'#245#137#148#243#11#224'?'#219#184' '#128#247'7l^-'#194#135#244#16
+ +'z'#198'<'#160#135#18#128'E'#143'B6'#17#224'/'#160'}'#16'B'#131#164#22#8#129
+ ,'5'#0#172'}'#157'Q'#216#144'F'#165'L'#4'R'#177#200#239#177'D'#160#29#136#161
+ +#199'A}'#144#129'v '#210#182#246#31'(]'#151' '#219#170#152'}'#132#165's'#209
+ +'4'#200#156#244'!, '#160'Vy^v'#3'j'#183#164'W'#184#253#10'U>7'#157't'#217#129
+ +''''#222'{'#165#165#188#5#190'S'#127#207'^|'#165#165'=/p'#236#161#209#6#253
+ +'~'#168#243#19#172'%'#166'?!'#160'c'#31#196'0C=>'#169#247' '#142#132#142'!y'
+ +#7#128#207#156'8'#190#156#253#5#232#159'e\'#16#192#7#27#150#8#240#0#186'Z'#1
+ +'I'#168'`gg'#7'R;'#132#137#0#243#20'd'#0'p'#139#218'_'#23#240'#'#215#192#128
+ +#159'5'#2'G30D`4'#3#215'g`'#9'Ai'#13#1'$'#16'pI?'#231#28's'#242#156'''`'#247
+ +#12#17'('#19';8D'#19'p'#192#207#0'/'#8'AK~'#165'{'#230#27#213'>'#173#0#222
+ +#196#233#141#138'o'#156'y'#0#191#241#228'O'#5#220'v'#27#199#1'~'#243#127#168
+ +#245'x}'#20'Es'#0#31#210#30#234'='#17'jz'#227#198#141#20#160#135#180'w'#242
+ +#245#249'|O'#251'a8'#143#227#130#0#158#223'8'#160#21#12#6#3#175#211#233#4#180
+ +#248#244#0#179#153#0'I'#14'S'#129#30#234#152#30'n'#164#31'C'#202#215#232'X'
+ +#141#142#25'S'#192#152#5#150#4#232#189#186'eY'#161#21#132'UBP'#154#20'x'#246
+ +'$!'#4#156#147'/'#224#247'DK'#176#219#149#243#182#170#188'2'#210#221#181#225
+ +'s''>/'#210']z'#234#25#208'/'#28#208'W'#213'|+'#245'E'#221#231#181#144#194#12
+ +'*=IwH'#249#5'@O@_'#200'g&'#0'=T|c'#219#11#232#205'y'#186#235#139#241'>'#198
+ +#5#1#28#207'Xj"'#208#218#7#25'@3'#160#7#157'M'#5','#4'nL'#127#142#233#206'"'
+ +#151#16'|'#157'?`4'#6#248#22'P'#189#24#11#17'D'#134#16'@*'#244#186'RD'#1'D@'
+ +#175'E'#196#194#19'2`"'#192#182#28#243#212#146'x`'#201#142'/'#0#159#27#21'_'
+ +#21'j=7'#212#196'B'#223#195#192#167#207#157#211#246#1#2#192'B'#191'k'#230#2
+ +#158#200#14#210#29#239'Y@'#194#131'H'#232'xj$'#189#1'=]'#175#188#162#226#187
+ +#235#139#241#1#199#5#1#28#239#176#215#215'8'#14#141'f'#0'3aoo'#143#9'!@i'#218
+ +'`'#16#192'l'#160#151#134' '#3#172'A'#8' '#7':'#206'k'#128#158'^'#202'k9'#30
+ +#154#227'J'#252#4#202'1'#13#180'I'#192'f'#128'oH'#0#231#148'!.X'#144'@q'#178
+ +#5#208'sQ'#237'-'#240#177#166#247'X'#201#175#196#161''''#4#176'0'#251#134#0
+ +'d!<'''#6#228#144#236#176#223#23'Fk'#0#224#137#3#210#181#181#181#148'~?'#212
+ +#250#140'L'#168#28#160#191'p'#232#157#204#184' '#128#147#27#165'D\'#233'Y'
+ +#168'@'#8#208#12'n'#222#188#233'-#'#4#12#2'M '#160#14#5#212'au'#219#172#149
+ +'&'#14#214#0'0'#0'v'#1'k6'#155#217't:'#205#232#156#243'e'#18'~'#9#224#171#219#23#227#152
+ +#199#5#1#156#141'Q'#186#15#198'\'#192#182'1'#25#8'H'#30'H'#129'H'#192'#py'
+ +#134#24#8#148#30#200#129#128#232#25'r'#160'}'#143'@j'#23':'#206#128#199'6>'
+ +#19#219#4'V'#187#141#181#207#253'L'#148'"'#0#27#192#243'>}/o'#155#133#190'?'
+ +#7#208#137'Dr'#128#156#190'+'#235#247#251'9'#129#222#2#29#146#189#221'n'#231
+ +#6#236#248#156#11#192#159#205'qA'#0'gsT'#239#139''''#192'Q.1`'#13'r'#184'u'
+ +#235#150'7'#28#14'-9'#224'8'#8#2'k'#179'O'#192#230'5'#8#3#235#245#245'u'#187
+ +'m'#6#128#140'5Iy'#11'J'#2';o'#3#220'X?~'#252'8'#199'6@'#142#253'e@'#199#250
+ +#16#176'/'#219#191#24#167'8.'#8#224'|'#141'e'#247#235#0'9`'#24#130'0'#3'D'
+ +#177#236#3#161'Y`]'#175#215#15#0#211#128#218#29#6#224#24#0'9'#214#135#0#253
+ +#176'c'#23#227#12#141#11#2'x1'#198#179#220#199#163#190#246#168#224#189#0#249
+ +'9'#30#23#4'p1.'#198#135'x'#252#127'p'#251'ut'#3#215#244'"'#0#0#0#0'IEND'#174
+ +'B`'#130'('#0#0#0#128#0#0#0#0#1#0#0#1#0' '#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#1#0#0#0#1#0#0#0#1#0#0#0#1#0#0#0#1#0#0#0#1#0#0#0#1#0#0
+ +#0#1#0#0#0#1#0#0#0#1#0#0#0#1#0#0#0#1#0#0#0#1#0#0#0#1#0#0#0#1#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ ,#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#1#0#0#0#1#0#0#0#2#128#128#128#2'UUU'#3'@@@'#4'333'#5'III'#7'@@@'#8
+ +'999'#9'999'#9'MMM'#10'FFF'#11'FFF'#11'FFF'#11'MMM'#10'999'#9'@@@'#8'@@@'#8
+ +'UUU'#6'333'#5'UUU'#3#128#128#128#2#0#0#0#2#0#0#0#1#0#0#0#1#0#0#0#1#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#1#0#0#0#1#128#128#128#2'UUU'#3'UUU'#6'@@@'#8'FFF'#11'III'#14'<<'
+ +'<'#17'III'#21'EEE'#26'DDD'#30'DDD"EEE%AAA''DDD)AAA+AAA+AAA+DDD)AAA''GGG$FFF'
+ +'!DDD'#30'==='#25'@@@'#20'@@@'#16';;;'#13'FFF'#11'@@@'#8'333'#5'UUU'#3#128
+ +#128#128#2#0#0#0#1#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1#0#0#0
+ +#2'UUU'#3'+++'#6'999'#9'NNN'#13'CCC'#19'BBB'#27'GGG$DDD-CCC5DDD'#211'SC6'#219'W@0'#227'[>+'#235']<('#238'^<'''#240
+ +'_<%'#243'`<#'#245'a;"'#247'a:!'#248'a;"'#246'`<$'#245'_<%'#242'^='''#240'\='
+ +')'#237'Z=,'#233'V@1'#225'RD8'#217'NG?'#210'JHD'#204'IHC'#204'HHD'#204'GEC'
+ +#203'FEC'#202'EED'#198'EED'#195'DDC'#190'DDC'#183'DDD'#172'DDD'#157'DDD'#138
+ +'DDDtCCC\DDDDCCC.@@@'#28'DDD'#15'III'#7'UUU'#3#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'UUU'#3'@@'
+ +'@'#8'KKK'#17'HHH CCC5CCCPDDDlCCC'#134'DDC'#156'EED'#172'FEC'#185'GFD'#193'G'
+ +'FC'#198'HFC'#202'IGD'#203'PE;'#213'VA0'#227']<('#239'a;#'#246'd9'#30#254'g:'
+ +#29#255'g:'#30#255'i<'#30#255'j='#31#255'j>'#30#255'k>'#30#255'l?'#31#255'l@'
+ +#31#255'mA'#31#255'nA'#31#255'm@'#31#255'l@'#31#255'l?'#31#255'k>'#30#255'j>'
+ +#30#255'j='#31#255'i<'#30#255'g:'#30#255'f:'#29#255'd9'#31#252'`<#'#245'[=*'
+ +#236'UA3'#223'MF?'#210'IHC'#204'HFD'#204'FFC'#203'FFE'#200'DDC'#197'EED'#191
+ +'DCC'#182'DDD'#170'CCC'#152'CCC'#129'DDDfDDDKDDD1FFF'#29'@@@'#16'III'#7'UUU'
+ +#3#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'UUU'#3'II'
+ +'I'#7'@@@'#16'@@@ FFF7DDDRCCCoCCC'#140'DDC'#163'EED'#180'EED'#191'FFC'#198'I'
+ +'GD'#201'ME?'#208'UA2'#224'\<('#238'b9 '#250'f:'#29#255'h;'#30#255'j>'#30#255
+ +'m@'#31#255'oB '#255'qD '#255'sF '#255'uH!'#255'|L#'#255#128'O$'#255#133'Q%'
+ +#255#136'S&'#255#139'V'''#255#143'X('#255#145'Y)'#255#142'W('#255#139'U'''
+ +#255#135'S&'#255#131'Q%'#255#128'O$'#255'yK"'#255'tG!'#255'rE '#255'pD '#255
+ +'nA '#255'l@'#31#255'j='#31#255'g;'#30#255'e9'#29#255'a;!'#247'Z=+'#234'RB5'
+ +#221'JGC'#207'HFD'#204'FEC'#203'FFE'#200'EED'#196'DDC'#189'DDD'#177'CCC'#159
+ +'DDD'#135'CCCjBBBMBBB2FFF'#29'III'#14'UUU'#6#128#128#128#2#0#0#0#1#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#2'333'#5';;;'#13'BBB'#27'AAA3BBBQDDDqDDD'#142'EED'#165
+ +'EDB'#183'FEC'#194'HFD'#200'IFB'#205'SA3'#223'^;&'#242'e8'#29#255'g;'#30#255
+ +'j>'#31#255'mA'#31#255'pD!'#255'tG!'#255'~M#'#255#141'W('#255#151']*'#255#160
+ +'c-'#255#169'i0'#255#178'n1'#255#181'q2'#255#182's3'#255#183't3'#255#184't3'
+ +#255#184'v3'#255#185'v4'#255#186'w3'#255#185'v3'#255#184'u3'#255#184't3'#255
+ +#183't3'#255#182'r3'#255#181'q2'#255#175'l1'#255#166'h/'#255#158'a,'#255#149
+ ,'\*'#255#138'U('#255'zK"'#255'sF '#255'pC '#255'l@'#31#255'i='#31#255'g;'#30
+ +#255'c8'#31#252'[<*'#237'RC8'#218'IGD'#205'HFD'#204'EED'#201'DDC'#198'EED'
+ +#191'DDD'#179'CCC'#161'DDD'#136'CCCkEEEJDDD-@@@'#24'FFF'#11'@@@'#4#0#0#0#1#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#1'UUU'#3'999'#9'FFF'#22'CCC*DDDGDDDiCCC'#138'EED'#165'FEC'#184'FEC'#194
+ +'HHD'#200'QC9'#216'[<*'#237'c8'#31#253'g;'#30#255'j>'#31#255'nA '#255'sF!'
+ +#255'|M#'#255#141'W('#255#158'a,'#255#173'k1'#255#181'r3'#255#185'v4'#255#187
+ +'y4'#255#189'{4'#255#191'~5'#255#193#129'5'#255#195#131'5'#255#196#132'6'#255
+ +#197#134'6'#255#198#134'6'#255#199#136'6'#255#200#136'6'#255#200#137'6'#255
+ +#199#136'6'#255#198#135'6'#255#198#134'6'#255#197#133'5'#255#196#132'6'#255
+ +#195#131'5'#255#193#128'5'#255#191'~4'#255#188'z4'#255#186'x4'#255#184'u3'
+ +#255#181'q2'#255#168'i/'#255#153'_+'#255#137'T'''#255'yJ"'#255'rE '#255'm@'
+ +#31#255'i<'#31#255'f:'#30#255'b9!'#249'X>.'#232'MD>'#212'HFD'#204'EED'#202'E'
+ +'ED'#198'EED'#192'CCC'#180'CCC'#160'DDD'#132'DDDbCCCACCC&CCC'#19'@@@'#8'UUU'
+ +#3#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'333'#5
+ +'III'#14'>>>!DDD'#255
+ +#232#177'>'#255#234#179'?'#255#236#181'>'#255#236#182'?'#255#237#183'?'#255
+ ,#237#183'?'#255#238#183'@'#255#238#184'?'#255#238#185'?'#255#238#184'?'#255
+ +#238#183'@'#255#237#182'?'#255#237#183'?'#255#236#182'?'#255#236#181'>'#255
+ +#234#179'>'#255#232#176'>'#255#230#175'>'#255#229#172'='#255#227#169'='#255
+ +#224#167'='#255#220#161'<'#255#217#157'<'#255#213#153';'#255#209#148':'#255
+ +#204#142'9'#255#198#135'8'#255#193#129'7'#255#188'{6'#255#183't5'#255#171'k2'
+ +#255#142'W)'#255'tH"'#255'nA '#255'h<'#31#255'd7'#30#255'[:('#240'KD?'#211'G'
+ +'FD'#204'DDC'#201'EDD'#195'CCC'#182'CCC'#159'CCC}EEEUBBB2@@@'#24'999'#9'UUU'
+ +#3#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#1'333'#5'III'#14'BBB#EEECCCCkEEE'#145'DDC'#174'FFE'#192'KE@'#206'Z;)'
+ +#238'c8'#30#255'i<'#31#255'oB!'#255'|M%'#255#153'_-'#255#178'o4'#255#186'x6'
+ +#255#192#128'7'#255#198#135'9'#255#204#142':'#255#209#149';'#255#214#155'='
+ +#255#219#161'>'#255#223#167'>'#255#227#170'>'#255#230#174'?'#255#232#177'@'
+ +#255#235#181'A'#255#237#183'A'#255#238#185'A'#255#240#187'A'#255#241#188'A'
+ +#255#242#189'B'#255#243#190'A'#255#244#191'B'#255#244#192'B'#255#244#191'B'
+ +#255#244#192'B'#255#244#192'B'#255#245#193'A'#255#244#192'B'#255#244#192'B'
+ +#255#244#191'B'#255#244#192'B'#255#244#191'B'#255#243#190'A'#255#242#189'B'
+ +#255#240#187'A'#255#239#186'A'#255#238#184'@'#255#237#183'A'#255#235#179'@'
+ +#255#232#176'?'#255#229#173'?'#255#226#169'?'#255#223#165'>'#255#218#160'='
+ +#255#213#153'<'#255#208#147';'#255#202#140':'#255#196#133'9'#255#190'~7'#255
+ +#184'v6'#255#173'l3'#255#145'Y+'#255'uH$'#255'm@ '#255'g;'#31#255'b7'#31#253
+ +'U>/'#230'IEC'#206'FFE'#202'EED'#199'CCC'#189'DDD'#170'DDD'#139'BBBdCCC=BBB'
+ +#31'@@@'#12'UUU'#3#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#1'UUU'#6'KKK'#17'DDD)EEENDDDxDCC'#157'DDC'#182'GGC'#197'T=1'#225'a7 '
+ +#252'g;'#31#255'l@ '#255'wI$'#255#154'^.'#255#179'o6'#255#186'x7'#255#193#128
+ +'9'#255#200#137':'#255#207#146'<'#255#212#153'>'#255#217#159'>'#255#222#166
+ +'?'#255#227#170'@'#255#231#175'A'#255#234#180'B'#255#236#182'B'#255#238#185
+ +'B'#255#240#187'B'#255#242#190'D'#255#243#191'C'#255#244#192'D'#255#245#193
+ +'C'#255#246#194'D'#255#247#194'D'#255#247#196'E'#255#247#196'D'#255#247#196
+ +'D'#255#248#197'D'#255#248#197'D'#255#248#197'D'#255#248#197'D'#255#248#197
+ +'D'#255#248#197'D'#255#248#196'D'#255#247#196'D'#255#247#196'D'#255#247#195
+ +'E'#255#246#195'D'#255#245#193'D'#255#245#193'C'#255#244#192'D'#255#243#191
+ +'C'#255#242#189'C'#255#240#186'C'#255#238#184'C'#255#236#182'B'#255#233#179
+ +'B'#255#230#174'A'#255#226#169'@'#255#221#164'?'#255#216#157'>'#255#211#151
+ +'='#255#205#143'<'#255#198#135':'#255#191#127'8'#255#184'w7'#255#174'l4'#255
+ +#144'X+'#255'rE"'#255'j> '#255'e9'#30#255'_8"'#247'O@8'#219'GFD'#204'DDC'#201
+ +'CCC'#194'CCC'#178'DDD'#151'DDDqDDDGGGG$III'#14'@@@'#4#0#0#0#1#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#2'III'#7'@@@'#20'CCC.DDDVCCC'#130'EED'#165'DDC'#189
+ +'LB='#207']7$'#244'd7'#31#255'j> '#255'qE"'#255#140'W+'#255#174'l5'#255#186
+ +'x8'#255#193#129':'#255#200#138'<'#255#207#146'>'#255#213#155'?'#255#220#163
+ +'@'#255#225#169'A'#255#229#174'B'#255#233#179'D'#255#236#182'D'#255#239#185
+ +'D'#255#241#189'E'#255#242#190'E'#255#244#192'E'#255#245#194'E'#255#246#195
+ +'F'#255#247#195'F'#255#247#196'G'#255#247#197'F'#255#248#197'F'#255#248#197
+ +'F'#255#249#198'F'#255#249#198'G'#255#249#198'G'#255#249#198'G'#255#249#198
+ +'G'#255#249#198'G'#255#249#198'G'#255#249#198'G'#255#249#198'G'#255#249#198
+ +'G'#255#249#198'G'#255#249#198'G'#255#249#198'F'#255#248#197'F'#255#248#197
+ +'F'#255#247#196'F'#255#247#196'F'#255#247#195'F'#255#246#194'F'#255#244#193
+ +'F'#255#243#191'E'#255#242#190'E'#255#240#188'E'#255#238#185'D'#255#235#181
+ +'D'#255#232#178'C'#255#228#172'C'#255#223#167'B'#255#218#161'@'#255#212#153
+ +'?'#255#205#144'='#255#198#135';'#255#191#127'9'#255#183'u7'#255#167'g3'#255
+ +#130'P('#255'oB"'#255'h< '#255'c7'#30#255'X:*'#237'HFB'#207'EEE'#202'DCC'#197
+ +'DDD'#184'CCC'#160'CCCzEEENFFF(@@@'#16'333'#5#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ ,#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#2
+ +'III'#7'FFF'#22'BBB2CCC\DDD'#136'DDC'#171'EED'#192'Q?5'#219'a6'#31#252'f:'#31
+ +#255'mA!'#255#127'N'''#255#164'f3'#255#182'u8'#255#190#127':'#255#199#138'='
+ +#255#207#147'?'#255#213#155'A'#255#220#163'B'#255#225#170'D'#255#230#177'E'
+ +#255#234#181'E'#255#237#184'F'#255#240#188'G'#255#242#189'G'#255#243#192'G'
+ +#255#244#193'H'#255#245#194'H'#255#246#195'H'#255#247#196'H'#255#247#197'H'
+ +#255#247#197'H'#255#248#198'H'#255#248#198'H'#255#248#197'H'#255#248#198'H'
+ +#255#248#198'I'#255#249#198'I'#255#249#198'I'#255#249#198'I'#255#249#198'I'
+ +#255#249#198'I'#255#249#198'I'#255#249#198'I'#255#249#198'I'#255#249#198'I'
+ +#255#249#198'I'#255#249#198'I'#255#248#198'I'#255#248#198'H'#255#248#198'H'
+ +#255#248#198'H'#255#248#198'H'#255#247#197'H'#255#247#196'I'#255#247#195'H'
+ +#255#246#195'H'#255#245#195'H'#255#244#193'H'#255#243#191'G'#255#241#189'G'
+ +#255#239#186'G'#255#236#183'F'#255#233#180'F'#255#229#175'D'#255#224#168'D'
+ +#255#218#161'B'#255#211#153'@'#255#205#144'?'#255#196#134'='#255#188'{:'#255
+ +#180'r8'#255#155'_/'#255'wJ$'#255'j? '#255'e8'#30#255']8#'#246'LB<'#213'FEE'
+ +#203'EED'#199'DDD'#188'DDD'#165'DDD'#128'DDDSFFF,GGG'#18'+++'#6#0#0#0#1#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#2'III'#7'CCC'#23'BBB6DDDaCCC'#141'DDC'#174'GDB'#196'V:+'#233'c7'#30#255'h; '
+ +#255'pC#'#255#146'Z-'#255#179'p7'#255#187'{;'#255#196#133'='#255#204#144'?'
+ +#255#212#154'B'#255#219#163'E'#255#225#170'E'#255#230#176'G'#255#234#181'H'
+ +#255#238#185'I'#255#240#189'I'#255#242#190'J'#255#243#192'J'#255#244#193'J'
+ +#255#245#195'J'#255#246#195'J'#255#246#196'J'#255#247#196'K'#255#247#196'K'
+ +#255#247#197'K'#255#247#197'K'#255#247#197'K'#255#247#197'J'#255#247#197'J'
+ +#255#247#198'J'#255#247#198'J'#255#247#198'J'#255#247#198'J'#255#247#198'J'
+ +#255#247#198'J'#255#247#198'J'#255#247#198'J'#255#247#198'J'#255#247#198'J'
+ +#255#247#198'J'#255#247#198'J'#255#247#198'J'#255#247#198'J'#255#247#197'J'
+ +#255#247#197'J'#255#247#197'J'#255#247#197'K'#255#247#197'K'#255#247#197'K'
+ +#255#247#196'K'#255#246#196'K'#255#246#196'J'#255#246#195'J'#255#245#195'J'
+ +#255#244#194'J'#255#243#191'I'#255#241#189'I'#255#239#188'I'#255#236#184'H'
+ +#255#233#180'H'#255#228#174'G'#255#223#168'E'#255#217#160'C'#255#210#151'B'
+ +#255#202#141'?'#255#193#130'<'#255#185'x:'#255#174'm6'#255#134'S*'#255'mA"'
+ +#255'f:'#31#255'a6'#30#253'R>4'#224'FFE'#203'EED'#200'CCC'#190'DDD'#169'CCC'
+ +#133'CCCXAAA/CCC'#19'+++'#6#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#1'III'#7'CCC'#23'BBB6CCCcCCC'#144'EED'#177'JC>'#202
+ +'[6"'#244'c8'#31#255'j?!'#255'xI&'#255#162'd2'#255#183'u:'#255#192#129'='#255
+ +#200#140'@'#255#209#150'B'#255#217#160'E'#255#223#169'G'#255#229#176'H'#255
+ +#233#181'J'#255#236#185'J'#255#239#188'K'#255#241#190'K'#255#242#192'K'#255
+ +#243#193'L'#255#244#194'L'#255#245#195'L'#255#245#195'L'#255#245#195'L'#255
+ +#246#196'L'#255#246#196'L'#255#246#196'L'#255#246#196'L'#255#246#196'M'#255
+ +#246#196'M'#255#246#197'M'#255#246#197'M'#255#246#197'M'#255#246#197'M'#255
+ +#246#197'M'#255#246#197'M'#255#246#197'M'#255#246#197'M'#255#246#197'M'#255
+ +#246#197'M'#255#246#197'M'#255#246#197'M'#255#246#197'M'#255#246#197'M'#255
+ +#246#197'M'#255#246#197'M'#255#246#197'M'#255#246#197'M'#255#246#196'M'#255
+ +#246#196'M'#255#246#196'M'#255#246#196'L'#255#246#196'L'#255#246#196'L'#255
+ +#246#196'L'#255#245#195'L'#255#245#196'L'#255#244#195'M'#255#244#194'L'#255
+ +#243#193'L'#255#242#192'L'#255#241#190'K'#255#238#188'K'#255#236#184'J'#255
+ +#232#179'I'#255#228#173'H'#255#222#166'F'#255#215#158'E'#255#207#148'B'#255
+ +#198#137'?'#255#190'~<'#255#180'r9'#255#150']/'#255'qE$'#255'h< '#255'b6'#30
+ +#255'W9*'#235'GED'#204'DDC'#201'DDD'#192'CCC'#172'CCC'#137'DDDZAAA/GGG'#18'3'
+ +'33'#5#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'+++'#6'II'
+ +'I'#21'CCC5DDDbCCC'#145'DDC'#178'LB;'#206'^6 '#249'd8'#31#255'l@!'#255#131'Q'
+ +'*'#255#172'k7'#255#186'z;'#255#196#133'?'#255#205#146'C'#255#213#156'E'#255
+ +#220#165'G'#255#227#173'I'#255#232#180'K'#255#236#184'L'#255#238#187'L'#255
+ ,#240#189'N'#255#241#191'N'#255#242#192'N'#255#243#193'N'#255#244#194'N'#255
+ +#244#194'N'#255#244#194'O'#255#244#195'O'#255#244#195'O'#255#244#195'O'#255
+ +#244#195'O'#255#244#195'O'#255#244#195'O'#255#244#195'O'#255#244#195'O'#255
+ +#244#195'O'#255#244#195'O'#255#244#195'O'#255#244#195'O'#255#244#195'O'#255
+ +#244#195'O'#255#244#195'O'#255#244#195'O'#255#244#195'O'#255#244#195'O'#255
+ +#244#195'O'#255#244#195'O'#255#244#195'O'#255#244#195'O'#255#244#195'O'#255
+ +#244#195'O'#255#244#195'O'#255#244#195'O'#255#244#195'O'#255#244#195'O'#255
+ +#244#195'O'#255#244#195'O'#255#244#195'O'#255#244#195'O'#255#244#195'O'#255
+ +#244#195'O'#255#244#195'O'#255#244#194'O'#255#244#195'N'#255#244#194'N'#255
+ +#243#193'N'#255#242#192'M'#255#241#190'N'#255#240#189'M'#255#237#186'M'#255
+ +#235#182'L'#255#230#178'K'#255#225#171'I'#255#219#163'G'#255#211#153'D'#255
+ +#202#143'B'#255#192#130'>'#255#183'u:'#255#164'f4'#255'yK&'#255'i=!'#255'c7'
+ +#30#255'Z8%'#241'GEC'#205'DDC'#201'CCC'#193'DDD'#173'DDD'#136'BBBYDDD-KKK'#17
+ +'333'#5#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'333'#5'CCC'#19'BBB2CCC_DD'
+ +'D'#143'DDC'#178'M@8'#211'_5'#31#251'e9'#31#255'lA"'#255#144'Y/'#255#179'r9'
+ +#255#188'}='#255#198#138'B'#255#208#149'D'#255#217#161'H'#255#223#170'K'#255
+ +#229#177'L'#255#234#181'M'#255#236#186'N'#255#239#188'O'#255#240#190'P'#255
+ +#241#191'P'#255#242#192'P'#255#242#192'P'#255#242#193'P'#255#243#193'P'#255
+ +#243#194'P'#255#243#194'P'#255#243#194'P'#255#243#194'P'#255#243#194'P'#255
+ +#243#194'P'#255#243#194'P'#255#243#194'P'#255#243#194'P'#255#243#194'P'#255
+ +#243#194'P'#255#243#194'P'#255#243#194'P'#255#243#194'P'#255#243#194'P'#255
+ +#243#194'P'#255#243#194'P'#255#243#194'P'#255#243#194'P'#255#243#194'P'#255
+ +#243#194'P'#255#243#194'P'#255#243#194'P'#255#243#194'P'#255#243#194'P'#255
+ +#243#194'P'#255#243#194'P'#255#243#194'P'#255#243#194'P'#255#243#194'P'#255
+ +#243#194'P'#255#243#194'P'#255#243#194'P'#255#243#194'P'#255#243#194'P'#255
+ +#243#194'P'#255#243#194'P'#255#243#194'P'#255#243#194'P'#255#243#193'P'#255
+ +#242#193'P'#255#242#192'O'#255#242#192'P'#255#241#192'P'#255#240#190'P'#255
+ +#238#188'O'#255#236#185'N'#255#232#180'M'#255#228#175'L'#255#222#167'I'#255
+ +#215#159'H'#255#205#147'D'#255#196#134'@'#255#186'y<'#255#173'm7'#255#130'O*'
+ +#255'j?!'#255'c8'#31#255'[7#'#245'HDA'#208'DDC'#201'CCC'#193'CCC'#172'CCC'
+ +#134'AAAVAAA+@@@'#16'@@@'#4#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'@@@'#4'<<<'#17'CCC.CC'
+ +'C[CCC'#140'EED'#176'O>5'#213'_5'#30#253'e9'#31#255'nB#'#255#151'\1'#255#181
+ +'s:'#255#191#129'@'#255#201#142'C'#255#211#154'G'#255#219#164'K'#255#226#173
+ +'M'#255#231#179'O'#255#234#184'P'#255#237#187'Q'#255#239#189'Q'#255#240#190
+ +'R'#255#240#191'Q'#255#241#192'R'#255#241#192'R'#255#241#192'R'#255#242#192
+ +'R'#255#242#192'R'#255#242#193'R'#255#242#193'R'#255#242#193'R'#255#242#193
+ +'R'#255#242#193'R'#255#242#193'R'#255#242#193'R'#255#242#193'R'#255#242#193
+ +'R'#255#242#193'R'#255#242#193'R'#255#242#193'R'#255#242#193'R'#255#242#193
+ +'R'#255#242#193'R'#255#242#193'R'#255#242#193'R'#255#242#193'R'#255#242#193
+ +'R'#255#242#193'R'#255#242#193'R'#255#242#193'R'#255#242#193'R'#255#242#193
+ +'R'#255#242#193'R'#255#242#193'R'#255#242#193'R'#255#242#193'R'#255#242#193
+ +'R'#255#242#193'R'#255#242#193'R'#255#242#193'R'#255#242#193'R'#255#242#193
+ +'R'#255#242#193'R'#255#242#193'R'#255#242#193'R'#255#242#193'R'#255#242#193
+ +'R'#255#242#192'R'#255#242#192'R'#255#241#192'R'#255#241#192'R'#255#241#192
+ +'R'#255#240#191'Q'#255#240#190'R'#255#238#189'Q'#255#236#186'P'#255#234#182
+ +'O'#255#230#177'N'#255#224#171'L'#255#217#162'J'#255#208#150'F'#255#198#138
+ +'C'#255#188'}>'#255#177'o:'#255#136'S,'#255'k?"'#255'c8'#31#255'\6!'#248'JC?'
+ +#211'DCC'#201'CCC'#193'CCC'#171'BBB'#131'DDDRAAA''777'#14'UUU'#3#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +'UUU'#3';;;'#13'AAA''CCCTBBB'#135'DDC'#174'N=5'#213'`4'#29#254'e9'#31#255'oC'
+ +'$'#255#156'`3'#255#181'u<'#255#193#131'A'#255#204#146'E'#255#213#157'I'#255
+ +#221#167'M'#255#227#175'O'#255#232#180'Q'#255#235#184'R'#255#237#187'S'#255
+ +#238#189'S'#255#239#190'S'#255#240#191'T'#255#240#191'T'#255#240#191'T'#255
+ +#240#191'T'#255#240#191'T'#255#240#191'T'#255#240#191'T'#255#240#191'T'#255
+ +#240#191'T'#255#240#191'T'#255#240#191'T'#255#240#191'T'#255#240#191'T'#255
+ +#240#191'T'#255#240#191'T'#255#240#191'T'#255#240#191'T'#255#240#191'T'#255
+ ,#240#191'T'#255#240#191'T'#255#240#191'T'#255#240#191'T'#255#240#191'T'#255
+ +#234#187'R'#255#202#161'G'#255#232#185'R'#255#240#191'T'#255#240#191'T'#255
+ +#240#191'T'#255#240#191'T'#255#240#191'T'#255#240#191'T'#255#240#191'T'#255
+ +#240#191'T'#255#240#191'T'#255#240#191'T'#255#240#191'T'#255#240#191'T'#255
+ +#240#191'T'#255#240#191'T'#255#240#191'T'#255#240#191'T'#255#240#191'T'#255
+ +#240#191'T'#255#240#191'T'#255#240#191'T'#255#240#191'T'#255#240#191'T'#255
+ +#240#191'T'#255#240#191'T'#255#240#191'T'#255#240#191'T'#255#240#191'T'#255
+ +#239#189'S'#255#238#188'R'#255#236#186'R'#255#234#184'Q'#255#231#179'Q'#255
+ +#226#173'O'#255#219#165'L'#255#211#154'H'#255#201#142'E'#255#190#128'@'#255
+ +#179'q:'#255#140'V.'#255'l@"'#255'c8'#31#255'\4'#31#250'JC>'#211'CCC'#201'DD'
+ +'D'#192'CCC'#168'CCC~DDDKFFF!MMM'#10#128#128#128#2#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#128#128#128#2'333'#10'@@@ EEE'
+ +'JCCC~EDD'#169'L?8'#208'^4'#30#253'd8 '#255'pD%'#255#159'b4'#255#182'v='#255
+ +#194#132'C'#255#205#147'H'#255#215#160'L'#255#222#169'O'#255#228#176'Q'#255
+ +#232#181'S'#255#235#185'T'#255#236#187'T'#255#237#188'U'#255#238#189'U'#255
+ +#238#190'U'#255#238#190'U'#255#238#191'U'#255#239#190'U'#255#239#190'U'#255
+ +#239#190'U'#255#239#190'U'#255#239#190'U'#255#239#190'U'#255#239#190'U'#255
+ +#239#190'U'#255#239#190'U'#255#239#190'U'#255#239#190'U'#255#239#190'U'#255
+ +#239#190'U'#255#239#190'U'#255#239#190'U'#255#239#190'U'#255#181#144'@'#255
+ +';/'#21#255#21#16#7#255#9#7#3#255#2#2#1#255#0#0#0#255#0#0#0#255#0#0#0#255#1#1
+ +#1#255#7#6#3#255#17#14#6#255#31#25#11#255'2'''#18#255'SB'#29#255#157'}8'#255
+ +#233#186'S'#255#239#190'U'#255#239#190'U'#255#239#190'U'#255#239#190'U'#255
+ +#239#190'U'#255#239#190'U'#255#239#190'U'#255#239#190'U'#255#239#190'U'#255
+ +#239#190'U'#255#239#190'U'#255#239#190'U'#255#239#190'U'#255#239#190'U'#255
+ +#239#190'U'#255#239#190'U'#255#239#190'U'#255#238#190'U'#255#238#190'U'#255
+ +#238#190'U'#255#238#189'U'#255#237#188'U'#255#236#186'T'#255#234#184'T'#255
+ +#231#180'S'#255#226#175'Q'#255#220#166'N'#255#212#156'K'#255#202#143'F'#255
+ +#190#129'A'#255#179'r<'#255#145'Y0'#255'k?"'#255'c7'#31#255'[4 '#248'IC@'#209
+ +'DDD'#200'CCC'#190'CCC'#163'DDDtCCCAEEE'#26'III'#7#0#0#0#1#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'III'#7'==='#25'AAA?CCCsBBB'
+ +#162'K?;'#202'^4'#30#252'c8 '#255'oB%'#255#160'b5'#255#183'v>'#255#194#134'D'
+ +#255#205#148'J'#255#215#161'M'#255#223#171'Q'#255#228#177'T'#255#232#182'U'
+ +#255#234#185'V'#255#236#187'V'#255#236#187'V'#255#237#188'W'#255#237#189'W'
+ +#255#237#188'W'#255#237#188'W'#255#237#188'W'#255#237#188'W'#255#237#188'W'
+ +#255#237#188'W'#255#237#188'W'#255#237#188'W'#255#237#188'W'#255#237#188'W'
+ +#255#237#188'W'#255#237#188'W'#255#237#188'W'#255#237#188'W'#255#237#188'W'
+ +#255#237#188'W'#255#237#188'W'#255#159'~:'#255#16#13#6#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1#0#0#255#16#13#6
+ +#255'9-'#21#255'y`,'#255#208#165'M'#255#237#188'W'#255#237#188'W'#255#237#188
+ +'W'#255#237#188'W'#255#237#188'W'#255#237#188'W'#255#237#188'W'#255#237#188
+ +'W'#255#237#188'W'#255#237#188'W'#255#237#188'W'#255#237#188'W'#255#237#188
+ +'W'#255#237#188'W'#255#237#188'W'#255#237#188'W'#255#237#189'W'#255#237#188
+ +'W'#255#236#187'V'#255#235#186'V'#255#234#184'U'#255#231#180'U'#255#227#175
+ +'R'#255#221#169'Q'#255#213#157'L'#255#202#144'H'#255#191#129'C'#255#180's='
+ +#255#145'X0'#255'j>#'#255'b6'#31#255'Z5#'#245'GDB'#206'DDD'#200'CCC'#186'DDD'
+ +#154'EEEhBBB6@@@'#20'333'#5#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#1'@@@'#4'GGG'#18'AAA3DDDfCCC'#152'IA>'#195'\4 '#250'c7'#31#255'm@#'#255
+ +#156'_5'#255#182'v?'#255#194#134'E'#255#206#148'K'#255#215#161'O'#255#223#171
+ +'S'#255#228#178'V'#255#232#182'V'#255#233#185'X'#255#234#186'X'#255#235#187
+ +'X'#255#236#187'X'#255#236#188'X'#255#236#188'X'#255#236#188'X'#255#236#188
+ +'X'#255#236#188'X'#255#236#188'X'#255#236#188'X'#255#236#188'X'#255#236#188
+ +'X'#255#236#188'X'#255#236#188'X'#255#236#188'X'#255#236#188'X'#255#236#188
+ +'X'#255#236#188'X'#255#236#188'X'#255#236#188'X'#255#236#188'X'#255'9-'#21
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#6
+ +#5#2#255'$'#29#14#255'ZH"'#255#169#135'@'#255#234#186'X'#255#236#188'X'#255
+ ,#236#188'X'#255#236#188'X'#255#236#188'X'#255#236#188'X'#255#236#188'X'#255
+ +#236#188'X'#255#236#188'X'#255#236#188'X'#255#236#188'X'#255#236#188'X'#255
+ +#236#188'X'#255#236#187'X'#255#235#187'Y'#255#235#186'X'#255#234#186'X'#255
+ +#233#184'W'#255#231#180'W'#255#227#176'T'#255#221#169'R'#255#213#158'N'#255
+ +#203#145'J'#255#192#130'D'#255#179's='#255#139'U/'#255'i="'#255'a5'#30#255'X'
+ +'7%'#242'FDC'#204'CCC'#198'DDD'#180'CCC'#144'CCC[AAA+III'#14'UUU'#3#0#0#0#1#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#128#128#128#2'@@@'#12'AAA''CCCWCCC'#140'GB?'
+ +#185'Z4!'#247'a6'#30#255'j?"'#255#151']2'#255#181't>'#255#194#133'F'#255#206
+ +#149'M'#255#215#161'Q'#255#223#170'T'#255#228#178'W'#255#231#181'Y'#255#232
+ +#183'Y'#255#233#185'Z'#255#234#185'Y'#255#234#186'Y'#255#234#186'Y'#255#234
+ +#186'Z'#255#234#186'Z'#255#234#186'Z'#255#234#186'Z'#255#234#186'Z'#255#234
+ +#186'Z'#255#234#186'Z'#255#234#186'Z'#255#234#186'Z'#255#234#186'Z'#255#234
+ +#186'Z'#255#234#186'Z'#255#234#186'Z'#255#234#186'Z'#255#234#186'Z'#255#234
+ +#186'Z'#255#234#186'Z'#255'C5'#26#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#1#1#1#255#20#16#8#255'K;'#29#255#189#150'I'#255#234#186'Z'#255#234#186
+ +'Z'#255#234#186'Z'#255#234#186'Z'#255#234#186'Z'#255#234#186'Z'#255#234#186
+ +'Z'#255#234#186'Z'#255#234#186'Z'#255#234#186'Z'#255#234#186'Y'#255#234#186
+ +'Y'#255#234#185'Y'#255#233#185'Z'#255#232#183'Y'#255#230#181'X'#255#226#176
+ +'W'#255#221#169'T'#255#213#159'O'#255#203#145'K'#255#190#129'D'#255#178'p='
+ +#255#134'Q-'#255'g;"'#255'`4'#29#255'U7('#238'CCC'#202'DDD'#195'DDD'#173'BBB'
+ +#131'CCCL@@@ 999'#9#0#0#0#2#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'III'#7'BBB'#27'CC'
+ +'CEDDD|DDD'#170'V6%'#238'`5'#30#255'h<"'#255#145'Y1'#255#179's?'#255#192#132
+ +'F'#255#205#148'M'#255#215#161'R'#255#222#171'U'#255#227#176'X'#255#230#181
+ +'Z'#255#231#183'Z'#255#232#183'['#255#232#184'['#255#233#185'['#255#233#185
+ +'['#255#233#185'['#255#233#185'['#255#233#185'['#255#233#185'['#255#233#185
+ +'['#255#233#185'['#255#233#185'['#255#233#185'['#255#233#185'['#255#233#185
+ +'['#255#233#185'['#255#233#185'['#255#233#185'['#255#233#185'['#255#233#185
+ +'['#255#233#185'['#255#233#185'['#255#127'd1'#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#13#11#5
+ +#255'N>'#31#255#193#153'L'#255#233#185'['#255#233#185'['#255#233#185'['#255
+ +#233#185'['#255#233#185'['#255#233#185'['#255#233#185'['#255#233#185'['#255
+ +#233#185'['#255#233#184'['#255#232#184'['#255#232#183'Z'#255#231#182'Z'#255
+ +#229#180'Y'#255#226#175'X'#255#220#168'U'#255#213#158'R'#255#201#144'K'#255
+ +#189#127'D'#255#175'n<'#255#128'N+'#255'e9 '#255'_3'#29#255'Q;1'#227'CCC'#201
+ +'CCC'#191'CCC'#163'CCCrAAA;FFF'#22'333'#5#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'@@@'#4'<<<'
+ +#17'AAA3EEEhCCC'#156'R:/'#220'_3'#29#255'e: '#255#134'Q-'#255#178'p>'#255#190
+ +#130'F'#255#203#145'M'#255#213#161'S'#255#221#170'W'#255#226#176'Z'#255#229
+ +#180'Z'#255#230#182'\'#255#231#182'\'#255#231#183'\'#255#231#183'\'#255#231
+ +#183'\'#255#231#183'\'#255#231#183'\'#255#231#183'\'#255#231#183'\'#255#231
+ +#183'\'#255#231#183'\'#255#231#183'\'#255#231#183'\'#255#231#183'\'#255#231
+ +#183'\'#255#231#183'\'#255#231#183'\'#255#231#183'\'#255#231#183'\'#255#231
+ +#183'\'#255#231#183'\'#255#231#183'\'#255#180#142'G'#255#1#1#1#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#15#12#6#255'VE"'#255#215#171'V'#255
+ +#231#183'\'#255#231#183'\'#255#231#183'\'#255#231#183'\'#255#231#183'\'#255
+ +#231#183'\'#255#231#183'\'#255#231#183'\'#255#231#183'\'#255#231#182'\'#255
+ +#230#181'['#255#228#178'['#255#225#175'Y'#255#219#168'W'#255#211#156'Q'#255
+ +#200#142'K'#255#187'|D'#255#172'k<'#255'wF('#255'c7 '#255'^1'#30#254'K@:'#214
+ +'DDD'#199'CCC'#184'CCC'#148'AAA^GGG+NNN'#13'UUU'#3#0#0#0#0#0#0#0#0#0#0#0#0#0
+ ,#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#2'MMM'#10'@'
+ +'@@$DDDSDDD'#139'L?8'#197'^1'#29#254'c7 '#255'wG)'#255#173'l<'#255#188#127'E'
+ +#255#201#144'N'#255#212#158'T'#255#220#169'X'#255#225#175'['#255#228#179'\'
+ +#255#229#180'\'#255#230#181']'#255#230#181']'#255#230#182']'#255#230#182']'
+ +#255#230#182']'#255#230#182']'#255#230#182']'#255#230#182']'#255#230#182']'
+ +#255#230#182']'#255#230#182']'#255#230#182']'#255#230#182']'#255#230#182']'
+ +#255#230#182']'#255#230#182']'#255#230#182']'#255#230#182']'#255#230#182']'
+ +#255#230#182']'#255#230#182']'#255#221#175'Y'#255#10#8#4#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1#1#1#255'4'
+ +')'#21#255#184#146'J'#255#230#182']'#255#230#182']'#255#230#182']'#255#230
+ +#182']'#255#230#182']'#255#230#182']'#255#230#182']'#255#230#181']'#255#229
+ +#182']'#255#228#180']'#255#227#178'\'#255#224#174'['#255#218#166'W'#255#209
+ +#155'R'#255#198#139'K'#255#184'zC'#255#162'd8'#255'l@$'#255'a5'#30#255'Z3 '
+ +#249'FBA'#206'DDD'#196'CCC'#174'CCC'#129'BBBIFFF'#29'@@@'#8#0#0#0#1#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'333'#5'FF'
+ +'F'#22'BBB>CCCvFA?'#174'Z3'#31#248'`5'#30#255'l@$'#255#163'd9'#255#184'{D'
+ +#255#199#142'N'#255#210#156'T'#255#218#167'Y'#255#223#174'\'#255#226#177'^'
+ +#255#228#179'^'#255#228#179'^'#255#228#180'_'#255#228#180'_'#255#228#180'_'
+ +#255#228#180'_'#255#228#180'_'#255#228#180'_'#255#228#180'_'#255#228#180'_'
+ +#255#228#180'_'#255#228#180'_'#255#228#180'_'#255#228#180'_'#255#228#180'_'
+ +#255#228#180'_'#255#228#180'_'#255#228#180'_'#255#228#180'_'#255#228#180'_'
+ +#255#228#180'_'#255#228#180'_'#255#228#180'_'#255'bM)'#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#27#21#11#255#140'o;'#255#228#180'_'#255#228#180
+ +'_'#255#228#180'_'#255#228#180'_'#255#228#180'_'#255#228#180'_'#255#228#180
+ +'_'#255#228#179'^'#255#227#179'^'#255#226#176']'#255#222#172'['#255#216#164
+ +'X'#255#207#152'R'#255#195#137'K'#255#181'tA'#255#149'Z3'#255'g<"'#255'_3'#29
+ +#255'V6'''#239'CCC'#201'CCC'#190'CCC'#159'CCCkCCC5GGG'#18'@@@'#4#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#2'@@@'#12'CCC'
+ +'*DDD^DDD'#150'U6('#230'^2'#28#255'f:!'#255#149'Z3'#255#181'uB'#255#195#137
+ +'K'#255#208#154'T'#255#216#165'Y'#255#221#172']'#255#225#176'^'#255#226#178
+ +'_'#255#227#178'_'#255#227#178'_'#255#227#179'_'#255#227#179'_'#255#227#179
+ +'_'#255#227#179'_'#255#227#179'_'#255#227#179'_'#255#227#179'_'#255#227#179
+ +'_'#255#227#179'_'#255#227#179'_'#255#227#179'_'#255#227#179'_'#255#227#179
+ +'_'#255#227#179'_'#255#227#179'_'#255#227#179'_'#255#227#179'_'#255#227#179
+ +'_'#255#227#179'_'#255#227#179'_'#255#227#179'_'#255#13#10#6#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'&'#30#16#255#208#164
+ +'W'#255#227#179'_'#255#227#179'_'#255#227#179'_'#255#227#179'_'#255#227#178
+ +'_'#255#227#178'_'#255#226#179'`'#255#226#177'_'#255#224#176'^'#255#220#170
+ +'\'#255#214#162'X'#255#205#149'R'#255#191#131'I'#255#177'p?'#255#131'O.'#255
+ +'c7 '#255']1'#29#255'N;3'#222'DDD'#199'DDD'#181'CCC'#140'DDDSDDD"999'#9#0#0#0
+ +#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'+++'#6'@@@'#24
+ +'EEECCCC~K=7'#193']0'#28#255'b6'#31#255#129'M,'#255#177'o@'#255#191#131'J'
+ +#255#204#149'S'#255#214#163'Z'#255#220#171']'#255#223#174'_'#255#225#176'`'
+ +#255#225#177'`'#255#226#177'`'#255#226#177'`'#255#226#177'`'#255#226#177'`'
+ +#255#226#177'`'#255#226#177'`'#255#226#177'`'#255#226#177'`'#255#226#177'`'
+ +#255#226#177'`'#255#226#177'`'#255#226#177'`'#255#226#177'`'#255#226#177'`'
+ ,#255#226#177'`'#255#226#177'`'#255#226#177'`'#255#226#177'`'#255#226#177'`'
+ +#255#226#177'`'#255#226#177'`'#255#226#177'`'#255#161'~D'#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#4#3#2
+ +#255#134'i9'#255#226#177'`'#255#226#177'`'#255#226#177'`'#255#226#177'`'#255
+ +#226#177'`'#255#225#178'`'#255#225#177'`'#255#224#176'_'#255#222#174'^'#255
+ +#219#169']'#255#212#159'X'#255#200#144'Q'#255#187'~G'#255#170'j<'#255'qB%'
+ +#255'`5'#30#255'Z2'#31#250'FBA'#205'CCC'#193'DDD'#166'CCCsCCC9CCC'#19'@@@'#4
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#2'@@@'#12'AAA+BBB'
+ +'aDBB'#155'Y3!'#244'_3'#29#255'l?$'#255#167'f;'#255#186'}H'#255#200#144'R'
+ +#255#211#158'Y'#255#218#168']'#255#221#172'`'#255#223#174'a'#255#223#176'a'
+ +#255#224#176'b'#255#224#176'b'#255#224#176'b'#255#224#176'b'#255#224#176'b'
+ +#255#224#176'b'#255#224#176'b'#255#224#176'b'#255#224#176'b'#255#224#176'b'
+ +#255#224#176'b'#255#224#176'b'#255#224#176'b'#255#224#176'b'#255#224#176'b'
+ +#255#224#176'b'#255#224#176'b'#255#224#176'b'#255#224#176'b'#255#224#176'b'
+ +#255#224#176'b'#255#224#176'b'#255#224#176'b'#255'hR.'#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255'qY2'#255#224#176'b'#255#224#176'b'#255#224#176'b'#255#224#176
+ +'b'#255#224#176'b'#255#224#176'b'#255#223#176'a'#255#223#174'`'#255#221#172
+ +'_'#255#217#166']'#255#208#155'W'#255#196#139'O'#255#182'wE'#255#152'\5'#255
+ +'e9!'#255'^2'#29#255'S7*'#233'DDD'#200'CCC'#183'DDD'#143'EEEUDDD"UUU'#9#0#0#0
+ +#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'333'#5'@@@'#24'DDDDCCC~P8-'
+ +#211']0'#29#255'c8!'#255#144'V2'#255#180'uD'#255#196#138'P'#255#207#155'X'
+ +#255#215#165']'#255#220#171'`'#255#221#173'b'#255#222#174'a'#255#222#175'b'
+ +#255#222#175'b'#255#222#175'b'#255#222#175'b'#255#222#175'b'#255#222#175'b'
+ +#255#222#175'b'#255#222#175'b'#255#222#175'b'#255#222#175'b'#255#222#175'b'
+ +#255#222#175'b'#255#222#175'b'#255#222#175'b'#255#222#175'b'#255#222#175'b'
+ +#255#222#175'b'#255#222#175'b'#255#222#175'b'#255#222#175'b'#255#222#175'b'
+ +#255#222#175'b'#255#222#175'b'#255#222#175'b'#255'VD&'#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#1#1#0#255#166#132'J'#255#222#175'b'#255#222#175'b'#255#222#175
+ +'b'#255#222#175'b'#255#222#175'b'#255#222#175'b'#255#222#174'a'#255#221#173
+ +'a'#255#219#170'`'#255#213#163'\'#255#205#150'V'#255#192#132'M'#255#176'oA'
+ +#255'}K,'#255'a5'#31#255'\0'#28#254'I?;'#212'CCC'#194'DDD'#166'CCCrDDD8GGG'
+ +#18'@@@'#4#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#2'FFF'#11'DDD)BBB`G@<'
+ +#164'[1'#29#252'_3'#29#255'uD)'#255#174'l?'#255#189#130'L'#255#204#150'V'#255
+ +#213#162'^'#255#217#168'`'#255#220#172'b'#255#221#173'b'#255#221#173'c'#255
+ +#221#173'c'#255#221#173'c'#255#221#173'c'#255#221#173'c'#255#221#173'c'#255
+ +#221#173'c'#255#221#173'c'#255#221#173'c'#255#221#173'c'#255#221#173'c'#255
+ +#221#173'c'#255#221#173'c'#255#221#173'c'#255#221#173'c'#255#221#173'c'#255
+ +#221#173'c'#255#221#173'c'#255#221#173'c'#255#221#173'c'#255#221#173'c'#255
+ +#221#173'c'#255#221#173'c'#255#221#173'c'#255#221#173'c'#255'gQ.'#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ ,#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#8#6#4#255#207#163']'#255#221#173'c'#255
+ +#221#173'c'#255#221#173'c'#255#221#173'c'#255#221#173'c'#255#221#173'c'#255
+ +#221#172'b'#255#219#171'b'#255#217#167'`'#255#211#159'['#255#200#145'T'#255
+ +#185'{H'#255#164'd;'#255'h<#'#255'^1'#29#255'X3#'#244'DDD'#200'CCC'#183'DDD'
+ +#142'DDDSFFF!@@@'#8#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'@@@'#4'III'#21'EEE?DD'
+ +'D|S5'''#222'\1'#28#255'c8!'#255#158'_8'#255#183'yH'#255#198#142'S'#255#209
+ +#158'\'#255#215#166'`'#255#218#170'b'#255#219#171'c'#255#219#171'd'#255#219
+ +#172'd'#255#219#172'd'#255#219#172'd'#255#219#172'd'#255#219#172'd'#255#219
+ +#172'd'#255#219#172'd'#255#219#172'd'#255#219#172'd'#255#219#172'd'#255#219
+ +#172'd'#255#219#172'd'#255#219#172'd'#255#219#172'd'#255#219#172'd'#255#219
+ +#172'd'#255#219#172'd'#255#219#172'd'#255#219#172'd'#255#219#172'd'#255#219
+ +#172'd'#255#219#172'd'#255#219#172'd'#255#219#172'd'#255#219#172'd'#255#213
+ +#168'b'#255#3#3#1#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'M<#'#255#219#172
+ +'d'#255#219#172'd'#255#219#172'd'#255#219#172'd'#255#219#172'd'#255#219#172
+ +'d'#255#219#171'd'#255#219#170'c'#255#217#168'b'#255#214#164'`'#255#207#153
+ +'Z'#255#194#136'P'#255#178'rD'#255#139'R1'#255'a4'#31#255'\0'#28#255'L<5'#219
+ +'CCC'#193'DDD'#164'CCCoCCC5@@@'#16'UUU'#3#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'@@@'#8
+ +'BBB#CCCWHA='#158'\0'#28#253'_3'#29#255'~I+'#255#175'nB'#255#191#133'O'#255
+ +#205#151'Z'#255#213#163'a'#255#216#167'c'#255#217#169'c'#255#218#170'd'#255
+ +#218#170'd'#255#218#170'd'#255#218#170'd'#255#218#170'd'#255#218#170'd'#255
+ +#218#170'd'#255#218#170'd'#255#218#170'd'#255#218#170'd'#255#218#170'd'#255
+ +#218#170'd'#255#218#170'd'#255#218#170'd'#255#218#170'd'#255#218#170'd'#255
+ +#218#170'd'#255#218#170'd'#255#218#170'd'#255#218#170'd'#255#218#170'd'#255
+ +#218#170'd'#255#218#170'd'#255#218#170'd'#255#218#170'd'#255#218#170'd'#255
+ +#218#170'd'#255#218#170'd'#255'YF)'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#15#12#7#255#218#170'd'#255#218#170'd'#255#218#170'd'#255#218#170'd'#255
+ +#218#170'd'#255#218#170'd'#255#218#170'd'#255#218#169'c'#255#217#168'c'#255
+ +#215#166'b'#255#211#160'_'#255#201#147'W'#255#187#127'L'#255#169'h>'#255'l=$'
+ +#255'^1'#29#255'W3"'#244'DDD'#199'DDD'#180'DDD'#136'DDDKBBB'#27'UUU'#6#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0'UUU'#3'DDD'#15'EEE4BBBpS6)'#215'\1'#28#255'b7!'#255#158'_9'
+ +#255#184'{J'#255#199#144'W'#255#209#158'_'#255#214#165'c'#255#216#168'd'#255
+ +#217#168'd'#255#217#168'd'#255#217#168'd'#255#217#168'd'#255#217#168'd'#255
+ +#217#168'd'#255#217#168'd'#255#217#168'd'#255#217#168'd'#255#217#168'd'#255
+ +#217#168'd'#255#217#168'd'#255#217#168'd'#255#217#168'd'#255#217#168'd'#255
+ +#217#168'd'#255#217#168'd'#255#217#168'd'#255#217#168'd'#255#217#168'd'#255
+ +#217#168'd'#255#217#168'd'#255#217#168'd'#255#217#168'd'#255#217#168'd'#255
+ +#217#168'd'#255#217#168'd'#255#217#168'd'#255#217#168'd'#255#217#168'd'#255
+ +'YD)'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#189#147'W'#255#217#168'd'
+ +#255#217#168'd'#255#217#168'd'#255#217#168'd'#255#217#168'd'#255#217#168'd'
+ +#255#217#168'd'#255#216#168'd'#255#215#167'c'#255#213#164'a'#255#207#154']'
+ +#255#195#138'S'#255#179'tF'#255#139'R1'#255'`5'#30#255'\0'#28#255'K=7'#216'D'
+ +'DD'#191'DDD'#157'CCCcAAA+FFF'#11#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ ,#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'+++'#6'EEE'#26'BBBIE?='
+ +#144'Z0'#28#252'^2'#29#255'zF*'#255#174'mB'#255#192#135'R'#255#205#152'\'#255
+ +#211#161'b'#255#214#165'd'#255#215#166'd'#255#215#166'd'#255#215#166'd'#255
+ +#215#166'd'#255#215#166'd'#255#215#166'd'#255#215#166'd'#255#215#166'd'#255
+ +#215#166'd'#255#215#166'd'#255#215#166'd'#255#215#166'd'#255#215#166'd'#255
+ +#215#166'd'#255#215#166'd'#255#215#166'd'#255#215#166'd'#255#215#166'd'#255
+ +#215#166'd'#255#215#166'd'#255#215#166'd'#255#215#166'd'#255#215#166'd'#255
+ +#215#166'd'#255#215#166'd'#255#215#166'd'#255#215#166'd'#255#215#166'd'#255
+ +#215#166'd'#255#215#166'd'#255#215#166'd'#255#215#166'd'#255'jR1'#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255'fN/'#255#215#166'd'#255#215#166'd'#255#215#166'd'
+ +#255#215#166'd'#255#215#166'd'#255#215#166'd'#255#215#166'd'#255#215#166'd'
+ +#255#215#167'e'#255#214#164'c'#255#210#159'a'#255#202#148'Z'#255#187#128'N'
+ +#255#168'f='#255'i;#'#255'\1'#28#255'V3#'#242'CCC'#197'DDD'#173'BBB{FFF>@@@'
+ +#20'@@@'#4#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#1'MMM'#10'FFF(CCC_R6*'#206'\0'#28#255'`5'#31#255#154'\8'
+ +#255#182'yJ'#255#199#144'Y'#255#208#156'`'#255#212#163'd'#255#213#165'd'#255
+ +#214#165'e'#255#214#165'e'#255#214#165'e'#255#214#165'e'#255#214#165'e'#255
+ +#214#165'e'#255#214#165'e'#255#214#165'e'#255#214#165'e'#255#214#165'e'#255
+ +#214#165'e'#255#214#165'e'#255#214#165'e'#255#214#165'e'#255#214#165'e'#255
+ +#214#165'e'#255#214#165'e'#255#214#165'e'#255#214#165'e'#255#214#165'e'#255
+ +#214#165'e'#255#214#165'e'#255#214#165'e'#255#214#165'e'#255#214#165'e'#255
+ +#214#165'e'#255#214#165'e'#255#214#165'e'#255#214#165'e'#255#214#165'e'#255
+ +#214#165'e'#255#214#165'e'#255#214#165'e'#255#135'h@'#255#2#1#1#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'b'
+ +'L/'#255#214#165'e'#255#214#165'e'#255#214#165'e'#255#214#165'e'#255#214#165
+ +'e'#255#214#165'e'#255#214#165'e'#255#214#165'e'#255#213#165'e'#255#213#164
+ +'d'#255#211#161'c'#255#206#154'^'#255#194#139'U'#255#177'sF'#255#135'P/'#255
+ +'^3'#29#255'[/'#27#255'J>9'#213'DDD'#185'CCC'#144'DDDSHHH III'#7#0#0#0#1#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'UUU'#3
+ +'<<<'#17'DDD8DBAyZ0'#29#248'\1'#28#255'uB'''#255#172'lA'#255#190#132'Q'#255
+ +#203#151'^'#255#209#160'c'#255#211#162'e'#255#212#163'e'#255#212#163'e'#255
+ +#212#163'e'#255#212#163'e'#255#212#163'e'#255#212#163'e'#255#212#163'e'#255
+ +#212#163'e'#255#212#163'e'#255#212#163'e'#255#212#163'e'#255#212#163'e'#255
+ +#212#163'e'#255#212#163'e'#255#212#163'e'#255#212#163'e'#255#212#163'e'#255
+ +#212#163'e'#255#212#163'e'#255#212#163'e'#255#212#163'e'#255#212#163'e'#255
+ +#212#163'e'#255#212#163'e'#255#212#163'e'#255#212#163'e'#255#212#163'e'#255
+ +#212#163'e'#255#212#163'e'#255#212#163'e'#255#212#163'e'#255#212#163'e'#255
+ +#212#163'e'#255#212#163'e'#255#212#163'e'#255#156'xK'#255#1#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'jQ2'#255#212
+ +#163'e'#255#212#163'e'#255#212#163'e'#255#212#163'e'#255#212#163'e'#255#212
+ +#163'e'#255#212#163'e'#255#212#163'e'#255#212#163'e'#255#212#162'e'#255#211
+ +#162'd'#255#208#158'b'#255#200#147'['#255#186'~M'#255#165'd<'#255'd8!'#255'\'
+ +'0'#28#255'T5'''#237'CCC'#193'DDD'#162'CCCjCCC.@@@'#12#0#0#0#2#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'333'#5'GGG'#25'BB'
+ +'BIN:1'#174'[/'#27#255'^2'#29#255#145'T3'#255#180'vI'#255#196#142'Y'#255#206
+ +#155'a'#255#209#161'e'#255#211#162'e'#255#211#162'e'#255#211#162'e'#255#211
+ +#162'e'#255#211#162'e'#255#211#162'e'#255#211#162'e'#255#211#162'e'#255#211
+ +#162'e'#255#211#162'e'#255#211#162'e'#255#211#162'e'#255#211#162'e'#255#211
+ ,#162'e'#255#211#162'e'#255#211#162'e'#255#211#162'e'#255#211#162'e'#255#211
+ +#162'e'#255#211#162'e'#255#211#162'e'#255#211#162'e'#255#211#162'e'#255#211
+ +#162'e'#255#211#162'e'#255#211#162'e'#255#211#162'e'#255#211#162'e'#255#211
+ +#162'e'#255#211#162'e'#255#211#162'e'#255#211#162'e'#255#211#162'e'#255#211
+ +#162'e'#255#211#162'e'#255#211#162'e'#255#211#162'e'#255'O=&'#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'sX7'#255#211
+ +#162'e'#255#211#162'e'#255#211#162'e'#255#211#162'e'#255#211#162'e'#255#211
+ +#162'e'#255#211#162'e'#255#211#162'e'#255#211#162'e'#255#211#162'e'#255#210
+ +#161'f'#255#209#159'd'#255#204#153'`'#255#192#135'U'#255#175'pE'#255'~H+'#255
+ +']0'#29#255'Z0'#28#253'FBA'#201'DDD'#176'CCC~FFF>CCC'#19'@@@'#4#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'999'#9'EEE%CCC[V3'
+ +'$'#222'\0'#27#255'f7!'#255#167'd>'#255#187#128'Q'#255#200#148'^'#255#207#156
+ +'d'#255#209#159'e'#255#209#160'e'#255#209#160'e'#255#209#160'e'#255#209#160
+ +'e'#255#209#160'e'#255#209#160'e'#255#209#160'e'#255#209#160'e'#255#209#160
+ +'e'#255#209#160'e'#255#209#160'e'#255#209#160'e'#255#209#160'e'#255#209#160
+ +'e'#255#209#160'e'#255#209#160'e'#255#151'tI'#255'2&'#25#255#27#21#13#255#15
+ +#12#7#255#7#5#3#255#7#5#3#255' '#25#16#255'P='''#255#151'tI'#255#209#160'e'
+ +#255#209#160'e'#255#209#160'e'#255#209#160'e'#255#209#160'e'#255#209#160'e'
+ +#255#209#160'e'#255#209#160'e'#255#209#160'e'#255#209#160'e'#255#209#160'e'
+ +#255#209#160'e'#255#209#160'e'#255#6#5#3#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#146'pF'#255#209#160'e'#255#209#160'e'#255
+ +#209#160'e'#255#209#160'e'#255#209#160'e'#255#209#160'e'#255#209#160'e'#255
+ +#209#160'e'#255#209#160'e'#255#209#160'e'#255#209#160'e'#255#209#159'e'#255
+ +#206#155'c'#255#198#143'['#255#182'zM'#255#151'Y6'#255'^3'#29#255'[/'#27#255
+ +'N:1'#222'DDD'#185'DDD'#142'DDDOIII'#28'+++'#6#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#2';;;'#13'DDD1F@=x[/'#28#253'\1'#28
+ +#255'~G+'#255#174'oE'#255#193#137'X'#255#203#151'b'#255#207#156'e'#255#207
+ +#158'f'#255#208#158'f'#255#208#158'f'#255#208#158'f'#255#208#158'f'#255#208
+ +#158'f'#255#208#158'f'#255#208#158'f'#255#208#158'f'#255#208#158'f'#255#208
+ +#158'f'#255#208#158'f'#255#208#158'f'#255#208#158'f'#255#208#158'f'#255'x[;'
+ +#255#15#12#8#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#4#3#2#255'bJ0'#255#208#158'f'#255#208#158'f'
+ +#255#208#158'f'#255#208#158'f'#255#208#158'f'#255#208#158'f'#255#208#158'f'
+ +#255#208#158'f'#255#208#158'f'#255#208#158'f'#255#208#158'f'#255'3'''#25#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#2#2#1#255#208#158'f'
+ +#255#208#158'f'#255#208#158'f'#255#208#158'f'#255#208#158'f'#255#208#158'f'
+ +#255#208#158'f'#255#208#158'f'#255#208#158'f'#255#208#158'f'#255#208#158'f'
+ +#255#208#158'f'#255#207#158'e'#255#206#156'd'#255#201#149'_'#255#189#131'T'
+ +#255#169'h@'#255'j:#'#255'\0'#28#255'V3#'#242'DDD'#191'CCC'#156'BBB`AAA''333'
+ +#10#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'@@@'#4'C'
+ +'CC'#19'EEE?Q7+'#179'[/'#27#255'^1'#29#255#152'X6'#255#181'yM'#255#197#144']'
+ +#255#204#153'c'#255#206#155'f'#255#206#156'e'#255#206#156'e'#255#206#156'e'
+ +#255#206#156'e'#255#206#156'e'#255#206#156'e'#255#206#156'e'#255#206#156'e'
+ +#255#206#156'e'#255#206#156'e'#255#206#156'e'#255#206#156'e'#255#206#156'e'
+ +#255#202#154'c'#255'6)'#27#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#14#10#7#255#178#135'W'#255#206#156'e'#255#206#156'e'#255#206#156'e'
+ +#255#206#156'e'#255#206#156'e'#255#206#156'e'#255#206#156'e'#255#206#156'e'
+ +#255#206#156'e'#255'WB+'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ ,#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#29#22#14#255#206#156'e'#255#206#156'e'#255#206#156'e'#255#206#156'e'
+ +#255#206#156'e'#255#206#156'e'#255#206#156'e'#255#206#156'e'#255#206#156'e'
+ +#255#206#156'e'#255#206#156'e'#255#206#156'e'#255#206#156'e'#255#205#156'e'
+ +#255#203#151'c'#255#194#139'Z'#255#176'qH'#255#131'K-'#255'\1'#28#255'[/'#27
+ +#255'HA='#204'DDD'#169'DDDqEEE4III'#14#128#128#128#2#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'+++'#6'BBB'#27'EEENW2!'#228'[/'#27#255'i9!'
+ +#255#168'e?'#255#187#130'T'#255#200#147'`'#255#203#153'e'#255#205#154'e'#255
+ +#205#154'e'#255#205#154'e'#255#205#154'e'#255#205#154'e'#255#205#154'e'#255
+ +#205#154'e'#255#205#154'e'#255#205#154'e'#255#205#154'e'#255#205#154'e'#255
+ +#205#154'e'#255#205#154'e'#255#199#150'a'#255#19#14#9#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#7#6#4#255#178#133'W'
+ +#255#205#154'e'#255#205#154'e'#255#205#154'e'#255#205#154'e'#255#205#154'e'
+ +#255#205#154'e'#255#205#154'e'#255#205#154'e'#255'S>)'#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#128'a?'#255#205#154'e'#255#205#154'e'
+ +#255#205#154'e'#255#205#154'e'#255#205#154'e'#255#205#154'e'#255#205#154'e'
+ +#255#205#154'e'#255#205#154'e'#255#205#154'e'#255#205#154'e'#255#205#154'e'
+ +#255#205#154'e'#255#204#154'e'#255#203#152'd'#255#197#145'^'#255#182'zO'#255
+ +#157'Z8'#255']1'#29#255'[/'#27#255'P9.'#226'CCC'#179'CCC'#129'CCCA@@@'#20'@@'
+ +'@'#4#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'999'#9'EEE%EA?'
+ +'b[/'#27#253'\0'#27#255#127'F*'#255#173'nG'#255#191#136'Z'#255#200#149'c'#255
+ +#202#152'e'#255#202#152'e'#255#202#153'e'#255#202#153'e'#255#202#153'e'#255
+ +#202#153'e'#255#202#153'e'#255#202#153'e'#255#202#153'e'#255#202#153'e'#255
+ +#202#153'e'#255#202#153'e'#255#202#153'e'#255#202#153'e'#255#31#24#16#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#11#8#6#255#200#151'e'#255#202#153'e'#255#202#153'e'#255#202
+ +#153'e'#255#202#153'e'#255#202#153'e'#255#202#153'e'#255#202#153'e'#255'O;'''
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255''''#29#19#255#202#153'e'#255
+ +#202#153'e'#255#202#153'e'#255#202#153'e'#255#202#153'e'#255#202#153'e'#255
+ +#202#153'e'#255#202#153'e'#255#202#153'e'#255#202#153'e'#255#202#153'e'#255
+ +#202#153'e'#255#202#153'e'#255#202#153'e'#255#202#152'e'#255#202#151'd'#255
+ +#199#147'b'#255#188#130'U'#255#168'e@'#255'k:"'#255'[/'#27#255'V3$'#241'CCC'
+ +#186'BBB'#142'EEENBBB'#27'+++'#6#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#2'@@@'#12'DDD-O:0'#146'[/'#27#255'\0'#28#255#145'R2'#255#179'wM'
+ +#255#194#141'^'#255#200#148'c'#255#201#150'e'#255#201#150'e'#255#201#150'e'
+ +#255#201#150'e'#255#201#150'e'#255#201#150'e'#255#201#150'e'#255#201#150'e'
+ +#255#201#150'e'#255#201#150'e'#255#201#150'e'#255#201#150'e'#255#201#150'e'
+ +#255';,'#30#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'S>*'#255#201#150'e'
+ +#255#201#150'e'#255#201#150'e'#255#201#150'e'#255#201#150'e'#255#201#150'e'
+ +#255#201#150'e'#255'K8&'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#29#22#14#255
+ +#184#138']'#255#201#150'e'#255#201#150'e'#255#201#150'e'#255#201#150'e'#255
+ ,#201#150'e'#255#201#150'e'#255#201#150'e'#255#201#150'e'#255#201#150'e'#255
+ +#201#150'e'#255#201#150'e'#255#201#150'e'#255#201#150'e'#255#201#150'e'#255
+ +#201#150'e'#255#200#149'd'#255#199#148'c'#255#191#136'['#255#173'mG'#255'}D('
+ +#255'\0'#27#255'Z0'#28#253'DBB'#192'CCC'#152'DDDZBBB#@@@'#8#0#0#0#1#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#128#128#128#2'III'#14'CCC5T5'''#190'[/'#27#255
+ +'_2'#29#255#162'^:'#255#184'}S'#255#195#142'`'#255#198#147'd'#255#199#148'd'
+ +#255#199#148'd'#255#199#148'd'#255#199#148'd'#255#199#148'd'#255#199#148'd'
+ +#255#199#148'd'#255#199#148'd'#255#199#148'd'#255#199#148'd'#255#199#148'd'
+ +#255#199#148'd'#255#147'mJ'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#3#2#1#255#195#144'b'#255#199#148'd'#255#199#148'd'#255#199#148'd'#255
+ +#199#148'd'#255#199#148'd'#255#199#148'd'#255'H6$'#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#3#2#1#255#23#17#12
+ +#255'qT8'#255#199#148'd'#255#199#148'd'#255#199#148'd'#255#199#148'd'#255#199
+ +#148'd'#255#199#148'd'#255#199#148'd'#255#199#148'd'#255#199#148'd'#255#199
+ +#148'd'#255#199#148'd'#255#199#148'd'#255#199#148'd'#255#199#148'd'#255#199
+ +#148'd'#255#199#148'd'#255#199#148'd'#255#199#148'd'#255#198#146'c'#255#193
+ +#140'^'#255#178'uN'#255#143'O1'#255'\0'#28#255'[/'#27#255'J=7'#208'CCC'#161
+ +'DDDfAAA+FFF'#11#0#0#0#2#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'UUU'#3'<<<'
+ +#17'CCC=X1 '#227'[/'#27#255'm:"'#255#167'eA'#255#187#130'X'#255#195#143'a'
+ +#255#196#144'c'#255#197#145'c'#255#197#145'c'#255#197#145'c'#255#197#145'c'
+ +#255#197#145'c'#255#197#145'c'#255#197#145'c'#255#197#145'c'#255#197#145'c'
+ +#255#197#145'c'#255#197#145'c'#255#197#145'c'#255#19#14#10#255#0#0#0#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#135'cD'#255#197#145'c'#255#197
+ +#145'c'#255#197#145'c'#255#197#145'c'#255#197#145'c'#255#197#145'c'#255'I5$'
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#19#14#10#255'4&'#26#255'cI2'#255
+ +#161'vP'#255#197#145'c'#255#197#145'c'#255#197#145'c'#255#197#145'c'#255#197
+ +#145'c'#255#197#145'c'#255#197#145'c'#255#197#145'c'#255#197#145'c'#255#197
+ +#145'c'#255#197#145'c'#255#197#145'c'#255#197#145'c'#255#197#145'c'#255#197
+ +#145'c'#255#197#145'c'#255#197#145'c'#255#197#145'c'#255#197#145'c'#255#197
+ +#145'c'#255#197#145'b'#255#196#144'c'#255#194#140'`'#255#182'|S'#255#159'\:'
+ +#255']2'#28#255'[/'#27#255'Q8-'#226'DDD'#168'DDDqAAA3NNN'#13#128#128#128#2#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'@@@'#4':::'#22'G@/[/'#27
+ +#254'[/'#27#255'}A&'#255#167'gD'#255#180'zW'#255#181'|Y'#255#181'|Y'#255#181
+ +'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'
+ +#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#136']C'#255#0#0#0#255#0#0#0#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#19#13#9#255#151'gJ'#255#181'|Y'#255#181'|Y'#255#181
+ +'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'
+ +#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#171'vU'#255'1"'#24#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1#0#0#255'}V>'#255
+ +#181'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#181
+ +'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'
+ +#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'#255
+ +#181'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#181
+ +'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'#255#181'|Y'
+ +#255#181'|Y'#255#181'|Y'#255#178'wT'#255#161'];'#255'k8 '#255'[/'#27#255'V3#'
+ +#238'DDD'#151'CCCWFFF!@@@'#8#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#2'FFF'#11
+ +'K:3?[/'#27#255'[/'#27#255#131'F*'#255#169'iH'#255#179'xV'#255#180'zW'#255
+ +#180'{W'#255#180'{W'#255#180'{W'#255#180'{W'#255#180'{W'#255#180'{W'#255#180
+ +'{W'#255#180'{W'#255#180'{W'#255#180'{W'#255#180'{W'#255'<)'#29#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#1#1#1#255'O6&'#255#180'{W'#255#180'{W'#255#180'{W'#255#180
+ +'{W'#255#180'{W'#255#180'{W'#255#180'{W'#255#180'{W'#255#180'{W'#255#180'{W'
+ +#255#180'{W'#255#180'{W'#255#180'{W'#255#180'{W'#255#180'{W'#255#180'{W'#255
+ +#180'{W'#255#142'aE'#255#27#19#13#255#2#1#1#255#0#0#0#255#0#0#0#255#0#0#0#255
+ ,#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#8#5#4#255
+ +#135']A'#255#180'{W'#255#180'{W'#255#180'{W'#255#180'{W'#255#180'{W'#255#180
+ +'{W'#255#180'{W'#255#180'{W'#255#180'{W'#255'pL6'#255'+'#29#20#255'('#28#19
+ +#255'*'#28#20#255'+'#29#21#255'-'#30#21#255'fF2'#255#180'{W'#255#180'{W'#255
+ +#180'{W'#255#180'{W'#255#180'{W'#255#180'{W'#255#180'{W'#255#180'{W'#255#180
+ +'{W'#255#180'{W'#255#180'{W'#255#180'{W'#255#180'{W'#255#180'{W'#255#180'{W'
+ +#255#180'{W'#255#180'{W'#255#180'{W'#255#180'zX'#255#178'vU'#255#163'_>'#255
+ +'r<"'#255'[/'#27#255'X2!'#243'CCC'#152'BBBYDDD"@@@'#8#0#0#0#1#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#2'FFF'#11'N8.J[/'#27#255'[/'#27#255#135'H,'#255#170'kI'#255
+ +#178'wV'#255#179'yX'#255#179'yX'#255#179'yX'#255#179'yX'#255#179'yX'#255#179
+ +'yX'#255#179'yX'#255#179'yX'#255#179'yX'#255#179'yX'#255#179'yX'#255#179'yX'
+ +#255#16#11#8#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#19#13#10#255#150'fJ'#255#179'yX'#255#179
+ +'yX'#255#179'yX'#255#179'yX'#255#179'yX'#255#179'yX'#255#179'yX'#255#179'yX'
+ +#255#179'yX'#255#179'yX'#255#179'yX'#255#179'yX'#255#179'yX'#255#179'yX'#255
+ +#179'yX'#255#179'yX'#255#179'yX'#255#179'yX'#255#179'yX'#255#179'yX'#255#179
+ +'yX'#255'~V>'#255'=)'#30#255#19#13#9#255#1#1#1#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255'$'#24#17#255#172'uT'#255#179'yX'#255#179'yX'#255#179'yX'
+ +#255#179'yX'#255#179'yX'#255#179'yX'#255#179'yX'#255#158'kN'#255'=)'#30#255#6
+ +#4#3#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#6#4#3#255'?+'#31#255#164'oP'#255#179'yX'#255#179'yX'#255#179'yX'#255#179
+ +'yX'#255#179'yX'#255#179'yX'#255#179'yX'#255#179'yX'#255#179'yX'#255#179'yX'
+ +#255#179'yX'#255#179'yX'#255#179'yX'#255#179'yX'#255#179'yX'#255#179'yX'#255
+ +#177'uU'#255#164'b@'#255'v?%'#255'[/'#27#255'Y1'#31#246'CCC'#152'BBBYDDD"@@@'
+ +#8#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'FFF'#11'Q7+U[/'#27#255'\0'#28#255
+ +#139'J-'#255#171'lL'#255#177'wW'#255#178'wV'#255#178'wV'#255#178'wV'#255#178
+ +'wV'#255#178'wV'#255#178'wV'#255#178'wV'#255#178'wV'#255#178'wV'#255#178'wV'
+ +#255#178'wV'#255#172'sT'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1#1#1#255'O5&'#255#178'wV'#255#178'wV'
+ +#255#178'wV'#255#178'wV'#255#178'wV'#255#178'wV'#255#178'wV'#255#178'wV'#255
+ +#178'wV'#255#178'wV'#255#178'wV'#255#178'wV'#255#178'wV'#255#178'wV'#255#178
+ +'wV'#255#178'wV'#255#178'wV'#255#178'wV'#255#178'wV'#255#178'wV'#255#178'wV'
+ +#255#178'wV'#255#178'wV'#255#178'wV'#255#178'wV'#255#178'wV'#255#176'wV'#255
+ +'vO9'#255'7%'#27#255#16#10#8#255#1#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0
+ +#0#255#0#0#0#255#11#8#6#255'9&'#28#255#137'\C'#255#178'wV'#255#178'wV'#255
+ +#178'wV'#255#178'wV'#255#178'wV'#255#178'wV'#255#178'wV'#255#178'wV'#255'M3%'
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1#0#0#255'4"'#25#255#178'wV'
+ +#255#178'wV'#255#178'wV'#255#178'wV'#255#178'wV'#255#178'wV'#255#178'wV'#255
+ +#178'wV'#255#178'wV'#255#178'wV'#255#178'wV'#255#178'wV'#255#178'wV'#255#178
+ +'wV'#255#178'wV'#255#176'tT'#255#165'cC'#255'yA'''#255'[/'#27#255'Z0'#29#250
+ +'DDD'#150'CCCWFFF!III'#7#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'MMM'#10'R4'
+ +'''^[/'#27#255'\0'#28#255#142'M.'#255#171'nN'#255#177'uV'#255#177'wX'#255#177
+ +'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'
+ +#255#177'wX'#255#177'wX'#255#177'wX'#255'gF3'#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#23#16#12#255#152'fK'#255#177
+ +'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'
+ +#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255
+ +#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#177
+ +'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'
+ +#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#173'uV'#255
+ +#136'\D'#255#133'YB'#255#131'XA'#255#128'V@'#255#153'gL'#255#177'wX'#255#177
+ +'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'
+ +#255#177'wX'#255#177'wX'#255'S8)'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255'"'#23#17#255#175'wX'#255#177'wX'#255#177
+ +'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'
+ +#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#177'wX'#255#175'tU'#255
+ +#166'eE'#255'}B)'#255'\0'#28#255'[/'#28#253'CCC'#148'CCCTBBB'#31'III'#7#0#0#0
+ ,#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'999'#9'V4%h[/'#27#255'\0'#28#255#145'O0'
+ +#255#171'mN'#255#175'sU'#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255
+ +#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175
+ +'uW'#255'*'#29#21#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#2
+ +#1#1#255'X;,'#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255
+ +#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175
+ +'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'
+ +#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255
+ +#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175
+ +'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'
+ +#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255
+ +#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255'^?/'#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255'$'#24#18#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255
+ +#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175'uW'#255#175
+ +'uW'#255#175'uW'#255#175'uW'#255#175'sT'#255#166'eE'#255#128'D*'#255'\0'#28
+ +#255'[/'#27#255'ECB'#149'CCCP@@@'#28'UUU'#6#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#1'@@@'#8'W3#q[/'#27#255'\1'#29#255#150'Q1'#255#171'mN'#255#174'sU'#255
+ +#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175
+ +'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#15#10#8#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#4#3#2#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#29#19#14#255#156'iM'#255#175'uV'#255
+ +#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175
+ +'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'
+ +#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255
+ +#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175
+ +'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'
+ +#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255
+ +#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175
+ +'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#11#7#6#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255'sM9'#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255
+ +#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175'uV'#255#175
+ +'tV'#255#174'rS'#255#167'fG'#255#131'G,'#255'\0'#28#255'[/'#27#255'GA?'#150
+ +'CCCLGGG'#25'333'#5#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'III'#7'W3#k[/'#27
+ +#255'\1'#29#255#149'P2'#255#169'lM'#255#174'qT'#255#175'tV'#255#175'tV'#255
+ +#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175
+ +'tV'#255#175'tV'#255#175'tV'#255#9#6#4#255#0#0#0#255#0#0#0#255#0#0#0#255#136
+ +'ZC'#255'T8*'#255#1#1#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#7#5#3#255
+ +'bA0'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'
+ +#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255
+ +#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175
+ +'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'
+ +#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255
+ +#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175
+ +'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'
+ +#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255
+ +#165'nR'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#10#7#5#255#175'tV'#255#175
+ +'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'#255#175'tV'
+ +#255#175'tV'#255#175'tV'#255#175'tV'#255#174'sU'#255#173'qR'#255#166'eG'#255
+ +#131'F,'#255'\0'#28#255'[/'#27#255'EA?'#145'DDDGFFF'#22'@@@'#4#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#1'333'#5'W3#\[/'#27#255'\1'#29#255#146'P3'#255#168
+ +'jM'#255#173'pT'#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'
+ +#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255
+ +#4#3#2#255#0#0#0#255#0#0#0#255#21#14#10#255#173'rU'#255#173'rU'#255#152'dK'
+ +#255'dB1'#255'A+ '#255'D-!'#255#141']E'#255#173'rU'#255#173'rU'#255#173'rU'
+ +#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255
+ +#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173
+ +'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'
+ ,#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255
+ +#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173
+ +'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'
+ +#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255
+ +#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#169'pS'#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#139'\D'#255#173'rU'#255#173'rU'
+ +#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255#173'rU'#255
+ +#173'rU'#255#173'rU'#255#173'qT'#255#172'oR'#255#165'cF'#255#128'E+'#255'\0'
+ +#28#255'[/'#27#255'CBA'#132'DDD@CCC'#19'UUU'#3#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0'@@@'#4'U2"L[/'#27#255'\1'#29#255#143'N3'#255#168'hK'#255#172'oT'
+ +#255#173'qU'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255
+ +#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#1#1#1#255#0#0#0
+ +#255#0#0#0#255'nI7'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173
+ +'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'
+ +#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255
+ +#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173
+ +'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'
+ +#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255
+ +#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173
+ +'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'
+ +#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255
+ +#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#2#1#1#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255'H0$'#255#173'rV'#255#173'rV'#255#173'rV'
+ +#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255#173'rV'#255
+ +#173'rV'#255#173'qU'#255#171'nQ'#255#165'dF'#255'~D+'#255'\1'#29#255'Z0'#28
+ +#252'CCCzCCC9@@@'#16#128#128#128#2#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'U'
+ +'UU'#3'T2#=[/'#27#255'\1'#29#255#140'N1'#255#166'gI'#255#171'oR'#255#173'qU'
+ +#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255
+ +#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#1#1#1#255#27#18#13#255'a@0'
+ +#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255
+ +#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173
+ +'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'
+ +#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255
+ +#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173
+ +'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'
+ +#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255
+ +#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173
+ +'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'
+ +#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255'$'#24#18#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#31#20#15#255#173'qU'#255#173'qU'#255#173'qU'#255
+ +#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173'qU'#255#173
+ +'qU'#255#172'pT'#255#169'lP'#255#164'aD'#255'{C*'#255'\1'#29#255'Y0'#30#247
+ +'CCCoBBB2;;;'#13#0#0#0#2#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#128#128#128
+ +#2'V6''-[/'#27#255'\1'#29#255#137'L0'#255#165'fH'#255#170'mQ'#255#172'pT'#255
+ +#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172
+ +'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#166'lS'#255#172'pU'#255#172'pU'
+ +#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255
+ +#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172
+ +'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'
+ +#255#172'pU'#255#172'pU'#255#172'pU'#255#168'nS'#255#134'WB'#255'b@0'#255'tK'
+ +'9'#255#166'lS'#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'
+ +#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255
+ +#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172
+ +'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'
+ +#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255
+ +#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#129'T@'#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ ,#255#0#0#0#255#0#0#0#255#22#14#11#255#172'pU'#255#172'pU'#255#172'pU'#255#172
+ +'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'#255#172'pU'
+ +#255#172'oT'#255#170'mP'#255#163'`C'#255'xB*'#255'\1'#29#255'Y1'#31#241'BBBd'
+ +'CCC*MMM'#10#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#2'T7*'#29
+ +'[/'#27#255'\1'#29#255#134'J0'#255#165'dG'#255#169'lQ'#255#171'pU'#255#172'q'
+ +'W'#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'
+ +#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255
+ +#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172
+ +'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'
+ +#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255
+ +#135'YD'#255'$'#24#18#255#3#2#2#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#8#5#4#255#30#20#16#255'xO='#255#172'qW'#255#172'qW'#255#172'qW'#255
+ +#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172
+ +'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'
+ +#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255
+ +#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172
+ +'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#14#9#7#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#20#13#10#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'
+ +#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#172'qW'#255#171'oT'#255
+ +#169'jM'#255#162'_A'#255's>'''#255'\1'#29#255'X2 '#234'CCCXDDD"@@@'#8#0#0#0#1
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'C><'#9'[/'#27#247'\1'#29#255
+ +'}F-'#255#164'bE'#255#169'lO'#255#171'pT'#255#172'qV'#255#172'qV'#255#172'qV'
+ +#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255
+ +#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255#172
+ +'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'
+ +#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255
+ +#172'qV'#255#172'qV'#255#154'eM'#255#22#15#11#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#25#17#13#255#136'ZE'#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'
+ +#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255
+ +#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255#172
+ +'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'
+ +#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255
+ +#172'qV'#255'U7*'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#17#11#9#255#172'qV'#255#172
+ +'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'#255#172'qV'
+ +#255#172'qV'#255#172'qV'#255#171'oT'#255#168'jM'#255#161'^@'#255'k;%'#255'\0'
+ +#28#255'V3#'#220'CCCLEEE'#26'333'#5#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0'+++'#6'[/'#28#214'\1'#29#255't@)'#255#162'`B'#255#168'jO'#255
+ +#172'pV'#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#173
+ +'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'
+ +#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255
+ +#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#173
+ +'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#144'_I'#255#6#4#3
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'Z;-'#255
+ +#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#173
+ +'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'
+ +#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255
+ +#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#173
+ +'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#171'pV'#255#3#2#1#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255'!'#22#17#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'
+ +#255#173'rX'#255#173'rX'#255#173'rX'#255#173'rX'#255#172'qX'#255#171'oU'#255
+ +#167'hM'#255#160'[>'#255'b5!'#255'\0'#28#255'S5'''#196'EEE?CCC'#19'@@@'#4#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'UUU'#3'Z0'#29#176'\1'#29
+ +#255'k:%'#255#162'^A'#255#169'jN'#255#173'qV'#255#174'sY'#255#174'sY'#255#174
+ +'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'
+ +#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255
+ +#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174
+ ,'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'
+ +#255#151'dM'#255#4#2#2#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#1#1#1#255#136'YF'#255#174'sY'#255#174'sY'#255#174's'
+ +'Y'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'
+ +#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255
+ +#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174
+ +'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'
+ +#255#174'sY'#255'5#'#27#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'G.$'#255#174'sY'#255#174'sY'#255
+ +#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174
+ +'sY'#255#174'sY'#255#172'pV'#255#167'gK'#255#153'X:'#255'^3'#31#255'\0'#28
+ +#255'Q7+'#166'BBB2777'#14#0#0#0#2#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#2'Z0'#29#137'\0'#28#255'a5!'#255#160']>'#255#168'jN'#255
+ +#173'sY'#255#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255#175
+ +'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'
+ +#255#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255
+ +#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255#175
+ +'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255#29#20#15#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#8
+ +#5#4#255#169'rX'#255#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'
+ +#255#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255
+ +#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255#175
+ +'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'
+ +#255#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255#156'jR'#255#1#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255'yQ?'#255#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255
+ +#175'v\'#255#175'v\'#255#175'v\'#255#175'v\'#255#174'u['#255#172'qV'#255#166
+ +'gJ'#255#143'S6'#255'^2'#31#255'[/'#27#255'O;2'#130'CCC&999'#9#0#0#0#1#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'Z0'#29'a\0'#28#255
+ +'^3'#31#255#153'W;'#255#168'jN'#255#174'tZ'#255#176'x_'#255#176'y_'#255#176
+ +'y_'#255#176'y_'#255#176'y_'#255#176'y_'#255#176'y_'#255#176'y_'#255#176'y_'
+ +#255#176'y_'#255#176'y_'#255#176'y_'#255#176'y_'#255#176'y_'#255#176'y_'#255
+ +#176'y_'#255#176'y_'#255#176'y_'#255#176'y_'#255#176'y_'#255#176'y_'#255#176
+ +'y_'#255#176'y_'#255#176'y_'#255#176'y_'#255#176'y_'#255#176'y_'#255'oL='#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255']@2'#255#176'y_'#255#176'y_'#255#176
+ +'y_'#255#176'y_'#255#176'y_'#255#176'y_'#255'Z=1'#255')'#28#22#255#26#18#14
+ +#255#14#10#8#255#10#7#5#255#23#16#12#255'+'#30#23#255'E0&'#255#138'_J'#255
+ +#176'y_'#255#176'y_'#255#176'y_'#255#176'y_'#255#176'y_'#255#176'y_'#255#176
+ +'y_'#255#176'y_'#255#176'y_'#255#176'y_'#255#176'y_'#255#176'y_'#255#176'y_'
+ +#255#176'y_'#255'#'#24#19#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#172'w]'#255#176'y_'#255#176'y_'#255
+ +#176'y_'#255#176'y_'#255#176'y_'#255#176'y_'#255#176'y_'#255#176'y_'#255#176
+ +'y_'#255#175'w^'#255#172'rW'#255#165'fI'#255#134'K2'#255']1'#30#255'[/'#27
+ +#255'H?:ZBBB'#27'+++'#6#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0'X/'#29'7[/'#27#255'^2'#31#255#141'P5'#255#167'hK'#255#174
+ +'sY'#255#177'x_'#255#177'za'#255#177'za'#255#177'za'#255#177'za'#255#177'za'
+ +#255#177'za'#255#177'za'#255#177'za'#255#177'za'#255#177'za'#255#177'za'#255
+ +#177'za'#255#177'za'#255#177'za'#255#177'za'#255#177'za'#255#177'za'#255#177
+ +'za'#255#177'za'#255#177'za'#255#177'za'#255#177'za'#255#177'za'#255#177'za'
+ +#255#177'za'#255#177'za'#255#9#6#5#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255'%'#25#20#255#177'za'#255#177'za'#255#177'za'#255#177'za'#255'bD6'#255#8
+ +#6#4#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255'>+"'#255#175'za'#255#177'za'#255#177'za'#255#177'za'
+ +#255#177'za'#255#177'za'#255#177'za'#255#177'za'#255#177'za'#255#177'za'#255
+ +#177'za'#255#177'za'#255#177'za'#255#136'^K'#255#0#0#0#255#0#0#0#255#0#0#0
+ ,#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#16#11#9#255#177'za'#255#177
+ +'za'#255#177'za'#255#177'za'#255#177'za'#255#177'za'#255#177'za'#255#177'za'
+ +#255#177'za'#255#177'za'#255#176'x^'#255#172'qV'#255#164'cF'#255'{E,'#255']1'
+ +#30#255'Z0'#29#245'DDD'#255
+ +'`5!'#255'\0'#28#255'T5'''#155'DDD'#30'III'#7#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'Z/'#28'w\0'#28#255
+ +'`5!'#255#157'\?'#255#172'pU'#255#179'}d'#255#181#129'i'#255#182#129'j'#255
+ +#182#129'j'#255#182#129'j'#255#182#129'j'#255#182#129'j'#255#182#129'j'#255
+ +#182#129'j'#255#182#129'j'#255#182#129'j'#255#182#129'j'#255#182#129'j'#255
+ +#182#129'j'#255#182#129'j'#255#182#129'j'#255#182#129'j'#255#182#129'j'#255
+ +#182#129'j'#255#182#129'j'#255#182#129'j'#255#182#129'j'#255#182#129'j'#255
+ +#182#129'j'#255#182#129'j'#255#182#129'j'#255'.!'#27#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#2#1#1#255#166'va'#255#182#129'j'#255#182#129'j'#255'A.&'
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#9#6#5#255#170'yd'#255#182#129'j'#255#182#129'j'#255#182#129'j'#255#182
+ +#129'j'#255#182#129'j'#255#182#129'j'#255#182#129'j'#255#182#129'j'#255#182
+ +#129'j'#255#182#129'j'#255#182#129'j'#255#8#6#5#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#135'`O'#255#182#129'j'#255#182#129'j'#255#182#129'j'#255
+ +#182#129'j'#255#182#129'j'#255#182#129'j'#255#182#129'j'#255#182#129'j'#255
+ +#182#129'j'#255#182#129'j'#255#181#128'h'#255#177'za'#255#169'kP'#255#139'Q7'
+ +#255'^3'#31#255'\0'#28#255'N9/\GGG'#18'UUU'#3#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'X.'#26'4\0'#28#255
+ ,'^3'#31#255#141'S8'#255#170'mQ'#255#179'|c'#255#182#130'k'#255#184#132'm'#255
+ +#184#132'm'#255#184#132'm'#255#184#132'm'#255#184#132'm'#255#184#132'm'#255
+ +#184#132'm'#255#184#132'm'#255#184#132'm'#255#184#132'm'#255#184#132'm'#255
+ +#184#132'm'#255#184#132'm'#255#184#132'm'#255#184#132'm'#255#184#132'm'#255
+ +#184#132'm'#255#184#132'm'#255#184#132'm'#255#184#132'm'#255#184#132'm'#255
+ +#184#132'm'#255#184#132'm'#255#184#132'm'#255#20#15#12#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255'N8.'#255#184#132'm'#255#184#132'm'#255#184#132'm'
+ +#255#22#16#13#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#21#15#13#255#182#130'm'#255#184#132'm'#255#184#132
+ +'m'#255#184#132'm'#255#184#132'm'#255#184#132'm'#255#184#132'm'#255#184#132
+ +'m'#255#184#132'm'#255#184#132'm'#255#184#132'm'#255'N8.'#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#23#17#13#255#184#132'm'#255#184#132'm'#255#184#132'm'#255
+ +#184#132'm'#255#184#132'm'#255#184#132'm'#255#184#132'm'#255#184#132'm'#255
+ +#184#132'm'#255#184#132'm'#255#183#131'l'#255#182#129'j'#255#177'x_'#255#167
+ +'hK'#255'zG/'#255']1'#30#255'Z0'#28#241'@@@(MMM'#10#0#0#0#1#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'='#31
+ +#18#3'[/'#27#238']1'#30#255'{G/'#255#167'hL'#255#177'za'#255#183#131'l'#255
+ +#185#134'p'#255#185#134'p'#255#185#134'p'#255#185#134'p'#255#185#134'p'#255
+ +#185#134'p'#255#185#134'p'#255#185#134'p'#255#185#134'p'#255#185#134'p'#255
+ +#185#134'p'#255#185#134'p'#255#185#134'p'#255#185#134'p'#255#185#134'p'#255
+ +#185#134'p'#255#185#134'p'#255#185#134'p'#255#185#134'p'#255#185#134'p'#255
+ +#185#134'p'#255#185#134'p'#255#185#134'p'#255#185#134'p'#255#26#19#16#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#12#9#7#255#185#134'p'#255#185#134'p'#255#185#134'p'
+ +#255#185#134'p'#255#3#2#2#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'U>4'#255#185#134'p'#255#185
+ +#134'p'#255#185#134'p'#255#185#134'p'#255#185#134'p'#255#185#134'p'#255#185
+ +#134'p'#255#185#134'p'#255#185#134'p'#255#185#134'p'#255#185#134'p'#255#25#18
+ +#15#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255'xWI'#255#185#134'p'#255#185#134'p'#255#185#134
+ +'p'#255#185#134'p'#255#185#134'p'#255#185#134'p'#255#185#134'p'#255#185#134
+ +'p'#255#185#134'p'#255#185#134'p'#255#184#134'o'#255#182#129'j'#255#175'v\'
+ +#255#165'dG'#255'h;&'#255'\1'#29#255'X2 '#193'==='#25'+++'#6#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0'[/'#27#170'\1'#29#255'f9%'#255#164'bG'#255#175'v]'#255#183#131
+ +'l'#255#186#135'r'#255#186#137's'#255#186#137's'#255#186#137's'#255#186#137
+ +'s'#255#186#137's'#255#186#137's'#255#186#137's'#255#186#137's'#255#186#137
+ +'s'#255#186#137's'#255#186#137's'#255#186#137's'#255#186#137's'#255#186#137
+ +'s'#255#186#137's'#255#186#137's'#255#186#137's'#255#186#137's'#255#186#137
+ +'s'#255#186#137's'#255#186#137's'#255#186#137's'#255#186#137's'#255'$'#27#23
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#129'_P'#255#186#137's'#255#186#137's'#255
+ +#186#137's'#255#186#137's'#255#1#1#1#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255' '#23#19#255#186
+ +#137's'#255#186#137's'#255#186#137's'#255#186#137's'#255#186#137's'#255#186
+ +#137's'#255#186#137's'#255#186#137's'#255#186#137's'#255#186#137's'#255#186
+ +#137's'#255#172#127'j'#255#7#5#4#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#12#9#7#255#186#137's'#255#186#137's'
+ +#255#186#137's'#255#186#137's'#255#186#137's'#255#186#137's'#255#186#137's'
+ +#255#186#137's'#255#186#137's'#255#186#137's'#255#186#137's'#255#185#135'q'
+ +#255#181#129'i'#255#173'qW'#255#149'X='#255'`5!'#255'\0'#28#255'V4%'#127'333'
+ +#15#0#0#0#3#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'Z/'#27'O\0'#28#255'_4 '#255#144'U:'
+ +#255#172'qV'#255#182#130'k'#255#187#137't'#255#188#139'u'#255#188#140'v'#255
+ +#188#140'v'#255#188#140'v'#255#188#140'v'#255#188#140'v'#255#188#140'v'#255
+ +#188#140'v'#255#188#140'v'#255#188#140'v'#255#188#140'v'#255#188#140'v'#255
+ ,#188#140'v'#255#188#140'v'#255#188#140'v'#255#188#140'v'#255#188#140'v'#255
+ +#188#140'v'#255#188#140'v'#255#188#140'v'#255#188#140'v'#255#188#140'v'#255
+ +#188#140'v'#255'1$'#31#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255':+$'#255#188#140'v'#255#188#140
+ +'v'#255#188#140'v'#255#188#140'v'#255#188#140'v'#255#1#1#1#255#0#0#0#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#4#3#3#255#188#140'v'#255#188#140'v'#255#188#140'v'#255#188#140'v'#255
+ +#188#140'v'#255#188#140'v'#255#188#140'v'#255#188#140'v'#255#188#140'v'#255
+ +#188#140'v'#255#188#140'v'#255#188#140'v'#255#188#140'v'#255'}]N'#255'6("'
+ +#255#14#11#9#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'S>5'#255
+ +#188#140'v'#255#188#140'v'#255#188#140'v'#255#188#140'v'#255#188#140'v'#255
+ +#188#140'v'#255#188#140'v'#255#188#140'v'#255#188#140'v'#255#188#140'v'#255
+ +#188#139'u'#255#186#136'r'#255#180'~f'#255#169'kP'#255'|H1'#255'^2'#31#255'['
+ +'/'#27#249'L=6+III'#7#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#5'[/'#27#235
+ +']1'#30#255'wD/'#255#169'jO'#255#180#127'g'#255#187#137'u'#255#189#141'x'#255
+ +#189#142'y'#255#189#142'y'#255#189#142'y'#255#189#142'y'#255#189#142'y'#255
+ +#189#142'y'#255#189#142'y'#255#189#142'y'#255#189#142'y'#255#189#142'y'#255
+ +#189#142'y'#255#189#142'y'#255#189#142'y'#255#189#142'y'#255#189#142'y'#255
+ +#189#142'y'#255#189#142'y'#255#189#142'y'#255#189#142'y'#255#189#142'y'#255
+ +#189#142'y'#255#189#142'y'#255'J7/'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#16#12#11#255#187#140'y'#255
+ +#189#142'y'#255#189#142'y'#255#189#142'y'#255#189#142'y'#255#189#142'y'#255#1
+ +#1#1#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#181#136'u'#255#189#142'y'#255#189#142
+ +'y'#255#189#142'y'#255#189#142'y'#255#189#142'y'#255#189#142'y'#255#189#142
+ +'y'#255#189#142'y'#255#189#142'y'#255#189#142'y'#255#189#142'y'#255#189#142
+ +'y'#255#189#142'y'#255#189#142'y'#255#189#142'y'#255#11#8#7#255#0#0#0#255#0#0
+ +#0#255#0#0#0#255#1#1#1#255#181#136's'#255#189#142'y'#255#189#142'y'#255#189
+ +#142'y'#255#189#142'y'#255#189#142'y'#255#189#142'y'#255#189#142'y'#255#189
+ +#142'y'#255#189#142'y'#255#189#142'y'#255#189#141'x'#255#186#136'q'#255#177
+ +'za'#255#164'dG'#255'f:&'#255'\1'#29#255'Y1'#31#186'@@@'#16'UUU'#3#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'Z/'#27#147'\1'#29#255'b8$'#255#160'bF'#255
+ +#177'y`'#255#186#137's'#255#190#143'z'#255#191#145'|'#255#191#145'|'#255#191
+ +#145'|'#255#191#145'|'#255#191#145'|'#255#191#145'|'#255#191#145'|'#255#191
+ +#145'|'#255#191#145'|'#255#191#145'|'#255#191#145'|'#255#191#145'|'#255#191
+ +#145'|'#255#191#145'|'#255#191#145'|'#255#191#145'|'#255#191#145'|'#255#191
+ +#145'|'#255#191#145'|'#255#191#145'|'#255#191#145'|'#255#191#145'|'#255#162
+ +'{i'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#1#1#1#255#162'{i'#255#191#145'|'#255#191#145'|'#255#191#145'|'#255
+ +#191#145'|'#255#191#145'|'#255#191#145'|'#255#2#1#1#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1
+ +#1#1#255#191#145'|'#255#191#145'|'#255#191#145'|'#255#191#145'|'#255#191#145
+ +'|'#255#191#145'|'#255#191#145'|'#255#191#145'|'#255#191#145'|'#255#191#145
+ +'|'#255#191#145'|'#255#191#145'|'#255#191#145'|'#255#191#145'|'#255#191#145
+ +'|'#255#191#145'|'#255#5#4#3#255#0#0#0#255#0#0#0#255#0#0#0#255'&'#29#25#255
+ +#191#145'|'#255#191#145'|'#255#191#145'|'#255#191#145'|'#255#191#145'|'#255
+ +#191#145'|'#255#191#145'|'#255#191#145'|'#255#191#145'|'#255#191#145'|'#255
+ +#191#145'|'#255#189#142'y'#255#184#134'o'#255#174'sY'#255#143'U;'#255'`5!'
+ +#255'\0'#28#255'U3$`@@@'#8#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0'Z.'#27'5\0'#28#255'_4 '#255#137'Q8'#255#173'rX'#255#184#134'o'#255#190#144
+ +'{'#255#192#147#127#255#192#147#127#255#192#147#127#255#192#147#127#255#192
+ +#147#127#255#192#147#127#255#192#147#127#255#192#147#127#255#192#147#127#255
+ +#192#147#127#255#192#147#127#255#192#147#127#255#192#147#127#255#192#147#127
+ +#255#192#147#127#255#192#147#127#255#192#147#127#255#192#147#127#255#192#147
+ +#127#255#192#147#127#255#192#147#127#255#192#147#127#255#192#147#127#255#14
+ ,#11#9#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255' '
+ +#24#21#255#192#147#127#255#192#147#127#255#192#147#127#255#192#147#127#255
+ +#192#147#127#255#192#147#127#255#192#147#127#255#4#3#3#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#8#6#5#255#192#147#127#255#192#147#127#255#192#147#127#255#192#147#127
+ +#255#192#147#127#255#192#147#127#255#192#147#127#255#192#147#127#255#192#147
+ +#127#255#192#147#127#255#192#147#127#255#192#147#127#255#192#147#127#255#192
+ +#147#127#255#192#147#127#255#192#147#127#255#1#1#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#137'iZ'#255#192#147#127#255#192#147#127#255#192#147#127#255#192#147
+ +#127#255#192#147#127#255#192#147#127#255#192#147#127#255#192#147#127#255#192
+ +#147#127#255#192#147#127#255#192#146'~'#255#189#142'y'#255#182#129'j'#255#169
+ +'lP'#255'uD.'#255'^2'#31#255'[/'#28#237'NFB'#21'UUU'#3#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#211']1'#30#255'l>)'#255#167'iM'
+ +#255#181#127'g'#255#190#143'z'#255#193#148#128#255#194#149#130#255#194#149
+ +#130#255#194#149#130#255#194#149#130#255#194#149#130#255#194#149#130#255#194
+ +#149#130#255#194#149#130#255#194#149#130#255#194#149#130#255#194#149#130#255
+ +#194#149#130#255#194#149#130#255#194#149#130#255#194#149#130#255#194#149#130
+ +#255#194#149#130#255#194#149#130#255#194#149#130#255#194#149#130#255#194#149
+ +#130#255#194#149#130#255'G60'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255'ZE<'#255#194#149#130#255#194#149#130#255#194#149#130#255
+ +#194#149#130#255#194#149#130#255#194#149#130#255#194#149#130#255#7#6#5#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#23#17#15#255#194#149#130#255#194#149#130#255#194#149#130
+ +#255#194#149#130#255#194#149#130#255#194#149#130#255#194#149#130#255#194#149
+ +#130#255#194#149#130#255#194#149#130#255#194#149#130#255#194#149#130#255#194
+ +#149#130#255#194#149#130#255#194#149#130#255#179#137'x'#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255'-#'#30#255#194#149#130#255#194#149#130#255#194#149#130#255#194
+ +#149#130#255#194#149#130#255#194#149#130#255#194#149#130#255#194#149#130#255
+ +#194#149#130#255#194#149#130#255#194#149#130#255#192#147#127#255#188#140'v'
+ +#255#177'za'#255#156'_D'#255'a6#'#255'\1'#29#255'Y1'#31#153'@@@'#8#0#0#0#1#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'Z/'#27']\0'#28#255
+ +'`5!'#255#143'V='#255#175'v]'#255#187#138'u'#255#193#149#129#255#195#152#132
+ +#255#195#152#133#255#195#152#133#255#195#152#133#255#195#152#133#255#195#152
+ +#133#255#195#152#133#255#195#152#133#255#195#152#133#255#195#152#133#255#195
+ +#152#133#255#195#152#133#255#195#152#133#255#195#152#133#255#195#152#133#255
+ +#195#152#133#255#195#152#133#255#195#152#133#255#195#152#133#255#195#152#133
+ +#255#195#152#133#255#195#152#133#255#170#133't'#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#172#133'u'#255#195#152#133#255#195#152
+ +#133#255#195#152#133#255#195#152#133#255#195#152#133#255#195#152#133#255#146
+ +'rd'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'_JA'#255#195#152#133#255#195#152#133
+ +#255#195#152#133#255#195#152#133#255#195#152#133#255#195#152#133#255#195#152
+ +#133#255#195#152#133#255#195#152#133#255#195#152#133#255#195#152#133#255#195
+ +#152#133#255#195#152#133#255#195#152#133#255#195#152#133#255#140'm`'#255#0#0
+ +#0#255#0#0#0#255#6#5#4#255#186#145#127#255#195#152#133#255#195#152#133#255
+ +#195#152#133#255#195#152#133#255#195#152#133#255#195#152#133#255#195#152#133
+ +#255#195#152#133#255#195#152#133#255#195#152#133#255#195#152#132#255#192#147
+ +#127#255#185#134'p'#255#172'pU'#255'|I2'#255'^3'#31#255'\0'#28#250'R5()UUU'#3
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#3
+ +'[/'#27#221']1'#30#255'oA,'#255#169'lP'#255#183#131'l'#255#192#147#127#255
+ +#196#154#135#255#197#155#136#255#197#155#136#255#197#155#136#255#197#155#136
+ +#255#197#155#136#255#197#155#136#255#197#155#136#255#197#155#136#255#197#155
+ +#136#255#197#155#136#255#197#155#136#255#197#155#136#255#197#155#136#255#197
+ +#155#136#255#197#155#136#255#197#155#136#255#197#155#136#255#197#155#136#255
+ +#197#155#136#255#197#155#136#255#197#155#136#255#197#155#136#255#26#20#18#255
+ ,#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#8#6#5#255#197#155#136#255#197
+ +#155#136#255#197#155#136#255#197#155#136#255#197#155#136#255#197#155#136#255
+ +#197#155#136#255#28#22#19#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#4#3#3#255#193#153#134#255
+ +#197#155#136#255#197#155#136#255#197#155#136#255#197#155#136#255#197#155#136
+ +#255#197#155#136#255#197#155#136#255#197#155#136#255#197#155#136#255#197#155
+ +#136#255#197#155#136#255#197#155#136#255#197#155#136#255#197#155#136#255#197
+ +#155#136#255#182#143'~'#255'=0*'#255#7#5#5#255#130'fY'#255#197#155#136#255
+ +#197#155#136#255#197#155#136#255#197#155#136#255#197#155#136#255#197#155#136
+ +#255#197#155#136#255#197#155#136#255#197#155#136#255#197#155#136#255#196#154
+ +#136#255#195#152#133#255#190#144'{'#255#180'~f'#255#159'bG'#255'c8%'#255'\1'
+ +#29#255'Z0'#30#163'III'#7#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27'g\0'#28#255'a6#'#255#147'Y@'#255#177
+ +'za'#255#190#143'z'#255#196#154#135#255#198#157#139#255#198#157#139#255#198
+ +#157#139#255#198#157#139#255#198#157#139#255#198#157#139#255#198#157#139#255
+ +#198#157#139#255#198#157#139#255#198#157#139#255#198#157#139#255#198#157#139
+ +#255#198#157#139#255#198#157#139#255#198#157#139#255#198#157#139#255#198#157
+ +#139#255#198#157#139#255#198#157#139#255#198#157#139#255#198#157#139#255#198
+ +#157#139#255'<0+'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'*!'#29#255
+ +#198#157#139#255#198#157#139#255#198#157#139#255#198#157#139#255#198#157#139
+ +#255#198#157#139#255#164#130's'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'?2,'#255#198
+ +#157#139#255#198#157#139#255#198#157#139#255#198#157#139#255#198#157#139#255
+ +#198#157#139#255#198#157#139#255#198#157#139#255#198#157#139#255#198#157#139
+ +#255#198#157#139#255#198#157#139#255#198#157#139#255#198#157#139#255#198#157
+ +#139#255#198#157#139#255#198#157#139#255#198#157#139#255#198#157#139#255#198
+ +#157#139#255#198#157#139#255#198#157#139#255#198#157#139#255#198#157#139#255
+ +#198#157#139#255#198#157#139#255#198#157#139#255#198#157#139#255#198#157#139
+ +#255#198#157#139#255#198#156#138#255#195#152#132#255#187#138't'#255#173'sY'
+ +#255#127'L5'#255'^3'#31#255'\0'#28#252'U3$,'#128#128#128#2#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#7
+ +'[/'#27#229'^2'#31#255'qB.'#255#171'nS'#255#185#134'p'#255#194#151#131#255
+ +#198#158#140#255#200#160#142#255#200#160#142#255#200#160#142#255#200#160#142
+ +#255#200#160#142#255#200#160#142#255#200#160#142#255#200#160#142#255#200#160
+ +#142#255#200#160#142#255#200#160#142#255#200#160#142#255#200#160#142#255#200
+ +#160#142#255#200#160#142#255#200#160#142#255#200#160#142#255#200#160#142#255
+ +#200#160#142#255#200#160#142#255#200#160#142#255'9.)'#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255'hSJ'#255#200#160#142#255#200#160#142#255#200#160#142
+ +#255#200#160#142#255#200#160#142#255#200#160#142#255'6+'''#255#0#0#0#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#6#5#5#255#184#148#131#255#200#160#142#255#200#160#142#255#200#160#142
+ +#255#200#160#142#255#200#160#142#255#200#160#142#255#200#160#142#255#200#160
+ +#142#255#200#160#142#255#200#160#142#255#200#160#142#255#200#160#142#255#200
+ +#160#142#255#200#160#142#255#200#160#142#255#200#160#142#255#200#160#142#255
+ +#200#160#142#255#200#160#142#255#200#160#142#255#200#160#142#255#200#160#142
+ +#255#200#160#142#255#200#160#142#255#200#160#142#255#200#160#142#255#200#160
+ +#142#255#200#160#142#255#200#160#142#255#199#159#141#255#198#157#139#255#192
+ +#147#127#255#181#127'g'#255#161'dI'#255'd:&'#255'\1'#29#255'Z0'#29#171'@@@'#4
+ +#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27'q\1'#29#255'a6#'#255#143'W?'#255#177'za'#255
+ +#191#144'|'#255#198#157#139#255#200#161#144#255#201#162#145#255#201#163#145
+ +#255#201#163#145#255#201#163#145#255#201#163#145#255#201#163#145#255#201#163
+ +#145#255#201#163#145#255#201#163#145#255#201#163#145#255#201#163#145#255#201
+ +#163#145#255#201#163#145#255#201#163#145#255#201#163#145#255#201#163#145#255
+ +#201#163#145#255#201#163#145#255#201#163#145#255#201#163#145#255'=2,'#255#0#0
+ ,#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255'!'#27#24#255#197#161#143#255#201#163#145#255
+ +#201#163#145#255#201#163#145#255#201#163#145#255#201#163#145#255#197#161#143
+ +#255#3#2#2#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#1#1#1#255#149'zl'#255#201#163#145#255#201#163#145
+ +#255#201#163#145#255#201#163#145#255#201#163#145#255#201#163#145#255#201#163
+ +#145#255#201#163#145#255#201#163#145#255#201#163#145#255#201#163#145#255#201
+ +#163#145#255#201#163#145#255#201#163#145#255#201#163#145#255#201#163#145#255
+ +#201#163#145#255#201#163#145#255#201#163#145#255#201#163#145#255#201#163#145
+ +#255#201#163#145#255#201#163#145#255#201#163#145#255#201#163#145#255#201#163
+ +#145#255#201#163#145#255#201#163#145#255#201#163#145#255#201#162#145#255#200
+ +#161#143#255#197#155#136#255#187#138'u'#255#173'rX'#255'|I3'#255'_4 '#255'\0'
+ +#28#253'W1 2'#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#6'\0'#28#216'^2'#31#255
+ +'i=)'#255#165'jP'#255#184#133'n'#255#196#152#134#255#201#162#145#255#202#164
+ +#148#255#202#165#148#255#202#165#148#255#202#165#148#255#202#165#148#255#202
+ +#165#148#255#202#165#148#255#202#165#148#255#202#165#148#255#202#165#148#255
+ +#202#165#148#255#202#165#148#255#202#165#148#255#202#165#148#255#202#165#148
+ +#255#202#165#148#255#202#165#148#255#202#165#148#255#202#165#148#255#202#165
+ +#148#255'E82'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#2#2#2#255#1#1#1#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'.&"'#255#202#165#148#255#202#165#148
+ +#255#202#165#148#255#202#165#148#255#202#165#148#255#202#165#148#255#202#165
+ +#148#255#146'wk'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'eRI'#255#202#165#148#255#202#165#148
+ +#255#202#165#148#255#202#165#148#255#202#165#148#255#202#165#148#255#202#165
+ +#148#255#202#165#148#255#202#165#148#255#202#165#148#255#202#165#148#255#202
+ +#165#148#255#202#165#148#255#202#165#148#255#202#165#148#255#202#165#148#255
+ +#202#165#148#255#202#165#148#255#202#165#148#255#202#165#148#255#202#165#148
+ +#255#202#165#148#255#202#165#148#255#202#165#148#255#202#165#148#255#202#165
+ +#148#255#202#165#148#255#202#165#148#255#202#165#148#255#202#165#148#255#202
+ +#164#147#255#200#160#143#255#193#148#128#255#180'~f'#255#151'^D'#255'a7$'#255
+ +'\1'#29#255'Z0'#28#156'UUU'#3#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27
+ +'D\0'#28#255'`5!'#255#128'N8'#255#175'v]'#255#190#143'{'#255#200#159#142#255
+ +#203#165#150#255#204#167#151#255#204#167#151#255#204#167#151#255#204#167#151
+ +#255#204#167#151#255#204#167#151#255#204#167#151#255#204#167#151#255#204#167
+ +#151#255#204#167#151#255#204#167#151#255#204#167#151#255#204#167#151#255#204
+ +#167#151#255#204#167#151#255#204#167#151#255#204#167#151#255#204#167#151#255
+ +#204#167#151#255'N?9'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'vaW'#255
+ +#204#167#151#255#160#131'w'#255'cRI'#255'WG@'#255#168#137'|'#255#204#167#151
+ +#255#204#167#151#255#204#167#151#255#204#167#151#255#204#167#151#255#204#167
+ +#151#255#204#167#151#255#204#167#151#255#145'wk'#255#0#0#0#255#0#0#0#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'G:4'#255#204#167
+ +#151#255#204#167#151#255#204#167#151#255#204#167#151#255#204#167#151#255#204
+ +#167#151#255#204#167#151#255#204#167#151#255#204#167#151#255#204#167#151#255
+ +#204#167#151#255#204#167#151#255#204#167#151#255#204#167#151#255#204#167#151
+ +#255#204#167#151#255#204#167#151#255#204#167#151#255#204#167#151#255#204#167
+ +#151#255#204#167#151#255#204#167#151#255#204#167#151#255#204#167#151#255#204
+ +#167#151#255#204#167#151#255#204#167#151#255#204#167#151#255#204#167#151#255
+ +#204#167#151#255#204#167#150#255#202#165#148#255#198#155#138#255#186#137's'
+ +#255#171'nU'#255'oB.'#255'^2'#31#255'\0'#28#235'V2"'#21#0#0#0#1#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#169'\1'#29#255'c9&'#255#155'aH'#255
+ +#182#128'j'#255#195#152#133#255#202#164#148#255#205#169#154#255#206#169#155
+ +#255#206#169#155#255#206#169#155#255#206#169#155#255#206#169#155#255#206#169
+ +#155#255#206#169#155#255#206#169#155#255#206#169#155#255#206#169#155#255#206
+ +#169#155#255#206#169#155#255#206#169#155#255#206#169#155#255#206#169#155#255
+ +#206#169#155#255#206#169#155#255#206#169#155#255'VGA'#255#0#0#0#255#0#0#0#255
+ ,#0#0#0#255#5#4#4#255#206#169#155#255#206#169#155#255#206#169#155#255#206#169
+ +#155#255#206#169#155#255#206#169#155#255#206#169#155#255#206#169#155#255#206
+ +#169#155#255#206#169#155#255#206#169#155#255#206#169#155#255#206#169#155#255
+ +#206#169#155#255#152'}r'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#2#1#1#255'vaY'#255#206#169#155#255#206#169#155#255#206#169
+ +#155#255#206#169#155#255#206#169#155#255#206#169#155#255#206#169#155#255#206
+ +#169#155#255#206#169#155#255#206#169#155#255#206#169#155#255#206#169#155#255
+ +#206#169#155#255#206#169#155#255#206#169#155#255#206#169#155#255#206#169#155
+ +#255#206#169#155#255#206#169#155#255#206#169#155#255#206#169#155#255#206#169
+ +#155#255#206#169#155#255#206#169#155#255#206#169#155#255#206#169#155#255#206
+ +#169#155#255#206#169#155#255#206#169#155#255#206#169#155#255#206#169#155#255
+ +#205#167#152#255#201#162#145#255#192#147#127#255#177'za'#255#138'T='#255'`6"'
+ +#255'\1'#29#255'[0'#29'e'#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0'[/'#27#27'\0'#28#243'^3'#31#255'pC/'#255#171'oU'#255#188#138'u'
+ +#255#199#158#141#255#205#169#154#255#207#171#157#255#207#172#158#255#207#172
+ +#158#255#207#172#158#255#207#172#158#255#207#172#158#255#207#172#158#255#207
+ +#172#158#255#207#172#158#255#207#172#158#255#207#172#158#255#207#172#158#255
+ +#207#172#158#255#207#172#158#255#207#172#158#255#207#172#158#255#207#172#158
+ +#255#207#172#158#255'~i`'#255#0#0#0#255#0#0#0#255#0#0#0#255#22#18#16#255#207
+ +#172#158#255#207#172#158#255#207#172#158#255#207#172#158#255#207#172#158#255
+ +#207#172#158#255#207#172#158#255#207#172#158#255#207#172#158#255#207#172#158
+ +#255#207#172#158#255#207#172#158#255#207#172#158#255#207#172#158#255#207#172
+ +#158#255'/''$'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#9#7#7#255
+ +#164#136'~'#255#207#172#158#255#207#172#158#255#207#172#158#255#207#172#158
+ +#255#207#172#158#255#207#172#158#255#207#172#158#255#207#172#158#255#207#172
+ +#158#255#207#172#158#255#207#172#158#255#207#172#158#255#207#172#158#255#207
+ +#172#158#255#207#172#158#255#207#172#158#255#207#172#158#255#207#172#158#255
+ +#207#172#158#255#207#172#158#255#207#172#158#255#207#172#158#255#207#172#158
+ +#255#207#172#158#255#207#172#158#255#207#172#158#255#207#172#158#255#207#172
+ +#158#255#207#172#158#255#207#172#158#255#207#172#158#255#207#171#157#255#204
+ +#167#151#255#196#153#136#255#183#131'l'#255#160'fK'#255'f;('#255']1'#30#255
+ +'[/'#27#199'te^'#3#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0'[/'#27'q\0'#28#255'`6"'#255#130'P9'#255#177'x`'#255#192#146
+ +#127#255#203#164#149#255#208#173#159#255#209#175#161#255#209#175#161#255#209
+ +#175#161#255#209#175#161#255#209#175#161#255#209#175#161#255#209#175#161#255
+ +#209#175#161#255#209#175#161#255#209#175#161#255#209#175#161#255#209#175#161
+ +#255#209#175#161#255#209#175#161#255#209#175#161#255#209#175#161#255#209#175
+ +#161#255#199#167#153#255#0#0#0#255#0#0#0#255#0#0#0#255'.'#255#209#175#161
+ +#255#209#175#161#255#209#175#161#255#209#175#161#255#209#175#161#255#209#175
+ +#161#255#209#175#161#255#209#175#161#255#209#175#161#255#209#175#161#255#209
+ +#175#161#255#209#175#161#255#209#175#161#255#209#175#161#255#209#175#161#255
+ +#209#175#161#255'*$!'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'"'#28#26#255#197#165#153#255
+ +#209#175#161#255#209#175#161#255#209#175#161#255#209#175#161#255#209#175#161
+ +#255#209#175#161#255#209#175#161#255#209#175#161#255#209#175#161#255#209#175
+ +#161#255#209#175#161#255#209#175#161#255#209#175#161#255#209#175#161#255#209
+ +#175#161#255#209#175#161#255#209#175#161#255#209#175#161#255#209#175#161#255
+ +#209#175#161#255#209#175#161#255#209#175#161#255#209#175#161#255#209#175#161
+ +#255#209#175#161#255#209#175#161#255#209#175#161#255#209#175#161#255#209#175
+ +#161#255#209#175#161#255#209#175#161#255#209#174#160#255#207#171#157#255#200
+ +#160#144#255#188#139'w'#255#171'pV'#255'rD0'#255'^3'#31#255'\0'#28#250'\2'#30
+ +'1'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0'[/'#27#1'[/'#27#184']1'#30#255'c9&'#255#148'^E'#255#182#128'j'#255#197
+ +#154#136#255#206#170#155#255#210#176#163#255#211#178#164#255#211#178#165#255
+ +#211#178#165#255#211#178#165#255#211#178#165#255#211#178#165#255#211#178#165
+ +#255#211#178#165#255#211#178#165#255#211#178#165#255#211#178#165#255#211#178
+ ,#165#255#211#178#165#255#211#178#165#255#211#178#165#255#211#178#165#255#211
+ +#178#165#255#12#10#9#255#0#0#0#255#0#0#0#255'MA<'#255#211#178#165#255#211#178
+ +#165#255#211#178#165#255#211#178#165#255#211#178#165#255#211#178#165#255#211
+ +#178#165#255#211#178#165#255#211#178#165#255#211#178#165#255#211#178#165#255
+ +#211#178#165#255#211#178#165#255#211#178#165#255#211#178#165#255#211#178#165
+ +#255#211#178#165#255#178#150#139#255'D95'#255#9#7#7#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'VIC'#255#211#178#165#255#211#178#165
+ +#255#211#178#165#255#211#178#165#255#211#178#165#255#211#178#165#255#211#178
+ +#165#255#211#178#165#255#211#178#165#255#211#178#165#255#211#178#165#255#211
+ +#178#165#255#211#178#165#255#211#178#165#255#211#178#165#255#211#178#165#255
+ +#211#178#165#255#211#178#165#255#211#178#165#255#211#178#165#255#211#178#165
+ +#255#211#178#165#255#211#178#165#255#211#178#165#255#211#178#165#255#211#178
+ +#165#255#211#178#165#255#211#178#165#255#211#178#165#255#211#178#165#255#211
+ +#178#165#255#211#178#165#255#211#178#164#255#209#176#162#255#204#167#151#255
+ +#193#148#129#255#177'x`'#255#129'P9'#255'`6"'#255'\0'#28#255'[0'#28't'#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0'[/'#27#21'\0'#28#229'^2'#31#255'i?+'#255#163'jP'#255#186#136
+ +'s'#255#200#160#144#255#209#174#160#255#212#180#167#255#213#181#169#255#213
+ +#181#169#255#213#181#169#255#213#181#169#255#213#181#169#255#213#181#169#255
+ +#213#181#169#255#213#181#169#255#213#181#169#255#213#181#169#255#213#181#169
+ +#255#213#181#169#255#213#181#169#255#213#181#169#255#213#181#169#255#213#181
+ +#169#255'.''%'#255#0#0#0#255',%#'#255#200#170#159#255#213#181#169#255#213#181
+ +#169#255#213#181#169#255#213#181#169#255#213#181#169#255#213#181#169#255#213
+ +#181#169#255#213#181#169#255#213#181#169#255#213#181#169#255#213#181#169#255
+ +#213#181#169#255#213#181#169#255#213#181#169#255#213#181#169#255#213#181#169
+ +#255#213#181#169#255#213#181#169#255#213#181#169#255#139'vo'#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'.''$'#255#213#181#169#255#213#181#169
+ +#255#213#181#169#255#213#181#169#255#213#181#169#255#213#181#169#255#213#181
+ +#169#255#213#181#169#255#213#181#169#255#213#181#169#255#213#181#169#255#213
+ +#181#169#255#213#181#169#255#213#181#169#255#213#181#169#255#213#181#169#255
+ +#213#181#169#255#213#181#169#255#213#181#169#255#213#181#169#255#213#181#169
+ +#255#213#181#169#255#213#181#169#255#213#181#169#255#213#181#169#255#213#181
+ +#169#255#213#181#169#255#213#181#169#255#213#181#169#255#213#181#169#255#213
+ +#181#169#255#213#181#169#255#212#180#168#255#211#178#165#255#207#171#157#255
+ +#197#155#137#255#182#128'j'#255#148']E'#255'c9&'#255']1'#30#255'[/'#27#179#0
+ +#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27'?\0'#28#252'_4 '#255'tF1'#255#172
+ +'sY'#255#190#142'z'#255#203#165#150#255#211#178#164#255#213#183#170#255#214
+ +#184#172#255#214#184#172#255#214#184#172#255#214#184#172#255#214#184#172#255
+ +#214#184#172#255#214#184#172#255#214#184#172#255#214#184#172#255#214#184#172
+ +#255#214#184#172#255#214#184#172#255#214#184#172#255#214#184#172#255#214#184
+ +#172#255#127'ng'#255'{ib'#255#214#184#172#255#214#184#172#255#214#184#172#255
+ +#214#184#172#255#214#184#172#255#214#184#172#255#214#184#172#255#214#184#172
+ +#255#214#184#172#255#214#184#172#255#214#184#172#255#214#184#172#255#214#184
+ +#172#255#214#184#172#255#214#184#172#255#214#184#172#255#214#184#172#255#214
+ +#184#172#255#214#184#172#255#214#184#172#255#214#184#172#255' '#28#26#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#14#12#11#255#209#180#168#255#214#184#172
+ +#255#214#184#172#255#214#184#172#255#214#184#172#255#214#184#172#255#214#184
+ +#172#255#214#184#172#255#214#184#172#255#214#184#172#255#214#184#172#255#214
+ +#184#172#255#214#184#172#255#214#184#172#255#214#184#172#255#214#184#172#255
+ +#214#184#172#255#214#184#172#255#214#184#172#255#214#184#172#255#214#184#172
+ +#255#214#184#172#255#214#184#172#255#214#184#172#255#214#184#172#255#214#184
+ +#172#255#214#184#172#255#214#184#172#255#214#184#172#255#214#184#172#255#214
+ +#184#172#255#214#184#172#255#214#184#172#255#213#182#169#255#209#176#161#255
+ +#200#161#143#255#186#135'q'#255#161'gO'#255'h=*'#255'^2'#31#255'\0'#28#226'W'
+ +'-'#26#19#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27'}\1'#29#255'`6"'
+ +#255'|M8'#255#175'x^'#255#192#147#127#255#205#170#154#255#213#181#169#255#215
+ ,#185#173#255#216#187#175#255#216#187#175#255#216#187#175#255#216#187#175#255
+ +#216#187#175#255#216#187#175#255#216#187#175#255#216#187#175#255#216#187#175
+ +#255#216#187#175#255#216#187#175#255#216#187#175#255#216#187#175#255#216#187
+ +#175#255#216#187#175#255#216#187#175#255#216#187#175#255#216#187#175#255#216
+ +#187#175#255#216#187#175#255#216#187#175#255#216#187#175#255#216#187#175#255
+ +#216#187#175#255#216#187#175#255#216#187#175#255#216#187#175#255#216#187#175
+ +#255#216#187#175#255#216#187#175#255#216#187#175#255#216#187#175#255#216#187
+ +#175#255#216#187#175#255#216#187#175#255#216#187#175#255#187#162#151#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#2#2#2#255#180#156#146#255#216#187#175
+ +#255#216#187#175#255#216#187#175#255#216#187#175#255#216#187#175#255#216#187
+ +#175#255#216#187#175#255#216#187#175#255#216#187#175#255#216#187#175#255#216
+ +#187#175#255#216#187#175#255#216#187#175#255#216#187#175#255#216#187#175#255
+ +#216#187#175#255#216#187#175#255#216#187#175#255#216#187#175#255#216#187#175
+ +#255#216#187#175#255#216#187#175#255#216#187#175#255#216#187#175#255#216#187
+ +#175#255#216#187#175#255#216#187#175#255#216#187#175#255#216#187#175#255#216
+ +#187#175#255#216#187#175#255#216#187#175#255#215#185#173#255#211#179#166#255
+ +#202#165#148#255#188#139'w'#255#167'mU'#255'nC/'#255'^3'#31#255'\0'#28#251'Z'
+ +'.'#27';'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#2'[/'#27
+ +#170'\1'#29#255'a7$'#255#130'Q<'#255#178'{c'#255#195#151#132#255#208#173#159
+ +#255#215#185#173#255#217#189#178#255#217#189#178#255#217#189#178#255#217#189
+ +#178#255#217#189#178#255#217#189#178#255#217#189#178#255#217#189#178#255#217
+ +#189#178#255#217#189#178#255#217#189#178#255#217#189#178#255#217#189#178#255
+ +#217#189#178#255#217#189#178#255#217#189#178#255#217#189#178#255#217#189#178
+ +#255#217#189#178#255#217#189#178#255#217#189#178#255#217#189#178#255#217#189
+ +#178#255#217#189#178#255#217#189#178#255#217#189#178#255#217#189#178#255#217
+ +#189#178#255#217#189#178#255#217#189#178#255#217#189#178#255#217#189#178#255
+ +#217#189#178#255#217#189#178#255#217#189#178#255#217#189#178#255'.(&'#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#128'oi'#255#217#189#178#255#217#189#178
+ +#255#217#189#178#255#217#189#178#255#217#189#178#255#217#189#178#255#217#189
+ +#178#255#217#189#178#255#217#189#178#255#217#189#178#255#217#189#178#255#217
+ +#189#178#255#217#189#178#255#217#189#178#255#217#189#178#255#217#189#178#255
+ +#217#189#178#255#217#189#178#255#217#189#178#255#217#189#178#255#217#189#178
+ +#255#217#189#178#255#217#189#178#255#217#189#178#255#217#189#178#255#217#189
+ +#178#255#217#189#178#255#217#189#178#255#217#189#178#255#217#189#178#255#217
+ +#189#178#255#217#189#178#255#217#188#177#255#213#183#170#255#205#168#153#255
+ +#191#144'|'#255#170'rZ'#255'sF2'#255'`5!'#255'\0'#28#255'Z/'#27'g'#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#6'[/'#27
+ +#188']1'#30#255'c9&'#255#136'V?'#255#180'~g'#255#197#154#136#255#209#176#162
+ +#255#216#187#176#255#219#192#181#255#219#192#182#255#219#193#183#255#219#193
+ +#183#255#219#193#183#255#219#193#183#255#219#193#183#255#219#193#183#255#219
+ +#193#183#255#219#193#183#255#219#193#183#255#219#193#183#255#219#193#183#255
+ +#219#193#183#255#219#193#183#255#219#193#183#255#219#193#183#255#219#193#183
+ +#255#219#193#183#255#219#193#183#255#219#193#183#255#219#193#183#255#219#193
+ +#183#255#219#193#183#255#219#193#183#255#219#193#183#255#219#193#183#255#219
+ +#193#183#255#219#193#183#255#219#193#183#255#219#193#183#255#219#193#183#255
+ +#219#193#183#255#219#193#183#255#158#138#131#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#1#1#1#255#131'sm'#255#219#193#183#255#219#193#183#255#219#193#183#255
+ +#219#193#183#255#219#193#183#255#219#193#183#255#219#193#183#255#219#193#183
+ +#255#219#193#183#255#219#193#183#255#219#193#183#255#219#193#183#255#219#193
+ +#183#255#219#193#183#255#219#193#183#255#219#193#183#255#219#193#183#255#219
+ +#193#183#255#219#193#183#255#219#193#183#255#219#193#183#255#219#193#183#255
+ +#219#193#183#255#219#193#183#255#219#193#183#255#219#193#183#255#219#193#183
+ +#255#219#193#183#255#219#193#183#255#219#193#183#255#219#193#183#255#219#192
+ +#182#255#218#191#180#255#215#185#173#255#207#172#156#255#193#147#128#255#174
+ +'v^'#255'wJ6'#255'`6"'#255'\1'#29#255'[/'#27'~'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ ,#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#12'[/'#27#203
+ +']1'#30#255'c:'''#255#141'YC'#255#181#128'h'#255#198#155#138#255#210#177#164
+ +#255#217#190#178#255#220#194#184#255#221#195#185#255#221#196#186#255#221#196
+ +#186#255#221#196#186#255#221#196#186#255#221#196#186#255#221#196#186#255#221
+ +#196#186#255#221#196#186#255#221#196#186#255#221#196#186#255#221#196#186#255
+ +#221#196#186#255#221#196#186#255#221#196#186#255#221#196#186#255#221#196#186
+ +#255#221#196#186#255#221#196#186#255#221#196#186#255#221#196#186#255#221#196
+ +#186#255#221#196#186#255#221#196#186#255#221#196#186#255#221#196#186#255#221
+ +#196#186#255#221#196#186#255#221#196#186#255#221#196#186#255#221#196#186#255
+ +#221#196#186#255're_'#255#0#0#0#255#0#0#0#255#4#4#4#255#160#142#134#255#221
+ +#196#186#255#221#196#186#255#221#196#186#255#221#196#186#255#221#196#186#255
+ +#221#196#186#255#221#196#186#255#221#196#186#255#221#196#186#255#221#196#186
+ +#255#221#196#186#255#221#196#186#255#221#196#186#255#221#196#186#255#221#196
+ +#186#255#221#196#186#255#221#196#186#255#221#196#186#255#221#196#186#255#221
+ +#196#186#255#221#196#186#255#221#196#186#255#221#196#186#255#221#196#186#255
+ +#221#196#186#255#221#196#186#255#221#196#186#255#221#196#186#255#221#196#186
+ +#255#221#196#186#255#221#196#186#255#221#195#185#255#219#193#183#255#216#187
+ +#175#255#207#172#158#255#194#148#130#255#176'x_'#255'{M8'#255'a6#'#255'\1'#29
+ +#255'[/'#27#148#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#21'\0'#28#217']1'#30#255'c:'''
+ +#255#138'XB'#255#181#127'h'#255#197#156#137#255#211#178#164#255#218#191#180
+ +#255#221#196#187#255#222#198#188#255#223#198#189#255#223#198#189#255#223#198
+ +#189#255#223#198#189#255#223#198#189#255#223#198#189#255#223#198#189#255#223
+ +#198#189#255#223#198#189#255#223#198#189#255#223#198#189#255#223#198#189#255
+ +#223#198#189#255#223#198#189#255#223#198#189#255#223#198#189#255#223#198#189
+ +#255#223#198#189#255#223#198#189#255#223#198#189#255#223#198#189#255#223#198
+ +#189#255#223#198#189#255#223#198#189#255#223#198#189#255#223#198#189#255#223
+ +#198#189#255#223#198#189#255#223#198#189#255#223#198#189#255#221#196#187#255
+ +#6#6#5#255#10#9#8#255#188#167#159#255#223#198#189#255#223#198#189#255#223#198
+ +#189#255#223#198#189#255#223#198#189#255#223#198#189#255#223#198#189#255#223
+ +#198#189#255#223#198#189#255#223#198#189#255#223#198#189#255#223#198#189#255
+ +#223#198#189#255#223#198#189#255#223#198#189#255#223#198#189#255#223#198#189
+ +#255#223#198#189#255#223#198#189#255#223#198#189#255#223#198#189#255#223#198
+ +#189#255#223#198#189#255#223#198#189#255#223#198#189#255#223#198#189#255#223
+ +#198#189#255#223#198#189#255#223#198#189#255#223#198#189#255#223#198#189#255
+ +#222#198#188#255#221#196#186#255#217#188#177#255#208#173#159#255#193#149#129
+ +#255#174'w^'#255'zM8'#255'a7$'#255'\1'#29#255'[/'#27#170'[/'#27#2#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0'[/'#27' \0'#28#223']1'#30#255'c:'''#255#132'T?'#255#180
+ +'~g'#255#197#155#136#255#211#178#164#255#219#193#181#255#223#198#189#255#224
+ +#201#192#255#224#201#192#255#224#201#192#255#224#201#192#255#224#201#192#255
+ +#224#201#192#255#224#201#192#255#224#201#192#255#224#201#192#255#224#201#192
+ +#255#224#201#192#255#224#201#192#255#224#201#192#255#224#201#192#255#224#201
+ +#192#255#224#201#192#255#224#201#192#255#224#201#192#255#224#201#192#255#224
+ +#201#192#255#224#201#192#255#224#201#192#255#224#201#192#255#224#201#192#255
+ +#224#201#192#255#224#201#192#255#224#201#192#255#224#201#192#255#224#201#192
+ +#255#224#201#192#255#224#201#192#255#134'xr'#255#205#184#176#255#224#201#192
+ +#255#224#201#192#255#224#201#192#255#224#201#192#255#224#201#192#255#224#201
+ +#192#255#224#201#192#255#224#201#192#255#224#201#192#255#224#201#192#255#224
+ +#201#192#255#224#201#192#255#224#201#192#255#224#201#192#255#224#201#192#255
+ +#224#201#192#255#224#201#192#255#224#201#192#255#224#201#192#255#224#201#192
+ +#255#224#201#192#255#224#201#192#255#224#201#192#255#224#201#192#255#224#201
+ +#192#255#224#201#192#255#224#201#192#255#224#201#192#255#224#201#192#255#224
+ +#201#192#255#224#201#192#255#223#200#191#255#222#197#187#255#217#189#178#255
+ +#207#172#158#255#192#147#127#255#171'u\'#255'vI6'#255'a6#'#255'\1'#29#255'[/'
+ +#27#179'[/'#27#6#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ ,#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#25'\'
+ +'0'#28#209']1'#30#255'c9&'#255#128'Q='#255#177'{c'#255#195#151#133#255#209
+ +#176#162#255#219#192#181#255#223#200#191#255#225#203#194#255#226#204#196#255
+ +#226#204#196#255#226#204#196#255#226#204#196#255#226#204#196#255#226#204#196
+ +#255#226#204#196#255#226#204#196#255#226#204#196#255#226#204#196#255#226#204
+ +#196#255#226#204#196#255#226#204#196#255#226#204#196#255#226#204#196#255#226
+ +#204#196#255#226#204#196#255#226#204#196#255#226#204#196#255#226#204#196#255
+ +#226#204#196#255#226#204#196#255#226#204#196#255#226#204#196#255#226#204#196
+ +#255#226#204#196#255#226#204#196#255#226#204#196#255#226#204#196#255#226#204
+ +#196#255#226#204#196#255#226#204#196#255#226#204#196#255#226#204#196#255#226
+ +#204#196#255#226#204#196#255#226#204#196#255#226#204#196#255#226#204#196#255
+ +#226#204#196#255#226#204#196#255#226#204#196#255#226#204#196#255#226#204#196
+ +#255#226#204#196#255#226#204#196#255#226#204#196#255#226#204#196#255#226#204
+ +#196#255#226#204#196#255#226#204#196#255#226#204#196#255#226#204#196#255#226
+ +#204#196#255#226#204#196#255#226#204#196#255#226#204#196#255#226#204#196#255
+ +#226#204#196#255#226#204#196#255#226#203#195#255#225#202#193#255#222#198#188
+ +#255#217#188#177#255#206#169#155#255#191#144'|'#255#168'qY'#255'rG3'#255'`6"'
+ +#255'\1'#29#255'[/'#27#159'[/'#27#4#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0'[/'#27#15'\0'#28#193']1'#30#255'b8%'#255'yM8'#255#170
+ +'u\'#255#192#146'~'#255#207#171#156#255#217#189#178#255#223#200#191#255#226
+ +#205#197#255#227#206#198#255#228#207#199#255#228#207#199#255#228#207#199#255
+ +#228#207#199#255#228#207#199#255#228#207#199#255#228#207#199#255#228#207#199
+ +#255#228#207#199#255#228#207#199#255#228#207#199#255#228#207#199#255#228#207
+ +#199#255#228#207#199#255#228#207#199#255#228#207#199#255#228#207#199#255#228
+ +#207#199#255#228#207#199#255#228#207#199#255#228#207#199#255#228#207#199#255
+ +#228#207#199#255#228#207#199#255#228#207#199#255#228#207#199#255#228#207#199
+ +#255#228#207#199#255#228#207#199#255#228#207#199#255#228#207#199#255#228#207
+ +#199#255#228#207#199#255#228#207#199#255#228#207#199#255#228#207#199#255#228
+ +#207#199#255#228#207#199#255#228#207#199#255#228#207#199#255#228#207#199#255
+ +#228#207#199#255#228#207#199#255#228#207#199#255#228#207#199#255#228#207#199
+ +#255#228#207#199#255#228#207#199#255#228#207#199#255#228#207#199#255#228#207
+ +#199#255#228#207#199#255#228#207#199#255#228#207#199#255#228#207#199#255#228
+ +#207#199#255#228#207#199#255#227#206#198#255#226#204#196#255#222#198#188#255
+ +#215#185#173#255#202#165#148#255#187#137'u'#255#159'jR'#255'nD0'#255'`6"'#255
+ +'\1'#29#255'[/'#27#137#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#8'[/'#27#175'\1'#29#255'`6"'#255'n'
+ +'D0'#255#158'iR'#255#187#137'u'#255#202#165#148#255#215#186#174#255#223#199
+ +#190#255#227#205#198#255#229#208#201#255#229#209#202#255#229#210#202#255#229
+ +#210#202#255#229#210#202#255#229#210#202#255#229#210#202#255#229#210#202#255
+ +#229#210#202#255#229#210#202#255#229#210#202#255#229#210#202#255#229#210#202
+ +#255#229#210#202#255#229#210#202#255#229#210#202#255#229#210#202#255#229#210
+ +#202#255#229#210#202#255#229#210#202#255#229#210#202#255#229#210#202#255#229
+ +#210#202#255#229#210#202#255#229#210#202#255#229#210#202#255#229#210#202#255
+ +#229#210#202#255#229#210#202#255#229#210#202#255#229#210#202#255#229#210#202
+ +#255#229#210#202#255#229#210#202#255#229#210#202#255#229#210#202#255#229#210
+ +#202#255#229#210#202#255#229#210#202#255#229#210#202#255#229#210#202#255#229
+ +#210#202#255#229#210#202#255#229#210#202#255#229#210#202#255#229#210#202#255
+ +#229#210#202#255#229#210#202#255#229#210#202#255#229#210#202#255#229#210#202
+ +#255#229#210#202#255#229#210#202#255#229#210#202#255#229#210#202#255#229#209
+ +#202#255#228#207#201#255#226#204#197#255#221#196#187#255#212#180#168#255#198
+ +#157#140#255#183#130'l'#255#143'^G'#255'g>+'#255'_4 '#255'\1'#29#254'[/'#27
+ +'q'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ ,#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#3'[/'#27#132'\1'#29#254'_4 '#255'g>+'
+ +#255#140'[F'#255#181#129'j'#255#198#155#138#255#211#178#165#255#221#195#185
+ +#255#227#204#197#255#230#209#203#255#230#212#205#255#231#212#206#255#231#212
+ +#206#255#231#212#206#255#231#212#206#255#231#212#206#255#231#212#206#255#231
+ +#212#206#255#231#212#206#255#231#212#206#255#231#212#206#255#231#212#206#255
+ +#231#212#206#255#231#212#206#255#231#212#206#255#231#212#206#255#231#212#206
+ +#255#231#212#206#255#231#212#206#255#231#212#206#255#231#212#206#255#231#212
+ +#206#255#231#212#206#255#231#212#206#255#231#212#206#255#231#212#206#255#231
+ +#212#206#255#231#212#206#255#231#212#206#255#231#212#206#255#231#212#206#255
+ +#231#212#206#255#231#212#206#255#231#212#206#255#231#212#206#255#231#212#206
+ +#255#231#212#206#255#231#212#206#255#231#212#206#255#231#212#206#255#231#212
+ +#206#255#231#212#206#255#231#212#206#255#231#212#206#255#231#212#206#255#231
+ +#212#206#255#231#212#206#255#231#212#206#255#231#212#206#255#231#212#206#255
+ +#231#212#206#255#231#211#206#255#230#211#205#255#229#209#201#255#225#203#194
+ +#255#219#191#181#255#208#173#159#255#193#149#129#255#173'w`'#255'~Q='#255'c:'
+ +''''#255'^2'#31#255'\0'#28#238'[/'#27'O'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0'[/'#27'F\0'#28#234'^2'#31#255'c:'''#255'zN:'#255#168's['#255
+ +#190#143'{'#255#205#167#152#255#217#187#177#255#225#201#193#255#229#209#202
+ +#255#232#213#207#255#232#214#209#255#233#215#210#255#233#215#210#255#233#215
+ +#210#255#233#215#210#255#233#215#210#255#233#215#210#255#233#215#210#255#233
+ +#215#210#255#233#215#210#255#233#215#210#255#233#215#210#255#233#215#210#255
+ +#233#215#210#255#233#215#210#255#233#215#210#255#233#215#210#255#233#215#210
+ +#255#233#215#210#255#233#215#210#255#233#215#210#255#233#215#210#255#233#215
+ +#210#255#233#215#210#255#233#215#210#255#233#215#210#255#233#215#210#255#233
+ +#215#210#255#233#215#210#255#233#215#210#255#233#215#210#255#233#215#210#255
+ +#233#215#210#255#233#215#210#255#233#215#210#255#233#215#210#255#233#215#210
+ +#255#233#215#210#255#233#215#210#255#233#215#210#255#233#215#210#255#233#215
+ +#210#255#233#215#210#255#233#215#210#255#233#215#210#255#233#215#210#255#233
+ +#215#210#255#232#215#209#255#232#214#208#255#231#212#206#255#228#207#201#255
+ +#223#198#189#255#213#182#170#255#200#160#144#255#186#136'r'#255#158'iR'#255
+ +'pE2'#255'a7$'#255']1'#30#255'\0'#28#201'[/'#27#31#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#26'\0'#28#193']1'#30#255'`'
+ +'6"'#255'iA.'#255#142']H'#255#179#128'h'#255#196#153#135#255#210#176#163#255
+ +#220#194#184#255#227#205#198#255#231#212#206#255#233#216#211#255#234#217#212
+ +#255#234#218#213#255#234#218#213#255#234#218#213#255#234#218#213#255#234#218
+ +#213#255#234#218#213#255#234#218#213#255#234#218#213#255#234#218#213#255#234
+ +#218#213#255#234#218#213#255#234#218#213#255#234#218#213#255#234#218#213#255
+ +#234#218#213#255#234#218#213#255#234#218#213#255#234#218#213#255#234#218#213
+ +#255#234#218#213#255#234#218#213#255#234#218#213#255#234#218#213#255#234#218
+ +#213#255#234#218#213#255#234#218#213#255#234#218#213#255#234#218#213#255#234
+ +#218#213#255#234#218#213#255#234#218#213#255#234#218#213#255#234#218#213#255
+ +#234#218#213#255#234#218#213#255#234#218#213#255#234#218#213#255#234#218#213
+ +#255#234#218#213#255#234#218#213#255#234#218#213#255#234#218#213#255#234#217
+ +#212#255#234#216#211#255#233#215#210#255#230#211#205#255#226#203#195#255#218
+ +#190#179#255#206#170#155#255#192#146#127#255#172'v`'#255#129'S?'#255'e<)'#255
+ +'_4 '#255'\1'#29#255'[/'#27#143'[/'#27#5#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#3'[/'#27#127'\0'#28
+ +#248'^3'#31#255'c:'''#255'sI6'#255#158'kT'#255#186#136's'#255#200#160#143#255
+ ,#213#180#169#255#222#197#187#255#229#208#201#255#232#214#209#255#234#218#213
+ +#255#235#219#215#255#236#220#215#255#236#220#216#255#236#220#216#255#236#220
+ +#216#255#236#220#216#255#236#220#216#255#236#220#216#255#236#220#216#255#236
+ +#220#216#255#236#220#216#255#236#220#216#255#236#220#216#255#236#220#216#255
+ +#236#220#216#255#236#220#216#255#236#220#216#255#236#220#216#255#236#220#216
+ +#255#236#220#216#255#236#220#216#255#236#220#216#255#236#220#216#255#236#220
+ +#216#255#236#220#216#255#236#220#216#255#236#220#216#255#236#220#216#255#236
+ +#220#216#255#236#220#216#255#236#220#216#255#236#220#216#255#236#220#216#255
+ +#236#220#216#255#236#220#216#255#236#220#216#255#236#220#216#255#236#220#216
+ +#255#236#220#216#255#236#220#215#255#235#219#215#255#234#217#212#255#232#213
+ +#207#255#227#205#198#255#219#193#183#255#209#176#162#255#196#153#136#255#181
+ +#129'l'#255#145'`K'#255'lB0'#255'a7$'#255']1'#30#255'\0'#28#231'[/'#27'O'#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27'$\0'#28#185'\1'#29#255'`5!'#255
+ +'f=*'#255#128'S>'#255#166'r['#255#188#139'v'#255#201#161#145#255#213#181#169
+ +#255#223#197#189#255#229#209#202#255#233#216#210#255#235#219#215#255#236#221
+ +#217#255#237#222#219#255#238#223#220#255#238#223#220#255#238#223#220#255#238
+ +#223#220#255#238#223#220#255#238#223#220#255#238#223#220#255#238#223#220#255
+ +#238#223#220#255#238#223#220#255#238#223#220#255#238#223#220#255#238#223#220
+ +#255#238#223#220#255#238#223#220#255#238#223#220#255#238#223#220#255#238#223
+ +#220#255#238#223#220#255#238#223#220#255#238#223#220#255#238#223#220#255#238
+ +#223#220#255#238#223#220#255#238#223#220#255#238#223#220#255#238#223#220#255
+ +#238#223#220#255#238#223#220#255#238#223#220#255#238#223#220#255#238#223#220
+ +#255#237#222#219#255#237#222#218#255#236#221#217#255#235#218#214#255#232#214
+ +#208#255#228#206#199#255#220#193#184#255#210#176#163#255#197#155#137#255#184
+ +#134'o'#255#155'iR'#255'uI7'#255'c:'''#255'^3'#31#255'\1'#29#252'[/'#27#144
+ +'[/'#27#14#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'['
+ +'/'#27'U\0'#28#228']1'#30#255'`6"'#255'g>,'#255#127'R?'#255#164'qZ'#255#188
+ +#139'v'#255#200#159#144#255#211#179#166#255#220#194#184#255#228#206#199#255
+ +#232#214#209#255#235#219#215#255#237#222#219#255#238#225#221#255#239#225#222
+ +#255#239#225#222#255#239#226#223#255#239#226#223#255#239#226#223#255#239#226
+ +#223#255#239#226#223#255#239#226#223#255#239#226#223#255#239#226#223#255#239
+ +#226#223#255#239#226#223#255#239#226#223#255#239#226#223#255#239#226#223#255
+ +#239#226#223#255#239#226#223#255#239#226#223#255#239#226#223#255#239#226#223
+ +#255#239#226#223#255#239#226#223#255#239#226#223#255#239#226#223#255#239#226
+ +#223#255#239#226#223#255#239#226#223#255#239#225#222#255#238#225#221#255#238
+ +#224#220#255#237#222#218#255#235#218#214#255#231#212#206#255#226#203#195#255
+ +#218#191#180#255#209#174#160#255#197#154#136#255#184#132'o'#255#154'hR'#255
+ +'uK8'#255'e;('#255'_4 '#255'\1'#29#255'\0'#28#197'[/'#27'/'#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27
+ +#12'[/'#27#134'\0'#28#242'^2'#31#255'a5#'#255'g>+'#255'|Q='#255#160'lV'#255
+ +#184#133'p'#255#196#152#134#255#207#170#156#255#216#187#175#255#224#200#192
+ +#255#230#210#203#255#234#216#211#255#236#220#216#255#238#224#220#255#239#226
+ +#223#255#240#227#225#255#240#228#225#255#240#228#225#255#241#229#226#255#241
+ +#229#226#255#241#229#226#255#241#229#226#255#241#229#227#255#241#229#227#255
+ +#241#229#227#255#241#229#227#255#241#229#227#255#241#229#227#255#241#229#227
+ +#255#241#229#227#255#241#229#227#255#241#229#226#255#241#229#226#255#241#229
+ ,#226#255#241#229#226#255#240#228#225#255#240#228#225#255#240#227#224#255#239
+ +#225#222#255#238#223#220#255#236#220#215#255#233#215#210#255#228#207#201#255
+ +#222#196#187#255#213#183#170#255#204#166#150#255#192#147#127#255#179#127'i'
+ +#255#150'fO'#255'tI7'#255'e;('#255'`5!'#255']1'#30#255'\0'#28#223'[/'#27'`[/'
+ +#27#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#17'[/'#27#127'\0'#28#238']1'
+ +#30#255'`6"'#255'e<)'#255'rI6'#255#142'_J'#255#170'wa'#255#188#140'w'#255#199
+ +#158#141#255#208#173#159#255#216#186#175#255#222#196#187#255#227#206#198#255
+ +#232#213#208#255#235#219#214#255#237#222#218#255#238#224#220#255#239#226#223
+ +#255#240#227#225#255#241#229#226#255#242#230#228#255#242#230#228#255#242#231
+ +#229#255#242#231#229#255#242#231#229#255#242#231#229#255#242#231#229#255#242
+ +#231#229#255#242#231#229#255#242#230#228#255#241#229#227#255#241#229#226#255
+ +#240#227#225#255#239#225#222#255#238#224#220#255#236#221#217#255#234#218#213
+ +#255#231#211#206#255#226#204#196#255#220#194#184#255#214#183#171#255#206#169
+ +#155#255#196#153#135#255#185#135'r'#255#162'q['#255#134'XD'#255'lC1'#255'c:'
+ +''''#255'_4 '#255']0'#30#255'\0'#28#217'[/'#27'`[/'#27#4#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#13'[/'#27'w\0'#28#233
+ +']1'#30#255'_4 '#255'b8%'#255'h?-'#255'zN;'#255#149'dP'#255#170'xa'#255#187
+ +#137't'#255#194#150#131#255#202#164#148#255#210#176#163#255#216#187#175#255
+ +#220#194#184#255#224#200#192#255#228#207#199#255#231#212#206#255#234#217#211
+ +#255#236#220#215#255#236#222#217#255#237#222#219#255#238#223#220#255#238#223
+ +#220#255#238#224#220#255#238#223#220#255#237#223#219#255#237#223#218#255#236
+ +#221#217#255#235#219#215#255#233#216#210#255#230#211#204#255#227#204#197#255
+ +#223#199#190#255#219#192#183#255#215#185#173#255#208#173#159#255#200#160#144
+ +#255#192#146#127#255#183#133'o'#255#164's\'#255#142']J'#255'rI7'#255'f=*'#255
+ +'a6#'#255'^3'#31#255'\1'#29#255'\0'#28#210'[/'#27'X[/'#27#2#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0'[/'#27#5'[/'#27'P\0'#28#173'\1'#29#249']1'#30#255'`5!'#255'c9&'#255'g'
+ +'>,'#255'qH6'#255#133'YE'#255#153'iT'#255#172'yd'#255#186#136'q'#255#191#144
+ +'}'#255#196#153#136#255#202#162#146#255#207#171#156#255#211#178#165#255#214
+ +#183#171#255#216#186#175#255#217#188#177#255#218#190#179#255#219#191#182#255
+ +#219#192#182#255#219#192#181#255#218#189#179#255#217#187#177#255#215#185#173
+ +#255#213#182#169#255#210#176#163#255#205#169#154#255#200#160#144#255#195#151
+ +#133#255#190#142'z'#255#183#132'o'#255#167'u_'#255#148'eP'#255#127'S@'#255'm'
+ +'E2'#255'f=*'#255'b7%'#255'_4 '#255']1'#30#255'\0'#28#235'[/'#27#147'[/'#27
+ +'5'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'['
+ ,'/'#27#18'[/'#27'i\0'#28#199'\1'#29#254']1'#30#255'_4 '#255'a6#'#255'd9('#255
+ +'g>,'#255'oF3'#255'}Q>'#255#138'[G'#255#149'fQ'#255#160'oZ'#255#170'xa'#255
+ +#176'}h'#255#180#128'l'#255#183#133'p'#255#186#136's'#255#188#138'u'#255#188
+ +#139'v'#255#187#138'u'#255#186#135'r'#255#183#132'n'#255#178#128'j'#255#174
+ +'|e'#255#168'v`'#255#158'mW'#255#146'bN'#255#133'YE'#255'yM;'#255'mC1'#255'g'
+ +'>+'#255'c9&'#255'`6"'#255'^3'#31#255']1'#30#255'\0'#28#248'\0'#28#173'[/'#27
+ +'O[/'#27#5#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#20'[/'#27'V\0'#28#153
+ +'\0'#28#220'\1'#29#255']1'#30#255'^3'#31#255'`5!'#255'a7$'#255'c9&'#255'e;('
+ +#255'f=*'#255'g>,'#255'i@.'#255'jB0'#255'mE2'#255'qH5'#255'tJ7'#255'qG5'#255
+ +'lC1'#255'jA0'#255'h?-'#255'g>+'#255'e<)'#255'd:('#255'c9&'#255'a6#'#255'`5!'
+ +#255'^2'#31#255']1'#30#255'\1'#29#252'\0'#28#201'[/'#27#134'[/'#27'C[/'#27#8
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0'[/'#27#31'[/'#27'_[/'#27#138'\0'#28#176'\0'#28#213'\0'#28
+ +#248'\1'#29#255'\1'#29#255'\1'#29#255']1'#30#255'^2'#31#255'^2'#31#255'^3'#31
+ +#255'^3'#31#255'^3'#31#255'^2'#31#255']1'#30#255']1'#30#255'\1'#29#255'\1'#29
+ +#255'\1'#29#255'\0'#28#241'\0'#28#203'\0'#28#165'[/'#27#127'[/'#27'N[/'#27#15
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0'[/'#27#2'[/'#27'![/'#27'E[/'#27'U[/'#27'a[/'#27'm[/'#27'y[/'#27
+ +#134'\0'#29#141'[/'#27#130'[/'#27'v[/'#27'j[/'#27'^[/'#27'Q[/'#27'=[/'#27#23
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ ,#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#255#255#255#255#255#255#255#128#0#255#255
+ +#255#255#255#255#255#255#255#255#255#255#255#224#0#0#3#255#255#255#255#255
+ +#255#255#255#255#255#255#254#0#0#0#0'?'#255#255#255#255#255#255#255#255#255
+ +#255#240#0#0#0#0#7#255#255#255#255#255#255#255#255#255#255#128#0#0#0#0#0#255
+ +#255#255#255#255#255#255#255#255#254#0#0#0#0#0#0'?'#255#255#255#255#255#255
+ +#255#255#248#0#0#0#0#0#0#15#255#255#255#255#255#255#255#255#224#0#0#0#0#0#0#3
+ +#255#255#255#255#255#255#255#255#128#0#0#0#0#0#0#0#255#255#255#255#255#255
+ +#255#254#0#0#0#0#0#0#0#0'?'#255#255#255#255#255#255#252#0#0#0#0#0#0#0#0#31
+ +#255#255#255#255#255#255#240#0#0#0#0#0#0#0#0#7#255#255#255#255#255#255#224#0
+ +#0#0#0#0#0#0#0#3#255#255#255#255#255#255#128#0#0#0#0#0#0#0#0#1#255#255#255
+ +#255#255#255#0#0#0#0#0#0#0#0#0#0#127#255#255#255#255#254#0#0#0#0#0#0#0#0#0#0
+ +'?'#255#255#255#255#252#0#0#0#0#0#0#0#0#0#0#31#255#255#255#255#248#0#0#0#0#0
+ +#0#0#0#0#0#15#255#255#255#255#240#0#0#0#0#0#0#0#0#0#0#7#255#255#255#255#224#0
+ +#0#0#0#0#0#0#0#0#0#3#255#255#255#255#192#0#0#0#0#0#0#0#0#0#0#1#255#255#255
+ +#255#128#0#0#0#0#0#0#0#0#0#0#0#255#255#255#255#0#0#0#0#0#0#0#0#0#0#0#0#127
+ +#255#255#254#0#0#0#0#0#0#0#0#0#0#0#0#127#255#255#254#0#0#0#0#0#0#0#0#0#0#0#0
+ +'?'#255#255#252#0#0#0#0#0#0#0#0#0#0#0#0#31#255#255#248#0#0#0#0#0#0#0#0#0#0#0
+ +#0#15#255#255#240#0#0#0#0#0#0#0#0#0#0#0#0#7#255#255#240#0#0#0#0#0#0#0#0#0#0#0
+ +#0#7#255#255#224#0#0#0#0#0#0#0#0#0#0#0#0#3#255#255#192#0#0#0#0#0#0#0#0#0#0#0
+ +#0#3#255#255#192#0#0#0#0#0#0#0#0#0#0#0#0#1#255#255#128#0#0#0#0#0#0#0#0#0#0#0
+ +#0#1#255#255#128#0#0#0#0#0#0#0#0#0#0#0#0#0#255#255#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#255#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#127#254#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#127#254#0#0#0#0#0#0#0#0#0#0#0#0#0#0'?'#254#0#0#0#0#0#0#0#0#0#0#0#0#0#0'?'
+ +#252#0#0#0#0#0#0#0#0#0#0#0#0#0#0'?'#252#0#0#0#0#0#0#0#0#0#0#0#0#0#0#31#252#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#31#248#0#0#0#0#0#0#0#0#0#0#0#0#0#0#15#248#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#15#248#0#0#0#0#0#0#0#0#0#0#0#0#0#0#15#240#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#7#240#0#0#0#0#0#0#0#0#0#0#0#0#0#0#7#240#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#7#224#0#0#0#0#0#0#0#0#0#0#0#0#0#0#7#224#0#0#0#0#0#0#0#0#0#0#0#0#0#0#3
+ +#224#0#0#0#0#0#0#0#0#0#0#0#0#0#0#3#224#0#0#0#0#0#0#0#0#0#0#0#0#0#0#3#224#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#3#224#0#0#0#0#0#0#0#0#0#0#0#0#0#0#3#192#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#3#192#0#0#0#0#0#0#0#0#0#0#0#0#0#0#3#192#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#1#192#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1#192#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#1#192#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1#192#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1#192#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#1#192#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1#192#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#1#192#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1#192#0#0#0#0#0#0#0#0#0
+ ,#0#0#0#0#0#1#192#0#0#0#0#0#0#0#0#0#0#0#0#0#0#3#192#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#3#224#0#0#0#0#0#0#0#0#0#0#0#0#0#0#3#224#0#0#0#0#0#0#0#0#0#0#0#0#0#0#3#224
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#3#224#0#0#0#0#0#0#0#0#0#0#0#0#0#0#3#224#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#3#240#0#0#0#0#0#0#0#0#0#0#0#0#0#0#7#240#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#7#240#0#0#0#0#0#0#0#0#0#0#0#0#0#0#7#240#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#15#248#0#0#0#0#0#0#0#0#0#0#0#0#0#0#15#248#0#0#0#0#0#0#0#0#0#0#0#0#0#0#15
+ +#248#0#0#0#0#0#0#0#0#0#0#0#0#0#0#15#252#0#0#0#0#0#0#0#0#0#0#0#0#0#0#31#252#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#31#252#0#0#0#0#0#0#0#0#0#0#0#0#0#0'?'#254#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0'?'#254#0#0#0#0#0#0#0#0#0#0#0#0#0#0'?'#254#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#127#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#127#255#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#255#255#128#0#0#0#0#0#0#0#0#0#0#0#0#0#255#255#128#0#0#0#0#0#0#0#0
+ +#0#0#0#0#1#255#255#128#0#0#0#0#0#0#0#0#0#0#0#0#1#255#255#192#0#0#0#0#0#0#0#0
+ +#0#0#0#0#3#255#255#192#0#0#0#0#0#0#0#0#0#0#0#0#3#255#255#224#0#0#0#0#0#0#0#0
+ +#0#0#0#0#7#255#255#224#0#0#0#0#0#0#0#0#0#0#0#0#15#255#255#240#0#0#0#0#0#0#0#0
+ +#0#0#0#0#15#255#255#248#0#0#0#0#0#0#0#0#0#0#0#0#31#255#255#248#0#0#0#0#0#0#0
+ +#0#0#0#0#0'?'#255#255#252#0#0#0#0#0#0#0#0#0#0#0#0#127#255#255#252#0#0#0#0#0#0
+ +#0#0#0#0#0#0#255#255#255#254#0#0#0#0#0#0#0#0#0#0#0#0#255#255#255#255#0#0#0#0
+ +#0#0#0#0#0#0#0#1#255#255#255#255#128#0#0#0#0#0#0#0#0#0#0#3#255#255#255#255
+ +#128#0#0#0#0#0#0#0#0#0#0#7#255#255#255#255#192#0#0#0#0#0#0#0#0#0#0#15#255#255
+ +#255#255#224#0#0#0#0#0#0#0#0#0#0#31#255#255#255#255#240#0#0#0#0#0#0#0#0#0#0
+ +#31#255#255#255#255#248#0#0#0#0#0#0#0#0#0#0'?'#255#255#255#255#252#0#0#0#0#0
+ +#0#0#0#0#0#127#255#255#255#255#254#0#0#0#0#0#0#0#0#0#1#255#255#255#255#255
+ +#255#0#0#0#0#0#0#0#0#0#3#255#255#255#255#255#255#128#0#0#0#0#0#0#0#0#7#255
+ +#255#255#255#255#255#224#0#0#0#0#0#0#0#0#15#255#255#255#255#255#255#240#0#0#0
+ +#0#0#0#0#0#31#255#255#255#255#255#255#248#0#0#0#0#0#0#0#0#127#255#255#255#255
+ +#255#255#254#0#0#0#0#0#0#0#0#255#255#255#255#255#255#255#255#128#0#0#0#0#0#0
+ +#3#255#255#255#255#255#255#255#255#192#0#0#0#0#0#0#7#255#255#255#255#255#255
+ +#255#255#240#0#0#0#0#0#0#31#255#255#255#255#255#255#255#255#252#0#0#0#0#0#0
+ +#127#255#255#255#255#255#255#255#255#255#0#0#0#0#0#3#255#255#255#255#255#255
+ +#255#255#255#255#224#0#0#0#0#15#255#255#255#255#255#255#255#255#255#255#252#0
+ +#0#0#0#127#255#255#255#255#255#255#255#255#255#255#255#192#0#0#7#255#255#255
+ +#255#255#255#255#255#255#255#255#255#254#0#1#255#255#255#255#255#255#255#255
+ +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
+ +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
+ +#255#255#255#255#255#255#255#255#255'('#0#0#0'@'#0#0#0#128#0#0#0#1#0' '#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'@@@'#4'III'#7'III'#7
+ +'333'#5#128#128#128#2#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'UUU'#6'DDD'
+ +#15'FFF'#22'EEE'#26'DDD'#30'III#GGG/DDD'#30#255'j>'#31#253'g>#'#249'[>+'#235'PB8'#218'HE'
+ +'C'#203'FEC'#195'EED'#184'DDD'#166'DDDqEEE4@@@'#20'@@@'#4#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1
+ +'999'#9'BBB'#31'CCCPEDD'#143'FFE'#182'NB:'#211'Z?-'#231'g>#'#249'l?'#31#255
+ +'zK$'#253#150']*'#255#165'h.'#255#172'm0'#255#180's2'#255#186'x4'#255#189'{4'
+ +#255#192#127'5'#255#190'|4'#255#187'x4'#255#182'u3'#255#175'p1'#255#167'j/'
+ +#255#156'b+'#255#131'R&'#254'oB '#255'i>!'#253'_>)'#238'S@6'#222'FEB'#203'DD'
+ +'C'#190'DDD'#164'CCCkCCC.PPP'#16'UUU'#3#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#128#128#128#2'CCC'#19'BBBBDDD'#136'EED'#179'LA9'
+ +#209'`=&'#243'k?'#31#255#127'N&'#254#154'`,'#255#176'q1'#255#191'~5'#255#200
+ +#138'7'#255#207#145'8'#255#210#149'9'#255#213#153'9'#255#217#157':'#255#219
+ +#160';'#255#221#162';'#255#220#162':'#255#217#158':'#255#215#155':'#255#211
+ +#151'9'#255#208#146'8'#255#203#141'8'#255#194#129'6'#255#183'v4'#255#163'f.'
+ +#255#137'U('#254'qC"'#254'f'
+ +'>>!+++'#6#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'@@@'#4'BBB'#27'CC'
+ +'C[CCB'#165'LD='#203']<('#238'j> '#255#135'R('#254#176'p3'#255#193#128'7'#255
+ +#202#139'9'#255#211#151';'#255#220#162'<'#255#227#170'>'#255#232#176'?'#255
+ +#234#180'?'#255#237#182'?'#255#239#185'@'#255#241#187'@'#255#242#188'A'#255
+ +#241#187'@'#255#240#185'A'#255#238#183'@'#255#235#180'@'#255#233#178'?'#255
+ +#229#173'>'#255#222#165'='#255#215#156'<'#255#205#144':'#255#196#133'8'#255
+ +#185'x5'#255#152'^-'#255'oC"'#254'd<#'#247'QA7'#220'FFE'#200'CCC'#180'CCC}AA'
+ +'A/UUU'#9#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'III'#7'CCC&DDDpECC'#180'X<,'#232'i='
+ +'!'#254#128'O('#254#170'l3'#255#194#130':'#255#210#150'>'#255#220#163'?'#255
+ +#227#171'A'#255#234#180'B'#255#240#187'D'#255#242#190'D'#255#244#193'E'#255
+ +#246#194'D'#255#247#195'E'#255#248#197'E'#255#249#197'E'#255#249#198'E'#255
+ +#249#197'E'#255#248#196'E'#255#247#195'E'#255#246#195'E'#255#245#194'D'#255
+ +#243#191'D'#255#240#188'C'#255#236#183'C'#255#230#174'B'#255#223#165'@'#255
+ +#215#156'?'#255#200#137';'#255#182'u6'#255#146'[,'#255'm@!'#254'`:%'#244'KA;'
+ +#211'CCC'#189'CCC'#144'BBB>PPP'#16#128#128#128#2#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'999'#9'@@@4CCC'#133
+ +'HD@'#192'_9$'#244'rE%'#254#164'h3'#255#191#127';'#255#206#146'?'#255#219#163
+ +'C'#255#232#178'F'#255#238#185'G'#255#241#189'H'#255#244#193'H'#255#246#195
+ +'I'#255#247#196'I'#255#247#197'J'#255#247#197'I'#255#247#198'I'#255#248#198
+ +'I'#255#248#198'I'#255#248#197'I'#255#248#198'I'#255#248#198'I'#255#248#198
+ +'I'#255#247#197'I'#255#247#197'I'#255#247#196'I'#255#246#196'I'#255#245#194
+ +'H'#255#242#190'H'#255#239#187'H'#255#235#182'G'#255#224#168'D'#255#211#153
+ +'A'#255#196#134'='#255#177'q7'#255#133'Q)'#254'e: '#253'N?7'#218'DDC'#195'CC'
+ +'C'#160'FFFP@@@'#20#0#0#0#2#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0'III'#7'FFF3CCC'#145'LB;'#204'd:"'#250'|L('#254#180's9'#255
+ +#202#143'A'#255#216#159'F'#255#228#174'I'#255#236#184'K'#255#241#191'L'#255
+ +#243#193'M'#255#244#194'M'#255#244#195'M'#255#245#196'M'#255#245#195'M'#255
+ +#245#195'M'#255#245#195'M'#255#245#195'M'#255#245#195'M'#255#245#195'M'#255
+ +#245#195'M'#255#245#195'M'#255#245#195'M'#255#245#195'M'#255#245#195'M'#255
+ +#245#195'M'#255#245#195'M'#255#245#196'M'#255#245#195'M'#255#244#194'M'#255
+ +#243#194'M'#255#242#192'M'#255#238#186'L'#255#232#179'J'#255#220#165'F'#255
+ +#208#150'C'#255#190#127'<'#255#147'[.'#255'h< '#255'S=1'#228'EED'#199'DDD'
+ +#168'BBBUGGG'#18#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +'@@@'#4'FFF(EEE'#134'P?5'#212'e:!'#254#137'U,'#254#186'z='#255#208#150'E'#255
+ +#224#171'L'#255#233#181'O'#255#238#187'P'#255#240#191'P'#255#242#192'Q'#255
+ +#242#193'Q'#255#242#193'Q'#255#242#193'P'#255#242#193'Q'#255#242#193'Q'#255
+ +#242#193'Q'#255#242#193'Q'#255#242#193'Q'#255#242#193'Q'#255#242#193'Q'#255
+ ,#242#193'Q'#255#242#193'Q'#255#242#193'Q'#255#242#193'Q'#255#242#193'Q'#255
+ +#242#193'Q'#255#242#193'Q'#255#242#193'Q'#255#242#193'Q'#255#242#193'Q'#255
+ +#242#193'Q'#255#242#193'Q'#255#241#192'Q'#255#239#189'P'#255#234#184'O'#255
+ +#228#175'M'#255#215#159'I'#255#194#132'@'#255#160'd3'#255'k?"'#254'X:*'#236
+ +'FDC'#201'CCC'#164'AAAG;;;'#13#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'U'
+ +'UU'#3'BBB'#31'CCCvO=3'#211'f:'#31#255#150']2'#255#190#128'A'#255#211#155'I'
+ +#255#226#175'Q'#255#234#185'S'#255#237#188'T'#255#238#190'T'#255#239#191'U'
+ +#255#239#191'U'#255#239#191'U'#255#239#191'U'#255#239#191'U'#255#239#191'U'
+ +#255#239#191'U'#255#239#191'U'#255#235#189'S'#255'|d,'#255'N>'#28#255'4*'#19
+ +#255'=1'#22#255'WE'#31#255'w_*'#255#173#139'='#255#239#191'U'#255#239#191'U'
+ +#255#239#191'U'#255#239#191'U'#255#239#191'U'#255#239#191'U'#255#239#191'U'
+ +#255#239#191'U'#255#239#191'U'#255#239#190'T'#255#238#189'U'#255#236#187'S'
+ +#255#230#179'R'#255#217#162'L'#255#198#138'D'#255#170'l8'#255'pC$'#254'Z8'''
+ +#240'DBB'#197'CCC'#153'FFF:@@@'#8#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#2'FFF'#22
+ +'BBBeJ?9'#195'b8 '#254#150']2'#255#194#133'E'#255#213#158'N'#255#226#176'T'
+ +#255#233#185'W'#255#236#187'W'#255#236#188'X'#255#236#188'X'#255#236#188'X'
+ +#255#236#188'X'#255#236#188'X'#255#236#188'X'#255#236#188'X'#255#236#188'X'
+ +#255#236#188'X'#255'cO%'#255#4#3#1#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#1#1#0#255#18#14#7#255'A4'#24#255#134'k2'
+ +#255#218#174'R'#255#236#188'X'#255#236#188'X'#255#236#188'X'#255#236#188'X'
+ +#255#236#188'X'#255#236#188'X'#255#236#187'W'#255#234#186'W'#255#229#180'U'
+ +#255#218#165'P'#255#201#143'H'#255#173'o<'#255'k>#'#254'S;-'#231'CCC'#193'CC'
+ +'C'#141'DDD-fff'#5#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'@@@'#12'DDDKFA='#179'`7 '#251#137'S-'
+ +#255#192#131'E'#255#214#161'Q'#255#226#176'W'#255#231#183'Y'#255#233#185'['
+ +#255#233#186'['#255#234#185'Z'#255#234#185'Z'#255#234#185'Z'#255#234#185'Z'
+ +#255#234#185'Z'#255#234#185'Z'#255#234#185'Z'#255#234#185'Z'#255'L<'#29#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#8#7#3#255'P'
+ +'?'#31#255#203#161'N'#255#234#185'Z'#255#234#185'Z'#255#234#185'Z'#255#234
+ +#185'Z'#255#233#186'['#255#232#183'Z'#255#228#178'Y'#255#219#167'T'#255#201
+ +#143'K'#255#163'g8'#255'f: '#255'O=4'#222'DDD'#188'CCCzBBB'#27#0#0#0#1#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'U'
+ +'UU'#3'GGG$D@@'#147'\6#'#245'{I*'#254#185'{C'#255#211#157'R'#255#225#175'Z'
+ +#255#229#181'\'#255#230#183']'#255#230#183']'#255#230#183']'#255#230#183']'
+ +#255#230#183']'#255#230#183']'#255#230#183']'#255#230#183']'#255#230#183']'
+ +#255#230#183']'#255#138'm8'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#24#20#10#255'x_0'
+ +#255#226#181'['#255#230#183']'#255#230#183']'#255#230#183']'#255#230#181'\'
+ +#255#227#177'['#255#217#165'V'#255#196#136'J'#255#151']4'#255'b8 '#254'K@9'
+ +#214'CCC'#175'AAAJ...'#11#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0'@@@'#16'CCC\V6'''#228'nA&'#254#178'tA'#255#205
+ +#151'R'#255#221#172'\'#255#226#179'_'#255#228#180'_'#255#228#180'_'#255#228
+ +#180'_'#255#228#180'_'#255#228#180'_'#255#228#180'_'#255#228#180'_'#255#228
+ +#180'_'#255#228#180'_'#255#228#180'_'#255#228#180'_'#255#17#13#7#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#2#1#1#255'H9'#30#255#224#178']'
+ +#255#228#180'_'#255#228#180'_'#255#227#179'^'#255#224#175']'#255#213#160'W'
+ +#255#190#129'H'#255#137'T/'#255'^4 '#252'FB?'#201'CCC'#140'DDD"'#0#0#0#3#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'@@@'#4'FFF,J=7'
+ +#175'`4'#30#255#165'g;'#255#200#144'Q'#255#217#166'\'#255#223#176'`'#255#225
+ +#177'`'#255#225#177'a'#255#225#177'a'#255#225#177'a'#255#225#177'a'#255#225
+ +#177'a'#255#225#177'a'#255#225#177'a'#255#225#177'a'#255#225#177'a'#255#225
+ +#177'a'#255#218#171'^'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#11#9#5#255#196#154'U'#255#225#177'a'#255#225#177
+ +'`'#255#224#177'a'#255#220#171'^'#255#208#154'W'#255#184'{F'#255'nA%'#254'T8'
+ +'*'#233'DDD'#180'CCCX333'#15#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0'CCC'#19'CCCjY5#'#239'~J,'#254#191#132'M'#255#213#162']'#255
+ ,#220#171'a'#255#221#173'c'#255#222#174'b'#255#222#174'b'#255#222#174'b'#255
+ +#222#174'b'#255#222#174'b'#255#222#174'b'#255#222#174'b'#255#222#174'b'#255
+ +#222#174'b'#255#222#174'b'#255#222#174'b'#255#154'yC'#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#15#11#6
+ +#255#218#172'`'#255#222#174'b'#255#222#174'b'#255#221#173'b'#255#217#167'_'
+ +#255#202#146'T'#255#156'a9'#255'^4'#30#254'G@='#206'DDD'#151'>>>)@@@'#4#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'UUU'#3'AAA+L;4'#188'b6 '#254#170
+ +'l@'#255#206#152'Z'#255#217#168'b'#255#219#171'd'#255#219#171'd'#255#219#171
+ +'d'#255#219#171'd'#255#219#171'd'#255#219#171'd'#255#219#171'd'#255#219#171
+ +'d'#255#219#171'd'#255#219#171'd'#255#219#171'd'#255#219#171'd'#255#219#171
+ +'d'#255#219#171'd'#255#26#20#12#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'oW3'#255#219#171'd'#255#219
+ +#171'd'#255#219#171'd'#255#218#169'c'#255#212#161'_'#255#187#127'L'#255'uD)'
+ +#254'W6('#238'CCC'#182'CCC[III'#14#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0'@@@'#12'EBBS[3'#31#244#134'O/'#255#192#134'Q'#255#212#162'b'#255#215
+ +#167'd'#255#216#168'd'#255#216#168'd'#255#216#168'd'#255#216#168'd'#255#216
+ +#168'd'#255#216#168'd'#255#216#168'd'#255#216#168'd'#255#216#168'd'#255#216
+ +#168'd'#255#216#168'd'#255#216#168'd'#255#216#168'd'#255#216#168'd'#255#198
+ +#154'\'#255#5#4#2#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255'!'#25#15#255#216#168'd'#255#216#168'd'#255#216#168
+ +'d'#255#216#168'd'#255#214#166'd'#255#202#147'Y'#255#161'e='#255'^2'#29#255
+ +'J?:'#208'CCC'#137'EEE'#26#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'C'
+ +'CC'#23'O9/'#171'`3'#31#254#174'pD'#255#203#150']'#255#212#163'e'#255#213#164
+ +'e'#255#213#164'e'#255#213#164'e'#255#213#164'e'#255#213#164'e'#255#213#164
+ +'e'#255#213#164'e'#255#213#164'e'#255#213#164'e'#255#213#164'e'#255#213#164
+ +'e'#255#213#164'e'#255#213#164'e'#255#213#164'e'#255#213#164'e'#255#213#164
+ +'e'#255#173#133'R'#255#3#2#1#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#22#17#11#255#213#164'e'#255#213#164'e'#255#213#164
+ +'e'#255#213#164'e'#255#213#164'f'#255#209#158'a'#255#187#128'O'#255'yD)'#254
+ +'W4$'#241'BBB'#169'DDD1@@@'#4#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#2'FFF(W4'
+ +'$'#229'{E)'#255#191#134'T'#255#207#157'c'#255#210#160'f'#255#210#160'f'#255
+ +#210#160'f'#255#210#160'f'#255#210#160'f'#255#210#160'f'#255#210#160'f'#255
+ +#210#160'f'#255#152'tJ'#255'[E,'#255'K9$'#255'{]<'#255#196#149'_'#255#210#160
+ +'f'#255#210#160'f'#255#210#160'f'#255#210#160'f'#255#210#160'f'#255#159'yM'
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'"'
+ +#26#17#255#210#160'f'#255#210#160'f'#255#210#160'f'#255#210#160'f'#255#210
+ +#160'f'#255#209#160'e'#255#199#146']'#255#156'_;'#255'\1'#28#254'FBA'#188'FF'
+ +'FXNNN'#13#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'FFF'#11'F@=T\/'#28#253#151'\9'#255
+ +#200#147'_'#255#207#156'e'#255#207#156'e'#255#207#156'e'#255#207#156'e'#255
+ +#207#156'e'#255#207#156'e'#255#207#156'e'#255#178#135'W'#255'$'#27#17#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'N:&'#255#207#156'e'#255#207
+ +#156'e'#255#207#156'e'#255#207#156'e'#255#207#156'e'#255#3#2#1#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'uX9'#255#207#156'e'#255#207
+ +#156'e'#255#207#156'e'#255#207#156'e'#255#207#156'e'#255#207#157'e'#255#204
+ +#153'b'#255#180'wK'#255'a4'#30#254'M;3'#216'DDD'#132'==='#25#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0'CCC'#19'N9.'#159'^2'#30#254#176'rI'#255#202#150'c'#255#203
+ +#153'e'#255#203#153'f'#255#203#153'f'#255#203#153'f'#255#203#153'f'#255#203
+ +#153'f'#255#163'zQ'#255#1#1#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#29#22#15#255#203#153'f'#255#203#153'f'#255#203#153
+ +'f'#255#203#153'f'#255#14#10#7#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ ,#0#0#255#4#3#2#255#203#153'f'#255#203#153'f'#255#203#153'f'#255#203#153'f'
+ +#255#203#153'f'#255#203#153'f'#255#203#153'f'#255#203#152'e'#255#190#134'X'
+ +#255'yC)'#254'V5&'#239'DDD'#165'FFF('#128#128#128#2#0#0#0#0#0#0#0#0#0#0#0#0
+ +'GGG'#25'V4%'#212's@&'#254#186#128'U'#255#199#148'd'#255#200#148'd'#255#200
+ +#148'd'#255#200#148'd'#255#200#148'd'#255#200#148'd'#255#198#146'd'#255#12#9
+ +#6#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#138'fE'#255#200#148'd'#255#200#148'd'#255#200#148'd'#255
+ +#15#11#7#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1#0#0#255'&'#28#19#255#145'kH'#255
+ +#200#148'd'#255#200#148'd'#255#200#148'd'#255#200#148'd'#255#200#148'd'#255
+ +#200#148'd'#255#200#148'd'#255#200#148'd'#255#194#141'^'#255#146'W6'#255'[0'
+ +#28#254'EBB'#178'CCC9UUU'#6#0#0#0#0#0#0#0#0#0#0#0#0'JAA'#31'\1'#29#249#140'P'
+ +'2'#255#190#135'\'#255#196#143'c'#255#196#143'c'#255#196#143'c'#255#196#143
+ +'c'#255#196#143'c'#255#196#143'c'#255'>-'#31#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'&'
+ +#28#19#255#196#143'c'#255#196#143'c'#255#196#143'c'#255#25#18#12#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#2#2#1
+ +#255'*'#31#21#255'kM6'#255#187#137'_'#255#196#143'c'#255#196#143'c'#255#196
+ +#143'c'#255#196#143'c'#255#196#143'c'#255#196#143'c'#255#196#143'c'#255#196
+ +#143'c'#255#196#143'c'#255#196#143'c'#255#194#141'b'#255#170'kF'#255'\0'#28
+ +#254'L<5'#203'CCCH333'#10#0#0#0#0#0#0#0#0#0#0#0#1'K3+@[/'#27#255#160'`>'#255
+ +#190#136'_'#255#191#137'`'#255#191#137'`'#255#191#137'`'#255#191#137'`'#255
+ +#191#137'`'#255#189#135'`'#255#1#1#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#30#21#15#255
+ +#191#137'`'#255#191#137'`'#255#191#137'`'#255'aF1'#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#5#3#2#255#165'vS'#255#191#137'`'
+ +#255#191#137'`'#255#191#137'`'#255#191#137'`'#255#191#137'`'#255#191#137'`'
+ +#255#191#137'`'#255#191#137'`'#255#191#137'`'#255#191#137'`'#255#191#137'`'
+ +#255#191#137'`'#255#191#137'`'#255#191#136'`'#255#178'vQ'#255'h7 '#253'Q8,'
+ +#220'DDDV;;;'#13#0#0#0#0#0#0#0#0'UUU'#3'R4''^[/'#27#255#169'hF'#255#187#131
+ +']'#255#187#132'^'#255#187#132'^'#255#187#132'^'#255#187#132'^'#255#187#132
+ +'^'#255'uS;'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'{W>'#255#187#132'^'#255
+ +#187#132'^'#255#187#132'^'#255#185#130'^'#255#19#14#10#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#1#1#1#255#158'oO'#255#187#132'^'#255#187#132'^'
+ +#255#187#132'^'#255#187#132'^'#255#187#132'^'#255#187#132'^'#255#187#132'^'
+ +#255#187#132'^'#255#187#132'^'#255#187#132'^'#255#187#132'^'#255#187#132'^'
+ +#255#187#132'^'#255#187#132'^'#255#187#132'^'#255#181'{V'#255'r<"'#255'T6'''
+ +#228'BBBd@@@'#16#0#0#0#0#0#0#0#0'UUU'#6'T5''}_2'#30#253#171'kI'#255#183'}Z'
+ +#255#183'~Z'#255#183'~Z'#255#183'~Z'#255#183'~Z'#255#183'~Z'#255'. '#23#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#1#1#0#255'S9)'#255#183'~Z'#255#183'~Z'#255#183'~Z'#255#183'~Z'
+ +#255#183'~Z'#255#173'xV'#255#31#21#15#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'b'
+ +'C0'#255#183'~Z'#255#183'~Z'#255#183'~Z'#255#183'~Z'#255#183'~Z'#255#183'~Z'
+ +#255#183'~Z'#255#183'~Z'#255#183'~Z'#255#183'~Z'#255#183'~Z'#255#183'~Z'#255
+ +#183'~Z'#255#183'~Z'#255#183'~Z'#255#183'~Z'#255#181'zV'#255'zA%'#255'X4$'
+ +#237'DDDqCCC'#19#0#0#0#0#0#0#0#0'@@@'#8'U4%'#149'f5'#31#252#172'mK'#255#180
+ +'yX'#255#180'yX'#255#180'yX'#255#180'yX'#255#180'yX'#255#180'yX'#255#6#4#3
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#19#13#9#255#153'gK'#255#180'yX'#255#180'yX'#255#180'yX'#255#180'yX'
+ +#255#180'yX'#255#180'yX'#255#180'yX'#255#180'yX'#255'{S<'#255'+'#29#21#255#7
+ +#4#3#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1#1#1
+ +#255'gF3'#255#180'yX'#255#180'yX'#255#180'yX'#255#139']D'#255'+'#29#21#255#8
+ +#6#4#255#8#6#4#255#16#11#8#255'W:*'#255#178'wV'#255#180'yX'#255#180'yX'#255
+ +#180'yX'#255#180'yX'#255#180'yX'#255#180'yX'#255#180'yX'#255#179'yV'#255#131
+ +'F+'#255'[3!'#245'CCCyIII'#21#0#0#0#0#0#0#0#0'UUU'#6'X3"'#165'n:"'#253#172'p'
+ +'O'#255#177'wW'#255#177'wW'#255#177'wW'#255#177'wW'#255#177'wW'#255#173'uU'
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1
+ +#0#0#255'P6'''#255#177'wW'#255#177'wW'#255#177'wW'#255#177'wW'#255#177'wW'
+ ,#255#177'wW'#255#177'wW'#255#177'wW'#255#177'wW'#255#177'wW'#255#177'wW'#255
+ +#177'wW'#255#177'wW'#255#158'jM'#255'W;+'#255''''#26#19#255'"'#23#17#255'%'
+ +#25#18#255'W:+'#255#167'qS'#255#177'wW'#255#177'wW'#255#177'wW'#255'@+'#31
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#3#2#1#255
+ +#149'dI'#255#177'wW'#255#177'wW'#255#177'wW'#255#177'wW'#255#177'wW'#255#177
+ +'wW'#255#177'vV'#255#139'M0'#255'[1'#30#250'DDDpCCC'#19#0#0#0#0#0#0#0#0'UUU'
+ +#3'Y1'#31#182'v>%'#255#172'oQ'#255#175'tW'#255#175'tW'#255#175'tW'#255#175't'
+ +'W'#255#175'tW'#255'}S?'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#26#17#13#255#150'cK'#255#175'tW'#255#175'tW'#255#175'tW'#255
+ +#175'tW'#255#175'tW'#255#175'tW'#255#175'tW'#255#175'tW'#255#175'tW'#255#175
+ +'tW'#255#175'tW'#255#175'tW'#255#175'tW'#255#175'tW'#255#175'tW'#255#175'tW'
+ +#255#175'tW'#255#175'tW'#255#175'tW'#255#175'tW'#255#175'tW'#255#175'tW'#255
+ +#175'tW'#255'dC2'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#9#6#4#255#169'pU'#255#175'tW'#255#175'tW'#255#175't'
+ +'W'#255#175'tW'#255#175'tW'#255#174'sU'#255#145'S6'#255']0'#28#254'DBBd@@@'
+ +#16#0#0#0#0#0#0#0#0#0#0#0#0'Z0'#30#175'v=%'#255#171'nP'#255#174'rV'#255#174
+ +'rV'#255#174'rV'#255#174'rV'#255#174'rV'#255'L2&'#255#0#0#0#255'/'#31#23#255
+ +'}R>'#255' '#21#16#255'!'#22#17#255#139'[E'#255#174'rV'#255#174'rV'#255#174
+ +'rV'#255#174'rV'#255#174'rV'#255#174'rV'#255#174'rV'#255#174'rV'#255#174'rV'
+ +#255#174'rV'#255#174'rV'#255#174'rV'#255#174'rV'#255#174'rV'#255#174'rV'#255
+ +#174'rV'#255#174'rV'#255#174'rV'#255#174'rV'#255#174'rV'#255#174'rV'#255#174
+ +'rV'#255#174'rV'#255#174'rV'#255#174'rV'#255'?*'#31#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'6#'#27
+ +#255#174'rV'#255#174'rV'#255#174'rV'#255#174'rV'#255#174'rV'#255#173'qT'#255
+ +#145'S7'#255'\1'#29#254'AAAV;;;'#13#0#0#0#0#0#0#0#0#0#0#0#0'Z1'#30#150'n;$'
+ +#252#169'jM'#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255
+ +#149'bI'#255'@* '#255#170'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'
+ +#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255
+ +#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#172
+ +'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'
+ +#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255
+ +'G/#'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#24#16#12#255#172'qU'#255#172'qU'#255#172'qU'#255#172
+ +'qU'#255#172'qU'#255#171'oS'#255#138'N3'#255'\2'#31#249'DDDG999'#9#0#0#0#0#0
+ +#0#0#0#0#0#0#0'X1!|g7#'#250#167'gI'#255#172'pT'#255#172'qU'#255#172'qU'#255
+ +#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#172
+ +'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'
+ +#255#172'qU'#255'P5('#255')'#27#20#255#27#18#13#255'5#'#26#255'pJ8'#255#172
+ +'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'
+ +#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255
+ +#172'qU'#255#172'qU'#255#162'jO'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#9#6#4#255#172'qU'#255#172
+ +'qU'#255#172'qU'#255#172'qU'#255#172'qU'#255#170'mR'#255#131'I.'#255'[4"'#241
+ +'FFF7UUU'#6#0#0#0#0#0#0#0#0#0#0#0#0'Y1!`b5 '#251#164'cG'#255#172'pU'#255#173
+ +'rW'#255#173'rW'#255#173'rW'#255#173'rW'#255#173'rW'#255#173'rW'#255#173'rW'
+ +#255#173'rW'#255#173'rW'#255#173'rW'#255#173'rW'#255#173'rW'#255#173'rW'#255
+ +#173'rW'#255'}S?'#255#9#6#5#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#16#11#8#255#152'dM'#255#173'rW'#255#173'rW'#255#173'rW'#255#173'rW'#255
+ +#173'rW'#255#173'rW'#255#173'rW'#255#173'rW'#255#173'rW'#255#173'rW'#255#173
+ +'rW'#255#173'rW'#255#173'rW'#255#173'rW'#255'$'#24#18#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#4#3#2#255#173'r'
+ +'W'#255#173'rW'#255#173'rW'#255#173'rW'#255#173'rW'#255#170'mQ'#255'|C*'#255
+ +'W4$'#229'CCC&'#0#0#0#2#0#0#0#0#0#0#0#0#0#0#0#0'X5!A^2'#31#254#162'bE'#255
+ +#173'rV'#255#175'tY'#255#175'tY'#255#175'tY'#255#175'tY'#255#175'tY'#255#175
+ +'tY'#255#175'tY'#255#175'tY'#255#175'tY'#255#175'tY'#255#175'tY'#255#175'tY'
+ +#255#175'tY'#255'{Q?'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#14#9#7#255#173'tY'#255#175'tY'#255#175'tY'#255
+ +#175'tY'#255#175'tY'#255#175'tY'#255#175'tY'#255#175'tY'#255#175'tY'#255#175
+ +'tY'#255#175'tY'#255#175'tY'#255#175'tY'#255#175'tY'#255#132'XC'#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#21
+ +#14#11#255#175'tY'#255#175'tY'#255#175'tY'#255#175'tY'#255#174'tY'#255#170'm'
+ +'P'#255't?('#254'U5&'#203'@@@'#24#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'X0'#24' ^2'
+ +#31#255#156'\A'#255#175'v\'#255#177'y`'#255#177'y`'#255#177'y`'#255#177'y`'
+ +#255#177'y`'#255#177'y`'#255#177'y`'#255#177'y`'#255#177'y`'#255#177'y`'#255
+ ,#177'y`'#255#177'y`'#255#177'y`'#255#11#8#6#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#136']J'#255#177
+ +'y`'#255#177'y`'#255'7%'#30#255#9#6#5#255#13#9#7#255#16#11#9#255#26#18#14#255
+ +#139'_K'#255#177'y`'#255#177'y`'#255#177'y`'#255#177'y`'#255#177'y`'#255#177
+ +'y`'#255#18#12#9#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255'<)!'#255#177'y`'#255#177'y`'#255#177'y`'#255#177'y`'#255#176
+ +'x^'#255#169'kP'#255'j<&'#253'U4%'#168';;;'#13#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0'^2'#29#234#136'O4'#255#176'x^'#255#180'~f'#255#180'~f'#255#180'~f'
+ +#255#180'~f'#255#180'~f'#255#180'~f'#255#180'~f'#255#180'~f'#255#180'~f'#255
+ +#180'~f'#255#180'~f'#255#180'~f'#255#146'gS'#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#139'bO'#255#170'x`'#255#20#14#11#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255']A4'#255#180'~f'#255#180'~f'#255#180'~f'#255#180'~f'#255
+ +#180'~f'#255'qO@'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#1#1#0#255#165't^'#255#180'~f'#255#180'~f'#255#180'~f'#255#180'~f'#255
+ +#178'zb'#255#162'dH'#255'_3'#31#254'R6)c@@@'#4#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0'[/'#29#153'r?)'#252#174'sZ'#255#182#129'j'#255#183#131'l'#255#183
+ +#131'l'#255#183#131'l'#255#183#131'l'#255#183#131'l'#255#183#131'l'#255#183
+ +#131'l'#255#183#131'l'#255#183#131'l'#255#183#131'l'#255#183#131'l'#255'ZA5'
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#5#3#3#255#179#127'j'#255'uTE'#255#0#0#0#255#0#0#0#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'{XI'#255#183#131'l'
+ +#255#183#131'l'#255#183#131'l'#255#183#131'l'#255#183#131'l'#255#20#15#12#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255':)"'#255#183#131'l'#255
+ +#183#131'l'#255#183#131'l'#255#183#131'l'#255#183#131'l'#255#179'|c'#255#140
+ +'R9'#255'\2'#31#248'@@6'#28#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +'[/'#29'E`5 '#252#166'iO'#255#183#131'l'#255#186#136'q'#255#186#136'q'#255
+ +#186#136'q'#255#186#136'q'#255#186#136'q'#255#186#136'q'#255#186#136'q'#255
+ +#186#136'q'#255#186#136'q'#255#186#136'q'#255#186#136'q'#255'\D8'#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255'oQC'#255#186#136'q'#255'X@6'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#12#9#7#255#186#136'q'#255#186
+ +#136'q'#255#186#136'q'#255#186#136'q'#255#186#136'q'#255#148'lZ'#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#169'|g'#255#186#136'q'#255#186
+ +#136'q'#255#186#136'q'#255#186#136'q'#255#185#134'q'#255#177'y`'#255'tB+'#254
+ +'W2!'#194'III'#14#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'@@'#0#4'^3'
+ +#30#245#144'W='#255#184#134'o'#255#189#141'x'#255#189#141'x'#255#189#141'x'
+ +#255#189#141'x'#255#189#141'x'#255#189#141'x'#255#189#141'x'#255#189#141'x'
+ +#255#189#141'x'#255#189#141'x'#255#189#141'x'#255'tWJ'#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'('#30#26#255
+ +#189#141'x'#255#189#141'x'#255'?/('#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#187#139'v'#255#189#141
+ +'x'#255#189#141'x'#255#189#141'x'#255#189#141'x'#255#189#141'x'#255#172#128
+ +'m'#255'_G<'#255#1#0#0#255#0#0#0#255'-"'#28#255#189#141'x'#255#189#141'x'#255
+ +#189#141'x'#255#189#141'x'#255#189#141'x'#255#186#137's'#255#171'oU'#255'a6"'
+ +#253'T5$jUUU'#3#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'\/'
+ +#27#170'vD,'#252#181#128'h'#255#190#144'{'#255#192#146'~'#255#192#146'~'#255
+ +#192#146'~'#255#192#146'~'#255#192#146'~'#255#192#146'~'#255#192#146'~'#255
+ +#192#146'~'#255#192#146'~'#255#192#146'~'#255#186#142'z'#255#1#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#2#1#1#255#186#142'z'
+ +#255#192#146'~'#255#192#146'~'#255'=.('#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#192#146'~'#255#192
+ +#146'~'#255#192#146'~'#255#192#146'~'#255#192#146'~'#255#192#146'~'#255#192
+ +#146'~'#255#192#146'~'#255#0#0#0#255#0#0#0#255#167#127'n'#255#192#146'~'#255
+ +#192#146'~'#255#192#146'~'#255#192#146'~'#255#191#145'}'#255#186#137's'#255
+ +#149'[A'#255'^1'#31#250'F:.'#22#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0'\.'#28'H`5 '#252#164'jP'#255#190#143'z'#255#194#151#131
+ +#255#194#151#131#255#194#151#131#255#194#151#131#255#194#151#131#255#194#151
+ +#131#255#194#151#131#255#194#151#131#255#194#151#131#255#194#151#131#255#194
+ +#151#131#255#27#21#18#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255' '#25#21#255#194#151#131#255#194#151#131#255#194#151#131#255'7*%'
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#12#9#8#255#194#151#131#255#194#151#131#255#194#151#131#255#194#151
+ +#131#255#194#151#131#255#194#151#131#255#194#151#131#255#190#149#129#255#0#0
+ ,#0#255'0% '#255#194#151#131#255#194#151#131#255#194#151#131#255#194#151#131
+ +#255#194#151#131#255#192#147#127#255#180'~f'#255'q@+'#252'Z0'#29#180#0#0#0#2
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0']0'
+ +#28#199'{H2'#252#184#134'o'#255#196#153#134#255#197#156#137#255#197#156#137
+ +#255#197#156#137#255#197#156#137#255#197#156#137#255#197#156#137#255#197#156
+ +#137#255#197#156#137#255#197#156#137#255#197#156#137#255'G81'#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255'WE='#255#197#156#137#255#197
+ +#156#137#255#191#152#133#255#1#1#1#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#135'k^'#255#197#156#137#255#197
+ +#156#137#255#197#156#137#255#197#156#137#255#197#156#137#255#197#156#137#255
+ +#197#156#137#255#197#156#137#255#16#12#11#255#174#138'y'#255#197#156#137#255
+ +#197#156#137#255#197#156#137#255#197#156#137#255#197#155#136#255#191#145'|'
+ +#255#151'_F'#255'^3'#31#253'T2!-'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[0'#29'5_4 '#254#161'hP'#255#195#152#132
+ +#255#200#161#143#255#200#161#144#255#200#161#144#255#200#161#144#255#200#161
+ +#144#255#200#161#144#255#200#161#144#255#200#161#144#255#200#161#144#255#200
+ +#161#144#255'xaW'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1#1#1
+ +#255#171#138'{'#255#200#161#144#255#200#161#144#255#127'f\'#255#0#0#0#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255')!'#30#255
+ +#200#161#144#255#200#161#144#255#200#161#144#255#200#161#144#255#200#161#144
+ +#255#200#161#144#255#200#161#144#255#200#161#144#255#200#161#144#255#153'{n'
+ +#255#200#161#144#255#200#161#144#255#200#161#144#255#200#161#144#255#200#161
+ +#144#255#198#156#138#255#181#128'h'#255'l>*'#252'Z1'#30#159#0#0#0#1#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0'^0'#27#173'uE/'#249#186#136'r'#255#201#162#145#255#203#165#150#255#203#165
+ +#150#255#203#165#150#255#203#165#150#255#203#165#150#255#203#165#150#255#203
+ +#165#150#255#203#165#150#255#203#165#150#255#163#132'x'#255#0#0#0#255#0#0#0
+ +#255#26#21#19#255',$!'#255'-%!'#255#156'~s'#255#203#165#150#255#203#165#150
+ +#255#203#165#150#255'@4/'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#4#3#3#255#186#151#138#255#203#165#150#255#203#165
+ +#150#255#203#165#150#255#203#165#150#255#203#165#150#255#203#165#150#255#203
+ +#165#150#255#203#165#150#255#203#165#150#255#203#165#150#255#203#165#150#255
+ +#203#165#150#255#203#165#150#255#203#165#150#255#203#164#149#255#195#152#132
+ +#255#146'\D'#255'_3'#31#247'R3'#30#25#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'Z-'#30'"^4 '#252#155
+ +'cK'#255#196#153#136#255#206#169#155#255#207#171#156#255#207#171#156#255#207
+ +#171#156#255#207#171#156#255#207#171#156#255#207#171#156#255#207#171#156#255
+ +#207#171#156#255#203#167#152#255#0#0#0#255#0#0#0#255#193#159#145#255#207#171
+ +#156#255#207#171#156#255#207#171#156#255#207#171#156#255#207#171#156#255#207
+ +#171#156#255'E94'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#15#12#11#255#182#150#137#255#207#171#156#255#207#171#156#255#207#171#156
+ +#255#207#171#156#255#207#171#156#255#207#171#156#255#207#171#156#255#207#171
+ +#156#255#207#171#156#255#207#171#156#255#207#171#156#255#207#171#156#255#207
+ +#171#156#255#207#171#156#255#206#170#155#255#201#162#145#255#178'}f'#255'h<('
+ +#250'[0'#28#129#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0']1'#29#130'f:&'#250#171'u'
+ +'^'#255#202#164#148#255#210#176#163#255#210#177#164#255#210#177#164#255#210
+ +#177#164#255#210#177#164#255#210#177#164#255#210#177#164#255#210#177#164#255
+ +#210#177#164#255#2#1#1#255#27#22#21#255#210#177#164#255#210#177#164#255#210
+ +#177#164#255#210#177#164#255#210#177#164#255#210#177#164#255#210#177#164#255
+ +#210#177#164#255'I=8'#255#6#5#4#255#0#0#0#255#0#0#0#255#0#0#0#255'''!'#31#255
+ +#206#175#162#255#210#177#164#255#210#177#164#255#210#177#164#255#210#177#164
+ +#255#210#177#164#255#210#177#164#255#210#177#164#255#210#177#164#255#210#177
+ +#164#255#210#177#164#255#210#177#164#255#210#177#164#255#210#177#164#255#210
+ +#177#164#255#210#176#163#255#206#170#155#255#188#139'w'#255'zI4'#252'^2'#29
+ +#222']/'#23#11#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'^1'#29#181'oA-'
+ +#249#182#132'n'#255#208#173#159#255#213#182#169#255#213#183#170#255#213#183
+ +#170#255#213#183#170#255#213#183#170#255#213#183#170#255#213#183#170#255#213
+ +#183#170#255#12#10#9#255#159#136#127#255#213#183#170#255#213#183#170#255#213
+ +#183#170#255#213#183#170#255#213#183#170#255#213#183#170#255#213#183#170#255
+ +#213#183#170#255#213#183#170#255#139'xo'#255#0#0#0#255#0#0#0#255'% '#30#255
+ +#213#183#170#255#213#183#170#255#213#183#170#255#213#183#170#255#213#183#170
+ +#255#213#183#170#255#213#183#170#255#213#183#170#255#213#183#170#255#213#183
+ ,#170#255#213#183#170#255#213#183#170#255#213#183#170#255#213#183#170#255#213
+ +#183#170#255#213#183#170#255#211#178#165#255#196#152#134#255#136'T?'#254'`1 '
+ +#243'U+'#28'$'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'U+'#21#12
+ +']2'#30#218'zK5'#251#192#146#127#255#212#180#168#255#216#187#176#255#217#188
+ +#177#255#217#188#177#255#217#188#177#255#217#188#177#255#217#188#177#255#217
+ +#188#177#255'o`Z'#255#217#188#177#255#217#188#177#255#217#188#177#255#217#188
+ +#177#255#217#188#177#255#217#188#177#255#217#188#177#255#217#188#177#255#217
+ +#188#177#255#217#188#177#255#27#24#22#255#0#0#0#255#9#8#7#255#209#180#171#255
+ +#217#188#177#255#217#188#177#255#217#188#177#255#217#188#177#255#217#188#177
+ +#255#217#188#177#255#217#188#177#255#217#188#177#255#217#188#177#255#217#188
+ +#177#255#217#188#177#255#217#188#177#255#217#188#177#255#217#188#177#255#217
+ +#188#177#255#215#185#173#255#202#163#147#255#152'cM'#255'`5 '#252'X.'#27'B'#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'].'#23'!_'
+ +'3 '#241#135'V@'#254#197#155#137#255#215#185#173#255#219#193#183#255#220#194
+ +#184#255#220#194#184#255#220#194#184#255#220#194#184#255#220#194#184#255#220
+ +#194#184#255#220#194#184#255#220#194#184#255#220#194#184#255#220#194#184#255
+ +#220#194#184#255#220#194#184#255#220#194#184#255#220#194#184#255#220#194#184
+ +#255#220#194#184#255#4#4#4#255#13#11#11#255#197#173#164#255#220#194#184#255
+ +#220#194#184#255#220#194#184#255#220#194#184#255#220#194#184#255#220#194#184
+ +#255#220#194#184#255#220#194#184#255#220#194#184#255#220#194#184#255#220#194
+ +#184#255#220#194#184#255#220#194#184#255#220#194#184#255#220#194#183#255#218
+ +#190#179#255#205#169#154#255#165'pY'#255'b8$'#252'[/'#27'h'#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'Y1'#28'?_'
+ +'3!'#249#132'T?'#252#193#148#130#255#215#186#174#255#223#198#189#255#223#200
+ +#191#255#223#200#191#255#223#200#191#255#223#200#191#255#223#200#191#255#223
+ +#200#191#255#223#200#191#255#223#200#191#255#223#200#191#255#223#200#191#255
+ +#223#200#191#255#223#200#191#255#223#200#191#255#223#200#191#255#223#200#191
+ +#255#199#179#171#255#215#192#183#255#223#200#191#255#223#200#191#255#223#200
+ +#191#255#223#200#191#255#223#200#191#255#223#200#191#255#223#200#191#255#223
+ +#200#191#255#223#200#191#255#223#200#191#255#223#200#191#255#223#200#191#255
+ +#223#200#191#255#223#200#191#255#223#199#190#255#219#192#183#255#203#165#150
+ +#255#158'kS'#255'c9%'#251']0'#30#147#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'Z-'#25'3_3'#30
+ +#234'wI5'#250#185#138'v'#255#215#186#174#255#225#203#194#255#227#205#197#255
+ +#227#205#197#255#227#205#197#255#227#205#197#255#227#205#197#255#227#205#197
+ +#255#227#205#197#255#227#205#197#255#227#205#197#255#227#205#197#255#227#205
+ +#197#255#227#205#197#255#227#205#197#255#227#205#197#255#227#205#197#255#227
+ +#205#197#255#227#205#197#255#227#205#197#255#227#205#197#255#227#205#197#255
+ +#227#205#197#255#227#205#197#255#227#205#197#255#227#205#197#255#227#205#197
+ +#255#227#205#197#255#227#205#197#255#227#205#197#255#227#205#197#255#226#204
+ +#196#255#220#194#183#255#200#159#143#255#144'_H'#254'a6"'#253'\1'#30'y'#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'\3'#31#25'^2'#29#207'nB.'#249#175'~i'#255
+ +#213#182#169#255#225#202#193#255#230#209#203#255#230#211#205#255#230#211#205
+ +#255#230#211#205#255#230#211#205#255#230#211#205#255#230#211#205#255#230#211
+ +#205#255#230#211#205#255#230#211#205#255#230#211#205#255#230#211#205#255#230
+ +#211#205#255#230#211#205#255#230#211#205#255#230#211#205#255#230#211#205#255
+ +#230#211#205#255#230#211#205#255#230#211#205#255#230#211#205#255#230#211#205
+ +#255#230#211#205#255#230#211#205#255#230#211#205#255#230#211#205#255#230#210
+ +#204#255#227#205#198#255#219#191#181#255#193#149#131#255#131'R='#251'_4 '#247
+ +'Z0'#26'O'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'` '#8']0'
+ +#28#169'e:'''#250#148'aL'#255#196#153#136#255#220#193#183#255#229#209#202#255
+ +#233#216#210#255#234#216#211#255#234#216#211#255#234#216#211#255#234#216#211
+ +#255#234#216#211#255#234#216#211#255#234#216#211#255#234#216#211#255#234#216
+ +#211#255#234#216#211#255#234#216#211#255#234#216#211#255#234#216#211#255#234
+ +#216#211#255#234#216#211#255#234#216#211#255#234#216#211#255#234#216#211#255
+ +#234#216#211#255#234#216#211#255#234#216#211#255#233#216#211#255#231#212#206
+ ,#255#224#200#192#255#207#171#156#255#168'va'#255'rE1'#249'^3'#31#230'Y,'#28
+ +'.'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0'^1'#29'h`3'#31#237'nA/'#249#158'mW'#255#203#165#150#255#224#201#192
+ +#255#232#213#208#255#235#219#215#255#237#222#218#255#237#222#218#255#237#222
+ +#218#255#237#222#218#255#237#222#218#255#237#222#218#255#237#222#218#255#237
+ +#222#218#255#237#222#218#255#237#222#218#255#237#222#218#255#237#222#218#255
+ +#237#222#218#255#237#222#218#255#237#222#218#255#237#222#218#255#237#222#218
+ +#255#236#220#216#255#233#216#211#255#228#206#200#255#213#182#170#255#177#131
+ +'n'#255'}M:'#250'a6"'#253']1'#29#155'U1'#24#21#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'].'#23#11
+ +']1'#29'~`5!'#246'tF5'#249#166'u`'#255#202#164#148#255#221#195#186#255#230
+ +#210#203#255#234#218#213#255#238#224#220#255#240#227#224#255#240#227#225#255
+ +#240#227#225#255#240#227#225#255#240#227#225#255#240#227#225#255#240#227#225
+ +#255#240#227#225#255#240#227#225#255#240#227#225#255#240#227#225#255#239#225
+ +#222#255#236#220#215#255#232#213#207#255#225#203#194#255#210#176#164#255#183
+ +#138'u'#255#133'UA'#252'c9&'#254'^2'#30#178'\.'#26''''#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'U1'#24#21']0'#30#147'`7"'#251'jA-'#249#133'UA'
+ +#253#169'zf'#255#201#162#146#255#220#194#184#255#230#211#205#255#233#215#210
+ +#255#234#217#212#255#236#220#215#255#237#222#218#255#238#223#220#255#237#222
+ +#219#255#236#220#216#255#234#219#213#255#233#216#211#255#231#213#206#255#225
+ +#203#194#255#209#174#160#255#181#136'u'#255#145'`L'#255'sG4'#249'c9&'#255'_2'
+ +#30#198'].'#28'7'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0'U+'#28#18'\.'#27'^_1'#30#179'c7$'#248'h?,'#251#127
+ +'Q;'#251#148'dN'#255#163't_'#255#175#129'n'#255#186#143'~'#255#198#157#141
+ +#255#204#167#151#255#201#161#145#255#191#149#132#255#179#135'u'#255#167'ye'
+ +#255#153'iT'#255#136'WC'#254'pE2'#249'c9&'#255'_3'#31#212'Z/'#27'|].'#29','#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'U9'#28#9'\.'#26'N^0'#29#157'`'
+ +'4 '#203'c6#'#230'c7%'#249'd:('#255'f=*'#255'i?-'#252'g>+'#255'e;('#255'd9&'
+ +#253'b7$'#237'a5!'#214'_1'#30#180'\/'#26'lX,'#26#29#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0'`0 '#16'[1'#24'*].'#27'B]1'#29'4\3'#31#25'UU'#0#3#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#255#255#255#248#15#255
+ +#255#255#255#255#254#0#0#127#255#255#255#255#240#0#0#7#255#255#255#255#192#0
+ +#0#1#255#255#255#255#0#0#0#0#255#255#255#252#0#0#0#0'?'#255#255#248#0#0#0#0
+ +#31#255#255#240#0#0#0#0#7#255#255#192#0#0#0#0#3#255#255#128#0#0#0#0#1#255#255
+ +#128#0#0#0#0#0#255#255#0#0#0#0#0#0#127#254#0#0#0#0#0#0#127#252#0#0#0#0#0#0'?'
+ +#252#0#0#0#0#0#0#31#248#0#0#0#0#0#0#31#248#0#0#0#0#0#0#15#240#0#0#0#0#0#0#15
+ ,#240#0#0#0#0#0#0#7#224#0#0#0#0#0#0#7#224#0#0#0#0#0#0#7#224#0#0#0#0#0#0#3#192
+ +#0#0#0#0#0#0#3#192#0#0#0#0#0#0#3#192#0#0#0#0#0#0#1#192#0#0#0#0#0#0#1#192#0#0
+ +#0#0#0#0#1#128#0#0#0#0#0#0#1#128#0#0#0#0#0#0#1#128#0#0#0#0#0#0#1#128#0#0#0#0
+ +#0#0#1#128#0#0#0#0#0#0#1#128#0#0#0#0#0#0#1#192#0#0#0#0#0#0#1#192#0#0#0#0#0#0
+ +#1#192#0#0#0#0#0#0#1#192#0#0#0#0#0#0#1#192#0#0#0#0#0#0#3#192#0#0#0#0#0#0#3
+ +#224#0#0#0#0#0#0#3#224#0#0#0#0#0#0#7#224#0#0#0#0#0#0#7#224#0#0#0#0#0#0#7#240
+ +#0#0#0#0#0#0#15#240#0#0#0#0#0#0#15#248#0#0#0#0#0#0#31#248#0#0#0#0#0#0#31#252
+ +#0#0#0#0#0#0'?'#252#0#0#0#0#0#0#127#254#0#0#0#0#0#0#127#254#0#0#0#0#0#0#255
+ +#255#0#0#0#0#0#1#255#255#128#0#0#0#0#3#255#255#192#0#0#0#0#7#255#255#224#0#0
+ +#0#0#15#255#255#240#0#0#0#0#31#255#255#248#0#0#0#0'?'#255#255#254#0#0#0#0#127
+ +#255#255#255#0#0#0#1#255#255#255#255#192#0#0#7#255#255#255#255#240#0#0#31#255
+ +#255#255#255#254#0#0#255#255#255#255#255#255#248#31#255#255#255#255#255#255
+ +#255#255#255#255#255'('#0#0#0'0'#0#0#0'`'#0#0#0#1#0' '#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0'UUU'#3'333'#5'UUU'#6'III'#7'@@@'#8'@@@'#8'III'#7
+ +'UUU'#6'333'#5'UUU'#3#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'@@@'
+ +#4'@@@'#8'@@@'#16'DDD1BBBMCCC_FCCrDBB'#129'FDD'#133'CCCvCCCcDDDRDDD('#240'l@!'#252'qE!'
+ +#253'yJ$'#252#129'R&'#252#138'X)'#253#134'T('#253'}N%'#252'uG#'#252'oC"'#253
+ +'h=#'#248'Z>.'#230'OC;'#211'FEC'#198'DDC'#187'BBB|CCC&999'#9#0#0#0#1#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#2'<<<'#17'CCCWEED'#170'OB9'#211'd=&'#244'qE"'#253#137'V)'#253
+ +#164'h.'#255#186'y3'#255#194#130'5'#255#198#135'6'#255#203#140'7'#255#207#145
+ +'8'#255#205#143'7'#255#201#137'7'#255#196#132'6'#255#192#127'5'#255#177'r1'
+ +#255#152'_+'#254'{L%'#252'k?"'#251'[>-'#233'IEA'#203'EDD'#184'DDDq<<<'#30'@@'
+ +'@'#4#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0'@@@'#4'BBB#EDD'#146'KB<'#205'a='''#242'yK&'#252#166'i/'#255#192#128'6'
+ +#255#205#143'9'#255#217#159'<'#255#226#169'>'#255#230#173'>'#255#232#176'>'
+ +#255#235#180'?'#255#237#182'@'#255#236#181'?'#255#234#178'>'#255#231#175'>'
+ +#255#228#171'>'#255#223#165'<'#255#211#150':'#255#199#136'8'#255#182'v5'#255
+ +#146'\,'#253'k@"'#252'W?1'#227'GFE'#199'CCC'#171'???=@@@'#8#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'III'#7'DDD8ECB'#170'[>,'#234'sF$'
+ +#252#160'e0'#255#196#133';'#255#216#158'@'#255#227#170'A'#255#234#180'C'#255
+ +#241#189'D'#255#245#193'E'#255#246#195'F'#255#247#195'F'#255#247#196'E'#255
+ +#248#197'F'#255#248#197'E'#255#247#195'F'#255#247#194'F'#255#246#194'E'#255
+ +#244#192'E'#255#238#184'C'#255#230#176'C'#255#223#166'A'#255#207#147'='#255
+ +#182'w7'#255#138'V+'#253'h>#'#250'NA9'#215'CCC'#186'@@@[;;;'#13#0#0#0#1#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'@@@'#8'EEENGC?'#189'b;%'#245#139'W-'#253#190
+ +#127';'#255#212#153'B'#255#227#172'F'#255#239#186'I'#255#242#191'J'#255#244
+ +#193'K'#255#246#195'K'#255#247#196'K'#255#247#196'K'#255#247#196'L'#255#247
+ +#196'L'#255#247#196'L'#255#247#196'L'#255#247#196'L'#255#247#196'K'#255#247
+ +#196'K'#255#246#196'K'#255#245#195'J'#255#243#193'J'#255#242#190'J'#255#234
+ +#180'H'#255#221#165'E'#255#202#142'@'#255#173'o5'#255'oC$'#252'T?3'#225'CCC'
+ +#193'AAAy@@@'#16#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'+++'#6'DDD@K@<'#198'g<"'#250#154
+ +'a2'#254#200#141'B'#255#222#168'J'#255#234#183'N'#255#239#189'P'#255#242#192
+ +'P'#255#242#193'P'#255#243#193'P'#255#243#193'P'#255#243#193'P'#255#243#193
+ +'P'#255#243#193'P'#255#243#193'P'#255#243#193'P'#255#243#193'P'#255#243#193
+ ,'P'#255#243#193'P'#255#243#193'P'#255#243#193'P'#255#243#193'P'#255#242#193
+ +'P'#255#242#193'P'#255#241#191'P'#255#238#187'N'#255#229#176'L'#255#214#158
+ +'G'#255#183'y;'#255'yJ)'#252'[=,'#236'CCB'#195'EEEoFFF'#11#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'UUU'#3
+ +'CCC.J?;'#190'g=#'#252#167'k7'#255#205#147'H'#255#226#173'P'#255#235#186'T'
+ +#255#238#189'T'#255#239#190'U'#255#239#190'U'#255#239#190'U'#255#239#190'U'
+ +#255#239#190'U'#255#239#190'U'#255#191#152'D'#255'A4'#23#255'>1'#22#255'D6'
+ +#24#255'H9'#26#255'RA'#29#255#146's4'#255#228#182'Q'#255#239#190'U'#255#239
+ +#190'U'#255#239#190'U'#255#239#190'U'#255#239#190'U'#255#238#190'U'#255#237
+ +#187'T'#255#232#182'S'#255#217#162'M'#255#191#129'B'#255#132'R-'#253'[9('#240
+ +'DDD'#191'CCCW@@@'#8#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#1'>>>'#29'F@='#169'd9#'#250#165'i8'#255#208#151'L'#255
+ +#226#174'U'#255#233#184'Y'#255#235#186'Y'#255#235#187'Y'#255#235#187'Y'#255
+ +#235#187'Y'#255#235#187'Y'#255#235#187'Y'#255#235#187'Y'#255'<0'#23#255#1#1#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1#1#0#255#0#0#0#255#6
+ +#5#2#255'*!'#16#255'w^-'#255#227#181'W'#255#235#187'Y'#255#235#187'Y'#255#235
+ +#186'Y'#255#234#186'Y'#255#231#181'X'#255#218#164'Q'#255#194#133'E'#255'{J*'
+ +#252'U=/'#230'CCC'#186'EEE?@@@'#4#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0'333'#10'DAAw_9%'#244#150'^4'#254#204#148'N'#255#225#175
+ +'Y'#255#230#181'\'#255#231#183'\'#255#231#183'\'#255#231#183'\'#255#231#183
+ +'\'#255#231#183'\'#255#231#183'\'#255#231#183'\'#255'hR*'#255#1#1#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#1#1#0#255#1#1#0#255'*!'#17#255#164#130'B'#255#231#183'\'
+ +#255#231#183'\'#255#231#182']'#255#228#179'['#255#217#165'V'#255#185'|C'#255
+ +'nA'''#252'N>5'#219'CCC'#163'@@@'#20#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#128#128#128#2'@@@,W8*'#227#132'P/'#253#196#139'M'#255#220
+ +#170'['#255#226#179'_'#255#227#179'_'#255#227#179'_'#255#227#179'_'#255#227
+ +#179'_'#255#227#179'_'#255#227#179'_'#255#227#179'_'#255#227#179'_'#255#4#3#2
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1#1#0
+ +#255#7#6#3#255#178#141'J'#255#227#179'_'#255#227#179'_'#255#225#176'^'#255
+ +#211#158'U'#255#174'q?'#255'c9"'#252'GA>'#203'BBB]III'#7#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0'FFF'#11'H>:'#150'e:#'#252#186'~H'#255#214#164'\'
+ +#255#222#174'a'#255#223#175'b'#255#223#175'b'#255#223#175'b'#255#223#175'b'
+ +#255#223#175'b'#255#223#175'b'#255#223#175'b'#255#223#175'b'#255#188#148'S'
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#1#1#1#255#154'yC'#255#223#175'b'#255#223#175'a'#255
+ +#220#171'`'#255#204#150'U'#255#145'Y5'#254'Y8('#238'CCC'#175'FFF'#29#0#0#0#1
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'UUU'#3'AAA3Z7'''#236#148'\6'#255#207#154'Z'
+ +#255#218#170'b'#255#219#171'd'#255#219#171'd'#255#219#171'd'#255#219#171'd'
+ +#255#219#171'd'#255#219#171'd'#255#219#171'd'#255#219#171'd'#255#219#171'd'
+ +#255#211#165'`'#255#6#5#3#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#2#2#1#255#219#171'd'#255#219
+ +#171'd'#255#219#171'd'#255#215#166'`'#255#189#129'M'#255'h=$'#252'H>;'#207'E'
+ +'EEhIII'#7#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'III'#7'K<5'#137'h;$'#252#188#130
+ +'O'#255#213#164'b'#255#215#167'd'#255#215#167'd'#255#215#167'd'#255#215#167
+ +'d'#255#215#167'd'#255#215#167'd'#255#215#167'd'#255#215#167'd'#255#215#167
+ +'d'#255#215#167'd'#255#215#167'd'#255#168#130'N'#255#1#1#1#255#0#0#0#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#200#155']'#255#215#167'd'#255#215#167'd'#255#215#166'd'#255#205#153']'
+ +#255#153'`:'#255'[6$'#243'CCC'#164';;;'#13#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'7'
+ +'77'#14'Z5%'#229#150'[8'#255#203#150'^'#255#211#162'e'#255#211#162'e'#255#211
+ +#162'e'#255#211#162'e'#255#211#162'e'#255#211#162'e'#255#211#162'e'#255#211
+ +#162'e'#255#211#162'e'#255#211#162'e'#255#211#162'e'#255#211#162'e'#255#211
+ +#162'e'#255#142'mD'#255#1#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#1#1#0#255#145'pF'#255#211#162'e'#255#211#162
+ +'e'#255#211#162'e'#255#210#159'd'#255#189#131'R'#255'f9#'#252'I@;'#202'===.'
+ +#128#128#128#2#0#0#0#0#0#0#0#0#128#128#128#2'D??4]3'#30#252#181'yM'#255#206
+ +#155'd'#255#207#157'f'#255#207#157'f'#255#207#157'f'#255#207#157'f'#255#205
+ +#155'f'#255'S?('#255#1#1#1#255#1#0#0#255#3#2#1#255#15#11#7#255#169#128'S'#255
+ ,#207#157'f'#255#207#157'f'#255#207#157'f'#255#16#12#8#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1#0#0#255#186#141'\'
+ +#255#207#157'f'#255#207#157'f'#255#207#157'f'#255#207#157'e'#255#201#148'`'
+ +#255#135'O0'#254'R9-'#226'BBBeIII'#7#0#0#0#0#0#0#0#0'UUU'#6'O8/'#141'o>'''
+ +#251#193#139'['#255#203#151'e'#255#203#152'e'#255#203#152'e'#255#203#152'e'
+ +#255#203#152'e'#255#23#17#11#255#1#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0
+ +#0#255#1#1#1#255#153'rL'#255#203#152'e'#255#203#152'e'#255',!'#22#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1#0#0#255' '#24#16
+ +#255#203#152'e'#255#203#152'e'#255#203#152'e'#255#203#152'e'#255#203#152'e'
+ +#255#202#150'd'#255#165'jC'#255'\3!'#247'DDD'#151'MMM'#10#0#0#0#0#0#0#0#0'@@'
+ +'@'#8'Z6%'#206#142'T5'#255#195#142'a'#255#198#145'c'#255#198#145'c'#255#198
+ +#145'c'#255#198#145'c'#255'W@,'#255#1#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255'%'#27#19#255#198#145'c'#255#198#145'c'#255'U>+'
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1#0#0#255#1#1#1#255#27#20#13#255'vW;'
+ +#255#198#145'c'#255#198#145'c'#255#198#145'c'#255#198#145'c'#255#198#145'c'
+ +#255#198#145'c'#255#198#145'c'#255#184'}S'#255'`4 '#252'FA>'#183'@@@'#12#0#0
+ +#0#0#0#0#0#0'999'#9']2'#30#243#166'gD'#255#192#138'`'#255#192#139'a'#255#192
+ +#139'a'#255#192#139'a'#255#190#137'a'#255#1#1#1#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#8#6#4#255#192#139'a'#255#192#139
+ +'a'#255#129']B'#255#1#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1#0#0#255'Q;)'#255#192#139'a'
+ +#255#192#139'a'#255#192#139'a'#255#192#139'a'#255#192#139'a'#255#192#139'a'
+ +#255#192#139'a'#255#192#139'a'#255#192#139'a'#255#192#139'a'#255#188#132'['
+ +#255'u@'''#252'M;3'#212'999'#18#0#0#0#0#0#0#0#0'FFF'#11'^1'#29#250#174'oK'
+ +#255#186#131'\'#255#186#131'\'#255#186#131'\'#255#186#131'\'#255'vS:'#255#1#1
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1#0#0#255
+ +'S:)'#255#186#131'\'#255#186#131'\'#255#184#129'\'#255'('#28#20#255#1#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255'Q9('#255#186#131'\'#255#186#131'\'#255#186#131'\'#255#186#131'\'#255#186
+ +#131'\'#255#186#131'\'#255#186#131'\'#255#186#131'\'#255#186#131'\'#255#186
+ +#131'\'#255#186#131'\'#255#186#130'['#255#131'I-'#255'Q9-'#221'FFF!'#0#0#0#1
+ +#0#0#0#0'M33'#20'_2'#30#251#173'pN'#255#180'{X'#255#180'{X'#255#180'{X'#255
+ +#180'{X'#255'-'#30#22#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#2#1#1#255'dE1'#255#180'{X'#255#180'{X'#255#180'{X'#255#180'{X'#255
+ +#180'{X'#255'O6&'#255#2#1#1#255#1#1#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255'G0#'#255#180'{X'#255#180'{X'#255#178'{X'#255'hH3'#255'U:)'#255
+ +'mK5'#255#180'{X'#255#180'{X'#255#180'{X'#255#180'{X'#255#180'{X'#255#180'{X'
+ +#255#180'{X'#255#139'P3'#255'U7)'#231'BBB2UUU'#3#0#0#0#0'T1&,c5 '#249#174'rQ'
+ +#255#178'wW'#255#178'wW'#255#178'wW'#255#178'wW'#255#8#5#4#255#0#0#0#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#1#0#0#255#27#18#13#255#164'nQ'#255#178'wW'#255#178
+ +'wW'#255#178'wW'#255#178'wW'#255#178'wW'#255#178'wW'#255#178'wW'#255#178'wW'
+ +#255#142'_F'#255'H0#'#255#20#13#10#255#25#16#12#255'9'''#28#255'lI5'#255#178
+ +'wW'#255#178'wW'#255'kG4'#255#1#1#1#255#1#1#0#255#1#0#0#255#1#0#0#255#3#2#1
+ +#255'zQ<'#255#178'wW'#255#178'wW'#255#178'wW'#255#178'wW'#255#178'wW'#255#149
+ +'W9'#255'Z5%'#238'DDD-'#128#128#128#2#0#0#0#0'Y3 Bj8#'#248#173'qS'#255#175't'
+ +'W'#255#175'tW'#255#175'tW'#255#175'tW'#255#1#0#0#255#1#1#1#255#0#0#0#255#0#0
+ +#0#255#5#3#3#255'cB2'#255#175'tW'#255#175'tW'#255#175'tW'#255#175'tW'#255#175
+ +'tW'#255#175'tW'#255#175'tW'#255#175'tW'#255#175'tW'#255#175'tW'#255#175'tW'
+ +#255#175'tW'#255#175'tW'#255#175'tW'#255#175'tW'#255#175'tW'#255#175'tW'#255
+ +#173'rU'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#2#1
+ +#1#255#152'eL'#255#175'tW'#255#175'tW'#255#175'tW'#255#175'tW'#255#155'[>'
+ +#255'\4"'#244'@@@'#28#0#0#0#1#0#0#0#0'X0!3g7"'#246#172'oR'#255#174'rV'#255
+ +#174'rV'#255#174'rV'#255#166'lR'#255#7#5#3#255#131'VA'#255#155'fM'#255'oI7'
+ +#255#174'rV'#255#174'rV'#255#174'rV'#255#174'rV'#255#174'rV'#255#174'rV'#255
+ +#174'rV'#255#174'rV'#255#174'rV'#255#174'rV'#255#174'rV'#255#174'rV'#255#174
+ +'rV'#255#174'rV'#255#174'rV'#255#174'rV'#255#174'rV'#255#174'rV'#255#174'rV'
+ +#255#153'dL'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255'<'''#29#255#174'rV'#255#174'rV'#255#174'rV'#255#173'qU'#255#151'Y'
+ +'='#255']6%'#239'333'#15#0#0#0#0#0#0#0#0'O1'''#25'b3'#31#247#168'jN'#255#172
+ +'oU'#255#172'oU'#255#172'oU'#255#172'oU'#255#172'oU'#255#172'oU'#255#172'oU'
+ +#255#172'oU'#255#172'oU'#255#172'oU'#255#172'oU'#255#172'oU'#255#136'XD'#255
+ ,'U7*'#255'^=/'#255'kE5'#255#170'oU'#255#172'oU'#255#172'oU'#255#172'oU'#255
+ +#172'oU'#255#172'oU'#255#172'oU'#255#172'oU'#255#172'oU'#255#172'oU'#255#172
+ +'oU'#255#172'oU'#255#5#3#2#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255'!'#21#16#255#172'oU'#255#172'oU'#255#172'oU'#255#172'oT'#255
+ +#143'R7'#255'Y6('#225'@@@'#12#0#0#0#0#0#0#0#0'333'#5'_2'#31#248#167'hL'#255
+ +#172'qW'#255#172'qX'#255#172'qX'#255#172'qX'#255#172'qX'#255#172'qX'#255#172
+ +'qX'#255#172'qX'#255#172'qX'#255#172'qX'#255#172'qX'#255':&'#30#255#1#0#0#255
+ +#1#1#0#255#1#1#1#255#1#1#0#255#4#2#2#255#133'WD'#255#172'qX'#255#172'qX'#255
+ +#172'qX'#255#172'qX'#255#172'qX'#255#172'qX'#255#172'qX'#255#172'qX'#255#172
+ +'qX'#255#172'qX'#255'E.$'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#30#20#15#255#172'qX'#255#172'qX'#255#172'qX'#255#172'pV'#255
+ +#134'K2'#255'V8)'#199'999'#9#0#0#0#0#0#0#0#0#0#0#0#1'_3'#30#239#164'fJ'#255
+ +#175'w]'#255#175'w^'#255#175'w^'#255#175'w^'#255#175'w^'#255#175'w^'#255#175
+ +'w^'#255#175'w^'#255#175'w^'#255#175'w^'#255'hF7'#255#1#0#0#255#0#0#0#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#7#5#4#255#175'w^'#255#175'w^'#255'{TB'
+ +#255'X;/'#255']?2'#255#127'VD'#255#175'w^'#255#175'w^'#255#175'w^'#255#175'w'
+ +'^'#255#165'qY'#255#1#1#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1#1#1
+ +#255'fF7'#255#175'w^'#255#175'w^'#255#175'w^'#255#175'v\'#255'{D-'#253'S5('
+ +#154'333'#5#0#0#0#0#0#0#0#0#0#0#0#0'a3'#30#200#149'Z?'#255#179'|c'#255#179'}'
+ +'e'#255#179'}e'#255#179'}e'#255#179'}e'#255#179'}e'#255#179'}e'#255#179'}e'
+ +#255#179'}e'#255#179'}e'#255#19#13#11#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#2#1#1#255#179'}e'#255'E0'''#255#1#0#0#255#1#1#0#255
+ +#1#1#0#255#0#0#0#255'R:/'#255#179'}e'#255#179'}e'#255#179'}e'#255#179'}e'#255
+ +'.!'#26#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1#1#1#255#177'}e'#255#179
+ +'}e'#255#179'}e'#255#179'}e'#255#175'v\'#255'g8$'#251'W7*O'#0#0#0#1#0#0#0#0#0
+ +#0#0#0#0#0#0#0'[0'#29'lyD-'#249#181#128'i'#255#183#131'l'#255#183#131'l'#255
+ +#183#131'l'#255#183#131'l'#255#183#131'l'#255#183#131'l'#255#183#131'l'#255
+ +#183#131'l'#255#183#131'l'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255'"'#25#20#255#183#131'l'#255#0#0#0#255#0#0#0#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255'B/'''#255#183#131'l'#255#183#131'l'#255
+ +#183#131'l'#255#169'yd'#255#1#1#1#255#0#0#0#255#0#0#0#255#0#0#0#255'#'#25#21
+ +#255#183#131'l'#255#183#131'l'#255#183#131'l'#255#183#131'l'#255#167'lQ'#255
+ +'^3'#31#248'@@@'#12#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'Y1'#30#26'b5 '#244#178'z'
+ +'c'#255#187#138't'#255#187#138'u'#255#187#138'u'#255#187#138'u'#255#187#138
+ +'u'#255#187#138'u'#255#187#138'u'#255#187#138'u'#255#187#138'u'#255#2#2#1#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1#1#0#255#170'~j'#255#177
+ +#130'o'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#4#3#3
+ +#255#187#138'u'#255#187#138'u'#255#187#138'u'#255#187#138'u'#255'jNB'#255#11
+ +#8#7#255#0#0#0#255#0#0#0#255#152'p`'#255#187#138'u'#255#187#138'u'#255#187
+ +#138'u'#255#186#136'r'#255#144'W?'#255']6#'#193'333'#5#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0'`4'#31#217#160'gN'#255#190#143'{'#255#191#145'}'#255#191
+ +#145'}'#255#191#145'}'#255#191#145'}'#255#191#145'}'#255#191#145'}'#255#191
+ +#145'}'#255#191#145'}'#255#19#14#12#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255'7*$'#255#191#145'}'#255#164'|k'#255#1#1#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#2#2#1#255#191#145'}'#255#191#145'}'#255
+ +#191#145'}'#255#191#145'}'#255#191#145'}'#255#191#145'}'#255#0#0#0#255#30#23
+ +#20#255#191#145'}'#255#191#145'}'#255#191#145'}'#255#191#145'}'#255#187#138
+ +'t'#255'p>('#249'Y2#U'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27
+ +'huB+'#244#190#142'z'#255#195#152#132#255#195#152#132#255#195#152#132#255#195
+ +#152#132#255#195#152#132#255#195#152#132#255#195#152#132#255#195#152#132#255
+ +'A3,'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1#0#0#255#183#142'|'#255
+ +#195#152#132#255#138'k]'#255#1#1#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#9#7#6#255#195#152#132#255#195#152#132#255#195#152#132#255#195
+ +#152#132#255#195#152#132#255#195#152#132#255#1#1#1#255#160'}m'#255#195#152
+ +#132#255#195#152#132#255#195#152#132#255#194#150#131#255#167'pW'#255'`4 '#240
+ +'M33'#10#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'@@'#0#4'`3'#30#229
+ +#164'nU'#255#197#156#137#255#199#159#141#255#199#159#141#255#199#159#141#255
+ +#199#159#141#255#199#159#141#255#199#159#141#255#199#159#141#255'x`U'#255#1#1
+ +#1#255#0#0#0#255#0#0#0#255#0#0#0#255#18#14#13#255#199#159#141#255#199#159#141
+ +#255' '#26#23#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1#1#0#255
+ +#139'oc'#255#199#159#141#255#199#159#141#255#199#159#141#255#199#159#141#255
+ +#199#159#141#255#199#159#141#255'^KC'#255#199#159#141#255#199#159#141#255#199
+ +#159#141#255#199#159#141#255#192#147#127#255'rB-'#249'\1 k'#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'\.'#28'Sn>('#243#194#149#131
+ ,#255#202#165#148#255#203#165#149#255#203#165#149#255#203#165#149#255#203#165
+ +#149#255#203#165#149#255#203#165#149#255#169#138'|'#255#0#0#0#255#1#1#1#255
+ +#16#13#11#255#23#19#17#255#171#139'~'#255#203#165#149#255#203#165#149#255#3#3
+ +#2#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1#0#0#255'*"'#31#255#203#165
+ +#149#255#203#165#149#255#203#165#149#255#203#165#149#255#203#165#149#255#203
+ +#165#149#255#203#165#149#255#203#165#149#255#203#165#149#255#203#165#149#255
+ +#203#165#149#255#201#162#145#255#163'mU'#255'_3'#31#227'U'#0#0#3#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'a3'#30#213#153
+ +'eM'#254#204#167#151#255#207#172#158#255#207#172#158#255#207#172#158#255#207
+ +#172#158#255#207#172#158#255#207#172#158#255#205#170#156#255#0#0#0#255'<1.'
+ +#255#207#172#158#255#207#172#158#255#207#172#158#255#207#172#158#255#207#172
+ +#158#255#20#16#15#255#1#0#0#255#0#0#0#255#0#0#0#255#1#0#0#255'?40'#255#207
+ +#172#158#255#207#172#158#255#207#172#158#255#207#172#158#255#207#172#158#255
+ +#207#172#158#255#207#172#158#255#207#172#158#255#207#172#158#255#207#172#158
+ +#255#207#172#158#255#207#171#156#255#192#147#127#255'k<'''#244'Z.'#29'L'#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +'^/'#27'&b5!'#240#174'{f'#255#209#176#162#255#212#180#167#255#212#180#167#255
+ +#212#180#167#255#212#180#167#255#212#180#167#255#212#180#167#255#6#5#5#255
+ +#179#151#140#255#212#180#167#255#212#180#167#255#212#180#167#255#212#180#167
+ +#255#212#180#167#255#212#180#167#255'gXR'#255#0#0#0#255#0#0#0#255'gXR'#255
+ +#212#180#167#255#212#180#167#255#212#180#167#255#212#180#167#255#212#180#167
+ +#255#212#180#167#255#212#180#167#255#212#180#167#255#212#180#167#255#212#180
+ +#167#255#212#180#167#255#211#179#166#255#202#162#146#255#127'M7'#248'`2'#31
+ +#169#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0'[/'#26'Fg:#'#242#190#145#127#255#214#184#172#255#216
+ +#187#176#255#216#187#176#255#216#187#176#255#216#187#176#255#216#187#176#255
+ +'k]X'#255#216#187#176#255#216#187#176#255#216#187#176#255#216#187#176#255#216
+ +#187#176#255#216#187#176#255#216#187#176#255'E<8'#255#0#0#0#255'>63'#255#216
+ +#187#176#255#216#187#176#255#216#187#176#255#216#187#176#255#216#187#176#255
+ +#216#187#176#255#216#187#176#255#216#187#176#255#216#187#176#255#216#187#176
+ +#255#216#187#176#255#216#187#175#255#210#176#163#255#147'_H'#252'`4'#31#210
+ +'U++'#6#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'\0'#29'trB-'#242#198#157#140#255#218#191
+ +#180#255#221#195#185#255#221#195#185#255#221#195#185#255#221#195#185#255#221
+ +#195#185#255#221#195#185#255#221#195#185#255#221#195#185#255#221#195#185#255
+ +#221#195#185#255#221#195#185#255#221#195#185#255',''%'#255'920'#255#221#195
+ +#185#255#221#195#185#255#221#195#185#255#221#195#185#255#221#195#185#255#221
+ +#195#185#255#221#195#185#255#221#195#185#255#221#195#185#255#221#195#185#255
+ +#221#195#185#255#220#194#184#255#213#183#170#255#162'oW'#255'b5 '#232'].'#23
+ +#22#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'_1'#30#138'l>)'#242#187#143'|'
+ +#255#221#196#186#255#225#202#193#255#225#203#194#255#225#203#194#255#225#203
+ +#194#255#225#203#194#255#225#203#194#255#225#203#194#255#225#203#194#255#225
+ +#203#194#255#225#203#194#255#225#203#194#255#225#203#194#255#225#203#194#255
+ +#225#203#194#255#225#203#194#255#225#203#194#255#225#203#194#255#225#203#194
+ +#255#225#203#194#255#225#203#194#255#225#203#194#255#225#203#194#255#225#203
+ +#194#255#224#201#192#255#212#180#168#255#149'aK'#252'a5!'#230']2'#25')'#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#28'\d9$'#241#172
+ +'|h'#255#222#197#187#255#228#206#200#255#230#209#203#255#230#209#203#255#230
+ +#209#203#255#230#209#203#255#230#209#203#255#230#209#203#255#230#209#203#255
+ +#230#209#203#255#230#209#203#255#230#209#203#255#230#209#203#255#230#209#203
+ +#255#230#209#203#255#230#209#203#255#230#209#203#255#230#209#203#255#230#209
+ +#203#255#230#209#203#255#230#209#203#255#229#209#202#255#226#204#197#255#208
+ +#173#159#255#131'R;'#245'a3'#31#207'Y3'#26#20#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'].'#28'7a5!'#236#137'WB'#248#201
+ +#163#148#255#229#210#202#255#233#215#210#255#234#217#212#255#234#217#212#255
+ +#234#217#212#255#234#217#212#255#234#217#212#255#234#217#212#255#234#217#212
+ +#255#234#217#212#255#234#217#212#255#234#217#212#255#234#217#212#255#234#217
+ +#212#255#234#217#212#255#234#217#212#255#234#217#212#255#234#216#211#255#231
+ +#212#206#255#221#195#185#255#174#128'm'#255'm>*'#242'`1'#29#163'f33'#5#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ ,#0#0#0#0#0'b'''#20#13'`2'#29#140'd8$'#241#151'hR'#251#211#179#167#255#233#215
+ +#210#255#236#220#215#255#237#222#219#255#238#225#221#255#238#225#221#255#238
+ +#225#221#255#238#225#221#255#238#225#221#255#238#225#221#255#238#225#221#255
+ +#238#225#221#255#238#225#221#255#238#223#220#255#236#221#217#255#234#219#213
+ +#255#227#205#198#255#188#146#128#255'wH2'#242'b5 '#219'].'#27'B'#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'X1'#29#26'a3'#30#168'f:$'#242#134'T?'
+ +#246#179#136'v'#255#214#183#172#255#235#218#214#255#238#225#221#255#239#226
+ +#223#255#240#227#224#255#240#227#225#255#240#227#225#255#239#226#223#255#239
+ +#225#222#255#238#224#220#255#226#204#196#255#199#161#145#255#158'o['#254'rD-'
+ +#239'b4"'#232'^2'#30'\'#0#0#0#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0'`+ '#24']/'#30'fd6#'#197'c8#'#243'vE0'#240#140'ZF'
+ +#247#156'mY'#255#171#127'm'#255#184#143#127#255#178#136'v'#255#164'wd'#255
+ +#148'dP'#252#130'Q;'#243'l<('#239'b6"'#234'b5!'#151'Z-'#29'>UU'#0#3#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0'].'#23#11'Z/'#29'G^4 fa4!'#130'd6!'#166'd7#'#194
+ +'d7"'#182'c6"'#150'_3'#31's\0'#29'YY/'#30'+'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#255#255#224#3#255#255#255
+ +#255#255#254#0#0#127#255#255#255#255#248#0#0#31#255#255#255#255#224#0#0#7#255
+ +#255#255#255#192#0#0#3#255#255#255#255#128#0#0#1#255#255#255#255#0#0#0#0#127
+ +#255#255#254#0#0#0#0#127#255#255#252#0#0#0#0'?'#255#255#248#0#0#0#0#31#255
+ +#255#240#0#0#0#0#15#255#255#240#0#0#0#0#15#255#255#224#0#0#0#0#7#255#255#224
+ +#0#0#0#0#3#255#255#192#0#0#0#0#3#255#255#192#0#0#0#0#3#255#255#192#0#0#0#0#1
+ +#255#255#128#0#0#0#0#1#255#255#128#0#0#0#0#1#255#255#128#0#0#0#0#1#255#255
+ +#128#0#0#0#0#1#255#255#128#0#0#0#0#0#255#255#128#0#0#0#0#0#255#255#128#0#0#0
+ +#0#0#255#255#128#0#0#0#0#0#255#255#128#0#0#0#0#1#255#255#128#0#0#0#0#1#255
+ +#255#128#0#0#0#0#1#255#255#128#0#0#0#0#1#255#255#192#0#0#0#0#1#255#255#192#0
+ +#0#0#0#3#255#255#192#0#0#0#0#3#255#255#224#0#0#0#0#7#255#255#224#0#0#0#0#7
+ +#255#255#224#0#0#0#0#15#255#255#240#0#0#0#0#15#255#255#248#0#0#0#0#31#255#255
+ +#248#0#0#0#0'?'#255#255#252#0#0#0#0'?'#255#255#254#0#0#0#0#127#255#255#255#0
+ +#0#0#0#255#255#255#255#128#0#0#1#255#255#255#255#192#0#0#3#255#255#255#255
+ +#224#0#0#15#255#255#255#255#248#0#0#31#255#255#255#255#254#0#0#127#255#255
+ +#255#255#255#192#7#255#255#255#255#255#255#255#255#255#255#255#255'('#0#0#0
+ +' '#0#0#0'@'#0#0#0#1#0' '#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#2'CCC'#19'FFF'#22'UUU'#3#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0'@@@'#12'EAAGDDB'#133'DDC'#181'HC?'#205'LA;'#213
+ +'JB='#212'FC@'#204'EED'#185'DDC'#145'DDDSFFF'#22#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'III'#14'EEBoLA;'#208'eE-'#235'xK('
+ +#246#131'R)'#250#139'W*'#251#149'_,'#252#145'\+'#252#136'V*'#250#128'Q('#249
+ +'rI)'#244'\D2'#227'FB?'#207'CCC'#134'DDD'#30#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0'EEENMA9'#206'oF)'#245#147']-'#252#187'}4'#255#211#150'9'#255#224
+ +#167';'#255#230#174'='#255#234#179'>'#255#233#178'>'#255#228#171'='#255#221
+ +#163'<'#255#205#143'8'#255#175'r2'#255#131'R*'#250'eC,'#238'FB?'#205'CCCoUUU'
+ +#3#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0'@@@'#4'GEA|dB+'#239#142'[.'#252#198#137'<'#255#227#172'C'#255
+ +#236#183'E'#255#242#190'F'#255#246#195'G'#255#248#198'G'#255#249#199'H'#255
+ +#249#198'H'#255#247#196'G'#255#245#193'G'#255#240#188'F'#255#234#180'D'#255
+ +#220#163'A'#255#183'y8'#255'}O*'#250'WA4'#225'CCC'#152'<<<'#17#0#0#0#0#0#0#0
+ ,#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1'G@='#148
+ +'lD*'#245#175'u8'#254#221#166'I'#255#234#182'M'#255#242#193'P'#255#243#194'O'
+ +#255#244#195'O'#255#244#195'P'#255#244#195'P'#255#244#195'P'#255#244#195'P'
+ +#255#244#195'P'#255#244#195'P'#255#243#194'O'#255#243#194'O'#255#240#190'O'
+ +#255#230#179'L'#255#212#155'F'#255#148'^1'#252'`A.'#234'CCC'#171'@@@'#12#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'FA>vmB)'#247#189
+ +#130'A'#255#224#172'P'#255#236#187'U'#255#238#189'W'#255#238#190'V'#255#238
+ +#190'V'#255#238#190'V'#255'fQ%'#255#17#14#6#255#17#13#6#255#16#13#6#255',#'
+ +#16#255#155'|8'#255#238#190'V'#255#238#190'V'#255#238#189'V'#255#238#189'W'
+ +#255#233#184'U'#255#217#163'M'#255#164'l8'#254'_>+'#238'DDD'#147#128#128#128
+ +#2#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'FDD=e?*'#243#183'}B'#255
+ +#223#171'W'#255#232#183'['#255#232#183'\'#255#232#183'\'#255#232#183'\'#255
+ +#232#183'\'#255'>1'#25#255#1#1#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255
+ +#1#1#1#255#5#4#2#255#22#17#9#255'pX,'#255#218#171'V'#255#232#183'\'#255#230
+ +#182'['#255#217#164'T'#255#152'a7'#252'V=1'#228'DDDb'#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#128#128#128#2'Z<-'#215#163'k='#254#217#166'['#255#226#178'`'
+ +#255#226#179'a'#255#226#179'a'#255#226#179'a'#255#226#179'a'#255#226#179'a'
+ +#255#5#4#2#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#3#3#1#255',#'#19#255#226#179'a'#255#225#177'_'
+ +#255#208#154'T'#255#129'O1'#251'H?;'#205'@@@'#20#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0'J@<[vF,'#249#206#153'Y'#255#220#172'b'#255#220#172'c'#255#220#172'c'#255
+ +#220#172'c'#255#220#172'c'#255#220#172'c'#255#205#160']'#255#4#3#2#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#1#0#0#255'.$'#21#255#220#172'c'#255#218#170'a'#255#190#132
+ +'N'#255'c=)'#242'CCCz'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'\9('#218#177'vG'#255
+ +#213#164'c'#255#214#166'e'#255#214#166'e'#255#214#166'e'#255#214#166'e'#255
+ +#214#166'e'#255#214#166'e'#255#214#166'e'#255'v\8'#255#2#2#1#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#11#9#5#255#214#166'e'#255#214#166'e'#255#209#159'a'#255#139'Y'
+ +'6'#252'K>7'#206'333'#5#0#0#0#0#0#0#0#0'?;9'#19'mA+'#247#201#148'^'#255#209
+ +#159'e'#255#209#159'e'#255#209#159'e'#255#146'oF'#255#18#14#9#255#21#16#10
+ +#255'O<&'#255#209#159'e'#255#209#159'e'#255'$'#27#17#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#11#8#5#255#209#159'e'#255#209#159'e'#255#208#158'e'#255#185#128'Q'#255
+ +'^9)'#240'BBB6'#0#0#0#0#0#0#0#0'P8-q'#144'Z:'#252#201#150'd'#255#202#151'd'
+ +#255#202#151'd'#255'uW:'#255#2#1#1#255#0#0#0#255#0#0#0#255#1#0#0#255'-!'#22
+ +#255#202#151'd'#255'ZC-'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#1#1#0#255#5#4#3#255'gM3'#255#202#151'd'
+ +#255#202#151'd'#255#202#151'd'#255#197#145'`'#255'l@*'#248'CCBo'#0#0#0#0#0#0
+ +#0#0'^7$'#194#171'pK'#255#194#140'a'#255#194#140'a'#255#194#140'a'#255#6#4#3
+ +#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#7#5#4#255#194#140'a'#255#139'eE'
+ +#255#1#1#1#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#13
+ +#9#6#255'wV<'#255#192#138'a'#255#194#140'a'#255#194#140'a'#255#194#140'a'#255
+ +#194#140'a'#255#193#140'a'#255#137'T7'#252'K=6'#158#0#0#0#0#0#0#0#0'a6#'#220
+ +#177'uQ'#255#185#129'['#255#185#129'['#255#127'Y>'#255#1#1#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#2#1#1#255'8'''#27#255#185#129'['#255#185#129'['#255'+'#30
+ +#21#255#2#1#1#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#13#9#6#255#179'}Y'
+ +#255#185#129'['#255#185#129'['#255#185#129'['#255#185#129'['#255#185#129'['
+ +#255#185#129'['#255#185#129'['#255#152'^>'#255'P:1'#190#0#0#0#0#0#0#0#0'c7#'
+ +#227#175'sS'#255#178'xW'#255#178'xW'#255','#30#21#255#0#0#0#255#0#0#0#255#0#0
+ +#0#255#5#4#3#255'uO:'#255#178'xW'#255#178'xW'#255#178'xW'#255#178'xW'#255'xP'
+ +':'#255'('#26#19#255#10#7#5#255#10#7#5#255#28#19#13#255#168'rS'#255#163'nO'
+ +#255#25#17#12#255#6#4#3#255#17#11#8#255'bB/'#255#178'xW'#255#178'xW'#255#178
+ +'xW'#255#158'aB'#255'V9,'#210#0#0#0#0#0#0#0#0'f7"'#227#173'sT'#255#175'tW'
+ +#255#175'tW'#255#15#10#7#255#13#8#6#255#5#4#3#255'+'#29#21#255#169'pU'#255
+ +#175'tW'#255#175'tW'#255#175'tW'#255#175'tW'#255#175'tW'#255#175'tW'#255#175
+ +'tW'#255#175'tW'#255#175'tW'#255#175'tW'#255#175'tW'#255#17#11#8#255#0#0#0
+ +#255#0#0#0#255#0#0#0#255#2#2#1#255#136'ZD'#255#175'tW'#255#175'tW'#255#161'd'
+ +'G'#255'[8('#211#0#0#0#0#0#0#0#0'e6"'#218#171'nR'#255#173'qV'#255#173'qV'#255
+ +#136'YC'#255#173'qV'#255#173'qV'#255#173'qV'#255#173'qV'#255#173'qV'#255'sK9'
+ +#255'uM:'#255#159'gN'#255#173'qV'#255#173'qV'#255#173'qV'#255#173'qV'#255#173
+ +'qV'#255#173'qV'#255#173'qV'#255'5"'#27#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0
+ +#0#255'H/$'#255#173'qV'#255#173'qV'#255#153'^D'#255'Y8*'#188#0#0#0#0#0#0#0#0
+ +'c5 '#203#170'kQ'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'
+ ,#255#174'sY'#255#164'mU'#255#11#7#6#255#1#1#1#255#1#1#1#255#5#3#2#255#127'TA'
+ +#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255#174'sY'#255
+ +#128'UA'#255#2#1#1#255#0#0#0#255#0#0#0#255#0#0#0#255'J1&'#255#174'sY'#255#174
+ +'sY'#255#147'X?'#255'S8,'#140#0#0#0#0#0#0#0#0'd4'#30#153#162'gM'#255#178'{c'
+ +#255#178'{c'#255#178'{c'#255#178'{c'#255#178'{c'#255#178'{c'#255'A-$'#255#0#0
+ +#0#255#0#0#0#255#0#0#0#255#0#0#0#255#20#14#11#255'xSB'#255#6#4#3#255#5#4#3
+ +#255#18#12#10#255#170'u_'#255#178'{c'#255#178'{c'#255#9#6#5#255#0#0#0#255#0#0
+ +#0#255#3#2#2#255#166's]'#255#178'{c'#255#178'{c'#255#131'P8'#252'S3$>'#0#0#0
+ +#0#0#0#0#0'[/'#27'3'#137'T='#247#184#134'o'#255#184#134'o'#255#184#134'o'#255
+ +#184#134'o'#255#184#134'o'#255#184#134'o'#255#14#10#9#255#0#0#0#255#0#0#0#255
+ +#0#0#0#255#1#1#1#255'\C7'#255#14#10#8#255#0#0#0#255#0#0#0#255#0#0#0#255#14#10
+ +#8#255#184#134'o'#255#184#134'o'#255'xWI'#255#2#1#1#255#0#0#0#255#18#14#11
+ +#255#184#134'o'#255#184#134'o'#255#183#131'l'#255'h:&'#240#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0'n<%'#218#189#140'x'#255#190#143'z'#255#190#143'z'#255#190#143
+ +'z'#255#190#143'z'#255#190#143'z'#255',!'#28#255#0#0#0#255#0#0#0#255#0#0#0
+ +#255#9#7#6#255#190#143'z'#255#9#7#6#255#0#0#0#255#0#0#0#255#0#0#0#255#5#4#3
+ +#255#190#143'z'#255#190#143'z'#255#190#143'z'#255#159'xe'#255#0#0#0#255#140
+ +'jZ'#255#190#143'z'#255#190#143'z'#255#175'yc'#255'b6"'#193#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0'd4'#30#151#167's\'#254#196#154#135#255#196#154#135#255#196#154
+ +#135#255#196#154#135#255#196#154#135#255'qYN'#255#0#0#0#255#0#0#0#255#1#1#1
+ +#255'v]R'#255#194#152#133#255#5#4#4#255#0#0#0#255#0#0#0#255#0#0#0#255#10#8#7
+ +#255#196#154#135#255#196#154#135#255#196#154#135#255#196#154#135#255'"'#27#24
+ +#255#196#154#135#255#196#154#135#255#196#154#135#255#131'R<'#248'^1'#28'1'#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#14'o>('#224#198#157#140#255#202#163#146
+ +#255#202#163#146#255#202#163#146#255#202#163#146#255#170#138'{'#255#0#0#0#255
+ +#8#6#6#255#26#21#19#255#202#163#146#255#143'th'#255#1#1#1#255#0#0#0#255#0#0#0
+ +#255#2#2#2#255#143'sg'#255#202#163#146#255#202#163#146#255#202#163#146#255
+ +#202#163#146#255#191#155#138#255#202#163#146#255#202#163#146#255#183#135'r'
+ +#255'd5 '#193#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'd3'#30'{'#156
+ +'jS'#248#209#174#160#255#209#174#160#255#209#174#160#255#209#174#160#255#209
+ +#174#160#255#2#2#2#255#205#172#158#255#209#174#160#255#209#174#160#255#169
+ +#140#129#255#11#9#9#255#1#1#0#255#4#3#3#255#132'oe'#255#209#174#160#255#209
+ +#174#160#255#209#174#160#255#209#174#160#255#209#174#160#255#209#174#160#255
+ +#209#174#160#255#205#167#152#255'yG3'#235'[/'#27'"'#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'd4'#30#181#179#134'r'#254#215#185#173#255#215
+ +#185#173#255#215#185#173#255#215#185#173#255'm^X'#255#215#185#173#255#215#185
+ +#173#255#215#185#173#255#215#185#173#255#133'sk'#255#0#0#0#255#156#134'}'#255
+ +#215#185#173#255#215#185#173#255#215#185#173#255#215#185#173#255#215#185#173
+ +#255#215#185#173#255#215#185#173#255#214#183#172#255#143'^I'#243'b3'#29'`'#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#8'f6 '
+ +#205#189#148#131#254#222#197#187#255#222#197#187#255#222#197#187#255#222#197
+ +#187#255#222#197#187#255#222#197#187#255#222#197#187#255#222#197#187#255#127
+ +'qk'#255#134'wq'#255#222#197#187#255#222#197#187#255#222#197#187#255#222#197
+ +#187#255#222#197#187#255#222#197#187#255#222#197#187#255#220#193#183#255#159
+ +'o['#247'd3'#30#147#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0'[/'#27#15'c3'#30#193#176#132'q'#248#228#206#199#255
+ +#228#208#201#255#228#208#201#255#228#208#201#255#228#208#201#255#228#208#201
+ +#255#228#208#201#255#228#208#201#255#228#208#201#255#228#208#201#255#228#208
+ +#201#255#228#208#201#255#228#208#201#255#228#208#201#255#228#208#201#255#221
+ +#196#186#255#141']I'#237'c3'#29#129#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#2'c3'#29#150
+ +#135'XD'#231#208#176#164#255#235#219#215#255#235#219#215#255#235#219#215#255
+ +#235#219#215#255#235#219#215#255#235#219#215#255#235#219#215#255#235#219#215
+ +#255#235#219#215#255#235#219#215#255#235#219#215#255#232#214#209#255#189#149
+ +#133#253'qA+'#220'a2'#29'O'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27
+ +'"e4'#30#185#144'cO'#235#195#158#144#254#230#209#203#255#242#231#229#255#242
+ +#231#229#255#242#231#229#255#242#231#229#255#242#231#229#255#241#230#226#255
+ +#220#193#184#255#180#141'|'#251'zK6'#226'd3'#30#142'[/'#27#10#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#28'b3'#29'{g5'#30
+ +#198'xH2'#218#137']J'#229#156'r`'#236#151'mZ'#234#132'VB'#227'q?)'#213'f4'#30
+ +#182'_1'#28'W[/'#27#11#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ ,#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#5'[/'
+ +#27#30'[/'#27#22'[/'#27#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#255#252'?'#255
+ +#255#192#3#255#255#0#0#255#254#0#0'?'#248#0#0#31#240#0#0#15#240#0#0#7#224#0#0
+ +#7#192#0#0#3#192#0#0#3#192#0#0#1#128#0#0#1#128#0#0#1#128#0#0#1#128#0#0#1#128
+ +#0#0#1#128#0#0#1#128#0#0#1#128#0#0#1#128#0#0#1#128#0#0#3#192#0#0#3#192#0#0#3
+ +#192#0#0#7#224#0#0#7#240#0#0#15#240#0#0#31#248#0#0'?'#252#0#0#127#255#0#0#255
+ +#255#192#3#255#255#252'?'#255'('#0#0#0#16#0#0#0' '#0#0#0#1#0' '#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +';;;'#13'ICB7M=4zL>6xFBA;@@@'#16#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0'III'#7'W;,'#171'nC('#245#145'`+'#250#181#127'2'#253#175
+ +'z1'#253#139'\*'#250'h?&'#244'P=3'#159'@@@'#12#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0'K921d;'''#235#191#137'7'#254#249#198'E'#255#251#199'F'#255#251#200
+ +'F'#255#251#200'F'#255#251#199'F'#255#246#194'E'#255#173'y3'#253'\9)'#229'E>'
+ +';2'#0#0#0#0#0#0#0#0#0#0#0#0'>2,'#7'nC'''#238#223#171'N'#255#239#191'U'#255
+ +#240#192'U'#255#164#131':'#255'@3'#23#255'J;'#26#255'~e-'#255#196#157'E'#255
+ +#239#191'U'#255#212#159'J'#255'a<('#231'MMM'#10#0#0#0#0#0#0#0#0'[7('#183#195
+ +#145'N'#254#228#180'_'#255#228#180'_'#255#228#180'_'#255''#25#255#0#0#0#255
+ +#0#0#0#255#0#0#0#255#4#3#1#255'9-'#24#255#205#163'U'#255#175'~E'#253'Q:0'#168
+ +#0#0#0#0'[/'#27#10#143'd@'#248#219#174'l'#255#219#173'l'#255#159'~N'#255#206
+ +#163'f'#255'qY7'#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#1#1#0#255#152'x'
+ +'K'#255#218#172'k'#255'zQ5'#246'UUU'#3'W4$H'#178#134'_'#254#213#169'x'#255'Y'
+ +'F2'#255#0#0#0#255'L<+'#255#200#158'p'#255#8#6#4#255#0#0#0#255#0#0#0#255#18
+ +#15#10#255'pY?'#255#213#169'x'#255#213#169'x'#255#157'tR'#251'M=74^6$'#154
+ +#193#151'x'#255#179#144's'#255#6#5#4#255#27#21#17#255#155'|c'#255#206#165#132
+ +#255#130'hS'#255'=1'''#255':/%'#255#170#137'm'#255#141'q['#255#166#133'j'#255
+ +#206#165#132#255#178#135'l'#253'Q8,{c5 '#167#195#154#133#255#163#130'q'#255
+ +#153'zj'#255#192#152#132#255#199#159#138#255#200#159#138#255#201#160#139#255
+ +#201#160#139#255#201#160#139#255#154'zj'#255#1#1#1#255#29#23#20#255#197#157
+ +#136#255#181#139'v'#255'X5%|_1'#28'V'#176#132'r'#254#199#159#141#255#199#159
+ +#141#255#184#147#130#255'#'#28#25#255#27#22#19#255#167#133'v'#255#127'fZ'#255
+ +#172#137'z'#255#197#157#139#255' '#26#23#255#15#12#11#255#187#150#133#255#156
+ +'tb'#251'W1 0[/'#27#30#160'zk'#246#210#176#163#255#210#176#163#255#154#129'x'
+ +#255#0#0#0#255' '#27#25#255#152#128'v'#255#4#3#3#255'>40'#255#210#176#163#255
+ +#148'|s'#255'RD?'#255#210#176#163#255#140'fW'#243'[/'#27#2#0#0#0#0'tI6'#209
+ +#216#188#178#255#221#195#185#255#213#188#178#255'$'#31#30#255#131'sn'#255'sf'
+ +'`'#255#0#0#0#255'eYU'#255#221#195#185#255#221#195#185#255#204#180#170#255
+ +#207#178#166#255'k>+'#182#0#0#0#0#0#0#0#0'[/'#27#31#156'xi'#240#232#213#207
+ +#255#232#213#207#255#180#165#161#255#232#213#207#255#182#167#162#255'ICA'#255
+ +#226#207#201#255#232#213#207#255#232#213#207#255#231#213#206#255#134'_O'#233
+ +'[/'#27#12#0#0#0#0#0#0#0#0#0#0#0#0'd3'#30'e'#171#139'~'#240#239#226#224#255
+ +#242#231#229#255#242#231#229#255#240#229#227#255#242#231#229#255#242#231#229
+ +#255#242#231#229#255#235#221#216#255#153'uh'#236'a2'#29'?'#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0'\0'#27'*'#131'\I'#215#212#191#183#252#239#229#226#255
+ +#253#250#252#255#253#249#250#255#236#223#220#255#204#180#172#250'yM;'#196'[/'
+ +#27#23#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'[/'#27#3'[/'
+ +#27'>c3'#29#131'uI4'#190'oA-'#183'b2'#29'v[/'#27'4'#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#248#31#172'A'#224#7#172'A'#192#3#172'A'#128#1#172'A'#128#1#172
+ +'A'#0#0#172'A'#0#0#172'A'#0#0#172'A'#0#0#172'A'#0#0#172'A'#0#0#172'A'#128#1
+ +#172'A'#128#1#172'A'#192#3#172'A'#224#7#172'A'#240#31#172'A'
+]);
+
diff --git a/branches/script-component/Projects/PStest/project1.manifest b/branches/script-component/Projects/PStest/project1.manifest
new file mode 100644
index 0000000..07fb624
--- /dev/null
+++ b/branches/script-component/Projects/PStest/project1.manifest
@@ -0,0 +1,17 @@
+
+
+
+ Your application description here.
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/branches/script-component/Projects/PStest/testps.pas b/branches/script-component/Projects/PStest/testps.pas
new file mode 100644
index 0000000..34da04e
--- /dev/null
+++ b/branches/script-component/Projects/PStest/testps.pas
@@ -0,0 +1,132 @@
+unit TestPS;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+ Classes, SysUtils;
+
+type
+ TStringArray = array of string;
+ w_TPoint = record
+ x, y:integer;
+ end;
+
+ function MakeArr : TStringArray;
+procedure TestParameters(Int1,Int2,Int3,Int4,Int5,Int6 : integer);
+function TestResult(Int1,Int2,Int3,Int4,Int5,Int6 : integer): Integer;
+function TestString(Str1,Str2,Str3 : string) : string;
+function TestStringEdit(var Str : string) : String;
+procedure TestArrayPassing( Arr : TStringArray);
+Procedure TestArrayEdit(var Arr : TStringArray);
+function TestArrayFull(var Arr1: TStringArray; Arr2 : TStringArray): TStringArray;
+function makePoint(x, y: integer): w_Tpoint;
+
+implementation
+
+uses
+ Unit1;
+
+procedure Writeln(s : string);
+begin;
+ Form1.Memo2.Lines.add(s);
+end;
+
+procedure TestParameters(Int1,Int2,Int3,Int4,Int5,Int6 : integer);
+begin;
+ Writeln('Parameters are: ' + format('%d %d %d %d %d %d',[int1,int2,int3,int4,int5,int6]));
+ if (int1 <> 1) or (int2 <> 2) or (int3 <> 3) or (int4 <> 4) or (int5 <> 5) or (int6 <> 6) then
+ Writeln('WRONG.')
+ else
+ Writeln('Passed this test');
+end;
+
+function TestResult(Int1,Int2,Int3,Int4,Int5,Int6 : integer): Integer;
+begin;
+ Result := int1 + int2 + int3 + int4 + int5 + int6;
+ Writeln('Result should be:' + inttostr(int1+int2+int3+int4+int5+int6));
+end;
+
+function TestString(Str1,Str2,Str3 : string) : string;
+begin;
+ if Str1+Str2+str3 = 'lol' then
+ Writeln('Strings got passed over correctly.');
+ Str1 := 'a';
+ Str2 := 'b';
+ Str3 := 'c';
+ Result := str1;
+ Writeln('Result should be a');
+end;
+
+function TestStringEdit(var Str : string) : String;
+begin;
+ Result := 'False';
+ if Str <> 'Test' then
+ Writeln('String didn''t get passed on right');
+ Str := 'tseT';
+ Result := Str;
+ Result := 'hopla';
+ Writeln('Result should be: hopla; Input str should be tseT');
+end;
+
+procedure TestArrayPassing(Arr : TStringArray);
+var
+ i : integer;
+begin;
+ Writeln('Length of arr is: ' + inttostr(length(arr)));
+ for i := 0 to high(arr) do
+ Writeln(format('Arr[%d] := %s',[i,arr[i]]));
+end;
+
+
+Procedure TestArrayEdit(var Arr : TStringArray);
+begin;
+ Writeln('Arr size is ' + inttostr(length(arr)));
+ SetLength(arr,0);
+ SetLength(arr,5);
+ arr[0] := 'a';
+ arr[1] := 'b';
+ arr[2] := 'c';
+ arr[3] := 'd';
+ arr[4] := '!';
+end;
+
+function ConvStrArr( Arr : Array of String): TStringArray;
+var
+ Len : Integer;
+begin;
+ Len := Length(Arr);
+ SetLength(Result, Len);
+ Move(Arr[Low(Arr)], Result[0], Len*SizeOf(String));
+end;
+
+function TestArrayFull(var Arr1: TStringArray; Arr2 : TStringArray): TStringArray;
+begin
+ Writeln(Format('Len(Arr1) = %d - Len(Arr2) = %d',[Length(Arr1),length(arr2)]));
+ SetLength(Result,0);
+ Setlength(Arr1,0);
+ SetLength(Arr2,0);
+ SetLength(result,3);
+ SetLength(Arr1,4);
+ SetLength(arr2,5);
+ Arr1 := ConvStrArr(['Hoi','Hoe','Gaat','Het?']);
+ Arr2 := ConvStrArr(['Ik','ben','een','geest!']);
+ Result := ConvStrArr(['Waza?','Gaat','Alles','Goed']);
+end;
+
+function MakeArr : TStringArray;
+begin;
+ setlength(result,2);
+ result[0] := 'Test0';
+ Result[1] := 'Wow!';
+end;
+
+function makePoint(x, y: integer): w_Tpoint;
+begin
+ result.x := x;
+ result.y := y;
+end;
+
+end.
+
diff --git a/branches/script-component/Projects/PStest/unit1.lfm b/branches/script-component/Projects/PStest/unit1.lfm
new file mode 100644
index 0000000..da8adc7
--- /dev/null
+++ b/branches/script-component/Projects/PStest/unit1.lfm
@@ -0,0 +1,100 @@
+object Form1: TForm1
+ Left = 347
+ Height = 300
+ Top = 314
+ Width = 400
+ ActiveControl = Button1
+ Caption = 'Bug in Pascal Script for Lazarus'
+ ClientHeight = 300
+ ClientWidth = 400
+ LCLVersion = '0.9.29'
+ object Memo1: TMemo
+ Left = 0
+ Height = 137
+ Top = 55
+ Width = 400
+ Align = alBottom
+ Lines.Strings = (
+ 'program TestPS;'
+ ''
+ 'var'
+ ' Str,Str1,str2,str3 : String;'
+ ' Arr,Arr1,Arr2,Arr3 : TStringArray;'
+ ' I : integer;'
+ ' p: w_TPoint;'
+ 'begin'
+ ' TestParameters(1,2,3,4,5,6);'
+ ' if TestResult(1,2,3,4,5,6) = (1+2+3+4+5+6) then'
+ ' Writeln(''Result = '' + inttostr(1+2+3+4+5+6) + ''. Passed the result test'')'
+ ' else'
+ ' Writeln(''Result = '' + Inttostr(TestResult(1,2,3,4,5,6)) +'
+ ' ''. Failed @ result test'');'
+ ' p := makePoint(2,2);'
+ ' writeln(''p: '' + inttostr(p.x) + '', '' + inttostr(p.y));'
+ ' Str1 := ''l'';'
+ ' Str2 := ''o'';'
+ ' Str3 := ''l'';'
+ ' if TestString(Str1,Str2,Str3) = ''a'' then'
+ ' Writeln(''String test succesful.'')'
+ ' else'
+ ' Writeln(''String test failed.'');'
+ ' if (str1 = ''l'') and (str2 = ''o'') and (str3 = ''l'') then'
+ ' Writeln(''String test passed again.'')'
+ ' else'
+ ' Writeln(''String test failed.'');'
+ ' Str := ''Test'';'
+ ' if TestStringEdit(Str) = ''hopla'' then'
+ ' Writeln(''TestStringEdit result passed.'')'
+ ' else'
+ ' Writeln(''TestStringEdit result failed.'');'
+ ' if Str = ''tseT'' then'
+ ' Writeln(''TestStringEdit input passed.'')'
+ ' else'
+ ' Writeln(''TestStringEdit input failed.'');'
+ ' TestArrayEdit(Arr);'
+ ' For i := 0 to Length(arr) - 1 do'
+ ' Writeln(Arr[i]);'
+ ' Writeln(''it shouldve written: "abcd!"'');'
+ ' Arr := TStringArray([''Dit'',''is'',''een'',''test'']);'
+ ' TestArrayPassing(arr);'
+ ' TestArrayPassing(TStringArray([''Dit'',''is'',''een'',''test'']));'
+ ' Arr1 := TStringArray([''W'',''a'',''t'']);'
+ ' Arr2 := TStringArray([''T'',''es'',''t'',''ing'']);'
+ ' Arr3 := TStringArray([''Wowing'',''!'']);'
+ ' Arr3 := TestArrayFull(Arr1,Arr2);'
+ ' Writeln(''Should writeln: Hoi Hoe Gaat Het?'');'
+ ' for i := 0 to high(arr1) do'
+ ' Writeln(arr1[i]);'
+ ' Writeln('''');'
+ ' Writeln(''Should writeln: Ik ben een geest!'');'
+ ' for i := 0 to high(arr2) do'
+ ' writeln(arr2[i]);'
+ ' writeln('''');'
+ ' Writeln(''Should writeln: Waza? Gaat alles goed'');'
+ ' for I := 0 to high(arr3) do'
+ ' Writeln(arr3[i]);'
+ ''
+ 'end.'
+ )
+ OnChange = Memo1Change
+ TabOrder = 0
+ end
+ object Memo2: TMemo
+ Left = 0
+ Height = 108
+ Top = 192
+ Width = 400
+ Align = alBottom
+ TabOrder = 1
+ end
+ object Button1: TButton
+ Left = 0
+ Height = 55
+ Top = 0
+ Width = 400
+ Align = alClient
+ Caption = 'Compile'
+ OnClick = Button1Click
+ TabOrder = 2
+ end
+end
diff --git a/branches/script-component/Projects/PStest/unit1.lrs b/branches/script-component/Projects/PStest/unit1.lrs
new file mode 100644
index 0000000..4947017
--- /dev/null
+++ b/branches/script-component/Projects/PStest/unit1.lrs
@@ -0,0 +1,43 @@
+{ This is an automatically generated lazarus resource file }
+
+LazarusResources.Add('TForm1','FORMDATA',[
+ 'TPF0'#6'TForm1'#5'Form1'#4'Left'#3'['#1#6'Height'#3','#1#3'Top'#3':'#1#5'Wid'
+ +'th'#3#144#1#13'ActiveControl'#7#7'Button1'#7'Caption'#6' Bug in Pascal Scri'
+ +'pt for Lazarus'#12'ClientHeight'#3','#1#11'ClientWidth'#3#144#1#10'LCLVersi'
+ +'on'#6#6'0.9.29'#0#5'TMemo'#5'Memo1'#4'Left'#2#0#6'Height'#3#137#0#3'Top'#2
+ +'7'#5'Width'#3#144#1#5'Align'#7#8'alBottom'#13'Lines.Strings'#1#6#15'program'
+ +' TestPS;'#6#0#6#3'var'#6#30' Str,Str1,str2,str3 : String;'#6'$ Arr,Arr1,A'
+ +'rr2,Arr3 : TStringArray;'#6#14' I : integer;'#6#14' p: w_TPoint;'#6#5'beg'
+ +'in'#6#30' TestParameters(1,2,3,4,5,6);'#6'1 if TestResult(1,2,3,4,5,6) = '
+ +'(1+2+3+4+5+6) then'#6'M Writeln(''Result = '' + inttostr(1+2+3+4+5+6) + '
+ +'''. Passed the result test'')'#6#6' else'#6'> Writeln(''Result = '' + '
+ +'Inttostr(TestResult(1,2,3,4,5,6)) +'#6#31' ''. Failed @ result test'');'
+ +#6#22' p := makePoint(2,2);'#6'8 writeln(''p: '' + inttostr(p.x) + '', '' '
+ +'+ inttostr(p.y));'#6#14' Str1 := ''l'';'#6#14' Str2 := ''o'';'#6#14' Str'
+ +'3 := ''l'';'#6'* if TestString(Str1,Str2,Str3) = ''a'' then'#6'% Writel'
+ +'n(''String test succesful.'')'#6#6' else'#6'# Writeln(''String test fai'
+ +'led.'');'#6'8 if (str1 = ''l'') and (str2 = ''o'') and (str3 = ''l'') then'
+ +#6'( Writeln(''String test passed again.'')'#6#6' else'#6'# Writeln('
+ +'''String test failed.'');'#6#16' Str := ''Test'';'#6''' if TestStringEdit'
+ +'(Str) = ''hopla'' then'#6', Writeln(''TestStringEdit result passed.'')'#6
+ +#6' else'#6'- Writeln(''TestStringEdit result failed.'');'#6#22' if Str'
+ +' = ''tseT'' then'#6'+ Writeln(''TestStringEdit input passed.'')'#6#6' e'
+ +'lse'#6', Writeln(''TestStringEdit input failed.'');'#6#21' TestArrayEdi'
+ +'t(Arr);'#6'" For i := 0 to Length(arr) - 1 do'#6#20' Writeln(Arr[i]);'#6
+ +'* Writeln(''it shouldve written: "abcd!"'');'#6'1 Arr := TStringArray(['''
+ +'Dit'',''is'',''een'',''test'']);'#6#24' TestArrayPassing(arr);'#6'< TestA'
+ +'rrayPassing(TStringArray([''Dit'',''is'',''een'',''test'']));'#6'& Arr1 :='
+ +' TStringArray([''W'',''a'',''t'']);'#6'- Arr2 := TStringArray([''T'',''es'
+ +''',''t'',''ing'']);'#6''' Arr3 := TStringArray([''Wowing'',''!'']);'#6'# '
+ +'Arr3 := TestArrayFull(Arr1,Arr2);'#6'/ Writeln(''Should writeln: Hoi Hoe G'
+ +'aat Het?'');'#6#29' for i := 0 to high(arr1) do'#6#21' Writeln(arr1[i])'
+ +';'#6#14' Writeln('''');'#6'/ Writeln(''Should writeln: Ik ben een geest!'
+ +''');'#6#29' for i := 0 to high(arr2) do'#6#20' writeln(arr2[i]);'#6#14' '
+ +' writeln('''');'#6'3 Writeln(''Should writeln: Waza? Gaat alles goed'');'#6
+ +#29' for I := 0 to high(arr3) do'#6#21' Writeln(arr3[i]);'#6#0#6#4'end.'
+ +#0#8'OnChange'#7#11'Memo1Change'#8'TabOrder'#2#0#0#0#5'TMemo'#5'Memo2'#4'Lef'
+ +'t'#2#0#6'Height'#2'l'#3'Top'#3#192#0#5'Width'#3#144#1#5'Align'#7#8'alBottom'
+ +#8'TabOrder'#2#1#0#0#7'TButton'#7'Button1'#4'Left'#2#0#6'Height'#2'7'#3'Top'
+ +#2#0#5'Width'#3#144#1#5'Align'#7#8'alClient'#7'Caption'#6#7'Compile'#7'OnCli'
+ +'ck'#7#12'Button1Click'#8'TabOrder'#2#2#0#0#0
+]);
diff --git a/branches/script-component/Projects/PStest/unit1.pas b/branches/script-component/Projects/PStest/unit1.pas
new file mode 100644
index 0000000..ead7918
--- /dev/null
+++ b/branches/script-component/Projects/PStest/unit1.pas
@@ -0,0 +1,181 @@
+unit Unit1;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+ Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
+ StdCtrls, uPSComponent, uPSCompiler, uPSRuntime,UPSUtils,testps;
+
+type
+
+ { TForm1 }
+
+ TForm1 = class(TForm)
+ Button1: TButton;
+ Memo1: TMemo;
+ Memo2: TMemo;
+ procedure Button1Click(Sender: TObject);
+ procedure Memo1Change(Sender: TObject);
+ procedure ScriptCompile(Sender: TPSScript);
+ procedure ScriptCompImport(Sender: TObject; x: TPSPascalCompiler);
+ procedure ScriptExecImport(Sender: TObject; se: TPSExec;
+ x: TPSRuntimeClassImporter);
+ private
+ { private declarations }
+ public
+ { public declarations }
+ end;
+
+var
+ Form1: TForm1;
+
+implementation
+
+
+uses
+ uPSR_std,
+ uPSC_std,
+ uPSR_stdctrls,
+ uPSC_stdctrls,
+ uPSR_forms,
+ uPSC_forms,
+ uPSC_graphics,
+ uPSC_controls,
+ uPSC_classes,
+ uPSR_graphics,
+ uPSR_controls,
+ uPSR_classes;
+{ TForm1 }
+
+procedure TForm1.Button1Click(Sender: TObject);
+var
+ Script : TPSScript;
+ procedure OutputMessages;
+ var
+ l: Longint;
+ b: Boolean;
+ begin
+ b := False;
+
+ for l := 0 to Script.CompilerMessageCount - 1 do
+ begin
+ Memo2.Lines.Add('Compiler: '+ Script.CompilerErrorToStr(l));
+ if (not b) and (Script.CompilerMessages[l] is TIFPSPascalCompilerError) then
+ begin
+ b := True;
+ Memo1.SelStart := Script.CompilerMessages[l].Pos;
+ end;
+ end;
+ end;
+begin
+ Script := TPSScript.Create(self);
+ Script.OnCompImport:=@ScriptCompImport;
+ Script.OnExecImport:=@ScriptExecImport;
+ Script.OnCompile:=@ScriptCompile;
+ Memo2.Lines.Clear;
+ Script.Script.Assign(Memo1.Lines);
+ Memo2.Lines.Add('Compiling');
+ if Script.Compile then
+ begin
+ OutputMessages;
+ Memo2.Lines.Add('Compiled succesfully');
+ if not Script.Execute then
+ begin
+ Memo1.SelStart := Script.ExecErrorPosition;
+ Memo2.Lines.Add(Script.ExecErrorToString +' at '+Inttostr(Script.ExecErrorProcNo)+'.'+Inttostr(Script.ExecErrorByteCodePosition));
+ end else Memo2.Lines.Add('Succesfully executed');
+ end else
+ begin
+ OutputMessages;
+ Memo2.Lines.Add('Compiling failed');
+ end;
+ Script.free;
+end;
+
+procedure TForm1.Memo1Change(Sender: TObject);
+begin
+
+end;
+
+
+
+function teststdcall(num1,num2,num3,num4,num5,num6 : LongInt) : boolean; stdcall;
+begin;
+ Result := false;
+ Form1.Memo2.Lines.add(Format('stdcall AddFunctionEx: %d %d %d %d %d %d',[num1,num2,num3,num4,num5,num6]));
+end;
+
+function testcdecl(num1,num2,num3,num4,num5,num6 : LongInt) : boolean; cdecl;
+begin;
+ Result := false;
+ Form1.Memo2.Lines.add(Format('cdecl AddFunctionEx: %d %d %d %d %d %d',[num1,num2,num3,num4,num5,num6]));
+end;
+
+
+function testnormal(num1,num2,num3,num4,num5,num6 : LongInt) : boolean;
+begin;
+ Result := false;
+ Form1.Memo2.Lines.add(Format('Normal AddFunction: %d %d %d %d %d %d',[num1,num2,num3,num4,num5,num6]));
+end;
+
+function DiffTest(num : integer; str : string; byt : byte; wor : longword; bool : boolean) : boolean;
+begin;
+ Result := false;
+ Form1.Memo2.Lines.add(inttostr(num) + '-' + str +'-' + inttostr(byt) +'-' + inttostr(wor) +'-' + booltostr(bool,true));
+end;
+
+
+procedure TForm1.ScriptCompImport(Sender: TObject; x: TPSPascalCompiler);
+begin
+ SIRegister_Std(x);
+ SIRegister_Classes(x, true);
+ SIRegister_Graphics(x, true);
+ SIRegister_Controls(x);
+ SIRegister_stdctrls(x);
+ SIRegister_Forms(x);
+end;
+
+procedure TForm1.ScriptExecImport(Sender: TObject; se: TPSExec;
+ x: TPSRuntimeClassImporter);
+begin
+ RIRegister_Std(x);
+ RIRegister_Classes(x, True);
+ RIRegister_Graphics(x, True);
+ RIRegister_Controls(x);
+ RIRegister_stdctrls(x);
+ RIRegister_Forms(x);
+end;
+
+procedure Writeln(s : string);
+begin;
+ Form1.Memo2.Lines.add(s);
+end;
+
+procedure TForm1.ScriptCompile(Sender: TPSScript);
+begin
+ Sender.Comp.AddTypeS('TStringArray','Array of string');
+ Sender.Comp.AddTypeS('w_TPoint', 'record x, y: integer; end;');
+ Sender.AddFunction(@Writeln,'procedure writeln(s:string)');
+ Sender.AddFunction(@testnormal,'function testnormal(num1,num2,num3,num4,num5,num6 : LongInt) : boolean;');
+ Sender.AddFunctionEx(@teststdcall, 'function teststdcall(num1,num2,num3,num4,num5,num6 : LongInt) : boolean;stdcall;',cdStdCall);
+ Sender.AddFunctionEx(@testcdecl, 'function testcdecl(num1,num2,num3,num4,num5,num6 : LongInt) : boolean; cdecl;',cdCdecl);
+ Sender.AddFunction(@DiffTest,'function DiffTest(num : integer; str : string; byt : byte; wor : longword; bool : boolean) : boolean;');
+ Sender.AddFunction(@TestParameters,'procedure TestParameters(Int1,Int2,Int3,Int4,Int5,Int6 : integer);');
+ Sender.AddFunction(@TestResult,'function TestResult(Int1,Int2,Int3,Int4,Int5,Int6 : integer): Integer;');
+ Sender.AddFunction(@TestString,'function TestString(Str1,Str2,Str3 : string) : string;');
+ Sender.AddFunction(@TestStringEdit,'function TestStringEdit(var Str : string) : String;');
+ Sender.AddFunction(@TestArrayPassing,'procedure TestArrayPassing(const Arr : TStringArray);');
+ Sender.AddFunction(@TestArrayEdit,'Procedure TestArrayEdit(var Arr : TStringArray);');
+ Sender.AddFunction(@TestArrayFull,'function TestArrayFull(var Arr1: TStringArray; Arr2 : TStringArray): TStringArray;');
+ Sender.AddFunction(@MakeArr,'function MakeArr : TStringArray;');
+ Sender.AddFunction(@makePoint, 'function makePoint(x, y: integer): w_Tpoint;');
+end;
+
+
+initialization
+ {$I unit1.lrs}
+
+end.
+
diff --git a/branches/script-component/Projects/SAMufasaGUI/Makefile b/branches/script-component/Projects/SAMufasaGUI/Makefile
new file mode 100644
index 0000000..9d79011
--- /dev/null
+++ b/branches/script-component/Projects/SAMufasaGUI/Makefile
@@ -0,0 +1,35 @@
+#$ fpc -MObjFPC -Scgi -O2 -OoREGVAR -gl -vewnhi -l -Fu../../Units/MMLCore/ -Fu../../Units/MMLAddon/ -Fu../../Units/PascalScript/ -Fu../../Units/Misc/ -Fu../../../lazarus/components/synedit/units/x86_64-linux/ -Fu../../../lazarus/ideintf/units/x86_64-linux/ -Fu../../../lazarus/lcl/units/x86_64-linux/ -Fu../../../lazarus/lcl/units/x86_64-linux/gtk2/ -Fu../../../lazarus/packager/units/x86_64-linux/ -Fu. -oSAMufasaGUI -dUseCThreads -dM_MEMORY_DEBUG -dLCL -dLCLgtk2 project1.lpr
+
+.PHONY: default clean
+
+#Set these ----------
+platform := x86_64-linux
+widgetset := gtk2
+lazaruspath := /home/merlijn/Programs/lazarus
+
+#-dUseCThreads on linux, none on windows. :)
+platformdefines := -dUseCThreads
+#End set there -------
+
+CC := fpc
+build := $(CC)
+binary := SAMufasaGUI
+flags := -MObjFPC -Scgi -O2 -OoREGVAR -gl -vewnhi -l -Fu.
+defines := $(platformdefines) -dM_MEMORY_DEBUG -dLCL -dLCL$(widgetset)
+units := -Fu../../Units/MMLCore/ -Fu../../Units/MMLAddon/ -Fu../../Units/PascalScript/ -Fu../../Units/Misc/
+
+
+
+lclplatpath := $(lazaruspath)/lcl/units/$(platform)/
+
+lazarusunits := -Fu$(lazaruspath)/components/synedit/units/$(platform)/ -Fu$(lazaruspath)ideintf/units/$(platform)/ -Fu$(lclplatpath) -Fu$(lclplatpath)$(widgetset)/ -Fu$(lazaruspath)/packager/units/$(platform)/
+
+default: $(binary)
+
+clean:
+ rm -f *.o *.ppu $(binary)
+
+$(binary):
+ $(CC) $(flags) $(units) $(lazarusunits) -o$(binary) $(defines) project1.lpr
+
+ -Fu/usr/local/share/lazarus/ideintf/units/x86_64-linux/
diff --git a/branches/script-component/Projects/SAMufasaGUI/Makefile.win b/branches/script-component/Projects/SAMufasaGUI/Makefile.win
new file mode 100644
index 0000000..94389ba
--- /dev/null
+++ b/branches/script-component/Projects/SAMufasaGUI/Makefile.win
@@ -0,0 +1,30 @@
+#$ fpc -MObjFPC -Scgi -O2 -OoREGVAR -gl -vewnhi -l -Fu../../Units/MMLCore/ -Fu../../Units/MMLAddon/ -Fu../../Units/PascalScript/ -Fu../../Units/Misc/ -Fu../../../lazarus/components/synedit/units/x86_64-linux/ -Fu../../../lazarus/ideintf/units/x86_64-linux/ -Fu../../../lazarus/lcl/units/x86_64-linux/ -Fu../../../lazarus/lcl/units/x86_64-linux/gtk2/ -Fu../../../lazarus/packager/units/x86_64-linux/ -Fu. -oSAMufasaGUI -dUseCThreads -dM_MEMORY_DEBUG -dLCL -dLCLgtk2 project1.lpr
+
+.PHONY: default clean
+
+#Set these ----------
+platform := i386-win32
+widgetset := win32
+lazaruspath := "C:\path\to\lazarus"
+
+CC := fpc
+build := $(CC)
+binary := SAMufasaGUI
+flags := -MObjFPC -Scgi -O2 -OoREGVAR -gl -vewnhi -l -Fu.
+defines := $(platformdefines) -dM_MEMORY_DEBUG -dLCL -dLCL$(widgetset)
+units := -Fu../../Units/MMLCore/ -Fu../../Units/MMLAddon/ -Fu../../Units/PascalScript/ -Fu../../Units/Misc/
+
+
+
+lclplatpath := $(lazaruspath)/lcl/units/$(platform)/
+
+lazarusunits := -Fu$(lazaruspath)/components/synedit/units/$(platform)/ -Fu$(lazaruspath)ideintf/units/$(platform)/ -Fu$(lclplatpath) -Fu$(lclplatpath)$(widgetset)/ -Fu$(lazaruspath)/packager/units/$(platform)/
+
+default: $(binary)
+
+clean:
+ #Zoek zelf ff uit
+ del $(binary)
+
+$(binary):
+ $(CC) $(flags) $(units) $(lazarusunits) -o$(binary) $(defines) project1.lpr
diff --git a/branches/script-component/Projects/SAMufasaGUI/about.lfm b/branches/script-component/Projects/SAMufasaGUI/about.lfm
new file mode 100644
index 0000000..9cf082a
--- /dev/null
+++ b/branches/script-component/Projects/SAMufasaGUI/about.lfm
@@ -0,0 +1,433 @@
+object AboutForm: TAboutForm
+ Left = 622
+ Height = 400
+ Top = 270
+ Width = 400
+ ActiveControl = AboutMemo
+ BorderIcons = [biSystemMenu, biMinimize]
+ BorderStyle = bsSingle
+ Caption = 'About'
+ ClientHeight = 400
+ ClientWidth = 400
+ OnCreate = FormCreate
+ LCLVersion = '0.9.29'
+ object AboutMemo: TMemo
+ AnchorSideBottom.Control = ButtonClose
+ Left = 10
+ Height = 270
+ Top = 50
+ Width = 380
+ Align = alClient
+ BorderSpacing.Left = 10
+ BorderSpacing.Top = 50
+ BorderSpacing.Right = 10
+ BorderSpacing.Bottom = 80
+ TabOrder = 0
+ end
+ object ButtonClose: TButton
+ AnchorSideLeft.Control = AboutMemo
+ AnchorSideLeft.Side = asrCenter
+ AnchorSideRight.Control = AboutMemo
+ AnchorSideRight.Side = asrCenter
+ Left = 297
+ Height = 28
+ Top = 346
+ Width = 93
+ Anchors = [akTop]
+ Caption = 'Ok'
+ ModalResult = 1
+ TabOrder = 1
+ end
+ object LabelTitle: TLabel
+ Left = 8
+ Height = 27
+ Top = 16
+ Width = 69
+ Caption = 'Simba'
+ Font.Height = -23
+ Font.Name = 'Sans'
+ ParentColor = False
+ ParentFont = False
+ end
+ object LabelRevision: TLabel
+ Left = 286
+ Height = 20
+ Top = 19
+ Width = 104
+ Anchors = [akRight]
+ Caption = 'Revision XXX'
+ Font.Height = -17
+ Font.Name = 'Sans'
+ ParentColor = False
+ ParentFont = False
+ end
+ object ImageSimba: TImage
+ Left = 16
+ Height = 64
+ Top = 328
+ Width = 166
+ Picture.Data = {
+ 0A544A706567496D616765FA2C0000FFD8FFE000104A46494600010101012C01
+ 2C0000FFE1057A4578696600004D4D002A000000080007011200030000000100
+ 010000011A00050000000100000062011B0005000000010000006A0128000300
+ 00000100020000013100020000000B0000007201320002000000140000007E87
+ 6900040000000100000092000000BC0000012C000000010000012C0000000147
+ 494D5020322E362E370000323031303A30313A31322032303A31343A34390000
+ 03A001000300000001FFFF0000A002000400000001000000A6A0030004000000
+ 0100000040000000000006010300030000000100060000011A00050000000100
+ 00010A011B000500000001000001120128000300000001000200000201000400
+ 0000010000011A02020004000000010000045800000000000000480000000100
+ 00004800000001FFD8FFE000104A46494600010100000100010000FFDB004300
+ 080606070605080707070909080A0C140D0C0B0B0C1912130F141D1A1F1E1D1A
+ 1C1C20242E2720222C231C1C2837292C30313434341F27393D38323C2E333432
+ FFDB0043010909090C0B0C180D0D1832211C2132323232323232323232323232
+ 3232323232323232323232323232323232323232323232323232323232323232
+ 3232323232FFC00011080018004003012200021101031101FFC4001F00000105
+ 01010101010100000000000000000102030405060708090A0BFFC400B5100002
+ 010303020403050504040000017D010203000411051221314106135161072271
+ 14328191A1082342B1C11552D1F02433627282090A161718191A25262728292A
+ 3435363738393A434445464748494A535455565758595A636465666768696A73
+ 7475767778797A838485868788898A92939495969798999AA2A3A4A5A6A7A8A9
+ AAB2B3B4B5B6B7B8B9BAC2C3C4C5C6C7C8C9CAD2D3D4D5D6D7D8D9DAE1E2E3E4
+ E5E6E7E8E9EAF1F2F3F4F5F6F7F8F9FAFFC4001F010003010101010101010101
+ 0000000000000102030405060708090A0BFFC400B51100020102040403040705
+ 040400010277000102031104052131061241510761711322328108144291A1B1
+ C109233352F0156272D10A162434E125F11718191A262728292A35363738393A
+ 434445464748494A535455565758595A636465666768696A737475767778797A
+ 82838485868788898A92939495969798999AA2A3A4A5A6A7A8A9AAB2B3B4B5B6
+ B7B8B9BAC2C3C4C5C6C7C8C9CAD2D3D4D5D6D7D8D9DAE2E3E4E5E6E7E8E9EAF2
+ F3F4F5F6F7F8F9FAFFDA000C03010002110311003F00F35607B9FC05390E074C
+ 53B663B73EB4BE531F6A8B9E652D0B3616B35FDD25B5B8DD23F404E001DC9AEC
+ 6C7C29671DB09AE185C363E63B8AA8FA7F8D50F0A68EA036AD348E161621157F
+ 8B8E73EDCD76C74F66D3731DC48AA482ACE379F5C7CC0E476E6BC1CC31B51CDD
+ 3A52B25BFF005FE47D3E5B8487B3552A46EDED7FF2381D7B42FECC293DB9325B
+ 49DF39DA7EB59F1A5B25A3492ACF24A465150855EFCE4F5E9FCEBB9D5E06BBB4
+ 9ADAD4C6148DB267F84139E3DF19AE0B549FC9D6A5B7B6464B68245112A9C8DE
+ BC038E84E73DBB9AEFCAB10EBD3B547AAFEB53971B97A8D472A51D2D7B7F9135
+ A5909EC05D4AE530E51971C8FF0039ABD122F9788D76C7FA9FAD52D6DCE8FA44
+ 2227CCAEC77EE3C12DC938E9DA9FA7CCF756703B9C6E40DB6BB6A2EAB639E8C2
+ 1176B6A66818E00A77967EF1A28A9933CB51491B5A46AFAB4167258DA6C10B92
+ 5999794CF5C1F7AD64D27579F45B79ADB74881DC18E37E4024727D79CFE94515
+ C7565ECF58A5AB3E830179C2D27B1158DF4BA668D7515CE9B76B7292BFCC40C4
+ 993C7539E3A7E15CB5BEB9676972B2DE6952C339048746DCA73DC0278FD68A2A
+ F0118CDCE76D5B271B5674D4545E963075DD59F54BECF99FB9185418C633D4D7
+ 57733C3A7C51A2233BB9D91C718CB1E3FA514577555AA471D06DA727B9FFD9FF
+ DB00430001010101010101010101010101010101010101010101010101010101
+ 0101010101010101010101010101010101010101010101010101010101010101
+ 01010101FFDB0043010101010101010101010101010101010101010101010101
+ 0101010101010101010101010101010101010101010101010101010101010101
+ 010101010101010101FFC0001108004000A603012200021101031101FFC4001E
+ 000000060301010000000000000000000004050607080900030A0201FFC40034
+ 1000010402010205030205040301000000010203040506110712210008133141
+ 14225123610915163271174281A12452E191FFC4001D01000203010003010000
+ 0000000000000006070508090400010203FFC400361100020202010206000404
+ 030900000000010203040511061221000713223141081451611523327181A1E1
+ 162425335262B1F0F1FFDA000C03010002110311003F00E6E54F36B6CA94E8E9
+ DA4ECA8688DE893F046FB1EFEDE09E45AC56DF4B41B2AE82764275A27FB4A75D
+ 88F63BFC7E46878D9F40F4AE9429A4B7154900A14AFBC84F7248EC0157B8F7F6
+ DEFE7C0B5406194FDBEC94924A86CE87603BEFB760076F6D6BB788D336BB9EA6
+ D0D74AFB764EBBFF0061FDF7F3AD0F9A3F52B58BCCAA56389C8F7C931EDAD7C9
+ 27B0D004FB7B9047EDE00870C84FDAD929591BDFB9EFADEC7C0DECEF7DBB7B6F
+ C1BC3AE0C1417893AEFD24F57724A803A3DC9DFEFAF6D6FC11BD3DB86A084235
+ D47FBBDCEBDCF6EDF8D6FBEF7E0747B675C480D34A3BF6247641DE8FFDEC8EFD
+ FE4F8F83EA4836430047DB0F83AD1F9F904EBFB8F81E18B84A783C72A48D6A1B
+ 56D002EE815828214948D413A1D88DB0D9DFC680DAC5B713D254406DA40D0DFD
+ A4A75DB49D93EC4F60763B7E3C7D4CA4920A3EE035FA8469208EC343F201FC7E
+ 3BEFC16C7696B49764AD4413BE92001B27ABDBB0F6D8EFDBFC76F02132195282
+ 54025B4FF6211F72DCD76FB8EC6827B76F9DF6D81AF1ED14200CE48037DC9D9F
+ AF9FBDF71FE07F6EC5D5F366DCA61AD1AAAA91D524ADAD2F61D4157FB680EC00
+ 3DB7DBC29614E90E236971246B64F4E8EBB93F23E37EFBD1D8F6EC0529CDEC05
+ 2544FCABFB893DBB1D6876FC7EFF00F250CBE3A7DC236076E920FCFB7B8207C8
+ F6FDF7E1F2E1CF2EFCB1CF160636078FB88A08AEF4DEE6F6C97E0E2746C804BA
+ 5FB25327EB26A10857A7555889766FB8A404C64B65C7598ACF725C1718C5DACC
+ E7B2F430F8AA49D762F642C2568231DD82F5BE8B48E15847120796420AC68EDA
+ 1E0E30983CBF22BD5F1381C6DECD64ED9095E950AEF3589598A827A5474C7121
+ 61EA4F2B470C480C92C88A090CBA23AE74C6204288FD9584C790C43AF84C3B2E
+ 5C97D67486D88D1D2E3CF28A88052DA0946F7A001265CF1E7929E65CBA531FD4
+ B468C1E14884B9319DBD7588D223BCE361505532AD2B5D87A0F2FA50E27D14BE
+ D2161DE85F4949B8AE01F27D88F978C5A3C8C72257647CA2F20AEEB36C8E0A7E
+ A1C2F254A544AA64AA5FF258900047D3B71D4F3CE3BD4ECB71D794168739FC6B
+ 2F8AC0CA26B0D4E9696904B70E4AD99B2015829764A47A6FBCE9EC509692B5EB
+ A48689D8143B98FE34465ADDFC5F97AB88A18E4EBA74B3B9E9DA3CB5FBA08F42
+ C51C549E9C15A9CAC8EB1BDC9279DC32996BC1EF8C6847945F81CE3D72A4393F
+ 35B917FC46C22FA5C5F0D7E1A9141248AADF95C8645EBD9B370B21D4AD8F7C7C
+ 7049A11CF615448681F95FCB0F37F0CA153331C3A50A02B25AC96857FCEA8CA7
+ A4292A7A5440B7216D246C4C699E8D10B50E927C47F4AD4169DA8E8EFDBBF56B
+ DBDB7F6F7D8F71DF7DBB6BAA4A76B20B9829126037615B2D92A970725751650E
+ 67A85C4B8224820B8D129429954675871318F4A6484A540AA9D7CF4F95685C55
+ 68D729F1F562AB70AC82525BBAA08DD2F46C6EE9F503EBC30DA54966AA73CBF4
+ C309296A34B284B4943321086CBBC96FC58AF2DE434F81F3E87118EE45758D7C
+ 66671523458EBF714295A1768CF24CF8FBF382C217827B14EC480471085D910A
+ 07F10DF8247E098FB9CA7CBBCD58CC6128B9933185C8B258CA622B0FEBB556EC
+ 2900C85680E8D85687D6821EB9858B2A8E12BC1296D1DD6A08481EDF2AFF001B
+ EE3E403AD6CFC76F1F04B49DB6C3600D80AD9D9501AEDAFCE883AFF8FCF82B90
+ B709D15020EBBEB67A4104FEFBD1EDD20FC6C13E1DDC0AB78AEB50D5D726CEC9
+ EDD95BC9457E0B8308912DAD95D694A5CBCCA6C5A950F1D812165B6E347ABADB
+ FC866FDDFF008550CB8CCC7AE875B18D480CCEEC10051D5D4DB1A55D0D6F4740
+ 13F3AEFE28E371B4AF652A433C32DC97A1A4B3758455ABA0D0796794FBB5B2AA
+ 8B1A4B2B3FB5227704043434CC9487FE963BB25115B0F4C5B0CB8F08CC29696F
+ D694E361488CC75A820BF214DB4951E92B07C0DB16A7523EA8332B6641989574
+ A999D1DD69C0B521B711D969D290F30F36FB0E27ADA79871B79A5B8CB8959B30
+ 7FCDC712F0BF17D726ABCB4658FCB69F4B70AB2F73289754546D94FE92E76616
+ 28B6C86A9D96A5A80AC670B8F1DE71A72339363BE5BF1551E61BCCEE49CEF6F5
+ E9457E27C774D42D48629F18C261371971D2F7AA7D4B3B5794BB9B4722FAEBFA
+ 6612E5756464A9498953096BDF890A581CC5C7659A97E4A01DC4965C2BB0EC40
+ 1080CC77F04FB42F7EEDF00932BC1F078DA51D88797265F30C9138A1571D3253
+ 8F654CAB25A95F4A15598A928B2B1400C4A1B60F10D38EF538F38A008EE07EE4
+ 76D9FEED0F83AFD801AF1AD6FB68210D27BFB29449249FF68D0D76ECA235FE7C
+ 494F299C5753CCDC5367985D97AC723A6C96D311990BD68F06BA22EBEBAA6DAB
+ EDDE4897010EFD7D7DCC52652FEAE19B18F651138D4A66207DE5D47E20E39C06
+ 54991716F55975A457BA931997E649871965D4FE892CD75756CA7D9FBC043730
+ 95ABA5261A12B484C15DB6D8E92C452C524935794C2D0C5D2AA1977B219F40A9
+ 6D283FBEC03F7DF07961CC73B06267A8D86C663ADA2CED61672D24707B7524C1
+ 62EB696521B5145BE9234EC8367C3018471E64F9AA9953111C87540F548B5968
+ 5B51186C772A428F49795D3D45286F614A036402772420318E71EC2541C79689
+ 362E7487EC5607D5C95A52AEC85A07E847515FDAD34A1D923A892493B2E7399D
+ 218FE575D1910E2A806E3C6690965475D925C6994A12C25093A4B7DF7EE4FBF8
+ 218154DB4A1225A973259FB5311AFB8B6A568E94012A03BA5206C01EFD477A03
+ 16ACDCC8A03740AF57A895A513759946C006775006BF607FC4EBC3EF87F01C57
+ 1710CB14EF99CD88C2CD96BA02FE4CED7F954612A5200765BAC3493C87B1902E
+ 93C6BAF484BD22CED8A1D7E7294A4996488E8FB8121B07EF5BAAD0DA89E94A52
+ 46B6AED9E14FFCA12F243B620A96AEC88C873A111D3F092B4824AC0D052423A4
+ 77DABAB40E78E532C6A4AFA8C9D27A42C51878C05D01D25BB91A1DC771B04027
+ 7B2C710A8D7512EDDBA998F4927DBB3ADEF5B1B04F723B91BEC6AD8C86529D29
+ D423B100AFB6F7EDFBFCF61DC7E3C11C87E44E712DC60AE841E953AA490827EE
+ D11DB64F603DBE47724F818E553D3D6D7AC43686F4348FB763F7D6BE0120FB82
+ 0F7F827463B719091AF6EC48D6FB0E9EAFDF5ADFEE41DECF86148C88BD5B0343
+ ECFC9D0D7F9F63AF8FBF19794E3B134895D7AD6463AECC199DB4BD3B4D9E903E
+ 09EDAEDF3DBC113352D05A54FA83ABD0D03AD0EC7B01DBE091B3DFFE77E0DDB4
+ C58E8D21A48EFDF435DC1D820FCFB0F8DEBF1DFC6B515A9C3D29514920756BF0
+ 3F1AF627B6FB1F63EC3BF874100000256764950EE35B07F6D9EDEDAF6EDDF7E3
+ 9D27690757F4F4FB40EC7E003FF93FFBBF0C5C671E2046F3CD1C2CFD25A188F5
+ 483B2F50660CC34C07C1DFBB63F41E3D4879C7406DA21B480428A8E89075EC3B
+ 11DBE4E95DF5AD78F51436C3614424A81EC57DF64FBEBF3EDEDFE3BEB7E00901
+ 2AD2B4A51F7D927B7B92483F27B689D6B7F3AF1EBA4AD20ED5A048E91F1EDEC7
+ FBB67B0F91DC6BDB5E3C797FEA6D9D7C7C93F1AEC3B93FEBFBF82EAF4EA535D4
+ 4804875EE73D4EDDC77D1247DEFB0FD4FD761EB7D52DD4B05D547616E21B79E4
+ A56E2D965C5043CF2503EE754D3654E2508FB94521036547C75618FCFC768784
+ 70783C5E2ADDC41587E3EE637169C833E4D74986CEE520C3EA8B15FB4B25A2BD
+ F7E434EB8E5A4970B8E2A50586F9A0E20E14E50E6EC8D38B71A6332AEE636DA6
+ 4584C529A855D530CA837F576765296D4582C171452DA9C7038E2B6194AD408F
+ 1D20F96AE036F8D3CBF49E0DCDDD4B9653EBB22ABCE6CB0FB49F5739F89982A6
+ 2D9958FE4AA69AB187610A0CCE9AFB28EDA5AAEB98525FAF692DB0D1F140FF00
+ 1AF96E2D6AA708A76393A2E570BC816C5EE3303476A54C4E5628524CE5EA51CC
+ B3C7F9035152A7A8AAF3ADE952B152ED278D01FC16E3F9056B1CC32638D4D362
+ 729898E3A9C8A7530432643196182E1EA4EE3A2C24EB71E5B263D2C3254884AC
+ ECAA88E8F16E0FCA1C572AFB8EB94E9AE286DA2C7A8CAAA205C65AEE7A1AAAC8
+ D125B911E165F2198F2EC9B8D715D62DCA892D9439573BD7830D72AA99852DE7
+ 0F27BB18ED1CDB5FA27AC5D8C8488B5AC3ADC77A74C71C4B71A387DDFD38E853
+ 8A0B7DF521C2C30971C432F389432B8D9E57F80729F2FD5599E20F739E57CBF8
+ 22F2065DE388B9B51B15B698353B6CA957548188590DB3120585BBCFCD767479
+ 30E34D9AA916C9A2AC913DD610B0E7883CC9698DBA78438D6A396B24A747F32F
+ E90B8CD71BC42A2D9F69F6DF6EB2C4DCDC56CFB6813196951E7D4D2265CEB382
+ FBF5E1510CAFAA6B3FF2380FE31E611C34393C3E6858BB484997A50DCE3588C8
+ 75D486433FE5F3F74D8C59B21BA674B794B0C2CBCCF15D9D1E39E4BE38EB3769
+ F1B1733704952DD6AD34B669C5D3249EA2BC85046B0ED4171D217A57A14B2864
+ 017A7C37F85F36E5B3B2C5B5716F8E59D7D8A552E1E391B18BEC58B748CC910E
+ 65CE27905F476C677535B2243226DCD6373EA8BEFB30D13E3B92D85787C792E9
+ 30ACFEA3FD39CB9A8F2E265F06598289011E8BEEC4FA775BF4F6A49FA9295AA4
+ 4742168596E33CB4ABADB48F09FE2BE44F34BE64F882FE93CE6797EC2B81320C
+ 5B2CC1AD78AEF2AC2AAAF1E455467579A3117007327CE2FA91852D918E41B556
+ 431A932AC4323B485669AE5C17E15C93F2E1FE938B86E5EA69CB88D89CA541B2
+ 8C5096DE9959322B91DF71B694E969121B64BAF464979684CA6D801475DBA32D
+ 8DBD8CE4B5695CC563B8A727C75A9EB475F8CF23C6721A72495EB57B985CB63F
+ 2F898A8C2C2C3C91C4C966954BF15E8278E6F5BA1277E1C2E48E730B66CDFA12
+ C704D23576AD70596492AC9D08FB8EE0EB6565675922DB44C0865555214507F9
+ A2E0E1E5F7364C17643A9C76CA33F32BE5CBE94B6C165612A613254521C4290B
+ 6DC63AFF005744B7B75401283E03B5C5EFE77206459342C960D4607C7B93DFD2
+ E5B53163CFA6A8C8E0B5F4F593EED0F8664261BEEBCFD3C482C3526DA75D4F81
+ 16B60BD254971B977E7C39470BF3199EF16712711DA9CBECCD9A22CFBBA24B0F
+ 1025A7D05B112D2584448EE34CA16ECCB97DB94D406DB79D723CB71B5B2577E6
+ EB8DB8F3CB6F96AE3DE39A362BE9577B9941B2CA5F1297297900C7719B65CF6A
+ 4D94B6DB9B665A9D6315EAF7A4B71D8626A185C1ADAA8822D3C3DBAFC304BC83
+ 9570EF2ECF986D6F0FC8F3537A53E432DD341EBE228D9999F3B7A3B6616557A1
+ 08282C0D4AA3D560C49EBC92F3AB87E3311E62798B98E095A3CFE0707155B38F
+ E39858A5BE323C9AFD5AF1FF00B398F82824CD29394B015E2AC5DA0332C4880A
+ 2848AFC8583659E5EF897CBDF33724733629CB7857994C72D6658D155BD43676
+ 1844E87494D723E8E2D6B4CB9229962EA4505A449E890EB367525E0FA04C6A1B
+ 4CACEC5A6CDE2B97CD761E59B2FAEE073321C497C9C83192982D5AC9950AAEFF
+ 00F9334E3770DD1CAB0852A1B7695E25C0893194B13169322137323B41A9C032
+ ABBB1835D47570A9A155C94FA9EACD87696B2AC5F4362C63A9E4CE7E2A6B4329
+ 5C68014CC2625BC97D4DA93E93099108E5CF3228E086FCAA56F34E4F61C2F628
+ 4E3F5F80231CC2DAB1975B61766E7FA722E5CF63B65941AA72F5D54D456376CD
+ 454BEB5C7663B3054A89E2D5E3782798391C3C396E39C8F88F36C645CCAED6CA
+ 67AFC73F1D88F11A96A5972163155B1E96564BD456618DA73D8E8AD7131AD7A5
+ 409613D457F3DCF708E0B99C6F0CE75C5B98704E6AFC1686727E3D13266AED5E
+ 439E8AABF1DC3651AE489E88931F126672D1C2CD6AB59CF0C4AB09F193812CFC
+ 83A62E1753CDAE0C8A24AC0AC51C7D9463374ECE8ECB0A88EC7CD625D4A794A5
+ B498EEC1447A88F6121D2CB695185EAFA2F07996CE3993D46EC19BBC4F2F6EE6
+ 9ED5A5CC83321CAA8C8A0485475ADA9509A9E94CA65610EA7D3DC69A14DAFB15
+ A005106BC51E5720F14797CCA38E1FB595272BCF2A2CCDD59497CBACD349B561
+ B5B1475A63B4C7A702BE43697254861A0ED8D839227F421262B0DC0BE45E79E3
+ 3E19C5E938B70E36F9FDFE289B5392498ECBB535E7269F296FD9C65D85A107D0
+ 8D202A2B6884D583CCA5A4A65697D4A296CCC30E4F3F9238BF52EC3F9B31C324
+ 71154962890442C03B2046ED186562C3A8306D292515CF8B9EAF1BE0D8819EB3
+ 1E3AF2C65FF292C9EE536A49AD187AD98B34D5FAD63920546E86EB008F4F6648
+ E24D59DF3CB9112432FCF40EA750B47D3C786DA9C53665BEE2CA96B1D685B4B0
+ BE971A9095475212E2405BD706256E3F05C64C82ECB7C29C9D39612A7DD7544A
+ 836DF50262C746CA52D27EF52523ACEB40424E16E57ADE4384E59E38DBD5D92D
+ 33AA9964DA61DB7F20951A514B7675CEDBCAAF868926194B522129C6197DE790
+ F8532969455E1FD9B75364320A4A56A74256B5B64969475B7149277B0924A7B7
+ 601206FE4855EAD63F346A481A2688EA58D805653D8E98F61D0CA474E8F7F93B
+ 1AF05188BD5AC514B71BC72C52C61A09E30595BB8EA09BD9EA0C74C06FA4EC76
+ D0D2C2C72209296E33C9436DA8A7D55A8152D5EE4246F611B24F7F7201F6F6CF
+ 01E8AAE133193227C213664940536C48D0618887A4A57A2A485BEF2F4AEA3DDB
+ 6FECD6D4AD6788B92511398E3852454F6870FA075F3A1DFF0071BD9DFCF89B8A
+ 35745793A8B37B8EC9DF7208DFBBE75F23B7E87E4EABD64B25282A6877D7B020
+ 80A3EDA00F6D927E413AD1F9F000B4E947EB20EF5BD904E81EDAD023BFCFB7ED
+ E0F99694F2F642024689D760744286F7F8D7FF009E0C0C50BF70904F6EFDF7F3
+ F8D77FF1FF00C3AD99A42764C63BF4B7EFA03406C6FB1FFEF7F198D4E48AA448
+ 6388099B7FCD43D2CA0F6201F93B07EC68EBBFCF74B2597D48296DB481AD027F
+ BBBFB6BDF5ADF73BF191E865BCB064E923B91AEEA093EDD891EFD89EE7B6BB6F
+ 7E16A988863A5D290A1A034344F6D8D91F91BEE081AD1FC0F1AA54E432474201
+ 4E8ECEC756CE8FFD1F7FC81FBF8FC64B0B112A9A1AEE411DC9EC3B77FD343C14
+ 52BF761AE91C5E94464F73144769A5075AEB772C06FB7F401A2091AD9F052D63
+ D1194FA8E75296A4E827A4956CF7FCECEB5AFF008D7C8F03A356C66C82DB2D8D
+ 04ED4A48D6CFE49EC3F249EDDB5F1E3E30F3D208504FD8AEE344F56CF7D11F07
+ 47E3FC76DF83D8ACA74A2E0FD3D92A47C94246CA4903B852BB68EBFBBDFC46CD
+ 33959242492149001D6F5DC2EFFEED05FEE7EFEE4858B133A2199FDE511CF5B1
+ 08090199C81B0A06CB151D803F1E3A35F251C391388382718F52234DE519DC58
+ D9A64F2BD3024A8DB30245256AD6475FA35B50E475FA44A529992A59E9041217
+ 9C83CB5130CCEF1EAB109E9697509897288DDE4BD126A5C7D9FA767694BAED6F
+ A0ED837D64153466446805CA3D528F8E30EAFCF709C2728C1EDA22F17C9B1287
+ 79406434E753751EA221408E54D294952D2C069B737D25A75B7587108532A1E2
+ 1679E87B0AE0D6F8FF00916B5E8F9267B31EAF15945326AA145BA8CA941AB3DB
+ 50D97A6C68F12A9A96EBD2C05B9164468AD2825D9086D78D09E5EF3EF30FCCAC
+ E5ECFE1E6B392E4193C93AFAD66358E7B566622BC113194BAD7AB018963042A5
+ 7862404011851BEF849B8E70AE0F81C5616CD78F1581C3E32B4124486447AB5E
+ 0883DA72A089A4B67D4B0F27531B12CB24AA4FA8099C740ED3E651F0D9355416
+ 76901C9322265773430A0CA8D5F03E88B74F71322CC7DAB25C972C94D429B129
+ EB2DAC1865B932EC62438D0D529B57728E2F418D555042AB86CC559993D6E81F
+ AAF4A2F21B71F9525E5EDC79D2F21B49717FED0942425B4252203F914F38D9DF
+ 2C724731D267D8E60D86E0786E16730564F8ED79A4A7C4A0D6CC891E3576616D
+ 69394CDD3B6550ECEB1876D30C29ADB78F4F7A5385A790D30C9CBFE2BAD67356
+ EAAE785AA2124CA7D75258CCA58C8234671D4B719D9F12454368492CA9064B4C
+ 24C4D82A69D5247AC6C7F27F243CD1CCF0FC8F01863A99ECAE0B1B850F335BA9
+ 140ECEC2CE357D795E1436A2A70B564560A22088C42432AB91AA7E68605ED54B
+ 962F5EAD8EB162FAD6A92C166478C55295AC33242AFB8FD4997D31EE3A661182
+ 564559F12DF6D86CA96E36D34DA54A75C2A4A420246C97144FDA1206FEED6803
+ BF11EF25991B9624B78ED1BCC4DC3604E0E6517ACBA831A7391812296A5C0A52
+ A5BEA0A50953A3A5C850D2543D57A5A1310D73F337F10D76061D7F6B3B8E7139
+ F5519911E5B12B20B0BF5B8E4B92DC28B1CD1A9316A5E536FBCD75192E24A148
+ DA14081B931E4C2BB3C738BBFD44CFA22E8DFE452C5F6378AAD81157458A3C82
+ F550763A1E790C2EC1B77EAA3C70B5A63C25474256428815CB917907CEBCADE2
+ 6399736AD4709627C9458BC363DB234AE5AB9764844D33C1052B3683C94EBEA5
+ 7924912287AA362CEFD0A49B17E6371AE4F9F938DE16C58BF6ABE3065AF1FCAC
+ F0455E999C415E49A49634E9162C068618D97D493D39749D28C7C00BDF2C3C75
+ C7BCE58E73A61755558FB1365B74D98E3CDB04573CFDB4A8B0EBEDAA184A4375
+ D2E44E5448F3D2C0F41C6D25C484AE43FEA56E7F179C8A55FE7F8063F5CA7DF7
+ B00C65DB091099EA78392B3DB44B52632996F60BB1A063D4531A7340A1A9AF03
+ A6CF51BA2E4BB1F4F0FC89E438DB4F47AD7E5C579D485B4C4E82B44CAF7D483B
+ EA11EC23C67FA47725BDA74AD6B9DFF33D9BE7395F31E6792F2062D2311B6B49
+ 70A357550428342A296A2B69EBD31A6C82866CDC7A3446A5C89B05C5C775E96E
+ 16D2DA74DA2EEFE1539DE739D707C971FE4991B590B7C526A9468DFB2ED35A4C
+ 1DC8DA5A75249A467925346C41662579199CD7686225D613E1796F8C63385799
+ 38DE53C7AAD5C58BB1DCCA58A95FD38239B300475AC4F1C31943BB55ECA4B616
+ 1409EB46F29DB4CC3C42DC2A0E6F8FDEB16F3A342811150E421F88C5AB8894E2
+ 1F696DB51A638C30A487132531A6ADA8CEADA0867E98CC0E3EA2DCF2F27B1159
+ AF31B93ED1B82AACC36A1EBA690DC5528BB74A5263440D4879C90B0A89EA2DD7
+ 54A907F554940054857A71B70CC3F27E51CB2AB0BC52BE42AC6DA421A75F792B
+ 447AD8CAEB72458CE7521D1120C58AD4890EBCE10B74B623C569E94E3683715C
+ 6DC558970DD5231FC6E1B6B7A255C762D72175A4A676416125D53B2663CB0A52
+ 9B65B530110E18516E2475F48EA79D92F3D76B19CC3926138E59E2389CC5FA78
+ 4BD3CF66D5081D42CF25B821AD62269DBFDE56BCD1C0BEAC026103B992431754
+ AFB41F9D9C7781F29E57579E726C1D2E41E64418DA58BA19CBABFCDC751C7642
+ CE46B4FF009389A2A02E40D6EC57AB71EAB5B485608C4A8B1212E6DD5821C2B6
+ D4A2E217F62920F4ED2A574A876D10483A1AEE37DB446FC731BE62F206ECF983
+ 9065258663BC9C866C492B608F4A5CC82EAA2BF61E9803D2726FA4975C401A4B
+ A5613F9F179FE62F9BA8F8678F724CBED1F6C4A855EEA29A0FAE1122C2E25876
+ 354456107EE599139274A1A09662CD920A9B8520A79B5BCBB956F3A75BD8BA5D
+ 9B62FBF6131D51DA94FCA75725F5294AD9DFA8E2B64FC920EF7BF12FC2EAB46F
+ 72D38217A163566EC19CB191C2823455015666F8EA2DAD9DF8A97E6DE415E2C4
+ E3A36669CCAF6254DF78A248C47183A63B321771D241F6E8F604132F3C9346B0
+ 9BC8D9849896B3A0C0A8C76BD761099F4555772BB19B21810EC995F4AD3223A5
+ 0DCC87299587180DBA85A5D6A42909B50A96A0C896D30A485B6C36EC89696C24
+ A3D165B2A0C8E92000E39D2958EDB0B3DF67BC08F239894B8BC536F9BA9B0CBD
+ 9D64B3E44690E0D7A94D409555412D9480036B922C36123A14B6F7DD436271E3
+ D0E7427A64973A9C8EFC54B0AEBD25656E3C9520A4001246DB3BDFB8D6F7DFC0
+ CF249A2B190C818E6556522242AC016312846DE86C9059BA0904FC6F5F469C3A
+ 85DC5603189240EF145134B37A84900CEEB2332A93B0174A3DA012A4FB77E1CE
+ 831D13F5226345B6C35E9474A4A404A12A1DB475EFEE0EBDB40680D78CF05ED5
+ A188CA145D60255F6A43AA1D29EC094A42BD8EC771F077AF9F19E001A9DB2C4C
+ 6DA4D0E904B6FE00EFED3DF7FBFDF862C57E011A0916467D0EA60ABA3F1F1B60
+ 75ADFD03AEDFA7881B1A22827AD4A012077EDD3AD8F8275BFCF7DFC01AF1B016
+ C2874A81295F6528EC7600827F2364FC1FF8D78F4A6C840F549E823AF609046F
+ B83A1DBFCF7F71FE47808A6FAC84212A20FD9D5A20F73D8EF5F248D13FFDF07E
+ D65550B4606BE0E80DEC95D1F8D7D9FF004F19B38BC05FBCCA2351E9200D24EC
+ 4F42A800EFE8F7D680DEC9F1B54F923D3469C5ECF748D8D6F7F07E003D8FCFF9
+ EE1BF9597FEF7095286F5DB5AD92747DF63447B7B6FB8DEF6A1830911D077B1D
+ 4A03A4A4156BA765409F8EAD6CF6D7C7B9F07EC406880B29291A24FC03B27F60
+ 7F71BF63EE00F10534AC59CB1EE09D107EBB6BE7EFE7FCB47EC11A4114682289
+ 98B21319763B1B046C8DECEF7BD7EDA1F5E13716388ED9E86C2B49EC75DD0477
+ FF001BD0D6FDFF006F015760415368014A2540F49EDB3EE0FEE476207CEFE360
+ A8AC43686D4DB4B4A12A3B235F7107637A1DB5BF73AEE081DBE53ECD70D2D680
+ 75D9455FFB1EFBD7EFDBFEC0FCF8E7F53AFDA4923F42763B68FD9EFA2011DBEB
+ 7F5E2571156BC737A974B4918076A088D64275B0CDDB607DFEA3B688241903C4
+ BE747CCBF03C0628F8CF96B20A0A08A668858E4F8F599263709562AF5662A1D2
+ E450AD60455BCF1FA857D3C769264F548524BAB52891C4E53C8395B3BC8327E5
+ 4C972BCD732BE713318B57DEBB93154E2D329CB0829A8A6F468EBE32D496A4C7
+ 8CDD7458C57F5896FEF2078D5C69C1F759FBC674951A5C61871099D7B31A590B
+ E9095AD8AE67EC32A4F4772014B6CA74B7D48D94F89BCC61581639891C5AB6A9
+ AA6A293F4CE4E9CE3406537F2233CDC98B3D13548F5E3043ED34FC731FA22C72
+ 341B74A55B808130D8DCB1C856C4534C8CC4AD9B75EA411D8647D17325848C48
+ D3125890AE1994EDC9DF8B49E5A6579DDB140CB94C9AF0EC71295F1793BD76C5
+ 3B107488D23A1427944623850ABC12347F9785954C6AC76027BCA457B39372E6
+ 6BC56CC0BE72C7997CBA73260B8E5056CC453D6DC65AC631FD4D410EDE4256EB
+ 75950A5627219FA9991D488F6EF476A4A7D275C6DC8DD384EA8624E3F76DD7B1
+ 778D5A48C7AFE96430EC39D53754368E51CEABB1612DDA8FAE8B2A32A35833E9
+ 342338D3C8F596DA02CDE7FF000C8471BC3B6E43871F0D855D99FAD19CA3CBAC
+ 14675BCBA696CBAB9B43165CB515C65FAD11CB271B8696153E3A5FF550A62B5D
+ 70BC9E617F86C711730DA59E5B864D57186616D3E75BDBBD0AB62DD633736D67
+ 27EAEC6D66D1BCE32EC59F3DE53CECE915161084C75D53AF25675E039FCDFE3B
+ 8BE6F9EC6E521B346974636B4B700161932152193AA5961AECF2475E5A76AB28
+ 411CD657D3492455493A56DC51E1592C8E0B1F94C7B4333DB17A75ACC4D63F94
+ B0F088D3AD97D39658ADC36CB11E9D7025655DBA92796DF30CEB8788B2DE9855
+ EE05A6ADA42A3C871C4B1D56D051F56A4AA2460047ECEA529EAEB50482A50D9F
+ 1D22795CE4DE38F333E59B85B2AC7F24A3A6CC63E2D0F19C8299D9AD86A99588
+ 553554E57D923A43C87A3AE2434C371B8E438CCDDBC875B68AC40EF343FC2439
+ 2A3715593541CC5844F332EA8633C95E137744DB0DBF6F0D2C3921C62FAE8BCD
+ 2E5FA0C3A94B0C240783A0E9250B8E5C13FC3633CE1BB5FE7CF799FCA68A6BCC
+ AC4DA9E34A66AA2BA5A9681B66C1CC8E4DD47B04F609131BAC8535B4247A2EB4
+ 40F011E7AF2FF2379C70AA789CDF37AB57298CBF67218FA098BCF599EDAD8AB0
+ 5774E98280303996A46D059EB0A8D1949418E46E9E2E238FF35388F990F90C5F
+ 08B392E3397C063B1991BDFC4B0F4850B94EEE467496BB5BB119B1D115B659AB
+ AA75B895258B6F1806C2BCE1E7384F0EF16E7F2B20CBABE5CBA9C7DD92514D25
+ 022489EFC6949AAAB8F2A732DAE64C9B62DC660C68D156131D6E3CE491D07C53
+ 9F107F146E3AC922C9C6FCC6F1FB504D82A107321C76A519362325C8D01AAD72
+ 458E2F60245C51A5D8D161B8B8F527266DE9A99723501B90D32D07F321E5C6CF
+ 91ECAC52321C9321CBE94B8CBA332C8674EAFB5F43D5430961B714DC0A99EE16
+ DD446931D84324BCD894AF4545C6E0A49F2756D9560FFD4DC7970E232BA4973E
+ 9733E3BCA4260CEAEC82ADC526447AFB4D7A51C4A8AA89361B1689F464B7312B
+ 45AB71805067FE1BBCBAF2FB8EF076C9622E7E724E4E68DA9A5FE7D79EBAD659
+ A381652F2C85D9A49A6123944881509D2BA6674EF9FBCFFCCBBBCDEAD2A58B14
+ 29E060B69040F2C371729EBFA06D4A163481A378628E2F4EBA4AB6823BCA19D4
+ 692F1F8EB933CB75F3C87784720E2C6A2CA8D67267C1C38D050CB54C90E55F43
+ B6D571910263535B610E3684CD8C890843AFB653A5293E3D722E74AA76BE96BD
+ 2D48B391A512EBA7D08AC289EB92E2594AD6EB8A0408D1FED0B57DCB79B68695
+ CBA59E197F89648E53653437B87E5D58A4BEA8D6B5AF46714CA882CC84A96842
+ 5D61F4A82E34F812D31A5347D5832E46D2A5382D72CF25D2A149819D64D11E51
+ DAFD2B89D2014F4807B593929691D80D03A090003D209F160D78642CE268AEFA
+ B0903A15D37F277FF351BDE35F7D23BFC7E8121279B52293164F173456BB095A
+ 29983A380AADA8AD0240041D8F5D88D107E3C1C79AFCF72DCEF95324ABC86E26
+ 5941A8CCED234486F1437120C2AD71C65A0C47692DB6D23E9A3B686FED568AD6
+ B2A2F487D6EC5BCAEC9516AA629B500E3C12C20EFF00DCF10D9235A24E8F503F
+ 1E165915D585ED94EBAB9B093656F62E97A7CE92B0A7643AA03ADD73A1294FA8
+ A28495A801D646C8EAD92CDE6D2FFF00122A37B065A147E741B4957CFC7E3F1A
+ 27F725CD1A53A0CA8A8862AEB16D0000900283FBF539EB3BEFB3BF9EE571599F
+ 37998A79CC924725D9A70662198A49399C2B9EA653D11AC71F63FD080761D874
+ 8FC3383FF4B713F1A6311D1F7D36138D32F44434508336556469B62E15A01003
+ 9672E5BAA5AFB9F53BFDC7B3BF25B6E2C26FEAB5EBA3ED6D840286D0A4FDA12A
+ 5241F50A541493D5F6EBA74013BF0478365B5D2318C3E557388719B8C1F15BA6
+ 4FA9EB38FC7B1A0AE9C17EA2121B4A1B4480DFA40F520A4057DE14046AF361E6
+ 058E10E38997311D6E466B942DFA2C0AADCFBFD198F34854CB95C7492E3F1E99
+ 9710F9514969731D830D67AE6A36874AB6AEDDE96ECD627665DEC33166DB316F
+ 9E95EEEE767DA0EFB0D78B4C6D57AF5229640457AF5D199413EFE9455455035B
+ 62DA403F7F8FD1EBB2958ECA52DFB39F4F012DC87227A9365438E83258D87638
+ 321D4053ECEC8752075A15B4AF4468678ACFE30F21390F24E2B5597F989E41CC
+ A34EBB8CAB4A6C56BDD6DE994CD5A39F5EA976EED837263B765621F5C897162C
+ 469C69C702A54990EA825BCF124F4E8A3143949B687A0FA15CBC5B5214F43B3F
+ BBBEB6C3DA4F75EC3C702DCC8CCAB2C7858D91C02A649BA1B5ED1DD163D2F7F8
+ 1DC8EDBEFF003FFFD9
+ }
+ end
+end
diff --git a/branches/script-component/Projects/SAMufasaGUI/about.lrs b/branches/script-component/Projects/SAMufasaGUI/about.lrs
new file mode 100644
index 0000000..3300c32
--- /dev/null
+++ b/branches/script-component/Projects/SAMufasaGUI/about.lrs
@@ -0,0 +1,495 @@
+{ This is an automatically generated lazarus resource file }
+
+LazarusResources.Add('TAboutForm','FORMDATA',[
+ 'TPF0'#10'TAboutForm'#9'AboutForm'#4'Left'#3'n'#2#6'Height'#3#144#1#3'Top'#3
+ +#14#1#5'Width'#3#144#1#13'ActiveControl'#7#9'AboutMemo'#11'BorderIcons'#11#12
+ +'biSystemMenu'#10'biMinimize'#0#11'BorderStyle'#7#8'bsSingle'#7'Caption'#6#5
+ +'About'#12'ClientHeight'#3#144#1#11'ClientWidth'#3#144#1#8'OnCreate'#7#10'Fo'
+ +'rmCreate'#10'LCLVersion'#6#6'0.9.29'#0#5'TMemo'#9'AboutMemo'#24'AnchorSideB'
+ +'ottom.Control'#7#11'ButtonClose'#4'Left'#2#10#6'Height'#3#14#1#3'Top'#2'2'#5
+ +'Width'#3'|'#1#5'Align'#7#8'alClient'#18'BorderSpacing.Left'#2#10#17'BorderS'
+ +'pacing.Top'#2'2'#19'BorderSpacing.Right'#2#10#20'BorderSpacing.Bottom'#2'P'
+ +#8'TabOrder'#2#0#0#0#7'TButton'#11'ButtonClose'#22'AnchorSideLeft.Control'#7
+ +#9'AboutMemo'#19'AnchorSideLeft.Side'#7#9'asrCenter'#23'AnchorSideRight.Cont'
+ +'rol'#7#9'AboutMemo'#20'AnchorSideRight.Side'#7#9'asrCenter'#4'Left'#3')'#1#6
+ +'Height'#2#28#3'Top'#3'Z'#1#5'Width'#2']'#7'Anchors'#11#5'akTop'#0#7'Caption'
+ +#6#2'Ok'#11'ModalResult'#2#1#8'TabOrder'#2#1#0#0#6'TLabel'#10'LabelTitle'#4
+ +'Left'#2#8#6'Height'#2#27#3'Top'#2#16#5'Width'#2'E'#7'Caption'#6#5'Simba'#11
+ +'Font.Height'#2#233#9'Font.Name'#6#4'Sans'#11'ParentColor'#8#10'ParentFont'#8
+ +#0#0#6'TLabel'#13'LabelRevision'#4'Left'#3#30#1#6'Height'#2#20#3'Top'#2#19#5
+ +'Width'#2'h'#7'Anchors'#11#7'akRight'#0#7'Caption'#6#12'Revision XXX'#11'Fon'
+ +'t.Height'#2#239#9'Font.Name'#6#4'Sans'#11'ParentColor'#8#10'ParentFont'#8#0
+ +#0#6'TImage'#10'ImageSimba'#4'Left'#2#16#6'Height'#2'@'#3'Top'#3'H'#1#5'Widt'
+ +'h'#3#166#0#12'Picture.Data'#10#9'-'#0#0#10'TJpegImage'#250','#0#0#255#216
+ +#255#224#0#16'JFIF'#0#1#1#1#1','#1','#0#0#255#225#5'zExif'#0#0'MM'#0'*'#0#0#0
+ +#8#0#7#1#18#0#3#0#0#0#1#0#1#0#0#1#26#0#5#0#0#0#1#0#0#0'b'#1#27#0#5#0#0#0#1#0
+ +#0#0'j'#1'('#0#3#0#0#0#1#0#2#0#0#1'1'#0#2#0#0#0#11#0#0#0'r'#1'2'#0#2#0#0#0#20
+ +#0#0#0'~'#135'i'#0#4#0#0#0#1#0#0#0#146#0#0#0#188#0#0#1','#0#0#0#1#0#0#1','#0
+ +#0#0#1'GIMP 2.6.7'#0#0'2010:01:12 20:14:49'#0#0#3#160#1#0#3#0#0#0#1#255#255#0
+ +#0#160#2#0#4#0#0#0#1#0#0#0#166#160#3#0#4#0#0#0#1#0#0#0'@'#0#0#0#0#0#6#1#3#0#3
+ +#0#0#0#1#0#6#0#0#1#26#0#5#0#0#0#1#0#0#1#10#1#27#0#5#0#0#0#1#0#0#1#18#1'('#0#3
+ +#0#0#0#1#0#2#0#0#2#1#0#4#0#0#0#1#0#0#1#26#2#2#0#4#0#0#0#1#0#0#4'X'#0#0#0#0#0
+ +#0#0'H'#0#0#0#1#0#0#0'H'#0#0#0#1#255#216#255#224#0#16'JFIF'#0#1#1#0#0#1#0#1#0
+ +#0#255#219#0'C'#0#8#6#6#7#6#5#8#7#7#7#9#9#8#10#12#20#13#12#11#11#12#25#18#19
+ +#15#20#29#26#31#30#29#26#28#28' $.'' ",#'#28#28'(7),01444'#31'''9=82<.342'
+ +#255#219#0'C'#1#9#9#9#12#11#12#24#13#13#24'2!'#28'!2222222222222222222222222'
+ +'2222222222222222222222222'#255#192#0#17#8#0#24#0'@'#3#1'"'#0#2#17#1#3#17#1
+ +#255#196#0#31#0#0#1#5#1#1#1#1#1#1#0#0#0#0#0#0#0#0#1#2#3#4#5#6#7#8#9#10#11#255
+ +#196#0#181#16#0#2#1#3#3#2#4#3#5#5#4#4#0#0#1'}'#1#2#3#0#4#17#5#18'!1A'#6#19'Q'
+ +'a'#7'"q'#20'2'#129#145#161#8'#B'#177#193#21'R'#209#240'$3br'#130#9#10#22#23
+ +#24#25#26'%&''()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz'#131#132#133#134#135
+ +#136#137#138#146#147#148#149#150#151#152#153#154#162#163#164#165#166#167#168
+ +#169#170#178#179#180#181#182#183#184#185#186#194#195#196#197#198#199#200#201
+ +#202#210#211#212#213#214#215#216#217#218#225#226#227#228#229#230#231#232#233
+ +#234#241#242#243#244#245#246#247#248#249#250#255#196#0#31#1#0#3#1#1#1#1#1#1#1
+ +#1#1#0#0#0#0#0#0#1#2#3#4#5#6#7#8#9#10#11#255#196#0#181#17#0#2#1#2#4#4#3#4#7#5
+ +#4#4#0#1#2'w'#0#1#2#3#17#4#5'!1'#6#18'AQ'#7'aq'#19'"2'#129#8#20'B'#145#161
+ +#177#193#9'#3R'#240#21'br'#209#10#22'$4'#225'%'#241#23#24#25#26'&''()*56789:'
+ +'CDEFGHIJSTUVWXYZcdefghijstuvwxyz'#130#131#132#133#134#135#136#137#138#146
+ +#147#148#149#150#151#152#153#154#162#163#164#165#166#167#168#169#170#178#179
+ +#180#181#182#183#184#185#186#194#195#196#197#198#199#200#201#202#210#211#212
+ +#213#214#215#216#217#218#226#227#228#229#230#231#232#233#234#242#243#244#245
+ +#246#247#248#249#250#255#218#0#12#3#1#0#2#17#3#17#0'?'#0#243'V'#7#185#252#5
+ +'9'#14#7'LS'#182'c'#183'>'#180#190'S'#31'j'#139#158'e-'#11'6'#22#179'_'#221
+ +'%'#181#184#221'#'#244#4#224#1#220#154#236'l|)g'#29#176#154#225#133#195'c'
+ +#230';'#138#168#250#127#141'P'#240#166#142#160'6'#173'4'#142#22#22'!'#21#127
+ +#139#142's'#237#205'v'#199'Of'#211's'#29#196#138#164#130#172#227'y'#245#199
+ +#204#14'Gnk'#193#204'1'#181#28#221':R'#178'['#255#0'_'#228'}>['#132#135#179
+ +'U*F'#237#237#127#242'8'#29'{B'#254#204')='#185'2[I'#223'9'#218'~'#181#159#26
+ +'[%'#163'I*'#207'$'#164'e'#21#8'U'#239#206'O^'#159#206#187#157'^'#6#187#180
+ +#154#218#212#198#20#141#178'g'#248'A9'#227#223#25#174#11'T'#159#201#214#165
+ +#183#182'FKh$Q'#18#169#200#222#188#3#142#132#231'='#187#154#239#202#177#14
+ +#189';Tz'#175#235'S'#151#27#151#168#212'r'#165#29'-{'#127#145'5'#165#144#158
+ +#192']J'#229'0'#229#25'q'#200#255#0'9'#171#209'"'#249'x'#141'v'#199#250#159
+ +#173'R'#214#220#232#250'D"'''#204#174#199'~'#227#193'-'#201'8'#233#218#159
+ +#167#204#247'Vp;'#156'n@'#219'k'#182#162#234#182'9'#232#194#17'v'#182#166'h'
+ +#24#224#10'w'#150'~'#241#162#138#153'3'#203'QI'#27'ZF'#175#171'Ag%'#141#166
+ +#193#11#146'Y'#153'yL'#245#193#247#173'd'#210'uy'#244'[y'#173#183'H'#129#220
+ ,#24#227'~@$r}y'#207#233'E'#21#199'V^'#207'X'#165#171'>'#131#1'y'#194#210'{'
+ +#17'X'#223'K'#166'h'#215'Q\'#233#183'kr'#146#191#204'@'#196#153''#224'5'#250#132'i '#142#195'C'#242#1#252
+ +'~;'#239#193'lv'#150#180#151'd'#173'D'#19#190#146#0#27''''#171#219#176#246
+ +#216#239#219#252'v'#240'!2'#25'R'#130'T'#2'[O'#246'!'#31'r'#220#215'o'#184
+ +#236'h'''#183'o'#157#246#216#26#241#237#20' '#12#228#128'7'#220#157#159#175
+ +#159#189#247#31#224#127'n'#197#213#243'f'#220#166#26#209#170#170#145#213'$'
+ +#173#173'/a'#212#21#127#182#128#236#0'='#183#219#194#150#20#233#14'#iq$kd'
+ +#244#232#235#185'?#'#227'~'#251#209#216#246#236#5')'#205#236#5'%D'#252#171
+ +#251#137'='#187#29'hv'#252'~'#255#0#242'P'#203#227#167#220'#`v'#233' '#252
+ +#251'{'#130#7#200#246#253#247#225#242#225#207'.'#252#177#207#22#6'6'#7#143
+ +#184#138#8#174#244#222#230#246#201'~'#14'''F'#200#4#186'_'#178'S'''#235'&'
+ +#161#8'W'#167'UX'#137'vo'#184#164#4#198'Ke'#199'Y'#138#207'r\'#23#24#197#218
+ +#204#231#178#244'0'#248#170'I'#215'b'#246'B'#194'V'#130'1'#221#130#245#190
+ +#139'H'#225'XG'#18#7#150'B'#10#198#142#218#30#14'0'#152'<'#191'"'#189'_'#19
+ +#129#198#222#205'd'#237#144#149#233'P'#174#243'X'#149#152#168''''#165'GLq!a'
+ +#234'O+G'#12'H'#12#146#200#138#9#12#186'#'#174't'#198' B'#136#253#149#132#199
+ +#144#196':'#248'L;.\'#151#214't'#134#216#141#29'.<'#242#138#136#5'-'#160#148
+ +'oz'#0#18'e'#207#30'y)'#230'\'#186'S'#31#212#180'h'#193#225'H'#132#185'1'#157
+ +#189'u'#136#210'#'#188#227'aPU2'#173'+]'#135#160#242#250'P'#226'}'#20#190#210
+ +#22#29#232'_II'#184#174#1#242'}'#136#249'x'#197#163#200#199'"Wd|'#162#242#10
+ +#238#179'l'#142#10'~'#161#194#242'T'#165'D'#170'd'#170'_'#242'X'#144#0'G'#211
+ +#183#29'O<'#227#189'N'#203'q'#215#148#22#135'9'#252'k/'#138#192#202'&'#176
+ +#212#233'ii'#4#183#14'J'#217#155' '#21#130#151'd'#164'zo'#188#233#236'P'#150
+ +#146#181#235#164#134#137#216#20';'#152#254'4FZ'#221#252'_'#151#171#136#161
+ +#142'N'#186't'#179#185#233#218'<'#181#251#160#143'B'#197#28'T'#158#156#21#169
+ +#202#200#235#27#220#146'y'#220'2'#153'k'#193#239#140'hG'#148'_'#129#206'=r'
+ +#164'9?5'#185#23#252'F'#194'/'#165#197#240#215#225#169#20#18'H'#170#223#149
+ +#200'd^'#189#155'7'#11'!'#212#173#143'||pI'#161#28#246#21'D'#134#129#249'_'
+ +#203#15'7'#240#202#21'31'#195#165#10#2#178'Z'#201'hW'#252#234#140#167#164')*'
+ +'zT@'#183'!m$lLi'#158#141#16#181#14#146'|G'#244#173'Ai'#218#142#142#253#187
+ +#245'k'#219#219#127'o}'#143'q'#223'}'#187'k'#170'Jv'#178#11#152')'#18'`7a[-'
+ +#146#169'prWQe'#14'g'#168'\K'#130'$'#130#11#141#18#148')'#149'Fu'#135#19#24
+ +#244#166'HJT'#10#169#215#207'O'#149'h\Uh'#215')'#241#245'b'#171'p'#172#130'R'
+ +'['#186#160#141#210#244'ln'#233#245#3#235#195#13#165'If'#170's'#203#244#195#9
+ +')j4'#178#132#180#148'3!'#8'l'#187#201'o'#197#138#242#222'CO'#129#243#232'q'
+ +#24#238'Eu'#141'|fg'#21'#E'#142#191'qB'#149#161'v'#140#242'L'#248#251#243#130
+ ,#194#23#130'{'#20#236'H'#4'q'#8']'#145#10#7#241#13#248'$~'#9#143#185#202'|'
+ +#187#205'X'#204'a('#185#147'1'#133#200#178'X'#202'b+'#15#235#181'V'#236')'#0
+ +#200'V'#128#232#216'V'#135#214#130#30#185#133#139'*'#142#18#188#18#150#209
+ +#221'j'#8'H'#30#223'*'#255#0#27#238'>@:'#214#207#199'o'#31#4#180#157#182#195
+ +'`'#13#128#173#157#149#1#174#218#252#232#131#175#248#252#248'+'#144#183#9#209
+ +'P '#235#190#182'zA'#4#254#251#209#237#210#15#198#193'>'#29#220#10#183#138
+ +#235'P'#213#215'&'#206#201#237#217'['#201'E~'#11#131#8#145'-'#173#149#214#148
+ +#165#203#204#166#197#169'P'#241#216#18#22'[n4z'#186#219#252#134'o'#221#255#0
+ +#133'P'#203#140#204'z'#232'u'#177#141'H'#12#206#236#16#5#29']M'#177#165']'#13
+ +'oG@'#19#243#174#254'('#227'q'#180#175'e*C<2'#220#151#161#164#179'u'#132'U'
+ +#171#160#208'yg'#148#251#181#178#170#139#26'K+?'#181'"w'#4#4'44'#204#148#135
+ +#254#150';'#178'Q'#21#176#244#197#176#203#143#8#204')io'#214#148#227'aH'#140
+ +#199'Z'#130#11#242#20#219'IQ'#233'+'#7#192#219#22#167'R>'#168'3+fA'#152#149
+ +'t'#169#153#209#221'i'#192#181'!'#183#17#217'i'#210#144#243#15'6'#251#14''''
+ +#173#167#152'q'#183#154'['#140#184#149#155'0'#127#205#199#18#240#191#23#215
+ +'&'#171#203'FX'#252#182#159'Kp'#171'/s('#151'TTm'#148#254#146#231'f'#22'('
+ +#182#200'j'#157#150#165#168#10#198'p'#184#241#222'q'#167'#96;'#229#191#21'Q'
+ +#230#27#204#238'I'#206#246#245#233'E~'''#199't'#212'-Hb'#159#24#194'a7'#25'q'
+ +#210#247#170'}K;W'#148#187#155'G"'#250#235#250'f'#18#229'udd'#169'I'#137'S'#9
+ +'k'#223#137#10'X'#28#197#199'e'#154#151#228#160#29#196#150'\+'#176#236'@'#16
+ +#128#204'w'#240'O'#180'/~'#237#240#9'2'#188#31#7#141#165#29#136'yre'#243#12
+ +#145'8'#161'W'#29'2S'#143'eL'#171'%'#169'_J'#21'Y'#138#146#139'+'#20#0#196
+ +#161#182#15#16#211#142#245'8'#243#138#0#142#224'~'#228'v'#217#254#237#15#131
+ +#175#216#1#175#26#214#251'h!'#13''''#191#178#148'I$'#159#246#141#13'v'#236
+ +#162'5'#254'|IO)'#156'WS'#204#220'Sg'#152']'#151#172'r:l'#150#211#17#153#11
+ +#214#143#6#186'"'#235#235#170'm'#171#237#222'H'#151#1#14#253'}}'#204'Re/'#234
+ +#225#155#24#246'Q'#19#141'Jf }'#229#212'~ '#227#156#6'T'#153#23#22#245'Yu'
+ +#164'W'#186#147#25#151#230'I'#135#25'e'#212#254#137','#215'WV'#202'}'#159#188
+ +#4'70'#149#171#165'&'#26#18#180#132#193']'#182#216#233',E,RI5yL-'#12']*'#161
+ +#151'{!'#159'@'#169'm(?'#190#192'?}'#240'ya'#204's'#176'bg'#168#216'lf:'#218
+ +','#237'ag-$p{u$'#193'b'#235'ie!'#181#20'['#233'#N'#200'6|0'#24'G'#30'd'#249
+ +#170#153'S'#17#28#135'T'#15'T'#139'Yh[Q'#24'lw*B'#143'Iy]=E(oaJ'#3'd'#2'w$ 1'
+ +#142'q'#236'%A'#199#150#137'6.t'#135#236'V'#7#213#201'ZR'#174#200'Z'#7#232'G'
+ +'Q_'#218#211'J'#29#146':'#137'$'#147#178#231'9'#157'!'#143#229'u'#209#145#14
+ +'*'#128'n'#9#237#174#223'='#188#17'3R'#208'ZT'#250#131#171
+ +#208#208':'#208#236'{'#1#219#224#145#179#223#254'w'#224#221#180#197#142#141
+ +'!'#164#142#253#244'5'#220#29#130#15#207#176#248#222#191#29#252'kQZ'#156'=)Q'
+ +'I uk'#240'?'#26#246''''#182#251#31'c'#236';'#248't'#16#0#0'%gd'#149#14#227
+ +'['#7#246#217#237#237#175'n'#221#247#227#157'''i'#7'W'#244#244#251'@'#236'~'
+ +#0'?'#249'?'#251#191#12'\g'#30' F'#243#205#28','#253'%'#161#136#245'H;/Pf'#12
+ +#195'L'#7#193#223#187'c'#244#30'=Hy'#199'@m'#162#27'H'#4'('#168#232#144'u'
+ +#236';'#17#219#228#233']'#245#173'x'#245#20'6'#195'aD$'#168#30#197'}'#246'O'
+ +#190#191'>'#222#223#227#190#183#224#9#1'*'#210#180#165#31'}'#146'{{'#146'H?'
+ +''''#182#137#214#183#243#175#30#186'J'#210#14#213#160'H'#233#31#30#222#199
+ +#251#182'{'#15#145#220'k'#219'^hX'#187'HI'#151#165#13#206'5'#136#200'u'#212#134
+ +'C?'#229#243#247'M'#140'Y'#178#27#166't'#183#148#176#194#203#204#241']'#157
+ +#30'9'#228#190'8'#235'7i'#241#177's7'#4#149'-'#214#173'4'#182'i'#197#211'$'
+ +#158#162#188#133#4'k'#14#212#23#29'!zW'#161'K(d'#1'z|7'#248'_6'#229#179#178
+ +#197#181'qo'#142'Y'#215#216#165'R'#225#227#145#177#139#236'X'#183'H'#204#145
+ +#14'e'#206''''#144'_Glgu5'#178'$2&'#220#214'7>'#168#190#251'0'#209'>;'#146
+ +#216'W'#135#199#146#233'0'#172#254#163#253'9'#203#154#143'.&_'#6'Y'#130#137#1
+ +#30#139#238#196#250'w['#244#246#164#159#169')Z'#164'GB'#22#133#150#227'<'#180
+ +#171#173#180#143#9#254'+'#228'O4'#190'd'#248#130#254#147#206'g'#151#236'+'
+ +#129'2'#12'[,'#193#173'x'#174#242#172'*'#170#241#228'UFuy'#163#17'p'#7'2|'
+ +#226#250#145#133'-'#145#142'A'#181'VC'#26#147'*'#196'2;HVi'#174'\'#23#225'\'
+ +#147#242#225#254#147#139#134#229#234'i'#203#136#216#156#165'A'#178#140'P'#150
+ +#222#153'Y2+'#145#223'q'#182#148#233'i'#18#27'd'#186#244'd'#151#150#132#202
+ +'m'#128#20'u'#219#163'-'#141#189#140#228#181'i\'#197'c'#184#167''''#199'Z'
+ +#158#180'u'#248#207'#'#198'r'#26'rI^'#181'{'#152'\'#182'?/'#137#138#140',,<'
+ +#145#196#201'f'#149'K'#241'^'#130'x'#230#245#186#18'w'#225#194#228#142's'#11
+ +'f'#205#250#18#199#4#210'5v'#173'pYd'#146#172#157#8#251#142#224#235'eegY"'
+ +#219'D'#192#134'UU!E'#7#249#162#224#225#229#247'6L'#23'd:'#156'v'#202'3'#243
+ +'+'#229#203#233'Kl'#22'V'#18#166#19'%E!'#196')'#11'm'#198':'#255#0'WD'#183
+ +#183'T'#1'(>'#3#181#197#239#231'r'#6'E'#147'B'#201'`'#212'`|{'#147#223#210
+ +#229#181'1c'#207#166#168#200#224#181#244#245#147#238#208#248'fBa'#190#235#207
+ +#211#196#130#195'Rm'#167']O'#129#22#182#11#210'T'#151#27#151'~|9G'#11#243#25
+ +#158#241'g'#18'q'#29#169#203#236#205#154'"'#207#187#162'K'#15#16'%'#167#208
+ +'['#17'-%'#132'D'#142#227'L'#161'n'#204#185'}'#185'M@m'#183#157'r<'#183#27'['
+ +'%w'#230#235#141#184#243#203'o'#150#174'='#227#154'6+'#233'W{'#153'A'#178#202
+ +'_'#18#151')y'#0#199'q'#155'e'#207'jM'#148#182#219#155'fZ'#157'c'#21#234#247
+ +#164#183#29#134'&'#161#133#193#173#170#136'"'#211#195#219#175#195#4#188#131
+ +#149'p'#239'.'#207#152'mo'#15#200#243'SzS'#228'2'#221'4'#30#190'"'#141#153
+ +#153#243#183#163#182'aeW'#161#8'(,'#13'J'#163#213'`'#196#158#188#146#243#171
+ +#135#227'1'#30'by'#139#152#224#149#163#207#224'pqU'#179#143#227#152'X'#165
+ +#190'2<'#154#253'Z'#241#255#0#179#152#248'($'#205')9K'#1'^*'#197#218#3'2'#196
+ +#136#10'(H'#175#200'X6Y'#229#239#137'|'#189#243'7$s6)'#203'xW'#153'Lr'#214'e'
+ +#141#21'['#212'6v'#24'D'#232't'#148#215'#'#232#226#214#180#203#146')'#150'.'
+ +#164'PZD'#158#137#14#179'gR^'#15#160'Lj'#27'L'#172#236'Zl'#222'+'#151#205'v'
+ +#30'Y'#178#250#238#7'3!'#196#151#201#200'1'#146#152'-Z'#201#149#10#174#255#0
+ +#249'3N7p'#221#28#171#8'R'#161#183'i^%'#192#137'1'#148#177'1i2!72;A'#169#192
+ +'2'#171#187#24'5'#212'up'#169#161'U'#201'O'#169#234#205#135'ik*'#197#244'6,c'
+ +#169#228#206'~*kC)\h'#1'L'#194'b['#201'}M'#169'>'#147#9#145#8#229#207'2('#224
+ +#134#252#170'V'#243'NOa'#194#246'(N?_'#128'#'#28#194#218#177#151'[avn'#127
+ +#167'"'#229#207'c'#182'YA'#170'r'#245#213'MEcv'#205'EK'#235'\vc'#179#5'J'#137
+ +#226#213#227'x'''#152'9'#28'<9n9'#200#248#143'6'#198'E'#204#174#214#202'g'
+ +#175#199'?'#29#136#241#26#150#165#151'!c'#21'['#30#150'VK'#212'Va'#141#167'='
+ +#142#138#215#19#26#215#165'@'#150#19#212'W'#243#220#247#8#224#185#156'o'#12
+ ,#231'\['#152'pNj'#252#22#134'r~='#19'&j'#237'^C'#158#138#171#241#220'6Q'#174
+ +'H'#158#136#147#31#18'fr'#209#194#205'j'#181#156#240#196#171#9#241#147#129','
+ +#252#131#166'.'#23'S'#205#174#12#138'$'#172#10#197#28'}'#148'c7N'#206#142#203
+ +#10#136#236'|'#214'%'#212#167#148#165#180#152#238#193'Dz'#136#246#18#29','
+ +#182#149#24'^'#175#162#240'y'#150#206'9'#147#212'n'#193#155#188'O/n'#230#158
+ +#213#165#204#131'2'#28#170#140#138#4#133'GZ'#218#149#9#169#233'L'#166'V'#16
+ +#234'}='#198#154#20#218#251#21#160#5#16'k'#197#30'W '#241'G'#151#204#163#142
+ +#31#181#149'''+'#207'*,'#205#213#148#151#203#172#211'I'#181'a'#181#177'GZc'
+ +#180#199#167#2#190'CirT'#134#26#14#216#216'9"'#127'B'#18'b'#176#220#11#228'^'
+ +'y'#227'>'#25#197#233'8'#183#14'6'#249#253#254'('#155'S'#146'I'#142#203#181
+ +'5'#231'&'#159')o'#217#198']'#133#161#7#208#141' *+h'#132#213#131#204#165#164
+ +#166'V'#151#212#162#150#204#195#14'O?'#146'8'#191'R'#236'?'#155'1'#195'$q'#21
+ +'Ib'#137#4'B'#192'; F'#237#24'eb'#195#168'0m)%'#21#207#139#158#175#27#224#216
+ +#129#158#179#30':'#242#198'_'#242#146#201#238'SjI'#173#24'z'#217#139'4'#213
+ +#250#214'9 Tn'#134#235#0#143'OfH'#226'MY'#223'<'#185#17'$2'#252#244#14#167'P'
+ +#180'}0'#243#210#8
+ +'PO'#216#174#227'D'#245'l'#247#209#31#7'G'#227#252'v'#223#131#216#172#167'J.'
+ +#15#211#217'*G'#201'BF'#202'I'#3#184'R'#187'h'#235#251#189#252'F'#205'3'#149
+ +#146'BI!I'#0#29'o]'#194#239#254#237#5#254#231#239#238'HX'#177'3'#162#25#159
+ +#222'Q'#28#245#177#8#9#1#153#200#27#10#6#203#21#29#128'?'#30':5'#242'Q'#195
+ +#145'8'#131#130'q'#143'R#M'#229#25#220'X'#217#166'O+'#211#2'J'#141#179#2'E%j'
+ +#214'G_'#163'[P'#228'u'#250'D'#165')'#153'*Y'#233#4#18#23#156#131#203'Q0'#204
+ +#239#30#171#16#158#150#151'P'#152#151'('#141#222'K'#209'&'#165#199#217#250'v'
+ +'v'#148#186#237'o'#160#237#131'}d'#21'4fDh'#5#202'=R'#143#142'0'#234#252#247
+ +#9#194'r'#140#30#218'"'#241'|'#155#18#135'y@d4'#231'Su'#30#162'!@'#142'T'#210
+ +#148#149'-,'#6#155's}%'#167'[u'#135#16#133'2'#161#226#22'y'#232'{'#10#224#214
+ +#248#255#0#145'k^'#143#146'g'#179#30#175#21#148'S&'#170#20'['#168#202#148#26
+ +#179#219'P'#217'zlh'#241'*'#154#150#235#210#192'['#145'dF'#138#210#130']'#144
+ +#134#215#141#9#229#239'>'#243#15#204#172#229#236#254#30'k9.A'#147#201':'#250
+ +#214'cX'#231#181'fb+'#193#19#25'K'#173'z'#176#24#150'0B'#165'xb@@'#17#133#27
+ +#239#132#155#142'p'#174#15#129#197'al'#215#143#21#129#195#227'+A$HdG'#171'^'
+ +#8#131#218'r'#160#137#164#182'}K'#15'''S'#27#18#203'$'#170'O'#168#9#156't'#14
+ +#211#230'Q'#240#217'5T'#22'v'#144#28#147'"&WsC'#10#12#168#213#240'>'#136#183
+ +'Oq2,'#199#218#178'\'#151','#148#212')'#177')'#235'-'#172#24'e'#185'2'#236'b'
+ +'C'#141#13'R'#155'Wr'#142'/A'#141'UPB'#171#134#204'U'#153#147#214#232#31#170
+ +#244#162#242#27'q'#249'R^^'#220'y'#210#242#27'Iq'#127#237#9'BB[BR ?'#145'O8'
+ +#217#223',rG1'#210'g'#216#230#13#134#224'xn'#22's'#5'd'#248#237'y'#164#167
+ +#196#160#214#204#137#30'5vami9L'#221';eP'#236#235#24'v'#211#12')'#173#183#143
+ ,'OzS'#133#167#144#211#12#156#191#226#186#214'sV'#234#174'xZ'#162#18'L'#167
+ +#215'RX'#204#165#140#130'4g'#29'Kq'#157#159#18'EChI,'#169#6'KL$'#196#216'*i'
+ +#213'$z'#198#199#242#127'$<'#209#204#240#252#143#1#134':'#153#236#174#11#27
+ +#133#15'3['#169#20#14#206#194#206'5}y^'#20'6'#162#167#11'VE`'#162' '#136#196
+ +'$2'#171#145#170'~h`^'#213'K'#150'/^'#173#142#177'b'#250#214#169','#22'dx'
+ +#197'R'#149#172'3$*'#251#143#212#153'}1'#238':f'#17#130'VEY'#241'-'#246#216
+ +'l'#169'n6'#211'M'#165'Ju'#194#164#164' $l'#151#20'O'#218#18#6#254#237'h'#3
+ +#191#17#239'%'#153#27#150'$'#183#142#209#188#196#220'6'#4#224#230'Qz'#203#168
+ +'1'#167'9'#24#18')j\'#10'R'#165#190#160#165#9'S'#163#165#200'P'#210'T=W'#165
+ +#161'1'#13's'#243'7'#241#13'v'#6#29#127'k;'#142'q9'#245'Q'#153#17#229#177'+ '
+ +#176#191'['#142'K'#146#220'('#177#205#26#147#22#165#229'6'#251#205'u'#25'.$'
+ +#161'H'#218#20#8#27#147#30'L+'#179#199'8'#187#253'D'#207#162'.'#141#254'E,_c'
+ +'x'#170#216#17'WE'#138'<'#130#245'Pv:'#30'y'#12'.'#193#183'~'#170''#162#220#242#242'{'#17'Y'
+ +#175'1'#185'>'#209#184'*'#172#195'j'#30#186'i'#13#197'R'#139#183'JRcD'#13'Hy'
+ +#201#11#10#137#234'-'#215'T'#169#7#245'T'#148#0'T'#133'zq'#183#12#195#242'~Q'
+ +#203'*'#176#188'R'#190'B'#172'm'#164'!'#167'_y+Dz'#216#202#235'rE'#140#231'R'
+ +#29#17' '#197#138#212#137#14#188#225#11't'#182'#'#197'i'#233'N6'#131'q\m'#197
+ +'X'#151#13#213'#'#31#198#225#182#183#162'U'#199'b'#215'!u'#164#166'vAa%'#213
+ +';&c'#203#10'R'#155'e'#181'0'#17#14#24'Qn$u'#244#142#167#157#146#243#215'k'
+ +#25#204'9&'#19#142'Y'#226'8'#156#197#250'xK'#211#207'f'#213#8#29'B'#207'%'
+ +#184'!'#173'b&'#157#191#222'V'#188#209#192#190#172#2'a'#3#185#146'C'#23'T'
+ +#175#180#31#157#156'w'#129#242#158'WW'#158'rl'#29'.A'#230'D'#24#218'X'#186#25
+ +#203#171#252#220'u'#28'vB'#206'F'#180#255#0#147#137#162#160'.@'#214#236'W'
+ +#171'q'#234#181#180#133'`'#140'J'#139#18#18#230#221'X!'#194#182#212#162#226
+ +#23#246') '#244#237'*WJ'#135'm'#16'H:'#26#238'7'#219'Do'#199'1'#190'b'#242#6
+ +#236#249#131#144'e%'#134'c'#188#156#134'lI+`'#143'J\'#200'.'#170'+'#246#30
+ +#152#3#210'ro'#164#151'\@'#26'K'#165'a?'#159#23#159#230'/'#155#168#248'g'#143
+ +'rL'#190#209#246#196#168'U'#238#162#154#15#174#17'"'#194#226'Xv5DV'#16'~'#229
+ +#153#19#146't'#161#160#150'b'#205#146#10#155#133' '#167#155'['#203#185'V'#243
+ +#167'['#216#186']'#155'b'#251#246#19#29'Q'#218#148#252#167'W%'#245')J'#217
+ +#223#168#226#182'O'#201' '#239'{'#241'/'#194#234#180'or'#211#130#23#161'cVn'
+ +#193#156#177#145#194#130'4U'#1'Vf'#248#234'-'#173#157#248#169'~m'#228#21#226
+ +#196#227#163'fi'#204#175'bT'#223'x'#162'H'#196'q'#131#166';2'#23'q'#210'A'
+ +#246#232#246#4#19'/<'#147'F'#176#155#200#217#132#152#150#179#160#192#168#199
+ +'k'#215'a'#9#159'EUw+'#177#155'!'#129#14#201#149#244#173'2#'#165#13#204#135
+ +')'#149#135#24#13#186#133#165#214#164')'#9#181#10#150#160#200#150#211#10'H[l'
+ +'6'#236#137'il$'#163#209'e'#178#160#200#233' '#0#227#157')X'#237#176#179#223
+ +'g'#188#8#242'9'#137'K'#139#197'6'#249#186#155#12#189#157'd'#179#228'F'#144
+ +#224#215#169'M@'#149'UA-'#148#128#3'k'#146',6'#18':'#20#182#247#221'Cbq'#227
+ +#208#231'Bzd'#151':'#156#142#252'T'#176#174#189'%en<'#149' '#164#0#18'F'#219
+ +';'#223#184#214#247#223#192#207'$'#154'+'#25#12#129#142'eVR"B'#172#1'c'#18
+ +#132'm'#232'l'#144'Y'#186#9#4#252'o_F'#156':'#133#220'V'#3#24#146'@'#239#20
+ +'Q4'#179'z'#132#144#12#238#178'3*'#147#176#23'J='#160#18#164#251'w'#225#206
+ +#131#29#19#245'"cE'#182#195'^'#148't'#164#164#4#161'*'#29#180'u'#239#238#14
+ +#189#180#6#128#215#140#240'^'#213#161#136#202#20']`%_jC'#170#29')'#236#9'JB'
+ ,#189#142#199'q'#240'w'#175#159#25#224#1#169#219',Lm'#164#208#233#4#182#254#0
+ +#239#237'='#247#251#253#248'b'#197'~'#1#26#9#22'F}'#14#166#10#186'?'#31#27'`'
+ +'u'#173#253#3#174#223#167#136#27#26'"'#130'z'#212#160#18#7'~'#221':'#216#248
+ +'''['#252#247#223#192#26#241#176#22#194#135'J'#129')_e('#236'v'#0#130#127'#d'
+ +#252#31#248#215#143'Jl'#132#15'T'#158#130':'#246#9#4'o'#184':'#29#191#207#127
+ +'q'#254'G'#128#138'o'#172#132'!* '#253#157'Z '#247'='#142#245#242'H'#209'?'
+ +#253#240'~'#214'UP'#180'`k'#224#232#13#236#149#209#248#215#217#255#0'O'#25
+ +#179#139#192'_'#188#202'#Q'#233' '#13'$'#236'OB'#168#0#239#232#247#214#128
+ +#222#201#241#181'O'#146'=4i'#197#236#247'H'#216#214#247#240'~'#0'='#143#207
+ +#249#238#27#249'Y'#127#239'p'#149'(o]'#181#173#146't}'#246'4G'#183#182#251
+ +#141#239'j'#24'0'#145#29#7'{'#29'J'#3#164#164#21'k'#167'e@'#159#142#173'l'
+ +#246#215#199#185#240'~'#196#6#136#11'))'#26'$'#252#3#178#127'`'#127'q'#191'c'
+ +#238#0#241#5'4'#172'Y'#203#30#224#157#16'~'#187'k'#231#239#231#252#180'~'#193
+ +#26'A'#20'h"'#137#152#178#19#25'v;'#27#4'l'#141#236#239'{'#215#237#161#245
+ +#225'7'#22'8'#142#217#232'l+I'#236'u'#221#4'w'#255#0#27#208#214#253#255#0'o'
+ +#1'W`ASh'#1'J%@'#244#158#219'>'#224#254#228'v |'#239#227'`'#168#172'ChmM'#180
+ +#180#161'*;#_q'#7'cz'#29#181#191's'#174#224#129#219#229'>'#205'p'#210#214#128
+ +'u'#217'E_'#251#30#251#215#239#219#254#192#252#248#231#245':'#253#164#146'?B'
+ +'v;h'#253#158#250' '#17#219#235#127'^%q'#21'k'#199'7'#169't'#180#145#128'v'
+ +#160#136#214'Bu'#176#205#219'`}'#254#163#182#136'$'#25#3#196#190't|'#203#240
+ +'<'#6'('#248#207#150#178#10#10#8#166'h'#133#142'O'#143'Y'#146'cp'#149'b'#175
+ +'Vb'#161#210#228'P'#173'`E['#207#31#168'W'#211#199'i&OT'#133'$'#186#181'('
+ +#145#196#229'<'#131#149#179#188#131''''#229'L'#151'+'#205's+'#231#19'1'#139
+ +'W'#222#187#147#21'N-2'#156#176#130#154#138'oF'#142#190'2'#212#150#164#199
+ +#140#221'tX'#197#127'X'#150#254#242#7#141'\i'#193#247'Y'#251#198't'#149#26'\'
+ +'a'#135#16#153#215#179#26'Y'#11#233#9'Z'#216#174'g'#236'2'#164#244'w '#20#182
+ +#202't'#183#212#141#148#248#155#204'aX'#22'9'#137#28'Z'#182#169#170'j)?L'#228
+ +#233#206'4'#6'S'#127'"3'#205#201#139'='#19'T'#143'^0C'#237'4'#252's'#31#162
+ +',r4'#27't'#165'['#128#129'0'#216#220#177#200'V'#196'SL'#140#196#173#155'u'
+ +#234'A'#29#134'G'#209's%'#132#140'H'#211#18'X'#144#174#25#148#237#201#223#139
+ +'I'#229#166'W'#157#219#20#12#185'L'#154#240#236'q)_'#23#147#189'v'#197';'#16
+ +'t'#136#210':'#20''''#148'F#'#133#10#188#18'4'#127#151#133#149'Lj'#199'`'''
+ +#188#164'W'#179#147'r'#230'k'#197'l'#192#190'r'#199#153'|'#186's&'#11#142'PV'
+ +#204'E=m'#198'Z'#198'1'#253'MA'#14#222'BV'#235'u'#149#10'V''!'#159#169#153#29
+ +'H'#143'n'#244'v'#164#167#210'u'#198#220#141#211#132#234#134'$'#227#247'm'
+ +#215#177'w'#141'ZH'#199#175#233'd0'#236'9'#213'7T6'#142'Q'#206#171#177'a-'
+ +#218#143#174#139'*2'#163'X3'#233'4#8'#211#200#245#150#218#2#205#231#255#0#12
+ +#132'q'#188';nC'#135#31#13#133']'#153#250#209#156#163#203#172#20'g['#203#166
+ +#150#203#171#155'C'#22'\'#181#21#198'_'#173#17#203''''#27#134#150#21'>:_'#245
+ +'P'#166'+]p'#188#158'a'#127#134#199#17's'#13#165#158'['#134'MW'#24'f'#22#211
+ +#231'['#219#189#10#182'-'#214'3smg'''#234#236'mf'#209#188#227'.'#197#159'='
+ +#229'<'#236#233#21#22#16#132#199']S'#175'%g^'#3#159#205#254';'#139#230#249
+ +#236'nR'#27'4itckKp'#1'a'#147'!R'#25':'#165#150#26#236#242'G^Zv'#171'(A'#28
+ +#214'W'#211'I$UI:V'#220'Q'#225'Y,'#142#11#31#148#199#180'3='#177'zu'#172#196
+ +#214'?'#148#176#240#136#211#173#151#211#150'X'#173#195'l'#177#30#157'p%e]'
+ +#186#146'ym'#243#12#235#135#136#178#222#152'U'#238#5#166#173#164'*<'#135#28
+ +'K'#29'V'#208'Q'#245'jJ'#162'F'#0'G'#236#234'R'#158#174#181#4#130#165#13#159
+ +#29'"y\'#228#222'8'#243'3'#229#155#133#178#172#127'$'#163#166#204'c'#226#208
+ +#241#156#130#153#217#173#134#169#149#136'U5T'#229'}'#146':C'#200'z:'#226'CL7'
+ +#27#142'C'#140#205#219#200'u'#182#138#196#14#243'C'#252'$9*7'#21'Y5A'#204'XD'
+ +#243'2'#234#134'3'#201'^'#19'wD'#219#13#191'o'#13',9!'#198'/'#174#139#205'._'
+ +#160#195#169'K'#12'$'#7#131#160#233'%'#11#142'\'#19#252'63'#206#27#181#254'|'
+ +#247#153#252#166#138'k'#204#172'M'#169#227'Jf'#170'+'#165#169'h'#27'f'#193
+ +#204#142'M'#212'{'#4#246#9#19#27#172#133'5'#180'$z.'#180'@'#240#17#231#175'/'
+ +#242'7'#156'p'#170'x'#156#223'7'#171'W)'#140#191'g!'#143#160#152#188#245#153
+ +#237#173#138#176'Wt'#233#130#128'09'#150#164'm'#5#158#176#168#209#148#148#24
+ +#228'n'#158'.#'#143#243'S'#136#249#144#249#12'_'#8#179#146#227'9|'#6';'#25
+ +#145#189#252'K'#15'HP'#185'N'#238'Ft'#150#187'['#177#25#177#209#21#182'Y'#171
+ +#170'u'#184#149'%'#139'o'#24#6#194#188#225#231'8O'#14#241'n'#127'+ '#203#171
+ +#229#203#169#199#221#146'QM%'#2'$'#137#239#198#148#154#170#184#242#167'2'#218
+ +#230'L'#155'b'#220'f'#12'h'#209'V'#19#29'n<'#228#145#208'|S'#159#16#127#20'n'
+ +':'#201'"'#201#198#252#198#241#251'PM'#130#161#7'2'#28'v'#165#25'6#%'#200#208
+ +#26#173'rE'#142'/`$\Q'#165#216#209'a'#184#184#245'''&m'#233#169#151'#P'#27
+ +#144#211'-'#7#243'!'#229#198#207#145#236#172'R2'#28#147'!'#203#233'K'#140#186
+ ,'3,'#134't'#234#251'_C'#213'C'#9'a'#183#20#220#10#153#238#22#221'Di1'#216'C$'
+ +#188#216#148#175'EE'#198#224#164#159'''V'#217'V'#15#253'M'#199#151#14'#+'#164
+ +#151'>'#151'3'#227#188#164'&'#12#234#236#130#173#197'&Dz'#251'MzQ'#196#168
+ +#170#137'6'#27#22#137#244'd'#183'1+E'#171'q'#128'Pg'#254#27#188#186#242#251
+ +#142#240'v'#201'b.~rNNh'#218#154'_'#231#215#158#186#214'Y'#163#129'e/,'#133
+ +#217#164#154'a#'#148'H'#129'P'#157'+'#166'gN'#249#251#207#252#203#187#205#234
+ +#210#165#139#20')'#224'`'#182#144'@'#242#195'qr'#158#191#160'mJ'#22'4'#129
+ +#163'xb'#142'/N'#186'J'#182#130';'#202#25#212'i/'#31#142#185'3'#203'u'#243
+ +#200'w'#132'r'#14',j,'#168#214'rg'#193#195#141#5#12#181'L'#144#229'_C'#182
+ +#213'q'#145#2'cS[a'#14'6'#132#205#140#137#8'C'#175#182'S'#165')>=r.t'#170'v'
+ +#190#150#189'-H'#179#145#165#18#235#167#208#138#194#137#235#146#226'YJ'#214
+ +#235#138#4#8#209#254#208#181'}'#203'y'#182#134#149#203#165#158#25#127#137'd'
+ +#142'Se47'#184'~]X'#164#190#168#214#181#175'FqL'#168#130#204#132#169'hB]a'
+ +#244#168'.4'#248#18#211#26'SG'#213#131'.F'#210#165'8-r'#207'%'#210#161'I'#129
+ +#157'd'#209#30'Q'#218#253'+'#137#210#1'OH'#7#181#147#146#150#145#216#13#3#160
+ +#144#0'= '#159#22#13'xd,'#226'h'#174#250#176#144':'#21#211#127''''#127#243'Q'
+ +#189#227'_}#'#191#199#232#18#18'y'#181'"'#147#22'O'#23'4V'#187#9'Z)'#152':8'
+ +#10#173#168#173#2'@'#4#29#143']'#136#209#7#227#193#199#154#252#247'-'#206#249
+ +'S$'#171#200'n&YA'#168#204#237'#D'#134#241'Cq '#194#173'q'#198'Z'#12'Gi-'#182
+ +#210'>'#154';ho'#237'V'#138#214#178#162#244#135#214#236'['#202#236#149#22#170
+ +'b'#155'P'#14'<'#18#194#14#255#0#220#241#13#146'5'#162'N'#143'P?'#30#22'Y'#21
+ +#213#133#237#148#235#171#155#9'6V'#246'.'#151#167#206#146#176#167'd:'#160':'
+ +#221's'#161')O'#168#162#132#149#168#1#214'F'#200#234#217','#222'm/'#255#0#18
+ +'*7'#176'e'#161'G'#231'A'#180#149'|'#252'~?'#26''''#247'%'#205#26'S'#160#202
+ +#138#136'b'#174#177'm'#0#0#144#2#131#251#245'9'#235';'#239#179#191#158#229'q'
+ +'Y'#159'7'#153#138'y'#204#146'G%'#217#167#6'b'#25#138'I9'#156'+'#158#166'S'
+ +#209#26#199#31'c'#253#8#7'a'#216't'#143#195'8?'#244#183#19#241#166'1'#29#31
+ +'}6'#19#141'2'#244'D4P'#131'6Udi'#182'.'#21#160#16#3#150'r'#229#186#165#175
+ +#185#245';'#253#199#179#191'%'#182#226#194'o'#234#181#235#163#237'm'#132#2
+ +#134#208#164#253#161'*RA'#245#10'T'#20#147#213#246#235#167'@'#19#191#4'x6[]#'
+ +#24#195#229'W8'#135#25#184#193#241'['#166'O'#169#235'8'#252'{'#26#10#233#193
+ +'~'#162#18#27'J'#27'D'#128#223#164#15'R'#10'@W'#222#20#4'j'#243'a'#230#5#142
+ +#16#227#137#151'1'#29'nFk'#148'-'#250','#10#173#207#191#209#152#243'HT'#203
+ +#149#199'I.?'#30#153#151#16#249'QIis'#29#131#13'g'#174'j6'#135'J'#182#174#221
+ +#233'n'#205'bve'#222#195'1f'#219'1o'#158#149#238#238'v}'#160#239#176#215#139
+ +'LmW'#175'R)d'#4'W'#175']'#25#148#19#239#233'ETU'#3'[b'#218'@?'#127#143#209
+ +#235#178#149#142#202'R'#223#179#159'O'#1'-'#200'r'''#169'6T8'#232'2X'#216'v8'
+ +'2'#29'@S'#236#236#135'R'#7'Z'#21#180#175'Dhg'#138#207#227#15'!9'#15'$'#226
+ +#181'Y'#127#152#158'A'#204#163'N'#187#140#171'JlV'#189#214#222#153'L'#213#163
+ +#159'^'#169'v'#238#216'7&;vV!'#245#200#151#22',F'#156'i'#199#2#165'I'#144#234
+ +#130'['#207#18'ON'#138'1C'#148#155'hz'#15#161'\'#188'[R'#20#244';?'#187#190
+ +#182#195#218'Ou'#236' .
+
+ See the file COPYING, included in this distribution,
+ for details about the copyright.
+
+ about form for the Mufasa Macro Library
+}
+
+unit about;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+ Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
+ StdCtrls, ExtCtrls;
+
+type
+
+ { TAboutForm }
+
+ TAboutForm = class(TForm)
+ AboutMemo: TMemo;
+ ButtonClose: TButton;
+ ImageSimba: TImage;
+ LabelTitle: TLabel;
+ LabelRevision: TLabel;
+ procedure FormCreate(Sender: TObject);
+ procedure OkButtonClick(Sender: TObject);
+ private
+ { private declarations }
+ public
+ { public declarations }
+ end;
+
+var
+ AboutForm: TAboutForm;
+
+implementation
+uses
+ TestUnit;
+{ TAboutForm }
+
+procedure TAboutForm.FormCreate(Sender: TObject);
+begin
+ Self.Caption := format('About Simba r%d', [TestUnit.SimbaVersion]);
+ Self.LabelRevision.Caption := format('Revision %d', [TestUnit.SimbaVersion]);
+ AboutMemo.Lines.Add('---Simba---');
+ AboutMemo.Lines.Add('');
+ AboutMemo.Lines.Add('');
+ AboutMemo.Lines.Add('Simba is released under the GPL license.');
+ AboutMemo.Lines.Add(format('You are currently using version: %d',[Testunit.SimbaVersion]));
+ AboutMemo.Lines.Add('');
+ AboutMemo.Lines.Add('Please report bugs at: http://mufasa.villavu.com/mantis/');
+end;
+
+procedure TAboutForm.OkButtonClick(Sender: TObject);
+begin
+ Self.ModalResult:=mrOK;
+ Self.Hide;
+end;
+
+initialization
+ {$I about.lrs}
+
+end.
+
diff --git a/branches/script-component/Projects/SAMufasaGUI/colourhistory.lfm b/branches/script-component/Projects/SAMufasaGUI/colourhistory.lfm
new file mode 100644
index 0000000..92262b0
--- /dev/null
+++ b/branches/script-component/Projects/SAMufasaGUI/colourhistory.lfm
@@ -0,0 +1,149 @@
+object ColourHistoryForm: TColourHistoryForm
+ Left = 374
+ Height = 260
+ Top = 335
+ Width = 499
+ ActiveControl = SelectionName
+ Caption = 'Colour Picker History'
+ ClientHeight = 235
+ ClientWidth = 499
+ Constraints.MinHeight = 200
+ Constraints.MinWidth = 490
+ Menu = CHMainMenu
+ OnCreate = FormCreate
+ OnHide = UnSetCHShowMenu
+ OnShow = SetCHShowMenu
+ LCLVersion = '0.9.29'
+ object DeleteButton: TButton
+ Left = 16
+ Height = 25
+ Top = 193
+ Width = 128
+ Anchors = [akLeft, akBottom]
+ Caption = 'Delete'
+ OnClick = DeleteSelected
+ TabOrder = 0
+ end
+ object SelectionName: TEdit
+ Left = 370
+ Height = 27
+ Top = 16
+ Width = 112
+ Anchors = [akTop, akRight]
+ OnChange = ChangeName
+ OnKeyPress = SelectionNameKeyPress
+ TabOrder = 1
+ Text = 'Name'
+ end
+ object PickNewColourButton: TButton
+ Left = 226
+ Height = 25
+ Top = 193
+ Width = 128
+ Anchors = [akRight, akBottom]
+ Caption = 'Pick New Colour'
+ TabOrder = 2
+ end
+ object ColourValue: TEdit
+ Left = 370
+ Height = 27
+ Top = 56
+ Width = 112
+ Anchors = [akTop, akRight]
+ ReadOnly = True
+ TabOrder = 3
+ Text = 'ColourValue'
+ end
+ object CoordValue: TLabel
+ Left = 370
+ Height = 18
+ Top = 96
+ Width = 112
+ Anchors = [akTop, akRight]
+ Caption = 'CoordValue'
+ Constraints.MinWidth = 112
+ ParentColor = False
+ end
+ object ColourImage: TImage
+ Left = 152
+ Height = 24
+ Top = 194
+ Width = 66
+ Anchors = [akLeft, akRight, akBottom]
+ end
+ object OkButton: TButton
+ Left = 402
+ Height = 24
+ Top = 194
+ Width = 80
+ Anchors = [akRight, akBottom]
+ Caption = 'Ok'
+ OnClick = OkButtonClick
+ TabOrder = 4
+ end
+ object CH_RGB_Label: TLabel
+ Left = 370
+ Height = 18
+ Top = 128
+ Width = 112
+ Anchors = [akTop, akRight]
+ Caption = 'RGBValues'
+ Constraints.MinWidth = 112
+ ParentColor = False
+ end
+ object ColourTree: TTreeView
+ Left = 8
+ Height = 154
+ Top = 16
+ Width = 346
+ Anchors = [akTop, akLeft, akRight, akBottom]
+ DefaultItemHeight = 19
+ DragMode = dmAutomatic
+ Images = CHImages
+ ScrollBars = ssAutoBoth
+ TabOrder = 5
+ OnChange = ColourTreeChange
+ OnDragDrop = ColourTreeDragDrop
+ OnDragOver = ColourTreeDragOver
+ end
+ object CHImages: TImageList
+ left = 424
+ top = 160
+ end
+ object CHMainMenu: TMainMenu
+ left = 360
+ top = 160
+ object CHFile: TMenuItem
+ Caption = 'File'
+ object CHClear: TMenuItem
+ Caption = 'Clear'
+ OnClick = CHClearClick
+ end
+ object CHLoad: TMenuItem
+ Caption = 'Load'
+ OnClick = CHLoadClick
+ end
+ object CHSave: TMenuItem
+ Caption = 'Save'
+ OnClick = CHSaveClick
+ end
+ end
+ object CHHelp: TMenuItem
+ Caption = 'Help'
+ object CHAbout: TMenuItem
+ Caption = 'About'
+ OnClick = CHAboutClick
+ end
+ end
+ end
+ object CHSaveDialog: TSaveDialog
+ DefaultExt = '.xml'
+ left = 392
+ top = 160
+ end
+ object CHOpenDialog: TOpenDialog
+ DefaultExt = '.xml'
+ left = 456
+ top = 160
+ end
+end
diff --git a/branches/script-component/Projects/SAMufasaGUI/colourhistory.lrs b/branches/script-component/Projects/SAMufasaGUI/colourhistory.lrs
new file mode 100644
index 0000000..f407234
--- /dev/null
+++ b/branches/script-component/Projects/SAMufasaGUI/colourhistory.lrs
@@ -0,0 +1,45 @@
+{ This is an automatically generated lazarus resource file }
+
+LazarusResources.Add('TColourHistoryForm','FORMDATA',[
+ 'TPF0'#18'TColourHistoryForm'#17'ColourHistoryForm'#4'Left'#3'v'#1#6'Height'#3
+ +#4#1#3'Top'#3'O'#1#5'Width'#3#243#1#13'ActiveControl'#7#13'SelectionName'#7
+ +'Caption'#6#21'Colour Picker History'#12'ClientHeight'#3#235#0#11'ClientWidt'
+ +'h'#3#243#1#21'Constraints.MinHeight'#3#200#0#20'Constraints.MinWidth'#3#234
+ +#1#4'Menu'#7#10'CHMainMenu'#8'OnCreate'#7#10'FormCreate'#6'OnHide'#7#15'UnSe'
+ +'tCHShowMenu'#6'OnShow'#7#13'SetCHShowMenu'#10'LCLVersion'#6#6'0.9.29'#0#7'T'
+ +'Button'#12'DeleteButton'#4'Left'#2#16#6'Height'#2#25#3'Top'#3#193#0#5'Width'
+ +#3#128#0#7'Anchors'#11#6'akLeft'#8'akBottom'#0#7'Caption'#6#6'Delete'#7'OnCl'
+ +'ick'#7#14'DeleteSelected'#8'TabOrder'#2#0#0#0#5'TEdit'#13'SelectionName'#4
+ +'Left'#3'r'#1#6'Height'#2#27#3'Top'#2#16#5'Width'#2'p'#7'Anchors'#11#5'akTop'
+ +#7'akRight'#0#8'OnChange'#7#10'ChangeName'#10'OnKeyPress'#7#21'SelectionName'
+ +'KeyPress'#8'TabOrder'#2#1#4'Text'#6#4'Name'#0#0#7'TButton'#19'PickNewColour'
+ +'Button'#4'Left'#3#226#0#6'Height'#2#25#3'Top'#3#193#0#5'Width'#3#128#0#7'An'
+ +'chors'#11#7'akRight'#8'akBottom'#0#7'Caption'#6#15'Pick New Colour'#8'TabOr'
+ +'der'#2#2#0#0#5'TEdit'#11'ColourValue'#4'Left'#3'r'#1#6'Height'#2#27#3'Top'#2
+ +'8'#5'Width'#2'p'#7'Anchors'#11#5'akTop'#7'akRight'#0#8'ReadOnly'#9#8'TabOrd'
+ +'er'#2#3#4'Text'#6#11'ColourValue'#0#0#6'TLabel'#10'CoordValue'#4'Left'#3'r'
+ +#1#6'Height'#2#18#3'Top'#2'`'#5'Width'#2'p'#7'Anchors'#11#5'akTop'#7'akRight'
+ +#0#7'Caption'#6#10'CoordValue'#20'Constraints.MinWidth'#2'p'#11'ParentColor'
+ +#8#0#0#6'TImage'#11'ColourImage'#4'Left'#3#152#0#6'Height'#2#24#3'Top'#3#194
+ +#0#5'Width'#2'B'#7'Anchors'#11#6'akLeft'#7'akRight'#8'akBottom'#0#0#0#7'TBut'
+ +'ton'#8'OkButton'#4'Left'#3#146#1#6'Height'#2#24#3'Top'#3#194#0#5'Width'#2'P'
+ +#7'Anchors'#11#7'akRight'#8'akBottom'#0#7'Caption'#6#2'Ok'#7'OnClick'#7#13'O'
+ +'kButtonClick'#8'TabOrder'#2#4#0#0#6'TLabel'#12'CH_RGB_Label'#4'Left'#3'r'#1
+ +#6'Height'#2#18#3'Top'#3#128#0#5'Width'#2'p'#7'Anchors'#11#5'akTop'#7'akRigh'
+ +'t'#0#7'Caption'#6#9'RGBValues'#20'Constraints.MinWidth'#2'p'#11'ParentColor'
+ +#8#0#0#9'TTreeView'#10'ColourTree'#4'Left'#2#8#6'Height'#3#154#0#3'Top'#2#16
+ +#5'Width'#3'Z'#1#7'Anchors'#11#5'akTop'#6'akLeft'#7'akRight'#8'akBottom'#0#17
+ +'DefaultItemHeight'#2#19#8'DragMode'#7#11'dmAutomatic'#6'Images'#7#8'CHImage'
+ +'s'#10'ScrollBars'#7#10'ssAutoBoth'#8'TabOrder'#2#5#8'OnChange'#7#16'ColourT'
+ +'reeChange'#10'OnDragDrop'#7#18'ColourTreeDragDrop'#10'OnDragOver'#7#18'Colo'
+ +'urTreeDragOver'#0#0#10'TImageList'#8'CHImages'#4'left'#3#168#1#3'top'#3#160
+ +#0#0#0#9'TMainMenu'#10'CHMainMenu'#4'left'#3'h'#1#3'top'#3#160#0#0#9'TMenuIt'
+ +'em'#6'CHFile'#7'Caption'#6#4'File'#0#9'TMenuItem'#7'CHClear'#7'Caption'#6#5
+ +'Clear'#7'OnClick'#7#12'CHClearClick'#0#0#9'TMenuItem'#6'CHLoad'#7'Caption'#6
+ +#4'Load'#7'OnClick'#7#11'CHLoadClick'#0#0#9'TMenuItem'#6'CHSave'#7'Caption'#6
+ +#4'Save'#7'OnClick'#7#11'CHSaveClick'#0#0#0#9'TMenuItem'#6'CHHelp'#7'Caption'
+ +#6#4'Help'#0#9'TMenuItem'#7'CHAbout'#7'Caption'#6#5'About'#7'OnClick'#7#12'C'
+ +'HAboutClick'#0#0#0#0#11'TSaveDialog'#12'CHSaveDialog'#10'DefaultExt'#6#4'.x'
+ +'ml'#4'left'#3#136#1#3'top'#3#160#0#0#0#11'TOpenDialog'#12'CHOpenDialog'#10
+ +'DefaultExt'#6#4'.xml'#4'left'#3#200#1#3'top'#3#160#0#0#0#0
+]);
\ No newline at end of file
diff --git a/branches/script-component/Projects/SAMufasaGUI/colourhistory.pas b/branches/script-component/Projects/SAMufasaGUI/colourhistory.pas
new file mode 100644
index 0000000..25ff55f
--- /dev/null
+++ b/branches/script-component/Projects/SAMufasaGUI/colourhistory.pas
@@ -0,0 +1,559 @@
+{
+ This file is part of the Mufasa Macro Library (MML)
+ Copyright (c) 2009 by Raymond van Venetië and Merlijn Wajer
+
+ MML is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ MML is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with MML. If not, see .
+
+ See the file COPYING, included in this distribution,
+ for details about the copyright.
+
+ Colour History window for Mufasa Macro Library
+}
+unit colourhistory;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+ Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
+ ComCtrls, StdCtrls, ExtCtrls, Menus, DOM, XMLWrite, XMLRead;
+
+type
+ TColourPickerObject = class(TObject)
+ constructor Create(C: Integer; P: TPoint; N: String);
+ destructor Destroy; override;
+
+ public
+ Colour: Integer;
+ Pos: TPoint;
+ Name: String;
+ end;
+
+ { TColourHistoryForm }
+
+ TColourHistoryForm = class(TForm)
+ CH_RGB_Label: TLabel;
+ CHImages: TImageList;
+ CHMainMenu: TMainMenu;
+ CHFile: TMenuItem;
+ CHHelp: TMenuItem;
+ CHClear: TMenuItem;
+ CHLoad: TMenuItem;
+ CHSave: TMenuItem;
+ CHAbout: TMenuItem;
+ OkButton: TButton;
+ ColourValue: TEdit;
+ CoordValue: TLabel;
+ ColourImage: TImage;
+ CHOpenDialog: TOpenDialog;
+ PickNewColourButton: TButton;
+ DeleteButton: TButton;
+ CHSaveDialog: TSaveDialog;
+ SelectionName: TEdit;
+ ColourTree: TTreeView;
+ procedure CHAboutClick(Sender: TObject);
+ procedure ChangeName(Sender: TObject);
+ procedure CHClearClick(Sender: TObject);
+ procedure CHLoadClick(Sender: TObject);
+ procedure ColourTreeChange(Sender: TObject; Node: TTreeNode);
+ procedure ColourTreeDragDrop(Sender, Source: TObject; X, Y: Integer);
+ procedure ColourTreeDragOver(Sender, Source: TObject; X, Y: Integer;
+ State: TDragState; var Accept: Boolean);
+ procedure DeleteSelected(Sender: TObject);
+ procedure AddColObj(c: TColourPickerObject; autoName: Boolean);
+
+
+ procedure CHSaveClick(Sender: TObject);
+ procedure FormCreate(Sender: TObject);
+ procedure OkButtonClick(Sender: TObject);
+ procedure SelectionNameKeyPress(Sender: TObject; var Key: char);
+ procedure SetCHShowMenu(Sender: TObject);
+ procedure UnSetCHShowMenu(Sender: TObject);
+ private
+ TreeChanged: Boolean;
+ { private declarations }
+ protected
+ procedure AddColObj(c: TColourPickerObject);
+ procedure SetNodeBitmap(N: TTreeNode);
+ procedure SaveToXML(s: String);
+ procedure XML2Tree(XMLDoc: TXMLDocument);
+ public
+ constructor Create(TheOwner: TComponent); override;
+ destructor Destroy; override;
+ public
+ IndexSelected: Integer;
+ { public declarations }
+ end;
+
+
+
+var
+ ColourHistoryForm: TColourHistoryForm;
+
+implementation
+uses
+ colour_conv, TestUnit, lclintf, lcltype;
+
+constructor TColourPickerObject.Create(C: Integer; P: TPoint; N: String);
+begin
+ inherited Create;
+ Self.Colour := C;
+ Self.Pos := P;
+ Self.Name:= N;
+end;
+
+destructor TColourPickerObject.Destroy;
+begin
+
+ inherited Destroy;
+end;
+
+{ TColourHistoryForm }
+
+procedure TColourHistoryForm.AddColObj(c: TColourPickerObject; autoName: Boolean);
+begin
+ if autoName then
+ begin
+ // TODO: Proper name
+ c.Name := IntToStr(c.Colour);
+ end;
+ Self.AddColObj(c);
+end;
+
+procedure TColourHistoryForm.SetNodeBitmap(N: TTreeNode);
+var
+ bmp: TBitmap;
+begin
+ bmp:=TBitmap.Create;
+ bmp.SetSize(16,16);
+ if(Assigned(n.Data)) then
+ bmp.Canvas.Brush.Color:=TColourPickerObject(n.Data).Colour;
+ bmp.Canvas.Rectangle(0,0,16,16);
+
+ n.ImageIndex:=CHImages.Add(bmp, nil);
+ n.SelectedIndex:=n.ImageIndex;
+
+ bmp.Free;
+end;
+
+procedure TColourHistoryForm.AddColObj(c: TColourPickerObject);
+
+var
+ it: TTreeNode;
+
+begin
+ TreeChanged:=True;
+ it := ColourTree.Items.Add(nil, c.Name);
+ it.Data := c;
+ ColourTree.Selected := it;
+ SetNodeBitmap(it);
+end;
+
+procedure WalkDeleteTree(Node: TTreeNode; Img: TImageList);
+var
+ N: TTreeNode;
+
+begin
+ N := Node.GetFirstChild;
+
+ while assigned(n) do
+ begin
+ If Assigned(N.Data) then
+ TColourPickerObject(N.Data).Free;
+ WriteLn('Deleting ImageIndex: ' + IntToStr(n.ImageIndex) + '; Text: ' + N.Text);
+
+ // yeah....
+ try
+ if n.ImageIndex <> -1 Then
+ Img.Delete(n.ImageIndex);
+ except end;
+
+ WalkDeleteTree(n, img);
+ n := n.GetNextSibling;
+ end;
+end;
+
+procedure TColourHistoryForm.DeleteSelected(Sender: TObject);
+
+var
+ e: TTreeNodesEnumerator;
+
+begin
+ if (Assigned(ColourTree.Selected)) then
+ begin
+ if Assigned(ColourTree.Selected.Data) then
+ TColourPickerObject(ColourTree.Selected.Data).Free;
+
+ WalkDeleteTree(ColourTree.Selected, CHImages);
+
+ WriteLn('Deleting ImageIndex: ' + IntToStr(ColourTree.Selected.ImageIndex) + '; Text: ' + ColourTree.Selected.Text);
+ if ColourTree.Selected.ImageIndex <> -1 then
+ CHImages.Delete(ColourTree.Selected.ImageIndex);
+
+ ColourTree.Selected.Delete;
+ TreeChanged := True;
+
+ { Now, we have to recreate all images and their indices... Since the TImageList
+ fiddles with it's indices if one is deleted... Wtf? }
+ CHImages.Clear;
+
+ e := ColourTree.Items.GetEnumerator;
+ while e.MoveNext do
+ SetNodeBitmap(e.Current);
+ end;
+end;
+
+procedure WriteXMLData(n: TTreeNode;
+ XMLNode: TDOMNode; XMLDoc: TXMLDocument;
+ var XMLChild: TDOMNode; var C: Integer);
+
+var
+ DDataNode, DataNode, Data: TDOMNode;
+
+begin
+ XMLChild := XMLDoc.CreateElement('Item' + IntToStr(C));
+ Inc(C);
+ XMLNode.AppendChild(XMLChild);
+
+
+ DDataNode := XMLDoc.CreateElement('Data');
+ XMLChild.AppendChild(DDataNode);
+
+ DataNode := XMLDoc.CreateElement('Name');
+ DDataNode.AppendChild(DataNode);
+ Data := XMLDoc.CreateTextNode(TColourPickerObject(n.Data).Name);
+ DataNode.AppendChild(Data);
+ DataNode := XMLDoc.CreateElement('Colour');
+ DDataNode.AppendChild(DataNode);
+ Data := XMLDoc.CreateTextNode(IntToStr(TColourPickerObject(n.Data).Colour));
+ DataNode.AppendChild(Data);
+
+ DataNode := XMLDoc.CreateElement('CoordX');
+ DDataNode.AppendChild(DataNode);
+ Data := XMLDoc.CreateTextNode(IntToStr(TColourPickerObject(n.Data).Pos.X));
+ DataNode.AppendChild(Data);
+ DataNode := XMLDoc.CreateElement('CoordY');
+ DDataNode.AppendChild(DataNode);
+ Data := XMLDoc.CreateTextNode(IntToStr(TColourPickerObject(n.Data).Pos.Y));
+ DataNode.AppendChild(Data);
+end;
+
+procedure WalkTree(Node: TTreeNode; XMLNode: TDOMNode; XMLDoc: TXMLDocument;
+ var C: Integer);
+var
+ N: TTreeNode;
+ XMLChild, DDataNode, DataNode, Data: TDOMNode;
+
+begin
+ N := Node.GetFirstChild;
+
+ while assigned(n) do
+ begin
+ WriteXMLData(n, XMLNode, XMLDoc, XMLChild, C);
+
+ WalkTree(n, XMLChild, XMLDoc, C);
+ n := n.GetNextSibling;
+ end;
+end;
+
+procedure TColourHistoryForm.SaveToXML(s: String);
+var
+ XMLDoc: TXMLDocument;
+ RootNode, XMLChild: TDOMNode;
+ C, i: Integer;
+
+begin
+ XMLDoc := TXMLDocument.Create;
+
+ RootNode := XMLDoc.CreateElement('Tree');
+ XMLDoc.AppendChild(RootNode);
+
+ RootNode := XMLDoc.DocumentElement;
+
+ C := 0;
+
+ writeln(Colourtree.Items.TopLvlCount);
+ for i := 0 to Colourtree.Items.TopLvlCount -1 do
+ begin
+ WriteXMLData(ColourTree.Items.TopLvlItems[i], RootNode, XMLDoc, XMLChild, C);
+ WalkTree(ColourTree.Items.TopLvlItems[i], XMLChild, XMLDoc, C);
+ end;
+
+ WriteXMLFile(XMLDoc, s);
+
+ XMLDoc.Free;
+end;
+
+procedure TColourHistoryForm.ColourTreeChange(Sender: TObject; Node: TTreeNode);
+var
+ r,g,b:integer;
+begin
+ if not Assigned(Node) then
+ exit;
+ if not Node.Selected then
+ exit;
+
+ { This only occurs when we have manually added an item with the Form Editor }
+ if not Assigned(Node.Data) then
+ exit;
+
+ colour_conv.ColorToRGB(TColourPickerObject(Node.Data).Colour, r, g, b);
+
+ { Change Form Text / Values }
+ ColourValue.Caption := IntToStr(TColourPickerObject(Node.Data).Colour);
+ CoordValue.Caption := 'Coords: ' + IntToStr(TColourPickerObject(Node.Data).Pos.X) +
+ ', ' + IntToStr(TColourPickerObject(Node.Data).Pos.Y);
+ SelectionName.Text := TColourPickerObject(Node.Data).Name;
+
+ CH_RGB_Label.Caption:=Format('RGB:%d,%d,%d', [r,g,b]);
+
+ { Draw the Image }
+ ColourImage.Canvas.Brush.Color := TColourPickerObject(Node.Data).Colour;
+ ColourImage.Canvas.Rectangle(0,0,ColourImage.Width, ColourImage.Height);
+
+ if Self.Visible then
+ begin
+ try
+ SelectionName.SetFocus;
+ finally
+ end;
+ end;
+end;
+
+procedure TColourHistoryForm.ColourTreeDragDrop(Sender, Source: TObject; X,
+ Y: Integer);
+Var
+ Node: TTreeNode;
+
+begin
+ if Sender <> ColourTree then
+ Exit;
+ Node := ColourTree.GetNodeAt(X, Y);
+ if not assigned(ColourTree.Selected) then
+ begin
+ writeln('No valid node is currently selected');
+ exit;
+ end;
+
+ if not assigned(Node) then
+ begin
+ ColourTree.Selected.MoveTo(nil, naAdd);
+ TreeChanged:=True;
+ exit;
+ end;
+ ColourTree.Selected.MoveTo(Node, naAddChild);
+ TreeChanged:=True;
+ writeln('Dragging from: ' + ColourTree.Selected.Text);
+ writeln('Dragging to: ' + Node.Text);
+end;
+
+procedure TColourHistoryForm.ColourTreeDragOver(Sender, Source: TObject; X,
+ Y: Integer; State: TDragState; var Accept: Boolean);
+
+begin
+ Accept:=True;
+end;
+
+procedure TColourHistoryForm.ChangeName(Sender: TObject);
+begin
+ if not Assigned(ColourTree.Selected) then
+ begin
+ WriteLn('We double clicked but have nothing Selected?');
+ exit;
+ end;
+ ColourTree.Selected.Text := SelectionName.Text;
+ TColourPickerObject(ColourTree.Selected.Data).Name := SelectionName.Text;
+end;
+
+procedure TColourHistoryForm.CHClearClick(Sender: TObject);
+begin
+ TreeChanged:=False;
+ ColourTree.BeginUpdate;
+ ColourTree.Items.Clear;
+ CHImages.Clear;
+ ColourTree.EndUpdate;
+end;
+
+//heavily modded from http://wiki.lazarus.freepascal.org/XML_Tutorial
+procedure TColourHistoryForm.XML2Tree(XMLDoc: TXMLDocument);
+var
+ iNode: TDOMNode;
+
+ procedure ProcessNode(Node: TDOMNode; TreeNode: TTreeNode);
+ var
+ cNode, dNode: TDOMNode;
+ OP: TColourPickerObject;
+ pos: TPoint;
+ Colour: Integer;
+ Name: String;
+
+ begin
+ if Node = nil then Exit;
+
+ If Node.NodeName = 'Data' Then
+ exit;
+
+ TreeNode := ColourTree.Items.AddChild(TreeNode, 'ERROR');
+ writeln(Node.NodeName);
+ cNode := Node.FindNode('Data');
+ if Assigned(cNode) then
+ begin
+ dNode := cNode.FindNode('Name');
+ if assigned(dNode) then
+ Name := dNode.TextContent
+ else
+ Name := 'Error';
+ dNode := cNode.FindNode('Colour');
+ if assigned(dNode) then
+ Colour := StrToIntDef(dNode.TextContent, -1);
+
+ dNode := cNode.FindNode('CoordX');
+ if assigned(dNode) then
+ Pos.X := StrToIntDef(dNode.TextContent, -1);
+
+ dNode := cNode.FindNode('CoordY');
+ if assigned(dNode) then
+ Pos.Y := StrToIntDef(dNode.TextContent, -1);
+
+ OP := TColourPickerObject.Create(Colour, Pos, Name);
+ TreeNode.Text := Name;
+ TreeNode.Data := Pointer(OP);
+
+ SetNodeBitmap(TreeNode);
+ end;
+
+ // Goes to the child node
+ cNode := Node.FirstChild;
+
+ // Processes all child nodes
+ while cNode <> nil do
+ begin
+ ProcessNode(cNode, TreeNode);
+ cNode := cNode.NextSibling;
+ end;
+ end;
+
+begin
+ iNode := XMLDoc.DocumentElement.FirstChild;
+ while iNode <> nil do
+ begin
+ ProcessNode(iNode, nil); // Recursive
+ iNode := iNode.NextSibling;
+ end;
+end;
+
+
+procedure TColourHistoryForm.CHLoadClick(Sender: TObject);
+
+var
+ XMLDoc: TXMLDocument;
+
+begin
+ if TreeChanged then
+ begin
+ case MessageBox(0,pchar('Do you want to save the colours?'), Pchar('Colours have been modified.'),
+ MB_YESNOCANCEL or MB_ICONQUESTION) of
+ IDCANCEL :
+ Exit;
+ IDYES :
+ begin
+ if CHSaveDialog.Execute then
+ ColourTree.SaveToFile(CHSaveDialog.FileName)
+ else
+ Exit;
+ end;
+ end;
+ end;
+
+ if CHOpenDialog.Execute then
+ if FileExists(CHOpenDialog.FileName) then
+ begin
+ ReadXMLFile(XMLDoc, CHOpenDialog.FileName);
+
+ // Clear Tree and Images
+ ColourTree.BeginUpdate;
+ ColourTree.Items.Clear;
+ CHImages.Clear;
+ XML2Tree(XMLDoc);
+ ColourTree.EndUpdate;
+ TreeChanged:=False;
+ XMLDoc.Free;
+ end;
+end;
+
+procedure TColourHistoryForm.CHAboutClick(Sender: TObject);
+begin
+
+end;
+
+constructor TColourHistoryForm.Create(TheOwner: TComponent);
+begin
+ inherited Create(TheOwner);
+
+ PickNewColourButton.OnClick:= @Form1.ButtonPickClick;
+end;
+
+destructor TColourHistoryForm.Destroy;
+begin
+ PickNewColourButton.OnClick := nil;
+
+ inherited Destroy;
+end;
+
+procedure TColourHistoryForm.CHSaveClick(Sender: TObject);
+
+begin
+ if CHSaveDialog.Execute then
+ begin
+ SaveToXML(CHSaveDialog.FileName);
+ TreeChanged:=False;
+ end;
+end;
+
+procedure TColourHistoryForm.FormCreate(Sender: TObject);
+begin
+ TreeChanged:=False;
+end;
+
+procedure TColourHistoryForm.OkButtonClick(Sender: TObject);
+begin
+ Self.Close;
+end;
+
+procedure TColourHistoryForm.SelectionNameKeyPress(Sender: TObject;
+ var Key: char);
+begin
+ if key = #13 then
+ begin
+ key := #0;
+ Self.close;
+ end;
+end;
+
+procedure TColourHistoryForm.SetCHShowMenu(Sender: TObject);
+begin
+ Form1.MenuItemColourHistory.Checked := True;
+end;
+
+procedure TColourHistoryForm.UnSetCHShowMenu(Sender: TObject);
+begin
+ Form1.MenuItemColourHistory.Checked := False;
+end;
+
+initialization
+ {$I colourhistory.lrs}
+
+end.
+
diff --git a/branches/script-component/Projects/SAMufasaGUI/debugimage.lfm b/branches/script-component/Projects/SAMufasaGUI/debugimage.lfm
new file mode 100644
index 0000000..03dae46
--- /dev/null
+++ b/branches/script-component/Projects/SAMufasaGUI/debugimage.lfm
@@ -0,0 +1,22 @@
+object DebugImgForm: TDebugImgForm
+ Left = 491
+ Height = 300
+ Top = 266
+ Width = 400
+ BorderIcons = [biSystemMenu, biMinimize]
+ BorderStyle = bsToolWindow
+ Caption = 'DebugImgForm'
+ ClientHeight = 300
+ ClientWidth = 400
+ OnCreate = FormCreate
+ OnHide = FormHide
+ OnResize = FormResize
+ LCLVersion = '0.9.29'
+ object DrawImage: TImage
+ Left = 0
+ Height = 300
+ Top = 0
+ Width = 400
+ Align = alClient
+ end
+end
diff --git a/branches/script-component/Projects/SAMufasaGUI/debugimage.lrs b/branches/script-component/Projects/SAMufasaGUI/debugimage.lrs
new file mode 100644
index 0000000..fb31450
--- /dev/null
+++ b/branches/script-component/Projects/SAMufasaGUI/debugimage.lrs
@@ -0,0 +1,11 @@
+{ This is an automatically generated lazarus resource file }
+
+LazarusResources.Add('TDebugImgForm','FORMDATA',[
+ 'TPF0'#13'TDebugImgForm'#12'DebugImgForm'#4'Left'#3#235#1#6'Height'#3','#1#3
+ +'Top'#3#10#1#5'Width'#3#144#1#11'BorderIcons'#11#12'biSystemMenu'#10'biMinim'
+ +'ize'#0#11'BorderStyle'#7#12'bsToolWindow'#7'Caption'#6#12'DebugImgForm'#12
+ +'ClientHeight'#3','#1#11'ClientWidth'#3#144#1#8'OnCreate'#7#10'FormCreate'#6
+ +'OnHide'#7#8'FormHide'#8'OnResize'#7#10'FormResize'#10'LCLVersion'#6#6'0.9.2'
+ +'9'#0#6'TImage'#9'DrawImage'#4'Left'#2#0#6'Height'#3','#1#3'Top'#2#0#5'Width'
+ +#3#144#1#5'Align'#7#8'alClient'#0#0#0
+]);
\ No newline at end of file
diff --git a/branches/script-component/Projects/SAMufasaGUI/debugimage.pas b/branches/script-component/Projects/SAMufasaGUI/debugimage.pas
new file mode 100644
index 0000000..aec98d7
--- /dev/null
+++ b/branches/script-component/Projects/SAMufasaGUI/debugimage.pas
@@ -0,0 +1,124 @@
+{
+ This file is part of the Mufasa Macro Library (MML)
+ Copyright (c) 2009 by Raymond van Venetië and Merlijn Wajer
+
+ MML is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ MML is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with MML. If not, see .
+
+ See the file COPYING, included in this distribution,
+ for details about the copyright.
+
+ Image debug window for Mufasa Macro Library
+}
+unit debugimage;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+ Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
+ ExtCtrls, bitmaps;
+
+type
+
+ { TDebugImgForm }
+
+ TDebugImgForm = class(TForm)
+ DrawImage: TImage;
+ procedure FormCreate(Sender: TObject);
+ procedure FormHide(Sender: TObject);
+ procedure FormResize(Sender: TObject);
+ private
+ { private declarations }
+ public
+ DispSize : TPoint;
+ ToDrawBmp: TMufasaBitmap;//The bitmap we should draw!
+ GetDbgBmp : TMufasaBitmap;
+ procedure BlackDebugImage;
+ procedure DrawBitmap;
+ procedure GetDebugImage;
+ procedure ShowDebugImgForm; //Uses the global var for w/h
+ { public declarations }
+ end;
+
+
+var
+ DebugImgForm: TDebugImgForm;
+
+implementation
+
+uses
+ MufasaTypes, math, graphtype, IntfGraphics,TestUnit,lclintf,colour_conv,InterfaceBase;
+{ TDebugImgForm }
+
+procedure TDebugImgForm.FormCreate(Sender: TObject);
+begin
+ BlackDebugImage;
+end;
+
+procedure TDebugImgForm.FormHide(Sender: TObject);
+begin
+ Form1.MenuItemDebugImage.Checked := False;
+end;
+
+procedure TDebugImgForm.FormResize(Sender: TObject);
+begin
+ DrawImage.Picture.Graphic.Width := DrawImage.Width;
+ DrawImage.Picture.Graphic.Height := DrawImage.Height;
+ BlackDebugImage;
+end;
+
+procedure TDebugImgForm.BlackDebugImage;
+begin
+ DrawImage.Canvas.Brush.Color:= clBlack;
+ DrawImage.Canvas.Pen.Color:= clBlack;
+ DrawImage.Canvas.Rectangle(0,0,DrawImage.Width,DrawImage.Height);
+ DrawImage.Repaint;
+end;
+
+procedure TDebugImgForm.DrawBitmap;
+var
+ rawImage : TRawImage;
+ Bitmap : Graphics.TBitmap;
+begin
+ if ToDrawBmp = nil then
+ raise Exception.Create('ERROR in TDebugImgForm.DrawBitmap: ToDrawBmp = nil');
+ ArrDataToRawImage(ToDrawBmp.FData,Point(ToDrawBmp.width,ToDrawBmp.height),RawImage);
+ Bitmap := Graphics.TBitmap.Create;
+ Bitmap.LoadFromRawImage(Rawimage,false);
+ DrawImage.Canvas.Draw(0,0,Bitmap);
+ DrawImage.Repaint;
+ Bitmap.Free;
+end;
+
+procedure TDebugImgForm.GetDebugImage;
+begin;
+ GetDbgBmp.LoadFromRawImage(DrawImage.Picture.Bitmap.RawImage);
+end;
+
+procedure TDebugImgForm.ShowDebugImgForm;
+begin
+ Show;
+ if (DispSize.x <> Width) or (DispSize.y <> height) then
+ begin;
+ Width := DispSize.x;
+ Height := DispSize.y;
+ end;
+end;
+
+initialization
+ {$I debugimage.lrs}
+
+end.
+
diff --git a/branches/script-component/Projects/SAMufasaGUI/framefunctionlist.lfm b/branches/script-component/Projects/SAMufasaGUI/framefunctionlist.lfm
new file mode 100644
index 0000000..98de803
--- /dev/null
+++ b/branches/script-component/Projects/SAMufasaGUI/framefunctionlist.lfm
@@ -0,0 +1,138 @@
+object FunctionListFrame: TFunctionListFrame
+ Left = 0
+ Height = 522
+ Top = 0
+ Width = 182
+ Align = alLeft
+ ClientHeight = 522
+ ClientWidth = 182
+ OnEndDock = FrameEndDock
+ TabOrder = 0
+ DesignLeft = 401
+ DesignTop = 219
+ object FunctionList: TTreeView
+ Left = 0
+ Height = 483
+ Top = 18
+ Width = 182
+ Align = alClient
+ DefaultItemHeight = 15
+ ReadOnly = True
+ ScrollBars = ssAutoBoth
+ TabOrder = 0
+ OnDblClick = FunctionListDblClick
+ OnDeletion = FunctionListDeletion
+ OnMouseDown = FunctionListMouseDown
+ Options = [tvoAutoItemHeight, tvoHideSelection, tvoKeepCollapsedNodes, tvoReadOnly, tvoShowButtons, tvoShowLines, tvoShowRoot, tvoToolTips]
+ end
+ object editSearchList: TEdit
+ Left = 0
+ Height = 21
+ Top = 501
+ Width = 182
+ Align = alBottom
+ OnChange = editSearchListChange
+ TabOrder = 1
+ end
+ object FunctionListLabel: TLabel
+ Left = 2
+ Height = 14
+ Top = 2
+ Width = 178
+ Align = alTop
+ Alignment = taCenter
+ BorderSpacing.Around = 2
+ Caption = 'Functionlist'
+ Font.Style = [fsBold]
+ ParentColor = False
+ ParentFont = False
+ OnMouseDown = FunctionListLabelMouseDown
+ end
+ object CloseButton: TSpeedButton
+ Left = 134
+ Height = 16
+ Top = 2
+ Width = 16
+ Anchors = [akTop, akRight]
+ Color = clBtnFace
+ Flat = True
+ Glyph.Data = {
+ 36090000424D3609000000000000360000002800000018000000180000000100
+ 2000000000000009000064000000640000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 00FF0000000000000000000000000000000000000000000000FF000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000FF0000
+ 00FF000000FF000000000000000000000000000000FF000000FF000000FF0000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 00FF000000FF000000FF00000000000000FF000000FF000000FF000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000FF000000FF000000FF000000FF000000FF00000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 000000000000000000FF000000FF000000FF0000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000FF000000FF000000FF000000FF000000FF00000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 00FF000000FF000000FF00000000000000FF000000FF000000FF000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000FF0000
+ 00FF000000FF000000000000000000000000000000FF000000FF000000FF0000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 00FF0000000000000000000000000000000000000000000000FF000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000
+ }
+ NumGlyphs = 0
+ OnClick = CloseButtonClick
+ end
+end
\ No newline at end of file
diff --git a/branches/script-component/Projects/SAMufasaGUI/framefunctionlist.lrs b/branches/script-component/Projects/SAMufasaGUI/framefunctionlist.lrs
new file mode 100644
index 0000000..2445f04
--- /dev/null
+++ b/branches/script-component/Projects/SAMufasaGUI/framefunctionlist.lrs
@@ -0,0 +1,86 @@
+LazarusResources.Add('TFunctionListFrame','FORMDATA',[
+ 'TPF0'#18'TFunctionListFrame'#17'FunctionListFrame'#4'Left'#2#0#6'Height'#3#10
+ +#2#3'Top'#2#0#5'Width'#3#182#0#5'Align'#7#6'alLeft'#12'ClientHeight'#3#10#2
+ +#11'ClientWidth'#3#182#0#9'OnEndDock'#7#12'FrameEndDock'#8'TabOrder'#2#0#10
+ +'DesignLeft'#3#145#1#9'DesignTop'#3#219#0#0#9'TTreeView'#12'FunctionList'#4
+ +'Left'#2#0#6'Height'#3#227#1#3'Top'#2#18#5'Width'#3#182#0#5'Align'#7#8'alCli'
+ +'ent'#17'DefaultItemHeight'#2#15#8'ReadOnly'#9#10'ScrollBars'#7#10'ssAutoBot'
+ +'h'#8'TabOrder'#2#0#10'OnDblClick'#7#20'FunctionListDblClick'#10'OnDeletion'
+ +#7#20'FunctionListDeletion'#11'OnMouseDown'#7#21'FunctionListMouseDown'#7'Op'
+ +'tions'#11#17'tvoAutoItemHeight'#16'tvoHideSelection'#21'tvoKeepCollapsedNod'
+ +'es'#11'tvoReadOnly'#14'tvoShowButtons'#12'tvoShowLines'#11'tvoShowRoot'#11
+ +'tvoToolTips'#0#0#0#5'TEdit'#14'editSearchList'#4'Left'#2#0#6'Height'#2#21#3
+ +'Top'#3#245#1#5'Width'#3#182#0#5'Align'#7#8'alBottom'#8'OnChange'#7#20'editS'
+ +'earchListChange'#8'TabOrder'#2#1#0#0#6'TLabel'#17'FunctionListLabel'#4'Left'
+ +#2#2#6'Height'#2#14#3'Top'#2#2#5'Width'#3#178#0#5'Align'#7#5'alTop'#9'Alignm'
+ +'ent'#7#8'taCenter'#20'BorderSpacing.Around'#2#2#7'Caption'#6#12'Functionlis'
+ +'t'#10'Font.Style'#11#6'fsBold'#0#11'ParentColor'#8#10'ParentFont'#8#11'OnMo'
+ +'useDown'#7#26'FunctionListLabelMouseDown'#0#0#12'TSpeedButton'#11'CloseButt'
+ +'on'#4'Left'#3#134#0#6'Height'#2#16#3'Top'#2#2#5'Width'#2#16#7'Anchors'#11#5
+ +'akTop'#7'akRight'#0#5'Color'#7#9'clBtnFace'#4'Flat'#9#10'Glyph.Data'#10':'#9
+ +#0#0'6'#9#0#0'BM6'#9#0#0#0#0#0#0'6'#0#0#0'('#0#0#0#24#0#0#0#24#0#0#0#1#0' '#0
+ +#0#0#0#0#0#9#0#0'd'#0#0#0'd'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#255#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#0#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#255
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#255#0#0#0#255#0#0#0
+ +#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#0#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#255#0#0#0#0#0
+ ,#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#9'NumGlyphs'#2#0#7'OnClick'#7#16'CloseButtonC'
+ +'lick'#0#0#0
+]);
\ No newline at end of file
diff --git a/branches/script-component/Projects/SAMufasaGUI/framefunctionlist.pas b/branches/script-component/Projects/SAMufasaGUI/framefunctionlist.pas
new file mode 100644
index 0000000..890938b
--- /dev/null
+++ b/branches/script-component/Projects/SAMufasaGUI/framefunctionlist.pas
@@ -0,0 +1,348 @@
+unit framefunctionlist;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+ Classes, SysUtils, FileUtil, LResources, Forms, ComCtrls, StdCtrls, Controls,
+ ExtCtrls, Buttons;
+
+type
+
+ { TFunctionListFrame }
+
+ TFunctionListFrame = class(TFrame)
+ editSearchList: TEdit;
+ FunctionList: TTreeView;
+ FunctionListLabel: TLabel;
+ CloseButton: TSpeedButton;
+ procedure editSearchListChange(Sender: TObject);
+ procedure FrameEndDock(Sender, Target: TObject; X, Y: Integer);
+ procedure FunctionListDblClick(Sender: TObject);
+ procedure FunctionListDeletion(Sender: TObject; Node: TTreeNode);
+ procedure FunctionListLabelMouseDown(Sender: TObject; Button: TMouseButton;
+ Shift: TShiftState; X, Y: Integer);
+ procedure FunctionListMouseDown(Sender: TObject; Button: TMouseButton;
+ Shift: TShiftState; X, Y: Integer);
+ procedure DockFormOnClose(Sender: TObject; var CloseAction: TCloseAction);
+ procedure CloseButtonClick(Sender: TObject);
+ private
+ FFilterTree : TTreeView;
+ procedure FilterTreeVis(Vis : boolean);
+ function GetFilterTree: TTreeView;
+ { private declarations }
+ public
+ DraggingNode : TTreeNode;
+ ScriptNode : TTreeNode;
+ InCodeCompletion : boolean;
+ CompletionCaret : TPoint;
+ StartWordCompletion : TPoint;
+ CompletionLine : string;
+ CompletionStart : string;
+ property FilterTree : TTreeView read GetFilterTree;
+ procedure LoadScriptTree( Script : String);
+ function Find(Next : boolean; backwards : boolean = false) : boolean;
+ { public declarations }
+ end;
+
+implementation
+
+uses
+ TestUnit, Graphics, simpleanalyzer;
+
+{ TFunctionListFrame }
+
+procedure TFunctionListFrame.editSearchListChange(Sender: TObject);
+begin
+ Find(false);
+end;
+
+procedure TFunctionListFrame.FrameEndDock(Sender, Target: TObject; X, Y: Integer
+ );
+begin
+ if Target is TPanel then
+ begin
+ Form1.SplitterFunctionList.Visible := true;
+ CloseButton.Visible:= true;
+ end
+ else if Target is TCustomDockForm then
+ begin
+ TCustomDockForm(Target).Caption := 'Functionlist';
+ TCustomDockForm(Target).OnClose := @DockFormOnClose;
+ Form1.SplitterFunctionList.Visible:= false;
+ CloseButton.Visible:= false;
+ end;
+end;
+
+procedure TFunctionListFrame.FunctionListDblClick(Sender: TObject);
+var
+ Node : TTreeNode;
+begin
+ if FilterTree.Visible then
+ Node := FilterTree.Selected
+ else
+ node := FunctionList.Selected;
+ if node<> nil then
+ if node.Level > 0 then
+ if node.Data <> nil then
+ begin;
+ Form1.CurrScript.SynEdit.InsertTextAtCaret( GetMethodName(PChar(node.Data),true));
+ Form1.RefreshTab;
+ end;
+end;
+
+procedure TFunctionListFrame.FunctionListDeletion(Sender: TObject;
+ Node: TTreeNode);
+begin
+ if node.data <> nil then
+ StrDispose(PChar(Node.Data));
+end;
+
+procedure TFunctionListFrame.FunctionListLabelMouseDown(Sender: TObject;
+ Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
+begin
+ Self.DragKind := dkDock;
+ Self.BeginDrag(false, 40);
+end;
+
+procedure TFunctionListFrame.DockFormOnClose(Sender: TObject; var CloseAction: TCloseAction);
+begin
+ CloseAction := caHide;
+ Form1.MenuItemFunctionList.Checked := False;
+end;
+
+procedure TFunctionListFrame.CloseButtonClick(Sender: TObject);
+begin
+ self.Hide;
+ Form1.MenuItemFunctionList.Checked := False;
+end;
+
+procedure TFunctionListFrame.FilterTreeVis(Vis: boolean);
+begin
+ FunctionList.Visible:= not Vis;
+ FilterTree.Visible := Vis;
+end;
+
+function TFunctionListFrame.GetFilterTree: TTreeView;
+begin
+ Result := FFilterTree;
+ if Assigned(Result) then
+ exit;
+ FFilterTree := TTreeView.Create(Self);
+ FFilterTree.Parent := Self;
+ FFilterTree.Visible := false;
+ FFilterTree.SetBounds(FunctionList.Left,FunctionList.Top,FunctionList.Width,FunctionList.Height);
+ FFilterTree.Align := alClient;
+ FFilterTree.ReadOnly:= True;
+ FFilterTree.ScrollBars:= ssAutoBoth;
+ FFilterTree.OnMouseDown:= FunctionList.OnMouseDown;
+ FFilterTree.OnMouseUp:= FunctionList.OnMouseUp;
+ FFilterTree.OnChange:= FunctionList.OnChange;
+ FFilterTree.OnExit := FunctionList.OnExit;
+ FFilterTree.OnDblClick:= FunctionList.OnDblClick;
+ Result := FFilterTree;
+ //We do not want to delete the data from the FilterTree
+// FilterTree.OnDeletion:= FunctionList.OnDeletion;
+end;
+
+procedure TFunctionListFrame.LoadScriptTree(Script: String);
+var
+ I : integer;
+ Analyzer : TScriptAnalyzer;
+ tmpNode : TTreeNode;
+begin
+ if ScriptNode = nil then
+ exit;
+ if FilterTree.Visible then
+ Writeln('Might get some acces violations now..');
+ ScriptNode.DeleteChildren;
+ Analyzer := TScriptAnalyzer.create;
+ Analyzer.ScriptToAnalyze:= Script;
+ Analyzer.analyze;
+ for i := 0 to Analyzer.MethodLen - 1 do
+ begin
+ tmpNode := FunctionList.Items.AddChild(ScriptNode,Analyzer.Methods[i].Name);
+ tmpNode.Data:= strnew(PChar(Analyzer.Methods[i].CreateMethodStr));
+ end;
+ ScriptNode.Expand(true);
+ Analyzer.free;
+end;
+
+function TFunctionListFrame.Find(Next : boolean; backwards : boolean = false) : boolean;
+var
+ Start,Len,i,index,posi,c: Integer;
+ FoundFunction : boolean;
+ LastSection : string;
+ str : string;
+ RootNode : TTreeNode;
+ NormalNode : TTreeNode;
+ Node : TTreeNode;
+ InsertStr : string;
+begin
+ if(editSearchList.Text = '')then
+ begin
+ editSearchList.Color := clWhite;
+ FunctionList.FullCollapse;
+ if InCodeCompletion then
+ begin;
+ Form1.CurrScript.SynEdit.Lines[CompletionCaret.y - 1] := CompletionStart;
+ Form1.CurrScript.SynEdit.LogicalCaretXY:= point(CompletionCaret.x,CompletionCaret.y);
+ Form1.CurrScript.SynEdit.SelEnd:= Form1.CurrScript.SynEdit.SelStart;
+ end;
+ FilterTreeVis(False);
+ ScriptNode.Expand(true);
+ exit;
+ end;
+
+ //We only have to search the next item in our filter tree.. Fu-king easy!
+ if next then
+ begin;
+ if FilterTree.Visible = false then
+ begin;
+ Writeln('ERROR: You cannot search next, since the Tree isnt generated yet');
+ Find(false);
+ exit;
+ end;
+ if FilterTree.Selected <> nil then
+ begin;
+ if backwards then
+ start := FilterTree.Selected.AbsoluteIndex - 1
+ else
+ Start := FilterTree.Selected.AbsoluteIndex + 1;
+ end
+ else
+ begin
+ if backwards then
+ Start := FilterTree.Items.Count - 1
+ else
+ Start := 0;
+ end;
+ Len := FilterTree.Items.Count;
+ i := start + len; //This is for the backwards compatibily, we do mod anways.. it just makes sure -1 isn't negative.
+ c := 0;
+ while c < (len ) do
+ begin;
+ if FilterTree.Items[i mod len].Level = 1 then
+ begin
+ FilterTree.Items[i mod len].Selected:= true;
+ InsertStr := FilterTree.Items[i mod len].Text;
+ Result := true;
+ break;
+ end;
+ if backwards then
+ dec(i)
+ else
+ inc(i);
+ inc(c);
+ end;
+ end else
+ begin
+ FilterTree.Items.Clear;
+ FoundFunction := False;
+ if FunctionList.Selected <> nil then
+ Start := FunctionList.Selected.AbsoluteIndex
+ else
+ Start := 0;
+ Len := FunctionList.Items.Count;
+ LastSection := '';
+ for i := start to start + FunctionList.Items.Count - 1 do
+ begin;
+ Node := FunctionList.Items[i mod FunctionList.Items.Count];
+ if(Node.Level = 1)then
+ if(pos(lowercase(editSearchList.Text), lowercase(Node.Text)) > 0)then
+ begin
+ if not FoundFunction then
+ begin
+ FoundFunction := True;
+ index := i mod FunctionList.Items.Count;
+ InsertStr:= node.Text;
+ end;
+ if LastSection <> Node.Parent.Text then //We enter a new section, add it to the filter tree!
+ RootNode := FilterTree.Items.AddChild(nil,Node.Parent.Text);
+ FilterTree.Items.AddChild(RootNode,Node.Text).Data := Node.Data;
+ LastSection:= RootNode.Text;
+ // break;
+ end;
+ end;
+ Result := FoundFunction;
+
+ if Result then
+ begin;
+ FilterTreeVis(True);
+ FilterTree.FullExpand;
+ FilterTree.Items[1].Selected:= True;
+ Writeln(FunctionList.Items[Index].Text);
+ FunctionList.FullCollapse;
+ FunctionList.Items[Index].Selected := true;
+ FunctionList.Items[index].ExpandParents;
+ editSearchList.Color := clWhite;
+
+
+ end else
+ begin
+ FilterTreeVis(false);
+ editSearchList.Color := 6711039;
+ if InCodeCompletion then
+ Form1.CurrScript.SynEdit.Lines[CompletionCaret.y - 1] := CompletionStart;
+ end;
+ end;
+
+ if result and InCodeCompletion then
+ begin;
+ str := format(CompletionLine, [InsertStr]);
+ with Form1.CurrScript.SynEdit do
+ begin;
+ Lines[CompletionCaret.y - 1] := str;
+ LogicalCaretXY:= StartWordCompletion;
+ i := SelStart;
+ posi := pos(lowercase(editSearchList.text), lowercase(InsertStr)) + length(editSearchList.text) - 1; //underline the rest of the word
+ if Posi = Length(InsertStr) then //Special occasions
+ begin;
+ if Length(editSearchList.Text) <> Posi then //We found the last part of the text -> for exmaple when you Search for bitmap, you can find LoadBitmap -> We underline 'Load'
+ begin;
+ SelStart := i;
+ SelEnd := i + pos(lowercase(editSearchList.text), lowercase(InsertStr)) -1;
+ Exit;
+ end;
+ //We searched for the whole text -> for example LoadBitmap, and we found LoadBitmap -> Underline the whole text
+ Posi := 0;
+ end;
+ //Underline the rest of the word
+ SelStart := i + posi;
+ SelEnd := SelStart + Length(InsertStr) - posi;
+ end;
+ end;
+end;
+
+procedure TFunctionListFrame.FunctionListMouseDown(Sender: TObject;
+ Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
+var
+ N: TTreeNode;
+begin
+ if InCodeCompletion then
+ begin;
+ Writeln('Not yet implemented');
+ exit;
+ end;
+ if not (Sender is TTreeView) then
+ exit;
+ N := TTreeView(Sender).GetNodeAt(x, y);
+ if(N = nil)then
+ begin
+ Self.DragKind := dkDock;
+ Self.BeginDrag(false, 40);
+ exit;
+ end;
+ Self.DragKind := dkDrag;
+ if(Button = mbLeft) and (N.Level > 0)then
+ Self.BeginDrag(False, 10);
+ DraggingNode := N;
+end;
+
+
+initialization
+ {$I framefunctionlist.lrs}
+
+end.
+
diff --git a/branches/script-component/Projects/SAMufasaGUI/framescript.lfm b/branches/script-component/Projects/SAMufasaGUI/framescript.lfm
new file mode 100644
index 0000000..9fdb939
--- /dev/null
+++ b/branches/script-component/Projects/SAMufasaGUI/framescript.lfm
@@ -0,0 +1,723 @@
+object ScriptFrame: TScriptFrame
+ Left = 0
+ Height = 328
+ Top = 0
+ Width = 397
+ ClientHeight = 328
+ ClientWidth = 397
+ TabOrder = 0
+ DesignLeft = 159
+ DesignTop = 420
+ inline SynEdit: TSynEdit
+ Left = 0
+ Height = 328
+ Top = 0
+ Width = 397
+ Align = alClient
+ Font.Height = -13
+ Font.Name = 'Courier New'
+ Font.Pitch = fpFixed
+ Font.Quality = fqNonAntialiased
+ ParentColor = False
+ ParentFont = False
+ PopupMenu = Form1.ScriptPopup
+ TabOrder = 0
+ OnDragDrop = SynEditDragDrop
+ OnDragOver = SynEditDragOver
+ OnKeyDown = SynEditKeyDown
+ Gutter.Width = 57
+ Gutter.MouseActions = <
+ item
+ Shift = []
+ ShiftMask = []
+ Button = mbLeft
+ ClickCount = ccAny
+ ClickDir = cdDown
+ Command = 13
+ MoveCaret = False
+ Option = 0
+ Priority = 0
+ end
+ item
+ Shift = []
+ ShiftMask = []
+ Button = mbRight
+ ClickCount = ccSingle
+ ClickDir = cdUp
+ Command = 12
+ MoveCaret = False
+ Option = 0
+ Priority = 0
+ end>
+ Highlighter = SynFreePascalSyn1
+ Keystrokes = <
+ item
+ Command = ecUp
+ ShortCut = 38
+ end
+ item
+ Command = ecSelUp
+ ShortCut = 8230
+ end
+ item
+ Command = ecScrollUp
+ ShortCut = 16422
+ end
+ item
+ Command = ecDown
+ ShortCut = 40
+ end
+ item
+ Command = ecSelDown
+ ShortCut = 8232
+ end
+ item
+ Command = ecScrollDown
+ ShortCut = 16424
+ end
+ item
+ Command = ecLeft
+ ShortCut = 37
+ end
+ item
+ Command = ecSelLeft
+ ShortCut = 8229
+ end
+ item
+ Command = ecWordLeft
+ ShortCut = 16421
+ end
+ item
+ Command = ecSelWordLeft
+ ShortCut = 24613
+ end
+ item
+ Command = ecRight
+ ShortCut = 39
+ end
+ item
+ Command = ecSelRight
+ ShortCut = 8231
+ end
+ item
+ Command = ecWordRight
+ ShortCut = 16423
+ end
+ item
+ Command = ecSelWordRight
+ ShortCut = 24615
+ end
+ item
+ Command = ecPageDown
+ ShortCut = 34
+ end
+ item
+ Command = ecSelPageDown
+ ShortCut = 8226
+ end
+ item
+ Command = ecPageBottom
+ ShortCut = 16418
+ end
+ item
+ Command = ecSelPageBottom
+ ShortCut = 24610
+ end
+ item
+ Command = ecPageUp
+ ShortCut = 33
+ end
+ item
+ Command = ecSelPageUp
+ ShortCut = 8225
+ end
+ item
+ Command = ecPageTop
+ ShortCut = 16417
+ end
+ item
+ Command = ecSelPageTop
+ ShortCut = 24609
+ end
+ item
+ Command = ecLineStart
+ ShortCut = 36
+ end
+ item
+ Command = ecSelLineStart
+ ShortCut = 8228
+ end
+ item
+ Command = ecEditorTop
+ ShortCut = 16420
+ end
+ item
+ Command = ecSelEditorTop
+ ShortCut = 24612
+ end
+ item
+ Command = ecLineEnd
+ ShortCut = 35
+ end
+ item
+ Command = ecSelLineEnd
+ ShortCut = 8227
+ end
+ item
+ Command = ecEditorBottom
+ ShortCut = 16419
+ end
+ item
+ Command = ecSelEditorBottom
+ ShortCut = 24611
+ end
+ item
+ Command = ecToggleMode
+ ShortCut = 45
+ end
+ item
+ Command = ecCopy
+ ShortCut = 16429
+ end
+ item
+ Command = ecPaste
+ ShortCut = 8237
+ end
+ item
+ Command = ecDeleteChar
+ ShortCut = 46
+ end
+ item
+ Command = ecCut
+ ShortCut = 8238
+ end
+ item
+ Command = ecDeleteLastChar
+ ShortCut = 8
+ end
+ item
+ Command = ecDeleteLastChar
+ ShortCut = 8200
+ end
+ item
+ Command = ecDeleteLastWord
+ ShortCut = 16392
+ end
+ item
+ Command = ecUndo
+ ShortCut = 32776
+ end
+ item
+ Command = ecRedo
+ ShortCut = 40968
+ end
+ item
+ Command = ecLineBreak
+ ShortCut = 13
+ end
+ item
+ Command = ecSelectAll
+ ShortCut = 16449
+ end
+ item
+ Command = ecCopy
+ ShortCut = 16451
+ end
+ item
+ Command = ecBlockIndent
+ ShortCut = 24649
+ end
+ item
+ Command = ecLineBreak
+ ShortCut = 16461
+ end
+ item
+ Command = ecBlockUnindent
+ ShortCut = 24661
+ end
+ item
+ Command = ecPaste
+ ShortCut = 16470
+ end
+ item
+ Command = ecCut
+ ShortCut = 16472
+ end
+ item
+ Command = ecDeleteLine
+ ShortCut = 16473
+ end
+ item
+ Command = ecDeleteEOL
+ ShortCut = 24665
+ end
+ item
+ Command = ecUndo
+ ShortCut = 16474
+ end
+ item
+ Command = ecRedo
+ ShortCut = 24666
+ end
+ item
+ Command = ecGotoMarker0
+ ShortCut = 16432
+ end
+ item
+ Command = ecGotoMarker1
+ ShortCut = 16433
+ end
+ item
+ Command = ecGotoMarker2
+ ShortCut = 16434
+ end
+ item
+ Command = ecGotoMarker3
+ ShortCut = 16435
+ end
+ item
+ Command = ecGotoMarker4
+ ShortCut = 16436
+ end
+ item
+ Command = ecGotoMarker5
+ ShortCut = 16437
+ end
+ item
+ Command = ecGotoMarker6
+ ShortCut = 16438
+ end
+ item
+ Command = ecGotoMarker7
+ ShortCut = 16439
+ end
+ item
+ Command = ecGotoMarker8
+ ShortCut = 16440
+ end
+ item
+ Command = ecGotoMarker9
+ ShortCut = 16441
+ end
+ item
+ Command = ecSetMarker0
+ ShortCut = 24624
+ end
+ item
+ Command = ecSetMarker1
+ ShortCut = 24625
+ end
+ item
+ Command = ecSetMarker2
+ ShortCut = 24626
+ end
+ item
+ Command = ecSetMarker3
+ ShortCut = 24627
+ end
+ item
+ Command = ecSetMarker4
+ ShortCut = 24628
+ end
+ item
+ Command = ecSetMarker5
+ ShortCut = 24629
+ end
+ item
+ Command = ecSetMarker6
+ ShortCut = 24630
+ end
+ item
+ Command = ecSetMarker7
+ ShortCut = 24631
+ end
+ item
+ Command = ecSetMarker8
+ ShortCut = 24632
+ end
+ item
+ Command = ecSetMarker9
+ ShortCut = 24633
+ end
+ item
+ Command = EcFoldLevel1
+ ShortCut = 41009
+ end
+ item
+ Command = EcFoldLevel2
+ ShortCut = 41010
+ end
+ item
+ Command = EcFoldLevel1
+ ShortCut = 41011
+ end
+ item
+ Command = EcFoldLevel1
+ ShortCut = 41012
+ end
+ item
+ Command = EcFoldLevel1
+ ShortCut = 41013
+ end
+ item
+ Command = EcFoldLevel6
+ ShortCut = 41014
+ end
+ item
+ Command = EcFoldLevel7
+ ShortCut = 41015
+ end
+ item
+ Command = EcFoldLevel8
+ ShortCut = 41016
+ end
+ item
+ Command = EcFoldLevel9
+ ShortCut = 41017
+ end
+ item
+ Command = EcFoldLevel0
+ ShortCut = 41008
+ end
+ item
+ Command = EcFoldCurrent
+ ShortCut = 41005
+ end
+ item
+ Command = EcUnFoldCurrent
+ ShortCut = 41003
+ end
+ item
+ Command = EcToggleMarkupWord
+ ShortCut = 32845
+ end
+ item
+ Command = ecNormalSelect
+ ShortCut = 24654
+ end
+ item
+ Command = ecColumnSelect
+ ShortCut = 24643
+ end
+ item
+ Command = ecLineSelect
+ ShortCut = 24652
+ end
+ item
+ Command = ecTab
+ ShortCut = 9
+ end
+ item
+ Command = ecShiftTab
+ ShortCut = 8201
+ end
+ item
+ Command = ecMatchBracket
+ ShortCut = 24642
+ end
+ item
+ Command = ecColSelUp
+ ShortCut = 40998
+ end
+ item
+ Command = ecColSelDown
+ ShortCut = 41000
+ end
+ item
+ Command = ecColSelLeft
+ ShortCut = 40997
+ end
+ item
+ Command = ecColSelRight
+ ShortCut = 40999
+ end
+ item
+ Command = ecColSelPageDown
+ ShortCut = 40994
+ end
+ item
+ Command = ecColSelPageBottom
+ ShortCut = 57378
+ end
+ item
+ Command = ecColSelPageUp
+ ShortCut = 40993
+ end
+ item
+ Command = ecColSelPageTop
+ ShortCut = 57377
+ end
+ item
+ Command = ecColSelLineStart
+ ShortCut = 40996
+ end
+ item
+ Command = ecColSelLineEnd
+ ShortCut = 40995
+ end
+ item
+ Command = ecColSelEditorTop
+ ShortCut = 57380
+ end
+ item
+ Command = ecColSelEditorBottom
+ ShortCut = 57379
+ end>
+ MouseActions = <
+ item
+ Shift = []
+ ShiftMask = [ssShift, ssAlt]
+ Button = mbLeft
+ ClickCount = ccSingle
+ ClickDir = cdDown
+ Command = 1
+ MoveCaret = True
+ Option = 0
+ Priority = 0
+ end
+ item
+ Shift = [ssShift]
+ ShiftMask = [ssShift, ssAlt]
+ Button = mbLeft
+ ClickCount = ccSingle
+ ClickDir = cdDown
+ Command = 1
+ MoveCaret = True
+ Option = 1
+ Priority = 0
+ end
+ item
+ Shift = [ssAlt]
+ ShiftMask = [ssShift, ssAlt]
+ Button = mbLeft
+ ClickCount = ccSingle
+ ClickDir = cdDown
+ Command = 3
+ MoveCaret = True
+ Option = 0
+ Priority = 0
+ end
+ item
+ Shift = [ssShift, ssAlt]
+ ShiftMask = [ssShift, ssAlt]
+ Button = mbLeft
+ ClickCount = ccSingle
+ ClickDir = cdDown
+ Command = 3
+ MoveCaret = True
+ Option = 1
+ Priority = 0
+ end
+ item
+ Shift = []
+ ShiftMask = []
+ Button = mbRight
+ ClickCount = ccSingle
+ ClickDir = cdUp
+ Command = 12
+ MoveCaret = False
+ Option = 0
+ Priority = 0
+ end
+ item
+ Shift = []
+ ShiftMask = []
+ Button = mbLeft
+ ClickCount = ccDouble
+ ClickDir = cdDown
+ Command = 6
+ MoveCaret = True
+ Option = 0
+ Priority = 0
+ end
+ item
+ Shift = []
+ ShiftMask = []
+ Button = mbLeft
+ ClickCount = ccTriple
+ ClickDir = cdDown
+ Command = 7
+ MoveCaret = True
+ Option = 0
+ Priority = 0
+ end
+ item
+ Shift = []
+ ShiftMask = []
+ Button = mbLeft
+ ClickCount = ccQuad
+ ClickDir = cdDown
+ Command = 8
+ MoveCaret = True
+ Option = 0
+ Priority = 0
+ end
+ item
+ Shift = []
+ ShiftMask = []
+ Button = mbMiddle
+ ClickCount = ccSingle
+ ClickDir = cdDown
+ Command = 10
+ MoveCaret = True
+ Option = 0
+ Priority = 0
+ end
+ item
+ Shift = [ssCtrl]
+ ShiftMask = [ssShift, ssAlt, ssCtrl]
+ Button = mbLeft
+ ClickCount = ccSingle
+ ClickDir = cdUp
+ Command = 11
+ MoveCaret = False
+ Option = 0
+ Priority = 0
+ end>
+ MouseSelActions = <
+ item
+ Shift = []
+ ShiftMask = []
+ Button = mbLeft
+ ClickCount = ccSingle
+ ClickDir = cdDown
+ Command = 9
+ MoveCaret = False
+ Option = 0
+ Priority = 0
+ end>
+ Lines.Strings = (
+ 'program new;'
+ 'begin'
+ 'end.'
+ )
+ BracketHighlightStyle = sbhsBoth
+ OnChange = SynEditChange
+ OnProcessCommand = SynEditProcessCommand
+ OnProcessUserCommand = SynEditProcessUserCommand
+ OnSpecialLineColors = SynEditSpecialLineColors
+ OnStatusChange = SynEditStatusChange
+ inline TSynGutterPartList
+ object TSynGutterMarks
+ Width = 23
+ end
+ object TSynGutterLineNumber
+ Width = 17
+ MouseActions = <>
+ MarkupInfo.Background = clBtnFace
+ MarkupInfo.Foreground = clNone
+ DigitCount = 2
+ ShowOnlyLineNumbersMultiplesOf = 1
+ ZeroStart = False
+ LeadingZeros = False
+ end
+ object TSynGutterChanges
+ Width = 4
+ ModifiedColor = 59900
+ SavedColor = clGreen
+ end
+ object TSynGutterSeparator
+ Width = 2
+ end
+ object TSynGutterCodeFolding
+ MouseActions = <
+ item
+ Shift = []
+ ShiftMask = []
+ Button = mbRight
+ ClickCount = ccSingle
+ ClickDir = cdUp
+ Command = 16
+ MoveCaret = False
+ Option = 0
+ Priority = 0
+ end
+ item
+ Shift = []
+ ShiftMask = [ssShift]
+ Button = mbMiddle
+ ClickCount = ccAny
+ ClickDir = cdDown
+ Command = 14
+ MoveCaret = False
+ Option = 0
+ Priority = 0
+ end
+ item
+ Shift = [ssShift]
+ ShiftMask = [ssShift]
+ Button = mbMiddle
+ ClickCount = ccAny
+ ClickDir = cdDown
+ Command = 14
+ MoveCaret = False
+ Option = 1
+ Priority = 0
+ end
+ item
+ Shift = []
+ ShiftMask = []
+ Button = mbLeft
+ ClickCount = ccAny
+ ClickDir = cdDown
+ Command = 0
+ MoveCaret = False
+ Option = 0
+ Priority = 0
+ end>
+ MarkupInfo.Background = clNone
+ MarkupInfo.Foreground = clGray
+ MouseActionsExpanded = <
+ item
+ Shift = []
+ ShiftMask = []
+ Button = mbLeft
+ ClickCount = ccAny
+ ClickDir = cdDown
+ Command = 14
+ MoveCaret = False
+ Option = 0
+ Priority = 0
+ end>
+ MouseActionsCollapsed = <
+ item
+ Shift = [ssCtrl]
+ ShiftMask = [ssCtrl]
+ Button = mbLeft
+ ClickCount = ccAny
+ ClickDir = cdDown
+ Command = 15
+ MoveCaret = False
+ Option = 0
+ Priority = 0
+ end
+ item
+ Shift = []
+ ShiftMask = [ssCtrl]
+ Button = mbLeft
+ ClickCount = ccAny
+ ClickDir = cdDown
+ Command = 15
+ MoveCaret = False
+ Option = 1
+ Priority = 0
+ end>
+ end
+ end
+ end
+ object SynFreePascalSyn1: TSynFreePascalSyn
+ Enabled = False
+ CommentAttri.Foreground = clBlue
+ CommentAttri.Style = [fsBold]
+ IdentifierAttri.Foreground = clDefault
+ NumberAttri.Foreground = clNavy
+ StringAttri.Foreground = clBlue
+ SymbolAttri.Foreground = clRed
+ DirectiveAttri.Foreground = clRed
+ DirectiveAttri.Style = [fsBold]
+ CompilerMode = pcmObjFPC
+ NestedComments = True
+ left = 320
+ top = 16
+ end
+end
\ No newline at end of file
diff --git a/branches/script-component/Projects/SAMufasaGUI/framescript.lrs b/branches/script-component/Projects/SAMufasaGUI/framescript.lrs
new file mode 100644
index 0000000..915e204
--- /dev/null
+++ b/branches/script-component/Projects/SAMufasaGUI/framescript.lrs
@@ -0,0 +1,153 @@
+LazarusResources.Add('TScriptFrame','FORMDATA',[
+ 'TPF0'#12'TScriptFrame'#11'ScriptFrame'#4'Left'#2#0#6'Height'#3'H'#1#3'Top'#2
+ +#0#5'Width'#3#141#1#12'ClientHeight'#3'H'#1#11'ClientWidth'#3#141#1#8'TabOrd'
+ +'er'#2#0#10'DesignLeft'#3#159#0#9'DesignTop'#3#164#1#0#244#8'TSynEdit'#7'Syn'
+ +'Edit'#4'Left'#2#0#6'Height'#3'H'#1#3'Top'#2#0#5'Width'#3#141#1#5'Align'#7#8
+ +'alClient'#11'Font.Height'#2#243#9'Font.Name'#6#11'Courier New'#10'Font.Pitc'
+ +'h'#7#7'fpFixed'#12'Font.Quality'#7#16'fqNonAntialiased'#11'ParentColor'#8#10
+ +'ParentFont'#8#9'PopupMenu'#7#17'Form1.ScriptPopup'#8'TabOrder'#2#0#10'OnDra'
+ +'gDrop'#7#15'SynEditDragDrop'#10'OnDragOver'#7#15'SynEditDragOver'#9'OnKeyDo'
+ +'wn'#7#14'SynEditKeyDown'#12'Gutter.Width'#2'9'#19'Gutter.MouseActions'#14#1
+ +#5'Shift'#11#0#9'ShiftMask'#11#0#6'Button'#7#6'mbLeft'#10'ClickCount'#7#5'cc'
+ +'Any'#8'ClickDir'#7#6'cdDown'#7'Command'#2#13#9'MoveCaret'#8#6'Option'#2#0#8
+ +'Priority'#2#0#0#1#5'Shift'#11#0#9'ShiftMask'#11#0#6'Button'#7#7'mbRight'#10
+ +'ClickCount'#7#8'ccSingle'#8'ClickDir'#7#4'cdUp'#7'Command'#2#12#9'MoveCaret'
+ +#8#6'Option'#2#0#8'Priority'#2#0#0#0#11'Highlighter'#7#17'SynFreePascalSyn1'
+ +#10'Keystrokes'#14#1#7'Command'#7#4'ecUp'#8'ShortCut'#2'&'#0#1#7'Command'#7#7
+ +'ecSelUp'#8'ShortCut'#3'& '#0#1#7'Command'#7#10'ecScrollUp'#8'ShortCut'#3'&@'
+ +#0#1#7'Command'#7#6'ecDown'#8'ShortCut'#2'('#0#1#7'Command'#7#9'ecSelDown'#8
+ +'ShortCut'#3'( '#0#1#7'Command'#7#12'ecScrollDown'#8'ShortCut'#3'(@'#0#1#7'C'
+ +'ommand'#7#6'ecLeft'#8'ShortCut'#2'%'#0#1#7'Command'#7#9'ecSelLeft'#8'ShortC'
+ +'ut'#3'% '#0#1#7'Command'#7#10'ecWordLeft'#8'ShortCut'#3'%@'#0#1#7'Command'#7
+ +#13'ecSelWordLeft'#8'ShortCut'#3'%`'#0#1#7'Command'#7#7'ecRight'#8'ShortCut'
+ +#2''''#0#1#7'Command'#7#10'ecSelRight'#8'ShortCut'#3''' '#0#1#7'Command'#7#11
+ +'ecWordRight'#8'ShortCut'#3'''@'#0#1#7'Command'#7#14'ecSelWordRight'#8'Short'
+ +'Cut'#3'''`'#0#1#7'Command'#7#10'ecPageDown'#8'ShortCut'#2'"'#0#1#7'Command'
+ +#7#13'ecSelPageDown'#8'ShortCut'#3'" '#0#1#7'Command'#7#12'ecPageBottom'#8'S'
+ +'hortCut'#3'"@'#0#1#7'Command'#7#15'ecSelPageBottom'#8'ShortCut'#3'"`'#0#1#7
+ +'Command'#7#8'ecPageUp'#8'ShortCut'#2'!'#0#1#7'Command'#7#11'ecSelPageUp'#8
+ +'ShortCut'#3'! '#0#1#7'Command'#7#9'ecPageTop'#8'ShortCut'#3'!@'#0#1#7'Comma'
+ +'nd'#7#12'ecSelPageTop'#8'ShortCut'#3'!`'#0#1#7'Command'#7#11'ecLineStart'#8
+ +'ShortCut'#2'$'#0#1#7'Command'#7#14'ecSelLineStart'#8'ShortCut'#3'$ '#0#1#7
+ +'Command'#7#11'ecEditorTop'#8'ShortCut'#3'$@'#0#1#7'Command'#7#14'ecSelEdito'
+ +'rTop'#8'ShortCut'#3'$`'#0#1#7'Command'#7#9'ecLineEnd'#8'ShortCut'#2'#'#0#1#7
+ +'Command'#7#12'ecSelLineEnd'#8'ShortCut'#3'# '#0#1#7'Command'#7#14'ecEditorB'
+ +'ottom'#8'ShortCut'#3'#@'#0#1#7'Command'#7#17'ecSelEditorBottom'#8'ShortCut'
+ +#3'#`'#0#1#7'Command'#7#12'ecToggleMode'#8'ShortCut'#2'-'#0#1#7'Command'#7#6
+ +'ecCopy'#8'ShortCut'#3'-@'#0#1#7'Command'#7#7'ecPaste'#8'ShortCut'#3'- '#0#1
+ +#7'Command'#7#12'ecDeleteChar'#8'ShortCut'#2'.'#0#1#7'Command'#7#5'ecCut'#8
+ +'ShortCut'#3'. '#0#1#7'Command'#7#16'ecDeleteLastChar'#8'ShortCut'#2#8#0#1#7
+ +'Command'#7#16'ecDeleteLastChar'#8'ShortCut'#3#8' '#0#1#7'Command'#7#16'ecDe'
+ +'leteLastWord'#8'ShortCut'#3#8'@'#0#1#7'Command'#7#6'ecUndo'#8'ShortCut'#4#8
+ +#128#0#0#0#1#7'Command'#7#6'ecRedo'#8'ShortCut'#4#8#160#0#0#0#1#7'Command'#7
+ +#11'ecLineBreak'#8'ShortCut'#2#13#0#1#7'Command'#7#11'ecSelectAll'#8'ShortCu'
+ +'t'#3'A@'#0#1#7'Command'#7#6'ecCopy'#8'ShortCut'#3'C@'#0#1#7'Command'#7#13'e'
+ +'cBlockIndent'#8'ShortCut'#3'I`'#0#1#7'Command'#7#11'ecLineBreak'#8'ShortCut'
+ +#3'M@'#0#1#7'Command'#7#15'ecBlockUnindent'#8'ShortCut'#3'U`'#0#1#7'Command'
+ +#7#7'ecPaste'#8'ShortCut'#3'V@'#0#1#7'Command'#7#5'ecCut'#8'ShortCut'#3'X@'#0
+ +#1#7'Command'#7#12'ecDeleteLine'#8'ShortCut'#3'Y@'#0#1#7'Command'#7#11'ecDel'
+ +'eteEOL'#8'ShortCut'#3'Y`'#0#1#7'Command'#7#6'ecUndo'#8'ShortCut'#3'Z@'#0#1#7
+ +'Command'#7#6'ecRedo'#8'ShortCut'#3'Z`'#0#1#7'Command'#7#13'ecGotoMarker0'#8
+ +'ShortCut'#3'0@'#0#1#7'Command'#7#13'ecGotoMarker1'#8'ShortCut'#3'1@'#0#1#7
+ +'Command'#7#13'ecGotoMarker2'#8'ShortCut'#3'2@'#0#1#7'Command'#7#13'ecGotoMa'
+ +'rker3'#8'ShortCut'#3'3@'#0#1#7'Command'#7#13'ecGotoMarker4'#8'ShortCut'#3'4'
+ +'@'#0#1#7'Command'#7#13'ecGotoMarker5'#8'ShortCut'#3'5@'#0#1#7'Command'#7#13
+ +'ecGotoMarker6'#8'ShortCut'#3'6@'#0#1#7'Command'#7#13'ecGotoMarker7'#8'Short'
+ +'Cut'#3'7@'#0#1#7'Command'#7#13'ecGotoMarker8'#8'ShortCut'#3'8@'#0#1#7'Comma'
+ +'nd'#7#13'ecGotoMarker9'#8'ShortCut'#3'9@'#0#1#7'Command'#7#12'ecSetMarker0'
+ +#8'ShortCut'#3'0`'#0#1#7'Command'#7#12'ecSetMarker1'#8'ShortCut'#3'1`'#0#1#7
+ +'Command'#7#12'ecSetMarker2'#8'ShortCut'#3'2`'#0#1#7'Command'#7#12'ecSetMark'
+ +'er3'#8'ShortCut'#3'3`'#0#1#7'Command'#7#12'ecSetMarker4'#8'ShortCut'#3'4`'#0
+ +#1#7'Command'#7#12'ecSetMarker5'#8'ShortCut'#3'5`'#0#1#7'Command'#7#12'ecSet'
+ +'Marker6'#8'ShortCut'#3'6`'#0#1#7'Command'#7#12'ecSetMarker7'#8'ShortCut'#3
+ +'7`'#0#1#7'Command'#7#12'ecSetMarker8'#8'ShortCut'#3'8`'#0#1#7'Command'#7#12
+ +'ecSetMarker9'#8'ShortCut'#3'9`'#0#1#7'Command'#7#12'EcFoldLevel1'#8'ShortCu'
+ +'t'#4'1'#160#0#0#0#1#7'Command'#7#12'EcFoldLevel2'#8'ShortCut'#4'2'#160#0#0#0
+ ,#1#7'Command'#7#12'EcFoldLevel1'#8'ShortCut'#4'3'#160#0#0#0#1#7'Command'#7#12
+ +'EcFoldLevel1'#8'ShortCut'#4'4'#160#0#0#0#1#7'Command'#7#12'EcFoldLevel1'#8
+ +'ShortCut'#4'5'#160#0#0#0#1#7'Command'#7#12'EcFoldLevel6'#8'ShortCut'#4'6'
+ +#160#0#0#0#1#7'Command'#7#12'EcFoldLevel7'#8'ShortCut'#4'7'#160#0#0#0#1#7'Co'
+ +'mmand'#7#12'EcFoldLevel8'#8'ShortCut'#4'8'#160#0#0#0#1#7'Command'#7#12'EcFo'
+ +'ldLevel9'#8'ShortCut'#4'9'#160#0#0#0#1#7'Command'#7#12'EcFoldLevel0'#8'Shor'
+ +'tCut'#4'0'#160#0#0#0#1#7'Command'#7#13'EcFoldCurrent'#8'ShortCut'#4'-'#160#0
+ +#0#0#1#7'Command'#7#15'EcUnFoldCurrent'#8'ShortCut'#4'+'#160#0#0#0#1#7'Comma'
+ +'nd'#7#18'EcToggleMarkupWord'#8'ShortCut'#4'M'#128#0#0#0#1#7'Command'#7#14'e'
+ +'cNormalSelect'#8'ShortCut'#3'N`'#0#1#7'Command'#7#14'ecColumnSelect'#8'Shor'
+ +'tCut'#3'C`'#0#1#7'Command'#7#12'ecLineSelect'#8'ShortCut'#3'L`'#0#1#7'Comma'
+ +'nd'#7#5'ecTab'#8'ShortCut'#2#9#0#1#7'Command'#7#10'ecShiftTab'#8'ShortCut'#3
+ +#9' '#0#1#7'Command'#7#14'ecMatchBracket'#8'ShortCut'#3'B`'#0#1#7'Command'#7
+ +#10'ecColSelUp'#8'ShortCut'#4'&'#160#0#0#0#1#7'Command'#7#12'ecColSelDown'#8
+ +'ShortCut'#4'('#160#0#0#0#1#7'Command'#7#12'ecColSelLeft'#8'ShortCut'#4'%'
+ +#160#0#0#0#1#7'Command'#7#13'ecColSelRight'#8'ShortCut'#4''''#160#0#0#0#1#7
+ +'Command'#7#16'ecColSelPageDown'#8'ShortCut'#4'"'#160#0#0#0#1#7'Command'#7#18
+ +'ecColSelPageBottom'#8'ShortCut'#4'"'#224#0#0#0#1#7'Command'#7#14'ecColSelPa'
+ +'geUp'#8'ShortCut'#4'!'#160#0#0#0#1#7'Command'#7#15'ecColSelPageTop'#8'Short'
+ +'Cut'#4'!'#224#0#0#0#1#7'Command'#7#17'ecColSelLineStart'#8'ShortCut'#4'$'
+ +#160#0#0#0#1#7'Command'#7#15'ecColSelLineEnd'#8'ShortCut'#4'#'#160#0#0#0#1#7
+ +'Command'#7#17'ecColSelEditorTop'#8'ShortCut'#4'$'#224#0#0#0#1#7'Command'#7
+ +#20'ecColSelEditorBottom'#8'ShortCut'#4'#'#224#0#0#0#0#12'MouseActions'#14#1
+ +#5'Shift'#11#0#9'ShiftMask'#11#7'ssShift'#5'ssAlt'#0#6'Button'#7#6'mbLeft'#10
+ +'ClickCount'#7#8'ccSingle'#8'ClickDir'#7#6'cdDown'#7'Command'#2#1#9'MoveCare'
+ +'t'#9#6'Option'#2#0#8'Priority'#2#0#0#1#5'Shift'#11#7'ssShift'#0#9'ShiftMask'
+ +#11#7'ssShift'#5'ssAlt'#0#6'Button'#7#6'mbLeft'#10'ClickCount'#7#8'ccSingle'
+ +#8'ClickDir'#7#6'cdDown'#7'Command'#2#1#9'MoveCaret'#9#6'Option'#2#1#8'Prior'
+ +'ity'#2#0#0#1#5'Shift'#11#5'ssAlt'#0#9'ShiftMask'#11#7'ssShift'#5'ssAlt'#0#6
+ +'Button'#7#6'mbLeft'#10'ClickCount'#7#8'ccSingle'#8'ClickDir'#7#6'cdDown'#7
+ +'Command'#2#3#9'MoveCaret'#9#6'Option'#2#0#8'Priority'#2#0#0#1#5'Shift'#11#7
+ +'ssShift'#5'ssAlt'#0#9'ShiftMask'#11#7'ssShift'#5'ssAlt'#0#6'Button'#7#6'mbL'
+ +'eft'#10'ClickCount'#7#8'ccSingle'#8'ClickDir'#7#6'cdDown'#7'Command'#2#3#9
+ +'MoveCaret'#9#6'Option'#2#1#8'Priority'#2#0#0#1#5'Shift'#11#0#9'ShiftMask'#11
+ +#0#6'Button'#7#7'mbRight'#10'ClickCount'#7#8'ccSingle'#8'ClickDir'#7#4'cdUp'
+ +#7'Command'#2#12#9'MoveCaret'#8#6'Option'#2#0#8'Priority'#2#0#0#1#5'Shift'#11
+ +#0#9'ShiftMask'#11#0#6'Button'#7#6'mbLeft'#10'ClickCount'#7#8'ccDouble'#8'Cl'
+ +'ickDir'#7#6'cdDown'#7'Command'#2#6#9'MoveCaret'#9#6'Option'#2#0#8'Priority'
+ +#2#0#0#1#5'Shift'#11#0#9'ShiftMask'#11#0#6'Button'#7#6'mbLeft'#10'ClickCount'
+ +#7#8'ccTriple'#8'ClickDir'#7#6'cdDown'#7'Command'#2#7#9'MoveCaret'#9#6'Optio'
+ +'n'#2#0#8'Priority'#2#0#0#1#5'Shift'#11#0#9'ShiftMask'#11#0#6'Button'#7#6'mb'
+ +'Left'#10'ClickCount'#7#6'ccQuad'#8'ClickDir'#7#6'cdDown'#7'Command'#2#8#9'M'
+ +'oveCaret'#9#6'Option'#2#0#8'Priority'#2#0#0#1#5'Shift'#11#0#9'ShiftMask'#11
+ +#0#6'Button'#7#8'mbMiddle'#10'ClickCount'#7#8'ccSingle'#8'ClickDir'#7#6'cdDo'
+ +'wn'#7'Command'#2#10#9'MoveCaret'#9#6'Option'#2#0#8'Priority'#2#0#0#1#5'Shif'
+ +'t'#11#6'ssCtrl'#0#9'ShiftMask'#11#7'ssShift'#5'ssAlt'#6'ssCtrl'#0#6'Button'
+ +#7#6'mbLeft'#10'ClickCount'#7#8'ccSingle'#8'ClickDir'#7#4'cdUp'#7'Command'#2
+ +#11#9'MoveCaret'#8#6'Option'#2#0#8'Priority'#2#0#0#0#15'MouseSelActions'#14#1
+ +#5'Shift'#11#0#9'ShiftMask'#11#0#6'Button'#7#6'mbLeft'#10'ClickCount'#7#8'cc'
+ +'Single'#8'ClickDir'#7#6'cdDown'#7'Command'#2#9#9'MoveCaret'#8#6'Option'#2#0
+ +#8'Priority'#2#0#0#0#13'Lines.Strings'#1#6#12'program new;'#6#5'begin'#6#4'e'
+ +'nd.'#0#21'BracketHighlightStyle'#7#8'sbhsBoth'#8'OnChange'#7#13'SynEditChan'
+ +'ge'#16'OnProcessCommand'#7#21'SynEditProcessCommand'#20'OnProcessUserComman'
+ +'d'#7#25'SynEditProcessUserCommand'#19'OnSpecialLineColors'#7#24'SynEditSpec'
+ +'ialLineColors'#14'OnStatusChange'#7#19'SynEditStatusChange'#0#244#18'TSynGu'
+ +'tterPartList'#0#0#15'TSynGutterMarks'#0#5'Width'#2#23#0#0#20'TSynGutterLine'
+ +'Number'#0#5'Width'#2#17#12'MouseActions'#14#0#21'MarkupInfo.Background'#7#9
+ +'clBtnFace'#21'MarkupInfo.Foreground'#7#6'clNone'#10'DigitCount'#2#2#30'Show'
+ +'OnlyLineNumbersMultiplesOf'#2#1#9'ZeroStart'#8#12'LeadingZeros'#8#0#0#17'TS'
+ +'ynGutterChanges'#0#5'Width'#2#4#13'ModifiedColor'#4#252#233#0#0#10'SavedCol'
+ +'or'#7#7'clGreen'#0#0#19'TSynGutterSeparator'#0#5'Width'#2#2#0#0#21'TSynGutt'
+ +'erCodeFolding'#0#12'MouseActions'#14#1#5'Shift'#11#0#9'ShiftMask'#11#0#6'Bu'
+ +'tton'#7#7'mbRight'#10'ClickCount'#7#8'ccSingle'#8'ClickDir'#7#4'cdUp'#7'Com'
+ +'mand'#2#16#9'MoveCaret'#8#6'Option'#2#0#8'Priority'#2#0#0#1#5'Shift'#11#0#9
+ ,'ShiftMask'#11#7'ssShift'#0#6'Button'#7#8'mbMiddle'#10'ClickCount'#7#5'ccAny'
+ +#8'ClickDir'#7#6'cdDown'#7'Command'#2#14#9'MoveCaret'#8#6'Option'#2#0#8'Prio'
+ +'rity'#2#0#0#1#5'Shift'#11#7'ssShift'#0#9'ShiftMask'#11#7'ssShift'#0#6'Butto'
+ +'n'#7#8'mbMiddle'#10'ClickCount'#7#5'ccAny'#8'ClickDir'#7#6'cdDown'#7'Comman'
+ +'d'#2#14#9'MoveCaret'#8#6'Option'#2#1#8'Priority'#2#0#0#1#5'Shift'#11#0#9'Sh'
+ +'iftMask'#11#0#6'Button'#7#6'mbLeft'#10'ClickCount'#7#5'ccAny'#8'ClickDir'#7
+ +#6'cdDown'#7'Command'#2#0#9'MoveCaret'#8#6'Option'#2#0#8'Priority'#2#0#0#0#21
+ +'MarkupInfo.Background'#7#6'clNone'#21'MarkupInfo.Foreground'#7#6'clGray'#20
+ +'MouseActionsExpanded'#14#1#5'Shift'#11#0#9'ShiftMask'#11#0#6'Button'#7#6'mb'
+ +'Left'#10'ClickCount'#7#5'ccAny'#8'ClickDir'#7#6'cdDown'#7'Command'#2#14#9'M'
+ +'oveCaret'#8#6'Option'#2#0#8'Priority'#2#0#0#0#21'MouseActionsCollapsed'#14#1
+ +#5'Shift'#11#6'ssCtrl'#0#9'ShiftMask'#11#6'ssCtrl'#0#6'Button'#7#6'mbLeft'#10
+ +'ClickCount'#7#5'ccAny'#8'ClickDir'#7#6'cdDown'#7'Command'#2#15#9'MoveCaret'
+ +#8#6'Option'#2#0#8'Priority'#2#0#0#1#5'Shift'#11#0#9'ShiftMask'#11#6'ssCtrl'
+ +#0#6'Button'#7#6'mbLeft'#10'ClickCount'#7#5'ccAny'#8'ClickDir'#7#6'cdDown'#7
+ +'Command'#2#15#9'MoveCaret'#8#6'Option'#2#1#8'Priority'#2#0#0#0#0#0#0#0#17'T'
+ +'SynFreePascalSyn'#17'SynFreePascalSyn1'#7'Enabled'#8#23'CommentAttri.Foregr'
+ +'ound'#7#6'clBlue'#18'CommentAttri.Style'#11#6'fsBold'#0#26'IdentifierAttri.'
+ +'Foreground'#7#9'clDefault'#22'NumberAttri.Foreground'#7#6'clNavy'#22'String'
+ +'Attri.Foreground'#7#6'clBlue'#22'SymbolAttri.Foreground'#7#5'clRed'#25'Dire'
+ +'ctiveAttri.Foreground'#7#5'clRed'#20'DirectiveAttri.Style'#11#6'fsBold'#0#12
+ +'CompilerMode'#7#9'pcmObjFPC'#14'NestedComments'#9#4'left'#3'@'#1#3'top'#2#16
+ +#0#0#0
+]);
diff --git a/branches/script-component/Projects/SAMufasaGUI/framescript.pas b/branches/script-component/Projects/SAMufasaGUI/framescript.pas
new file mode 100644
index 0000000..4abaf30
--- /dev/null
+++ b/branches/script-component/Projects/SAMufasaGUI/framescript.pas
@@ -0,0 +1,356 @@
+{
+ This file is part of the Mufasa Macro Library (MML)
+ Copyright (c) 2009 by Raymond van Venetië and Merlijn Wajer
+
+ MML is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ MML is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with MML. If not, see .
+
+ See the file COPYING, included in this distribution,
+ for details about the copyright.
+
+ framescript for the Mufasa Macro Library
+}
+unit framescript;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+ Classes, SysUtils, FileUtil, LResources, Forms, SynHighlighterPas, SynEdit, SynEditMarkupHighAll,
+ mmlpsthread,ComCtrls, SynEditKeyCmds, LCLType, SynEditMarkupSpecialLine, Graphics, Controls;
+const
+ ecCodeCompletion = ecUserFirst;
+type
+ TScriptState = (ss_None,ss_Running,ss_Paused,ss_Stopping);
+ {
+ ss_None: Means the script either hasn't been run yet, or it has ended (Succesfully or terminated)
+ ss_Running: Means the script is running as we speak :-)
+ ss_Paused: Means the script is currently in pause modus.
+ ss_Stopping: Means we've asked PS-Script politely to stop the script (next time we press the stop button we won't be that nice).
+ }
+
+ { TScriptFrame }
+
+ TScriptFrame = class(TFrame)
+ SynEdit: TSynEdit;
+ SynFreePascalSyn1: TSynFreePascalSyn;
+ procedure SynEditChange(Sender: TObject);
+ procedure SynEditDragDrop(Sender, Source: TObject; X, Y: Integer);
+ procedure SynEditDragOver(Sender, Source: TObject; X, Y: Integer;
+ State: TDragState; var Accept: Boolean);
+ procedure SynEditKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState
+ );
+ procedure SynEditProcessCommand(Sender: TObject;
+ var Command: TSynEditorCommand; var AChar: TUTF8Char; Data: pointer);
+ procedure SynEditProcessUserCommand(Sender: TObject;
+ var Command: TSynEditorCommand; var AChar: TUTF8Char; Data: pointer);
+ procedure SynEditSpecialLineColors(Sender: TObject; Line: integer;
+ var Special: boolean; var FG, BG: TColor);
+ procedure SynEditStatusChange(Sender: TObject; Changes: TSynStatusChanges);
+ private
+ OwnerPage : TPageControl;
+ OwnerSheet : TTabSheet;//The owner TTabsheet -> For title setting
+ public
+ ErrorData : TErrorData; //For threadsafestuff
+ ScriptErrorLine : integer; //Highlight the error line!
+ ScriptFile : string;//The path to the saved/opened file currently in the SynEdit
+ StartText : string;//The text synedit holds upon start/open/save
+ ScriptName : string;//The name of the currently opened/saved file.
+ ScriptDefault : string;//The default script e.g. program new; begin end.
+ ScriptChanged : boolean;//We need this for that little * (edited star).
+ ScriptThread : TMMLPSThread;//Just one thread for now..
+ FScriptState : TScriptState;//Stores the ScriptState, if you want the Run/Pause/Start buttons to change accordingly, acces through Form1
+ procedure undo;
+ procedure redo;
+ procedure HandleErrorData;
+ procedure MakeActiveScriptFrame;
+ procedure ScriptThreadTerminate(Sender: TObject);
+ constructor Create(TheOwner: TComponent); override;
+ destructor Destroy; override;
+ { public declarations }
+ end;
+
+implementation
+uses
+ TestUnit, SynEditTypes, LCLIntF, StrUtils,framefunctionlist;
+
+{ TScriptFrame }
+
+procedure TScriptFrame.SynEditChange(Sender: TObject);
+begin
+ ScriptErrorLine:= -1;
+ if not ScriptChanged then
+ begin;
+ ScriptChanged:= True;
+ Form1.Caption:= Format(WindowTitle,[ScriptName + '*']);
+ OwnerSheet.Caption:=ScriptName + '*';
+ end;
+end;
+
+procedure TScriptFrame.SynEditDragDrop(Sender, Source: TObject; X, Y: Integer);
+begin
+ if Source is TFunctionListFrame then
+ if TFunctionListFrame(Source).DraggingNode.Data <> nil then
+ SynEdit.InsertTextAtCaret( GetMethodName(PChar(TFunctionListFrame(Source).DraggingNode.Data),true));
+end;
+
+procedure TScriptFrame.SynEditDragOver(Sender, Source: TObject; X, Y: Integer;
+ State: TDragState; var Accept: Boolean);
+begin
+ Accept := Source = Form1.frmFunctionList;
+ if(Accept)then
+ begin
+ SynEdit.CaretXY := SynEdit.PixelsToLogicalPos(point(x, y));
+ if(not(Form1.Active))then Form1.BringToFront;
+ if(Form1.ActiveControl <> SynEdit)then Form1.ActiveControl := SynEdit;
+ end;
+end;
+
+procedure TScriptFrame.SynEditKeyDown(Sender: TObject; var Key: Word;
+ Shift: TShiftState);
+begin
+ if key = VK_F3 then
+ begin;
+ Form1.ActionFindNextExecute(Sender);
+ key := 0;
+ end;
+end;
+
+procedure TScriptFrame.SynEditProcessCommand(Sender: TObject;
+ var Command: TSynEditorCommand; var AChar: TUTF8Char; Data: pointer);
+begin
+ if Command = ecUndo then
+ begin;
+ Command:= ecNone;
+ Self.Undo;
+ end else
+ if Command = ecRedo then
+ begin;
+ Command := ecNone;
+ Self.Redo;
+ end;
+end;
+
+procedure TScriptFrame.SynEditProcessUserCommand(Sender: TObject;
+ var Command: TSynEditorCommand; var AChar: TUTF8Char; Data: pointer);
+var
+ LineText,SearchText : string;
+ Caret : TPoint;
+ i,endI : integer;
+begin
+ if Command = ecCodeCompletion then
+ begin
+ form1.FunctionListShown(True);
+ with form1.frmFunctionList do
+ if editSearchList.CanFocus then
+ begin;
+ editSearchList.SetFocus;
+ LineText := SynEdit.LineText;
+ Caret:=SynEdit.LogicalCaretXY;
+ i := Caret.X - 1;
+ endi := caret.x;
+ if (i > length(LineText)) or ((i = 0) and (length(lineText) = 0)) then
+ begin
+ SearchText:= '';
+ CompletionLine := PadRight(linetext,caret.x);
+ end
+ else begin
+ while (i > 0) and (LineText[i] in ['a'..'z','A'..'Z','0'..'9','_']) do
+ dec(i);
+ while LineText[endi] in ['a'..'z','A'..'Z','0'..'9','_'] do
+ inc(endi);
+ SearchText := Trim(copy(LineText, i + 1, Caret.X - i - 1));
+ CompletionLine := LineText;
+ end;
+ CompletionStart:= LineText;
+ Delete(CompletionLine,i+1,endi - i - 1);
+ Insert('%s',CompletionLine,i+1);
+ CompletionCaret := Point(endi,Caret.y);
+ StartWordCompletion:= Point(i+1,caret.y);
+ Writeln(CompletionLine);
+ Writeln(CompletionStart);
+ InCodeCompletion := true;
+ editSearchList.Text:= SearchText;
+ editSearchList.SelStart:= Length(searchText);
+ SynEdit.SelectedColor.Style:= [fsUnderline];
+ SynEdit.SelectedColor.Foreground:= clBlack;
+ SynEdit.SelectedColor.Background:= clWhite;
+ Synedit.MarkupByClass[TSynEditMarkupHighlightAllCaret].TempDisable;
+ end;
+ end;
+end;
+
+procedure TScriptFrame.SynEditSpecialLineColors(Sender: TObject;
+ Line: integer; var Special: boolean; var FG, BG: TColor);
+begin
+ if line = ScriptErrorLine then
+ begin;
+ Special := true;
+ BG := $50a0ff;
+ FG := 0;
+ end;
+end;
+
+procedure TScriptFrame.SynEditStatusChange(Sender: TObject;
+ Changes: TSynStatusChanges);
+begin
+ {$IFDEF UpdateEditButtons}
+ if scSelection in changes then
+ begin;
+ Form1.TT_Cut.Enabled := SynEdit.SelAvail;
+ form1.TT_Copy.Enabled:= Form1.TT_Cut.Enabled;
+ form1.TT_Paste.Enabled:= SynEdit.CanPaste;
+ end;
+ {$ENDIF}
+end;
+
+
+procedure TScriptFrame.undo;
+begin
+ SynEdit.Undo;
+ if ScriptChanged then
+ if SynEdit.Lines.Text = StartText then
+ begin;
+ Form1.Caption:= format(WindowTitle,[ScriptName]);
+ OwnerSheet.Caption:= ScriptName;
+ ScriptChanged := false;
+ end;
+end;
+
+procedure TScriptFrame.redo;
+begin
+ SynEdit.Redo;
+ if ScriptChanged then
+ if SynEdit.Lines.Text = StartText then
+ begin;
+ Form1.Caption:= format(WindowTitle,[ScriptName]);
+ OwnerSheet.Caption := ScriptName;
+ ScriptChanged := false;
+ end;
+end;
+
+procedure TScriptFrame.HandleErrorData;
+var
+ i : integer;
+begin
+ if ErrorData.Module <> '' then
+ begin;
+ if not FileExists(ErrorData.Module) then
+ ErrorData.Module := ErrorData.IncludePath + ErrorData.Module;
+ if not FileExists(ErrorData.Module) then
+ Writeln('ERROR comes from a non-existing file....')
+ else
+ begin
+ ErrorData.Module:= SetDirSeparators(ErrorData.Module);// Set it right ;-)
+ for i := 0 to Form1.Tabs.Count - 1 do
+ if lowercase(TMufasaTab(Form1.Tabs[i]).ScriptFrame.ScriptFile) = lowercase(ErrorData.Module) then
+ begin;
+ ErrorData.Module:= '';
+ TMufasaTab(Form1.Tabs[i]).ScriptFrame.ErrorData := Self.ErrorData;
+ TMufasaTab(Form1.Tabs[i]).ScriptFrame.HandleErrorData;
+ Exit;
+ end;
+ Form1.AddTab;
+ Form1.LoadScriptFile(ErrorData.Module);
+ ErrorData.Module:= '';
+ Form1.CurrScript.ErrorData := Self.ErrorData;
+ Form1.CurrScript.HandleErrorData;
+ exit;
+ end;
+ end;
+ MakeActiveScriptFrame;
+ ScriptErrorLine:= ErrorData.Line;
+ SynEdit.Invalidate;
+ SynEdit.SelStart:= ErrorData.Position;
+ if pos('error',lowercase(ErrorData.Error)) > 0 then
+ formWriteln(Format('%s at line %d',[ErrorData.Error,ErrorData.Line]))
+ else
+ formWriteln(Format('Error: %s at line %d',[ErrorData.Error,ErrorData.Line]));
+end;
+
+procedure TScriptFrame.MakeActiveScriptFrame;
+var
+ i : integer;
+begin
+ if Form1.Visible then
+ for i := 0 to OwnerPage.PageCount - 1 do
+ if OwnerPage.Pages[i] = OwnerSheet then
+ begin;
+ OwnerPage.TabIndex := i;
+ if OwnerSheet.CanFocus then
+ OwnerSheet.SetFocus;
+ exit;
+ end;
+end;
+
+procedure TScriptFrame.ScriptThreadTerminate(Sender: TObject);
+begin
+ FScriptState:= ss_None;
+ Form1.RefreshTab;
+end;
+procedure AddKey(const SynEdit : TSynEdit; const ACmd: TSynEditorCommand; const AKey: word;const AShift: TShiftState);
+begin
+ with SynEdit.KeyStrokes.Add do
+ begin
+ Key := AKey;
+ Shift := AShift;
+ Command := ACmd;
+ end;
+end;
+constructor TScriptFrame.Create(TheOwner: TComponent);
+var
+ MarkCaret : TSynEditMarkupHighlightAllCaret;
+begin
+ inherited Create(TheOwner);
+ OwnerSheet := TTabSheet(TheOwner);
+ OwnerPage := TPageControl(OwnerSheet.Owner);
+ StartText:= SynEdit.Lines.text;
+ ScriptDefault:= StartText;
+ ScriptName:= 'Untitled';
+ ScriptChanged := false;
+ FScriptState:= ss_None;
+ ScriptErrorLine:= -1;
+ OwnerSheet.Caption:= ScriptName;
+ SynEdit.Options:= SynEdit.Options- [eoGroupUndo];
+ SynEdit.Options:= SynEdit.Options+ [eoGroupUndo];
+ SynEdit.IncrementColor.Background := $30D070;
+ SynEdit.HighlightAllColor.Background:= clYellow;
+ SynEdit.HighlightAllColor.Foreground:= clDefault;
+ MarkCaret := TSynEditMarkupHighlightAllCaret(SynEdit.MarkupByClass[TSynEditMarkupHighlightAllCaret]);
+ if assigned(MarkCaret) then
+ begin
+ with MarkCaret.MarkupInfo do
+ begin;
+ Background :=$E6E6E6;
+ FrameColor := clGray;
+ end;
+ MarkCaret.Enabled := True;
+ MarkCaret.FullWord:= True;
+ MarkCaret.FullWordMaxLen:= 3;
+ MarkCaret.WaitTime := 1500;
+ MarkCaret.IgnoreKeywords := true;
+ end;
+ AddKey(SynEdit,ecCodeCompletion,VK_SPACE,[ssCtrl]);
+end;
+
+destructor TScriptFrame.Destroy;
+begin
+ inherited Destroy;
+end;
+
+initialization
+ {$I framescript.lrs}
+
+end.
+
diff --git a/branches/script-component/Projects/SAMufasaGUI/project1.lpi b/branches/script-component/Projects/SAMufasaGUI/project1.lpi
new file mode 100644
index 0000000..807a915
--- /dev/null
+++ b/branches/script-component/Projects/SAMufasaGUI/project1.lpi
@@ -0,0 +1,2256 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/branches/script-component/Projects/SAMufasaGUI/project1.lpr b/branches/script-component/Projects/SAMufasaGUI/project1.lpr
new file mode 100644
index 0000000..0db1af9
--- /dev/null
+++ b/branches/script-component/Projects/SAMufasaGUI/project1.lpr
@@ -0,0 +1,50 @@
+{
+ This file is part of the Mufasa Macro Library (MML)
+ Copyright (c) 2009 by Raymond van Venetië and Merlijn Wajer
+
+ MML is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ MML is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with MML. If not, see .
+
+ See the file COPYING, included in this distribution,
+ for details about the copyright.
+
+ SAMufasaGUI for the Mufasa Macro Library
+}
+
+program project1;
+
+{$mode objfpc}{$H+}
+
+uses
+ {$IFDEF UNIX}{$IFDEF UseCThreads}
+ cthreads, cmem,
+ {$ENDIF}{$ENDIF}
+ Interfaces, Forms, testunit, colourhistory, About, internets, debugimage,
+ framefunctionlist, simpleanalyzer, updater, updateform, simbasettings,
+libloader;
+
+//{$R project1.res}
+
+begin
+ Application.Title:='Simba';
+ Application.Initialize;
+
+ Application.CreateForm(TForm1, Form1);
+ Application.CreateForm(TColourHistoryForm, ColourHistoryForm);
+ Application.CreateForm(TAboutForm, AboutForm);
+ Application.CreateForm(TDebugImgForm, DebugImgForm);
+ Application.CreateForm(TSimbaUpdateForm, SimbaUpdateForm);
+ Application.CreateForm(TSettingsForm, SettingsForm);
+ Application.Run;
+end.
+
diff --git a/branches/script-component/Projects/SAMufasaGUI/project1.lrs b/branches/script-component/Projects/SAMufasaGUI/project1.lrs
new file mode 100644
index 0000000..1f0bbe4
--- /dev/null
+++ b/branches/script-component/Projects/SAMufasaGUI/project1.lrs
@@ -0,0 +1,6495 @@
+LazarusResources.Add('MAINICON','ICO',[
+ #0#0#1#0#1#0#232#175#0#0#1#0' '#0'h'#144#2#0#22#0#0#0'('#0#0#0#232#0#0#0'^'#1
+ +#0#0#1#0' '#0#0#0#0#0'`z'#2#0'd'#0#0#0'd'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'&Du'#0'%'#148#255#10'''u'
+ +#255#5#23'_'#255#10#26'`'#255#9#21'['#255#10#20'['#255#10#20']'#255#9#19'`'
+ +#255#9#20'b'#255#12#21'a'#255#12#22'`'#255#12#20'^'#255#13#21'^'#255#12#21'_'
+ +#255#12#20'^'#255#9#20'^'#255#10#21'_'#255#11#20'b'#255#11#20'a'#255#10#20'c'
+ +#255#10#20'b'#255#9#19'b'#255#10#20'b'#255#8#18'a'#255#11#21'c'#255#10#20'b'
+ +#255#11#21'b'#255#10#21'b'#255#7#19'_'#255#9#20'a'#255#7#21'a'#255#9#22'b'
+ +#255#8#21'a'#255#8#21'a'#255#8#21'a'#255#10#22']'#255#9#20'^'#255#7#17'\'#255
+ +#7#18'`'#255#10#22'f'#255#10#22'g'#255#10#24'l'#255#9#22'm'#255#8#23'm'#255#9
+ +#24'n'#255#8#22'm'#255#7#21'm'#255#8#22'n'#255#8#22'n'#255#8#22'n'#255#8#22
+ +'o'#255#9#23'o'#255#8#22'n'#255#8#22'n'#255#9#22'm'#255#9#22'l'#255#10#25'n'
+ +#255#9#24'n'#255#7#22'l'#255#10#23'm'#255#9#22'l'#255#11#25'n'#255#11#23'o'
+ +#255#9#23'o'#255#8#22'n'#255#8#22'n'#255#7#21'n'#255#9#21'q'#255#10#22'r'#255
+ +#9#20'n'#255#11#22'p'#255#10#21'o'#255#11#22'o'#255#11#23'n'#255#10#23'n'#255
+ +#9#23'j'#255#11#24'i'#255#10#22'e'#255#6#17'b'#255#10#21'h'#255#10#23'k'#255
+ +#8#21'k'#255#10#21'i'#255#10#22'i'#255#9#23'f'#255#12#23'e'#255#13#21']'#255
+ +#12#21'U'#255#13#17'L'#255#13#17'F'#255#14#19'D'#255#12#18'C'#255#10#17'C'
+ +#255#11#18'D'#255#13#18'D'#255#12#16'E'#255#13#17'F'#255#12#16'D'#255#12#16
+ +'D'#255#14#17'D'#255#12#16'C'#255#13#17'D'#255#13#18'C'#255#12#16'B'#255#12
+ +#17'B'#255#12#16'C'#255#13#16'C'#255#12#15'B'#255#11#15'B'#255#11#15'B'#255
+ +#11#15'B'#255#11#16'B'#255#11#15'A'#255#12#16'B'#255#11#15'A'#255#10#15'A'
+ +#255#11#16'A'#255#12#17'B'#255#12#15'A'#255#14#14'A'#255#14#15'B'#255#12#14
+ +'A'#255#12#15'B'#255#11#15'B'#255#11#15'B'#255#11#15'B'#255#11#15'C'#255#11
+ +#15'C'#255#12#16'D'#255#11#15'D'#255#12#16'E'#255#12#16'D'#255#12#16'E'#255
+ +#12#16'E'#255#13#17'D'#255#14#18'<'#255#18#21'4'#255#11#14'#'#255#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'y'#149#188#8#24'7m'#243#8#29'^'
+ +#255#8#31'n'#255#7#29'r'#255#9#26'q'#255#8#27'q'#255#6#24'p'#255#6#25'p'#255
+ +#6#25'q'#255#5#24'p'#255#7#25'r'#255#6#24'p'#255#9#26'q'#255#8#26'p'#255#10
+ +#25'q'#255#8#25'q'#255#7#24'p'#255#6#24'p'#255#7#26'r'#255#5#23'p'#255#5#23
+ ,'r'#255#6#25't'#255#5#24's'#255#6#23'r'#255#5#24'q'#255#8#25'p'#255#8#23'o'
+ +#255#7#23'n'#255#6#23'n'#255#8#24'p'#255#5#25'n'#255#5#27'k'#255#6#26'h'#255
+ +#4')~'#255#14'b'#190#255#22'x'#220#255#29'x'#219#255#23'|'#219#255#20'x'#218
+ +#255#19'w'#217#255#21'y'#218#255#21'|'#219#255#20'{'#217#255#20'y'#218#255#17
+ +'u'#215#255#23'y'#220#255#22'{'#222#255#22'{'#221#255#23'|'#224#255#21'z'#224
+ +#255#22'{'#226#255#23'{'#227#255#21'z'#225#255#22'x'#224#255#20'y'#225#255#22
+ +'u'#223#255#29'|'#229#255#21'z'#226#255#21'y'#226#255#27'z'#228#255#23't'#222
+ +#255#21'y'#224#255#26'w'#217#255#23'~'#223#255#23'~'#225#255'"'#128#230#255
+ +#24'o'#213#255#24'n'#208#255#27'i'#197#255#16'G'#159#255#4'''y'#255#1#22'd'
+ +#255#6#22']'#255#12#24'^'#255#9#21'^'#255#7#19'`'#255#7#21'`'#255#8#21'^'#255
+ +#9#22']'#255#8#22']'#255#9#20'^'#255#10#21'_'#255#10#21'_'#255#10#21'_'#255
+ +#12#22'c'#255#10#20'a'#255#10#20'a'#255#10#20'a'#255#9#19'`'#255#9#19'a'#255
+ +#8#19'^'#255#10#21'`'#255#10#21'`'#255#10#20'`'#255#8#21'a'#255#8#21'a'#255#8
+ +#21'a'#255#7#20'`'#255#10#23'c'#255#8#21'a'#255#8#21'a'#255#9#22'b'#255#7#20
+ +'`'#255#9#22'a'#255#9#20'^'#255#8#20'\'#255#8#19'^'#255#8#20'a'#255#11#23'g'
+ +#255#10#24'j'#255#8#23'l'#255#8#23'm'#255#7#22'm'#255#7#21'm'#255#7#21'm'#255
+ +#9#23'o'#255#8#22'n'#255#8#22'o'#255#8#23'm'#255#7#22'l'#255#6#20'l'#255#9#21
+ +'n'#255#10#21'n'#255#7#21'm'#255#8#22'o'#255#7#21'n'#255#7#22'm'#255#7#21'm'
+ +#255#8#22'n'#255#8#22'n'#255#8#23'o'#255#7#23'n'#255#7#23'n'#255#6#21'm'#255
+ +#9#21'n'#255#9#22'o'#255#7#20'm'#255#10#23'p'#255#7#21'm'#255#7#21'm'#255#8
+ +#22'n'#255#10#23'o'#255#7#23'o'#255#7#23'l'#255#12#24'l'#255#8#19'f'#255#7#19
+ +'g'#255#10#23'm'#255#7#21'k'#255#9#24'k'#255#7#24'k'#255#6#24'j'#255#12#26'i'
+ +#255#11#21'a'#255#12#21'Y'#255#11#17'N'#255#12#17'H'#255#13#19'D'#255#10#17
+ +'B'#255#11#18'C'#255#13#20'F'#255#13#18'E'#255#12#15'E'#255#13#16'G'#255#12
+ +#14'F'#255#13#16'G'#255#13#16'D'#255#11#15'B'#255#11#16'A'#255#12#17'B'#255
+ +#12#18'A'#255#12#17'B'#255#13#17'C'#255#13#16'C'#255#12#16'D'#255#12#16'D'
+ +#255#12#16'C'#255#12#16'C'#255#12#16'C'#255#12#15'B'#255#12#15'B'#255#12#16
+ +'C'#255#11#15'B'#255#11#15'A'#255#13#16'B'#255#11#15'A'#255#11#14'@'#255#13
+ +#15'@'#255#11#15'@'#255#11#16'A'#255#10#15'@'#255#10#15'A'#255#11#16'B'#255
+ +#12#16'B'#255#11#15'B'#255#10#14'A'#255#11#15'B'#255#13#17'C'#255#12#15'C'
+ +#255#12#17'F'#255#10#14'C'#255#13#18'E'#255#14#18'<'#255#16#19'3'#255#9#12'!'
+ +#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'Km'#145#0'>^'#139'E'#6
+ +'"]'#255#16'&m'#255#6#30'm'#255#7#28't'#255#7#26'q'#255#7#26's'#255#6#25'p'
+ +#255#6#25'p'#255#6#26'p'#255#5#25'o'#255#7#25'p'#255#8#26'p'#255#9#26'q'#255
+ +#9#26'p'#255#9#27'q'#255#8#25'p'#255#8#26'q'#255#7#25'p'#255#8#26'p'#255#6#24
+ +'p'#255#6#25'r'#255#5#25'r'#255#5#25'r'#255#6#25's'#255#6#23'p'#255#7#24'p'
+ +#255#7#22'n'#255#7#22'o'#255#7#23'p'#255#8#23'q'#255#4#24'o'#255#8#27'j'#255
+ +#4#24'l'#255#5'I'#168#255#22'r'#211#255#22'u'#214#255#18'|'#220#255#21'{'#224
+ +#255#23'|'#222#255#21'z'#220#255#22'|'#221#255#22'|'#220#255#17'w'#214#255#22
+ +'|'#221#255#19'x'#218#255#22'|'#221#255#21'y'#219#255#21'y'#219#255#21'z'#220
+ +#255#21'z'#222#255#21'{'#223#255#24'}'#226#255#23'|'#227#255#22'z'#227#255#18
+ +'t'#225#255#27'y'#230#255#25'w'#228#255#21'w'#227#255#22'y'#227#255#22'w'#225
+ +#255#22'x'#225#255#19'{'#227#255#19'x'#225#255#21'x'#223#255#24'{'#224#255#23
+ +'{'#223#255#22'|'#224#255#17't'#218#255#13'm'#211#255'$'#127#229#255#31'l'
+ +#203#255#12'>'#150#255#2#31'k'#255#8#26'['#255#10#24'a'#255#6#23'd'#255#6#19
+ +']'#255#5#19'_'#255#8#22'`'#255#5#20'\'#255#6#19'^'#255#10#20'_'#255#11#19'^'
+ +#255#12#20'_'#255#11#22'`'#255#10#21'`'#255#7#19'^'#255#7#19'^'#255#8#19']'
+ +#255#9#20'^'#255#9#20'^'#255#10#21'_'#255#9#20'^'#255#9#20']'#255#8#20'_'#255
+ +#9#21'`'#255#7#20'_'#255#7#20'`'#255#9#22'b'#255#7#20'`'#255#7#20'`'#255#7#20
+ +'`'#255#9#20'b'#255#10#21'a'#255#10#21'_'#255#10#22'_'#255#7#19'\'#255#5#19
+ +'^'#255#8#23'c'#255#10#25'i'#255#8#24'j'#255#9#25'm'#255#8#22'n'#255#8#22'n'
+ +#255#8#22'n'#255#8#22'n'#255#8#22'o'#255#6#22'n'#255#9#23'n'#255#8#22'm'#255
+ +#7#22'n'#255#8#21'o'#255#9#22'q'#255#7#22'p'#255#9#22'q'#255#8#21'q'#255#8#22
+ +'q'#255#7#23'r'#255#7#22'q'#255#6#23'p'#255#6#23'o'#255#6#22'n'#255#7#24'p'
+ +#255#6#23'o'#255#7#21'o'#255#8#22'o'#255#8#22'p'#255#8#23'p'#255#8#22'o'#255
+ +#9#23'p'#255#8#23'o'#255#8#23'o'#255#6#23'p'#255#8#23'o'#255#13#25'n'#255#9
+ +#22'h'#255#7#19'g'#255#8#23'k'#255#8#22'l'#255#8#23'm'#255#5#24'm'#255#4#22
+ +'j'#255#10#23'j'#255#11#22'e'#255#11#22'\'#255#11#19'S'#255#11#18'K'#255#10
+ +#19'F'#255#11#19'F'#255#11#17'E'#255#12#18'F'#255#12#17'G'#255#12#16'F'#255
+ +#14#18'H'#255#12#15'E'#255#12#15'E'#255#12#16'D'#255#10#16'B'#255#11#17'C'
+ +#255#12#19'C'#255#11#18'A'#255#11#17'B'#255#12#17'B'#255#12#17'B'#255#11#16
+ +'C'#255#10#15'C'#255#11#15'C'#255#11#15'C'#255#12#16'D'#255#12#16'D'#255#11
+ ,#14'A'#255#12#15'B'#255#12#16'C'#255#12#16'C'#255#12#15'B'#255#13#16'C'#255
+ +#13#16'B'#255#13#16'B'#255#12#16'B'#255#11#15'A'#255#12#16'B'#255#11#15'A'
+ +#255#11#16'B'#255#11#16'B'#255#11#15'A'#255#12#16'B'#255#11#15'B'#255#12#16
+ +'C'#255#11#15'C'#255#10#15'D'#255#9#13'D'#255#11#16'D'#255#11#17';'#255#17#21
+ +'4'#255#11#14'"'#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +'1S|'#187#5' \'#255#8' j'#255#6#28'n'#255#7#26'r'#255#7#26'q'#255#8#26's'#255
+ +#6#25'p'#255#6#25'p'#255#6#26'p'#255#6#26'o'#255#8#25'p'#255#8#25'p'#255#9#26
+ +'p'#255#8#25'o'#255#8#25'o'#255#9#26'p'#255#9#26'p'#255#9#25'q'#255#7#24'q'
+ +#255#6#24'q'#255#6#26'r'#255#6#27's'#255#6#26'r'#255#6#23'p'#255#6#24'q'#255
+ +#7#23'p'#255#8#24'q'#255#8#24'q'#255#8#24'q'#255#6#23'p'#255#8#26'q'#255#4#28
+ +'j'#255#4'#}'#255#14'`'#195#255#18'n'#208#255#21'u'#215#255#22'{'#225#255#22
+ +'|'#222#255#21'z'#221#255#19'x'#218#255#19'x'#218#255#20'y'#219#255#21'z'#219
+ +#255#23'|'#222#255#21'z'#220#255#22'{'#222#255#18'w'#218#255#21'z'#221#255#21
+ +'|'#220#255#24#127#223#255#19'|'#221#255#18'{'#222#255#18'z'#223#255#21'{'
+ +#227#255#23'y'#227#255#24'{'#229#255#21'y'#226#255#24'|'#229#255#23'}'#227
+ +#255#21'z'#225#255#21'z'#225#255#21'z'#225#255#23'{'#226#255#22'z'#225#255#20
+ +'y'#223#255#18'y'#222#255#19'z'#223#255#24'|'#227#255#23'{'#225#255#24'{'#225
+ +#255'!}'#230#255'"'#127#230#255#22'\'#185#255#9'.}'#255#9'%m'#255#9'''p'#255
+ +#5#29'g'#255#7#21'Y'#255#9#21'a'#255#7#21'_'#255#5#20']'#255#8#21'_'#255#7#21
+ +'^'#255#8#21'_'#255#8#22'`'#255#8#22'`'#255#8#22']'#255#8#22'_'#255#9#19'^'
+ +#255#8#19']'#255#9#19'_'#255#9#19'_'#255#10#20'`'#255#11#22'a'#255#10#20'b'
+ +#255#11#21'b'#255#9#22'b'#255#8#21'a'#255#7#20'a'#255#8#21'b'#255#9#22'c'#255
+ +#7#20'a'#255#8#22'b'#255#8#22'a'#255#7#21'_'#255#9#21'_'#255#6#19']'#255#8#21
+ +'_'#255#4#17'\'#255#8#22'a'#255#8#23'f'#255#9#24'k'#255#9#23'o'#255#10#23'o'
+ +#255#9#23'p'#255#9#23'o'#255#9#23'o'#255#9#23'p'#255#9#21'm'#255#8#21'm'#255
+ +#9#23'o'#255#8#24'q'#255#8#24'q'#255#6#22'o'#255#8#22'p'#255#7#20'p'#255#7#22
+ +'q'#255#7#23'q'#255#6#23'o'#255#7#23'p'#255#7#23'p'#255#7#23'p'#255#6#23'p'
+ +#255#6#22'o'#255#5#21'n'#255#6#22'p'#255#7#24'o'#255#7#24'o'#255#7#24'o'#255
+ +#7#25'p'#255#7#23'o'#255#6#23'p'#255#6#23'o'#255#6#23'n'#255#9#25'l'#255#9#24
+ +'k'#255#6#19'e'#255#8#23'j'#255#7#22'l'#255#6#23'n'#255#7#23'm'#255#7#23'j'
+ +#255#10#24'j'#255#13#25'h'#255#12#22'_'#255#13#23'W'#255#11#19'O'#255#10#20
+ +'I'#255#12#19'E'#255#10#17'C'#255#10#18'C'#255#11#17'C'#255#12#17'C'#255#13
+ +#17'D'#255#13#17'E'#255#13#17'E'#255#12#18'D'#255#11#18'C'#255#12#19'D'#255
+ +#12#19'D'#255#10#17'B'#255#9#16'A'#255#12#18'B'#255#12#18'A'#255#10#17'A'#255
+ +#9#16'A'#255#11#16'C'#255#12#16'D'#255#12#16'E'#255#13#17'F'#255#11#15'C'#255
+ +#13#17'D'#255#12#16'C'#255#11#15'B'#255#11#15'B'#255#12#16'C'#255#12#16'C'
+ +#255#13#17'D'#255#13#17'D'#255#11#15'B'#255#12#16'C'#255#11#15'B'#255#12#16
+ +'C'#255#11#15'B'#255#11#15'B'#255#12#16'C'#255#12#16'C'#255#12#16'C'#255#12
+ +#16'C'#255#13#17'E'#255#10#16'E'#255#13#17'E'#255#13#19'?'#255#16#20'4'#255#8
+ +#10' '#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#26''#255#17
+ +#19'3'#255#9#9#31#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'Ts'#176#0'&E'
+ +#134'7'#9'&j'#255#8' o'#255#9#30'u'#255#9#27'v'#255#9#27'u'#255#8#26'v'#255#6
+ +#24'v'#255#7#25'u'#255#8#25'u'#255#9#25'v'#255#7#23't'#255#7#24'u'#255#9#25
+ +'v'#255#10#25'v'#255#11#25'w'#255#10#25'u'#255#9#24'u'#255#8#23't'#255#9#25
+ +'v'#255#8#24't'#255#9#24'u'#255#7#22's'#255#10#23's'#255#7#23'q'#255#9#23's'
+ +#255#9#22'r'#255#10#22'r'#255#8#23's'#255#7#22'r'#255#5#24'r'#255#5#23'q'#255
+ +#7#26'n'#255#8'$'#128#255#13'f'#199#255#26'j'#215#255#25't'#218#255#28'z'#220
+ +#255#22'w'#219#255#28'z'#221#255#25'{'#226#255#25'z'#226#255#29'}'#227#255#30
+ +#127#229#255#26'{'#224#255#27'|'#225#255#22'x'#221#255#26'|'#225#255#20'y'
+ +#223#255#24'|'#227#255#24'{'#230#255#24'{'#231#255#25'}'#231#255#25'{'#232
+ ,#255#24'z'#231#255#23'y'#230#255#24'z'#228#255#26'|'#230#255#24'z'#229#255#26
+ +'|'#231#255#25'z'#230#255#26'|'#231#255#21'v'#226#255#22'x'#226#255#25'|'#233
+ +#255#24'{'#231#255#22'x'#227#255#23'x'#228#255#24'w'#225#255#25'x'#227#255#24
+ +'u'#223#255#27'z'#228#255#21'x'#227#255#21'|'#228#255#25'y'#226#255#27'v'#228
+ +#255#31'|'#238#255#28'r'#216#255#11'O'#167#255#20'Y'#184#255')^'#180#255#0'"'
+ +'v'#255#2#21'd'#255#10#19'`'#255#7#21'`'#255#8#21'`'#255#9#20'a'#255#10#20'_'
+ +#255#15#22'b'#255#13#21'a'#255#10#20'a'#255#10#20'b'#255#10#20'a'#255#10#20
+ +'a'#255#12#21'c'#255#12#21'b'#255#12#20'a'#255#13#21'b'#255#12#19'`'#255#12
+ +#19'`'#255#13#20'b'#255#12#20'c'#255#12#22'd'#255#11#21'c'#255#12#21'e'#255
+ +#11#20'd'#255#10#20'd'#255#10#19'f'#255#10#19'e'#255#11#21'e'#255#10#20'd'
+ +#255#11#21'c'#255#11#20'`'#255#8#18'_'#255#7#18'`'#255#9#21'g'#255#10#21'k'
+ +#255#9#20'n'#255#7#21'p'#255#9#23'p'#255#8#21'n'#255#8#21'p'#255#8#22'p'#255
+ +#8#22'q'#255#9#24't'#255#8#23's'#255#8#23's'#255#8#23'q'#255#8#22'r'#255#8#22
+ +'r'#255#7#21'q'#255#8#22'r'#255#8#21'r'#255#8#22'r'#255#9#23's'#255#9#24's'
+ +#255#11#22's'#255#11#21's'#255#11#22'r'#255#10#21'p'#255#11#21'p'#255#10#21
+ +'p'#255#11#22'q'#255#10#20'q'#255#11#22'q'#255#10#21'p'#255#11#21'o'#255#12
+ +#23'o'#255#9#21'k'#255#8#20'j'#255#10#22'o'#255#10#21'p'#255#9#21'n'#255#10
+ +#21'p'#255#12#21'n'#255#12#22'n'#255#13#23'm'#255#12#22'e'#255#13#21'\'#255
+ +#12#21'T'#255#11#19'M'#255#12#18'J'#255#12#17'G'#255#13#17'G'#255#13#17'G'
+ +#255#13#17'F'#255#13#17'F'#255#14#16'F'#255#11#16'C'#255#13#18'F'#255#11#18
+ +'E'#255#11#17'F'#255#10#17'E'#255#10#16'E'#255#11#16'E'#255#12#16'E'#255#12
+ +#17'E'#255#11#17'D'#255#12#16'D'#255#12#16'E'#255#13#17'F'#255#12#16'E'#255
+ +#11#15'D'#255#13#17'F'#255#12#15'C'#255#12#15'B'#255#12#15'B'#255#13#16'D'
+ +#255#13#15'D'#255#13#15'D'#255#13#15'D'#255#11#14'B'#255#12#14'C'#255#12#14
+ +'D'#255#12#14'D'#255#12#14'D'#255#11#14'D'#255#12#15'D'#255#13#16'E'#255#12
+ +#15'E'#255#12#16'D'#255#11#14'C'#255#13#15'E'#255#11#14'B'#255#13#16';'#255
+ +#18#20'3'#255#13#12'!'#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'5'
+ +'T'#148#209#5'"i'#255#8'!q'#255#8#30't'#255#8#27'v'#255#7#26'u'#255#7#25'u'
+ +#255#8#26'v'#255#9#27'v'#255#7#25't'#255#7#24'u'#255#8#25'v'#255#9#26'w'#255
+ +#8#25'v'#255#8#24'u'#255#9#25'v'#255#9#24'u'#255#10#25'v'#255#9#24'u'#255#9
+ +#24'u'#255#8#23's'#255#10#25'u'#255#8#23's'#255#9#24't'#255#7#25'q'#255#9#23
+ +'t'#255#8#23's'#255#8#23's'#255#7#24's'#255#7#23'q'#255#6#24'q'#255#6#25'q'
+ +#255#5#28'm'#255#7'4'#146#255#17's'#214#255#24'r'#215#255#24'w'#220#255#24'|'
+ +#224#255#22'|'#223#255#26'~'#224#255#24'y'#225#255#24'y'#225#255#27'{'#226
+ +#255#30'}'#228#255#27'z'#225#255#28'|'#228#255#25'|'#227#255#28'~'#230#255#23
+ +'|'#226#255#23'|'#227#255#23'|'#230#255#25'}'#233#255#25'|'#232#255#22'x'#230
+ +#255#27'|'#234#255#25'z'#232#255#26'z'#231#255#26'|'#232#255#22'x'#229#255#25
+ +'{'#232#255#22'x'#228#255#22'y'#229#255#22'z'#228#255#23'{'#227#255#23#127
+ +#228#255#22'~'#228#255#24'|'#229#255#23'z'#229#255#25'y'#229#255#27'{'#232
+ +#255#25'y'#230#255#25'z'#230#255#19'v'#224#255#24'y'#228#255#26'y'#230#255#25
+ +'y'#231#255#22'y'#230#255#27'|'#232#255#30'r'#218#255#3'P'#177#255'%y'#219
+ +#255#20'e'#197#255#10'G'#159#255#6'-~'#255#7#26'g'#255#6#24'`'#255#11#21'a'
+ +#255#17#21'b'#255#13#21'_'#255#13#21'_'#255#9#19'a'#255#10#20'a'#255#9#19'`'
+ +#255#10#20'a'#255#11#20'a'#255#12#19'`'#255#10#19'`'#255#13#20'b'#255#12#19
+ +'a'#255#13#21'd'#255#12#20'c'#255#9#19'a'#255#12#22'd'#255#10#20'b'#255#10#20
+ +'b'#255#10#21'b'#255#9#19'b'#255#9#19'b'#255#9#19'b'#255#11#20'c'#255#11#21
+ +'c'#255#10#20'b'#255#10#20'b'#255#9#19'a'#255#8#17'_'#255#6#18'`'#255#10#21
+ +'f'#255#9#22'm'#255#8#22'o'#255#9#24'o'#255#7#22'o'#255#9#23'p'#255#7#20'p'
+ +#255#10#23's'#255#8#23's'#255#7#22'r'#255#7#22'r'#255#7#22'q'#255#8#23'r'#255
+ +#7#22'r'#255#7#22'r'#255#8#23's'#255#7#22'r'#255#8#23't'#255#7#22's'#255#8#23
+ +'t'#255#8#21's'#255#9#22'r'#255#8#22'r'#255#9#22'r'#255#10#23's'#255#9#22'r'
+ +#255#9#22'r'#255#10#22't'#255#11#22't'#255#11#22's'#255#11#22'p'#255#13#22'o'
+ +#255#13#24'o'#255#7#20'k'#255#10#23'n'#255#8#21'n'#255#9#22'o'#255#10#21'o'
+ +#255#11#20'n'#255#12#22'n'#255#11#21'm'#255#10#23'h'#255#11#21']'#255#13#22
+ +'X'#255#10#20'O'#255#10#17'L'#255#14#16'H'#255#13#16'E'#255#14#17'F'#255#12
+ +#16'E'#255#11#15'D'#255#13#16'D'#255#10#13'B'#255#13#17'F'#255#12#16'E'#255
+ +#12#18'G'#255#10#16'E'#255#12#18'G'#255#12#18'G'#255#13#17'F'#255#13#17'F'
+ +#255#13#17'F'#255#11#15'D'#255#11#15'D'#255#11#15'D'#255#12#16'E'#255#11#15
+ +'D'#255#13#17'F'#255#12#16'D'#255#13#16'C'#255#12#16'D'#255#12#15'E'#255#12
+ +#15'E'#255#12#15'D'#255#12#15'E'#255#11#14'D'#255#11#14'C'#255#12#14'D'#255
+ +#12#14'D'#255#13#15'E'#255#12#15'D'#255#11#15'D'#255#12#16'E'#255#11#15'D'
+ +#255#12#16'D'#255#11#14'D'#255#11#14'D'#255#11#14'B'#255#16#16'<'#255#17#19
+ ,'2'#255#8#10#31#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'^'#127#188'4'#26
+ +'9|'#255#11'''q'#255#5#31'r'#255#5#27's'#255#5#28's'#255#7#27's'#255#7#25'r'
+ +#255#8#26'r'#255#8#26'u'#255#7#25't'#255#7#24't'#255#7#24'u'#255#7#24'u'#255
+ +#6#23't'#255#6#23't'#255#7#25't'#255#8#24'u'#255#8#24't'#255#7#24't'#255#8#25
+ +'t'#255#7#24's'#255#9#25'u'#255#8#24's'#255#8#25't'#255#6#25't'#255#7#25't'
+ +#255#6#25't'#255#6#25's'#255#6#24's'#255#6#24'q'#255#6#27'q'#255#6#26'q'#255
+ +#0#28'r'#255#17'U'#180#255#21'u'#219#255#22't'#219#255#23'z'#220#255#22'|'
+ +#223#255#22'z'#224#255#22'|'#224#255#27'|'#231#255#25'z'#229#255#23'y'#226
+ +#255#25'z'#226#255#25'z'#226#255#24'z'#226#255#23'y'#228#255#25'|'#231#255#21
+ +'|'#227#255#21'|'#228#255#21'{'#229#255#24'}'#233#255#21'z'#230#255#22'x'#230
+ +#255#24'z'#232#255#24'z'#230#255#24'z'#232#255#23'x'#230#255#22'x'#230#255#26
+ +'{'#233#255#24'{'#231#255#25'}'#231#255#23'|'#229#255#23'|'#227#255#23#127
+ +#228#255#23#127#228#255#21'}'#226#255#24'}'#228#255#22'z'#228#255#24'{'#229
+ +#255#26'|'#232#255#24'{'#231#255#25'x'#228#255#25'z'#229#255#23'z'#229#255#22
+ +'z'#231#255#19'y'#232#255#18'w'#231#255#26'{'#233#255#16'o'#217#255#18'p'#217
+ +#255#28'w'#225#255#14'g'#206#255#26'_'#189#255#6'5'#133#255#0' g'#255#7#27'`'
+ +#255#5#21'^'#255#9#20'^'#255#9#20'^'#255#10#20'a'#255#9#19'`'#255#8#18'_'#255
+ +#12#22'c'#255#12#22'c'#255#11#21'b'#255#11#21'b'#255#11#21'c'#255#9#20'a'#255
+ +#9#19'a'#255#10#20'b'#255#9#19'a'#255#9#20'b'#255#8#19'a'#255#10#20'a'#255#10
+ +#20'b'#255#9#19'a'#255#9#19'a'#255#10#20'a'#255#11#21'c'#255#10#20'b'#255#10
+ +#20'a'#255#8#21'a'#255#10#20'b'#255#9#19'`'#255#7#17'^'#255#5#17'_'#255#9#22
+ +'f'#255#7#21'i'#255#8#23'n'#255#8#21'n'#255#9#24'p'#255#6#21'n'#255#9#24's'
+ +#255#7#22'r'#255#6#21'q'#255#6#21'q'#255#7#22'r'#255#7#22'r'#255#7#22'r'#255
+ +#7#22'r'#255#6#21'q'#255#7#22'r'#255#8#23't'#255#8#23't'#255#8#23't'#255#7#21
+ +'r'#255#8#22'r'#255#9#23's'#255#9#23'r'#255#9#24'r'#255#7#21'q'#255#8#22'r'
+ +#255#9#22's'#255#8#21's'#255#8#22's'#255#9#21'o'#255#10#23'n'#255#11#24'n'
+ +#255#9#22'l'#255#9#22'l'#255#8#22'l'#255#6#23'n'#255#9#23'p'#255#11#23'q'#255
+ +#12#23'q'#255#9#21'n'#255#8#23'k'#255#9#21'b'#255#11#21'['#255#11#21'S'#255
+ +#10#18'N'#255#13#16'H'#255#13#17'F'#255#13#17'F'#255#13#17'F'#255#13#17'F'
+ +#255#14#17'E'#255#13#16'B'#255#15#19'E'#255#13#17'E'#255#14#18'F'#255#11#17
+ +'F'#255#11#17'F'#255#13#18'G'#255#13#17'F'#255#13#17'F'#255#12#16'E'#255#12
+ +#16'E'#255#12#16'E'#255#11#15'D'#255#12#16'E'#255#11#15'D'#255#13#17'F'#255
+ +#10#15'D'#255#11#16'E'#255#10#15'D'#255#11#16'E'#255#12#17'F'#255#12#17'F'
+ +#255#12#17'F'#255#13#18'G'#255#12#15'E'#255#13#14'E'#255#12#15'D'#255#13#17
+ +'F'#255#12#16'E'#255#12#16'E'#255#13#17'F'#255#13#17'F'#255#12#17'F'#255#11
+ +#15'E'#255#13#15'F'#255#11#15'C'#255#16#18'='#255#19#21'4'#255#12#13'#'#255#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'-H'#134'R'#20'-q'#255#11'"n'#255#8#31
+ +'r'#255#7#28't'#255#5#26'u'#255#8#28't'#255#9#27't'#255#7#25'r'#255#7#27's'
+ +#255#6#25't'#255#7#25't'#255#7#24'u'#255#7#24'u'#255#8#25'v'#255#7#25'u'#255
+ +#8#26'u'#255#7#25't'#255#6#24's'#255#7#25't'#255#8#26'u'#255#5#24's'#255#7#26
+ +'u'#255#5#24's'#255#6#25't'#255#6#24's'#255#6#24't'#255#7#23's'#255#7#24's'
+ +#255#6#24's'#255#6#24's'#255#6#26'q'#255#6#25'q'#255#3'!y'#255#11'a'#191#255
+ +#24'o'#218#255#23'z'#221#255#25'z'#220#255#24'z'#223#255#30'y'#226#255#25'{'
+ +#226#255#27'}'#232#255#25'{'#230#255#25'|'#228#255#24'{'#228#255#23'z'#226
+ +#255#25'|'#228#255#24'}'#229#255#24'|'#229#255#22'{'#229#255#23'|'#231#255#23
+ +'{'#231#255#23'|'#232#255#22'z'#231#255#24'z'#232#255#23'z'#229#255#22'y'#229
+ +#255#27'}'#234#255#22'y'#230#255#22'z'#231#255#23'{'#232#255#22'y'#230#255#26
+ +'}'#233#255#25'|'#231#255#25'}'#231#255#23'~'#228#255#23'~'#228#255#22'{'#228
+ +#255#25'}'#232#255#23'{'#230#255#23'z'#230#255#24'{'#231#255#24'}'#233#255#26
+ +'|'#233#255#25'}'#233#255#24'|'#230#255#21'|'#228#255#22'}'#231#255#21'z'#230
+ +#255#22'z'#231#255#22'{'#232#255#21'{'#231#255#27'~'#235#255#21't'#219#255#27
+ +'w'#215#255#26'f'#190#255#12':'#141#255#9#30'm'#255#9#28'd'#255#9#22'`'#255#7
+ +#21'^'#255#11#21'b'#255#11#21'b'#255#8#18'_'#255#11#21'b'#255#10#21'b'#255#8
+ +#21'a'#255#9#19'`'#255#10#20'b'#255#11#21'c'#255#9#20'd'#255#11#21'e'#255#10
+ +#19'd'#255#9#21'c'#255#8#20'b'#255#12#22'd'#255#12#22'd'#255#12#22'd'#255#12
+ +#22'd'#255#11#20'c'#255#12#22'c'#255#10#20'b'#255#11#21'c'#255#9#22'b'#255#10
+ +#21'a'#255#12#21'c'#255#12#20'a'#255#8#17']'#255#6#19'^'#255#7#21'c'#255#9#23
+ +'m'#255#7#24'n'#255#7#24'o'#255#6#22'o'#255#9#24'r'#255#7#23'r'#255#8#23's'
+ +#255#8#23's'#255#8#23's'#255#8#23's'#255#7#22'r'#255#7#22'r'#255#8#23's'#255
+ +#7#22'r'#255#9#24'u'#255#8#23't'#255#8#23't'#255#8#23's'#255#8#22's'#255#7#22
+ ,'r'#255#8#23'q'#255#7#23'p'#255#6#21'q'#255#7#22'r'#255#7#22'r'#255#5#22'r'
+ +#255#6#23's'#255#8#23'p'#255#8#23'o'#255#9#22'm'#255#9#22'm'#255#6#19'j'#255
+ +#7#20'm'#255#8#24'p'#255#6#22'o'#255#6#20'm'#255#9#24'p'#255#8#22'o'#255#8#24
+ +'o'#255#10#24'g'#255#10#22'_'#255#10#19'W'#255#8#17'O'#255#10#16'G'#255#12#16
+ +'F'#255#12#16'C'#255#13#17'E'#255#13#16'E'#255#15#16'D'#255#11#14'@'#255#14
+ +#17'D'#255#12#15'B'#255#13#17'D'#255#11#16'D'#255#12#16'D'#255#11#16'D'#255
+ +#12#16'E'#255#14#18'G'#255#13#17'F'#255#11#15'D'#255#11#15'D'#255#12#16'E'
+ +#255#11#15'D'#255#11#15'D'#255#13#17'F'#255#11#16'E'#255#12#17'F'#255#11#16
+ +'E'#255#10#15'D'#255#11#16'E'#255#10#15'D'#255#11#17'E'#255#12#16'F'#255#11
+ +#16'E'#255#13#17'F'#255#12#16'E'#255#14#18'G'#255#12#16'E'#255#10#14'C'#255
+ +#12#16'E'#255#12#16'E'#255#11#16'F'#255#10#15'F'#255#12#16'G'#255#11#14'C'
+ +#255#14#18'>'#255#16#19'4'#255#9#9' '#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'Od'
+ +#143#143#12'$^'#255#1#24'_'#255#9' l'#255#8#29'r'#255#7#26't'#255#5#26'u'#255
+ +#8#27'u'#255#8#27't'#255#9#27'u'#255#8#27't'#255#8#26'u'#255#7#25't'#255#9#27
+ +'w'#255#8#26'v'#255#8#26'v'#255#7#25't'#255#7#25't'#255#7#26'u'#255#7#25't'
+ +#255#8#26'u'#255#7#25's'#255#7#25's'#255#7#26's'#255#6#24's'#255#9#25'u'#255
+ +#8#22's'#255#8#23't'#255#7#24't'#255#7#24's'#255#7#23's'#255#6#24'q'#255#7#26
+ +'r'#255#6#27'q'#255#3')'#131#255#22'q'#208#255#23'r'#222#255#25'z'#224#255#27
+ +'|'#220#255#27'{'#223#255#25'y'#224#255#23'x'#226#255#24'}'#228#255#23'z'#226
+ +#255#27#127#230#255#28#128#231#255#24'}'#227#255#23'|'#226#255#23'{'#227#255
+ +#27'~'#231#255#25'z'#230#255#25'{'#231#255#22'y'#229#255#22'z'#231#255#23'}'
+ +#233#255#23'z'#231#255#23'{'#231#255#24'|'#232#255#23'{'#231#255#23'{'#231
+ +#255#24'|'#232#255#25'}'#234#255#23'{'#232#255#23'z'#232#255#24'|'#232#255#24
+ +'|'#233#255#21'y'#229#255#26'}'#232#255#24'{'#231#255#28#127#235#255#24'|'
+ +#233#255#25'}'#233#255#21'z'#230#255#22'{'#232#255#23'y'#230#255#23'{'#232
+ +#255#23'}'#231#255#24'|'#229#255#23'{'#228#255#23'z'#228#255#22'z'#228#255#24
+ +'~'#233#255#19'x'#230#255#21'{'#234#255#21'}'#227#255#25'w'#218#255#23'm'#207
+ +#255#29'f'#195#255#4'4'#139#255#12#30'l'#255#5#22'a'#255#6#22'b'#255#8#19'a'
+ +#255#11#20'a'#255#13#20'`'#255#12#20'`'#255#10#20'b'#255#11#20'e'#255#8#19'b'
+ +#255#10#21'c'#255#10#21'c'#255#9#21'd'#255#10#21'e'#255#10#21'd'#255#9#20'b'
+ +#255#10#21'c'#255#8#20'`'#255#9#20'a'#255#9#20'b'#255#9#19'b'#255#11#20'd'
+ +#255#11#20'd'#255#10#20'c'#255#11#21'c'#255#9#21'b'#255#11#21'c'#255#11#20'b'
+ +#255#10#20'a'#255#9#20'^'#255#6#18'\'#255#4#17'_'#255#10#23'i'#255#7#24'n'
+ +#255#6#23'o'#255#6#23'p'#255#7#24'r'#255#8#23'r'#255#10#24't'#255#9#24'r'#255
+ +#8#24'r'#255#7#23'r'#255#7#23's'#255#6#21'q'#255#7#22'r'#255#5#20'p'#255#7#22
+ +'s'#255#8#23't'#255#8#24'u'#255#7#23's'#255#6#23's'#255#6#23'q'#255#7#24'p'
+ +#255#6#23'p'#255#6#22'p'#255#6#23'r'#255#6#23'r'#255#5#22'r'#255#8#24's'#255
+ +#7#22'r'#255#9#23'r'#255#9#23'q'#255#10#22'p'#255#7#19'o'#255#8#20'q'#255#8
+ +#23'r'#255#9#24's'#255#9#24's'#255#7#22'r'#255#7#22'o'#255#7#22'n'#255#11#25
+ +'j'#255#11#24'e'#255#10#21'['#255#9#20'R'#255#10#17'J'#255#13#17'F'#255#13#17
+ +'C'#255#12#16'C'#255#13#16'E'#255#14#16'D'#255#13#15'B'#255#14#17'D'#255#10
+ +#14'A'#255#12#16'D'#255#11#16'D'#255#12#17'D'#255#11#16'F'#255#12#17'F'#255
+ +#13#16'G'#255#12#16'E'#255#12#16'E'#255#13#17'F'#255#11#15'C'#255#11#15'D'
+ +#255#11#15'D'#255#11#16'E'#255#10#15'D'#255#12#16'F'#255#12#16'F'#255#11#16
+ +'F'#255#12#16'F'#255#11#14'D'#255#12#15'F'#255#13#15'F'#255#12#15'E'#255#13
+ +#16'E'#255#11#15'C'#255#12#15'C'#255#12#16'D'#255#12#16'D'#255#12#15'D'#255
+ +#11#16'E'#255#10#16'D'#255#10#14'D'#255#12#16'G'#255#10#14'B'#255#13#18'='
+ +#255#17#21'5'#255#11#15'$'#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#128#148#173#16';Q}'
+ +#255#0#19'L'#255#6#29'j'#255#9#29'o'#255#6#26'r'#255#8#25'v'#255#8#26'v'#255
+ +#9#27'w'#255#8#26'u'#255#7#24't'#255#8#25'u'#255#8#25'u'#255#8#25'u'#255#7#25
+ +'u'#255#7#24't'#255#6#24's'#255#7#25't'#255#7#25't'#255#8#25'v'#255#7#25'u'
+ +#255#7#25't'#255#8#26't'#255#8#26't'#255#7#25't'#255#8#24't'#255#10#25'u'#255
+ +#10#23't'#255#8#24't'#255#6#24's'#255#5#23'r'#255#8#23'r'#255#5#24'q'#255#6
+ +#25'q'#255#6#28't'#255#7'9'#153#255#25's'#218#255#21'u'#226#255#27'{'#227#255
+ +#22'z'#219#255#26'{'#222#255#20'{'#225#255#27#127#230#255#25'~'#229#255#24'}'
+ +#228#255#26#127#230#255#24'}'#227#255#24'{'#227#255#22'y'#225#255#24'z'#226
+ +#255#28'}'#232#255#25'{'#231#255#26'|'#232#255#24'{'#231#255#24'{'#232#255#26
+ +'|'#234#255#25'{'#232#255#24'{'#232#255#25'|'#232#255#22'y'#229#255#24'{'#231
+ +#255#25'|'#232#255#27'~'#234#255#27'~'#233#255#23'{'#229#255#22'{'#229#255#24
+ +'}'#231#255#23'z'#231#255#25'}'#234#255#23'y'#231#255#23'y'#233#255#21'w'#231
+ ,#255#26'{'#236#255#22'v'#231#255#25'z'#235#255#23'w'#233#255#26'y'#234#255#24
+ +'w'#231#255#25'z'#230#255#24'x'#229#255#25'{'#232#255#23'y'#230#255#25'{'#232
+ +#255#22'z'#230#255#23'y'#234#255#25'z'#234#255#27'|'#230#255#25'y'#222#255'#'
+ +#127#225#255#29'^'#186#255#9'/'#129#255#9#25'i'#255#9#22'e'#255#7#18'b'#255#9
+ +#20'b'#255#10#20'_'#255#11#21'_'#255#11#21'`'#255#11#23'a'#255#8#20'b'#255#10
+ +#23'e'#255#10#23'e'#255#11#22'd'#255#11#21'c'#255#11#21'c'#255#11#21'c'#255
+ +#10#20'b'#255#8#20'a'#255#9#21'a'#255#11#22'd'#255#10#21'c'#255#12#21'd'#255
+ +#10#20'c'#255#11#20'd'#255#11#20'd'#255#10#19'd'#255#12#21'd'#255#8#18'a'#255
+ +#10#19'a'#255#9#21'_'#255#8#20'_'#255#6#18']'#255#8#19'a'#255#8#22'j'#255#9
+ +#25'o'#255#5#22'o'#255#7#22'r'#255#8#20's'#255#9#21'r'#255#8#21'q'#255#8#23
+ +'r'#255#7#20'q'#255#8#21'r'#255#9#21'r'#255#11#22'u'#255#8#20'r'#255#11#22'u'
+ +#255#10#21't'#255#10#22't'#255#8#21'r'#255#9#23's'#255#6#21'p'#255#7#22'q'
+ +#255#7#22'o'#255#8#22'r'#255#8#21's'#255#8#22's'#255#7#22's'#255#8#23't'#255
+ +#6#21'q'#255#8#23's'#255#8#22'r'#255#9#22'r'#255#10#22'r'#255#8#20'q'#255#10
+ +#22's'#255#8#22'r'#255#8#22's'#255#6#20'q'#255#9#22'p'#255#9#23'm'#255#11#24
+ +'k'#255#11#24'g'#255#9#22'_'#255#10#19'U'#255#12#18'N'#255#14#18'H'#255#14#17
+ +'F'#255#14#18'F'#255#14#16'F'#255#13#15'F'#255#14#15'E'#255#14#15'F'#255#12
+ +#15'E'#255#13#17'G'#255#12#16'F'#255#13#16'H'#255#11#14'F'#255#11#14'H'#255
+ +#12#15'G'#255#12#15'E'#255#12#16'E'#255#12#16'E'#255#11#15'C'#255#13#17'F'
+ +#255#11#16'E'#255#10#16'E'#255#11#16'E'#255#11#16'F'#255#11#15'E'#255#11#15
+ +'E'#255#12#15'E'#255#11#14'D'#255#12#14'E'#255#13#15'F'#255#12#14'D'#255#12
+ +#14'D'#255#12#15'C'#255#10#13'@'#255#11#14'A'#255#11#15'B'#255#11#15'C'#255
+ +#11#15'D'#255#12#16'E'#255#11#15'D'#255#12#17'F'#255#10#15'A'#255#12#19'='
+ +#255#15#19'3'#255#7#9#31#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'Xm'#142#136#21'*['#255#4
+ +#23'S'#255#7#27'k'#255#10#27'p'#255#8#25'r'#255#8#25'v'#255#7#24'v'#255#8#25
+ +'w'#255#8#24'w'#255#11#24'y'#255#8#24'x'#255#8#24'x'#255#7#23'x'#255#8#24'x'
+ +#255#9#25'y'#255#6#22'w'#255#9#25'y'#255#8#24'y'#255#9#26'w'#255#7#24'v'#255
+ +#8#24'x'#255#8#24'w'#255#5#22't'#255#7#23'v'#255#7#23'u'#255#9#25'v'#255#5#23
+ +'s'#255#6#24's'#255#6#24's'#255#7#25't'#255#9#25'r'#255#6#24'q'#255#6#27's'
+ +#255#6#30't'#255#11'F'#175#255' z'#231#255#24's'#229#255#22'u'#225#255#23'|'
+ +#224#255#29'z'#226#255#22'y'#225#255#25'~'#226#255#24'}'#227#255#24'}'#227
+ +#255#27#127#229#255#26'~'#228#255#25'|'#228#255#28'}'#229#255#27'{'#229#255
+ +#30'~'#234#255#24'z'#230#255#25'{'#231#255#26'{'#234#255#26'|'#234#255#25'z'
+ +#232#255#24'z'#232#255#25'{'#233#255#25'{'#233#255#25'}'#230#255#26'~'#231
+ +#255#26'~'#232#255#23'{'#229#255#24'|'#231#255#25'}'#231#255#25'|'#231#255#26
+ +'~'#232#255#23'}'#233#255#24'}'#234#255#21'y'#232#255#22'y'#233#255#23'x'#233
+ +#255#24'y'#235#255#23'w'#233#255#26'y'#235#255#24'w'#231#255#27'y'#233#255#26
+ +'x'#232#255#27'x'#234#255#25'x'#234#255#26'y'#235#255#26'|'#236#255#27'}'#237
+ +#255#23'x'#226#255#22'x'#231#255#19'x'#233#255#21'{'#232#255#19'y'#230#255#27
+ +'}'#233#255'*x'#220#255#18'P'#170#255#5#30'n'#255#10#28'j'#255#8#19'`'#255#13
+ +#19'a'#255#12#18'b'#255#12#23'd'#255#8#20'`'#255#12#20'_'#255#10#19'a'#255#11
+ +#21'c'#255#11#21'c'#255#12#22'd'#255#11#21'c'#255#11#21'c'#255#11#21'c'#255
+ +#11#20'b'#255#8#19'c'#255#9#19'c'#255#12#20'e'#255#11#19'f'#255#12#19'g'#255
+ +#12#19'g'#255#13#22'f'#255#11#20'd'#255#8#19'e'#255#9#20'd'#255#8#19'b'#255
+ +#10#20'a'#255#10#20'b'#255#12#21'^'#255#9#18'\'#255#10#18'\'#255#7#17'a'#255
+ +#10#22'i'#255#9#22'm'#255#10#23'q'#255#11#21's'#255#12#22't'#255#11#20'r'#255
+ +#8#22's'#255#9#21's'#255#10#22't'#255#9#20's'#255#9#21's'#255#9#21's'#255#10
+ +#22't'#255#9#20'r'#255#9#21's'#255#8#21'q'#255#11#24't'#255#9#22'r'#255#10#22
+ +'s'#255#10#22's'#255#10#22'r'#255#10#21's'#255#11#21's'#255#10#23's'#255#11
+ +#23's'#255#9#22'r'#255#11#24't'#255#10#23's'#255#11#22'r'#255#11#22'p'#255#10
+ +#19'm'#255#10#21'n'#255#9#20'p'#255#12#22't'#255#10#22't'#255#9#22's'#255#11
+ +#23'p'#255#11#24'l'#255#11#24'i'#255#12#23'd'#255#12#20'Z'#255#12#19'S'#255
+ +#14#17'L'#255#13#16'I'#255#13#16'G'#255#13#15'G'#255#13#15'F'#255#13#14'E'
+ +#255#13#15'G'#255#12#14'F'#255#14#16'G'#255#13#16'G'#255#15#18'I'#255#12#15
+ +'G'#255#12#15'G'#255#13#16'G'#255#11#15'D'#255#12#16'E'#255#14#17'F'#255#10
+ +#14'B'#255#11#17'E'#255#8#14'C'#255#9#15'D'#255#11#16'D'#255#12#16'C'#255#11
+ +#15'C'#255#12#17'D'#255#12#16'D'#255#12#16'E'#255#12#16'E'#255#12#15'E'#255
+ +#12#14'D'#255#13#15'E'#255#13#15'C'#255#11#14'A'#255#10#13'@'#255#12#15'B'
+ +#255#12#14'C'#255#13#14'E'#255#13#16'F'#255#12#15'F'#255#12#16'D'#255#11#15
+ +'B'#255#13#18'>'#255#18#22'6'#255#12#14'$'#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'q'#127#144#24
+ ,'@U{'#255#10#29'U'#255#5#23'U'#255#5#25'i'#255#10#29'o'#255#8#27's'#255#9#27
+ +'v'#255#9#26'v'#255#8#26'v'#255#7#24'v'#255#9#24'y'#255#7#25'u'#255#9#26'v'
+ +#255#8#25'u'#255#8#25'u'#255#8#25'u'#255#8#25'u'#255#8#26'u'#255#7#25'u'#255
+ +#8#25'v'#255#8#24'v'#255#8#24'x'#255#7#23'w'#255#6#24'w'#255#8#25'x'#255#7#24
+ +'v'#255#6#24'u'#255#6#25't'#255#5#25't'#255#5#24's'#255#5#23'r'#255#8#24'q'
+ +#255#7#25'r'#255#4#26'q'#255#5#31'u'#255#16'W'#187#255#20'q'#216#255#26's'
+ +#225#255#23'z'#226#255#21'{'#224#255' z'#230#255#26'{'#227#255#26#129#226#255
+ +#26#127#229#255#26'~'#228#255#25'}'#227#255#25'}'#227#255#24'|'#228#255#26'~'
+ +#230#255#24'{'#230#255#25'{'#231#255#24'|'#231#255#27'}'#233#255#27'~'#234
+ +#255#25'}'#234#255#23'|'#233#255#23'|'#232#255#24'{'#232#255#25'|'#232#255#21
+ +'z'#228#255#24'}'#231#255#24'}'#231#255#25#127#231#255#23'|'#229#255#24#127
+ +#230#255#24#127#230#255#24#127#230#255#23'|'#229#255#23'|'#231#255#20'y'#228
+ +#255#24'}'#233#255#24'z'#231#255#26'|'#233#255#23'y'#230#255#24'{'#232#255#21
+ +'|'#227#255#22'|'#229#255#24'|'#231#255#25'{'#231#255#26'|'#233#255#25'|'#231
+ +#255#22'y'#229#255#24'{'#230#255#21'~'#225#255#19'}'#228#255#17'|'#228#255#18
+ +'|'#224#255#16'{'#226#255#21'{'#231#255'%~'#230#255'''u'#215#255#14'D'#156
+ +#255#4'+~'#255#1#24'd'#255#12#23'`'#255#10#21'b'#255#11#22'd'#255#9#20'c'#255
+ +#11#20'b'#255#11#21'c'#255#10#21'c'#255#7#18'`'#255#10#21'c'#255#8#21'c'#255
+ +#10#22'd'#255#9#21'c'#255#9#21'c'#255#9#21'd'#255#7#19'b'#255#9#21'e'#255#8
+ +#20'c'#255#9#20'e'#255#9#20'e'#255#9#20'd'#255#7#18'a'#255#8#19'b'#255#9#21
+ +'d'#255#7#19'a'#255#9#22'd'#255#11#21'b'#255#9#19'a'#255#10#19'_'#255#10#20
+ +'_'#255#7#15'Z'#255#8#19'a'#255#7#21'g'#255#9#22'o'#255#8#21'q'#255#11#21't'
+ +#255#7#20'r'#255#8#22't'#255#6#23'r'#255#7#24's'#255#7#23's'#255#6#23's'#255
+ +#6#23'r'#255#5#22'q'#255#5#22'p'#255#5#22'q'#255#5#21'o'#255#8#24'r'#255#7#22
+ +'p'#255#8#24'q'#255#8#24'q'#255#7#22'q'#255#6#22'q'#255#8#24't'#255#6#22'r'
+ +#255#7#22'r'#255#7#22'r'#255#8#23's'#255#8#23'r'#255#8#22'o'#255#8#21'm'#255
+ +#5#18'j'#255#8#23'o'#255#9#24'p'#255#10#24's'#255#8#21'r'#255#7#21'r'#255#9
+ +#23'p'#255#11#24'o'#255#11#22'k'#255#11#23'g'#255#11#20'^'#255#11#20'W'#255
+ +#11#17'M'#255#11#17'I'#255#11#17'H'#255#10#16'G'#255#12#18'F'#255#12#17'F'
+ +#255#13#16'G'#255#11#16'G'#255#10#16'G'#255#8#15'E'#255#11#17'G'#255#10#15'E'
+ +#255#11#16'F'#255#13#16'G'#255#11#15'D'#255#12#16'E'#255#12#17'F'#255#9#16'C'
+ +#255#11#17'E'#255#9#15'D'#255#9#15'D'#255#11#15'F'#255#10#14'E'#255#11#15'F'
+ +#255#12#16'G'#255#10#15'F'#255#10#16'F'#255#9#14'E'#255#9#15'F'#255#10#16'F'
+ +#255#12#17'F'#255#11#17'D'#255#11#16'A'#255#11#14'B'#255#12#15'B'#255#12#15
+ +'D'#255#12#15'E'#255#13#16'E'#255#12#16'E'#255#11#15'D'#255#12#16'B'#255#13
+ +#17';'#255#17#20'2'#255#8#11#31#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'\m'#135#0'Vg'#132'])?j'#254#9#28
+ +'U'#255#8#25'Y'#255#7#29'l'#255#8#30'n'#255#8#29'p'#255#8#28's'#255#5#24'q'
+ +#255#7#25's'#255#8#26't'#255#8#26'v'#255#8#26't'#255#7#25't'#255#6#24's'#255
+ +#7#25't'#255#7#25't'#255#7#25'u'#255#7#25'u'#255#8#26'u'#255#7#24'v'#255#7#24
+ +'t'#255#7#24'u'#255#6#24'v'#255#6#24'v'#255#7#25'v'#255#7#24'u'#255#6#25'v'
+ +#255#4#25'q'#255#7#24't'#255#6#24'r'#255#7#25's'#255#4#23'r'#255#5#26'o'#255
+ +#4#27'n'#255#5'''~'#255#15'd'#198#255#20't'#215#255#26'z'#223#255#24'~'#226
+ +#255#19'{'#223#255#26'{'#228#255#24'{'#226#255#21'}'#224#255#23'z'#223#255#27
+ +#128#228#255#24'|'#226#255#24'|'#227#255#22'}'#228#255#24'~'#231#255#20'{'
+ +#230#255#22'~'#232#255#25'|'#232#255#28#127#235#255#25'|'#232#255#23'|'#232
+ +#255#21'|'#232#255#22'}'#233#255#22'|'#231#255#25'~'#233#255#24#127#233#255
+ +#24#127#233#255#23#127#232#255#23#127#230#255#23#128#229#255#23#128#228#255
+ +#21#127#227#255#20#127#226#255#23#128#228#255#23#128#228#255#22#127#228#255
+ +#22'~'#228#255#21'~'#228#255#20'}'#229#255#21'~'#232#255#22'~'#233#255#19'~'
+ +#227#255#20#128#230#255#19'~'#228#255#19'}'#227#255#20'|'#227#255#22'~'#229
+ +#255#23'~'#229#255#25#127#231#255#25#127#226#255#22#127#226#255#20#128#226
+ +#255#21#130#224#255#20#129#225#255#18'~'#226#255#22#127#227#255#28#127#227
+ +#255#29'l'#205#255#18'S'#177#255#7'$y'#255#7#26'`'#255#8#29'e'#255#7#26'f'
+ +#255#4#23'c'#255#8#24'b'#255#9#22'c'#255#10#23'd'#255#7#20'a'#255#8#22'b'#255
+ +#7#21'c'#255#9#23'e'#255#10#23'e'#255#9#22'd'#255#9#20'b'#255#8#21'c'#255#10
+ +#22'd'#255#10#22'd'#255#9#23'f'#255#9#23'f'#255#8#22'd'#255#7#21'c'#255#9#22
+ +'e'#255#9#22'd'#255#8#21'b'#255#8#20'b'#255#8#20'b'#255#7#20'`'#255#8#20'`'
+ +#255#9#19'`'#255#8#18'['#255#4#17'\'#255#6#19'c'#255#9#24'm'#255#6#22'o'#255
+ +#6#23'r'#255#6#22'r'#255#6#24't'#255#7#24's'#255#7#23's'#255#6#23'q'#255#6#23
+ +'q'#255#6#23'q'#255#5#23'p'#255#5#24'o'#255#5#24'o'#255#5#24'o'#255#4#23'n'
+ +#255#4#23'o'#255#5#24'p'#255#4#22'o'#255#5#23'p'#255#5#24'p'#255#6#24's'#255
+ +#6#23'r'#255#7#24's'#255#6#22'r'#255#7#23's'#255#6#22'q'#255#8#23'q'#255#9#24
+ ,'p'#255#5#21'l'#255#5#22'o'#255#6#22'q'#255#7#23's'#255#5#22'r'#255#6#21'q'
+ +#255#8#23'q'#255#10#23'o'#255#10#22'm'#255#11#24'i'#255#9#21'b'#255#9#20'Z'
+ +#255#9#18'O'#255#8#18'I'#255#8#18'G'#255#10#18'G'#255#12#19'G'#255#9#17'F'
+ +#255#9#16'F'#255#9#17'G'#255#8#16'F'#255#7#15'E'#255#10#18'H'#255#10#17'G'
+ +#255#10#17'G'#255#12#17'H'#255#12#17'G'#255#11#16'F'#255#11#16'F'#255#9#15'D'
+ +#255#10#16'E'#255#9#14'D'#255#8#15'E'#255#8#14'F'#255#9#14'G'#255#9#15'H'#255
+ +#9#15'H'#255#8#15'G'#255#10#16'I'#255#9#15'G'#255#9#15'G'#255#10#16'F'#255#11
+ +#17'F'#255#10#16'D'#255#9#16'C'#255#9#14'B'#255#11#16'D'#255#11#16'D'#255#10
+ +#15'D'#255#11#16'D'#255#13#17'E'#255#12#16'E'#255#12#16'C'#255#15#19'<'#255
+ +#20#23'6'#255#12#16'"'#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'Qd'#133#217#20'*]'#255#3#23'V'#255
+ +#7#26'd'#255#7#29'o'#255#8#30'q'#255#9#28's'#255#7#25'q'#255#7#25's'#255#8#25
+ +'u'#255#9#26'v'#255#9#26'v'#255#9#26'v'#255#9#27'v'#255#8#25'u'#255#9#26'w'
+ +#255#8#26'v'#255#7#23'v'#255#7#23'w'#255#8#24'w'#255#8#23'x'#255#7#23'x'#255
+ +#8#24'x'#255#8#24'w'#255#8#24'w'#255#8#25'w'#255#7#24'u'#255#7#24'u'#255#3#25
+ +'r'#255#9#23'v'#255#6#24't'#255#8#24'w'#255#2#24'v'#255#7#28'q'#255#6#26'n'
+ +#255#5'/'#139#255#25'u'#220#255#25'w'#220#255#22'z'#223#255#20'y'#224#255#23
+ +'|'#226#255#25'|'#228#255#24'{'#228#255#24'}'#229#255#26'{'#225#255#28'}'#228
+ +#255#26'}'#227#255#28#128#231#255#27'~'#231#255#25'~'#232#255#21'|'#230#255
+ +#23#127#232#255#24'{'#231#255#27'~'#234#255#25'{'#231#255#24'{'#231#255#24'z'
+ +#231#255#24'{'#232#255#23'y'#230#255#26'|'#233#255#24'|'#232#255#23'{'#231
+ +#255#24'|'#232#255#22'~'#232#255#24#128#232#255#23#127#231#255#23#129#230#255
+ +#21#128#227#255#23#127#227#255#21'}'#225#255#23#127#230#255#24#127#231#255#24
+ +'~'#232#255#20'y'#228#255#22'{'#231#255#23'|'#233#255#21'{'#231#255#23'~'#232
+ +#255#23'~'#233#255#22'}'#230#255#23#127#231#255#24'~'#231#255#24'}'#231#255
+ +#25'}'#232#255#25'}'#230#255#23'|'#229#255#25#128#231#255#19#127#227#255#21
+ +#127#227#255#20#127#226#255#24'~'#228#255#24'~'#229#255#25'u'#222#255#27'n'
+ +#216#255#25'S'#179#255#5'#p'#255#9'!l'#255#10'!m'#255#4#24'_'#255#11#26'b'
+ +#255#8#21'b'#255#9#22'c'#255#8#20'a'#255#10#23'e'#255#7#20'b'#255#9#22'c'#255
+ +#8#21'b'#255#8#21'b'#255#11#21'c'#255#11#21'c'#255#11#22'd'#255#9#21'c'#255
+ +#10#21'e'#255#11#21'e'#255#10#22'f'#255#9#21'd'#255#8#21'd'#255#8#22'd'#255
+ +#10#22'f'#255#10#21'e'#255#9#21'c'#255#9#21'b'#255#10#20'b'#255#10#20'a'#255
+ +#10#20']'#255#8#20'^'#255#5#18'_'#255#10#23'i'#255#8#25'm'#255#8#24'o'#255#5
+ +#23'o'#255#7#23't'#255#7#23'q'#255#7#22'r'#255#7#22'r'#255#7#22'r'#255#6#23
+ +'q'#255#5#23's'#255#7#24't'#255#6#24's'#255#5#23'q'#255#5#23'q'#255#6#24'r'
+ +#255#5#24'r'#255#5#23'r'#255#6#24't'#255#6#23's'#255#6#24't'#255#6#23'r'#255
+ +#7#23's'#255#6#22'r'#255#8#23's'#255#9#22's'#255#9#23'q'#255#10#24'p'#255#6
+ +#19'l'#255#6#21'p'#255#7#22'r'#255#7#22'r'#255#9#24'u'#255#6#21'r'#255#7#22
+ +'q'#255#8#22'o'#255#8#22'n'#255#11#23'j'#255#8#21'd'#255#9#21']'#255#9#19'S'
+ +#255#8#18'J'#255#11#16'G'#255#10#16'G'#255#12#18'G'#255#12#18'G'#255#11#17'F'
+ +#255#13#18'H'#255#11#16'G'#255#11#15'F'#255#12#17'H'#255#12#17'G'#255#12#18
+ +'G'#255#12#18'G'#255#12#17'F'#255#12#17'F'#255#12#16'E'#255#11#16'E'#255#11
+ +#16'E'#255#9#16'D'#255#11#17'G'#255#9#14'E'#255#10#15'F'#255#11#16'G'#255#11
+ +#15'F'#255#10#15'F'#255#10#15'F'#255#9#14'E'#255#12#16'G'#255#12#16'E'#255#14
+ +#18'G'#255#12#16'E'#255#12#16'E'#255#10#14'C'#255#12#16'E'#255#12#16'E'#255
+ +#12#16'E'#255#12#16'D'#255#12#16'C'#255#12#14'D'#255#10#14'@'#255#16#19'='
+ +#255#18#20'3'#255#10#11#31#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'UZ{'#0'tu'#135#10''#255#19#23'6'#255#11#14'#'#255#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'Yaxg;Ku'
+ +#255#7'"['#255#11'%j'#255#4#26'h'#255#7#26'o'#255#7#27'r'#255#10#29't'#255#6
+ +#26'r'#255#9#28't'#255#9#27'v'#255#9#27'v'#255#7#24'u'#255#11#27'z'#255#7#25
+ +'v'#255#7#24'w'#255#9#25'y'#255#8#24'x'#255#8#24'x'#255#7#23'x'#255#7#24'u'
+ +#255#7#24'u'#255#7#24'u'#255#7#25'u'#255#7#23'w'#255#6#22'w'#255#8#24'x'#255
+ +#9#25'y'#255#7#23'w'#255#7#24'u'#255#8#24'u'#255#6#24's'#255#12#23'x'#255#3
+ +#24's'#255#8#25'w'#255#7#25'v'#255#6#27'p'#255#5'H'#168#255#21'u'#216#255#21
+ +'w'#218#255#25#128#226#255#19'|'#222#255#26#128#226#255#27#127#230#255#23'{'
+ +#225#255#26#127#229#255#25'~'#227#255#22'{'#225#255#24'~'#228#255#23#127#229
+ +#255#22#127#231#255#25#130#234#255#21#127#231#255#24'~'#234#255#25'}'#231#255
+ +#26'}'#232#255#23'z'#230#255#25'|'#232#255#22'{'#231#255#25'~'#234#255#23#127
+ +#234#255#23#128#233#255#20'~'#233#255#19'~'#230#255#19'~'#231#255#21'~'#231
+ +#255#22#127#233#255#25#127#235#255#25'~'#235#255#24'}'#234#255#23'z'#233#255
+ +#26'{'#233#255#28'~'#233#255#26'~'#231#255#21'~'#229#255#23#129#232#255#19'}'
+ +#228#255#23#127#232#255#24'{'#231#255#26'|'#233#255#25'{'#233#255#23'{'#236
+ +#255#24'{'#235#255#21'{'#232#255#22'|'#233#255#23'}'#233#255#24'~'#230#255#23
+ +'}'#231#255#21'|'#228#255#22'}'#229#255#19'|'#228#255#21'~'#230#255#22#127
+ +#231#255#21'~'#230#255#23'}'#232#255#26#127#230#255#20'~'#227#255#27'~'#237
+ +#255'#'#131#231#255#20'N'#164#255#9'8'#141#255#11'!p'#255#5#25'f'#255#8#24'e'
+ +#255#9#22'e'#255#9#20'f'#255#11#19'f'#255#12#19'g'#255#11#19'f'#255#9#20'd'
+ +#255#9#21'c'#255#9#21'c'#255#9#20'c'#255#8#19'c'#255#10#21'e'#255#9#21'e'#255
+ +#8#20'f'#255#9#21'g'#255#9#21'f'#255#10#23'e'#255#8#21'd'#255#8#21'b'#255#9
+ +#21'b'#255#10#21'b'#255#9#19'a'#255#9#19'a'#255#6#17'a'#255#11#20'd'#255#11
+ +#20'd'#255#10#20'd'#255#9#21'c'#255#5#18'`'#255#5#18'a'#255#9#22'i'#255#5#22
+ +'l'#255#4#22'l'#255#6#22'p'#255#7#22's'#255#7#23't'#255#7#23't'#255#6#22's'
+ +#255#7#23't'#255#7#24'u'#255#6#23't'#255#5#22's'#255#6#23't'#255#6#23't'#255
+ +#7#23'w'#255#6#22'w'#255#6#22'v'#255#8#22'w'#255#8#23'w'#255#5#21'u'#255#6#22
+ +'u'#255#8#23't'#255#8#23'r'#255#9#23'p'#255#7#21'm'#255#7#20'n'#255#9#22'q'
+ +#255#7#22'r'#255#8#23't'#255#6#22'u'#255#5#22'u'#255#7#23'u'#255#7#23's'#255
+ ,#8#23'r'#255#7#23'p'#255#11#24'l'#255#12#22'd'#255#11#19'Z'#255#9#18'Q'#255
+ +#12#17'J'#255#12#16'H'#255#10#15'F'#255#11#16'G'#255#10#15'G'#255#11#16'H'
+ +#255#11#16'H'#255#14#17'K'#255#13#14'J'#255#12#14'H'#255#13#15'G'#255#13#15
+ +'F'#255#12#16'G'#255#11#16'I'#255#12#16'J'#255#11#15'I'#255#12#15'J'#255#9#15
+ +'H'#255#12#16'J'#255#10#14'I'#255#10#16'J'#255#9#16'I'#255#8#16'I'#255#9#16
+ +'I'#255#10#17'I'#255#9#16'G'#255#10#16'G'#255#10#16'F'#255#12#16'E'#255#13#16
+ +'C'#255#13#16'B'#255#10#13'A'#255#12#15'E'#255#13#16'I'#255#12#14'G'#255#12
+ +#16'H'#255#11#13'E'#255#11#15'D'#255#13#19'>'#255#16#20'3'#255#8#11#31#255#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'Q'
+ +'\q'#206'''>l'#254#7'"a'#255#8' i'#255#5#27'i'#255#6#28'p'#255#6#26's'#255#9
+ +#28'v'#255#6#26's'#255#8#27'v'#255#7#26'u'#255#8#27'v'#255#7#26'u'#255#9#28
+ +'w'#255#7#25'w'#255#8#25'w'#255#6#24'v'#255#8#26'y'#255#7#23'w'#255#8#24'y'
+ +#255#7#23'w'#255#7#24'v'#255#8#24'v'#255#7#23'v'#255#7#23'w'#255#7#23'w'#255
+ +#8#24'x'#255#9#25'y'#255#6#23't'#255#7#24'u'#255#8#23'u'#255#6#24's'#255#9#23
+ +'w'#255#3#24's'#255#5#26'v'#255#8#27'u'#255#3#26'l'#255#8'N'#173#255#27'|'
+ +#221#255#18'w'#214#255#24#127#224#255#21'|'#221#255#25#128#226#255#24'|'#224
+ +#255#22'z'#224#255#22'{'#225#255#23'z'#225#255#26#127#229#255#27#128#230#255
+ +#24#128#229#255#23#128#229#255#24#128#230#255#23'}'#230#255#24'~'#233#255#22
+ +#128#233#255#22'}'#231#255#20'y'#229#255#24'}'#233#255#23'|'#232#255#24'}'
+ +#233#255#24#129#235#255#23#128#233#255#18'|'#229#255#22#128#233#255#24#129
+ +#234#255#21'|'#231#255#24'~'#234#255#23'{'#231#255#27'~'#234#255#24'}'#233
+ +#255#28'~'#237#255#29'~'#236#255#25'{'#231#255#24'{'#230#255#21'~'#231#255#20
+ +#128#231#255#20#127#231#255#22#127#232#255#25'~'#230#255#27#127#232#255#25'}'
+ +#230#255#23'z'#229#255#25'~'#234#255#25'}'#231#255#25'~'#231#255#25'~'#231
+ +#255#21'}'#226#255#23'~'#229#255#21'}'#227#255#24#127#229#255#21'~'#228#255
+ +#19'|'#227#255#19'~'#226#255#19'}'#226#255#19'|'#226#255#23'|'#226#255#22'~'
+ +#229#255#20'|'#237#255#27#127#236#255'$s'#210#255#18'R'#178#255#13'*|'#255#6
+ +#29'j'#255#9#25'h'#255#9#23'f'#255#9#20'd'#255#7#18'b'#255#9#20'd'#255#8#19
+ +'c'#255#9#20'd'#255#10#22'd'#255#7#19'a'#255#9#19'c'#255#12#21'e'#255#9#19'c'
+ +#255#9#20'd'#255#9#20'e'#255#8#20'f'#255#8#20'f'#255#8#20'g'#255#7#20'c'#255
+ +#9#21'c'#255#8#20'b'#255#11#22'd'#255#9#19'a'#255#9#19'a'#255#9#18'b'#255#10
+ +#19'c'#255#8#19'd'#255#8#19'c'#255#10#22'd'#255#9#21'b'#255#5#17'_'#255#9#21
+ +'d'#255#6#21'f'#255#7#22'h'#255#9#24'm'#255#7#24'p'#255#6#24'r'#255#6#23's'
+ +#255#5#22's'#255#5#23's'#255#6#24't'#255#5#22's'#255#5#22's'#255#6#23't'#255
+ +#5#22's'#255#6#22'v'#255#7#23'x'#255#6#22'v'#255#7#22'w'#255#7#23'x'#255#6#22
+ +'v'#255#6#23'u'#255#4#23'p'#255#6#24'p'#255#7#25'o'#255#7#23'k'#255#4#19'j'
+ +#255#8#22'o'#255#7#22'r'#255#7#23't'#255#7#23'v'#255#5#23's'#255#7#24'u'#255
+ +#5#23's'#255#8#23't'#255#8#23't'#255#10#23'm'#255#12#24'h'#255#10#20'['#255
+ +#11#20'U'#255#12#18'M'#255#12#17'I'#255#11#16'G'#255#12#17'H'#255#11#17'G'
+ +#255#13#19'H'#255#10#16'E'#255#11#16'F'#255#10#15'E'#255#10#16'F'#255#11#16
+ +'F'#255#11#16'G'#255#11#16'G'#255#10#15'F'#255#11#16'I'#255#11#15'J'#255#12
+ +#16'J'#255#10#14'H'#255#11#15'I'#255#10#14'H'#255#11#16'I'#255#9#16'I'#255#9
+ +#16'H'#255#9#16'H'#255#9#16'G'#255#8#15'F'#255#10#16'G'#255#11#15'E'#255#12
+ +#16'D'#255#12#15'B'#255#12#16'C'#255#10#12'A'#255#12#15'E'#255#12#15'G'#255
+ +#10#16'E'#255#11#15'F'#255#10#15'F'#255#11#16'D'#255#13#19'>'#255#17#21'4'
+ +#255#12#15'$'#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0'Tc~'#196#26'3h'#255#4#29'a'#255#14'#o'#255#5#26'l'#255#6#29
+ +'r'#255#7#26'v'#255#9#27'w'#255#6#25'u'#255#8#27'v'#255#7#26'u'#255#9#28'w'
+ +#255#8#27'v'#255#7#26'u'#255#8#27'v'#255#8#27'v'#255#7#25'v'#255#8#26'y'#255
+ +#7#25'x'#255#6#25'w'#255#8#25'y'#255#7#23'x'#255#7#23'x'#255#7#23'w'#255#7#23
+ +'w'#255#8#24'x'#255#7#23'w'#255#8#25'u'#255#6#23's'#255#7#26't'#255#6#22's'
+ +#255#6#24's'#255#11#22'v'#255#3#24's'#255#8#25'w'#255#5#24'r'#255#4#27'k'#255
+ +#8'K'#169#255#27'z'#220#255#21'u'#215#255#24'}'#224#255#22'|'#223#255#23'}'
+ +#225#255#24'|'#226#255#27#128#229#255#25#127#227#255#25#127#225#255#28#129
+ +#227#255#26#128#227#255#22'~'#225#255#21'}'#225#255#24#128#229#255#23'~'#229
+ +#255#24#127#230#255#21'~'#231#255#23#128#233#255#22'}'#232#255#24'|'#232#255
+ +#23'|'#232#255#23'|'#232#255#22#127#232#255#25#130#235#255#24'}'#230#255#28
+ +#128#235#255#27#127#235#255#23'|'#232#255#24'}'#233#255#24'}'#233#255#25'}'
+ +#233#255#23'|'#232#255#21'|'#232#255#24'|'#232#255#23'z'#230#255#26'}'#233
+ +#255#24'~'#234#255#22'~'#233#255#20'z'#230#255#24'|'#232#255#24'|'#228#255#25
+ +'}'#230#255#23'|'#228#255#24'}'#229#255#27#128#231#255#25#128#230#255#21'|'
+ +#226#255#21'|'#226#255#19'z'#225#255#22'}'#229#255#21'{'#230#255#23'}'#232
+ ,#255#20'}'#231#255#19'|'#229#255#19'|'#227#255#21'~'#228#255#21'~'#227#255#22
+ +'}'#230#255#20'~'#229#255#21'z'#233#255#20'{'#232#255'!{'#229#255'*x'#225#255
+ +#24'B'#156#255#9#30'o'#255#7#24'h'#255#5#21'd'#255#9#22'd'#255#11#23'f'#255
+ +#11#23'e'#255#10#22'c'#255#11#24'g'#255#9#21'c'#255#9#21'c'#255#10#19'c'#255
+ +#11#20'd'#255#11#20'd'#255#12#20'd'#255#9#20'e'#255#10#22'h'#255#10#23'g'#255
+ +#10#23'e'#255#9#22'e'#255#11#23'd'#255#10#23'd'#255#12#22'c'#255#9#19'a'#255
+ +#9#19'a'#255#11#20'c'#255#11#19'e'#255#8#19'e'#255#7#18'c'#255#9#22'c'#255#10
+ +#23'b'#255#8#21'a'#255#9#21'b'#255#8#20'`'#255#8#20'b'#255#10#23'i'#255#9#24
+ +'n'#255#6#24'r'#255#6#23'r'#255#7#23's'#255#8#24't'#255#6#23's'#255#5#22's'
+ +#255#5#22's'#255#7#24'u'#255#5#22's'#255#6#22'u'#255#6#22'w'#255#7#23'w'#255
+ +#7#22'w'#255#5#21'u'#255#7#23'w'#255#6#23'u'#255#5#23't'#255#7#23'r'#255#7#24
+ +'p'#255#7#22'm'#255#4#18'i'#255#7#24'o'#255#8#23'r'#255#5#21's'#255#6#23'w'
+ +#255#6#21'v'#255#6#22'u'#255#5#22't'#255#6#23'v'#255#5#23'u'#255#8#22'n'#255
+ +#10#21'g'#255#10#19'^'#255#10#19'T'#255#12#17'M'#255#11#17'I'#255#9#15'G'#255
+ +#11#17'H'#255#11#16'G'#255#12#17'G'#255#11#17'F'#255#11#17'F'#255#11#17'F'
+ +#255#11#17'F'#255#9#15'E'#255#10#15'F'#255#11#15'F'#255#10#15'F'#255#11#16'G'
+ +#255#10#15'H'#255#11#15'I'#255#11#13'G'#255#11#15'I'#255#10#14'H'#255#12#16
+ +'H'#255#8#15'F'#255#8#15'F'#255#8#15'F'#255#8#15'F'#255#10#16'E'#255#12#17'E'
+ +#255#12#16'E'#255#13#16'D'#255#12#15'B'#255#12#15'B'#255#10#12'A'#255#11#16
+ +'D'#255#9#15'E'#255#10#15'G'#255#8#15'H'#255#8#14'G'#255#8#14'D'#255#12#18'>'
+ +#255#14#18'3'#255#8#10' '#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0'HX'#127#155#21'(b'#255#12'$n'#255#10#28'o'#255#5
+ +#26'n'#255#8#28'v'#255#7#25'w'#255#10#28'z'#255#7#25'w'#255#8#27'x'#255#8#26
+ +'v'#255#8#26'v'#255#7#26'v'#255#8#26'v'#255#8#27'w'#255#9#28'x'#255#8#26'x'
+ +#255#8#26'x'#255#7#24'x'#255#7#25'x'#255#7#25'x'#255#6#24'w'#255#8#24'w'#255
+ +#8#24'x'#255#8#25'x'#255#7#24'v'#255#6#24'u'#255#8#25's'#255#6#24'q'#255#8#25
+ +'s'#255#9#23's'#255#7#26's'#255#9#23'u'#255#6#27'r'#255#8#25'v'#255#5#24's'
+ +#255#2#25'j'#255#10'L'#171#255#27'x'#221#255#23'w'#219#255#22'z'#221#255#23
+ +'|'#226#255#28'~'#233#255#27#127#232#255#26'~'#229#255#23'}'#225#255#27#128
+ +#228#255#29#130#230#255#28#129#230#255#24#127#227#255#26#130#229#255#26#130
+ +#232#255#23'}'#227#255#26#128#231#255#25#127#234#255#22'}'#231#255#22'|'#229
+ +#255#24'|'#231#255#22'{'#232#255#23'|'#232#255#21'|'#230#255#23'}'#231#255#27
+ +#127#233#255#24'|'#231#255#23'z'#229#255#22'{'#230#255#25'~'#233#255#26#127
+ +#234#255#24'}'#232#255#21'z'#230#255#24#127#233#255#24#127#231#255#22'|'#228
+ +#255#24'}'#230#255#22'{'#228#255#24'}'#231#255#22'z'#230#255#28'~'#234#255#24
+ +'z'#230#255#26'|'#231#255#24'{'#230#255#28'~'#234#255#27#128#234#255#26#127
+ +#233#255#21'{'#230#255#23'~'#233#255#25'}'#234#255#27#127#235#255#24'|'#233
+ +#255#25'|'#233#255#22'|'#233#255#22'}'#232#255#21'~'#231#255#20'}'#230#255#20
+ +'~'#227#255#21'|'#232#255#22'|'#229#255#23'y'#232#255#17'v'#226#255'!|'#234
+ +#255',}'#238#255#23'H'#170#255#12' t'#255#6#24'i'#255#6#22'd'#255#9#21'c'#255
+ +#11#23'e'#255#10#22'e'#255#8#20'c'#255#11#22'd'#255#8#19'a'#255#10#21'c'#255
+ +#11#21'd'#255#11#21'd'#255#11#20'c'#255#10#20'c'#255#9#21'd'#255#11#23'g'#255
+ +#11#23'e'#255#10#23'e'#255#8#22'b'#255#10#22'b'#255#12#22'c'#255#10#19'_'#255
+ +#8#18'`'#255#10#20'a'#255#10#19'd'#255#11#18'e'#255#8#19'e'#255#8#20'e'#255#9
+ +#22'd'#255#9#22'b'#255#8#20'_'#255#11#19'`'#255#8#17'X'#255#7#17'Z'#255#8#19
+ +'d'#255#9#21'l'#255#5#20'n'#255#6#23'p'#255#6#23'q'#255#7#23's'#255#7#23't'
+ +#255#7#23't'#255#6#22's'#255#5#22's'#255#6#22's'#255#6#23'u'#255#6#23'v'#255
+ +#6#23'u'#255#6#23'u'#255#6#21't'#255#6#22'v'#255#6#21'v'#255#6#22't'#255#8#23
+ +'t'#255#6#22'q'#255#7#21'o'#255#4#17'k'#255#7#22'q'#255#8#23's'#255#6#22'u'
+ +#255#5#21'v'#255#5#21'v'#255#5#21'v'#255#5#21'v'#255#7#23'u'#255#8#23'v'#255
+ +#9#23'p'#255#11#23'i'#255#11#21'`'#255#10#20'W'#255#10#19'P'#255#11#17'M'#255
+ +#11#16'J'#255#11#16'I'#255#12#16'I'#255#12#16'I'#255#11#16'H'#255#11#17'G'
+ +#255#11#16'F'#255#11#16'F'#255#11#17'H'#255#10#15'H'#255#10#16'F'#255#10#15
+ +'F'#255#11#16'G'#255#11#15'I'#255#12#14'H'#255#11#15'I'#255#11#14'H'#255#10
+ +#14'H'#255#10#15'G'#255#11#14'F'#255#10#15'F'#255#11#16'F'#255#10#16'F'#255
+ +#11#16'F'#255#12#16'D'#255#13#16'F'#255#13#16'C'#255#12#15'B'#255#13#16'B'
+ +#255#10#14'@'#255#12#16'D'#255#10#14'D'#255#12#16'H'#255#9#14'I'#255#10#14'I'
+ +#255#10#14'E'#255#13#19'>'#255#18#21'7'#255#13#13'%'#255#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'GX'#132#179#23'$]'
+ +#254#7'"l'#255#10#28'p'#255#5#27'm'#255#8#27't'#255#8#26'x'#255#11#29'{'#255
+ +#9#27'y'#255#9#27'y'#255#9#26'y'#255#10#27'y'#255#8#25'x'#255#7#24'w'#255#7
+ +#25'v'#255#7#25'v'#255#7#25'y'#255#7#26'x'#255#7#23'y'#255#8#25'x'#255#7#24
+ ,'w'#255#7#24'x'#255#8#24'w'#255#7#24'u'#255#9#26'v'#255#7#25't'#255#5#24's'
+ +#255#7#25't'#255#6#22's'#255#8#24't'#255#11#22'r'#255#6#25'q'#255#7#23't'#255
+ +#6#26's'#255#6#23't'#255#5#25't'#255#4#26'o'#255#12'K'#171#255'!{'#228#255#24
+ +'w'#223#255#21'z'#223#255#26'}'#228#255#27'|'#231#255#28'{'#232#255#27'{'#230
+ +#255#25'|'#226#255#25'|'#228#255#25'}'#228#255#27#128#230#255#26#127#229#255
+ +#25#128#229#255#27#129#231#255#27#128#230#255#26#127#230#255#27#127#232#255
+ +#23'|'#229#255#24'}'#231#255#22'|'#230#255#21'|'#231#255#22'{'#231#255#23'|'
+ +#232#255#24'{'#231#255#24'{'#231#255#25'|'#232#255#25'}'#231#255#27#127#233
+ +#255#25'}'#231#255#24'|'#230#255#27#127#233#255#24'{'#230#255#24#127#230#255
+ +#22'}'#227#255#22'~'#227#255#25'~'#229#255#23'|'#226#255#26#127#230#255#27'~'
+ +#233#255#27'}'#233#255#27'}'#232#255#26'|'#231#255#25'{'#230#255#25'|'#232
+ +#255#27'~'#234#255#28'~'#235#255#23'{'#232#255#24'{'#232#255#25'z'#233#255#24
+ +'z'#231#255#23'y'#229#255#26'~'#233#255#25'}'#230#255#23'|'#229#255#24'}'#229
+ +#255#26#127#232#255#27#129#232#255#22'|'#232#255#20'}'#232#255#24'z'#235#255
+ +#23'y'#230#255'"{'#233#255'0'#130#241#255'!T'#183#255#11'!v'#255#7#27'l'#255
+ +#7#24'd'#255#8#21'c'#255#9#21'c'#255#8#20'b'#255#8#20'c'#255#9#22'c'#255#10
+ +#21'c'#255#10#21'c'#255#9#20'b'#255#11#22'd'#255#10#22'd'#255#10#22'd'#255#9
+ +#21'c'#255#9#21'c'#255#10#23'd'#255#10#22'c'#255#9#22'b'#255#9#21'a'#255#10
+ +#20'b'#255#9#19'a'#255#9#20'b'#255#11#21'd'#255#9#19'e'#255#10#21'g'#255#9#21
+ +'g'#255#8#20'f'#255#8#20'd'#255#9#21'c'#255#9#19'`'#255#12#20'a'#255#12#20'Z'
+ +#255#7#16'Y'#255#5#16'`'#255#9#22'l'#255#6#21'm'#255#8#24'q'#255#6#24'p'#255
+ +#8#24't'#255#8#24't'#255#7#22'r'#255#8#23's'#255#8#23't'#255#7#22's'#255#8#22
+ +'s'#255#5#22't'#255#5#21'v'#255#5#23't'#255#6#23't'#255#6#24't'#255#6#23's'
+ +#255#6#23's'#255#6#23's'#255#8#23's'#255#8#22'q'#255#4#18'n'#255#7#22's'#255
+ +#7#22'v'#255#6#23'v'#255#5#22'w'#255#7#23'x'#255#6#21'v'#255#7#23'w'#255#6#23
+ +'t'#255#6#22't'#255#8#23'r'#255#7#25'k'#255#11#23'e'#255#10#21'['#255#12#21
+ +'U'#255#10#16'O'#255#11#15'J'#255#11#15'I'#255#12#16'J'#255#12#16'J'#255#11
+ +#16'G'#255#10#15'F'#255#9#14'E'#255#10#15'F'#255#11#15'H'#255#10#14'I'#255#10
+ +#14'I'#255#9#13'G'#255#10#14'H'#255#11#15'I'#255#10#14'G'#255#11#15'H'#255#9
+ +#14'G'#255#9#15'H'#255#10#14'I'#255#10#14'H'#255#12#14'I'#255#12#14'H'#255#12
+ +#14'H'#255#13#15'G'#255#12#15'E'#255#14#15'F'#255#12#15'B'#255#13#16'B'#255
+ +#11#15'A'#255#10#13'?'#255#12#16'D'#255#11#15'D'#255#13#16'G'#255#10#13'G'
+ +#255#10#13'H'#255#12#13'E'#255#12#17'='#255#16#19'4'#255#8#9'!'#255#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#234#0#0#0'=Q'#131
+ +#156#9#25'V'#255#8'$p'#255#9#29'q'#255#7#27'q'#255#7#26'v'#255#7#25'v'#255#8
+ +#26'w'#255#8#26'w'#255#7#25'v'#255#8#24'x'#255#9#25'y'#255#9#25'y'#255#9#25
+ +'y'#255#8#26'w'#255#8#26'w'#255#9#27'x'#255#9#27'z'#255#9#25'y'#255#9#25'y'
+ +#255#8#24'x'#255#8#24'x'#255#9#27'v'#255#8#26'u'#255#7#25't'#255#6#24's'#255
+ +#6#24's'#255#8#25'v'#255#7#23'v'#255#9#25'y'#255#11#23'r'#255#6#25'q'#255#9
+ +#22'v'#255#6#25's'#255#9#26'w'#255#4#25't'#255#3#22'l'#255#11'A'#164#255#31
+ +'v'#228#255#24'r'#223#255#27'{'#230#255#29'}'#232#255#29'{'#233#255#30'{'#232
+ +#255#30'{'#232#255#27'{'#229#255#27'~'#230#255#26'}'#229#255#28#127#231#255
+ +#28#127#231#255#31#130#234#255#30#131#234#255#28#129#233#255#28#127#235#255
+ +#24#127#232#255#23'~'#230#255#25#127#233#255#22#127#232#255#23#127#233#255#25
+ +'~'#234#255#27#127#235#255#26'}'#233#255#25'|'#232#255#27'~'#234#255#25'|'
+ +#232#255#25'}'#232#255#26'}'#233#255#25'{'#231#255#24'z'#229#255#26'|'#231
+ +#255#26#127#232#255#26#127#231#255#25#128#229#255#26#127#229#255#26#127#229
+ +#255#23'|'#227#255#25'}'#231#255#26'~'#232#255#25'|'#227#255#24'|'#227#255#23
+ +'}'#227#255#26'~'#231#255#25'}'#232#255#27'~'#233#255#25'|'#233#255#25'{'#232
+ +#255#26'|'#231#255#25'{'#231#255#23'y'#228#255#25'{'#230#255#23'z'#226#255#25
+ +'{'#227#255#24'{'#227#255#24'{'#226#255#23'z'#229#255#22'y'#230#255#22'{'#231
+ +#255#24'x'#233#255#24'{'#231#255'"}'#233#255'(|'#233#255#30'S'#180#255#7#31
+ +'p'#255#5#27'l'#255#3#21'b'#255#10#23'e'#255#10#23'e'#255#9#22'd'#255#10#22
+ +'d'#255#10#22'd'#255#9#21'c'#255#9#21'c'#255#8#20'b'#255#11#23'e'#255#7#19'a'
+ +#255#8#20'b'#255#10#22'd'#255#9#21'c'#255#9#24'a'#255#9#22'_'#255#10#23'`'
+ +#255#10#23'c'#255#10#23'c'#255#6#19'`'#255#8#19'c'#255#8#20'f'#255#8#20'f'
+ +#255#8#20'f'#255#7#19'e'#255#8#21'g'#255#10#22'e'#255#9#21'c'#255#6#19'_'#255
+ +#9#19'`'#255#12#20'^'#255#7#18'['#255#2#13'\'#255#9#22'h'#255#10#22'n'#255#11
+ +#24's'#255#7#23'r'#255#7#22'r'#255#6#22'o'#255#5#20'p'#255#7#22'r'#255#7#22
+ +'s'#255#7#22's'#255#8#22'v'#255#9#22'x'#255#9#21'x'#255#8#24'x'#255#7#24'x'
+ +#255#7#23'x'#255#5#22'v'#255#5#22'u'#255#8#25'v'#255#9#24't'#255#7#23'p'#255
+ +#4#19'n'#255#6#22'r'#255#6#22'u'#255#7#23'x'#255#6#23'x'#255#7#24'x'#255#5#23
+ +'w'#255#6#22'v'#255#6#22'v'#255#6#23'u'#255#7#23't'#255#7#24'o'#255#11#25'i'
+ ,#255#9#21'_'#255#10#19'W'#255#10#17'P'#255#14#18'N'#255#13#17'K'#255#12#16'J'
+ +#255#11#15'I'#255#11#15'I'#255#11#15'I'#255#11#16'H'#255#12#16'I'#255#11#16
+ +'I'#255#12#16'K'#255#11#15'J'#255#11#15'J'#255#10#14'H'#255#10#14'I'#255#10
+ +#15'F'#255#11#17'F'#255#10#16'H'#255#10#17'J'#255#8#15'I'#255#11#15'J'#255#11
+ +#15'J'#255#10#14'I'#255#10#14'I'#255#10#15'J'#255#12#15'H'#255#14#18'G'#255
+ +#13#15'D'#255#13#16'C'#255#11#14'A'#255#9#12'?'#255#12#15'C'#255#11#16'D'#255
+ +#13#17'F'#255#9#14'C'#255#11#14'F'#255#13#14'F'#255#12#17'>'#255#18#21'7'#255
+ +#12#13'$'#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0'8N'#131'q'#15#31'_'#252#5' o'#255#8#27'q'#255#8#27's'#255#8#26
+ +'y'#255#8#25'x'#255#8#25'x'#255#9#26'y'#255#8#25'w'#255#9#25'x'#255#8#25'w'
+ +#255#8#24'w'#255#7#24'v'#255#7#26'w'#255#8#25'v'#255#7#25'w'#255#8#24'x'#255
+ +#9#25'y'#255#8#24'x'#255#8#24'x'#255#8#25'w'#255#8#25'v'#255#8#25'u'#255#6#23
+ +'r'#255#4#22'q'#255#7#24'u'#255#8#26'v'#255#7#23'w'#255#9#25'y'#255#6#23'r'
+ +#255#5#24'r'#255#11#22'w'#255#6#25's'#255#7#25'x'#255#5#26'v'#255#9#26'p'#255
+ +#8'9'#156#255'"v'#230#255#28'u'#227#255#30'{'#232#255#26'z'#229#255#27'z'#232
+ +#255#29'{'#232#255#30'}'#234#255#29'~'#234#255#29#128#232#255#28#127#231#255
+ +#28#127#231#255#28#127#231#255#28'~'#232#255' '#132#237#255'!'#132#239#255#30
+ +#131#240#255#29#127#237#255#26'}'#234#255#27#127#236#255#26'~'#235#255#26'~'
+ +#235#255#27'~'#234#255#26'}'#233#255#26'|'#232#255#24'z'#230#255#26'{'#235
+ +#255#27'{'#234#255#27'{'#235#255#25'{'#234#255#27'}'#234#255#26'{'#232#255#25
+ +'{'#231#255#25'|'#233#255#27'~'#234#255#28#128#235#255#26'~'#233#255#25'}'
+ +#232#255#25'|'#232#255#27'~'#233#255#26'}'#232#255#25'}'#229#255#25'}'#229
+ +#255#24'}'#228#255#24'}'#229#255#25'|'#230#255#24'{'#230#255#25'|'#231#255#25
+ +'}'#231#255#24'z'#230#255#23'y'#229#255#22'x'#227#255#26'|'#232#255#25'{'#230
+ +#255#25'{'#232#255#25'x'#230#255#28'z'#234#255#22'x'#228#255#25'z'#234#255#25
+ +'|'#233#255#26'x'#233#255#24'{'#231#255#29'x'#229#255'&{'#233#255'&]'#191#255
+ +#4#26'p'#255#6#26'l'#255#6#23'd'#255#9#21'd'#255#8#20'b'#255#7#19'b'#255#8#19
+ +'b'#255#9#21'd'#255#11#22'd'#255#10#21'c'#255#10#21'c'#255#11#22'd'#255#10#22
+ +'d'#255#11#23'e'#255#11#23'e'#255#11#23'e'#255#7#20'`'#255#8#21'_'#255#9#21
+ +'_'#255#8#19'`'#255#10#21'b'#255#7#19'a'#255#7#18'b'#255#8#20'e'#255#7#19'e'
+ +#255#9#20'f'#255#7#18'd'#255#10#20'f'#255#8#18'b'#255#10#21'c'#255#9#20'a'
+ +#255#11#21'b'#255#11#21'a'#255#9#21'_'#255#1#14'X'#255#7#20'b'#255#9#21'm'
+ +#255#11#22't'#255#9#22'r'#255#8#24'q'#255#7#22'q'#255#10#24't'#255#8#23's'
+ +#255#9#24'u'#255#8#23't'#255#8#23't'#255#8#22't'#255#8#22'v'#255#8#21'x'#255
+ +#9#22'y'#255#8#22'y'#255#6#22'x'#255#7#22'w'#255#9#24'w'#255#9#23'u'#255#9#22
+ +'s'#255#7#18'o'#255#8#21't'#255#10#22'w'#255#9#23'y'#255#5#20'x'#255#7#23'{'
+ +#255#6#22'x'#255#9#23'y'#255#8#22'w'#255#9#23'u'#255#7#22't'#255#5#23'o'#255
+ +#9#23'j'#255#11#22'b'#255#13#21'Y'#255#12#18'R'#255#14#17'L'#255#12#16'J'#255
+ +#12#16'J'#255#13#17'K'#255#13#17'K'#255#11#15'I'#255#12#16'J'#255#13#17'K'
+ +#255#11#15'H'#255#13#17'J'#255#11#15'J'#255#12#16'K'#255#11#15'J'#255#12#16
+ +'J'#255#10#15'H'#255#12#16'H'#255#11#16'H'#255#11#16'I'#255#11#15'I'#255#12
+ +#15'I'#255#13#15'J'#255#12#13'I'#255#12#13'I'#255#12#13'I'#255#13#14'I'#255
+ +#13#16'H'#255#12#16'E'#255#14#17'D'#255#11#14'A'#255#11#14'A'#255#12#14'C'
+ +#255#13#15'E'#255#11#15'C'#255#10#15'C'#255#10#14'E'#255#14#16'G'#255#13#18
+ +'A'#255#17#20'6'#255#9#10' '#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0'4X'#135#0':My'#4'1F}|'#13#30'^'#236#10'"s'#255#9#27'u'#255#9
+ +#25't'#255#8#24'y'#255#9#25'y'#255#9#25'y'#255#10#26'z'#255#9#25'z'#255#8#24
+ +'w'#255#9#25'x'#255#9#26'x'#255#9#25'x'#255#8#25't'#255#9#25'v'#255#8#25'u'
+ +#255#7#24'v'#255#8#24'x'#255#6#22'v'#255#9#24'w'#255#8#23'v'#255#9#24'w'#255
+ +#9#24'v'#255#8#23't'#255#6#23'r'#255#8#24'u'#255#8#25'v'#255#7#24'v'#255#7#23
+ +'x'#255#5#23'q'#255#7#23's'#255#8#23'u'#255#6#24's'#255#7#26'v'#255#6#24'r'
+ +#255#3#23'p'#255#6'/'#145#255'"w'#232#255#29'v'#227#255#24'z'#227#255#25'{'
+ +#226#255#29#127#232#255#28'~'#230#255#28#127#232#255#27'}'#232#255#29#128#235
+ +#255#28#127#232#255'!'#129#234#255'!'#129#232#255#28'~'#231#255#30#128#236
+ +#255#27'~'#234#255#29#127#238#255#28#129#237#255#27'~'#235#255#26'~'#236#255
+ +#29#127#237#255#27'{'#232#255#29'|'#233#255#29'|'#232#255' ~'#235#255#29'{'
+ +#234#255#31'}'#238#255#28'z'#237#255#29'{'#239#255#28'}'#239#255#26'|'#236
+ +#255#27'}'#236#255#25'{'#235#255#26'{'#233#255#25'z'#234#255#28'~'#237#255#27
+ +'}'#237#255#28'~'#237#255#28'~'#236#255#27'}'#235#255#28'~'#235#255#24'z'#230
+ +#255#23'y'#230#255#24'z'#231#255#26'z'#233#255#27'|'#234#255#28'|'#236#255#24
+ +'y'#231#255#26'{'#233#255#24'z'#230#255#27'}'#233#255#26'|'#232#255#27'}'#233
+ +#255#25'z'#232#255#28'}'#235#255#28'z'#236#255#28'z'#237#255#27'z'#234#255#25
+ ,'z'#233#255#25'z'#232#255#24'y'#237#255#22'x'#229#255'"|'#234#255'''}'#235
+ +#255'/g'#208#255#8'"{'#255#8#26'n'#255#8#20'd'#255#9#20'd'#255#9#21'e'#255#9
+ +#20'f'#255#12#21'f'#255#12#21'e'#255#12#20'c'#255#12#20'c'#255#11#21'c'#255
+ +#10#20'b'#255#11#20'b'#255#11#22'd'#255#11#22'd'#255#11#22'd'#255#11#21'`'
+ +#255#11#22'_'#255#10#20'_'#255#9#19'`'#255#10#20'b'#255#9#20'b'#255#8#20'b'
+ +#255#8#20'd'#255#10#20'f'#255#10#19'g'#255#9#18'f'#255#11#19'g'#255#10#19'd'
+ +#255#12#21'e'#255#10#19'b'#255#9#19'a'#255#10#21'b'#255#10#21'a'#255#6#16'\'
+ +#255#6#16'_'#255#9#19'j'#255#10#21'p'#255#9#21's'#255#8#22's'#255#9#21'r'#255
+ +#9#23't'#255#9#22't'#255#9#24't'#255#9#24'v'#255#8#23'u'#255#7#21't'#255#9#23
+ +'v'#255#9#21'z'#255#10#22'|'#255#8#20'z'#255#9#21'{'#255#9#20'x'#255#10#22'y'
+ +#255#11#23'v'#255#11#23'u'#255#8#18'q'#255#10#22'u'#255#10#22'x'#255#10#22'|'
+ +#255#6#19'x'#255#10#20'z'#255#10#21'y'#255#10#21'w'#255#9#22'u'#255#9#22's'
+ +#255#9#23't'#255#8#24'p'#255#13#25'm'#255#11#22'a'#255#11#19'W'#255#13#18'P'
+ +#255#15#18'L'#255#13#16'J'#255#12#15'H'#255#13#16'J'#255#13#15'J'#255#13#15
+ +'K'#255#13#15'K'#255#14#17'K'#255#12#15'H'#255#15#17'K'#255#13#16'J'#255#14
+ +#16'L'#255#11#14'J'#255#12#16'K'#255#11#15'I'#255#11#15'J'#255#11#15'H'#255
+ +#11#16'H'#255#11#15'I'#255#13#14'H'#255#13#15'I'#255#12#13'H'#255#12#13'H'
+ +#255#13#15'J'#255#12#14'G'#255#13#15'G'#255#12#15'E'#255#13#15'D'#255#12#14
+ +'B'#255#13#15'C'#255#13#14'C'#255#15#16'F'#255#12#14'B'#255#11#14'C'#255#11
+ +#14'E'#255#13#15'F'#255#14#17'@'#255#20#22'9'#255#13#14'%'#255#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#128#128'o'#0'psd'#0'Yis'#1''#143#218#255'K'
+ +#151#224#255'J'#146#214#255'M'#147#212#255'M'#149#218#255'M'#157#230#255'D'
+ +#154#237#255'?'#153#237#255'9'#149#240#255'6'#146#238#255'.'#138#233#255'*'
+ +#134#235#255''''#133#235#255'"'#130#235#255#31#129#235#255'"'#133#239#255#29
+ +#128#231#255#28#127#232#255#25'}'#231#255#26'|'#233#255#25'~'#237#255#23'|'
+ +#234#255#24'~'#235#255#24#127#236#255#28#129#238#255#29#129#240#255#25'}'#237
+ +#255#23'z'#236#255#26'~'#238#255#28'~'#238#255#28'|'#237#255#26'{'#233#255#28
+ +'~'#234#255#26'|'#232#255#28'~'#234#255#28'}'#234#255#25'{'#232#255#26'{'#233
+ +#255#24'z'#232#255#26'{'#233#255#24'{'#238#255#26'}'#239#255#22'{'#236#255#24
+ +'~'#239#255#21'{'#235#255#24#128#236#255#22'}'#234#255#23'~'#235#255#25'~'
+ +#235#255#24#128#231#255#26'}'#233#255#21'~'#237#255#23'|'#232#255#29'~'#234
+ +#255'#'#127#235#255'1x'#227#255#2'/'#134#255#4#31's'#255#9#22'h'#255#10#23'f'
+ +#255#6#20'c'#255#8#19'e'#255#11#19'c'#255#11#20'd'#255#7#19'a'#255#9#21'c'
+ +#255#9#21'c'#255#10#22'd'#255#9#21'c'#255#11#22'd'#255#10#20'b'#255#11#21'c'
+ +#255#9#20'c'#255#9#21'c'#255#11#22'f'#255#9#20'e'#255#13#21'g'#255#10#19'd'
+ +#255#11#19'd'#255#10#19'd'#255#10#19'd'#255#11#20'e'#255#9#18'c'#255#11#20'e'
+ +#255#11#20'd'#255#11#20'c'#255#11#21'c'#255#8#18'_'#255#9#22'b'#255#11#22'`'
+ +#255#12#21'_'#255#5#15'Z'#255#6#18'b'#255#8#23'm'#255#7#22'p'#255#8#22'r'#255
+ +#8#23't'#255#7#22's'#255#9#24'u'#255#7#21'u'#255#9#23'x'#255#7#21'v'#255#7#20
+ +'v'#255#9#22'x'#255#7#21'w'#255#8#23'y'#255#8#21'w'#255#8#21'w'#255#9#23'w'
+ +#255#9#22'v'#255#8#20'r'#255#10#22't'#255#4#19'o'#255#8#23's'#255#7#21't'#255
+ +#7#23'w'#255#6#22'x'#255#7#23'x'#255#7#23'x'#255#8#21'w'#255#8#21'x'#255#7#20
+ +'v'#255#7#21'v'#255#6#21't'#255#8#22'o'#255#9#22'f'#255#10#19'^'#255#10#19'V'
+ +#255#12#17'P'#255#10#16'L'#255#10#17'K'#255#10#17'J'#255#11#19'K'#255#11#18
+ +'L'#255#10#17'K'#255#11#18'J'#255#12#16'J'#255#14#16'J'#255#13#15'I'#255#12
+ +#15'J'#255#10#14'I'#255#11#16'J'#255#10#15'M'#255#10#15'L'#255#10#15'L'#255
+ +#10#14'K'#255#12#14'L'#255#11#16'K'#255#12#16'J'#255#11#14'H'#255#11#15'I'
+ +#255#9#15'G'#255#9#15'E'#255#11#17'F'#255#12#17'F'#255#12#17'F'#255#10#15'B'
+ +#255#11#15'B'#255#12#16'C'#255#12#16'C'#255#12#15'B'#255#11#15'D'#255#12#15
+ +'F'#255#13#17'G'#255#13#17'?'#255#20#21'9'#255#12#13'%'#255#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#145#139'v'#7'pwq'#24'Ugv''H^x'#26'''At_'#19'-n'#194#11'"g'
+ +#242#7#29'p'#253#6#27's'#254#9#26's'#255#7#25'w'#255#8#26't'#255#10#28'v'#255
+ +#8#26'v'#255#7#24'u'#255#9#25'x'#255#9#25'x'#255#7#23'x'#255#9#25'z'#255#8#25
+ +'w'#255#9#26'y'#255#9#27'z'#255#8#26'y'#255#8#26'x'#255#7#25'w'#255#7#25'v'
+ +#255#7#26'u'#255#7#22'q'#255#3#18'n'#255#6#21'r'#255#9#23'w'#255#10#23'y'#255
+ +#8#24'y'#255#6#22'v'#255#8#24'x'#255#6#24'u'#255#9#23't'#255#10#23's'#255#6
+ +#25'u'#255#2#22'w'#255#6#22'w'#255#7#25'u'#255#3#23'n'#255#10':'#153#255#28
+ +'t'#222#255#23't'#225#255#25'}'#223#255#28#129#215#255'*'#132#210#255'9'#143
+ +#200#255'9p'#152#255'6Yq'#255'''BW'#255#22')8'#255#22'$-'#255#21'$,'#255#20
+ +')8'#255#25'7L'#255'*Jf'#255')Sr'#255'+\'#131#255';t'#169#255'?'#133#205#255
+ +':'#140#223#255'5'#143#232#255'&'#132#224#255'"'#130#223#255#29#130#227#255
+ +#30#131#228#255#28#129#230#255#27#127#232#255#25'|'#232#255#26'}'#232#255#26
+ +'}'#233#255#28#128#236#255#28#128#235#255#28#128#237#255#27#127#236#255#25'}'
+ +#233#255#25'{'#233#255#27'}'#235#255#27'}'#234#255#27'|'#232#255#25'{'#231
+ +#255#27'}'#233#255#28'~'#234#255#28#127#234#255#25'|'#232#255#24'{'#231#255
+ +#24'{'#232#255#22'{'#232#255#24'z'#235#255#25'|'#237#255#23'z'#235#255#27'}'
+ +#238#255#25'|'#236#255#28#127#237#255#25'}'#234#255#23#128#234#255#25#127#235
+ +#255#23#128#231#255#25'|'#232#255#19'{'#234#255#22'{'#231#255#27'}'#233#255
+ +#30'~'#235#255'-{'#231#255#8'6'#141#255#3'!t'#255#8#23'i'#255#9#23'f'#255#7
+ +#21'd'#255#13#21'h'#255#13#22'f'#255#9#20'd'#255#7#20'c'#255#9#22'd'#255#7#20
+ +'b'#255#9#21'c'#255#10#22'd'#255#9#21'c'#255#9#20'a'#255#11#21'c'#255#9#22'c'
+ +#255#8#20'b'#255#9#21'd'#255#8#19'd'#255#11#22'g'#255#8#19'd'#255#10#20'e'
+ +#255#11#20'f'#255#10#20'b'#255#10#20'c'#255#11#19'd'#255#10#19'd'#255#10#20
+ +'b'#255#9#19'a'#255#10#20'b'#255#7#17'^'#255#8#21'b'#255#7#20'a'#255#11#22'a'
+ +#255#8#19']'#255#3#16'^'#255#7#22'l'#255#7#22'p'#255#8#23'r'#255#7#23't'#255
+ +#6#22's'#255#8#23'u'#255#7#22'v'#255#8#23'w'#255#6#21'v'#255#5#20'u'#255#8#22
+ +'x'#255#6#21'v'#255#7#23'x'#255#6#21'v'#255#8#21'w'#255#9#22'w'#255#9#22'w'
+ +#255#8#22't'#255#11#23'u'#255#6#18'm'#255#9#21'q'#255#9#23't'#255#10#23'w'
+ +#255#6#22'w'#255#8#22'x'#255#9#22'x'#255#8#21'w'#255#9#21'y'#255#7#20'v'#255
+ +#8#21'w'#255#8#24'u'#255#10#25's'#255#12#23'k'#255#12#21'`'#255#12#20'Y'#255
+ ,#13#18'R'#255#11#16'M'#255#10#16'K'#255#10#17'K'#255#10#16'K'#255#11#16'M'
+ +#255#10#15'M'#255#12#17'O'#255#12#17'M'#255#12#17'L'#255#11#16'L'#255#11#17
+ +'L'#255#9#15'J'#255#10#16'K'#255#12#17'L'#255#10#16'J'#255#12#16'K'#255#11#15
+ +'J'#255#12#15'I'#255#12#15'I'#255#13#15'I'#255#12#15'I'#255#12#17'J'#255#11
+ +#18'J'#255#9#15'F'#255#11#16'F'#255#10#16'F'#255#11#16'F'#255#9#15'E'#255#9
+ +#16'E'#255#12#17'G'#255#11#15'D'#255#11#15'C'#255#11#14'C'#255#12#15'F'#255
+ +#13#17'G'#255#14#19'A'#255#15#17'5'#255#8#10'"'#255#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#134#132'rVjww&TgtnBY|+ :m|'#17'(h'#218#9#30'h'#247#7#27'q'#253#8
+ +#28'v'#254#11#28'x'#255#9#26'y'#255#8#25'w'#255#9#25'x'#255#9#26'w'#255#8#25
+ +'u'#255#9#24'y'#255#10#24'y'#255#9#24'y'#255#11#25'{'#255#8#25'v'#255#8#25'v'
+ +#255#7#25'v'#255#8#26'x'#255#9#25'u'#255#8#24'u'#255#8#25'u'#255#8#25't'#255
+ +#8#22'p'#255#6#19'o'#255#10#25'w'#255#8#22'w'#255#10#23'y'#255#9#24'y'#255#8
+ +#22'w'#255#10#24'x'#255#8#24'w'#255#11#23'v'#255#11#24'v'#255#10#25'w'#255#8
+ +#23'x'#255#7#22'w'#255#6#24't'#255#6#25's'#255#5'!z'#255#29'g'#207#255'$u'
+ +#234#255'.'#128#233#255'"'#132#216#255'8'#140#216#255'7~'#176#255#3#30'2'#255
+ +#5#13#16#255#4#11#10#255#11#13#11#255#16#10#11#255#14#11#12#255#12#12#12#255
+ +#9#10#10#255#7#5#10#255#5#10#8#255#6#8#6#255#5#5#9#255#5#14#27#255#15'$;'#255
+ +'%Io'#255'3r'#171#255'<'#146#213#255'3'#141#234#255','#141#227#255'('#135#226
+ +#255'&'#131#230#255#30#127#230#255#29#130#232#255#24#128#231#255#25'~'#233
+ +#255#31#130#238#255#29#127#236#255#30#128#237#255#26'}'#233#255#30#127#235
+ +#255#29'}'#233#255' }'#234#255' }'#232#255#28'z'#231#255#31'~'#234#255' ~'
+ +#235#255#30#127#234#255#29#128#235#255#24'{'#232#255#25'}'#234#255#23'|'#232
+ +#255#26'|'#232#255#27'|'#234#255#26'x'#234#255#30'|'#239#255#28'{'#238#255#26
+ +'z'#234#255#23'z'#232#255#23'}'#232#255#26'~'#236#255#23'}'#231#255#25'{'#233
+ +#255#23'|'#236#255#26'|'#233#255#29'}'#235#255'!{'#233#255'4'#131#240#255#20
+ +'@'#157#255#3#30'n'#255#8#22'f'#255#12#23'g'#255#13#23'g'#255#14#20'e'#255#11
+ +#21'f'#255#12#23'f'#255#10#21'e'#255#12#23'g'#255#10#21'e'#255#11#22'e'#255
+ +#11#22'd'#255#11#22'd'#255#9#19'a'#255#11#21'c'#255#12#22'f'#255#9#20'd'#255
+ +#11#21'g'#255#11#20'h'#255#14#22'l'#255#10#18'h'#255#10#18'i'#255#10#19'i'
+ +#255#10#19'c'#255#11#21'd'#255#11#21'c'#255#11#21'b'#255#10#21'a'#255#9#20'_'
+ +#255#10#20'`'#255#7#17'\'#255#11#22'd'#255#8#19'b'#255#9#19'a'#255#10#20'a'
+ +#255#3#15']'#255#9#22'l'#255#8#21'n'#255#9#22's'#255#7#23'u'#255#5#21's'#255
+ +#8#23'w'#255#8#23'w'#255#8#23'w'#255#7#22'v'#255#8#23'x'#255#9#24'y'#255#7#21
+ +'w'#255#8#22'w'#255#7#20'w'#255#9#20'x'#255#10#22'y'#255#10#21'w'#255#10#21
+ +'u'#255#12#23'u'#255#8#18'm'#255#8#19'o'#255#11#21's'#255#10#22'v'#255#7#20
+ +'t'#255#9#22'w'#255#8#21'u'#255#9#21'v'#255#10#21'w'#255#9#20'w'#255#11#22'w'
+ +#255#9#20'u'#255#10#21'r'#255#11#22'm'#255#13#21'c'#255#12#20'['#255#15#18'T'
+ +#255#14#17'O'#255#14#17'L'#255#14#16'L'#255#13#16'L'#255#12#15'O'#255#13#15
+ +'R'#255#15#17'S'#255#13#18'Q'#255#12#17'P'#255#11#17'M'#255#13#18'N'#255#12
+ +#16'L'#255#14#17'M'#255#15#17'L'#255#12#15'J'#255#13#15'I'#255#14#16'J'#255
+ +#13#15'I'#255#14#16'I'#255#13#14'G'#255#12#14'H'#255#13#15'I'#255#12#17'K'
+ +#255#11#15'H'#255#12#15'H'#255#11#14'F'#255#12#15'G'#255#12#15'F'#255#13#16
+ +'F'#255#13#15'E'#255#12#14'D'#255#12#16'D'#255#10#14'E'#255#11#15'H'#255#10
+ +#16'G'#255#13#18'?'#255#19#22'8'#255#10#12'$'#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#215#214#195#5'lyz;Riy'#179'@Yzb'#24'-cz'#13'!a'#221#14#31'n'#251#8
+ +#27't'#253#9#27'x'#254#10#28'z'#255#9#26'y'#255#9#26'z'#255#9#25'y'#255#8#25
+ +'w'#255#8#25'v'#255#9#24'y'#255#9#25'y'#255#10#25'z'#255#9#24'y'#255#8#24'y'
+ +#255#10#26'z'#255#7#23'x'#255#8#24'x'#255#10#25'u'#255#10#25'u'#255#9#24't'
+ +#255#9#24't'#255#6#20'p'#255#9#21's'#255#8#23'w'#255#8#22'x'#255#8#24'z'#255
+ +#9#23'z'#255#8#22'x'#255#8#23'x'#255#9#23'w'#255#9#23'w'#255#10#23'w'#255#11
+ +#23'w'#255#10#22'v'#255#8#22'v'#255#7#23'w'#255#7#23'w'#255#4#19'n'#255#5''''
+ +#138#255#24'Y'#201#255'.'#128#237#255'(|'#221#255'2'#132#218#255'@'#144#202
+ +#255#11'0G'#255#4#18#29#255#10#22#23#255#12#17#17#255#12#13#18#255#14#16#20
+ +#255#10#16#15#255#13#17#17#255#16#14#19#255#8#11#15#255#9#11#17#255#4#11#15
+ +#255#4#16#16#255#4#14#9#255#4#10#13#255#0#4#19#255#11#21'*'#255#26'Ci'#255';'
+ +'w'#182#255'1'#131#217#255'1'#139#238#255','#130#234#255'&}'#235#255'${'#235
+ +#255' }'#236#255#27'{'#233#255#28'|'#234#255' '#127#237#255#26'y'#231#255'!|'
+ +#235#255'"z'#235#255'#z'#235#255'#w'#234#255'"u'#230#255'%y'#235#255'#z'#235
+ +#255'!z'#235#255' z'#236#255#31'z'#236#255#28'{'#236#255#26'{'#236#255#26'y'
+ +#233#255#29'{'#236#255#28'w'#237#255' x'#240#255' x'#240#255' x'#239#255#29
+ +'z'#236#255#30'{'#234#255#27'y'#236#255#28'x'#234#255#31'{'#238#255#28'z'#237
+ +#255#28'|'#237#255#30'z'#235#255'%v'#231#255'9'#132#246#255')Z'#192#255#9'%x'
+ ,#255#9#25'l'#255#10#20'l'#255#14#19'h'#255#13#20'f'#255#11#21'i'#255#15#21'g'
+ +#255#11#20'b'#255#12#22'd'#255#11#21'd'#255#13#22'f'#255#11#20'e'#255#13#23
+ +'g'#255#9#19'c'#255#11#21'f'#255#11#22'h'#255#11#23'i'#255#13#21'h'#255#12#20
+ +'g'#255#14#21'i'#255#11#18'f'#255#12#19'h'#255#12#19'h'#255#10#19'd'#255#12
+ +#21'e'#255#11#21'c'#255#11#21'c'#255#11#20'b'#255#12#21'a'#255#13#21'a'#255#9
+ +#18'['#255#11#20'b'#255#9#20'b'#255#10#20'b'#255#11#21'd'#255#5#16'`'#255#9
+ +#19'j'#255#11#22'o'#255#9#20'r'#255#8#21'w'#255#7#20'v'#255#8#21'w'#255#8#21
+ +'w'#255#8#21'w'#255#7#20'v'#255#9#21'x'#255#10#23'y'#255#9#20'v'#255#11#21'w'
+ +#255#10#21'y'#255#9#20'z'#255#10#20'y'#255#11#21'x'#255#11#20'v'#255#12#21't'
+ +#255#10#20'q'#255#10#20'r'#255#9#21't'#255#10#21'w'#255#8#19'x'#255#12#23'}'
+ +#255#9#20'y'#255#11#21'y'#255#10#20'y'#255#11#20'w'#255#14#23'y'#255#13#21'w'
+ +#255#13#23'v'#255#13#22'p'#255#15#22'h'#255#14#19'^'#255#15#17'U'#255#14#17
+ +'P'#255#15#16'M'#255#13#14'K'#255#12#13'L'#255#12#14'R'#255#13#15'V'#255#16
+ +#18'X'#255#17#19'X'#255#15#17'R'#255#14#16'N'#255#15#16'L'#255#14#14'K'#255
+ +#13#14'K'#255#13#14'J'#255#13#15'J'#255#13#15'I'#255#14#16'J'#255#13#16'J'
+ +#255#13#14'H'#255#14#15'G'#255#15#15'H'#255#14#16'J'#255#14#16'J'#255#13#15
+ +'I'#255#14#15'I'#255#12#13'E'#255#13#14'F'#255#14#15'G'#255#14#15'G'#255#12
+ +#14'C'#255#12#14'D'#255#12#15'E'#255#13#15'I'#255#15#15'L'#255#13#16'G'#255
+ +#16#18'@'#255#18#20'6'#255#9#9#31#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#171
+ +#170#156'-m}}kXp'#130#163';Y|'#197#22'.`'#152#6#24'['#215#13#27'j'#248#9#27
+ +'s'#253#11#29'y'#254#7#25'x'#255#8#26'{'#255#8#26'y'#255#9#27'z'#255#9#26'z'
+ +#255#10#27'x'#255#8#26'v'#255#9#27'y'#255#9#26'y'#255#7#24'w'#255#8#24'z'#255
+ +#9#25'{'#255#7#23'x'#255#8#24'x'#255#9#24'u'#255#11#26'v'#255#10#24't'#255#8
+ +#23'q'#255#4#20'p'#255#8#24'u'#255#6#23'w'#255#7#23'x'#255#8#24'|'#255#6#21
+ +'y'#255#7#24'y'#255#7#24'x'#255#8#24'x'#255#8#23'w'#255#9#23'w'#255#10#23'w'
+ +#255#8#22'v'#255#8#23'w'#255#9#23'x'#255#7#23'x'#255#10#25'x'#255#9#21'o'#255
+ +#6'%'#132#255#30'Z'#196#255'(~'#225#255'+'#131#217#255'.'#145#206#255'/m'#150
+ +#255#5' /'#255#7#19#24#255#14#17#18#255#13#16#22#255#7#13#23#255#12#16#24#255
+ +#17#20#28#255#12#17#29#255#27'$('#255'1:>'#255#23' "'#255#2#11#11#255#0#6#4
+ +#255#4#10#7#255#4#13#13#255#10#21#22#255#2#14#15#255#5#11#22#255#18'"E'#255
+ +'*]'#156#255'+~'#208#255'/'#137#225#255'$'#128#222#255'!'#132#234#255#28'~'
+ +#227#255#27'}'#226#255#28#127#230#255#26'|'#228#255#31'}'#232#255'!|'#233#255
+ +'"z'#232#255'%z'#235#255'$z'#232#255'#z'#232#255'$|'#234#255'!{'#233#255#31
+ +'{'#233#255#31'~'#235#255#29'~'#234#255#27'}'#233#255#26'}'#234#255#26'}'#236
+ +#255#27'z'#236#255#28'y'#237#255#29'x'#236#255#28'y'#236#255#28'z'#236#255#28
+ +'|'#236#255#26'|'#235#255#27'{'#233#255#27'{'#233#255#24'{'#233#255#22'{'#232
+ +#255#23'y'#231#255#30'x'#230#255'%{'#232#255'*c'#205#255#0'#|'#255#9#28'p'
+ +#255#8#22'l'#255#10#20'f'#255#10#21'd'#255#10#21'f'#255#13#20'd'#255#11#21'c'
+ +#255#11#22'd'#255#9#19'a'#255#10#22'd'#255#8#19'c'#255#12#23'g'#255#9#21'e'
+ +#255#9#21'g'#255#9#21'g'#255#10#21'g'#255#9#20'f'#255#11#19'e'#255#12#20'f'
+ +#255#10#18'd'#255#11#20'e'#255#8#19'd'#255#9#18'b'#255#11#21'c'#255#10#20'b'
+ +#255#10#20'b'#255#11#19'b'#255#13#21'b'#255#12#20'a'#255#9#17'\'#255#8#19'a'
+ +#255#8#20'b'#255#7#19'b'#255#10#21'f'#255#7#19'e'#255#6#19'i'#255#10#24'p'
+ +#255#8#21's'#255#9#22'v'#255#9#23'w'#255#7#21'u'#255#9#23'v'#255#9#23'w'#255
+ +#9#23'v'#255#8#22'v'#255#9#23'w'#255#9#22'v'#255#8#22'w'#255#9#21'x'#255#8#22
+ +'y'#255#8#21'x'#255#9#23'w'#255#10#23'u'#255#10#22's'#255#5#17'l'#255#7#20'n'
+ +#255#9#22's'#255#10#23'x'#255#6#21'w'#255#9#23'z'#255#7#21'x'#255#7#22'y'#255
+ +#10#22'y'#255#10#22'x'#255#10#22'w'#255#10#23'w'#255#10#22't'#255#10#22'q'
+ +#255#14#23'k'#255#14#21'b'#255#12#17'X'#255#14#17'S'#255#14#15'P'#255#13#15
+ +'L'#255#12#15'N'#255#10#15'R'#255#11#16'W'#255#13#18'Z'#255#15#18'Z'#255#14
+ +#18'U'#255#13#16'N'#255#15#16'L'#255#16#16'L'#255#14#15'K'#255#12#16'K'#255
+ +#11#15'J'#255#12#15'I'#255#13#15'I'#255#12#14'H'#255#12#14'H'#255#14#15'H'
+ +#255#13#15'F'#255#12#15'F'#255#13#17'G'#255#13#15'F'#255#14#15'F'#255#11#12
+ +'C'#255#12#13'E'#255#13#14'F'#255#15#16'H'#255#12#13'E'#255#12#13'E'#255#13
+ +#14'G'#255#13#14'J'#255#15#15'K'#255#12#16'G'#255#14#16'@'#255#19#20'6'#255
+ +#13#13'#'#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#128#143#139#15'_y'
+ +#139'_9['#128#201#24'5f'#230#3#21'Y'#229#12#27'k'#248#8#25'r'#254#10#27'y'
+ +#255#6#25'y'#255#7#26'}'#255#9#27'z'#255#7#27'z'#255#7#27'z'#255#8#26'w'#255
+ +#7#25'v'#255#9#27'x'#255#7#25'v'#255#7#25'w'#255#9#27'z'#255#9#27'y'#255#7#24
+ +'v'#255#9#27'w'#255#8#23'r'#255#10#27'r'#255#10#24'p'#255#7#21'l'#255#5#23'q'
+ +#255#6#25't'#255#8#26'x'#255#6#24'x'#255#6#23'y'#255#6#24'y'#255#7#25'y'#255
+ +#7#25'x'#255#7#25'x'#255#6#23'w'#255#7#24'v'#255#6#24'u'#255#7#25'u'#255#7#25
+ ,'u'#255#7#25't'#255#6#23's'#255#4#26's'#255#5#28'l'#255#5#24'h'#255#6#29'p'
+ +#255#3'D'#140#255'''v'#185#255'0'#141#205#255'E'#147#205#255'0c'#136#255#0#26
+ +'/'#255#9#15#23#255#12#16#23#255#7#15#29#255#11#12#27#255#29' /'#255'"0A'#255
+ +'Pdy'#255#186#217#235#255#178#215#228#255#150#185#191#255't'#151#150#255'Ba_'
+ +#255#22')%'#255#0#6#5#255#0#6#11#255#6#9#18#255#7#4#19#255#6#6#25#255#14'*P'
+ +#255':y'#185#255'+'#134#219#255'$'#133#224#255#30#128#223#255#26'~'#220#255
+ +#29#130#226#255#25#127#225#255#26#127#225#255#27#128#229#255#31#127#228#255
+ +'"~'#230#255' }'#227#255#28'z'#223#255#30'~'#228#255#25'{'#226#255#27#127#233
+ +#255#28#127#235#255#25#127#235#255#23'~'#234#255#25#128#236#255#24#128#235
+ +#255#23'}'#233#255#26'|'#234#255#24'|'#232#255#24#127#234#255#22#128#233#255
+ +#22#129#234#255#20#128#232#255#22#128#231#255#21#127#232#255#21#129#234#255
+ +#17'~'#231#255#19#128#229#255#29#130#233#255#31#127#230#255'-v'#218#255#4'3'
+ +#138#255#5#30'o'#255#6#25'n'#255#10#23'e'#255#6#23'b'#255#5#21'd'#255#12#22
+ +'c'#255#11#23'd'#255#10#22'd'#255#8#20'b'#255#9#22'd'#255#10#22'd'#255#8#21
+ +'c'#255#8#21'd'#255#9#22'd'#255#9#21'f'#255#10#21'f'#255#8#19'c'#255#13#22'f'
+ +#255#11#21'c'#255#10#21'b'#255#10#21'c'#255#8#20'b'#255#7#20'`'#255#11#23'c'
+ +#255#9#21'c'#255#10#21'c'#255#7#18'`'#255#10#21'c'#255#8#20'`'#255#7#18']'
+ +#255#8#20'a'#255#8#21'b'#255#8#20'b'#255#9#21'g'#255#8#20'e'#255#6#18'h'#255
+ +#9#23'n'#255#8#22'r'#255#6#22's'#255#7#23't'#255#6#22's'#255#6#22's'#255#8#24
+ +'u'#255#7#23't'#255#7#23't'#255#8#24'u'#255#9#24'u'#255#8#23's'#255#6#23'v'
+ +#255#6#22'v'#255#5#23'u'#255#7#25'u'#255#6#24'r'#255#8#25't'#255#5#20'l'#255
+ +#6#22'l'#255#7#23'p'#255#6#23'u'#255#5#22'v'#255#7#24'x'#255#7#23'x'#255#7#23
+ +'w'#255#7#23'x'#255#6#23'x'#255#5#23'v'#255#6#23'u'#255#6#23't'#255#6#23'q'
+ +#255#11#24'l'#255#12#22'e'#255#10#19'Z'#255#10#18'S'#255#11#15'N'#255#12#16
+ +'L'#255#9#16'N'#255#8#18'U'#255#9#19'['#255#10#20']'#255#10#20'['#255#9#19'W'
+ +#255#9#17'P'#255#12#17'L'#255#14#16'K'#255#12#16'K'#255#11#16'K'#255#10#18'K'
+ +#255#10#16'I'#255#11#16'J'#255#11#16'J'#255#11#16'J'#255#11#16'H'#255#10#15
+ +'F'#255#11#16'F'#255#13#17'D'#255#13#17'D'#255#12#16'B'#255#11#14'B'#255#13
+ +#17'F'#255#12#15'F'#255#14#17'H'#255#11#13'G'#255#12#13'H'#255#12#15'J'#255
+ +#12#13'I'#255#11#14'I'#255#12#17'I'#255#13#17'?'#255#16#19'3'#255#8#11#31#255
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#248#188#0#0'4X'#138'y'
+ +#28'=u'#237#4#27'c'#250#10#27'n'#252#9#25'v'#253#7#26'x'#255#8#27'z'#255#7#26
+ +'y'#255#6#24'z'#255#6#26'y'#255#7#27'z'#255#7#28'y'#255#6#25'w'#255#8#27'y'
+ +#255#7#26'x'#255#7#26'x'#255#8#25'v'#255#9#26'w'#255#8#26'u'#255#8#25'r'#255
+ +#8#25'o'#255#9#26'n'#255#8#23'l'#255#6#21'j'#255#6#24's'#255#7#25't'#255#7#24
+ +'u'#255#5#24'w'#255#6#25'x'#255#7#26'y'#255#7#25'x'#255#7#25'w'#255#6#25'x'
+ +#255#3#24'v'#255#5#25'u'#255#7#24'u'#255#10#23't'#255#7#26's'#255#6#23'p'#255
+ +#4#24'o'#255#3#25'p'#255#5#27'k'#255#1#24'a'#255#6#29'`'#255#4'!\'#255#7'1h'
+ +#255#11'L'#134#255'3{'#185#255'Z'#161#215#255'It'#157#255#23'&='#255#5#15#24
+ +#255#0#14#19#255#6#15#22#255#13#16#24#255#30' ,'#255'PRh'#255#175#186#201#255
+ +#172#194#206#255#180#207#215#255#186#219#227#255#191#231#238#255#175#218#224
+ +#255#132#171#179#255'Mhw'#255#21'(+'#255#3#7#17#255#3#9#18#255#5#4#18#255#3
+ +#10'#'#255#20'9d'#255',y'#193#255'-'#135#223#255'#}'#219#255'!'#130#225#255
+ +#27#131#228#255#28#127#225#255#29'}'#224#255#27'~'#225#255'"'#127#228#255#31
+ +'}'#226#255#28'z'#224#255#27'{'#227#255#24'x'#226#255#26'|'#232#255#27'|'#233
+ +#255#27'{'#235#255#24'{'#236#255#25'{'#236#255#26'|'#237#255#27'}'#237#255#28
+ +'|'#236#255#24'}'#234#255#25#127#234#255#23#127#233#255#21'~'#233#255#20#127
+ +#233#255#21'~'#233#255#20'~'#232#255#21'~'#233#255#23#129#236#255#19'}'#232
+ +#255#24'}'#230#255' '#130#235#255'"v'#222#255#12'B'#159#255#5'#u'#255#6#27'n'
+ +#255#5#22'i'#255#5#22'e'#255#6#21'e'#255#11#21'f'#255#8#23'e'#255#10#23'f'
+ +#255#8#21'd'#255#11#24'f'#255#11#23'f'#255#7#20'b'#255#7#20'b'#255#9#22'c'
+ +#255#8#21'e'#255#10#21'f'#255#11#22'g'#255#10#21'e'#255#9#20'd'#255#10#20'd'
+ +#255#10#20'c'#255#11#22'd'#255#7#21'b'#255#10#23'c'#255#8#20'b'#255#6#19'a'
+ +#255#7#20'b'#255#8#21'b'#255#7#19'a'#255#6#19'`'#255#9#21'b'#255#9#21'c'#255
+ +#8#20'c'#255#9#22'f'#255#7#20'f'#255#4#18'e'#255#6#20'l'#255#7#23'r'#255#6#22
+ +'t'#255#6#22'u'#255#7#23'w'#255#5#22'v'#255#7#23'x'#255#5#22'w'#255#7#23'x'
+ +#255#7#23'w'#255#7#24't'#255#6#23'r'#255#7#24't'#255#4#22't'#255#4#22't'#255
+ +#6#23't'#255#7#24'r'#255#8#25's'#255#6#22'n'#255#6#21'o'#255#7#24't'#255#6#22
+ +'w'#255#6#21'x'#255#8#22'y'#255#7#23'y'#255#7#23'z'#255#6#23'y'#255#5#23'w'
+ +#255#5#22'w'#255#7#24'w'#255#5#23't'#255#5#23's'#255#10#23'n'#255#10#22'f'
+ +#255#8#20'Z'#255#9#18'S'#255#9#15'O'#255#9#16'N'#255#8#17'N'#255#8#17'T'#255
+ +#7#18'Y'#255#9#20'\'#255#8#21']'#255#8#21'Y'#255#8#18'R'#255#9#18'L'#255#12
+ +#16'K'#255#12#16'K'#255#12#17'L'#255#12#18'K'#255#9#16'I'#255#9#16'I'#255#9
+ ,#16'I'#255#9#16'I'#255#9#16'H'#255#10#16'H'#255#10#16'F'#255#11#17'D'#255#12
+ +#19'D'#255#9#16'B'#255#8#15'B'#255#12#18'G'#255#11#16'E'#255#12#16'F'#255#10
+ +#14'E'#255#10#13'H'#255#12#15'I'#255#11#15'J'#255#12#14'I'#255#13#17'I'#255
+ +#14#19'A'#255#17#21'5'#255#10#14'!'#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#18'8w>'#22'8z'#230#12'$s'#252#7#26's'#253#8#26'x'#254
+ +#8#28'y'#254#8#26'z'#255#7#24'y'#255#9#26'z'#255#9#25'y'#255#8#25'x'#255#9#26
+ +'z'#255#10#27'z'#255#9#26'y'#255#8#25'y'#255#10#27'z'#255#8#25'v'#255#9#25'v'
+ +#255#9#25'u'#255#9#24'q'#255#10#25'n'#255#11#27'm'#255#6#21'k'#255#8#23'm'
+ +#255#7#24'u'#255#7#24't'#255#7#23'v'#255#7#22'v'#255#7#24'x'#255#7#24'x'#255
+ +#7#24'w'#255#7#24'w'#255#8#24'y'#255#9#24'z'#255#7#22'w'#255#7#24'y'#255#3#22
+ +'w'#255#6#24'u'#255#4#25'p'#255#6#25'o'#255#8#23'd'#255#2'#v'#255#24'S'#174
+ +#255#20'e'#199#255#27'o'#200#255#31'd'#173#255#14'0g'#255#6#15'8'#255#4#31'G'
+ +#255'+Xu'#255'@s'#138#255'%EX'#255#15#25','#255#14#11#31#255#14#11#25#255#13
+ +#10#22#255'''$2'#255#172#172#188#255#183#186#204#255#186#197#209#255#183#203
+ +#209#255#177#207#212#255#171#204#218#255#177#213#231#255#176#219#250#255#181
+ +#218#244#255'_z'#164#255#27'2Q'#255#4#12'"'#255#13#7#28#255#2#1#19#255#5#20
+ +'8'#255'$U'#138#255'3'#128#201#255'%'#132#225#255''''#130#219#255'!'#128#218
+ +#255#30#128#226#255#29'{'#229#255'!~'#232#255#29'~'#230#255#29#127#230#255#30
+ +#128#232#255#24'{'#230#255#24'{'#231#255#25'|'#233#255#25'{'#233#255#26'{'
+ +#234#255#28'z'#235#255#27'|'#237#255#25'z'#235#255#26'|'#234#255#27'}'#235
+ +#255#26'~'#236#255#23'{'#231#255#26'|'#232#255#22'}'#232#255#24'~'#234#255#24
+ +'~'#235#255#22'|'#234#255#20'|'#236#255#21'|'#234#255#25'{'#234#255#26'{'#235
+ +#255'!{'#232#255#23'V'#187#255#8'*'#128#255#10#28'o'#255#10#26'k'#255#9#24'e'
+ +#255#7#21'c'#255#11#22'g'#255#9#20'c'#255#9#21'd'#255#8#20'c'#255#10#20'd'
+ +#255#11#21'e'#255#8#20'c'#255#9#21'c'#255#9#22'c'#255#9#21'd'#255#9#21'f'#255
+ +#10#22'h'#255#9#20'f'#255#8#20'e'#255#11#22'f'#255#11#21'c'#255#11#21'c'#255
+ +#10#21'c'#255#9#20'b'#255#7#19'a'#255#8#20'b'#255#7#20'b'#255#10#22'd'#255#7
+ +#19'a'#255#7#18'`'#255#11#20'b'#255#9#19'c'#255#9#20'e'#255#9#21'g'#255#7#19
+ +'e'#255#5#16'd'#255#8#21'm'#255#6#22'q'#255#7#22's'#255#7#23's'#255#6#23'u'
+ +#255#6#22'w'#255#6#23'w'#255#5#21'v'#255#5#22'v'#255#6#21'u'#255#8#22's'#255
+ +#6#23's'#255#7#24't'#255#5#21'u'#255#7#23'x'#255#7#24'u'#255#9#24't'#255#8#23
+ +'s'#255#6#20'n'#255#7#20'o'#255#7#23't'#255#6#22'u'#255#7#21'v'#255#9#21'w'
+ +#255#5#19'u'#255#6#22'w'#255#6#22'w'#255#5#21'v'#255#7#23'w'#255#6#22'w'#255
+ +#5#22't'#255#5#23's'#255#10#24'p'#255#9#22'f'#255#7#21'\'#255#9#18'U'#255#11
+ +#16'Q'#255#9#17'P'#255#8#16'S'#255#8#16'Y'#255#9#20']'#255#11#21'a'#255#12#23
+ +'a'#255#12#20']'#255#11#20'U'#255#11#19'O'#255#13#16'L'#255#14#17'L'#255#13
+ +#16'J'#255#12#17'I'#255#10#15'G'#255#10#14'H'#255#11#15'I'#255#11#15'I'#255
+ +#11#15'I'#255#10#15'G'#255#11#17'F'#255#11#18'E'#255#12#17'C'#255#10#14'@'
+ +#255#10#14'B'#255#13#17'E'#255#12#15'C'#255#13#16'C'#255#11#15'C'#255#12#13
+ +'I'#255#11#13'H'#255#13#14'J'#255#14#14'J'#255#13#14'H'#255#16#18'A'#255#17
+ +#19'6'#255#8#10' '#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0'"G'#134#142#11'+t'#229#17'+'#129#253#10' ~'#254#6#25'z'#255#10#28'{'
+ +#255#9#27'z'#255#10#26'z'#255#11#26'z'#255#10#25'y'#255#9#24'x'#255#8#23'w'
+ +#255#8#23'w'#255#9#24'x'#255#8#23'w'#255#9#24'x'#255#7#25't'#255#10#24'u'#255
+ +#12#24't'#255#10#22'n'#255#9#24'k'#255#10#25'm'#255#3#17'j'#255#6#23'p'#255#7
+ +#23'w'#255#6#22'w'#255#7#23'w'#255#7#23'w'#255#8#23'w'#255#9#24'x'#255#9#23
+ +'w'#255#9#23'w'#255#4#24'r'#255#12#24'v'#255#10#22'u'#255#5#24'v'#255#4#25's'
+ +#255#9#25'q'#255#6#24'p'#255#8#28'v'#255#2'='#159#255#25'g'#211#255#29'~'#239
+ +#255#29#127#235#255#30'~'#235#255'#'#130#240#255''''#137#239#255#30#127#215
+ +#255#29'g'#183#255#20'F'#140#255#16'.d'#255#10#31'A'#255#3#16''''#255#7#6#22
+ +#255#5#7#19#255#4#9#17#255#6#11#24#255'er'#134#255#172#194#221#255#169#193
+ +#217#255#172#193#209#255#177#200#217#255#170#197#227#255#163#196#240#255#161
+ +#194#245#255#155#185#250#255'_{'#208#255'Ob'#186#255'>G'#142#255#23#28'K'#255
+ +#9#10'#'#255#7#5#21#255#4#4#24#255#8' G'#255#29'['#158#255'''~'#215#255#27'v'
+ +#222#255'"{'#226#255#30'x'#227#255#31'{'#232#255#31'|'#230#255#30'{'#229#255
+ +#28'{'#230#255#28'|'#232#255#31#127#235#255#30'~'#234#255#28'|'#232#255#29'z'
+ +#232#255#26'w'#230#255#29'|'#234#255#27'{'#233#255#29'}'#235#255#30#127#237
+ +#255#29'~'#236#255#25'{'#232#255#27'}'#233#255#27'}'#235#255#27'{'#233#255#26
+ +'y'#234#255#25'z'#234#255#24'{'#237#255#26'{'#239#255#24'x'#236#255#26'z'#238
+ +#255#23's'#230#255#25'c'#210#255#14'@'#162#255#3#30't'#255#13#27'h'#255#12#24
+ +'e'#255#7#21'c'#255#8#20'f'#255#11#20'f'#255#11#20'c'#255#12#21'e'#255#12#20
+ +'d'#255#11#19'c'#255#12#21'd'#255#11#22'd'#255#10#22'c'#255#10#21'e'#255#9#20
+ ,'d'#255#9#20'e'#255#9#21'g'#255#11#20'd'#255#12#21'e'#255#10#21'c'#255#11#20
+ +'c'#255#12#19'`'#255#9#18'_'#255#9#19'a'#255#12#22'd'#255#9#20'b'#255#10#21
+ +'c'#255#8#18'`'#255#10#17'`'#255#12#19'b'#255#9#18'c'#255#9#19'f'#255#9#20'f'
+ +#255#10#21'g'#255#6#18'd'#255#6#18'i'#255#9#23'q'#255#8#23't'#255#7#22'r'#255
+ +#8#23't'#255#8#23's'#255#8#23't'#255#10#25'u'#255#9#23'w'#255#8#22'v'#255#8
+ +#23't'#255#8#23'u'#255#7#22'w'#255#6#21'v'#255#6#22'w'#255#7#21'v'#255#8#22
+ +'s'#255#8#22'r'#255#8#18'm'#255#7#17'l'#255#10#23't'#255#10#23'w'#255#9#20'v'
+ +#255#11#21'w'#255#10#21'v'#255#8#22'v'#255#5#22's'#255#6#23't'#255#9#24'u'
+ +#255#9#23'v'#255#7#22't'#255#7#23't'#255#12#23'o'#255#11#22'i'#255#11#21'`'
+ +#255#11#18'X'#255#10#15'T'#255#10#16'T'#255#8#13'T'#255#8#15'['#255#8#17'`'
+ +#255#11#20'f'#255#13#23'f'#255#11#19'_'#255#11#17'X'#255#12#18'R'#255#14#16
+ +'L'#255#15#15'L'#255#14#14'J'#255#15#16'J'#255#11#15'I'#255#11#15'I'#255#10
+ +#14'H'#255#10#14'H'#255#11#15'I'#255#12#15'G'#255#15#18'H'#255#14#18'G'#255
+ +#13#16'C'#255#11#15'@'#255#12#14'C'#255#14#15'E'#255#13#15'D'#255#11#14'A'
+ +#255#12#14'B'#255#15#14'I'#255#13#13'H'#255#13#14'J'#255#13#13'I'#255#12#13
+ +'G'#255#15#16'B'#255#20#20':'#255#12#14'%'#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#29';z'#172#4'"i'#255#13'('#127#255#12'%'#132
+ +#254#8#27'{'#255#9#26'y'#255#9#26'x'#255#10#26'y'#255#11#25'y'#255#12#26'z'
+ +#255#10#24'x'#255#10#24'x'#255#10#24'x'#255#11#25'y'#255#12#26'z'#255#10#24
+ +'x'#255#11#25'u'#255#14#26't'#255#14#24'q'#255#12#21'm'#255#13#24'l'#255#9#22
+ +'j'#255#7#20'n'#255#8#23't'#255#6#23'x'#255#7#24'y'#255#8#24'y'#255#8#24'y'
+ +#255#8#23'w'#255#8#23'w'#255#9#23'w'#255#9#23'w'#255#4#26'q'#255#14#25'v'#255
+ +#10#24't'#255#6#27's'#255#5#24'o'#255#6#25'q'#255#2''''#136#255#19'K'#179#255
+ +#22's'#227#255'!{'#236#255'"z'#232#255#27'{'#232#255#22'z'#226#255#25#127#229
+ +#255#25#128#227#255#29#129#227#255#29'~'#236#255'&'#138#241#255'('#140#231
+ +#255'0'#135#212#255'/{'#187#255'%i'#155#255#25'Ch'#255#13#27'<'#255#3#7#25
+ +#255#17#30'6'#255'Mk'#138#255#138#171#204#255#160#196#225#255#180#212#241#255
+ +#180#215#248#255#172#213#248#255#171#202#255#255'v'#136#226#255'FN'#190#255
+ +'WV'#205#255'SU'#196#255'V^'#176#255'>F'#135#255#16'!C'#255#4#5#21#255#2#1#16
+ +#255#2#10'('#255#24'I'#137#255'-q'#205#255'(z'#218#255' y'#220#255#31'x'#227
+ +#255#29'w'#228#255' {'#231#255#31'y'#231#255#29'y'#230#255' }'#233#255'!{'
+ +#232#255'!{'#232#255'"{'#232#255#28'z'#231#255'!~'#235#255#30'}'#234#255#29
+ +'|'#234#255#27'z'#231#255#27'{'#233#255#27'y'#231#255#29'{'#233#255#27'z'#231
+ +#255' {'#235#255#31'{'#234#255#29'{'#235#255#24'x'#234#255#23'{'#239#255#23
+ +'y'#239#255#20'v'#237#255#15'l'#221#255#16'e'#211#255#20'X'#191#255#8'1'#138
+ +#255#8#30'm'#255#8#23'h'#255#9#22'h'#255#11#21'f'#255#12#20'g'#255#11#19'f'
+ +#255#10#19'c'#255#12#20'd'#255#12#19'b'#255#12#22'd'#255#11#22'c'#255#11#21
+ +'d'#255#12#22'f'#255#9#19'c'#255#11#20'd'#255#11#19'c'#255#9#19'c'#255#12#19
+ +'c'#255#13#20'c'#255#11#18'a'#255#10#18'_'#255#10#19'`'#255#10#19'a'#255#11
+ +#21'c'#255#10#20'b'#255#9#19'a'#255#10#18'b'#255#10#17'c'#255#12#19'c'#255#11
+ +#19'f'#255#9#20'f'#255#10#21'g'#255#8#19'e'#255#7#19'd'#255#8#21'k'#255#6#22
+ +'o'#255#6#21'u'#255#8#24'v'#255#8#22'u'#255#7#22's'#255#8#23't'#255#8#22'u'
+ +#255#10#23'w'#255#7#22'v'#255#8#22'v'#255#10#23'x'#255#8#21'w'#255#8#21'w'
+ +#255#9#21'w'#255#8#21'v'#255#10#22't'#255#10#23't'#255#10#21'n'#255#6#17'j'
+ +#255#9#23's'#255#11#24'x'#255#9#21'v'#255#11#22'w'#255#13#24'x'#255#8#23'w'
+ +#255#6#21'w'#255#7#22'w'#255#8#21'w'#255#8#21'w'#255#9#22'x'#255#8#22'v'#255
+ +#10#22'p'#255#12#22'k'#255#14#22'b'#255#12#18'['#255#13#16'W'#255#10#16'T'
+ +#255#8#16'U'#255#8#16']'#255#8#18'e'#255#9#19'j'#255#14#21'k'#255#13#19'c'
+ +#255#12#18'\'#255#13#18'V'#255#13#15'O'#255#14#16'O'#255#13#16'K'#255#14#17
+ +'M'#255#13#17'L'#255#12#16'K'#255#11#15'J'#255#11#13'I'#255#13#15'I'#255#14
+ +#15'H'#255#13#15'F'#255#13#15'E'#255#12#15'B'#255#12#16'A'#255#12#15'D'#255
+ +#13#15'E'#255#13#15'C'#255#11#14'A'#255#11#14'B'#255#16#15'K'#255#13#13'H'
+ +#255#14#15'K'#255#12#13'J'#255#11#13'F'#255#16#16'@'#255#17#18'5'#255#10#10
+ +' '#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#30'9y'#201
+ +#11'''n'#255#3#28'n'#255#15'%'#128#255#8' }'#255#6#26'x'#255#9#25'v'#255#9#26
+ +'w'#255#9#25'v'#255#10#26'w'#255#8#23'v'#255#10#25'y'#255#9#24'x'#255#9#24'x'
+ +#255#10#25'y'#255#10#25'w'#255#10#24't'#255#13#25'r'#255#13#23'm'#255#11#21
+ +'k'#255#12#25'l'#255#5#17'h'#255#7#21'r'#255#9#24'v'#255#7#24'y'#255#7#24'y'
+ +#255#8#25'z'#255#8#25'x'#255#7#23'x'#255#7#23'w'#255#9#23'x'#255#9#24'v'#255
+ +#5#24'r'#255#14#24'z'#255#5#24'v'#255#3#28's'#255#7#26'r'#255#4'('#136#255#18
+ +'['#196#255#15'p'#221#255#28'|'#229#255#28'~'#229#255#25'|'#229#255#21'z'#230
+ +#255#22'w'#230#255#31'|'#233#255#30'|'#232#255#23'y'#234#255#30#127#224#255
+ ,#29'~'#228#255#31'y'#222#255'#'#127#220#255'%'#132#224#255'4'#143#229#255#24
+ +']'#175#255#22'o'#190#255'/|'#205#255#27'c'#168#255#14'M'#130#255#2'/T'#255#0
+ +#29':'#255#22'/Q'#255'/Lv'#255'Fg'#153#255'Y'#129#193#255'E]'#181#255'EU'#189
+ +#255'HQ'#199#255'KR'#191#255'UT'#176#255'WV'#160#255'T`'#142#255':Sg'#255#9
+ +#29','#255#8#2#21#255#7#7' '#255#13'8f'#255'&x'#196#255',}'#226#255'"|'#225
+ +#255#30'w'#230#255#30'{'#228#255#23'{'#226#255#25'|'#232#255#31#127#234#255
+ +'"'#128#231#255'!~'#230#255#30'{'#232#255#29'|'#230#255#29'}'#232#255#29'|'
+ +#233#255#28'}'#233#255#25'z'#230#255#28'{'#232#255#29'|'#232#255' '#127#234
+ +#255#26'{'#229#255#30'~'#233#255#29'|'#232#255#30#127#235#255#23'|'#232#255
+ +#20'z'#235#255#17'x'#237#255#19'z'#241#255#18'l'#220#255#11'd'#211#255#18'b'
+ +#205#255#19'H'#166#255#6'!v'#255#5#23'f'#255#8#24'h'#255#9#20'b'#255#13#21'f'
+ +#255#12#20'f'#255#10#18'd'#255#11#19'c'#255#11#19'b'#255#12#21'e'#255#9#19'd'
+ +#255#10#20'd'#255#11#22'e'#255#10#21'd'#255#10#21'd'#255#12#22'e'#255#12#20
+ +'c'#255#13#21'c'#255#11#20'a'#255#9#18'^'#255#7#18'_'#255#10#21'c'#255#10#21
+ +'c'#255#8#20'b'#255#9#21'c'#255#8#18'a'#255#10#18'b'#255#10#19'd'#255#9#19'e'
+ +#255#10#19'f'#255#9#18'e'#255#10#20'e'#255#8#20'd'#255#7#18'e'#255#5#17'h'
+ +#255#6#22'o'#255#6#22't'#255#10#25'x'#255#7#22't'#255#9#24'v'#255#9#23'v'#255
+ +#8#22'v'#255#7#23'x'#255#7#23'x'#255#9#21'v'#255#10#21'w'#255#9#21'w'#255#8
+ +#21'v'#255#9#22'w'#255#9#22'u'#255#8#21's'#255#10#23't'#255#10#22'o'#255#7#19
+ +'k'#255#8#22'p'#255#8#22'v'#255#9#22'w'#255#8#22'v'#255#7#22'w'#255#7#22'v'
+ +#255#7#21'w'#255#8#23'x'#255#9#22'w'#255#9#21'w'#255#8#22'y'#255#6#20'u'#255
+ +#10#22's'#255#13#23'm'#255#12#19'b'#255#11#18'['#255#12#14'W'#255#10#14'U'
+ +#255#9#15'U'#255#8#16']'#255#8#20'd'#255#11#21'i'#255#11#22'k'#255#10#20'e'
+ +#255#11#17']'#255#11#16'V'#255#12#16'P'#255#12#16'N'#255#12#16'K'#255#15#17
+ +'M'#255#11#15'J'#255#12#16'K'#255#11#15'I'#255#11#14'I'#255#13#16'I'#255#13
+ +#15'G'#255#12#15'E'#255#13#16'E'#255#11#14'B'#255#11#15'B'#255#11#15'C'#255
+ +#11#14'C'#255#12#15'C'#255#10#14'B'#255#12#15'D'#255#13#15'I'#255#12#14'H'
+ +#255#14#14'J'#255#13#14'I'#255#13#15'F'#255#16#17'A'#255#19#21'6'#255#13#14
+ +'"'#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#137#145#158#0#0#0#0#0'g'#128#160#26#0#0#0
+ +#0#16'.o'#177#6'$k'#255#6#27'j'#255#12#30'v'#255#6'"}'#255#2#28'x'#255#9#26
+ +'v'#255#9#25't'#255#7#26'v'#255#10#28'w'#255#7#24'v'#255#9#26'y'#255#9#27'z'
+ +#255#9#26'y'#255#9#26'w'#255#9#25'u'#255#7#25'r'#255#11#27'r'#255#13#24'k'
+ +#255#10#22'j'#255#10#24'm'#255#6#22'o'#255#6#23'u'#255#10#26'z'#255#6#25'w'
+ +#255#7#25'x'#255#8#26'x'#255#7#25'w'#255#6#23'v'#255#8#25'u'#255#7#24'u'#255
+ +#7#24't'#255#11#24'v'#255#0#27's'#255#1#25'o'#255#3#25'r'#255#8'3'#146#255#19
+ +'c'#197#255#30'|'#225#255#22'z'#227#255#25'}'#225#255#26'~'#226#255#25'}'#226
+ +#255#24'|'#225#255#28#128#231#255#28#129#231#255#24'~'#226#255#24#127#228#255
+ +#29'}'#226#255#29#130#233#255#30'}'#222#255#31'~'#218#255'('#135#227#255#23
+ +'a'#179#255#2'H'#155#255#30'x'#214#255#30#137#222#255#31#133#224#255'*'#138
+ +#234#255')'#140#235#255'"'#138#227#255'"'#131#209#255#27'e'#170#255#12'<}'
+ +#255#15',c'#255#0#12'A'#255#8#10'D'#255#14#21'X'#255#23'#r'#255'+;'#134#255
+ +'7O'#143#255'<^'#144#255#136#172#208#255#169#206#231#255''#255#16#20'3'#255#7#10' '#255'ogn1zv|'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#142#152
+ +#168'fl'#134#173'%'#0#0#0#0#8'&j'#173#10'*p'#255#6#27'j'#255#8#28'p'#255#12
+ +'('#128#255#5' z'#255#9#27'v'#255#7#28'u'#255#10#28'x'#255#10#28'y'#255#7#27
+ +'{'#255#7#28'{'#255#8#28'{'#255#10#28'y'#255#8#27'v'#255#7#26'u'#255#8#29'r'
+ +#255#10#30'p'#255#8#22'h'#255#8#22'i'#255#6#23'n'#255#7#25't'#255#6#26'y'#255
+ +#7#26'{'#255#7#27'w'#255#6#24'u'#255#6#24'u'#255#8#25'v'#255#7#25't'#255#7#26
+ +'t'#255#7#26'u'#255#7#26'u'#255#8#26'z'#255#6#26'p'#255#8#31'w'#255#10';'#156
+ +#255#13'j'#209#255#21'|'#224#255#23'z'#221#255#20#128#227#255#25#129#226#255
+ +#23#127#224#255#23#127#224#255#24#129#224#255#24#130#225#255#23#128#224#255
+ +#21#127#223#255#24#130#226#255#24#129#227#255#27#132#223#255#27#133#220#255
+ +'!'#133#222#255' '#129#211#255#11'E'#147#255#19'h'#184#255#26#128#219#255#29
+ +#128#220#255#20'~'#219#255#16#130#222#255#18#132#224#255#19#128#224#255#26
+ +#131#229#255#27#134#234#255'$'#145#243#255'$'#141#239#255'$'#135#235#255'"u'
+ +#218#255#26'c'#189#255#18'P'#156#255#14''#255#17#21'4'
+ +#255#9#9#31#255#145#147#149'nzx'#127#255#229#226#227'('#192#188#191#0#0#0#0#0
+ +#223#211#208#30#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'pigG'#143#144
+ +#143#168'i|'#151#29#0#0#0#0#1'&\'#18#5'$l'#249#9'%s'#254#8#29'o'#255#4#25'k'
+ +#255#2#28'p'#255#13'('#131#255#10'!~'#255#4#27'x'#255#8#25'v'#255#8#25'w'#255
+ +#9#26'{'#255#8#25'y'#255#9#27'z'#255#9#27'x'#255#10#27'u'#255#10#28't'#255#13
+ +#28'p'#255#11#26'j'#255#6#18'a'#255#9#20'j'#255#5#23'r'#255#5#27'u'#255#6#27
+ +'w'#255#8#27'y'#255#8#27'x'#255#6#27'w'#255#8#25'v'#255#11#24'v'#255#6#25'w'
+ +#255#6#26'w'#255#7#26'u'#255#4#28't'#255#7#30'w'#255#6'@'#163#255#17'j'#217
+ +#255#31'}'#236#255#26'|'#230#255#24#127#230#255#21#128#228#255#27#131#229#255
+ +#27#128#230#255#25#130#231#255#22#129#229#255#27#129#229#255#25#128#223#255
+ +#25#128#223#255#27#129#223#255'!'#132#227#255'('#132#224#255';'#131#235#255
+ +'9'#140#240#255'1~'#208#255#13'8'#133#255#26'e'#186#255'%'#131#235#255'!~'
+ +#231#255#23'|'#225#255#25#128#229#255#27#127#229#255#29#131#233#255#25#132
+ +#230#255#20#130#231#255#22#130#233#255#28#130#226#255#26#128#227#255#21'~'
+ +#230#255#20'|'#228#255#31'}'#234#255' |'#230#255#31#129#230#255#28'~'#229#255
+ +#30#130#232#255'('#140#235#255'.'#133#211#255'#c'#158#255#11',W'#255#23',P'
+ +#255':i'#129#255'''Ri'#255#8#14'0'#255#0#6'0'#255#25'D'#131#255'0'#130#214
+ +#255'"'#128#222#255#29#128#218#255#20#129#218#255#19#131#224#255#24#128#226
+ +#255#22#127#228#255#24#128#229#255#24#127#231#255#23'}'#232#255#23'{'#232#255
+ +#26'~'#234#255#21'{'#230#255#26#128#234#255#25'|'#234#255#25'|'#233#255#24'|'
+ +#231#255#23'~'#232#255#19'~'#231#255#15'}'#230#255#16'~'#234#255#16#127#237
+ +#255#11'l'#217#255#2'c'#208#255#3'a'#206#255#7'a'#208#255#10'f'#210#255#12'd'
+ +#206#255#19'Z'#188#255#9'?'#157#255#6'#n'#255#5#23']'#255#10#18'X'#255#13#22
+ +'\'#255#6#22'\'#255#7#23'^'#255#6#22'\'#255#8#23'Y'#255#8#20'\'#255#7#18'\'
+ +#255#6#17']'#255#7#20'a'#255#9#20'c'#255#10#21'd'#255#10#22'f'#255#9#21'e'
+ +#255#8#20'c'#255#7#19'b'#255#7#19'b'#255#7#19'a'#255#9#21'c'#255#9#20'c'#255
+ +#8#20'b'#255#8#20'd'#255#8#19'e'#255#4#22'b'#255#2#20'e'#255#6#22'f'#255#2#20
+ +'e'#255#7'+'#133#255#18'2'#143#255#7' |'#255#3#26'v'#255#11' }'#255#8#27'y'
+ +#255#8#26'{'#255#7#24'z'#255#7#23'z'#255#8#24'z'#255#8#23'z'#255#6#23'w'#255
+ +#8#25'z'#255#7#23'y'#255#7#23'z'#255#8#24'z'#255#7#24'w'#255#7#26't'#255#9#25
+ +'q'#255#5#21'k'#255#4#20'k'#255#6#24'o'#255#5#23's'#255#5#22'v'#255#5#22'v'
+ +#255#6#22'y'#255#6#22'y'#255#7#24'z'#255#7#24'y'#255#6#24'x'#255#7#24'x'#255
+ +#7#24'y'#255#5#23'u'#255#7#26'r'#255#8#24'k'#255#9#21'd'#255#11#19']'#255#9
+ +#15'W'#255#7#14'V'#255#7#16'^'#255#7#19'd'#255#10#22'm'#255#10#22'p'#255#10
+ +#24'm'#255#10#23'j'#255#12#20'c'#255#13#19'\'#255#12#17'S'#255#11#17'O'#255
+ +#10#16'M'#255#11#16'M'#255#10#16'K'#255#10#16'J'#255#10#16'I'#255#10#16'I'
+ +#255#10#15'H'#255#13#16'I'#255#12#15'G'#255#10#15'E'#255#10#15'F'#255#11#16
+ +'I'#255#11#16'J'#255#9#14'I'#255#9#15'J'#255#8#15'J'#255#7#14'H'#255#9#16'I'
+ +#255#7#15'I'#255#8#14'J'#255#9#15'I'#255#10#17'G'#255#13#18'A'#255#17#21'5'
+ +#255#9#13#29#255#0#0#0#0'|'#129#134#227'nos'#212#255#255#255#1#191#188#191#0
+ +#0#0#0#0#224#212#209#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'iiiN'#128#131
+ +#132#142'l'#131#165#15#0#0#0#0'!B'#128#166#6'''n'#255#10'#t'#255#14#30'u'#255
+ +#5#25'k'#255#3#24'l'#255#9'!{'#255#12'#'#131#255#6#29'z'#255#8#26'v'#255#8#26
+ +'x'#255#8#26'y'#255#9#27'{'#255#7#25'x'#255#9#27'x'#255#9#26's'#255#11#28's'
+ +#255#12#27'p'#255#11#25'g'#255#2#15']'#255#9#20'm'#255#7#24'x'#255#6#26'y'
+ +#255#6#26'x'#255#8#26'y'#255#8#25'y'#255#5#26'x'#255#8#25'w'#255#12#24'v'#255
+ +#8#27'y'#255#5#25'u'#255#7#23't'#255#3#27'u'#255#8'1'#152#255#31'm'#212#255
+ +#26'|'#232#255#29'x'#230#255#27'{'#230#255#27#127#230#255#27#127#228#255#26
+ ,#127#229#255#21#127#233#255#30#127#230#255'"'#129#228#255#26'}'#222#255#28
+ +#127#226#255' '#127#228#255','#131#234#255'3'#144#244#255'/'#130#226#255'&o'
+ +#197#255#29'I'#152#255#13'+x'#255#5#30'h'#255#5#29'i'#255#14'2'#140#255'!e'
+ +#203#255'*|'#233#255')'#130#230#255#26'}'#224#255#22#127#233#255#31'~'#234
+ +#255#29#127#229#255#24#127#227#255#27#127#232#255#28#128#230#255#28'}'#230
+ +#255#30#127#233#255' ~'#233#255' |'#232#255' ~'#230#255#30'}'#227#255#30'|'
+ +#227#255#30'~'#227#255'"}'#224#255' '#133#226#255'$'#142#222#255'(}'#190#255
+ +#20'J~'#255#25'El'#255#14'6S'#255#7#15')'#255#0#5'+'#255#21'?'#128#255',~'
+ +#210#255' '#130#226#255#24'~'#220#255#21#128#219#255#27'}'#227#255#26#129#229
+ +#255#26#127#229#255#27'~'#230#255#24'{'#231#255#25'|'#232#255#26'}'#234#255
+ +#24'z'#231#255#26'|'#232#255#30'}'#233#255#29'~'#234#255#26'{'#231#255#26'~'
+ +#231#255#22'~'#228#255#21'~'#232#255#21#127#236#255#16'z'#235#255#11'l'#221
+ +#255#9'd'#214#255#7'_'#210#255#7'^'#211#255#6'`'#211#255#8'`'#212#255#19'_'
+ +#206#255#22']'#200#255#16'H'#167#255#6'*}'#255#6#22'b'#255#4#13'O'#255#5#13
+ +'P'#255#11#14'W'#255#11#12'X'#255#9#15'Z'#255#8#17'['#255#7#18']'#255#9#20'`'
+ +#255#10#22'd'#255#8#20'c'#255#8#19'c'#255#9#20'd'#255#10#19'c'#255#12#22'f'
+ +#255#10#20'd'#255#10#20'd'#255#8#19'b'#255#8#19'a'#255#10#20'd'#255#9#20'd'
+ +#255#8#20'd'#255#6#19'f'#255#9#22'c'#255#4#19'k'#255#4'$z'#255#4'#{'#255#17
+ +'='#165#255#23'@'#166#255#4'%'#130#255#0#25'w'#255#15'$'#132#255#8#29'}'#255
+ +#7#23'{'#255#8#23'{'#255#8#24'{'#255#9#25'{'#255#8#23'z'#255#7#24'x'#255#7#23
+ +'x'#255#7#23'y'#255#7#23'{'#255#8#24'{'#255#8#24'x'#255#10#24'u'#255#10#25'r'
+ +#255#8#21'n'#255#8#20'n'#255#8#23'q'#255#7#21's'#255#7#22'w'#255#7#22'w'#255
+ +#7#22'w'#255#9#21'x'#255#6#22'v'#255#7#22'w'#255#9#22'w'#255#7#22'w'#255#6#23
+ +'w'#255#6#22'u'#255#8#24'r'#255#10#24'l'#255#10#22'd'#255#12#17']'#255#9#15
+ +'Y'#255#8#15'Y'#255#9#17'_'#255#9#18'h'#255#10#22'n'#255#11#22'q'#255#11#22
+ +'p'#255#12#22'n'#255#13#20'e'#255#13#19'^'#255#16#18'T'#255#14#16'P'#255#13
+ +#16'N'#255#11#16'M'#255#11#18'M'#255#11#16'K'#255#12#16'K'#255#11#16'J'#255
+ +#12#16'J'#255#13#15'I'#255#12#14'H'#255#12#14'G'#255#12#15'I'#255#13#17'L'
+ +#255#13#17'L'#255#11#15'J'#255#11#15'J'#255#12#16'K'#255#10#14'H'#255#10#14
+ +'H'#255#11#15'J'#255#10#15'J'#255#10#15'J'#255#11#16'H'#255#14#19'A'#255#16
+ +#20'4'#255#7#10#29#255#134#140#145#0#147#158#166#18'ty'#129#250'igq'#225#255
+ +#255#255#7#227#222#223#13#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'vy'
+ +'}Olqy'#234#0#0#0#0#0#0#0#0'-J'#137#242#6'#l'#254#12'#v'#255#9#28's'#255#7#26
+ +'l'#255#5#24'i'#255#8#27's'#255#15'$'#127#255#11'%~'#255#8#26'v'#255#8#26'w'
+ +#255#7#26'y'#255#11#29'|'#255#10#28'{'#255#11#29'z'#255#9#27't'#255#9#27'r'
+ +#255#11#27'r'#255#10#26'h'#255#1#17'^'#255#11#24'r'#255#9#25'{'#255#6#26'{'
+ +#255#8#26'y'#255#9#25'z'#255#9#22'x'#255#7#25'z'#255#9#24'y'#255#7#25'u'#255
+ +#7#26'v'#255#8#26'v'#255#6#24'y'#255#7'-'#142#255#17'Z'#200#255#25'v'#226#255
+ +#23'{'#231#255#27'x'#228#255#26'|'#227#255#28#127#230#255' '#128#231#255#24
+ +'|'#228#255' |'#227#255#29#127#228#255#31#128#225#255'%'#127#228#255'/'#133
+ +#236#255'5'#141#239#255')n'#202#255#28'N'#160#255#12'0|'#255#8'%o'#255#14#28
+ +'h'#255#5'#p'#255#5'2'#131#255#19'2'#134#255#16')v'#255#3'*j'#255#24'R'#170
+ +#255'&'#129#227#255#21'|'#223#255'!'#127#228#255#31#129#235#255#30#134#235
+ +#255#27#128#225#255#30#128#230#255#28#127#232#255#29'}'#229#255#31#127#231
+ +#255#31'}'#231#255'!}'#229#255'!|'#229#255#31'{'#226#255#30'|'#227#255#28'~'
+ +#228#255' |'#229#255#25'z'#227#255#27'z'#226#255'!'#130#225#255'%'#141#219
+ +#255'0'#139#197#255'$T'#134#255#4#29'<'#255#10#2#30#255#5#11','#255#12'>|'
+ +#255'-z'#216#255'!x'#219#255#25#127#219#255#20#129#226#255#26#127#226#255#24
+ +'|'#226#255#23'z'#226#255#26'{'#227#255#28'|'#230#255#27'{'#230#255#27'z'#229
+ +#255#27'{'#228#255#28'~'#228#255#27'|'#227#255#24'{'#226#255#26'~'#228#255#20
+ +'{'#225#255#19'|'#229#255#19'~'#234#255#19'}'#238#255#8'h'#218#255#9'd'#214
+ +#255#10'a'#210#255#10'_'#212#255#5'\'#212#255#8'`'#215#255#7']'#208#255#13'b'
+ +#211#255#18'`'#208#255#15'U'#193#255#4'A'#163#255#6'4'#140#255#3' s'#255#1#21
+ +'f'#255#5#22'c'#255#6#24'b'#255#9#22'c'#255#8#21'b'#255#8#20'b'#255#11#23'e'
+ +#255#8#20'b'#255#8#20'b'#255#9#21'b'#255#11#20'd'#255#12#21'e'#255#10#19'c'
+ +#255#11#20'd'#255#11#20'd'#255#12#21'e'#255#10#20'c'#255#8#20'f'#255#11#22'i'
+ +#255#6#21'e'#255#5#23'k'#255#4''''#132#255#10'4'#146#255#0'('#141#255#22'M'
+ +#189#255#11'C'#171#255#15'0'#146#255#3#28'~'#255#15'%'#136#255#9#30#129#255#9
+ +#26'{'#255#7#24'y'#255#8#24'y'#255#9#25'y'#255#8#24'y'#255#10#24'x'#255#9#22
+ +'w'#255#8#24'y'#255#8#24'y'#255#8#23'x'#255#9#23'u'#255#10#24'u'#255#10#24'r'
+ +#255#8#19'p'#255#10#20'q'#255#8#20's'#255#7#18't'#255#8#21'w'#255#7#20'v'#255
+ +#10#22'v'#255#11#23'w'#255#9#22'v'#255#9#22'v'#255#12#24'x'#255#9#23'w'#255#9
+ +#22'w'#255#9#23'u'#255#10#25'o'#255#13#24'k'#255#11#23'b'#255#7#16'Y'#255#8
+ +#15'X'#255#8#17'Z'#255#8#17'_'#255#8#18'h'#255#10#20'n'#255#11#22'r'#255#14
+ ,#24'r'#255#12#22'n'#255#12#21'f'#255#13#19'^'#255#15#17'V'#255#13#16'P'#255
+ +#12#15'M'#255#12#16'K'#255#13#17'L'#255#11#15'J'#255#12#15'J'#255#14#16'K'
+ +#255#12#14'I'#255#13#15'I'#255#11#12'H'#255#11#12'I'#255#13#14'J'#255#13#15
+ +'J'#255#13#15'K'#255#12#14'J'#255#12#14'I'#255#12#15'J'#255#12#15'I'#255#12
+ +#15'I'#255#12#15'J'#255#11#16'K'#255#11#16'K'#255#11#16'G'#255#12#17'?'#255
+ +#18#22'6'#255#11#15'"'#255#0#0#0#0#136#142#149#0#196#196#202')'#133#133#145
+ +#255'hbq'#153#0#0#0#0#227#222#223#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +'pw{DW`j'#255#255#255#255#2#255#255#255#2'&E'#131#249#13'''q'#255#9'!s'#255#9
+ +#31's'#255#6#26'j'#255#7#22'g'#255#9#25'r'#255#9#28'y'#255#9'$'#127#255#10' '
+ +'}'#255#8#30'}'#255#5#26'y'#255#8#28'{'#255#7#25'w'#255#9#28'v'#255#8#27'r'
+ +#255#11#28'p'#255#13#27'p'#255#9#23'd'#255#2#15']'#255#12#24'q'#255#7#24'x'
+ +#255#5#25'x'#255#6#26'w'#255#9#27'z'#255#7#24'x'#255#8#25'y'#255#7#23'x'#255
+ +#6#24'u'#255#8#28'u'#255#5#25'u'#255#2'$'#136#255#17'Z'#191#255#27't'#226#255
+ +#26'~'#232#255#26'{'#231#255#30#127#233#255#29#131#238#255#28#128#233#255'$'
+ +#128#231#255#30#127#228#255'"'#128#226#255'('#128#228#255'5'#135#236#255'8'
+ +#133#230#255'$h'#193#255#25'D'#151#255#0'"n'#255#7'0w'#255#11'4'#130#255#8'('
+ +'x'#255#7'&v'#255#10'2z'#255#16'5'#128#255#17'5'#135#255#12'2'#131#255#15'0{'
+ +#255#0#26'b'#255#4'?'#145#255#27'x'#215#255'#'#130#225#255'!'#127#225#255' '
+ +#127#229#255#31'~'#228#255#24#128#227#255#27#127#231#255#28#127#231#255#27'}'
+ +#229#255#29'}'#228#255#29'|'#227#255#31'~'#228#255#29'|'#227#255#31'~'#229
+ +#255#23#129#231#255#28'}'#226#255#31#129#227#255#28#129#228#255'!|'#226#255
+ +#25#128#226#255#27#133#220#255','#143#222#255'5'#127#194#255#19'>o'#255#3#2
+ +''''#255#5#7'5'#255#22'E'#135#255'&'#130#211#255#26'|'#219#255#29'~'#226#255
+ +#23#128#230#255#24'~'#228#255#25'~'#229#255#29#127#231#255#29#127#231#255#28
+ +'~'#230#255#27#127#230#255#29#129#234#255#27'}'#230#255#26'~'#228#255#25'}'
+ +#227#255#25#127#229#255#20#127#228#255#21#129#234#255#21#130#238#255#21#129
+ +#241#255#11'j'#216#255#5'a'#208#255#7'a'#206#255#8'b'#208#255#6'_'#210#255#10
+ +'`'#214#255#4'_'#212#255#10'c'#215#255#10'a'#213#255#8'b'#216#255#11'`'#213
+ +#255#17'Y'#205#255#10'C'#175#255#8'9'#156#255#4'&'#129#255#8#23'l'#255#3#20
+ +'e'#255#2#20'd'#255#3#20'c'#255#9#23'e'#255#8#20'b'#255#10#22'd'#255#9#20'b'
+ +#255#10#22'e'#255#8#20'd'#255#9#21'd'#255#8#20'd'#255#7#19'c'#255#10#22'f'
+ +#255#7#22'g'#255#4#20'f'#255#3#19'f'#255#2#28't'#255#5'-'#142#255#8'D'#169
+ +#255#11'8'#156#255#0'8'#162#255#24'Y'#203#255#18'L'#177#255#9'+'#145#255#1#27
+ +'~'#255#11'#'#134#255#9' '#130#255#7#26'z'#255#8#25'z'#255#8#25'z'#255#8#24
+ +'y'#255#8#23'x'#255#9#23'y'#255#9#23'x'#255#8#24'y'#255#7#23'x'#255#6#23'w'
+ +#255#7#23't'#255#9#25't'#255#11#24't'#255#9#20'q'#255#11#22'q'#255#7#19'r'
+ +#255#8#20'v'#255#8#21'w'#255#9#22'x'#255#9#22'x'#255#9#21'v'#255#8#22'w'#255
+ +#8#22'w'#255#10#23'w'#255#8#21'w'#255#6#21'u'#255#7#23'v'#255#8#23'q'#255#10
+ +#22'j'#255#10#23'c'#255#9#18'\'#255#9#16'Z'#255#9#16']'#255#8#17'd'#255#9#18
+ +'m'#255#9#20'q'#255#11#20't'#255#13#23's'#255#9#22'o'#255#13#23'i'#255#13#18
+ +'_'#255#13#18'X'#255#12#18'Q'#255#13#17'M'#255#11#15'J'#255#13#16'K'#255#14
+ +#16'I'#255#13#16'I'#255#15#19'I'#255#14#17'G'#255#13#15'G'#255#13#15'H'#255
+ +#13#14'J'#255#12#15'K'#255#10#14'I'#255#11#15'J'#255#11#15'J'#255#11#14'J'
+ +#255#11#13'I'#255#12#15'J'#255#12#15'I'#255#12#16'K'#255#11#16'K'#255#10#15
+ +'J'#255#9#14'F'#255#13#18'@'#255#17#21'5'#255#9#13' '#255#0#0#0#0#0#0#0#0#210
+ +#210#216#0#255#255#255#3'yq'#132#198'hbr2'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#139#150#155#138'IYb'#253#216#255#255#6#0#0#0#0#31'A~'#250#8
+ +'''p'#255#7'#q'#255#6#30'o'#255#9#29'l'#255#5#20'c'#255#9#24'm'#255#6#25's'
+ +#255#8' |'#255#13'#'#130#255#13'"'#130#255#6#27'z'#255#6#27'z'#255#9#26'w'
+ +#255#10#28'u'#255#8#26'q'#255#11#28'q'#255#16#29'n'#255#7#20'b'#255#2#14']'
+ +#255#12#23'p'#255#6#24'w'#255#4#27'w'#255#7#28'w'#255#9#27'{'#255#7#24'y'#255
+ +#10#25'u'#255#7#26'u'#255#6#24'y'#255#7#27'q'#255#2#30'v'#255#9'C'#165#255#24
+ +'t'#221#255#23'w'#224#255#22'}'#230#255#26#128#235#255#29#127#232#255#24'~'
+ +#231#255#25#128#229#255#30'~'#224#255'%'#131#227#255'.'#132#234#255'7'#140
+ +#242#255'/p'#208#255#20'>'#140#255#4'%o'#255#10'.x'#255#14'5'#129#255#11'2'
+ +#139#255#9'-v'#255#6'$r'#255#16'1'#129#255#17'1'#136#255#11'1'#133#255#10'4'
+ +#128#255#12'2'#127#255#13'1'#132#255#12'2'#128#255#8#27'f'#255#9'/'#132#255
+ +#28'l'#215#255'%'#132#238#255#29'~'#230#255#26#130#236#255#30#131#233#255#26
+ +#128#231#255#28#129#232#255#28#127#230#255#28#127#229#255#26'z'#225#255#31
+ +#127#230#255#31#127#230#255' '#128#232#255#30'~'#232#255#26'}'#231#255#27#128
+ +#233#255#23'z'#231#255#23'{'#231#255#27#127#233#255#24'}'#225#255'"'#128#224
+ +#255','#140#224#255'<'#152#221#255' _'#141#255#8#15'4'#255#0#16'>'#255#22'W'
+ +#158#255'*w'#216#255#22'}'#222#255#26#129#231#255#25#128#230#255#26#128#232
+ +#255#25'}'#231#255#24'|'#229#255#25'|'#229#255#24'{'#230#255#25'~'#233#255#28
+ ,'~'#234#255#28'}'#233#255#26#127#231#255#27#130#234#255#23#128#231#255#21#127
+ +#233#255#24#131#239#255#23#131#240#255#12'g'#215#255#6'b'#209#255#3'`'#206
+ +#255#6'a'#210#255#9'b'#213#255#9'a'#214#255#8'`'#214#255#8'_'#213#255#10'\'
+ +#210#255#11'a'#215#255#5']'#209#255#9'_'#210#255#6'\'#203#255#7'Z'#197#255#7
+ +'S'#188#255#6'H'#177#255#11'9'#149#255#10'('#131#255#4#26'n'#255#9#23'g'#255
+ +#5#18'_'#255#7#18'_'#255#6#19'_'#255#9#20'b'#255#5#19'a'#255#3#18'a'#255#5#23
+ +'d'#255#9#23'f'#255#8#20'c'#255#8#21'e'#255#0#23'i'#255#9'(}'#255#13'>'#167
+ +#255#12'V'#190#255#9'Q'#184#255#8'7'#159#255#8'M'#186#255#28'g'#217#255#15'N'
+ +#184#255#10'4'#156#255#6#31#128#255#11'$'#134#255#8'"'#132#255#10#26'z'#255#7
+ +#25'w'#255#8#25'x'#255#9#22'y'#255#10#23'z'#255#9#24'z'#255#11#25'{'#255#9#25
+ +'z'#255#8#24'y'#255#8#25'x'#255#8#24'u'#255#9#25's'#255#10#25's'#255#12#24'q'
+ +#255#11#24'o'#255#7#20'q'#255#9#23'x'#255#8#23'x'#255#9#24'y'#255#10#24'z'
+ +#255#9#22'x'#255#8#22'x'#255#9#22'x'#255#10#22'x'#255#10#22'z'#255#7#22'z'
+ +#255#7#24'x'#255#10#24's'#255#11#24'm'#255#11#23'e'#255#10#18']'#255#9#15'['
+ +#255#8#15'^'#255#7#14'e'#255#9#18'n'#255#11#21'u'#255#10#22'w'#255#11#23'u'
+ +#255#9#22'p'#255#12#23'k'#255#11#21'`'#255#12#18'X'#255#12#18'Q'#255#12#17'L'
+ +#255#13#16'J'#255#13#15'H'#255#13#16'G'#255#13#18'F'#255#14#18'H'#255#12#16
+ +'F'#255#11#14'E'#255#11#15'I'#255#11#14'I'#255#12#17'L'#255#12#15'J'#255#13
+ +#16'K'#255#12#16'K'#255#11#15'J'#255#10#14'I'#255#11#15'J'#255#11#15'I'#255
+ +#13#17'K'#255#11#15'K'#255#10#15'J'#255#10#15'H'#255#11#17'@'#255#17#21'6'
+ +#255#12#14'#'#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#128't'#133#217'ufu'
+ +#139#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#142#149#159#255'=O\'#251#197#236
+ +#255#9#0#0#0#0' B'#128#250#10'(p'#255#6'#o'#255#7#31'n'#255#8#28'k'#255#8#24
+ +'e'#255#6#23'f'#255#8#28'r'#255#6#28'x'#255#8#31'}'#255#12'#'#129#255#5#29'{'
+ +#255#5#27'z'#255#9#29'y'#255#8#28't'#255#8#27'q'#255#12#31's'#255#17#30'l'
+ +#255#6#19'`'#255#5#19'`'#255#11#24'q'#255#7#24'x'#255#9#27'x'#255#7#24'u'#255
+ +#9#26'{'#255#8#26'z'#255#7#27'u'#255#3#28'u'#255#6#26's'#255#5#29'q'#255#5'6'
+ +#142#255#22'j'#207#255#24'|'#227#255#24'}'#227#255#30'~'#230#255#29#127#230
+ +#255#25#130#230#255#24#129#227#255'"'#131#226#255'+'#132#226#255'4'#144#234
+ +#255'2'#130#223#255'"P'#164#255#1'%k'#255#6'1y'#255#16'3'#132#255#12'6'#134
+ +#255#10'9'#132#255#14'-x'#255#2'%o'#255#10'-{'#255#14'3'#134#255#12'3'#134
+ +#255#10'3'#134#255#10'3'#130#255#12'3'#130#255#12'2'#131#255#14'6'#130#255#19
+ +'5'#131#255#4'$o'#255#4'2'#131#255')p'#214#255'(~'#238#255''''#129#230#255#24
+ +#128#227#255#24#129#230#255#28#132#233#255#27#129#230#255#31#132#231#255#29
+ +#129#229#255' '#132#232#255#28#128#228#255#27'~'#229#255#24'|'#227#255#27'~'
+ +#230#255#27#129#233#255#27#128#233#255#27#129#233#255#26'~'#231#255#25'}'#229
+ +#255#28#128#231#255#28'~'#224#255'"'#140#212#255'9'#157#218#255'#l'#160#255
+ +#12#24'G'#255#3#22'M'#255#17'c'#184#255')'#132#230#255#24'{'#224#255#29#130
+ +#230#255#21'{'#223#255#22'~'#227#255#26#127#228#255#27#128#229#255#25'}'#229
+ +#255#26'~'#230#255#25#127#231#255#27#128#233#255#26#128#232#255#29#131#234
+ +#255#23#127#231#255#21#127#231#255#19#128#234#255#19#128#234#255#7'g'#209#255
+ +#7'f'#209#255#6'd'#208#255#7'c'#209#255#6'`'#208#255#7'a'#210#255#7'`'#209
+ +#255#7'`'#209#255#5'^'#207#255#7'`'#208#255#4'^'#207#255#8'b'#211#255#6'a'
+ +#208#255#4'_'#206#255#6'^'#205#255#12'b'#209#255#5'b'#215#255#11'^'#211#255
+ +#15'\'#202#255#3'S'#183#255#4'?'#159#255#10'0'#142#255#7')'#127#255#4'#r'#255
+ +#8#30'j'#255#3#24'f'#255#5#28'm'#255#7#29'p'#255#6#30't'#255#7'&~'#255#5':'
+ +#155#255#8'O'#184#255#12']'#205#255#10']'#201#255#1'K'#174#255#4'G'#173#255
+ +#10'X'#194#255#12'\'#202#255#18'P'#186#255#11'5'#149#255#3#30'z'#255#10'*'
+ +#138#255#6'#'#133#255#8#23'u'#255#7#27's'#255#8#26'v'#255#10#22'y'#255#10#24
+ +'z'#255#10#24'z'#255#8#24'y'#255#8#24'y'#255#7#24'x'#255#8#25'w'#255#8#26'u'
+ +#255#9#25's'#255#9#25'q'#255#10#24'n'#255#6#21'k'#255#6#20'p'#255#8#24'u'#255
+ +#6#23'w'#255#7#24'x'#255#7#23'x'#255#9#24'w'#255#6#23'v'#255#8#23'x'#255#8#22
+ +'w'#255#7#23'x'#255#7#24'y'#255#7#24'x'#255#8#24's'#255#11#24'm'#255#10#23'd'
+ +#255#10#18'^'#255#7#14'Y'#255#8#16'_'#255#8#17'f'#255#8#20'o'#255#6#20's'#255
+ +#8#22'v'#255#10#23'u'#255#9#23'q'#255#11#22'j'#255#11#22'c'#255#12#20'Y'#255
+ +#12#19'R'#255#15#18'L'#255#14#17'K'#255#13#17'I'#255#14#17'G'#255#13#17'G'
+ +#255#15#18'H'#255#13#17'G'#255#9#14'G'#255#12#16'K'#255#10#16'K'#255#11#16'K'
+ +#255#9#16'K'#255#10#16'K'#255#9#15'J'#255#9#15'J'#255#8#14'I'#255#10#16'K'
+ +#255#8#14'I'#255#10#15'J'#255#10#14'I'#255#11#15'J'#255#12#17'I'#255#12#18'B'
+ +#255#15#20'6'#255#6#11' '#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#129'p}'#206#129'r{'#211#255#255#255#9#218#215#218#0#0#0#0#0#0#0#0#0#158#165
+ +#173'OEUa'#253'n'#145#192#13#255#255#255#0#17'5s'#242#10'''q'#254#7'"n'#255#8
+ +#31'l'#255#11#30'i'#255#6#21'`'#255#4#21'a'#255#7#27'n'#255#7#28'v'#255#3#26
+ +'s'#255#8'!{'#255#12'%'#130#255#6' }'#255#4#26'w'#255#7#28't'#255#10#29'q'
+ ,#255#10#29'm'#255#16#29'k'#255#7#20'^'#255#1#14'Z'#255#13#26'q'#255#7#23'x'
+ +#255#9#27'x'#255#6#24't'#255#7#24'y'#255#10#26'w'#255#5#26'y'#255#5#26't'#255
+ +#8#29'n'#255#1'''|'#255#23'c'#197#255#22'{'#227#255#22'z'#225#255#25'~'#225
+ +#255#25#127#225#255#27#130#226#255#29#135#228#255#28#132#223#255''''#135#222
+ +#255'G'#149#231#255'&m'#187#255#20'0q'#255#2#22'T'#255#4'$k'#255#11'6'#132
+ +#255#12'4|'#255#14'9'#130#255#5'0{'#255#9'''j'#255#5'/|'#255#11'3'#130#255#7
+ +'1'#130#255#8'2'#133#255#9'3'#133#255#8'3'#132#255#11'4'#131#255#13'4'#130
+ +#255#13'5|'#255#18';|'#255#22'5o'#255#1#14'I'#255#18'.w'#255'*j'#204#255'%'
+ +#128#239#255'"'#127#233#255#23#129#230#255#28#133#234#255#24#128#228#255#27
+ +#131#231#255#28#130#228#255#29#131#230#255#28#129#228#255#29#130#229#255#26
+ +#127#229#255#25#129#228#255#25#129#229#255#25#130#227#255#23#127#227#255#23
+ +'}'#228#255#21'y'#227#255#23'z'#230#255#27'|'#230#255#22#131#224#255#23#133
+ +#220#255'&'#148#226#255' t'#173#255#9#22'K'#255#2#29'^'#255' o'#206#255' '
+ +#128#226#255#26'}'#223#255#26#129#225#255#24#130#225#255#22#128#224#255#27
+ +#130#227#255#24#128#226#255#23#127#226#255#21'~'#229#255#20'~'#229#255#19'{'
+ +#226#255#21'~'#229#255#22#127#231#255#20#127#232#255#18#127#234#255#18#127
+ +#234#255#7'g'#209#255#7'h'#209#255#3'd'#206#255#6'c'#208#255#6'c'#208#255#7
+ +'d'#209#255#5'b'#207#255#5'c'#207#255#6'c'#207#255#7'c'#207#255#4'c'#207#255
+ +#6'e'#208#255#4'c'#208#255#7'b'#208#255#3'^'#204#255#7'b'#207#255#8'e'#211
+ +#255#14'b'#207#255#5'Z'#197#255#0'b'#204#255#4'c'#209#255#7'`'#209#255#7'c'
+ +#211#255#9'b'#210#255#8'['#201#255#12']'#201#255#8'U'#186#255#1'I'#170#255#5
+ +'I'#169#255#5'S'#180#255#5']'#193#255#2'd'#205#255#9'f'#205#255#5'R'#184#255
+ +#4'V'#186#255#6'd'#200#255#7'_'#204#255#18'd'#208#255#16'V'#189#255#7'6'#152
+ +#255#3'#'#129#255#15'2'#147#255#6''''#137#255#9#28'x'#255#8#28's'#255#7#27'u'
+ +#255#8#21'w'#255#8#24'u'#255#8#24'w'#255#7#23'x'#255#5#22'w'#255#7#24'x'#255
+ +#8#26'x'#255#9#26'v'#255#11#27's'#255#10#24'q'#255#9#21'k'#255#5#19'g'#255#6
+ +#20'm'#255#8#25'u'#255#5#23'v'#255#7#25'x'#255#7#25'x'#255#8#24'v'#255#7#24
+ +'w'#255#7#24'y'#255#7#25'x'#255#6#24'x'#255#7#25'x'#255#4#24'u'#255#6#24'o'
+ +#255#10#25'k'#255#11#23'b'#255#8#19']'#255#6#16'Z'#255#7#17'`'#255#7#18'g'
+ +#255#6#21'n'#255#7#22's'#255#7#22's'#255#11#24't'#255#9#23'q'#255#11#21'j'
+ +#255#12#20'b'#255#10#19'X'#255#12#20'T'#255#10#17'M'#255#13#17'K'#255#12#16
+ +'H'#255#11#16'G'#255#11#17'H'#255#10#16'G'#255#9#14'F'#255#10#13'H'#255#9#15
+ +'J'#255#10#16'K'#255#8#14'J'#255#9#15'J'#255#9#15'J'#255#10#16'K'#255#10#16
+ +'K'#255#8#14'I'#255#10#16'K'#255#8#14'I'#255#11#16'K'#255#11#15'J'#255#11#15
+ +'J'#255#12#16'H'#255#12#18'?'#255#18#21'7'#255#10#12'"'#255#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#166#158#167'Hwp{'#151#138#142#143#18#0
+ +#0#0#0#155#163#167#0#0#0#0#0'L_j[Sn'#142'b'#0#0#0#0#14'-l'#187#10'''s'#255#8
+ +'"p'#255#10#31'l'#255#14#30'i'#255#15#27'b'#255#1#14'V'#255#8#22'd'#255#12#28
+ +'q'#255#9#27'r'#255#5#25's'#255#7#29'|'#255#10'"'#132#255#9#31'~'#255#6#27'u'
+ +#255#9#28'p'#255#11#29'k'#255#15#27'h'#255#5#18'['#255#3#16'\'#255#11#22'l'
+ +#255#7#24'u'#255#8#25'v'#255#9#26'w'#255#8#23'y'#255#6#24'x'#255#8#27'z'#255
+ +#10#27's'#255#3#31'w'#255#10'G'#177#255#18'r'#222#255#20'y'#224#255#24'z'#229
+ +#255#27#128#230#255#23#130#226#255#28#133#222#255'('#138#224#255'9'#147#231
+ +#255'D'#144#221#255')Z'#156#255#3#25'V'#255#10#16'I'#255#2'&k'#255#11'1'#132
+ +#255#15'2'#129#255#15'9~'#255#15'0x'#255#7' l'#255#4'(w'#255#8'2'#136#255#9
+ +'2'#134#255#11'5'#136#255#8'1'#134#255#9'1'#136#255#9'2'#135#255#10'2'#132
+ +#255#11'3~'#255#14'7z'#255#18'8k'#255#27'5c'#255#11#21'?'#255#0#6'3'#255#5' '
+ +'^'#255'%e'#189#255'3'#128#233#255#28#128#230#255#28#128#231#255#26#127#230
+ +#255#28#129#234#255#23'~'#230#255#25#127#232#255#29#127#231#255#31#127#230
+ +#255#28#127#230#255#29#127#230#255#28#127#231#255#28#127#232#255#26'~'#230
+ +#255#30#127#234#255#27'|'#233#255#29'|'#234#255'!z'#234#255#23'|'#237#255#30
+ +'~'#227#255#31#134#226#255#31#150#239#255#31'z'#193#255#11'#h'#255#0'1'#129
+ +#255'%}'#226#255' }'#224#255#29#128#225#255#26#129#226#255#21'}'#223#255#25
+ +#127#227#255#24#127#229#255#25'~'#232#255#24'~'#233#255#26#127#234#255#22'{'
+ +#231#255#25'~'#233#255#20'{'#231#255#21'~'#236#255#19'~'#238#255#21#128#241
+ +#255#6'e'#209#255#8'g'#210#255#4'a'#207#255#8'd'#212#255#7'`'#210#255#8'a'
+ +#213#255#8'`'#213#255#7'_'#211#255#7'c'#210#255#6'a'#208#255#8'b'#209#255#8
+ +'a'#209#255#7'a'#208#255#8'`'#208#255#5']'#205#255#10'c'#211#255#11'a'#207
+ +#255#11'N'#191#255#1'F'#180#255#9'['#198#255#9'a'#206#255#8'c'#210#255#0'^'
+ +#208#255#6'`'#212#255#4'_'#212#255#10'e'#214#255#5']'#204#255#11']'#205#255#9
+ +'^'#209#255#10'b'#214#255#7'_'#211#255#8'_'#209#255#4'W'#194#255#3'S'#189#255
+ +#3'['#200#255#5'b'#211#255#9'_'#212#255#12'_'#207#255#7'P'#188#255#8'9'#158
+ +#255#0'#'#131#255#23'='#161#255#7'('#140#255#9#27'y'#255#8#28'v'#255#7#26't'
+ +#255#8#23'v'#255#7#24'v'#255#7#24'v'#255#7#23'w'#255#8#24'y'#255#7#23'y'#255
+ ,#8#23'w'#255#11#25'v'#255#12#25'r'#255#11#25'o'#255#11#21'g'#255#6#18'a'#255
+ +#6#17'f'#255#11#25'r'#255#8#22'v'#255#7#24'w'#255#6#23'w'#255#8#24'x'#255#6
+ +#23'y'#255#7#23'y'#255#8#23'y'#255#8#22'x'#255#8#22'x'#255#7#23'u'#255#11#24
+ +'p'#255#13#24'k'#255#11#21'a'#255#9#18'^'#255#8#16']'#255#7#16'b'#255#5#16'h'
+ +#255#6#20'q'#255#8#22'w'#255#9#23'w'#255#10#23'u'#255#10#24'r'#255#12#23'k'
+ +#255#10#20'b'#255#10#18'X'#255#12#19'S'#255#14#16'L'#255#14#17'K'#255#13#16
+ +'H'#255#14#17'H'#255#14#17'H'#255#13#16'G'#255#12#15'G'#255#11#15'J'#255#11
+ +#16'K'#255#12#17'M'#255#10#15'K'#255#9#15'J'#255#9#15'J'#255#9#16'K'#255#9#15
+ +'J'#255#9#15'J'#255#11#17'L'#255#9#15'J'#255#12#17'K'#255#11#15'J'#255#11#15
+ +'J'#255#13#16'G'#255#14#17'>'#255#17#20'4'#255#7#10#31#255#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'pq{'#155'\il'#255#141#155#156
+ +#163#137#158#165'('#0#0#0#0#0#0#0#0'Ql'#148#156#0#0#0#0#5#28'`'#127#13'&w'
+ +#254#9'!r'#255#11#31'n'#255#15#29'h'#255#16#28'_'#255#8#17'V'#255#5#14'V'#255
+ +#11#21'd'#255#12#25'p'#255#10#24'u'#255#5#25'y'#255#6#28#128#255#12'"'#133
+ +#255#10#31'|'#255#11#30's'#255#11#29'l'#255#13#25'`'#255#7#19'Z'#255#2#13'Y'
+ +#255#12#24'm'#255#10#25'w'#255#8#25'w'#255#8#24'w'#255#8#23'x'#255#3#25'z'
+ +#255#5#27't'#255#9#27'q'#255#8'2'#147#255#16'h'#219#255#23'|'#236#255#26'~'
+ +#228#255#19'{'#228#255#24#130#230#255'"'#129#224#255'*'#133#219#255'7'#146
+ +#227#255'4'#131#204#255' J'#138#255#0#17'H'#255#7#10'A'#255#3'!d'#255#13'1~'
+ +#255#9'3'#128#255#9'3'#132#255#14'2'#132#255#10'%p'#255#9'%o'#255#6'.'#127
+ +#255#9'/'#137#255#9'0'#136#255#11'3'#137#255#10'1'#137#255#10'0'#137#255#10
+ +'0'#135#255#11'2'#132#255#12'4~'#255#12'7w'#255#21'7q'#255#27'/['#255#6#19'4'
+ +#255#10#19'2'#255#7#8'-'#255#8#28'S'#255#31'\'#173#255'+'#130#234#255#31'~'
+ +#231#255#29#128#235#255#27'}'#235#255#29'y'#233#255#29'{'#231#255' |'#233#255
+ +#28'y'#230#255#31'{'#232#255'!|'#234#255#31'y'#232#255#29'z'#236#255#27'x'
+ +#233#255' {'#236#255#31'x'#234#255' w'#235#255#31'q'#235#255#26'{'#235#255#27
+ +'{'#229#255'&|'#230#255#27#127#230#255'$'#143#234#255'!x'#203#255#1')}'#255#1
+ +'G'#169#255'(}'#231#255'!}'#224#255#27#127#226#255#28'{'#230#255#24#127#229
+ +#255#24'{'#231#255#27'|'#232#255#23'y'#231#255#27'}'#235#255#27'{'#235#255#27
+ +'}'#237#255#23'{'#236#255#22'~'#240#255#20'~'#242#255#20'}'#242#255#5'c'#209
+ +#255#9'e'#212#255#5'`'#208#255#9'`'#211#255#7'`'#214#255#9'`'#215#255#9'_'
+ +#215#255#6'\'#214#255#4'a'#214#255#5'^'#214#255#3'_'#215#255#6'a'#213#255#10
+ +'_'#212#255#8'^'#215#255#8'`'#215#255#12']'#211#255#3'M'#185#255#2'J'#182#255
+ +#7'W'#200#255#2'_'#211#255#3'\'#213#255#10'^'#216#255#7']'#213#255#8'^'#214
+ +#255#5'['#212#255#8']'#214#255#11'^'#213#255#9'^'#214#255#5'\'#214#255#4'['
+ +#214#255#6'^'#215#255#9'^'#213#255#8'Y'#207#255#4'\'#212#255#4'`'#216#255#10
+ +']'#215#255#12'\'#214#255#17'^'#213#255#17'P'#193#255#12'9'#158#255#3'%'#138
+ +#255#22'='#163#255#10'+'#142#255#13#29'~'#255#8#26'w'#255#7#25'v'#255#9#25'x'
+ +#255#12#25'x'#255#11#25'x'#255#9#23'x'#255#8#23'z'#255#7#22'z'#255#9#22'y'
+ +#255#10#23'u'#255#11#24'p'#255#15#24'n'#255#13#20'c'#255#9#16'^'#255#4#12'_'
+ +#255#15#22'o'#255#10#22'u'#255#10#24'z'#255#7#21'y'#255#9#22'y'#255#9#23'{'
+ +#255#9#23'{'#255#8#22'z'#255#8#20'y'#255#8#21'y'#255#11#21'v'#255#13#23'p'
+ +#255#16#22'j'#255#13#19'`'#255#11#17']'#255#9#14']'#255#7#15'c'#255#6#15'j'
+ +#255#9#19's'#255#10#22'w'#255#13#22'w'#255#12#22't'#255#11#22'q'#255#13#22'l'
+ +#255#14#22'd'#255#10#16'Y'#255#14#17'T'#255#14#15'N'#255#15#16'L'#255#15#15
+ +'J'#255#15#16'I'#255#14#16'I'#255#13#15'F'#255#13#16'H'#255#14#16'J'#255#13
+ +#16'K'#255#13#15'K'#255#14#16'L'#255#14#16'L'#255#13#16'L'#255#13#15'K'#255
+ +#14#16'L'#255#13#15'K'#255#15#17'L'#255#12#14'J'#255#14#16'L'#255#12#14'I'
+ +#255#12#14'I'#255#14#16'F'#255#15#18'='#255#19#21'5'#255#15#15'$'#255#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#179#167#180#9'k{'
+ +#130#250'Yin'#255'i'#127#133#255'|'#146#154'('#0#0#0#0'Op'#160'E'#215#255#255
+ +#4#11'''ky'#17')z'#255#9#31'q'#255#9#29'm'#255#16#30'i'#255#15#27'^'#255#10
+ +#18'Q'#255#8#15'Q'#255#8#15'U'#255#11#20'd'#255#14#26'q'#255#11#27'w'#255#7
+ +#26'z'#255#8#28'}'#255#17'&'#130#255#16'"x'#255#14#30'n'#255#16#24'['#255#5
+ +#14'T'#255#6#15'Z'#255#13#23'j'#255#9#24't'#255#8#24'x'#255#7#24'y'#255#7#23
+ +'x'#255#8#23'{'#255#7#28'p'#255#5#30'{'#255#14'P'#185#255#22'z'#230#255#25'|'
+ +#232#255#25#130#237#255#26#129#227#255'#'#129#227#255','#132#223#255'C'#148
+ +#228#255'?|'#197#255#27'@|'#255#1#15'A'#255#0#14'D'#255#8#31'_'#255#12'0'#130
+ +#255#14'4'#131#255#17'4'#131#255#16'4'#127#255#9'-t'#255#1'%o'#255#11'0'#130
+ +#255#8'/'#136#255#11'0'#137#255#10'1'#135#255#7'.'#133#255#12'4'#138#255#10
+ +'1'#135#255#13'0'#133#255#10'1'#129#255#12'4~'#255#16'5}'#255#22'4q'#255#23
+ +'+Z'#255#3#20'6'#255#4#21'.'#255#17#19'/'#255#6#12'4'#255#1#23'M'#255#31'U'
+ +#167#255'/'#134#229#255#23'{'#233#255'#|'#239#255'"|'#235#255#29'x'#231#255
+ +' y'#232#255#30'x'#229#255#29'w'#231#255#30'x'#231#255#30'{'#233#255#29'y'
+ ,#233#255#26'v'#230#255#29'w'#232#255#31'w'#234#255'#y'#238#255'%v'#235#255#28
+ +'y'#236#255#28'z'#235#255'#|'#235#255'!|'#230#255#31#127#228#255'-'#136#233
+ +#255'''j'#204#255#2'2'#139#255#13'U'#187#255'5'#128#240#255'!y'#226#255#28
+ +#127#233#255#31#127#234#255#25#127#229#255#27'}'#232#255#27'|'#234#255#30'}'
+ +#235#255#31'{'#236#255#28'y'#235#255#25'z'#236#255#22'{'#239#255#18'z'#239
+ +#255#19'{'#240#255#10'j'#216#255#8'c'#211#255#4'_'#207#255#8'`'#211#255#7'^'
+ +#210#255#9'a'#214#255#6'^'#213#255#6'`'#215#255#8'`'#215#255#5'a'#214#255#10
+ +'_'#213#255#12'_'#213#255#8'c'#214#255#10'a'#212#255#9'U'#200#255#6'M'#193
+ +#255#1'N'#196#255#14'`'#214#255#9']'#211#255#3']'#209#255#4'^'#213#255#6'`'
+ +#214#255#8'_'#215#255#10'`'#218#255#8'\'#213#255#8'^'#215#255#5'['#212#255#6
+ +'\'#213#255#6'\'#215#255#9'_'#218#255#7'\'#216#255#7']'#217#255#10'`'#216#255
+ +#8'`'#218#255#5'_'#217#255#11'a'#217#255#9'^'#215#255#13'\'#214#255#17'P'#199
+ +#255#12'?'#166#255#2')'#149#255' M'#182#255#8'+'#145#255#14#31#133#255#8#25
+ +'{'#255#8#24'y'#255#7#24'y'#255#11#23'y'#255#10#23'x'#255#9#22'x'#255#9#24'{'
+ +#255#8#23'|'#255#8#24'z'#255#13#24'v'#255#15#24'p'#255#16#27'l'#255#14#22'a'
+ +#255#9#16'['#255#3#11'\'#255#14#23'n'#255#9#21'q'#255#9#24'x'#255#8#22'z'#255
+ +#11#21'z'#255#8#21'z'#255#8#22'{'#255#8#22'|'#255#9#21'}'#255#10#21'|'#255#13
+ +#21'x'#255#13#22'p'#255#15#22'h'#255#11#19'_'#255#11#16'['#255#9#14']'#255#11
+ +#17'e'#255#8#16'l'#255#10#19'u'#255#10#22'w'#255#11#22'v'#255#11#21's'#255#11
+ +#22'q'#255#12#22'k'#255#15#23'e'#255#12#18'['#255#14#18'S'#255#17#16'P'#255
+ +#16#16'L'#255#14#15'K'#255#15#16'J'#255#13#14'H'#255#12#13'F'#255#13#14'G'
+ +#255#13#15'I'#255#12#15'J'#255#13#14'J'#255#13#14'J'#255#14#14'J'#255#14#15
+ +'K'#255#14#14'K'#255#14#14'K'#255#13#13'K'#255#14#14'K'#255#14#14'K'#255#14
+ +#14'K'#255#12#13'I'#255#14#14'J'#255#15#16'F'#255#15#17'<'#255#17#19'3'#255#9
+ +#10#30#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#129#145#152#0#0#0#0#0'l}'#130'EYov'#255'Wmv.'#0#0#0#0'B`'#142'YIk'#171#150
+ +#22'0r'#228#11'%t'#254#10'!p'#255#11' n'#255#14#29'h'#255#16#28']'#255#10#19
+ +'N'#255#12#18'L'#255#9#15'K'#255#5#15'W'#255#9#21'c'#255#13#27'o'#255#8#27'u'
+ +#255#8#27'v'#255#10#29'v'#255#21')|'#255#16'"p'#255#11#21'W'#255#7#17'T'#255
+ +#5#15'W'#255#11#23'g'#255#10#24'r'#255#7#24'x'#255#8#25'z'#255#7#24'y'#255#6
+ +#26'|'#255#6#27's'#255#6':'#160#255#19'q'#223#255#20'y'#222#255#17'}'#230#255
+ +#20'~'#239#255'#'#129#226#255'4'#130#222#255'>'#142#224#255'0p'#183#255#16'1'
+ +'j'#255#9#16'@'#255#5#16'A'#255#8#31'^'#255#11'0|'#255#16'4'#132#255#15'5'
+ +#135#255#13'3'#137#255#13','#131#255#11'*|'#255#6'1'#131#255#9'5'#133#255#12
+ +'0'#132#255#8'1'#133#255#8'2'#134#255#7'2'#132#255#10'5'#135#255#11'3'#135
+ +#255#10'2'#132#255#11'2'#128#255#11'4}'#255#13'3w'#255#21'9p'#255#21',U'#255
+ +#15#18'2'#255#15#22','#255#5#19'!'#255#13#19'('#255#8#12'*'#255#3#20'@'#255
+ +#24'O'#154#255'*}'#228#255'''~'#232#255#28'~'#226#255#27'}'#234#255#31'~'#235
+ +#255#31'}'#227#255'!~'#231#255#30'}'#231#255#28'|'#230#255#29'}'#232#255#27
+ +'{'#231#255#30'|'#234#255'!}'#236#255' z'#235#255' z'#231#255#31'{'#232#255
+ +#23'w'#228#255#24'|'#232#255#29'}'#231#255'"z'#226#255' |'#225#255'&'#136#234
+ +#255#29'`'#179#255#0','#133#255#20'i'#213#255'$'#129#234#255#31'}'#228#255' '
+ +'|'#235#255#22#130#229#255#26'}'#233#255#24'}'#233#255#28'~'#235#255#28'|'
+ +#234#255#29'|'#236#255#23'z'#235#255#20'}'#238#255#18'}'#237#255#17'|'#239
+ +#255#9'k'#215#255#5'e'#209#255#5'd'#210#255#7'c'#211#255#6'b'#211#255#10'f'
+ +#216#255#4'^'#211#255#5'`'#212#255#7'^'#214#255#9'`'#208#255#6'b'#208#255#5
+ +'b'#210#255#12'`'#209#255#9'R'#189#255#6'L'#184#255#6'W'#198#255#6'\'#211#255
+ +#6'^'#210#255#6'_'#209#255#7'd'#210#255#4'b'#208#255#6'a'#209#255#7'_'#210
+ +#255#9'`'#215#255#6'^'#210#255#8'_'#212#255#5']'#207#255#7'`'#209#255#7'`'
+ +#208#255#10'c'#211#255#6'`'#208#255#7'a'#209#255#7'b'#209#255#6'a'#211#255#5
+ +'`'#211#255#8'b'#211#255#7'a'#210#255#9'`'#213#255#11'V'#199#255#8'<'#159#255
+ +#1'2'#156#255#28'T'#191#255#3'1'#151#255#10'"'#133#255#5#27'y'#255#7#25'v'
+ +#255#5#24'u'#255#10#24'v'#255#7#23'w'#255#7#23'w'#255#8#25'y'#255#7#24'z'#255
+ +#8#25'x'#255#8#25'r'#255#14#26'n'#255#15#26'i'#255#12#23'\'#255#7#17'U'#255#2
+ +#12'X'#255#12#23'h'#255#9#25'p'#255#6#24't'#255#6#23'x'#255#7#23'x'#255#6#21
+ +'y'#255#7#21'{'#255#7#21'{'#255#6#21'{'#255#8#22'|'#255#9#22'x'#255#13#22'p'
+ +#255#12#22'i'#255#10#20'`'#255#7#18'['#255#6#14']'#255#9#17'g'#255#8#18'n'
+ +#255#8#21'w'#255#8#22'w'#255#9#21'v'#255#8#21'r'#255#10#22'q'#255#12#22'k'
+ +#255#13#22'd'#255#11#19'Z'#255#13#19'T'#255#14#16'N'#255#14#16'L'#255#15#17
+ +'K'#255#14#17'H'#255#12#15'F'#255#12#15'F'#255#13#16'I'#255#11#16'I'#255#12
+ +#15'J'#255#9#14'J'#255#10#14'J'#255#12#16'J'#255#12#16'K'#255#11#16'K'#255#13
+ +#16'K'#255#12#14'J'#255#14#14'L'#255#12#13'J'#255#12#16'L'#255#10#15'I'#255
+ +#10#14'H'#255#14#18'E'#255#15#20'<'#254#20#23'4'#255#13#15'!'#255#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ ,'n'#134#150'i?Zn'#249'@[w'#138'f'#135#185'b:]'#161#255#17')k'#254#10'#o'#255
+ +#6#29'k'#255#9#31'l'#255#14' j'#255#16#29'^'#255#10#20'M'#255#11#18'L'#255#12
+ +#20'L'#255#7#16'J'#255#5#16'P'#255#8#22'['#255#13#29'h'#255#11#29'j'#255#14
+ +' i'#255#13#31'e'#255#19'"e'#255#16'"d'#255#5#21'X'#255#0#15'U'#255#9#23'd'
+ +#255#8#25'p'#255#7#26'u'#255#5#26'x'#255#7#27'x'#255#3#30'v'#255#4'$'#133#255
+ +#17'b'#203#255#18#127#233#255#24#128#224#255#21#132#228#255#28#129#228#255'*'
+ +#135#224#255'7'#147#228#255'2u'#191#255#10'+j'#255#11#15'A'#255#7#16'D'#255
+ +#11'&f'#255#11'3'#127#255#9'2}'#255#10'$l'#255#1'&h'#255#6'''`'#255#11#24'V'
+ +#255#3#18'X'#255#11'-x'#255#4'3'#129#255#9'3'#132#255#9'4'#133#255#8'5'#132
+ +#255#9'6'#132#255#9'6'#132#255#7'2'#131#255#9'2'#129#255#9'3'#128#255#13'6'
+ +#127#255#14'7y'#255#14'8k'#255#26'4V'#255#13#21'.'#255#15#22')'#255#12#17#27
+ +#255#9#12#24#255#3#14#31#255#4#13'#'#255#1#13'<'#255#22'G'#142#255'0'#131#216
+ +#255'"'#127#221#255#27'~'#226#255#25#127#228#255#28#128#225#255#27'~'#226#255
+ +#26'|'#225#255#26'|'#225#255#30#127#230#255#29'~'#230#255#27'}'#229#255#26'{'
+ +#229#255#26'{'#230#255#27#127#227#255#24'}'#225#255#22'{'#226#255#26#127#229
+ +#255#25'~'#226#255#29#128#227#255#28#130#226#255'"'#134#228#255'+'#144#230
+ +#255#17'H'#155#255#0'@'#148#255#30#128#223#255#27'z'#225#255#24'|'#229#255#21
+ +'}'#234#255#27#128#231#255#20#127#232#255#24#128#235#255#23'}'#233#255#28#127
+ +#237#255#20'}'#235#255#19#128#239#255#16'~'#238#255#14'z'#234#255#3'e'#210
+ +#255#6'f'#211#255#5'd'#209#255#6'e'#211#255#9'b'#209#255#7'c'#211#255#7'c'
+ +#211#255#5'a'#209#255#6'c'#212#255#8'a'#208#255#4'd'#209#255#3'^'#199#255#5
+ +'O'#185#255#8'R'#189#255#8']'#201#255#6'd'#207#255#6'_'#210#255#6'_'#210#255
+ +#8'b'#210#255#7'`'#208#255#8'b'#208#255#7'c'#209#255#6'b'#208#255#7'c'#209
+ +#255#6'c'#208#255#7'd'#209#255#4'c'#205#255#7'e'#208#255#6'd'#207#255#7'e'
+ +#208#255#4'c'#204#255#6'e'#206#255#4'd'#204#255#6'd'#208#255#9'd'#209#255#11
+ +'f'#210#255#1'`'#204#255#8'f'#210#255#12']'#198#255#8'>'#156#255#0':'#162#255
+ +#25'Z'#194#255#7':'#157#255#7'"'#131#255#4#30'y'#255#7#26'v'#255#5#26'v'#255
+ +#9#25'w'#255#7#23'w'#255#8#26'y'#255#8#26'x'#255#7#25'x'#255#7#24'u'#255#6#25
+ +'p'#255#10#28'j'#255#14#28'e'#255#11#22'U'#255#7#18'P'#255#2#13'S'#255#7#19
+ +'a'#255#7#24'm'#255#6#24's'#255#4#22'u'#255#7#23'w'#255#6#22'z'#255#7#24'{'
+ +#255#7#23'z'#255#6#22'y'#255#7#23'x'#255#7#22'v'#255#10#24'o'#255#9#24'h'#255
+ +#8#20'a'#255#5#17']'#255#5#16'`'#255#9#21'j'#255#7#20'p'#255#7#23'w'#255#6#23
+ +'w'#255#7#23'u'#255#7#22's'#255#9#24'r'#255#12#24'l'#255#10#22'd'#255#10#19
+ +'Y'#255#10#18'R'#255#11#16'L'#255#10#16'H'#255#13#18'I'#255#13#17'H'#255#10
+ +#14'E'#255#9#15'G'#255#11#16'J'#255#9#15'K'#255#9#16'K'#255#9#16'L'#255#8#16
+ +'J'#255#10#16'K'#255#10#16'K'#255#9#16'K'#255#10#16'K'#255#11#16'K'#255#11#16
+ +'J'#255#10#14'J'#255#9#15'I'#255#8#16'I'#255#10#17'I'#255#13#17'D'#254#13#18
+ +';'#254#18#21'3'#253#10#11#30#250#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'm'#139#169#131'8\'#134
+ +#255#0#0#0#0'Eo'#184#145#13'+t'#255#11'"q'#255#9#31'o'#255#9#30'm'#255#12#30
+ +'j'#255#13#29'_'#255#7#20'O'#255#6#17'I'#255#9#20'J'#255#10#20'F'#255#9#19'F'
+ +#255#6#17'H'#255#10#21'P'#255#17#27'X'#255#16#27'W'#255#10#20'N'#255#8#18'J'
+ +#255#9#25'Y'#255#17'%h'#255#7#26'e'#255#7#25'i'#255#7#26'n'#255#9#25'q'#255#7
+ +#27't'#255#4#27'v'#255#2#31'r'#255#9'<'#163#255#26'{'#229#255#18#127#228#255
+ +#27#133#231#255#29#134#230#255'%'#132#222#255'4'#146#235#255'#i'#184#255#14
+ +':'#127#255#3#28'U'#255#7#30'X'#255#1'*h'#255#4'$m'#255#1#31'n'#255#15'0'#133
+ +#255#9'@'#152#255#17'['#186#255#28't'#218#255#31'l'#208#255#19'H'#155#255#2
+ +#31'_'#255#7#23'Y'#255#13'''q'#255#5'3'#130#255#11'5'#129#255#6'4'#127#255#5
+ +'5'#130#255#15'3'#131#255#11'2'#129#255#6'3~'#255#9'6|'#255#16'2z'#255#19'7q'
+ +#255#23'2Y'#255#10#28'1'#255#16#26'&'#255#15#17#22#255#18#14#20#255#9#13#21
+ +#255#7#11#31#255#10#13'%'#255#0#19'A'#255#16'O'#150#255'(z'#212#255'!'#127
+ +#224#255#28#129#230#255#30#129#226#255'!'#134#230#255#28#129#226#255#27#127
+ +#225#255#27#127#226#255#25#127#226#255#27#127#229#255#27#127#229#255#26'~'
+ +#228#255#25'}'#227#255#24#127#227#255#25#128#227#255#29#130#230#255#30#131
+ +#231#255#25#128#229#255#30#133#231#255#31#130#226#255' '#139#231#255#28#133
+ +#213#255#5'8~'#255#9'l'#188#255#27#131#233#255#23#129#227#255#22'|'#233#255
+ +#25'}'#234#255#25#128#236#255#25#127#235#255#23'y'#230#255#24'z'#232#255#24
+ +'|'#234#255#23#127#239#255#21#128#240#255#19'}'#237#255#5'e'#209#255#11'h'
+ +#213#255#3'b'#208#255#7'e'#212#255#7'd'#211#255#6'`'#209#255#10'f'#214#255#5
+ +']'#206#255#6'h'#212#255#7'f'#212#255#6'V'#197#255#11'V'#190#255#5'Y'#192#255
+ +#5'b'#205#255#3'c'#210#255#6'c'#209#255#7'c'#215#255#6'b'#213#255#7'b'#213
+ +#255#4'`'#210#255#6'b'#211#255#5'b'#210#255#4'b'#207#255#5'c'#208#255#4'a'
+ +#206#255#6'c'#208#255#4'b'#207#255#8'f'#212#255#5'c'#210#255#7'd'#211#255#7
+ +'b'#210#255#7'b'#209#255#5'c'#209#255#9'a'#207#255#5'b'#206#255#11'g'#211#255
+ ,#4'`'#207#255#11'g'#212#255#10'['#194#255#1'4'#147#255#5'G'#179#255#23']'#201
+ +#255#9'<'#163#255#8'$'#135#255#3#28'{'#255#4#25'x'#255#6#26'y'#255#7#25'{'
+ +#255#6#24'y'#255#9#27'z'#255#6#25'x'#255#6#24'v'#255#5#25't'#255#6#27'o'#255
+ +#11#29'i'#255#13#29'a'#255#9#22'Q'#255#7#18'N'#255#4#14'P'#255#6#16'['#255#7
+ +#22'i'#255#6#24'q'#255#6#23'u'#255#8#24'v'#255#7#23'y'#255#5#21'x'#255#7#25
+ +'x'#255#6#23'w'#255#8#24'w'#255#7#23't'#255#9#24'n'#255#7#23'g'#255#7#20'a'
+ +#255#6#19'_'#255#5#17'c'#255#6#19'i'#255#5#22'p'#255#6#22'u'#255#5#23'v'#255
+ +#6#23'v'#255#7#23't'#255#8#23's'#255#11#24'm'#255#9#20'c'#255#9#18'X'#255#9
+ +#16'Q'#255#13#17'L'#255#12#17'I'#255#14#18'H'#255#12#16'E'#255#11#14'E'#255
+ +#10#15'H'#255#10#16'J'#255#10#16'K'#255#10#17'L'#255#9#17'L'#255#8#15'K'#255
+ +#9#15'J'#255#9#15'J'#255#10#15'J'#255#10#15'J'#255#10#15'J'#255#10#15'J'#255
+ +#10#15'J'#255#10#16'I'#255#8#15'G'#255#10#16'H'#254#12#16'B'#254#14#18'9'#252
+ +#19#21'/'#255#13#13#30#149#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'\'#137#179#130',^'#150
+ +#226'-X'#157#173#17'1~'#255#5#26'l'#255#7#28'n'#255#10#29'o'#255#14#30'l'#255
+ +#16#30'c'#255#9#21'Q'#255#7#17'H'#255#12#19'H'#255#9#20'E'#255#10#21'F'#255#7
+ +#18'C'#255#8#19'E'#255#8#19'E'#255#9#19'F'#255#9#19'G'#255#9#19'F'#255#5#18
+ +'K'#255#4#20'S'#255#10#27'h'#255#16'$w'#255#7#28's'#255#3#26'q'#255#6#29's'
+ +#255#4#26's'#255#3#28'v'#255#14'Y'#194#255#28'{'#233#255#26'|'#226#255#29#127
+ +#227#255'%'#131#229#255'.'#139#227#255'.{'#214#255#14'D'#139#255#8'8'#133#255
+ +#7'0'#127#255#4'%t'#255#3'4'#135#255#8'@'#155#255#20'^'#200#255#16's'#231#255
+ +#20'w'#243#255#16'y'#239#255#17'w'#232#255#22'}'#233#255#28#128#242#255' {'
+ +#237#255#13'N'#175#255#2')w'#255#4#27'a'#255#8',{'#255#9'3'#136#255#16'3'#133
+ +#255#8'6'#127#255#9'4'#128#255#14'2~'#255#12'3~'#255#14'2y'#255#21'7v'#255#28
+ +'7f'#255#18#31'<'#255#17#23'%'#255#17#16#23#255#13#14#20#255#10#14#20#255#8
+ +#15#22#255#9#13#30#255#8#10')'#255#3#21'F'#255#21'M'#152#255'*'#129#224#255
+ +#30'z'#218#255' |'#224#255#29#128#224#255#26'}'#222#255#29#127#225#255#30#128
+ +#226#255#26'~'#226#255#26'}'#227#255#28#127#229#255#29#127#231#255#30'~'#230
+ +#255#28#128#229#255#28'~'#227#255#26'~'#226#255#28'}'#231#255#28'}'#233#255
+ +#30#127#233#255#29#127#233#255#30#131#231#255'&'#141#236#255'!r'#194#255#0'>'
+ +#141#255#8't'#203#255#30#134#235#255#24#127#228#255#23'~'#233#255#27#127#239
+ +#255#28'~'#238#255#27'|'#234#255#28'}'#234#255#25'{'#237#255#24#127#241#255
+ +#19'}'#238#255#17'{'#235#255#5'e'#209#255#8'l'#216#255#1'f'#213#255#8'b'#214
+ +#255#15'a'#216#255#11'_'#213#255#8'b'#214#255#8'g'#217#255#10'`'#203#255#2'U'
+ +#194#255#3'S'#194#255#8']'#203#255#5']'#205#255#7'a'#210#255#7'c'#212#255#8
+ +'`'#214#255#7'a'#216#255#5'_'#213#255#4'_'#211#255#4'`'#210#255#5'a'#210#255
+ +#6'a'#210#255#4'`'#209#255#6'b'#211#255#4'`'#208#255#7'c'#212#255#4'`'#209
+ +#255#7'a'#213#255#9'c'#215#255#8'b'#214#255#8'a'#213#255#6'_'#212#255#9'\'
+ +#204#255#0'I'#185#255#6'b'#206#255#9'c'#209#255#9'a'#212#255#11'e'#213#255#11
+ +'X'#198#255#5':'#157#255#6'L'#190#255#23'_'#208#255#17'B'#176#255#6'"'#137
+ +#255#6#31#128#255#7#29'|'#255#9#26'z'#255#5#26'{'#255#8#25'|'#255#9#26'{'#255
+ +#8#25'z'#255#9#25'y'#255#6#25'u'#255#7#26'n'#255#14#29'g'#255#13#26']'#255#9
+ +#18'N'#255#7#16'K'#255#7#15'P'#255#4#14'V'#255#8#19'g'#255#7#23'r'#255#5#22
+ +'v'#255#7#23'w'#255#7#21'z'#255#7#21'{'#255#7#22'y'#255#6#22'w'#255#10#23'y'
+ +#255#11#22'v'#255#12#22'p'#255#10#22'g'#255#6#18'a'#255#5#17'_'#255#6#16'd'
+ +#255#8#18'k'#255#8#21'p'#255#8#21'u'#255#9#23'w'#255#7#21'v'#255#10#22'x'#255
+ +#9#22'u'#255#13#22'o'#255#12#20'd'#255#11#18'Z'#255#12#17'R'#255#15#16'L'#255
+ +#14#16'K'#255#14#16'F'#255#12#15'D'#255#12#15'E'#255#12#16'I'#255#12#16'J'
+ +#255#11#17'L'#255#10#16'K'#255#10#16'K'#255#10#15'K'#255#11#15'L'#255#10#15
+ +'J'#255#12#16'K'#255#11#15'J'#255#11#15'J'#255#11#15'J'#255#12#16'K'#255#12
+ +#16'J'#255#12#14'G'#255#13#17'G'#255#14#17'@'#253#20#21'9'#251#22#20'/'#228
+ +#20#15#31'#'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'8p'#159#168#11':x'#255#16'4'
+ +'|'#255#5#30'o'#255#7#31'p'#255#8#30's'#255#11#30'm'#255#14#29'd'#255#12#24
+ +'W'#255#9#18'K'#255#13#18'H'#255#10#17'B'#255#13#20'E'#255#11#18'D'#255#13#20
+ +'E'#255#13#19'F'#255#12#19'E'#255#12#19'F'#255#14#20'H'#255#6#20'F'#255#7#16
+ +'J'#255#7#13'U'#255#12#27'l'#255#13''''#127#255#8''''#129#255#5#30'v'#255#9
+ +#26's'#255#8''''#137#255#18'o'#219#255' {'#233#255'#'#128#229#255'$'#129#229
+ +#255'2'#137#235#255'*'#136#221#255#26'P'#168#255#8'4'#141#255#7'*'#128#255#6
+ +'1'#141#255#13'L'#176#255#10'v'#233#255#17'p'#244#255#21'x'#247#255#8'u'#235
+ +#255#16'x'#231#255#15'p'#230#255#11'n'#232#255#17'o'#236#255#19'k'#225#255#20
+ +'u'#227#255#16'{'#225#255#31'y'#228#255#18'E'#158#255#5'"t'#255#7'&s'#255#13
+ +'5'#135#255#14'0'#135#255#15'3'#129#255#8'/~'#255#13'2'#133#255#14'4~'#255#21
+ +'6y'#255#26'6h'#255#22'''H'#255#14#23'('#255#15#18#25#255#13#14#19#255#11#15
+ ,#15#255#12#18#17#255#12#12#23#255#9#11'"'#255#7#11'.'#255#0#15'F'#255#31'M'
+ +#161#255'&z'#222#255'%x'#224#255'!~'#225#255' |'#223#255'!}'#226#255'"'#127
+ +#230#255'!'#128#231#255#31#128#232#255#29'~'#230#255#29'}'#233#255#31'|'#228
+ +#255' '#127#230#255#31'~'#229#255' }'#230#255#28'z'#230#255#27'z'#233#255#29
+ +'|'#234#255#26'{'#234#255#26'z'#231#255'!}'#231#255')'#135#239#255#27'U'#168
+ +#255#1'J'#155#255''''#132#237#255#24'{'#228#255#25'~'#228#255#27'~'#238#255
+ +#25'{'#234#255#28'~'#235#255#29#127#237#255#21'}'#237#255#22#127#242#255#20
+ +'~'#241#255#17'{'#236#255#10'h'#211#255#12'k'#215#255#5'c'#212#255#11'a'#216
+ +#255#6'_'#216#255#1'_'#211#255#12'e'#214#255#10'S'#195#255#8'L'#185#255#4'S'
+ +#191#255#8'`'#207#255#6'e'#216#255#3'^'#213#255#9'`'#216#255#9'`'#215#255#7
+ +'_'#214#255#6'`'#215#255#8'b'#217#255#8'b'#217#255#7'a'#215#255#7'`'#215#255
+ +#7'a'#215#255#6'`'#215#255#9'c'#218#255#3'`'#214#255#7'a'#216#255#8'`'#214
+ +#255#9'`'#216#255#10'`'#216#255#8'_'#215#255#7'`'#216#255#7'b'#216#255#17'\'
+ +#204#255#0'J'#186#255#8'^'#205#255#10'`'#214#255#6']'#212#255#16'i'#219#255#8
+ +'T'#195#255#0'7'#164#255#14'V'#206#255#17'Z'#209#255#23'I'#185#255#5' '#139
+ +#255#4#29#128#255#4#27'{'#255#8#25'y'#255#6#24'{'#255#6#22'z'#255#8#24'z'#255
+ +#8#24'y'#255#8#24'x'#255#7#26'v'#255#9#25'n'#255#17#30'h'#255#17#25'\'#255#13
+ +#19'O'#255#9#15'I'#255#8#15'Q'#255#6#14'W'#255#10#18'h'#255#7#22'r'#255#6#22
+ +'v'#255#7#23'w'#255#8#22'{'#255#8#22'|'#255#6#21'y'#255#10#22'y'#255#10#22'x'
+ +#255#13#22'w'#255#14#21'q'#255#12#22'j'#255#10#18'b'#255#8#17'a'#255#7#16'g'
+ +#255#7#18'l'#255#9#20's'#255#9#20'u'#255#10#21'w'#255#9#20'v'#255#13#22'x'
+ +#255#11#21't'#255#12#21'm'#255#11#18'c'#255#11#17'Y'#255#13#16'S'#255#16#16
+ +'L'#255#16#17'L'#255#13#15'H'#255#11#14'E'#255#10#14'F'#255#10#15'H'#255#11
+ +#15'I'#255#10#16'K'#255#9#15'J'#255#10#16'K'#255#10#14'K'#255#11#14'K'#255#11
+ +#14'K'#255#12#15'L'#255#11#14'J'#255#12#16'J'#255#11#15'J'#255#12#16'K'#255
+ +#12#15'I'#255#12#14'H'#255#11#16'C'#253#19#18'>'#251#22#19'5'#252#25#19'+'
+ +#145'%'#30'+ '#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#141#198#233#8' P'#130#254
+ +#18'9|'#255#20'6'#131#255#11')|'#255#5'"v'#255#4#30'n'#255#9#31'h'#255#10#26
+ +'['#255#5#19'M'#255#11#18'I'#255#12#17'G'#255#13#19'H'#255#11#17'F'#255#14#20
+ +'I'#255#12#18'G'#255#12#18'F'#255#12#18'E'#255#13#19'G'#255#9#19'H'#255#8#16
+ +'I'#255#9#16'Q'#255#5#17'\'#255#7#29'r'#255#7'"}'#255#13''''#130#255#4#27'u'
+ +#255#9'4'#151#255'*~'#236#255#31'}'#231#255'$'#131#228#255'$'#131#229#255'4'
+ +#140#236#255#20'Z'#177#255#7'+'#129#255#7')'#127#255#2'B'#166#255#15'l'#225
+ +#255#19's'#243#255#9'y'#238#255#16't'#226#255#20'x'#235#255#20'r'#236#255#13
+ +'s'#242#255#19'q'#234#255#19'r'#232#255#8'q'#237#255#4'o'#238#255#10's'#238
+ +#255#12'p'#229#255#23'{'#238#255#21#130#240#255#26'n'#205#255#13'1'#132#255#3
+ +#23'f'#255#1'.|'#255#5'4'#131#255#10'/'#130#255#16'3'#134#255#10'3~'#255#16
+ +'7}'#255#21'8n'#255#25'3Y'#255#15#31'6'#255#11#19#29#255#13#19#22#255#10#15
+ +#14#255#11#15#18#255#12#14#19#255#3#12#28#255#5#14'.'#255#8#14'>'#255#3#27'`'
+ +#255#27'P'#175#255'*x'#222#255'"y'#221#255'#{'#223#255'&'#128#229#255' ~'#227
+ +#255#31#127#230#255' '#129#233#255#31#128#232#255#31#128#233#255#28#127#230
+ +#255#29#128#230#255#29'}'#227#255#30'~'#230#255#30'}'#232#255#27'{'#233#255
+ +' '#129#238#255#27'}'#234#255#28#129#234#255'${'#233#255''''#132#241#255')'
+ +#132#228#255#3'2'#143#255#23'f'#201#255#29'~'#238#255#27'|'#228#255#29#127
+ +#236#255#28#127#235#255#26'~'#233#255#24'|'#233#255#18'{'#233#255#18'|'#237
+ +#255#18'|'#237#255#17'{'#235#255#5'e'#210#255#16'g'#214#255#12'c'#211#255#8
+ +'d'#212#255#8'c'#212#255#3'Z'#200#255#8'T'#192#255#4'H'#181#255#9'\'#200#255
+ +#10'b'#206#255#5'`'#204#255#7'd'#212#255#3'`'#211#255#6'a'#213#255#7'`'#213
+ +#255#7'd'#217#255#5'b'#214#255#4'b'#213#255#1'_'#210#255#5'b'#213#255#7'd'
+ +#216#255#6'c'#215#255#2'_'#213#255#4'a'#215#255#1']'#207#255#10'e'#215#255#5
+ +'a'#212#255#6'b'#214#255#8'c'#215#255#8'b'#215#255#12'e'#215#255#6'\'#206#255
+ +#8'P'#188#255#0'K'#184#255#8'b'#211#255#10'^'#211#255#7'a'#211#255#9'e'#213
+ +#255#6'N'#191#255#0'='#169#255#13'Y'#206#255#17']'#210#255#23'K'#187#255#7'&'
+ +#143#255#4#31#129#255#4#27'{'#255#12#25'{'#255#7#22'z'#255#7#23'y'#255#8#25
+ +'y'#255#8#25'y'#255#8#26'w'#255#8#26't'#255#11#28'n'#255#16#29'd'#255#11#20
+ +'U'#255#10#16'K'#255#9#15'I'#255#11#17'S'#255#7#14'X'#255#10#20'j'#255#8#24
+ +'u'#255#5#22'x'#255#9#24'{'#255#8#23'|'#255#6#22'z'#255#8#24'y'#255#7#22'w'
+ +#255#9#23'v'#255#11#22'u'#255#12#20'n'#255#9#20'e'#255#8#16'`'#255#6#16'`'
+ +#255#7#17'i'#255#8#20'q'#255#9#21'x'#255#8#20'y'#255#9#21'z'#255#9#20'y'#255
+ +#12#24'v'#255#11#21'r'#255#11#20'k'#255#10#18'b'#255#11#18'Y'#255#13#18'S'
+ +#255#12#18'L'#255#15#19'L'#255#11#14'H'#255#10#14'H'#255#10#14'H'#255#11#15
+ +'I'#255#11#16'J'#255#9#16'J'#255#9#15'J'#255#10#16'L'#255#11#15'L'#255#11#15
+ +'L'#255#11#15'L'#255#12#16'M'#255#11#14'K'#255#12#14'L'#255#11#15'K'#255#9#14
+ ,'I'#255#11#15'I'#255#11#17'G'#254#14#18'B'#253#20#19':'#250#22#19'/'#248#29
+ +#25'(B2-6.'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'=p'#157#140#13'8r'#255
+ +#8'''m'#255#13'*y'#255#22'2'#133#255#14'+'#127#255#10'$s'#255#7#29'`'#255#5
+ +#19'O'#255#11#19'J'#255#9#17'G'#255#10#19'F'#255#9#19'C'#255#10#20'E'#255#10
+ +#17'E'#255#13#20'H'#255#11#18'D'#255#12#19'B'#255#11#17'J'#255#7#17'K'#255#6
+ +#16'O'#255#8#19'\'#255#9#25'k'#255#6#26's'#255#6#30'w'#255#9'#z'#255#9'/'#142
+ +#255#31'f'#204#255#29'|'#222#255'%'#127#226#255')'#141#242#255#31'j'#203#255
+ +#2'&'#129#255#6'1'#143#255#2'Z'#198#255#23'p'#232#255#19'v'#243#255#17't'#236
+ +#255#9'u'#234#255#18't'#242#255#17'q'#239#255#10'u'#235#255#12't'#237#255#12
+ +'u'#241#255#12'r'#239#255#18'r'#235#255#13'q'#234#255#15'p'#236#255#17'r'#237
+ +#255#9'v'#232#255#13'w'#232#255#19'~'#237#255#29#129#234#255#20'Z'#173#255#1
+ +'!i'#255#11'&t'#255#2'/'#129#255#10'2'#135#255#14'4'#132#255#14'6'#128#255#13
+ +'4r'#255#24';h'#255#18'&D'#255#9#19'%'#255#13#16#27#255#11#14#19#255#14#14#19
+ +#255#4#15#25#255#7#10#28#255#10#10'$'#255#3#25'K'#255#12'&h'#255#4'"n'#255#29
+ +'S'#181#255'*{'#227#255'$z'#223#255'%|'#227#255#29'}'#227#255#31#128#232#255
+ +' ~'#229#255#28#127#231#255#30'}'#232#255#26#128#231#255#28#130#233#255#29
+ +#128#232#255' '#130#236#255#30#127#235#255#27'}'#235#255#27'}'#234#255#27'}'
+ +#234#255#25#128#233#255'#'#127#232#255#26'~'#228#255''''#133#241#255#26'`'
+ +#196#255#1'A'#162#255#28'}'#242#255#27'w'#231#255#26'}'#233#255#27#127#234
+ +#255#29#128#235#255#24'|'#232#255#20'|'#233#255#20#128#237#255#19'~'#237#255
+ +#18'y'#235#255#10'k'#217#255#11'i'#217#255#4'b'#213#255#8'd'#215#255#10'['
+ +#201#255#5'I'#178#255#10'T'#191#255#2'd'#209#255#6'e'#211#255#3'b'#208#255#6
+ +'a'#207#255#11'f'#213#255#5'`'#209#255#10'e'#215#255#5'a'#213#255#10'f'#219
+ +#255#6'b'#215#255#8'f'#215#255#5'c'#212#255#9'f'#214#255#5'b'#211#255#8'e'
+ +#215#255#5'b'#212#255#8'e'#216#255#10'c'#212#255#9'b'#213#255#6'e'#214#255#5
+ +'f'#213#255#8'd'#211#255#6'a'#213#255#13'e'#215#255#4'Q'#191#255#1'K'#183#255
+ +#11'a'#205#255#8'c'#212#255#8'a'#214#255#2'^'#209#255#15'g'#215#255#9'N'#190
+ +#255#1'D'#178#255#17'_'#213#255#16'^'#210#255#17'F'#180#255#9''''#144#255#6
+ +#31#129#255#6#27'~'#255#9#23'|'#255#9#24'{'#255#7#23'x'#255#7#24'x'#255#7#24
+ +'w'#255#9#26'w'#255#7#25'r'#255#12#27'k'#255#15#29'b'#255#11#20'R'#255#11#18
+ +'N'#255#10#17'M'#255#8#14'Q'#255#7#14'Y'#255#11#22'l'#255#8#23'w'#255#5#20'z'
+ +#255#7#23'{'#255#7#23'{'#255#7#23'z'#255#8#24'z'#255#6#23'w'#255#8#25'v'#255
+ +#12#24's'#255#12#21'm'#255#9#20'f'#255#7#15'`'#255#8#17'c'#255#8#18'i'#255#8
+ +#21'r'#255#7#21'x'#255#7#20'z'#255#9#22'|'#255#9#21'y'#255#11#23'u'#255#10#22
+ +'r'#255#13#23'l'#255#11#21'b'#255#12#20'Z'#255#12#19'R'#255#13#17'L'#255#12
+ +#16'H'#255#11#14'F'#255#12#16'I'#255#13#15'J'#255#12#16'J'#255#11#16'J'#255
+ +#11#15'K'#255#9#14'K'#255#11#16'N'#255#10#16'N'#255#10#17'N'#255#8#15'L'#255
+ +#11#15'L'#255#9#14'L'#255#10#14'L'#255#10#13'J'#255#11#15'K'#254#11#16'H'#255
+ +#13#17'D'#252#14#18'='#251#21#19'7'#250#21#18')'#147'6074'#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#21'D{'#255#8'!e'#255#2#25'e'#255#4
+ +#28'p'#255#6' w'#255#15'+'#127#255#26'5'#128#255#13'#f'#255#7#23'V'#255#4#18
+ +'B'#255#7#18'H'#255#6#16'H'#255#11#20'J'#255#13#21'E'#255#12#20'D'#255#11#19
+ +'F'#255#11#17'L'#255#10#19'G'#255#8#17'K'#255#7#15'P'#255#7#17'['#255#9#24'l'
+ +#255#7#27'r'#255#5#28'r'#255#6#29's'#255#2'-'#131#255#14'T'#188#255#20'l'#208
+ +#255'(y'#232#255'!'#134#240#255#15'-'#145#255#2'8'#160#255#15'g'#214#255#16
+ +'s'#235#255#17'u'#237#255#17'u'#239#255#17'v'#240#255#15't'#238#255#16'u'#239
+ +#255#15'u'#238#255#13'q'#234#255#13'v'#237#255#15'v'#238#255#14'v'#236#255#14
+ +'w'#236#255#7'q'#230#255#12'v'#234#255#11'u'#234#255#10't'#232#255#9'v'#228
+ +#255#10't'#228#255#18'w'#233#255#26#130#236#255#29't'#214#255#14'7'#146#255#8
+ +#28'q'#255#3'0z'#255#7'0'#129#255#9'5'#131#255#12'7'#127#255#21'6r'#255#25'6'
+ +'d'#255#4' ;'#255#1#17#31#255#10#15#23#255#12#14#22#255#1#13#29#255#7#9' '
+ +#255#4#11'+'#255#4#30'U'#255#15'.r'#255#7'#n'#255#4'"s'#255#28'c'#202#255'&}'
+ +#227#255'!y'#223#255#29'~'#233#255#29#130#233#255'"'#128#232#255#23'~'#231
+ +#255#29#127#234#255#27'~'#229#255#30#130#233#255#28#127#232#255#28'~'#233#255
+ +#28'z'#233#255#29'{'#234#255#28'{'#233#255'!'#128#239#255#27#130#229#255#26
+ +#131#229#255#25#127#225#255#25#128#231#255'%'#136#230#255#4'<'#148#255#6'h'
+ +#204#255' '#129#237#255#24'y'#232#255#27'~'#235#255#28'~'#235#255#28'}'#232
+ +#255#26#127#231#255#18#129#233#255#20#131#236#255#25'}'#234#255#10'e'#216#255
+ +#12'h'#215#255#8'\'#197#255#5'H'#177#255#1'F'#178#255#8'Z'#202#255#7'a'#211
+ +#255#11'c'#214#255#8'd'#212#255#7'c'#211#255#6'b'#210#255#9'c'#214#255#8'c'
+ +#214#255#9'c'#215#255#3'\'#211#255#9'c'#218#255#7'c'#218#255#5'a'#216#255#4
+ +'a'#214#255#7'a'#215#255#6'`'#212#255#6'a'#214#255#5'_'#213#255#6'b'#215#255
+ ,#6'`'#213#255#5'e'#213#255#7'b'#209#255#7'b'#209#255#6'g'#213#255#4'b'#208
+ +#255#8'W'#198#255#5'N'#187#255#6'['#201#255#8'c'#214#255#7'b'#216#255#8'c'
+ +#219#255#1'a'#213#255#12'd'#213#255#3'K'#188#255#5'S'#193#255#12']'#210#255
+ +#21'e'#214#255#13'D'#174#255#9'$'#138#255#4#29'~'#255#6#27'}'#255#10#25'|'
+ +#255#7#25'|'#255#8#24'y'#255#8#24'y'#255#7#23'w'#255#9#27'v'#255#7#25'n'#255
+ +#13#28'h'#255#14#26'^'#255#9#17'O'#255#9#15'L'#255#9#17'N'#255#6#13'P'#255#5
+ +#12'Z'#255#11#21'k'#255#8#22'u'#255#5#21'w'#255#8#24'z'#255#7#23'y'#255#8#22
+ +'z'#255#9#24'y'#255#8#24'u'#255#8#21'q'#255#14#24'o'#255#12#22'j'#255#9#19'e'
+ +#255#8#16'b'#255#9#19'f'#255#7#18'j'#255#8#21'r'#255#8#22'w'#255#6#21'v'#255
+ +#8#21'w'#255#8#22'u'#255#11#24't'#255#8#22'n'#255#11#23'i'#255#9#21'`'#255#10
+ +#18'V'#255#12#17'O'#255#13#17'L'#255#13#16'G'#255#10#14'E'#255#10#16'G'#255
+ +#10#16'J'#255#12#17'K'#255#10#15'J'#255#11#15'K'#255#9#14'K'#255#9#14'L'#255
+ +#9#14'M'#255#10#15'L'#255#9#13'J'#255#10#15'L'#255#9#15'M'#255#10#15'N'#255#9
+ +#15'K'#254#10#16'K'#254#13#18'H'#253#17#17'?'#250#21#18'7'#246#28#18'/'#210
+ +#26#17' !E>C'#20#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +'''Z'#144't'#11'&e'#255#2#26'`'#255#9#31'm'#255#6#28'o'#255#5#31'o'#255#8'"m'
+ +#255#13'(o'#255#26'3w'#255#24'*m'#255#14' Z'#255#2#20'H'#255#3#18'C'#255#5#16
+ +'D'#255#9#20'I'#255#10#20'G'#255#11#22'D'#255#8#18'J'#255#7#17'L'#255#6#15'P'
+ +#255#4#16'Z'#255#8#24'h'#255#5#25'q'#255#6#29's'#255#5#28'q'#255#7','#131#255
+ +#19'k'#219#255#31'x'#229#255#26#130#248#255#24'q'#223#255#5'5'#151#255#9'n'
+ +#231#255#20's'#240#255#13'v'#233#255#14'u'#236#255#13't'#234#255#13'u'#235
+ +#255#13'u'#235#255#11's'#233#255#15'w'#237#255#14'v'#234#255#11'u'#234#255#11
+ +'v'#233#255#11'v'#233#255#12'x'#233#255#9'u'#227#255#12'x'#231#255#10'v'#229
+ +#255#7's'#226#255#5'u'#231#255#9'v'#231#255#15'y'#230#255#11'w'#228#255#17
+ +#127#236#255#23#129#229#255#18'_'#185#255#11'1'#129#255#3'&l'#255#10'7|'#255
+ +#6'6|'#255#9'6|'#255#14'8y'#255#16'9q'#255#8'#P'#255#14#21'8'#255#3#9''''#255
+ +#2#7''''#255#5#8'.'#255#7#23'K'#255#11'(i'#255#8'-{'#255#12'0y'#255#7'"c'#255
+ +#6'<'#142#255'"}'#218#255#25'y'#222#255#20'z'#222#255#20#131#227#255#26#129
+ +#229#255#22#128#233#255#26#132#232#255#25#127#228#255#24#127#228#255#26#129
+ +#230#255#25#128#229#255#28#128#232#255#29#128#233#255#26'~'#230#255#30#130
+ +#235#255#27#128#234#255#24#129#234#255#16#131#235#255' '#132#230#255'!'#150
+ +#230#255' f'#176#255#2'F'#148#255#28#140#228#255#22'|'#223#255#24#128#227#255
+ +#24#128#226#255#30#132#230#255#23'~'#227#255#20#132#231#255#18#134#232#255#23
+ +#129#228#255#7'^'#190#255#9'I'#172#255#6'F'#169#255#4'Q'#186#255#4'c'#208#255
+ +#9'a'#210#255#10'b'#209#255#1'e'#203#255#2'c'#204#255#6'g'#208#255#7'h'#208
+ +#255#6'f'#208#255#4'c'#208#255#7'f'#211#255#6'e'#211#255#7'e'#213#255#6'd'
+ +#212#255#5'c'#211#255#6'd'#211#255#6'e'#212#255#4'b'#210#255#6'c'#211#255#8
+ +'c'#212#255#7'b'#211#255#4'a'#212#255#7'd'#208#255#7'i'#205#255#7'i'#209#255
+ +#13'g'#207#255#9'V'#187#255#2'M'#177#255#6']'#199#255#8'b'#208#255#4'd'#212
+ +#255#8'd'#216#255#8'f'#217#255#6'g'#215#255#8'c'#207#255#2'M'#185#255#6'Y'
+ +#194#255#11'a'#208#255#19'g'#211#255#5'@'#165#255#12''''#137#255#3#29'{'#255
+ +#4#27'y'#255#8#24'y'#255#7#25'y'#255#7#24'y'#255#8#24'y'#255#7#25'u'#255#8#27
+ +'r'#255#10#27'k'#255#17#31'f'#255#12#23'W'#255#10#18'L'#255#10#15'J'#255#10
+ +#17'L'#255#6#13'P'#255#5#13'Z'#255#9#21'l'#255#5#21't'#255#5#21'v'#255#7#23
+ +'w'#255#7#23'w'#255#8#24'w'#255#7#22't'#255#7#24's'#255#6#22'n'#255#13#27'n'
+ +#255#10#22'f'#255#6#19'a'#255#6#16'b'#255#7#18'i'#255#6#20'm'#255#6#22't'#255
+ +#6#23'x'#255#6#22'w'#255#8#24'x'#255#7#22't'#255#10#24'r'#255#7#23'l'#255#10
+ +#22'f'#255#10#20'['#255#10#19'T'#255#12#18'M'#255#12#18'J'#255#9#15'D'#255#8
+ +#17'F'#255#7#18'G'#255#11#18'J'#255#11#18'K'#255#9#16'I'#255#9#16'J'#255#10
+ +#16'J'#255#9#15'J'#255#11#15'K'#255#10#15'K'#255#9#16'L'#255#9#17'M'#255#8#16
+ +'M'#255#7#15'L'#254#9#16'J'#254#10#16'G'#253#10#17'@'#250#19#20'7'#246#29#22
+ +','#193'#'#17' .'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0'P'#141#194#27#20'3l'#255#3#30'a'#255#7#29'i'#255#9#30'q'#255
+ +#9#31'o'#255#12'!j'#255#5#23'X'#255#4#19'N'#255#9#26'R'#255#23'''e'#255#28'-'
+ +'p'#255#23')j'#255#12#30'U'#255#3#20'H'#255#5#18'G'#255#10#18'K'#255#4#18'F'
+ +#255#7#18'J'#255#6#17'N'#255#4#17'W'#255#11#27'k'#255#7#28'q'#255#7#31's'#255
+ +#4#28'p'#255#4'"{'#255#16'a'#196#255#24'z'#233#255#21#129#243#255#28'h'#215
+ +#255#6'W'#195#255#19'|'#249#255#18'u'#236#255#14'w'#237#255#15'w'#240#255#12
+ +'r'#236#255#17'v'#240#255#17't'#241#255#15's'#240#255#13'q'#237#255#17'u'#241
+ +#255#14's'#243#255#15's'#242#255#15't'#241#255#16'w'#243#255#15'w'#241#255#14
+ +'v'#240#255#13'u'#239#255#12't'#238#255#11's'#240#255#17'y'#244#255#12'x'#236
+ +#255#9'u'#233#255#15'v'#231#255#13'v'#232#255#29#135#239#255#25#127#229#255
+ ,#28'O'#166#255#0'''{'#255#8'+x'#255#11'4'#127#255#3'1~'#255#13'7'#134#255#16
+ +'6'#133#255#12'5|'#255#15'&m'#255#8' a'#255#13'%l'#255#18'/}'#255#15'3'#127
+ +#255#9'3'#129#255#13'2'#133#255#9'-y'#255#1'!o'#255'#u'#208#255#24'w'#227#255
+ +#27'~'#227#255#22#131#229#255#27#128#232#255#26'}'#234#255#26#132#232#255#27
+ +#129#234#255#25#127#231#255#27#129#233#255#29#130#234#255#25#127#232#255#28
+ +#130#234#255#25#127#231#255#29#131#236#255#31#127#239#255#29'}'#235#255#18
+ +#128#236#255'#'#131#233#255'%'#133#235#255'('#130#224#255#0','#132#255#23'r'
+ +#210#255'!'#127#232#255#30#129#231#255#27#130#228#255'$'#137#240#255#31#132
+ +#239#255' '#133#241#255#28'z'#228#255#5'Y'#189#255#8'J'#168#255#9'U'#184#255
+ +#8'c'#208#255#7'b'#214#255#4'a'#212#255#4'f'#212#255#3'd'#209#255#9'c'#211
+ +#255#6'e'#210#255#7'f'#211#255#8'g'#212#255#7'f'#211#255#6'd'#214#255#6'c'
+ +#214#255#7'd'#214#255#7'd'#217#255#1'^'#209#255#6'c'#214#255#5'b'#213#255#6
+ +'f'#216#255#6'd'#215#255#7'd'#215#255#8'e'#215#255#3'^'#208#255#3'`'#208#255
+ +#10'c'#213#255#10'i'#214#255#3'_'#201#255#5'P'#185#255#8'P'#186#255#5'Z'#199
+ +#255#5'a'#211#255#7'a'#211#255#5'b'#215#255#10'b'#217#255#6'_'#214#255#8'e'
+ +#216#255#4'\'#205#255#4'S'#195#255#7'^'#205#255#8'a'#212#255#15'a'#210#255#5
+ +':'#166#255#13'&'#142#255#7#30#129#255#6#25'|'#255#11#22'z'#255#9#23'|'#255#9
+ +#24'|'#255#8#24'y'#255#7#25's'#255#13#27'o'#255#13#27'g'#255#15#26']'#255#9
+ +#18'N'#255#14#19'I'#255#8#16'I'#255#10#17'L'#255#6#13'P'#255#5#15'['#255#10
+ +#23'q'#255#5#22'u'#255#6#22'w'#255#6#23'w'#255#7#21'w'#255#7#24'u'#255#6#23
+ +'s'#255#8#24's'#255#7#23'o'#255#9#25'n'#255#9#22'j'#255#8#20'e'#255#5#17'd'
+ +#255#5#17'g'#255#7#22'o'#255#6#22'u'#255#6#23'x'#255#5#22'w'#255#7#24'x'#255
+ +#9#22't'#255#11#24'r'#255#11#23'l'#255#14#22'f'#255#12#20'Z'#255#12#18'R'#255
+ +#14#17'K'#255#13#17'K'#255#10#14'G'#255#12#17'J'#255#9#15'H'#255#11#16'J'#255
+ +#10#16'I'#255#9#15'I'#255#8#15'I'#255#9#15'J'#255#10#16'K'#255#11#16'K'#255#9
+ +#14'H'#255#8#16'J'#255#8#16'M'#255#7#14'M'#254#8#14'L'#254#13#17'I'#253#14#17
+ +'D'#252#16#18';'#249#25#22'-'#169#30#19#31'"'#0#0#0#0'+'#26'#'#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'!K'#141'q'#6
+ +'%g'#255#7#26'f'#255#6#29't'#255#6#30'n'#255#16'"i'#255#13#28']'#255#15#18'L'
+ +#255#11#17'F'#255#9#17'G'#255#8#19'L'#255#16#28'W'#255#23'''f'#255#30'.o'#255
+ +#26'+k'#255#18'$a'#255#12#24'R'#255#8#23'R'#255#3#17'N'#255#6#14'U'#255#7#24
+ +'e'#255#4#30'p'#255#5#28'm'#255#5#31'm'#255#2'/'#140#255#18'P'#174#255'%'#133
+ +#243#255#27'z'#235#255#19'j'#214#255#7'_'#213#255#21'|'#245#255#14'x'#235#255
+ +#12'r'#237#255#12'r'#237#255#16't'#239#255#20'v'#244#255#16'r'#241#255#18't'
+ +#244#255#12'n'#240#255#16's'#246#255#17'r'#247#255#15'p'#245#255#15'q'#244
+ +#255#17's'#246#255#16'r'#243#255#16'r'#243#255#17's'#244#255#15'q'#243#255#12
+ +'q'#239#255#9'r'#241#255#10'u'#242#255#12'q'#239#255#8'o'#234#255#15'y'#241
+ +#255#16'w'#237#255#19'y'#239#255#23'}'#238#255'"m'#221#255#12'0'#147#255#6#31
+ +'o'#255#12'.'#129#255#19'5'#139#255#13'.'#131#255#11'2'#135#255#12'-'#137#255
+ +#9'6'#136#255#13'4'#137#255#16'3'#136#255#14'3'#131#255#11'1'#130#255#14'2'
+ +#138#255#14'/'#132#255#5' p'#255#6'N'#170#255#29'z'#231#255#24'{'#229#255#23
+ +'~'#232#255#28'|'#234#255#27'y'#234#255#28#127#234#255#29#127#236#255#30#127
+ +#236#255#27'}'#234#255#29#127#235#255#25'{'#232#255#29'}'#236#255#30'}'#236
+ +#255#31'~'#238#255'"~'#235#255#21'~'#233#255#26'~'#236#255' '#127#233#255' w'
+ +#236#255'.'#128#247#255#27'S'#191#255#5'>'#169#255'1'#128#247#255'"z'#243#255
+ +'$'#130#246#255'#'#127#240#255#27'k'#215#255#10'_'#200#255#4'['#198#255#15'U'
+ +#194#255#4'`'#209#255#6'f'#219#255#4'b'#214#255#3'b'#213#255#7'd'#217#255#6
+ +'`'#215#255#7'a'#218#255#4'^'#216#255#5'a'#218#255#6'b'#219#255#6'b'#217#255
+ +#7'b'#216#255#3'^'#214#255#5'_'#217#255#5'_'#220#255#6'_'#222#255#4'^'#214
+ +#255#7'd'#221#255#2']'#221#255#8'_'#224#255#7'^'#221#255#4'a'#220#255#7'a'
+ +#219#255#7']'#217#255#6'b'#215#255#9'c'#217#255#8'M'#197#255#6'F'#184#255#7
+ +'Q'#195#255#2']'#210#255#7'c'#219#255#7'\'#215#255#5'`'#218#255#3'a'#218#255
+ +#8'a'#219#255#6'^'#216#255#3'^'#213#255#5'^'#211#255#7']'#209#255#9'b'#216
+ +#255#12'_'#218#255#22'c'#221#255#12'>'#175#255#10'$'#143#255#6#30#130#255#7
+ +#25'|'#255#9#22'z'#255#11#24'|'#255#9#23'{'#255#8#23'w'#255#10#25'r'#255#16
+ +#27'l'#255#17#27'c'#255#13#22'V'#255#9#15'J'#255#16#19'J'#255#10#16'I'#255#9
+ +#16'M'#255#7#13'S'#255#5#15'^'#255#11#23'r'#255#6#22'w'#255#6#23'x'#255#7#23
+ +'w'#255#7#20'v'#255#8#23'v'#255#9#23'v'#255#10#23'u'#255#11#23'q'#255#11#23
+ +'o'#255#10#20'k'#255#7#17'g'#255#6#16'f'#255#8#20'l'#255#7#20'p'#255#6#21'u'
+ +#255#6#22'x'#255#5#21'x'#255#7#22'w'#255#9#22'v'#255#10#23'r'#255#11#24'l'
+ +#255#13#22'f'#255#14#20'['#255#15#18'Q'#255#15#16'L'#255#13#14'J'#255#11#14
+ +'I'#255#13#17'M'#255#11#14'J'#255#12#16'L'#255#12#15'K'#255#11#15'K'#255#10
+ +#15'K'#255#10#14'K'#255#11#15'L'#255#10#16'K'#255#10#15'J'#255#11#16'M'#255#9
+ ,#15'M'#255#7#14'L'#254#9#14'L'#253#15#16'H'#252#18#17'>'#249#25#19'4'#196'!'
+ +#21'%'#21'#'#20#27#10#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'@'#127#195#20#13'2r'#255#7#22'^'#255#8
+ +#28'q'#255#7#30'j'#255#17' f'#255#6#24'Y'#255#16#17'M'#255#8#19'D'#255#11#19
+ +'G'#255#9#18'E'#255#8#16'E'#255#7#15'E'#255#10#20'M'#255#6#19'O'#255#19' \'
+ +#255#21'"h'#255#19'(k'#255#14'''k'#255#23'!p'#255#11#31't'#255#7'%'#130#255#5
+ +#26'|'#255#6'"'#128#255#16'I'#177#255#9'@'#168#255#31'n'#221#255#29'~'#245
+ +#255#26'm'#224#255#4'T'#206#255#18't'#244#255#13't'#239#255#14's'#237#255#13
+ +'r'#236#255#14's'#236#255#15'u'#236#255#13'r'#235#255#12'p'#236#255#10'p'#239
+ +#255#15't'#244#255#13'q'#240#255#14's'#242#255#10'o'#238#255#13'r'#241#255#11
+ +'r'#239#255#13'r'#242#255#14's'#243#255#12'q'#242#255#14'u'#244#255#14'u'#243
+ +#255#11't'#240#255#11't'#238#255#12'u'#237#255#12'u'#235#255#12'u'#234#255#12
+ +'s'#233#255#16't'#237#255#19'z'#232#255#28#127#230#255#14'X'#184#255#2'''u'
+ +#255#7#31'l'#255#8'0'#131#255#11'7'#136#255#12'4'#131#255#9'4'#131#255#7'/'
+ +#129#255#15'.'#132#255#10'-'#134#255#2'3'#136#255#4'2'#132#255#7'+|'#255#7#31
+ +'u'#255#6'2'#146#255'"r'#221#255#29'u'#226#255#24'}'#232#255#26'|'#233#255#27
+ +'z'#232#255#24'~'#234#255#24'z'#229#255#28'~'#234#255#28#127#235#255#28#127
+ +#235#255#27#127#235#255#26'~'#235#255#28'~'#235#255#26'{'#233#255#24'|'#231
+ +#255#27#127#239#255#28'~'#238#255#28#128#235#255#24#128#235#255#30#134#240
+ +#255'''~'#229#255#1'/'#147#255'+'#128#237#255#24'l'#217#255#21'_'#197#255#4
+ +'H'#164#255#10'Q'#176#255#15'c'#206#255#12'{'#237#255#19'u'#233#255#8'f'#216
+ +#255#8'h'#218#255#2'b'#214#255#4'c'#217#255#8'e'#220#255#3'_'#214#255#6'`'
+ +#215#255#5'_'#214#255#5'c'#217#255#7'e'#220#255#6'c'#218#255#8'c'#217#255#6
+ +'b'#215#255#5'`'#214#255#4'a'#215#255#7'c'#217#255#6'a'#218#255#4'_'#214#255
+ +#7'`'#207#255#11'c'#209#255#10'e'#216#255#8'd'#218#255#9'd'#223#255#8'e'#221
+ +#255#10'Q'#196#255#9'Q'#192#255#0'K'#184#255#3'\'#197#255#7'a'#207#255#4'c'
+ +#212#255#7'f'#217#255#4'b'#212#255#6'b'#216#255#7'b'#217#255#6'b'#215#255#8
+ +'b'#215#255#7'b'#216#255#7'a'#216#255#8'a'#216#255#7'`'#215#255#12'^'#218#255
+ +#17'_'#217#255#21'H'#182#255#4#31#136#255#5' '#130#255#9#27'|'#255#8#25'z'
+ +#255#10#27'|'#255#8#24'y'#255#9#28'v'#255#13#26'p'#255#17#28'h'#255#16#25'^'
+ +#255#13#19'P'#255#11#15'J'#255#13#17'G'#255#11#16'I'#255#8#14'L'#255#6#12'U'
+ +#255#6#16'b'#255#10#23'r'#255#7#23'x'#255#7#23'x'#255#8#24'y'#255#7#23'x'#255
+ +#8#24'x'#255#9#23'y'#255#10#24'v'#255#11#25's'#255#10#23'n'#255#10#21'l'#255
+ +#8#18'j'#255#6#17'i'#255#9#21'p'#255#7#21't'#255#7#22'x'#255#7#23'z'#255#7#23
+ +'y'#255#6#22'w'#255#10#24'v'#255#8#24'r'#255#10#24'l'#255#12#22'e'#255#11#20
+ +'Y'#255#13#19'O'#255#15#16'L'#255#13#14'I'#255#14#17'L'#255#13#17'M'#255#13
+ +#16'M'#255#12#15'L'#255#13#16'M'#255#12#15'L'#255#12#15'L'#255#12#15'L'#255
+ +#12#15'L'#255#11#15'K'#255#12#15'M'#255#14#15'O'#255#12#14'L'#255#9#15'L'#254
+ +#9#15'J'#252#15#15'D'#250#21#19'8'#250#28#21'-T '#18#30#26#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#152#150#168#136#0#0#0#0#149#147#169#1#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#31'S'#143#149#1#25']'#255#12' k'#255#12#29'j'
+ +#254#16#30'g'#255#6#23'W'#255#12#18'K'#255#8#18'E'#255#11#19'F'#255#12#19'F'
+ +#255#13#20'F'#255#15#19'E'#255#13#19'F'#255#14#19'G'#255#14#18'H'#255#11#17
+ +'E'#255#8#19'G'#255#1#19'J'#255#8#19'T'#255#1#21'^'#255#10'''z'#255#10'$'#129
+ +#255#3','#138#255#7'K'#186#255#11'9'#166#255#3'?'#167#255#8'h'#221#255#13'd'
+ +#217#255#6'M'#191#255#21'r'#241#255#18'w'#238#255#16'v'#239#255#18'w'#240#255
+ +#18'w'#239#255#17'y'#240#255#16'w'#239#255#14'v'#238#255#13't'#238#255#15'u'
+ +#242#255#13'u'#238#255#12't'#238#255#9'r'#236#255#12't'#239#255#13'u'#241#255
+ +#12's'#242#255#13't'#243#255#12't'#242#255#13's'#246#255#13's'#243#255#11't'
+ +#243#255#11'u'#241#255#14'v'#240#255#11's'#238#255#14'v'#239#255#14'v'#238
+ +#255#11's'#235#255#18'v'#237#255#14'v'#227#255#25#128#241#255' x'#233#255#19
+ +'A'#155#255#9'!d'#255#1'#p'#255#0'*u'#255#8'3'#131#255#7'2'#136#255#3'4'#136
+ +#255#6'2'#132#255#10'*}'#255#5''''#130#255#9'8'#151#255#18'_'#195#255#5'['
+ +#194#255#17'p'#217#255#18'u'#226#255#25'{'#233#255#24'z'#231#255#26'{'#232
+ +#255#30'~'#238#255#29#127#235#255#28'~'#233#255#28#128#235#255#27#127#235#255
+ +#24#128#235#255#24#128#235#255#23#127#234#255#25#128#237#255#25'|'#236#255#30
+ +'{'#237#255#22'}'#237#255#24#133#235#255#23'z'#219#255#14'k'#204#255#24's'
+ +#204#255#11'F'#151#255#5'K'#162#255#8'S'#172#255#17']'#187#255#24'w'#218#255
+ +#20#129#237#255#24#128#248#255#13'~'#242#255#16#127#231#255#5'e'#214#255#7'g'
+ +#215#255#1'a'#211#255#7'e'#217#255#8'e'#218#255#6'b'#216#255#6'b'#217#255#7
+ +'a'#218#255#4'd'#214#255#6'f'#216#255#7'e'#218#255#7'c'#218#255#6'c'#216#255
+ +#6'c'#215#255#5'd'#212#255#4'd'#209#255#5'b'#206#255#10'a'#207#255#10'd'#212
+ ,#255#3'd'#213#255#13'k'#222#255#13'X'#204#255#6'L'#186#255#14'P'#187#255#3'K'
+ +#190#255#15'\'#205#255#7'`'#208#255#1'e'#210#255#3'f'#212#255#7'e'#214#255#6
+ +'c'#212#255#7'a'#214#255#8'a'#215#255#8'a'#216#255#5'_'#214#255#6'a'#217#255
+ +#3'_'#215#255#6'a'#219#255#8'c'#220#255#5'`'#217#255#11'_'#219#255#16'_'#213
+ +#255#17'D'#178#255#5#31#136#255#6#31#127#255#10#27'|'#255#8#25'z'#255#9#25'z'
+ +#255#7#25'v'#255#12#29't'#255#14#26'j'#255#19#29'c'#255#13#22'V'#255#12#18'L'
+ +#255#12#17'H'#255#11#17'G'#255#11#16'I'#255#8#14'O'#255#7#12'W'#255#8#18'e'
+ +#255#8#22'q'#255#7#22'w'#255#6#23'x'#255#7#23'x'#255#7#23'x'#255#8#24'x'#255
+ +#8#22'x'#255#9#22'w'#255#10#24't'#255#9#22'o'#255#8#19'k'#255#10#19'l'#255#5
+ +#19'l'#255#8#21's'#255#7#21'v'#255#6#21'z'#255#6#22'{'#255#6#23'y'#255#7#23
+ +'w'#255#9#24'v'#255#11#25't'#255#12#23'l'#255#13#22'b'#255#11#18'V'#255#12#18
+ +'N'#255#12#14'I'#255#12#14'G'#255#12#15'K'#255#13#16'M'#255#13#16'M'#255#13
+ +#16'M'#255#12#15'L'#255#13#16'M'#255#12#15'L'#255#12#15'L'#255#12#15'L'#255
+ +#11#15'K'#255#13#15'M'#255#15#15'O'#254#13#14'L'#254#11#15'J'#253#12#15'G'
+ +#252#20#18'>'#249#27#19'3'#220'#'#22'%'#28'.'#28#31#2#0#0#0#0#253#253#253#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0'W]|'#254'{~'#151#255#127#131#155'v'#183#180#193'='#209
+ +#210#218#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'Y'#160#219#27#9'.o'#255#11'#f'#251#10
+ +#31'm'#254#12#30'l'#254#9#25'\'#255#10#19'O'#255#12#17'H'#255#11#15'G'#255#11
+ +#17'F'#255#12#18'G'#255#10#17'F'#255#13#18'H'#255#12#17'F'#255#13#18'G'#255
+ +#16#20'E'#255#16#18'F'#255#11#16'G'#255#13#15'L'#255#5#16'Q'#255#5#21'b'#255
+ +#5#24's'#255#5'2'#144#255#13'c'#209#255#12'\'#194#255#2'I'#166#255#23'u'#233
+ +#255#30#131#246#255#4'X'#195#255#10'i'#234#255#12'y'#239#255#14's'#237#255#15
+ +'u'#240#255#12't'#238#255#15'v'#240#255#12'r'#238#255#14'u'#241#255#12's'#239
+ +#255#13's'#240#255#13't'#239#255#9'q'#235#255#12'u'#238#255#11't'#238#255#10
+ +'r'#237#255#10'q'#239#255#13't'#243#255#13't'#243#255#13'r'#244#255#10'o'#240
+ +#255#14'u'#243#255#13't'#241#255#15'w'#241#255#13'u'#239#255#14'v'#239#255#13
+ +'u'#237#255#8'w'#232#255#12'u'#233#255#13't'#242#255#9'u'#235#255#12'v'#230
+ +#255#16'}'#241#255#28'z'#235#255#19'U'#173#255#14'4'#136#255#7'$y'#255#6#26
+ +'t'#255#6'&'#127#255#9'.'#144#255#10'9'#164#255#16'R'#198#255#13'r'#230#255
+ +#24'v'#234#255#22'a'#208#255#19'd'#206#255'"|'#236#255#28'{'#233#255#27'~'
+ +#234#255#26'~'#234#255#30'~'#241#255#28#127#235#255#26'}'#233#255#24'~'#233
+ +#255#28#129#238#255#26#129#237#255#25#128#238#255#24#127#237#255#28#129#239
+ +#255#30#127#239#255#26#127#240#255#23#130#243#255#25'~'#231#255#28't'#221#255
+ +#27'k'#213#255'+x'#219#255'!i'#191#255#0'9'#151#255'2'#136#236#255' '#127#232
+ +#255#30#134#236#255#19#130#233#255#25'~'#239#255#22#127#246#255#10'y'#241#255
+ +#7'h'#218#255#4'd'#214#255#5'c'#212#255#5'c'#213#255#3'`'#211#255#5'b'#215
+ +#255#6'c'#217#255#7'c'#218#255#7'c'#217#255#7'b'#216#255#8'd'#217#255#6'c'
+ +#215#255#4'a'#212#255#6'b'#213#255#8'c'#213#255#11'f'#216#255#17'f'#221#255
+ +#10'c'#215#255#9'_'#206#255#2'H'#178#255#7'D'#166#255#10'<'#166#255#7'H'#185
+ +#255#3'Y'#211#255#3'`'#218#255#3'`'#219#255#8'^'#219#255#9'a'#220#255#4'd'
+ +#215#255#6'f'#216#255#3'a'#211#255#9'`'#215#255#9'`'#215#255#8'`'#216#255#4
+ +'^'#216#255#5'`'#220#255#4'`'#220#255#7'a'#222#255#7'b'#219#255#6'a'#216#255
+ +#11'a'#221#255#18'b'#217#255#21'G'#183#255#8#30#136#255#5#29'~'#255#10#26'{'
+ +#255#9#25'z'#255#9#25'z'#255#7#25't'#255#11#28'p'#255#15#28'h'#255#17#26'^'
+ +#255#10#18'O'#255#12#16'H'#255#8#15'G'#255#9#16'H'#255#6#14'I'#255#6#14'Q'
+ +#255#5#13'X'#255#8#18'h'#255#7#22'q'#255#5#21'u'#255#6#22'w'#255#6#22'w'#255
+ +#7#23'x'#255#8#23'z'#255#10#23'{'#255#10#23'y'#255#8#21't'#255#10#22'r'#255#8
+ +#17'l'#255#9#17'n'#255#4#18'o'#255#5#21'u'#255#6#21'x'#255#6#21'|'#255#6#21
+ +'{'#255#7#23'{'#255#7#23'x'#255#10#24'v'#255#11#24'r'#255#14#24'm'#255#12#20
+ +'a'#255#12#19'W'#255#14#16'N'#255#12#14'I'#255#11#15'I'#255#14#16'L'#255#11
+ +#15'L'#255#13#16'M'#255#12#15'L'#255#12#15'L'#255#14#17'N'#255#12#15'L'#255
+ +#12#15'L'#255#13#16'M'#255#10#15'K'#255#11#15'M'#255#14#15'O'#255#13#14'L'
+ +#254#15#17'I'#252#15#17'C'#250#25#17'8'#247'"'#21'.'#158#0#0#0#0#0#0#0#0#253
+ +#253#253#3#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'|'#131#163#158'LZv'#255'Taz'#255
+ +#133#140#159#203#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'%U'#151'k'#4#27
+ +'a'#230#10'$o'#252#8#30'n'#254#9#29'd'#254#11#22'R'#254#9#18'H'#255#9#18'G'
+ +#255#12#19'E'#255#11#19'D'#255#11#20'E'#255#11#20'F'#255#9#18'D'#255#10#19'F'
+ +#255#2#20'B'#255#8#21'D'#255#9#20'H'#255#11#17'J'#255#7#17'N'#255#8#20'U'#255
+ +#7#25'e'#255#6';'#153#255#14'Z'#198#255#9'd'#202#255#7'L'#169#255#16'['#201
+ +#255'#'#132#254#255#21'Y'#207#255#10'\'#213#255#18't'#248#255#15's'#237#255
+ +#15'u'#240#255#14'u'#241#255#13't'#240#255#13't'#241#255#12's'#241#255#11'r'
+ +#240#255#13't'#242#255#10'p'#237#255#8'p'#235#255#13'u'#240#255#12't'#238#255
+ ,#9'r'#237#255#11't'#240#255#12'u'#243#255#7'q'#240#255#14's'#244#255#11'p'
+ +#240#255#13's'#240#255#13't'#238#255#12't'#236#255#13'u'#237#255#14'v'#239
+ +#255#14'v'#238#255#20'w'#237#255#12'v'#237#255#12'v'#235#255#13'v'#235#255#14
+ +'v'#236#255#15'v'#234#255#11't'#234#255#9'y'#247#255#13'{'#245#255#15'w'#241
+ +#255#19'v'#241#255#17'o'#236#255#15't'#243#255#10'v'#244#255#12'y'#241#255#22
+ +'z'#239#255#21't'#232#255#23'p'#220#255#4'Y'#191#255#28#128#235#255#22'x'#229
+ +#255#27'~'#236#255#25#127#234#255#24'{'#237#255#24'~'#234#255#26#128#237#255
+ +#26#127#236#255#26#127#238#255#27#129#238#255#29#129#241#255#28'~'#239#255#30
+ +#128#242#255#29#130#240#255#23'~'#239#255#30#128#243#255' ~'#240#255#28#132
+ +#244#255#22'|'#236#255'$'#129#240#255'!'#131#232#255#4':'#142#255' {'#216#255
+ +#29#133#233#255'"'#129#235#255#21#128#240#255#21#129#244#255#16'{'#247#255#17
+ +'u'#236#255#7'g'#217#255#2'a'#211#255#9'g'#216#255#7'b'#213#255#6'a'#211#255
+ +#9'f'#216#255#6'f'#216#255#4'e'#215#255#7'e'#215#255#8'd'#213#255#9'g'#215
+ +#255#4'd'#212#255#6'h'#213#255#5'e'#210#255#10'a'#209#255#7'X'#200#255#4'O'
+ +#181#255#4'M'#179#255#4'E'#172#255#7'C'#176#255#5'M'#192#255#6'a'#214#255#4
+ +'`'#218#255#7'\'#215#255#9'`'#219#255#7'a'#222#255#3'`'#219#255#5'c'#221#255
+ +#4'b'#214#255#9'h'#219#255#7'b'#211#255#7'b'#213#255#5'_'#215#255#6'`'#217
+ +#255#7'a'#220#255#5'`'#220#255#6'b'#219#255#7'c'#219#255#6'c'#215#255#6'd'
+ +#213#255#9'c'#217#255#24'j'#223#255#14'?'#168#255#11'$'#141#255#6#27'{'#255#7
+ +#26'y'#255#6#25'x'#255#8#25'x'#255#9#26's'#255#12#29'n'#255#16#30'h'#255#12
+ +#22'X'#255#10#19'K'#255#11#18'H'#255#8#16'F'#255#10#18'J'#255#7#16'L'#255#7
+ +#15'R'#255#6#15'['#255#9#23'l'#255#7#23's'#255#5#21'v'#255#7#23'x'#255#6#22
+ +'w'#255#7#23'y'#255#7#22'z'#255#8#22'y'#255#8#23'w'#255#9#23't'#255#9#22'r'
+ +#255#7#18'n'#255#9#19'p'#255#4#20'q'#255#6#22'v'#255#6#23'y'#255#6#22'z'#255
+ +#5#20'y'#255#6#22'z'#255#6#22'x'#255#8#24'v'#255#8#22'o'#255#14#24'k'#255#12
+ +#18'_'#255#14#20'V'#255#12#14'L'#255#10#13'H'#255#11#16'J'#255#13#17'L'#255
+ +#12#16'L'#255#13#18'N'#255#11#16'L'#255#10#15'K'#255#11#15'K'#255#10#15'K'
+ +#255#8#13'I'#255#11#15'L'#255#8#14'K'#255#8#14'M'#255#11#15'O'#254#10#15'L'
+ +#253#12#15'H'#252#18#17'>'#249#28#18'1'#238'$'#19'(*'#0#0#0#0#0#0#0#0#253#252
+ +#252#10#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#222#226#234'"bo'#132'aIWk'
+ +#255'=Nb'#170'^p'#133#127#137#159#177'~'#194#209#217''''#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'0h'#147#0#0#0#0#0'4s'
+ +#183#17#6' j'#141#6'%o'#246#7'!r'#253#9'!m'#254#10#27'\'#255#9#20'M'#255#8#19
+ +'H'#255#12#18'C'#255#11#19'C'#255#10#19'C'#255#11#21'E'#255#10#19'D'#255#14
+ +#20'F'#255#10#20'F'#255#12#20'B'#255#8#19'G'#255#9#18'J'#255#5#18'O'#255#8#17
+ +'Q'#255#2#20'W'#255#8'I'#171#255#8']'#194#255#14'd'#206#255#19'Z'#201#255#12
+ +'K'#189#255#26'y'#249#255#25'j'#235#255#4'O'#189#255#23'r'#243#255#11't'#233
+ +#255#12't'#235#255#11't'#236#255#10't'#235#255#8'p'#235#255#10'r'#238#255#9
+ +'p'#238#255#11'p'#240#255#8'p'#236#255#8'p'#236#255#10'r'#237#255#9'q'#236
+ +#255#9'r'#235#255#9'q'#236#255#11's'#240#255#9'q'#239#255#12'q'#240#255#12'r'
+ +#240#255#11'r'#237#255#13'u'#238#255#11's'#233#255#12't'#236#255#13't'#238
+ +#255#15'v'#241#255#13'v'#238#255#9'q'#234#255#8'p'#234#255#12't'#238#255#10
+ +'q'#237#255#14'u'#241#255#14'v'#241#255#14'v'#241#255#10'p'#238#255#10'p'#240
+ +#255#14't'#244#255#11'p'#241#255#11'p'#240#255#11'q'#236#255#13't'#234#255#17
+ +'x'#236#255#24'v'#234#255#15'o'#222#255#4'X'#188#255'%'#135#247#255#21'w'#227
+ +#255#29'}'#238#255#26'~'#232#255#24'~'#238#255#25#130#238#255#27#130#239#255
+ +#23'~'#235#255#24#127#236#255#20'|'#231#255#29#131#239#255#25'~'#237#255#26
+ +#127#238#255#26#128#235#255#23'{'#232#255#31#130#240#255#28#129#240#255'#'
+ +#135#244#255#28#129#236#255#30#131#233#255'/'#142#244#255#21'X'#169#255#6'T'
+ +#178#255#25#140#230#255#31#133#233#255#21#132#234#255#26#134#238#255' '#136
+ +#249#255#12't'#222#255#9'j'#213#255#3'g'#210#255#2'h'#212#255#4'k'#217#255#5
+ +'i'#217#255#11'm'#221#255#11'h'#218#255#16'e'#217#255#7'i'#217#255#6'd'#213
+ +#255#9'['#202#255#11'W'#190#255#9'Q'#185#255#6'H'#174#255#8'H'#174#255#8'C'
+ +#172#255#3'J'#187#255#12'Y'#204#255#7'X'#205#255#14'd'#220#255#5'`'#217#255#5
+ +'_'#217#255#5'\'#215#255#9'^'#217#255#7'a'#221#255#3'`'#219#255#3'`'#219#255
+ +#7'e'#222#255#1'^'#216#255#9'e'#221#255#4'a'#215#255#7'c'#216#255#7'd'#218
+ +#255#6'b'#216#255#6'd'#217#255#4'b'#216#255#9'f'#218#255#5'c'#213#255#4'c'
+ +#209#255#4'e'#209#255#8'c'#209#255#24'f'#213#255#9'.'#141#255#5#30#129#255#10
+ +#27'y'#255#8#26'z'#255#6#25'v'#255#10#25'v'#255#12#28'q'#255#10#27'j'#255#11
+ +#26'`'#255#9#19'P'#255#9#17'H'#255#8#16'E'#255#8#17'F'#255#9#18'I'#255#8#15
+ +'L'#255#7#16'S'#255#5#16'^'#255#7#24'n'#255#6#23't'#255#5#21'u'#255#7#25'y'
+ +#255#4#21'v'#255#6#22'y'#255#6#22'x'#255#6#22'v'#255#8#24'v'#255#7#22's'#255
+ +#8#22's'#255#4#19'p'#255#7#20'r'#255#6#21'u'#255#5#21'v'#255#7#23'z'#255#6#22
+ +'z'#255#6#20'z'#255#7#22'{'#255#6#21'w'#255#7#23'w'#255#7#22'o'#255#12#24'i'
+ ,#255#13#19'_'#255#14#20'U'#255#8#14'J'#255#7#14'H'#255#10#16'K'#255#11#17'L'
+ +#255#10#16'L'#255#11#17'M'#255#10#16'K'#255#11#17'L'#255#10#16'K'#255#10#16
+ +'K'#255#8#14'J'#255#10#15'L'#255#11#16'N'#255#7#14'M'#255#9#15'M'#253#9#15'I'
+ +#252#11#15'C'#250#21#20'9'#247#31#21'-'#174' '#7'!'#2#0#0#0#0#241#237#235#7#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#255#255#255#11
+ +'3Kd'#26'E]s'#255';Wn'#255'^|'#147#203#207#227#239#21'['#128#154#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'6n'#157#1'R'#159#209#1
+ +#15'4|'#31#7'&s'#230#4'"q'#252#6' m'#253#11#29'f'#255#10#24'S'#255#8#19'I'
+ +#255#10#19'E'#255#13#19'D'#255#12#17'B'#255#12#21'E'#255#10#19'E'#255#13#20
+ +'F'#255#11#20'F'#255#12#20'C'#255#8#19'F'#255#9#19'H'#255#4#21'O'#255#8#18'O'
+ +#255#4#23'Z'#255#5'K'#169#255#12'_'#203#255#10'c'#206#255#7'a'#206#255#19'G'
+ +#182#255#11'F'#189#255#16'b'#218#255#1'N'#185#255#9'p'#222#255#9'r'#231#255
+ +#10's'#232#255#10't'#233#255#7'p'#231#255#8'o'#234#255#10'q'#236#255#10'p'
+ +#234#255#10'm'#232#255#8'p'#236#255#8'o'#236#255#8'o'#236#255#7'n'#234#255#11
+ +'p'#237#255#11'p'#237#255#8'n'#235#255#7'n'#234#255#12'q'#239#255#10'p'#236
+ +#255#10'o'#234#255#11'q'#235#255#11'q'#235#255#11'q'#236#255#12'r'#238#255#13
+ +'r'#241#255#14's'#242#255#13's'#242#255#14's'#243#255#16'v'#245#255#11'p'#241
+ +#255#14's'#244#255#11'p'#241#255#12'q'#242#255#11'm'#240#255#13'o'#242#255#12
+ +'p'#245#255#9'n'#240#255#11'o'#240#255#13's'#241#255#14'v'#240#255#11's'#235
+ +#255#16'q'#234#255#23'u'#234#255#1'L'#183#255''''#134#248#255#17'r'#224#255
+ +#26'z'#237#255#28'~'#233#255#30#127#240#255#22'}'#235#255#24#127#237#255#23
+ +'~'#236#255#28#131#240#255#25#130#239#255#25#130#239#255#20'}'#234#255#26#131
+ +#240#255'"'#130#238#255#14'f'#211#255#2'L'#188#255#8'L'#187#255#17'W'#194#255
+ +#16'Z'#191#255#20'g'#198#255#27's'#206#255'&h'#182#255#0'3'#129#255'"|'#206
+ +#255' v'#218#255#29'u'#221#255#31'z'#231#255' |'#242#255#12'o'#226#255#12'c'
+ +#210#255#13'a'#209#255#8'Y'#199#255#15'\'#202#255#10'U'#191#255#13'S'#189#255
+ +#7'I'#177#255#8'J'#177#255#3'A'#168#255#7'G'#175#255#8'H'#175#255#5'M'#179
+ +#255#3'P'#183#255#5'Z'#198#255#3']'#206#255#4'b'#213#255#4'a'#221#255#6'a'
+ +#222#255#5'^'#218#255#3']'#215#255#7'_'#216#255#6']'#217#255#7'^'#218#255#8
+ +'^'#221#255#6'_'#220#255#5'`'#221#255#8'd'#225#255#4'`'#221#255#3'a'#220#255
+ +#5'b'#221#255#0'^'#215#255#9'e'#220#255#7'd'#215#255#5'b'#213#255#6'e'#218
+ +#255#5'e'#218#255#6'c'#214#255#5'c'#212#255#7'e'#210#255#5'c'#207#255#12'g'
+ +#212#255#27'e'#209#255#4#29'x'#255#8#27'z'#255#7#26'v'#255#8#26'z'#255#5#25
+ +'v'#255#8#26't'#255#12#27'l'#255#15#28'h'#255#12#24'['#255#7#17'L'#255#10#15
+ +'D'#255#10#17'D'#255#7#17'F'#255#7#17'K'#255#5#13'N'#255#6#13'V'#255#7#18'd'
+ +#255#6#23'p'#255#6#22'v'#255#5#21'v'#255#7#22'w'#255#6#22'x'#255#7#23'z'#255
+ +#6#22'w'#255#5#21'v'#255#7#23'v'#255#6#22'w'#255#6#22'v'#255#5#21'w'#255#6#21
+ +'z'#255#8#22'{'#255#8#22'{'#255#7#22'{'#255#7#21'{'#255#7#20'|'#255#8#22'|'
+ +#255#8#22'y'#255#9#23'x'#255#8#23'p'#255#10#21'g'#255#12#20']'#255#12#18'R'
+ +#255#9#14'K'#255#10#15'K'#255#10#16'K'#255#11#17'L'#255#11#16'L'#255#12#16'M'
+ +#255#11#16'K'#255#11#16'K'#255#10#15'J'#255#11#16'K'#255#11#14'L'#255#11#15
+ +'M'#255#10#15'N'#254#9#14'N'#254#12#15'K'#253#12#16'F'#252#16#16'<'#249#27#21
+ +'2'#241'!'#18'''I'#0#0#0#0'|XP'#4#186#166#156#10#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'd|'#146#0#0#0#0#0'q'#146#169'2='
+ +'by'#193'9`z'#228'?g'#129'A'#0#0#0#0';e'#136#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0'4l'#155#12'0l'#168#12'5m'#178#7#9'(z'#198#6'$t'#249#7' m'
+ +#252#12#30'n'#254#11#28'\'#255#7#20'P'#255#7#18'H'#255#11#20'E'#255#11#18'C'
+ +#255#10#20'F'#255#6#19'G'#255#11#19'I'#255#8#17'F'#255#11#20'D'#255#7#19'G'
+ +#255#9#18'I'#255#4#20'Q'#255#7#17'P'#255#2#19'Y'#255#10'N'#177#255#15'\'#198
+ +#255#9'U'#186#255#3'I'#181#255#13'H'#173#255#2'F'#172#255#25'x'#235#255#21'Z'
+ +#209#255#10']'#209#255#13'q'#234#255#12'n'#231#255#10'o'#231#255#11'o'#232
+ +#255#9'o'#228#255#6'k'#226#255#7'j'#226#255#10'k'#229#255#8'k'#231#255#6'i'
+ +#229#255#7'j'#230#255#8'k'#233#255#7'j'#233#255#8'l'#235#255#8'k'#234#255#8
+ +'k'#234#255#11'm'#238#255#10'm'#237#255#10'n'#237#255#12'p'#237#255#10'n'#235
+ +#255#11'o'#237#255#11'n'#238#255#12'o'#240#255#10'n'#238#255#14'r'#242#255#12
+ +'p'#240#255#14'r'#242#255#10'n'#239#255#12'p'#240#255#10'n'#239#255#13'q'#242
+ +#255#15'q'#244#255#14'p'#243#255#11'p'#242#255#12'q'#244#255#10'p'#241#255#15
+ +'t'#244#255#13'r'#241#255#10'p'#236#255#17's'#239#255#17'n'#229#255#2'J'#183
+ +#255'-'#133#253#255#26'z'#236#255#27'}'#243#255#24#127#235#255' '#128#244#255
+ +#27'}'#240#255#30#128#243#255#29'~'#242#255#30#130#243#255#26#128#241#255#23
+ +#128#239#255#24#129#240#255#29#134#245#255#19#133#240#255#24#133#242#255#28
+ +#132#242#255' '#133#241#255#25'z'#227#255#23'p'#214#255#23'i'#201#255#25'b'
+ +#192#255#31'j'#198#255#13'5'#128#255#7'B'#153#255#11'P'#183#255#7'O'#177#255
+ +#3'R'#185#255#13']'#198#255#9'R'#187#255#2'D'#172#255#7'J'#179#255#8'K'#181
+ ,#255#10'N'#185#255#5'K'#187#255#4'P'#191#255#4'W'#199#255#7'^'#208#255#6'_'
+ +#210#255#7'e'#216#255#3'g'#217#255#6'j'#219#255#6'h'#217#255#7'd'#213#255#5
+ +'d'#213#255#8'c'#212#255#7'a'#213#255#7'b'#214#255#9'a'#215#255#9'a'#216#255
+ +#8'`'#216#255#8'`'#217#255#5'^'#214#255#4'_'#215#255#3']'#213#255#4'_'#215
+ +#255#6'a'#217#255#4'`'#218#255#5'a'#218#255#4'`'#216#255#5'a'#216#255#9'e'
+ +#219#255#7'd'#216#255#6'c'#216#255#3'a'#215#255#7'd'#219#255#4'b'#215#255#7
+ +'e'#215#255#8'c'#212#255#10'd'#211#255#14'g'#213#255#28'b'#205#255#9#28's'
+ +#255#7#26't'#255#5#25's'#255#7#25'x'#255#7#24'u'#255#9#28'q'#255#15#31'j'#255
+ +#12#26'^'#255#7#18'P'#255#12#18'K'#255#13#17'D'#255#12#18'E'#255#8#16'I'#255
+ +#7#16'M'#255#5#13'R'#255#9#15'\'#255#10#21'l'#255#8#25'v'#255#6#21'z'#255#6
+ +#21'z'#255#7#22'{'#255#8#22'|'#255#8#22'|'#255#8#23'|'#255#6#21'y'#255#6#23
+ +'x'#255#7#24'x'#255#5#22'w'#255#7#23'{'#255#6#21'z'#255#6#21'{'#255#7#22'|'
+ +#255#5#20'z'#255#6#21'{'#255#7#20'|'#255#8#21'|'#255#9#22'x'#255#10#22'v'#255
+ +#10#24'q'#255#12#23'h'#255#12#20']'#255#10#17'P'#255#10#15'M'#255#12#17'N'
+ +#255#11#16'M'#255#11#16'M'#255#11#14'L'#255#10#13'J'#255#12#15'L'#255#13#17
+ +'L'#255#12#16'K'#255#12#15'L'#255#12#15'L'#255#12#14'N'#255#11#14'O'#255#12
+ +#16'Q'#253#14#15'I'#252#17#17'A'#251#21#18'8'#249#30#19'-'#193'&'#20'%'#7#0#0
+ +#0#0'yRK'#11#176#153#140#19#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#131#170#200' Bn'#136
+ +#163'.Yya*VvGLz'#154'g'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'4b'#137#2'1i'#152'*0'
+ +'n'#169')B'#127#199#13#9'.'#130#163#6'''{'#247#6#30'm'#252#10#31'n'#254#10#30
+ +'f'#255#10#24'Z'#255#5#17'J'#255#9#20'G'#255#7#19'G'#255#7#19'J'#255#4#17'G'
+ +#255#6#17'G'#255#4#17'C'#255#10#17'E'#255#5#16'F'#255#6#18'M'#255#0#20'Z'#255
+ +#6#28'c'#255#8'!n'#255#0'>'#162#255#12'F'#178#255#4'K'#185#255#10'S'#201#255
+ +#15'h'#217#255#9'V'#199#255#6'D'#191#255#13'H'#194#255#1'E'#187#255#10'e'#223
+ +#255#10'k'#230#255#10'j'#230#255#12'j'#230#255#10'l'#229#255#8'l'#228#255#11
+ +'l'#226#255#7'h'#222#255#10'j'#226#255#9'j'#228#255#9'h'#229#255#11'i'#234
+ +#255#11'j'#235#255#7'h'#232#255#7'i'#232#255#7'i'#233#255#8'k'#235#255#6'h'
+ +#231#255#9'k'#233#255#10'o'#235#255#8'l'#233#255#8'l'#234#255#9'n'#237#255#10
+ +'n'#239#255#9'n'#235#255#12'q'#239#255#8'm'#236#255#12'p'#240#255#15'r'#243
+ +#255#15'q'#242#255#15'q'#242#255#15'r'#243#255#12'o'#241#255#14't'#243#255#13
+ +'s'#243#255#12's'#243#255#13's'#243#255#13's'#242#255#14's'#242#255#17's'#242
+ +#255#19's'#237#255#20'o'#231#255#4'L'#182#255'%'#129#248#255#24'z'#235#255#27
+ +'~'#241#255#25#127#240#255#28#128#244#255#28'{'#239#255#30#127#242#255#27'}'
+ +#241#255#27'~'#243#255' '#133#247#255#28#130#243#255#27#129#241#255#27#128
+ +#239#255#22#128#238#255#26#127#236#255#27#127#234#255''''#141#250#255'!'#136
+ +#245#255'%'#136#244#255#31#133#235#255'#'#134#236#255')'#143#243#255#29'P'
+ +#156#255#0'='#151#255'$'#131#242#255#24'|'#239#255#21'}'#242#255#19#127#250
+ +#255#13's'#235#255#9'g'#219#255#9'f'#217#255#10'j'#218#255#6'i'#219#255#5'i'
+ +#219#255#9'f'#218#255#12'h'#219#255#2'b'#210#255#3'c'#212#255#5'e'#213#255#4
+ +'d'#214#255#7'd'#218#255#7'b'#216#255#8'c'#218#255#6'`'#217#255#6'c'#217#255
+ +#7'e'#216#255#4'a'#216#255#6'c'#219#255#5'b'#219#255#6'd'#218#255#7'd'#216
+ +#255#6'c'#214#255#7'e'#216#255#6'a'#216#255#6'b'#217#255#7'b'#217#255#6'b'
+ +#217#255#6'b'#216#255#4'b'#216#255#5'd'#217#255#8'f'#220#255#6'c'#218#255#5
+ +'e'#220#255#7'd'#221#255#6'c'#220#255#2'_'#216#255#5'c'#217#255#9'f'#217#255
+ +#10'd'#213#255#19'f'#213#255#27'X'#190#255#5#22'l'#255#4#23'm'#255#8#26'r'
+ +#255#9#26'u'#255#10#25's'#255#13#29'n'#255#16#30'd'#255#11#24'W'#255#8#17'L'
+ +#255#11#17'G'#255#12#17'D'#255#10#15'E'#255#7#15'J'#255#6#15'M'#255#5#14'U'
+ +#255#7#17'a'#255#9#23'o'#255#6#23'v'#255#6#21'{'#255#7#21'{'#255#8#22'|'#255
+ +#7#21'|'#255#6#20'z'#255#7#22'{'#255#6#22'z'#255#7#23'z'#255#7#23'z'#255#6#22
+ +'z'#255#7#22'{'#255#6#21'z'#255#7#22'|'#255#6#21'{'#255#7#21'|'#255#9#23'~'
+ +#255#8#22'}'#255#6#20'z'#255#9#22'v'#255#11#23'u'#255#12#25'n'#255#12#21'e'
+ +#255#10#18'Y'#255#9#14'M'#255#13#16'N'#255#12#17'N'#255#12#17'N'#255#13#17'O'
+ +#255#13#17'L'#255#12#15'K'#255#12#15'K'#255#12#16'K'#255#11#14'J'#255#13#16
+ +'N'#255#12#15'O'#255#12#15'O'#255#10#15'P'#255#11#15'P'#254#12#15'G'#251#18
+ +#16'>'#248#24#16'4'#241'!'#18'+=1'#18#26#0'yTO'#9'a6*'#2#190#169#158#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'v'#161#186'fZ'#130#153#154'Mz'
+ +#152#204''#144#135#10'/'#131#243#12')'#132
+ +#250#9'-'#137#253#17'/'#145#255#20'1'#142#255#16','#129#255#17'*w'#255#19''''
+ +'n'#255#21'(i'#255#20'%f'#255#16'!c'#255#21#29'S'#255#18#23'S'#255#5#22'J'
+ +#255#9#18'I'#255#13#17'R'#255#2#13'Q'#255#5#25'j'#255#11'P'#181#255#0'['#202
+ +#255#9'a'#206#255#11'\'#202#255#11'Y'#191#255#10'R'#182#255#7'N'#177#255#1'M'
+ +#177#255#12']'#196#255#6'T'#196#255#6'g'#215#255#6'h'#220#255#12'f'#220#255#7
+ +'f'#220#255#5'd'#217#255#12'f'#216#255#7'd'#215#255#5'b'#217#255#6'd'#217#255
+ +#6'e'#214#255#8'h'#215#255#6'f'#213#255#7'g'#216#255#6'd'#219#255#10'g'#224
+ +#255#9'f'#224#255#7'd'#223#255#5'e'#223#255#7'f'#225#255#12'l'#231#255#9'j'
+ +#230#255#8'i'#227#255#5'j'#227#255#8'j'#229#255#7'j'#229#255#11'm'#233#255#12
+ +'n'#235#255#12'l'#237#255#10'i'#236#255#12'l'#238#255#12'l'#239#255#9'm'#242
+ +#255#10'n'#242#255#8'n'#240#255#8'n'#239#255#11'r'#241#255#12'q'#241#255#11
+ +'n'#237#255#12'p'#238#255#13's'#234#255#16'm'#230#255#4'Q'#184#255#21'v'#236
+ +#255#20'z'#234#255#27#128#237#255#26'}'#235#255#27#129#238#255#28#128#244#255
+ +#27'~'#240#255#29'}'#237#255#31'~'#234#255#28'|'#232#255#23'y'#228#255#30#129
+ +#237#255' '#132#241#255#29#129#239#255#25#127#235#255' '#132#240#255#29'|'
+ +#230#255#15'b'#203#255#5'M'#182#255#11'P'#184#255#20'Y'#190#255' v'#227#255
+ +'''v'#224#255#0'&t'#255#13']'#203#255'"'#136#236#255#27#131#245#255#24'{'#249
+ +#255#20'q'#227#255#17'i'#222#255#16'_'#210#255#6'P'#193#255#3'N'#188#255#5'Y'
+ +#200#255#4'a'#212#255#6'a'#216#255#10'a'#215#255#7'b'#213#255#6'a'#212#255#7
+ +'a'#213#255#5'b'#214#255#5'b'#215#255#2'a'#214#255#7'f'#219#255#7'f'#219#255
+ +#2'c'#218#255#1'`'#215#255#8'd'#217#255#9'd'#215#255#6'd'#215#255#3'b'#215
+ +#255#5'c'#216#255#7'c'#218#255#3'b'#215#255#4'b'#215#255#6'b'#216#255#8'd'
+ +#219#255#6'a'#217#255#6'a'#219#255#4'`'#219#255#4'a'#220#255#5'`'#224#255#2
+ +'b'#226#255#6'`'#225#255#8'a'#224#255#4'a'#219#255#5'c'#217#255#9'k'#216#255
+ +#15'f'#212#255#24'e'#211#255#27'J'#169#255#4#20'i'#255#3#22'l'#255#9#27'r'
+ +#255#9#27'q'#255#16#30'q'#255#16#29'h'#255#14#22'W'#255#9#17'K'#255#7#14'G'
+ +#255#11#17'F'#255#9#16'E'#255#9#15'J'#255#7#15'P'#255#6#14'T'#255#4#14'^'#255
+ +#8#21'l'#255#7#23's'#255#6#23'w'#255#6#22'x'#255#7#23'x'#255#8#23'y'#255#6#22
+ +'z'#255#6#21'{'#255#7#22'|'#255#8#23'}'#255#7#21'{'#255#8#23'|'#255#8#22'{'
+ +#255#8#23'|'#255#7#22'{'#255#6#21'z'#255#8#22'|'#255#7#20'|'#255#7#20'|'#255
+ ,#8#21'|'#255#7#23'z'#255#11#24's'#255#14#23'p'#255#12#24'i'#255#12#20'_'#255
+ +#7#13'S'#255#15#17'Q'#255#16#16'Q'#255#13#17'Q'#255#11#16'N'#255#11#16'M'#255
+ +#12#17'L'#255#11#16'K'#255#11#16'K'#255#10#15'J'#255#11#16'K'#255#12#16'L'
+ +#255#12#15'N'#255#12#15'O'#255#13#14'N'#254#16#13'L'#250#19#15'@'#248#27#17
+ +'6'#250'"'#17'+n9'#29#17#0#18#1#23#2#161#135'|'#9#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0'E~'#171#7'1k'#164#25'3l'#174#20#15'>'#143'f'#6',~'#239#6
+ +'%~'#250#6' |'#253#9#25'u'#255#10#27'v'#255#10#28'm'#255#8#23']'#255#5#17'I'
+ +#255#11#18'C'#255#14#20'C'#255#12#18'C'#255#6#17'?'#255#13#18'G'#255#5#19'G'
+ +#255#9#19'H'#255#5#16'O'#255#5#19'U'#255#0#26'k'#255#17'Y'#196#255#17'`'#205
+ +#255#11'W'#195#255#2'R'#188#255#1'H'#178#255#10'Q'#187#255#10'^'#200#255#14
+ +'Y'#194#255#8'O'#183#255#8'L'#184#255#6'_'#205#255#7'f'#216#255#10'a'#216#255
+ +#6'c'#216#255#5'b'#214#255#9'a'#212#255#5'b'#213#255#6'c'#213#255#8'e'#215
+ +#255#5'c'#213#255#9'g'#215#255#6'f'#214#255#5'e'#214#255#4'd'#214#255#6'f'
+ +#217#255#6'd'#216#255#4'c'#216#255#6'd'#219#255#4'b'#219#255#6'e'#221#255#8
+ +'f'#224#255#6'f'#223#255#8'g'#224#255#6'h'#227#255#6'h'#227#255#9'l'#231#255
+ +#8'l'#231#255#7'l'#231#255#9'm'#235#255#9'm'#236#255#8'l'#235#255#8'l'#241
+ +#255#8'l'#240#255#8'n'#240#255#9'p'#239#255#7'n'#238#255#9'p'#238#255#8'm'
+ +#233#255#11'n'#234#255#11'p'#230#255#17'm'#228#255#13'Y'#190#255#18's'#231
+ +#255#21'{'#232#255#29#129#238#255#29'~'#236#255#28#128#240#255#29#128#241#255
+ +#29#128#241#255' '#131#242#255#30#130#238#255'"'#131#240#255#20't'#224#255#7
+ +'c'#205#255#28't'#223#255'!'#129#248#255#29'}'#240#255'"'#131#247#255#28'}'
+ +#244#255#12'h'#222#255#10'U'#199#255#11'H'#186#255#6'A'#184#255#0'F'#185#255
+ +#2'E'#187#255#14';'#158#255#2'7'#162#255#12'B'#163#255#14'@'#166#255#14'G'
+ +#177#255#10'L'#178#255#5'L'#187#255#7'I'#184#255#9'N'#189#255#13'`'#208#255#8
+ +'d'#214#255#11'd'#217#255#10'a'#216#255#7'`'#214#255#8'_'#214#255#10'b'#217
+ +#255#9'a'#216#255#10'b'#218#255#9'b'#217#255#7'c'#217#255#8'd'#218#255#9'e'
+ +#219#255#8'e'#224#255#8'c'#217#255#12'b'#211#255#3'X'#200#255#5'\'#205#255#5
+ +'a'#211#255#7'b'#214#255#8'`'#213#255#8'c'#216#255#6'a'#215#255#5'`'#215#255
+ +#5'a'#217#255#4'^'#218#255#4'^'#218#255#4'^'#218#255#6'`'#220#255#8'b'#222
+ +#255#3'c'#222#255#6'^'#219#255#7'a'#220#255#3'`'#216#255#8'e'#217#255#5'e'
+ +#210#255#14'e'#210#255'!k'#212#255#15'9'#148#255#2#14'`'#255#6#23'n'#255#9#28
+ +'q'#255#10#28'o'#255#17#29'k'#255#17#25'_'#255#13#19'O'#255#13#17'J'#255#10
+ +#15'F'#255#12#18'G'#255#8#15'E'#255#8#15'M'#255#8#15'U'#255#8#15'Z'#255#7#19
+ +'i'#255#9#23'q'#255#6#22'v'#255#8#24'y'#255#7#23'z'#255#8#24'x'#255#7#24'x'
+ +#255#7#23'{'#255#7#22'|'#255#6#21'{'#255#8#22'|'#255#6#20'z'#255#7#21'{'#255
+ +#7#21'{'#255#8#22'|'#255#8#22'|'#255#8#23'{'#255#9#23'}'#255#9#23'}'#255#7#22
+ +'{'#255#7#21'z'#255#7#24'x'#255#12#26's'#255#13#23'n'#255#13#24'f'#255#10#19
+ +'Y'#255#10#15'S'#255#14#15'Q'#255#12#16'P'#255#11#16'O'#255#10#17'N'#255#10
+ +#16'L'#255#11#18'L'#255#11#19'L'#255#10#17'J'#255#10#17'K'#255#11#17'L'#255
+ +#12#16'L'#255#12#14'L'#255#11#13'M'#255#13#14'K'#253#18#16'I'#249#24#18'='
+ +#246#31#19'1'#237'%'#17'''('''#18#31#5'wUI'#4#0#0#0#0#192#169#158#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#220#233#238#27#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0''#7'(x'#230#12'$z'#250#5#27'w'#253#7#28't'#255#7#27't'#255#6#28'q'#255#13
+ +#30'j'#255#11#27'^'#255#8#18'M'#255#8#17'I'#255#10#18'I'#255#9#22'B'#255#14
+ +#20'G'#255#13#15'E'#255#13#17'K'#255#6#17'P'#255#4#17'S'#255#5#27'g'#255#17
+ +'E'#168#255#2'H'#178#255#11'R'#186#255#4'P'#184#255#2'H'#182#255#10'Z'#201
+ +#255#6'e'#213#255#12'c'#207#255#6'Q'#187#255#7'>'#170#255#2'S'#192#255#9'g'
+ +#218#255#6'['#213#255#6'd'#219#255#4'`'#214#255#9'`'#211#255#6'd'#214#255#6
+ +'b'#214#255#7'c'#215#255#5'a'#212#255#7'c'#215#255#6'e'#215#255#4'c'#213#255
+ +#5'd'#214#255#6'e'#215#255#7'd'#215#255#7'd'#217#255#4'a'#217#255#4'a'#219
+ +#255#6'c'#222#255#8'd'#225#255#6'c'#223#255#8'e'#225#255#6'h'#225#255#7'h'
+ +#225#255#8'k'#224#255#9'l'#225#255#9'm'#229#255#7'k'#229#255#2'h'#229#255#5
+ +'j'#232#255#9'j'#238#255#7'k'#239#255#8'l'#238#255#7'm'#238#255#5'j'#234#255
+ +#8'n'#234#255#7'm'#231#255#10'm'#231#255#13'n'#228#255#14'k'#223#255#9'Q'#187
+ +#255#23'r'#226#255#27'~'#233#255'!'#130#240#255#31#127#239#255#27#127#239#255
+ +#29#130#239#255'!'#129#240#255#30#130#241#255#24#128#241#255#29#128#239#255
+ +' '#127#236#255#27'y'#227#255#15'd'#207#255#8'^'#196#255#29#127#239#255#31'w'
+ +#240#255#11'Y'#208#255#5'R'#202#255#11']'#216#255#4'`'#226#255#2'd'#228#255
+ +#11'e'#230#255#10'_'#225#255#4'`'#221#255#6'd'#216#255#8']'#204#255#7'K'#186
+ +#255#7'G'#183#255#5'C'#180#255#4'C'#173#255#0'D'#175#255#5'P'#188#255#14'V'
+ ,#201#255#11'V'#203#255#10'X'#207#255#4'X'#205#255#9'`'#213#255#9']'#216#255#9
+ +']'#215#255#6'Y'#208#255#9'Y'#205#255#10'Z'#205#255#10'X'#205#255#9'S'#201
+ +#255#7'Q'#201#255#5'M'#192#255#1'J'#186#255#3'Q'#190#255#7'W'#196#255#5'\'
+ +#204#255#5'`'#212#255#5'`'#216#255#4']'#215#255#5'`'#214#255#4'_'#214#255#5
+ +'_'#215#255#5'`'#218#255#6'_'#219#255#6'`'#218#255#8'a'#219#255#6'a'#217#255
+ +#5'`'#216#255#3'a'#219#255#5'`'#220#255#9'c'#223#255#6'b'#220#255#4'b'#215
+ +#255#6'd'#210#255#21'i'#214#255'#h'#207#255#12'3'#138#255#7#20'c'#255#6#22'k'
+ +#255#9#27'n'#255#14#28'm'#255#15#26'e'#255#12#21'T'#255#11#17'H'#255#11#17'F'
+ +#255#10#16'E'#255#11#17'G'#255#9#16'H'#255#9#16'N'#255#6#13'V'#255#6#15']'
+ +#255#9#21'm'#255#6#22's'#255#7#20'x'#255#8#21'z'#255#6#21'y'#255#7#22'z'#255
+ +#7#22'z'#255#7#22'{'#255#8#22'|'#255#7#22'|'#255#7#22'z'#255#7#22'{'#255#7#22
+ +'|'#255#7#21'{'#255#7#22'|'#255#8#22'|'#255#7#21'z'#255#7#22'{'#255#8#22'|'
+ +#255#7#21'{'#255#6#21'w'#255#7#24'w'#255#13#24'q'#255#14#24'l'#255#14#22'`'
+ +#255#10#16'U'#255#11#16'S'#255#13#16'Q'#255#11#16'N'#255#11#16'O'#255#11#17
+ +'O'#255#11#17'N'#255#10#16'M'#255#10#16'L'#255#10#16'J'#255#11#16'J'#255#11
+ +#17'L'#255#10#15'K'#255#11#15'K'#255#13#15'M'#254#15#15'I'#250#19#17'E'#247
+ +#24#16'7'#246'"'#18','#187')'#17#24#2'/'#26'%'#2#0#0#0#0#221#209#204'?'#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'{'#177#212
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#219#232#237#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'H~'#182#0#155
+ +#228#252#0#22'E'#146')'#7'''w'#223#12'&z'#250#4#30'z'#253#5#27't'#255#8#28'v'
+ +#255#8#28't'#255#12#30'p'#255#14#30'h'#255#12#25'Z'#255#9#18'L'#255#8#18'F'
+ +#255#11#18'F'#255#8#17'I'#255#3#19'E'#255#4#19'H'#255#3#17'P'#255#8#22'X'#255
+ +#3' o'#255#4'H'#172#255#11'Z'#194#255#13'W'#190#255#3'O'#184#255#2'X'#196#255
+ +#8'c'#211#255#6'`'#210#255#11'e'#211#255#8'g'#209#255#11'H'#173#255#1'C'#172
+ +#255#9'`'#207#255#4'c'#213#255#7'f'#217#255#7'c'#214#255#6'd'#218#255#5'e'
+ +#219#255#8'd'#213#255#7'c'#213#255#6'a'#211#255#7'b'#212#255#6'd'#213#255#5
+ +'b'#213#255#7'd'#215#255#5'b'#213#255#6'd'#214#255#6'd'#215#255#3'c'#214#255
+ +#4'c'#217#255#5'b'#218#255#5'b'#218#255#4'a'#219#255#6'c'#221#255#8'f'#223
+ +#255#7'f'#222#255#5'f'#218#255#6'g'#218#255#7'h'#221#255#6'h'#221#255#3'f'
+ +#223#255#7'k'#230#255#7'i'#232#255#8'k'#235#255#7'j'#234#255#9'm'#237#255#3
+ +'g'#229#255#6'j'#228#255#7'k'#227#255#7'k'#225#255#7'e'#217#255#8'h'#215#255
+ +#18'X'#196#255#13'f'#206#255#23'|'#228#255#28#127#237#255#28#127#235#255#23
+ +#128#236#255#24#131#239#255#24#130#239#255#25#127#238#255#29#130#245#255#26
+ +#130#243#255#26#127#241#255#28#128#240#255#28#128#240#255#26'|'#240#255#14'a'
+ +#205#255#8'F'#174#255#2'Q'#192#255#5'b'#220#255#14'^'#222#255#10'`'#223#255#4
+ +'`'#223#255#11'a'#222#255#6'_'#218#255#3'_'#215#255#6'c'#219#255#5'c'#220#255
+ +#12'f'#223#255#11'd'#219#255#11'd'#214#255#6'^'#207#255#9'_'#208#255#1'U'#197
+ +#255#4'S'#198#255#4'N'#192#255#4'L'#191#255#2'F'#187#255#11'M'#193#255#8'M'
+ +#195#255#8'O'#194#255#1'G'#185#255#2'G'#182#255#0'H'#181#255#6'Q'#189#255#4
+ +'S'#190#255#6'Y'#195#255#5'['#203#255#10'b'#210#255#11'h'#216#255#5'f'#216
+ +#255#6'e'#217#255#7'd'#219#255#9'd'#221#255#5'b'#221#255#5'a'#218#255#7'c'
+ +#221#255#5'`'#219#255#8'd'#222#255#6'a'#219#255#6'a'#219#255#7'b'#219#255#5
+ +'a'#215#255#6'a'#213#255#5'd'#217#255#3'`'#218#255#7'b'#222#255#7'b'#220#255
+ +#5'd'#215#255#10'g'#211#255#18'g'#207#255'&c'#200#255#3'#x'#255#7#16']'#255#9
+ +#22'f'#255#15#29'i'#255#17#29'g'#255#16#23']'#255#13#19'M'#255#12#18'H'#255
+ +#11#16'F'#255#9#16'F'#255#8#16'F'#255#9#16'J'#255#10#16'R'#255#5#14'X'#255#7
+ +#18'b'#255#6#23'o'#255#7#23's'#255#6#21'v'#255#6#22'x'#255#5#21'w'#255#7#23
+ +'y'#255#6#22'z'#255#8#22'|'#255#10#22'{'#255#7#22'y'#255#6#22'x'#255#6#22'z'
+ +#255#6#22'z'#255#6#21'z'#255#8#22'|'#255#7#21'{'#255#5#21'z'#255#7#22'{'#255
+ +#8#23'{'#255#8#22'{'#255#6#22'x'#255#6#23'u'#255#11#23'p'#255#11#22'f'#255#11
+ +#18'X'#255#8#14'Q'#255#10#15'P'#255#11#16'P'#255#11#16'N'#255#10#16'N'#255#11
+ +#16'N'#255#12#17'N'#255#11#16'O'#255#12#15'M'#255#11#15'J'#255#11#15'J'#255
+ +#12#16'K'#255#9#14'K'#254#9#15'J'#254#12#15'J'#252#15#16'F'#249#17#17'>'#246
+ +#26#18'3'#245'"'#18'''U1'#18#0#0#0#0#0#0#188#166#159#5#234#227#224#1#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'w'#169#200#0
+ +#131#177#206#11'Z'#148#188#11'~'#172#207#5'}'#176#215#0#0#0#0#0#0#0#0#0'['
+ +#149#192#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'<'
+ +'x'#169#0';s'#172#3'@x'#185#1'"S'#161#20#8'+y'#204#9'''w'#249#4#30'z'#253#5
+ +#27'{'#255#6#27'{'#255#7#28'y'#255#10#28'v'#255#10#29'n'#255#15#29'f'#255#11
+ +#24'X'#255#7#19'O'#255#2#20'D'#255#4#19'L'#255#7#17'K'#255#16'!_'#255#13'(o'
+ +#255#12'&m'#255#1'$r'#255#9'F'#167#255#12'Q'#187#255#2'O'#186#255#4'['#201
+ +#255#8'd'#211#255#8'a'#213#255#11'e'#216#255#6'c'#214#255#6'i'#216#255#9'b'
+ +#201#255#7'J'#184#255#9'Y'#197#255#4'j'#211#255#3'f'#209#255#10'b'#209#255#5
+ ,'d'#213#255#5'd'#215#255#7'b'#209#255#6'c'#210#255#4'b'#208#255#5'd'#210#255
+ +#3'b'#208#255#5'c'#212#255#6'd'#214#255#3'`'#211#255#4'd'#213#255#6'f'#215
+ +#255#5'e'#214#255#6'f'#216#255#5'd'#216#255#5'd'#216#255#8'f'#220#255#7'f'
+ +#220#255#6'f'#218#255#4'd'#216#255#6'g'#218#255#7'h'#217#255#8'i'#220#255#8
+ +'j'#221#255#3'e'#219#255#8'j'#227#255#3'h'#227#255#7'k'#230#255#5'i'#228#255
+ +#6'i'#228#255#3'f'#221#255#10'k'#224#255#7'i'#219#255#8'j'#217#255#12'j'#219
+ +#255#13'j'#214#255#18'Z'#194#255#4'a'#197#255#23#128#229#255#23#128#235#255
+ +#25#130#237#255#22#131#237#255#27#129#234#255#20#133#238#255#24#129#235#255
+ +#23'v'#227#255#8'm'#219#255#30#129#243#255#31#129#244#255#21#133#250#255#29
+ +#133#243#255#13'a'#209#255#8'Q'#186#255#3'K'#172#255#7'P'#186#255#6']'#212
+ +#255#1'd'#219#255#10'e'#215#255#6'c'#214#255#3'b'#212#255#7'e'#216#255#7'e'
+ +#217#255#7'e'#221#255#2'_'#217#255#4'c'#219#255#6'f'#219#255#9'f'#217#255#9
+ +'e'#218#255#7'c'#217#255#13'k'#222#255#8'g'#218#255#7'e'#217#255#4'd'#216#255
+ +#7'h'#218#255#2'e'#221#255#8'k'#227#255#6'h'#225#255#7'f'#223#255#11'g'#223
+ +#255#12'h'#223#255#6'e'#215#255#8'g'#217#255#4'e'#214#255#4'e'#214#255#7'g'
+ +#216#255#8'd'#216#255#3'b'#214#255#5'd'#217#255#6'd'#221#255#4'd'#220#255#4
+ +'b'#218#255#8'e'#222#255#4'a'#218#255#10'h'#222#255#7'f'#217#255#7'f'#217#255
+ +#5'e'#214#255#5'f'#214#255#9'e'#215#255#5'd'#215#255#4'b'#216#255#8'd'#220
+ +#255#7'e'#219#255#3'd'#212#255#9'g'#208#255#21'k'#208#255'#^'#187#255#5'!k'
+ +#255#10#22'['#255#7#24']'#255#15'!b'#255#16#27'X'#255#11#20'O'#255#11#18'G'
+ +#255#13#18'F'#255#11#16'F'#255#9#16'H'#255#10#17'J'#255#8#15'M'#255#6#14'S'
+ +#255#4#15'^'#255#7#20'k'#255#5#23's'#255#6#24'u'#255#6#23'x'#255#7#24'y'#255
+ +#5#22'w'#255#7#25'x'#255#5#23'w'#255#7#24'z'#255#7#21'w'#255#5#20'u'#255#6#22
+ +'w'#255#6#23'x'#255#6#23'x'#255#6#23'z'#255#8#24'|'#255#8#23'{'#255#6#22'|'
+ +#255#7#22'|'#255#8#23'|'#255#7#23'y'#255#8#24'y'#255#8#23's'#255#14#25'n'#255
+ +#11#20'a'#255#9#15'S'#255#10#16'Q'#255#11#16'O'#255#11#16'M'#255#13#16'M'#255
+ +#12#15'L'#255#11#15'L'#255#10#15'L'#255#13#17'N'#255#14#17'N'#255#13#16'M'
+ +#255#12#15'K'#255#12#15'L'#255#9#15'K'#255#9#15'J'#253#11#16'G'#251#16#18'B'
+ +#247#20#19'9'#245#28#18','#218'&'#19'!'#18#0#0#0#0#252#252#252'('#0#0#0#0#254
+ +#254#254#19#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0'g'#158#192#26'o'#163#196#145'i'#156#195'gq'#160#195'?\'#144
+ +#184'"Z'#144#185#7#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0';w'#166#1'=w'#174#14'Ay'#186#14'4i'#185#17#13'3'#129#171#7'%t'
+ +#245#8#31'x'#253#6#27'{'#255#7#26'z'#255#7#27'z'#255#6#26'x'#255#9#27't'#255
+ +#11#30'm'#255#8#26'c'#255#2#19'V'#255#6#22'M'#255#13#31'^'#255#15'&a'#255#17
+ +')g'#255#8#25'_'#255#5#14'Q'#255#3#23'\'#255#4'8'#142#255#5'M'#187#255#12'`'
+ +#207#255#5'b'#211#255#6'c'#213#255#8'e'#215#255#2'd'#212#255#7'f'#215#255#9
+ +'c'#214#255#3'e'#215#255#11'\'#207#255#3'T'#196#255#7'b'#210#255#1'b'#211#255
+ +#6'a'#213#255#10'b'#214#255#6'd'#212#255#6'd'#212#255#6'e'#212#255#5'd'#209
+ +#255#7'f'#212#255#5'd'#210#255#6'e'#212#255#7'e'#214#255#7'd'#214#255#4'd'
+ +#214#255#7'g'#217#255#6'f'#215#255#6'f'#215#255#6'f'#215#255#7'g'#217#255#4
+ +'d'#217#255#5'd'#217#255#8'i'#219#255#5'f'#217#255#7'h'#219#255#6'g'#218#255
+ +#6'f'#218#255#7'g'#220#255#4'c'#218#255#7'f'#221#255#3'g'#225#255#5'h'#225
+ +#255#7'e'#225#255#7'e'#225#255#5'c'#220#255#11'k'#225#255#7'g'#220#255#8'i'
+ +#221#255#4'd'#216#255#11'k'#218#255#21']'#200#255#5'^'#197#255#30#131#234#255
+ +#29#128#237#255#30#129#237#255#28#133#241#255#31#129#237#255#30#129#235#255
+ +#29#131#232#255#29'~'#227#255#3'a'#199#255#20'o'#219#255#28#127#239#255#23
+ +#128#245#255#17'h'#216#255#0'T'#192#255#1'd'#215#255#10'h'#223#255#12'V'#205
+ +#255#2'E'#179#255#9'L'#184#255#0'b'#211#255#9'g'#218#255#5'd'#215#255#6'f'
+ +#214#255#5'd'#217#255#5'b'#219#255#9'd'#222#255#8'c'#221#255#6'`'#214#255#4
+ +'c'#216#255#8'h'#222#255#5'e'#219#255#10'i'#224#255#6'f'#222#255#7'g'#222#255
+ +#7'f'#221#255#7'e'#220#255#5'c'#216#255#7'e'#218#255#6'd'#217#255#7'e'#218
+ +#255#6'e'#218#255#6'e'#218#255#4'f'#218#255#3'f'#219#255#3'b'#217#255#7'd'
+ +#219#255#8'd'#218#255#8'b'#218#255#3'`'#216#255#5'd'#220#255#5'c'#221#255#5
+ +'a'#219#255#5'a'#221#255#6'c'#221#255#4'a'#218#255#8'f'#221#255#3'c'#215#255
+ +#6'f'#217#255#4'd'#215#255#4'd'#214#255#6'd'#217#255#3'c'#218#255#1'`'#217
+ +#255#9'd'#222#255#5'c'#219#255#3'd'#211#255#11'i'#207#255#17'g'#202#255#30'V'
+ +#170#255#7'"a'#255#6#19'P'#255#8#26'Y'#255#12#30'X'#255#11#22'K'#255#8#17'I'
+ +#255#9#18'F'#255#14#18'G'#255#12#15'G'#255#10#16'J'#255#9#16'L'#255#8#16'R'
+ +#255#6#13'V'#255#6#17'e'#255#7#21'q'#255#7#23'w'#255#6#23'y'#255#8#23'{'#255
+ +#9#24'}'#255#7#23'y'#255#7#24'x'#255#6#23'v'#255#7#24'x'#255#6#20'v'#255#7#22
+ +'w'#255#7#23'x'#255#7#24'z'#255#7#23'z'#255#6#22'z'#255#7#23'{'#255#8#23'{'
+ +#255#7#22'}'#255#8#22'}'#255#8#24'z'#255#8#24'w'#255#8#24'u'#255#12#24'n'#255
+ +#12#24'g'#255#12#17'Z'#255#10#15'R'#255#13#17'R'#255#11#16'O'#255#12#16'N'
+ ,#255#14#16'N'#255#13#16'M'#255#12#15'L'#255#11#16'M'#255#10#16'M'#255#11#16
+ +'M'#255#13#17'N'#255#13#16'M'#255#11#15'M'#255#11#16'M'#255#12#16'J'#252#14
+ +#17'G'#250#20#20'?'#246#24#17'2'#245'!'#19''''#156#0#0#0#0#0#0#0#0#247#245
+ +#245'P'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#229#239#244'('#220#232#241#0#159#191#214#23'W'#144#181'VO'#136#176
+ +#153'L'#130#174#200'I'#127#169#213'H}'#169#212'?{'#164#143'L'#136#180'Rv'#188
+ +#224#5#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0':v'#165#3'=y'#173'(B|'
+ +#186'0=u'#193','#22'?'#146#133#7'$s'#238#9#30'x'#253#8#27'v'#255#7#26'v'#255
+ +#5#25'x'#255#6#26'z'#255#6#28'x'#255#9' v'#255#13'''u'#255#14'''p'#255#10'#d'
+ +#255#15'!c'#255#11#20'P'#255#10#16'H'#255#4#17'L'#255#9'!^'#255#5'$l'#255#8
+ +'/'#133#255#11'['#197#255#8'_'#207#255#6'_'#213#255#4'e'#217#255#1'd'#213#255
+ +#9'e'#213#255#6'c'#212#255#4'e'#212#255#6'f'#214#255#9'd'#211#255#5'S'#195
+ +#255#13']'#207#255#5'_'#214#255#3'b'#219#255#6'c'#217#255#2'd'#216#255#6'c'
+ +#214#255#4'b'#211#255#3'a'#211#255#7'f'#213#255#6'd'#212#255#6'd'#212#255#5
+ +'c'#213#255#7'e'#214#255#6'f'#215#255#7'f'#216#255#5'c'#213#255#5'd'#214#255
+ +#4'd'#214#255#6'f'#217#255#3'c'#214#255#6'f'#218#255#5'f'#216#255#6'f'#216
+ +#255#3'c'#213#255#4'c'#217#255#6'f'#219#255#7'g'#221#255#9'i'#223#255#6'f'
+ +#221#255#6'f'#226#255#6'd'#225#255#8'e'#226#255#8'e'#225#255#4'b'#221#255#6
+ +'d'#222#255#5'c'#219#255#5'd'#220#255#9'i'#221#255#10'g'#218#255#17'^'#205
+ +#255#6'Y'#195#255#29#128#237#255' '#128#239#255#31#127#236#255'!'#131#242#255
+ +#29#127#238#255'#~'#233#255#28#129#234#255#27#135#239#255#24'w'#220#255#3'U'
+ +#193#255#31'}'#240#255#20'v'#232#255#9']'#206#255#6'^'#213#255#9'h'#225#255#7
+ +'c'#224#255#4'e'#222#255#6'b'#220#255#10'S'#202#255#3'F'#180#255#5'Q'#193#255
+ +#9'\'#203#255#7'c'#216#255#6'd'#221#255#6'd'#221#255#1'b'#216#255#5'd'#218
+ +#255#5'b'#217#255#7'a'#221#255#6'`'#220#255#5'_'#218#255#8'b'#219#255#4'_'
+ +#216#255#6'c'#218#255#7'd'#219#255#7'd'#218#255#6'b'#221#255#7'd'#222#255#6
+ +'c'#219#255#3'`'#214#255#4'a'#215#255#7'd'#221#255#7'b'#222#255#9'c'#226#255
+ +#4'`'#221#255#7'c'#224#255#6'`'#222#255#4'_'#221#255#6'b'#223#255#6'b'#223
+ +#255#8'd'#224#255#9'b'#223#255#8'b'#225#255#8'b'#225#255#5'a'#219#255#6'd'
+ +#220#255#6'd'#219#255#5'd'#219#255#7'e'#221#255#6'd'#219#255#7'd'#221#255#6
+ +'g'#224#255#4'c'#223#255#5'f'#225#255#5'e'#217#255#7'g'#214#255#9'e'#205#255
+ +#31's'#210#255#24'E'#143#255#5#27'X'#255#8#21'P'#255#6#19'M'#255#11#21'L'#255
+ +#12#19'I'#255#12#17'J'#255#14#18'H'#255#12#16'H'#255#12#16'G'#255#11#17'J'
+ +#255#9#16'M'#255#6#15'T'#255#4#13'\'#255#6#21'k'#255#7#24'u'#255#8#24'z'#255
+ +#8#23'{'#255#8#22'|'#255#9#23'|'#255#7#22'z'#255#9#24'z'#255#7#23'x'#255#7#23
+ +'x'#255#5#20'u'#255#7#23'x'#255#7#22'z'#255#6#22'z'#255#7#23'{'#255#6#21'{'
+ +#255#6#21'{'#255#7#22'|'#255#7#23'{'#255#7#24'{'#255#8#24'x'#255#10#24'v'#255
+ +#11#24'q'#255#15#26'l'#255#12#21'_'#255#12#14'T'#255#12#15'R'#255#12#17'Q'
+ +#255#11#16'P'#255#13#17'P'#255#13#16'O'#255#13#17'O'#255#13#17'O'#255#11#16
+ +'N'#255#10#17'N'#255#9#17'N'#255#12#16'N'#255#12#16'M'#255#9#15'L'#255#9#16
+ +'M'#254#14#16'M'#251#14#17'C'#248#21#19';'#245#29#19'.'#242'%'#21'&K'#0#0#0#0
+ +#242#241#241#8#252#250#250#20#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#229#239#244#0#0#0#0#0#0#0#0#0#130#172#202#0#0#0#0#0
+ +#0#0#0#0'j'#165#209#7'Q'#137#179'%I~'#168'X@p'#157#142'J|'#169#234'D{'#170
+ +#246'>x'#166#223'8u'#161#212'8w'#162#204'(e'#143#164')c'#140#143'0l'#152#131
+ +'7u'#161'~N'#140#182'Ir'#153#27'?f'#138#17'I\|''AMs'#129'&:o'#255#4#23'\'#255#9' v'#255
+ +#7#29'u'#255#7#27'y'#255#6#25'z'#255#6#25'z'#255#7#26'{'#255#7#26'}'#255#7#25
+ +'~'#255#8#26'~'#255#8#26'~'#255#7#27'}'#255#8#27'v'#255#12#30'o'#255#11#25'`'
+ +#255#9#19'Q'#255#12#18'M'#255#5#15'L'#255#15#20'P'#255#2#17'Q'#255#9#15'W'
+ +#255#3#18'^'#255#8'A'#151#255#10'Z'#188#255#19'k'#195#255#30#139#214#255'1'
+ +#168#237#255'&'#137#199#255#2'3f'#255'#'#138#189#255#24'c'#149#255#2'1a'#255
+ +#3'['#165#255#9'K'#152#255#15'c'#193#255#2'N'#187#255#6'\'#200#255#2'g'#206
+ +#255#9'd'#210#255#4'b'#210#255#4'd'#211#255#5'e'#214#255#4'e'#215#255#3'd'
+ +#217#255#6'f'#221#255#5'b'#220#255#4'`'#217#255#3'a'#216#255#8'h'#221#255#3
+ +'e'#214#255#7'i'#218#255#6'g'#218#255#6'f'#219#255#7'e'#220#255#5'd'#219#255
+ +#6'f'#218#255#7'f'#218#255#6'd'#217#255#10'd'#227#255#8'`'#228#255#9'_'#224
+ +#255#13'f'#229#255#2'b'#220#255#9'e'#217#255#17'_'#200#255#7'O'#176#255#5'D'
+ +#148#255#1'+x'#255#24'V'#172#255'%v'#215#255#28'n'#204#255#26'z'#211#255'#'
+ +#134#228#255'!'#146#241#255'$'#148#245#255#28#139#238#255#19#127#231#255#7'p'
+ +#221#255#6'j'#221#255#10'i'#221#255#7'f'#218#255#10'j'#224#255#6'j'#223#255#7
+ +'j'#223#255#7'e'#221#255#9'f'#224#255#3'f'#224#255#7'i'#226#255#8']'#215#255
+ +#2'O'#200#255#0'Q'#201#255#4'Z'#210#255#10'a'#219#255#5'c'#220#255#5'c'#221
+ +#255#4'c'#221#255#3'c'#220#255#6'e'#222#255#7'f'#223#255#5'c'#222#255#6'c'
+ +#222#255#4'a'#221#255#6'd'#222#255#5'c'#219#255#5'd'#218#255#8'h'#220#255#6
+ +'f'#220#255#4'g'#221#255#5'c'#221#255#7'b'#221#255#10'c'#222#255#4'^'#217#255
+ +#8'e'#224#255#5'e'#222#255#7'd'#223#255#6'c'#222#255#8'e'#224#255#6'c'#223
+ +#255#8'e'#224#255#7'c'#223#255#10'd'#223#255#9'd'#222#255#9'f'#224#255#5'e'
+ +#219#255#9'j'#224#255#9'k'#226#255#6'h'#223#255#7'h'#222#255#5'h'#220#255#8
+ +'j'#220#255#3'd'#208#255#13'k'#209#255'!k'#203#255#18'<'#134#255#12'"^'#255#3
+ +#20'N'#255#10#17'G'#255#9#17'G'#255#10#16'G'#255#8#16'G'#255#9#16'I'#255#9#16
+ +'M'#255#6#14'R'#255#4#14']'#255#5#21'k'#255#6#23's'#255#6#23'y'#255#6#22'|'
+ +#255#7#23'|'#255#7#22'x'#255#8#20'w'#255#3#18's'#255#5#20'y'#255#6#22'{'#255
+ +#7#22'{'#255#7#22'}'#255#7#22'|'#255#8#23'}'#255#8#23'}'#255#7#22'|'#255#10
+ ,#25#127#255#6#22'}'#255#7#22'}'#255#7#23'}'#255#7#23'x'#255#8#25'u'#255#14#25
+ +'o'#255#10#22'd'#255#11#21']'#255#11#17'V'#255#9#16'Q'#255#11#18'Q'#255#9#17
+ +'N'#255#9#16'P'#255#9#14'Q'#255#11#16'Q'#255#10#16'N'#255#11#17'O'#255#10#16
+ +'O'#255#11#17'P'#255#11#17'P'#255#10#16'O'#255#10#16'O'#255#11#17'P'#255#11
+ +#17'P'#255#9#16'O'#255#7#15'M'#255#11#16'I'#254#13#17'C'#252#20#18';'#249#28
+ +#20'2'#182#31#20'.!:$-'#7#0#0#0#0'V3%'#13#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'DRo'#6
+ +'HXX'#26#7'_'#138#0'\^]6[WSQme`'#20'G;6'#19'ben;_'#142#175#129'X'#134#168'wM'
+ +'}'#163'QY'#137#171')d'#132#161#11#237#168#133#0#0#0#0#0'3u'#161#0'Bn'#149#0
+ +'Fs'#150#2'jv~'#2#137#131'{'#3#141#130'v'#23'IUu'#17'>Jtv'#31'3k'#255#10#31
+ +'e'#255#7#28't'#255#7#28'u'#255#8#27'x'#255#8#26'{'#255#8#26'{'#255#8#26'|'
+ +#255#8#26'~'#255#7#24'~'#255#10#26'~'#255#10#25'}'#255#9#26'{'#255#9#27'u'
+ +#255#15#31'p'#255#11#24'`'#255#10#19'R'#255#12#20'O'#255#12#17'N'#255#14#16
+ +'P'#255#7#17'R'#255#8#15'V'#255#1#13'T'#255#12'1'#129#255#15'W'#181#255'&|'
+ +#203#255'E'#164#237#255';'#160#219#255#18'R~'#255#13'R~'#255':'#186#246#255
+ +'A'#177#241#255'#'#155#203#255'/'#143#208#255'='#171#232#255'F'#195#255#255
+ +#16'x'#212#255#14'_'#200#255#13'j'#219#255#5'l'#223#255#5'i'#220#255#8'h'#214
+ +#255#8'h'#220#255#8'h'#222#255#8'g'#221#255#7'e'#222#255#4'b'#220#255#5'b'
+ +#220#255#3'b'#219#255#7'f'#222#255#7'h'#219#255#5'e'#218#255#6'f'#219#255#6
+ +'e'#220#255#4'b'#222#255#3'`'#219#255#5'a'#221#255#6'b'#222#255#4'b'#224#255
+ +#1'b'#227#255#3'`'#227#255#5'\'#220#255#11'^'#220#255#13'e'#223#255#8'Z'#206
+ +#255#11'U'#195#255#11'X'#188#255#25'Z'#179#255#14'6'#127#255#3'''j'#255'/d'
+ +#184#255'X'#166#247#255'U'#173#248#255'T'#171#248#255'Q'#174#246#255'P'#176
+ +#255#255'C'#175#255#255'B'#172#255#255'0'#160#251#255'"'#149#248#255'"'#135
+ +#245#255#15'x'#234#255#13'n'#226#255#7'i'#222#255#8'g'#222#255#6'd'#222#255#6
+ +'e'#224#255#3'e'#225#255#5'g'#227#255#6'f'#226#255#14'h'#224#255#9'^'#212#255
+ +#2'M'#196#255#4'U'#205#255#12'a'#221#255#7'c'#224#255#6'c'#223#255#7'b'#220
+ +#255#5'e'#223#255#7'f'#226#255#2'`'#222#255#5'd'#228#255#7'e'#229#255#7'd'
+ +#225#255#7'f'#222#255#6'c'#220#255#7'd'#220#255#8'f'#223#255#6'e'#224#255#8
+ +'f'#226#255#7'a'#223#255#10'e'#227#255#3'_'#221#255#5'e'#225#255#4'b'#220#255
+ +#4'c'#223#255#3'a'#224#255#6'd'#227#255#4'c'#226#255#5'e'#226#255#5'f'#225
+ +#255#6'g'#223#255#4'd'#221#255#6'f'#222#255#5'f'#220#255#5'f'#223#255#4'g'
+ +#225#255#4'e'#223#255#8'i'#225#255#4'e'#217#255#6'f'#213#255#11'g'#211#255#25
+ +'l'#213#255' Z'#183#255#12'(o'#255#11#24'T'#255#7#20'N'#255#15#19'G'#255#9#18
+ +'G'#255#10#17'J'#255#9#15'K'#255#10#15'N'#255#7#12'P'#255#7#14'Y'#255#8#18'h'
+ +#255#9#23's'#255#6#23'x'#255#6#22'{'#255#6#22'{'#255#7#22'{'#255#7#21'x'#255
+ +#8#20'x'#255#8#20'{'#255#8#21'}'#255#8#23'}'#255#8#23'}'#255#8#22'~'#255#7#21
+ +'|'#255#7#21'|'#255#8#22'}'#255#8#22'}'#255#10#23#128#255#8#22'}'#255#7#22'}'
+ +#255#9#23'|'#255#11#23'u'#255#13#24'p'#255#13#24'g'#255#9#19'\'#255#10#20'T'
+ +#255#10#17'R'#255#8#16'P'#255#7#16'O'#255#9#15'P'#255#10#15'S'#255#10#14'Q'
+ +#255#12#15'R'#255#12#14'O'#255#13#16'O'#255#12#16'O'#255#11#15'N'#255#12#16
+ +'O'#255#11#15'N'#255#11#15'N'#255#11#15'N'#255#12#16'O'#255#12#15'O'#255#12
+ +#16'N'#255#14#17'H'#253#17#18'A'#251#23#18'7'#248#30#19'0s('#24','#13'8'#31
+ +'+'#1'R4)'#9#183#166#159#28#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'|'#128#132'2|sp-reb'
+ +#25'vf_0'#139'tl'#20#191#182#175'"'#221#214#212' '#0#0#0#0#156'L'#27#1#190
+ +#127'R'#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'Eq'#151#0#0#0#0#0
+ +#190#174#163#0#136've'#1#183#171#158#1'FRx'#5'9Gu}'#30'2q'#255#11'!l'#255#9
+ +#29'v'#255#10#29'w'#255#10#28'{'#255#9#26'{'#255#10#27'|'#255#10#27'|'#255#11
+ +#27#127#255#10#25#127#255#10#26#128#255#10#26'~'#255#10#27'{'#255#9#28'v'#255
+ +#16' p'#255#12#25'`'#255#9#19'P'#255#9#18'K'#255#16#20'K'#255#8#19'P'#255#8
+ +#18'M'#255#7#15'S'#255#6#17'Q'#255#2#27'e'#255#31'^'#190#255'N'#151#240#255
+ +'8v'#191#255#16',W'#255#4#4'%'#255'*a'#142#255'P'#176#232#255'S'#172#238#255
+ +'N'#177#238#255'N'#160#218#255'5|'#180#255#26'F'#135#255#7'%u'#255#6'B'#158
+ +#255#6'b'#202#255#1'b'#214#255#4'a'#219#255#9'b'#221#255#6'f'#217#255#5'd'
+ +#217#255#5'c'#217#255#6'c'#218#255#6'b'#217#255#5'a'#217#255#6'c'#221#255#7
+ +'e'#223#255#9'g'#222#255#5'c'#219#255#4'c'#220#255#10'g'#227#255#8'f'#227#255
+ +#7'd'#225#255#9'e'#226#255#7'd'#226#255#13'a'#227#255#7'a'#225#255#9'f'#230
+ +#255#6'^'#219#255#2'N'#201#255#3'I'#195#255#5'J'#193#255#11'\'#206#255#16']'
+ +#207#255#15'Q'#189#255#25'Z'#183#255#13'7y'#255#3#15'<'#255#16'$K'#255#29'4W'
+ +#255#19'1Q'#255#20'1S'#255#29'Cc'#255#29'Av'#255'8f'#176#255'G'#142#226#255
+ +'B'#161#254#255'.'#151#253#255''''#154#253#255#31#141#249#255#19'~'#237#255#7
+ +'m'#224#255#6'd'#216#255#10'g'#220#255#6'j'#221#255#4'i'#222#255#9'g'#223#255
+ +#13'b'#226#255#7'g'#225#255#9'a'#215#255#9'M'#191#255#7'H'#187#255#6'R'#197
+ ,#255#6'`'#214#255#12'e'#223#255#5'b'#217#255#6'd'#220#255#3'b'#222#255#7'b'
+ +#226#255#8'c'#223#255#9'f'#221#255#7'd'#217#255#5'e'#216#255#6'e'#219#255#6
+ +'c'#219#255#2'_'#215#255#5'a'#219#255#4'a'#219#255#7'd'#222#255#1'_'#215#255
+ +#8'f'#222#255#8'e'#222#255#5'c'#220#255#6'd'#222#255#6'd'#222#255#8'f'#224
+ +#255#5'b'#222#255#5'c'#222#255#6'd'#221#255#4'c'#222#255#7'f'#222#255#6'e'
+ +#220#255#9'h'#222#255#8'h'#225#255#5'i'#223#255#4'f'#218#255#2'e'#213#255#9
+ +'h'#211#255#15'i'#213#255#31'e'#202#255#21'@'#147#255#6#28'['#255#11#21'P'
+ +#255#6#17'H'#255#13#19'F'#255#9#19'G'#255#8#18'L'#255#7#15'P'#255#5#14'R'#255
+ +#5#14'X'#255#7#20'd'#255#7#22'p'#255#9#24'y'#255#8#23'x'#255#10#25'y'#255#5
+ +#21'u'#255#4#21'v'#255#4#20'v'#255#6#21'x'#255#7#22'{'#255#8#22'}'#255#8#22
+ +'}'#255#7#22'|'#255#8#23'}'#255#9#23'}'#255#6#21'|'#255#8#22'}'#255#8#22'}'
+ +#255#9#23'~'#255#9#23'}'#255#8#24'{'#255#10#24't'#255#14#24'n'#255#14#23'g'
+ +#255#11#19'Z'#255#9#16'T'#255#10#18'Q'#255#8#16'O'#255#9#18'Q'#255#11#16'Q'
+ +#255#13#17'R'#255#12#16'R'#255#12#15'Q'#255#14#16'Q'#255#12#14'O'#255#13#15
+ +'O'#255#12#14'N'#255#13#15'O'#255#14#16'P'#255#13#15'O'#255#13#15'O'#255#11
+ +#13'M'#255#13#15'O'#255#13#15'P'#255#13#16'N'#254#14#17'H'#252#19#20'>'#251
+ +#27#19'4'#211'"'#18'*'#24'0'#28'*'#5'K,&'#4#0#0#0#0#0#0#0#0#239#235#233#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'>Kt'#3'6Eww'#21'(h'#255#13'!p'#255#9#29'v'
+ +#255#10#28'z'#255#9#26'|'#255#10#26'~'#255#9#25'|'#255#9#25'|'#255#10#26'~'
+ +#255#10#25#127#255#11#25#127#255#9#25'}'#255#11#27'{'#255#11#28'v'#255#11#29
+ +'m'#255#12#26'^'#255#10#20'Q'#255#12#21'K'#255#9#17'J'#255#8#19'L'#255#9#18
+ +'L'#255#7#16'S'#255#11#19'R'#255#5#21'Y'#255#13';'#151#255'7o'#201#255#20'G'
+ +#145#255#7'''a'#255#6#24'A'#255#0#5'*'#255#3#4'&'#255#6#10'+'#255#7#10'-'#255
+ +#0#5'*'#255#8#10';'#255#4'!c'#255#5'8'#149#255#5'A'#176#255#5'W'#195#255#5'e'
+ +#204#255#7'c'#211#255#8'a'#217#255#7'c'#217#255#9'f'#220#255#9'd'#220#255#8
+ +'b'#221#255#8'b'#220#255#9'c'#224#255#5'_'#220#255#11'd'#226#255#6'c'#222#255
+ +#8'd'#224#255#5'a'#223#255#5'b'#224#255#9'f'#229#255#7'c'#224#255#7'd'#225
+ +#255#4'd'#224#255#2'b'#222#255#2'c'#226#255#5'd'#228#255#5'c'#227#255#6'b'
+ +#227#255#5'_'#223#255#10'c'#227#255#13'g'#231#255#12'^'#210#255#27'Q'#187#255
+ +#15'T'#182#255#19'Z'#170#255#10'0a'#255#13'3`'#255';m'#161#255#13'''N'#255#4
+ +#22';'#255#7#5' '#255#17#1#26#255#2#0#20#255#3#11'0'#255#24'>|'#255'%'#127
+ +#204#255'1'#151#249#255'!'#149#250#255#30#148#253#255#15#129#240#255#10'l'
+ +#224#255#14'g'#220#255#12'h'#221#255#4'c'#217#255#8'f'#221#255#0'i'#225#255
+ +#11'd'#226#255#11'b'#227#255#9'd'#225#255#10'a'#214#255#6'L'#192#255#0'E'#184
+ +#255#5'\'#209#255#5'b'#219#255#12'g'#227#255#5'_'#224#255#4'`'#226#255#7'a'
+ +#224#255#7'c'#221#255#3'a'#216#255#4'e'#219#255#8'e'#224#255#7'e'#223#255#5
+ +'b'#220#255#7'd'#222#255#6'c'#221#255#9'f'#224#255#3'`'#218#255#10'g'#224#255
+ +#7'd'#222#255#4'b'#220#255#5'e'#220#255#4'd'#219#255#8'g'#224#255#7'e'#224
+ +#255#5'b'#224#255#7'b'#226#255#2'`'#225#255#6'c'#225#255#6'd'#222#255#9'h'
+ +#223#255#8'i'#222#255#6'g'#219#255#9'i'#217#255#8'i'#213#255#22'm'#219#255'"'
+ +'l'#210#255'*Y'#178#255#8'$l'#255#9#21'P'#255#12#19'K'#255#9#16'I'#255#12#18
+ +'L'#255#9#17'K'#255#7#16'N'#255#6#14'S'#255#6#16'\'#255#11#21'g'#255#14#25'q'
+ +#255#9#23'u'#255#7#21'y'#255#5#16't'#255#9#21'y'#255#8#20'x'#255#11#23'|'#255
+ +#8#21'{'#255#8#22'|'#255#9#22'~'#255#8#22'~'#255#8#22#127#255#8#22#128#255#7
+ +#21#128#255#9#23#129#255#8#22#127#255#9#22#127#255#9#22'}'#255#9#22'|'#255#9
+ +#23'z'#255#11#24'v'#255#13#24'q'#255#13#22'e'#255#12#20'^'#255#11#18'U'#255
+ +#13#17'S'#255#15#18'T'#255#13#17'Q'#255#13#18'Q'#255#12#16'Q'#255#11#15'P'
+ +#255#14#16'Q'#255#14#15'P'#255#14#16'Q'#255#11#13'M'#255#12#14'N'#255#12#14
+ +'N'#255#12#14'N'#255#13#15'O'#255#12#14'N'#255#13#15'O'#255#13#15'O'#255#12
+ +#14'N'#255#12#14'O'#254#13#14'M'#254#13#16'C'#252#21#18':'#250#27#18'0P)'#22
+ +'&'#13'5'#30'&'#3#0#0#0#0'I+&'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0'TZs'#5'/;m'#200#13#30'd'#255#10#30'p'#255#10#28'z'#255#9#27'{'#255#8
+ +#24'}'#255#10#25#127#255#9#25'}'#255#9#25'}'#255#9#24'~'#255#10#25#127#255#9
+ +#24'~'#255#8#25'}'#255#9#26'y'#255#10#27'u'#255#14#30'n'#255#12#26'`'#255#11
+ +#20'R'#255#11#20'M'#255#8#16'K'#255#14#19'L'#255#15#18'L'#255#6#17'V'#255#9
+ +#17'Q'#255#7#17'Q'#255#4'*'#129#255#13'<'#155#255#17'F'#164#255#24'J'#178#255
+ +#23'K'#172#255#15'H'#151#255#6'9'#136#255#18',~'#255#17'3'#133#255#5'>'#158
+ +#255#10'G'#180#255#9'P'#187#255#11'J'#181#255#7'G'#187#255#5'b'#216#255#9'`'
+ ,#222#255#11']'#218#255#4'c'#221#255#7'a'#218#255#7'c'#220#255#4'a'#220#255#9
+ +'h'#225#255#6'd'#222#255#8'd'#223#255#4'`'#219#255#8'c'#222#255#4'd'#221#255
+ +#8'f'#225#255#3'a'#221#255#7'c'#224#255#5'b'#224#255#5'a'#222#255#5'b'#223
+ +#255#4'c'#223#255#5'd'#222#255#5'a'#221#255#15'a'#225#255#9'^'#224#255#5'_'
+ +#225#255#7'd'#227#255#11'a'#226#255#18'a'#226#255#9'V'#210#255#20'M'#188#255
+ +#18'M'#173#255#26'X'#175#255#17'D'#131#255#21'\'#156#255'c'#189#255#255#24'F'
+ +'x'#255#13'"U'#255#1#26'@'#255#25';p'#255#9#30'N'#255#5'-T'#255#11'-Y'#255#0
+ +#19'?'#255#16'U'#170#255'7'#147#243#255')'#148#250#255#27#144#252#255#15'}'
+ +#241#255#2'd'#219#255#5'b'#219#255#6'c'#220#255#8'd'#223#255#10'c'#220#255#9
+ +']'#219#255#11'^'#225#255#10']'#227#255#8'`'#228#255#10'c'#227#255#9'X'#211
+ +#255#7'D'#190#255#0'C'#186#255#11'V'#208#255#12'`'#223#255#9'_'#225#255#8'b'
+ +#227#255#8'c'#227#255#6'b'#225#255#4'`'#223#255#4'b'#225#255#5'c'#226#255#3
+ +'`'#221#255#9'd'#226#255#5'b'#221#255#6'c'#223#255#4'a'#220#255#7'd'#223#255
+ +#6'c'#221#255#7'e'#224#255#7'd'#224#255#7'd'#226#255#6'c'#227#255#5'b'#225
+ +#255#6'c'#227#255#6'a'#226#255#4'`'#223#255#6'c'#225#255#7'd'#228#255#7'e'
+ +#227#255#6'e'#224#255#11'd'#220#255#17'f'#214#255#24'i'#209#255'''k'#206#255
+ +')V'#176#255#14'$m'#255#14#20'U'#255#11#18'N'#255#11#18'K'#255#9#15'J'#255#9
+ +#16'R'#255#7#14'P'#255#4#14'S'#255#7#15'_'#255#11#21'k'#255#13#24'r'#255#11
+ +#22's'#255#6#18'q'#255#7#19's'#255#4#17'w'#255#7#19'{'#255#8#21'}'#255#8#22
+ +#128#255#9#21#129#255#9#21#129#255#7#19#127#255#8#20#128#255#10#22#130#255#8
+ +#20#128#255#7#20#127#255#7#21#127#255#7#22'}'#255#10#23'|'#255#12#24'w'#255
+ +#15#24'v'#255#15#24'p'#255#14#23'l'#255#11#21'e'#255#10#17'^'#255#12#17'['
+ +#255#14#20'W'#255#13#17'V'#255#13#18'S'#255#12#17'Q'#255#11#16'O'#255#12#17
+ +'P'#255#12#16'Q'#255#13#18'R'#255#11#15'P'#255#12#17'Q'#255#12#17'P'#255#13
+ +#16'P'#255#13#15'O'#255#13#15'O'#255#12#14'N'#255#13#15'O'#255#11#13'M'#255
+ +#13#15'O'#255#12#14'N'#255#13#16'N'#255#13#16'J'#253#16#18'B'#252#24#21'6'
+ +#221'!'#21'('#19'('#21' '#5#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0'hTO'#0'hTO'#21#0#0#0#0'CLp$&6l'#242#9#31'f'#255#9#30'r'#255#7#26'z'#255#8
+ +#28'|'#255#7#26'|'#255#8#26#127#255#6#25'|'#255#7#25'}'#255#8#25'~'#255#8#26
+ +#128#255#7#25'{'#255#10#27'|'#255#9#26'x'#255#9#26'r'#255#14#30'n'#255#12#25
+ +'_'#255#9#19'Q'#255#11#19'M'#255#7#18'I'#255#13#18'G'#255#14#16'I'#255#3#17
+ +'O'#255#8#16'Q'#255#7#14'R'#255#1'"t'#255#17'A'#168#255#2'G'#169#255#9'L'#177
+ +#255#4'8'#164#255#10'F'#183#255#8'F'#180#255#15'N'#186#255#10'Q'#190#255#17
+ +'H'#178#255#3'K'#180#255#7'I'#181#255#8'H'#181#255#4'Q'#189#255#6'a'#206#255
+ +#5'd'#210#255#1'c'#207#255#8'e'#211#255#1'b'#214#255#5'd'#216#255#3'c'#215
+ +#255#9'i'#221#255#5'e'#216#255#8'i'#220#255#7'g'#219#255#6'g'#219#255#7'h'
+ +#219#255#10'l'#224#255#6'e'#222#255#6'e'#226#255#5'd'#225#255#9'g'#227#255#7
+ +'d'#223#255#8'f'#224#255#6'h'#221#255#6'g'#221#255#4'e'#220#255#4'c'#221#255
+ +#6'f'#223#255#8'e'#220#255#7'b'#216#255#8'c'#216#255#10'W'#198#255#8'R'#183
+ +#255#14'M'#166#255#22'S'#158#255#12'&_'#255#12'T'#132#255'\'#204#250#255#27
+ +'f'#151#255#1'''Y'#255#0'%Z'#255#31'_'#156#255#8'L'#131#255#9'u'#172#255':'
+ +#187#255#255'('#128#196#255#7'%^'#255#5'B'#143#255','#150#243#255#30#156#249
+ +#255#26#150#252#255#16#127#240#255#2'o'#222#255#4'i'#223#255#7'f'#220#255#3
+ +'`'#220#255#4'f'#223#255#5'g'#222#255#7'f'#223#255#6'e'#223#255#4'f'#225#255
+ +#7'f'#226#255#8'c'#220#255#17']'#211#255#2'K'#194#255#3'K'#194#255#2'O'#201
+ +#255#6'^'#214#255#4'^'#217#255#5'a'#223#255#10'd'#229#255#7'e'#227#255#2'e'
+ +#225#255#5'f'#224#255#6'i'#225#255#7'd'#220#255#6'c'#219#255#6'c'#219#255#7
+ +'f'#223#255#7'b'#217#255#8'e'#220#255#6'c'#220#255#8'd'#225#255#8'd'#227#255
+ +#8'e'#226#255#8'f'#225#255#9'f'#224#255#7'b'#222#255#6'f'#223#255#4'g'#223
+ +#255#3'g'#225#255#8'h'#223#255#14'g'#220#255'#o'#220#255'.l'#210#255'$K'#155
+ +#255#9'"g'#255#7#18'N'#255#14#17'K'#255#10#18'K'#255#8#17'J'#255#9#19'N'#255
+ +#3#15'O'#255#2#14'V'#255#6#18'_'#255#10#24'k'#255#10#22'o'#255#4#19'p'#255#2
+ +#18'q'#255#5#19'u'#255#10#24'{'#255#7#22'{'#255#6#22'|'#255#7#22'}'#255#7#22
+ +'~'#255#9#22#129#255#8#21#128#255#8#21#127#255#9#22#128#255#9#23#129#255#8#22
+ +#127#255#8#22'}'#255#8#23'|'#255#6#23'w'#255#9#24't'#255#14#26'p'#255#15#26
+ +'k'#255#13#23'`'#255#9#18'Y'#255#10#18'Y'#255#12#19'Z'#255#13#19'Y'#255#12#19
+ +'W'#255#11#18'S'#255#10#18'P'#255#11#17'O'#255#10#16'O'#255#11#17'P'#255#9#16
+ +'P'#255#10#16'Q'#255#7#15'O'#255#10#17'O'#255#8#16'M'#255#11#16'N'#255#11#15
+ +'N'#255#11#15'M'#255#12#15'M'#255#12#15'O'#255#11#14'O'#255#10#14'N'#255#9#14
+ +'L'#254#11#16'L'#254#12#16'H'#252#17#17'>'#250#26#21'3'#164'#'#16#30#10#23#6
+ +#7#0'6'#31'#'#0':#&'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ ,#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'gSN'#0#0#0
+ +#0#0'>Mui'#22'*c'#253#3#27'g'#255#12' u'#255#7#28'z'#255#7#28'z'#255#7#28'y'
+ +#255#7#28'|'#255#6#26'{'#255#7#27'}'#255#8#28'~'#255#8#27#127#255#5#26'z'#255
+ +#8#27'y'#255#7#28'w'#255#10#29's'#255#14#30'l'#255#11#25']'#255#8#20'Q'#255#9
+ +#20'J'#255#8#22'K'#255#12#19'I'#255#11#18'M'#255#7#22'L'#255#8#17'Q'#255#7#15
+ +'U'#255#2#30'g'#255#8'?'#163#255#11'G'#174#255#11'O'#171#255#15'9'#151#255#7
+ +'9'#156#255#4'N'#175#255#12'P'#179#255#12'M'#179#255#1'N'#181#255#3'N'#177
+ +#255#9'R'#183#255#5'H'#173#255#2'V'#189#255#4'e'#208#255#9'd'#211#255#4'f'
+ +#211#255#7'j'#213#255#4'h'#213#255#10'l'#216#255#8'i'#215#255#8'j'#216#255#4
+ +'e'#211#255#6'h'#214#255#6'h'#214#255#7'k'#216#255#6'j'#213#255#8'j'#215#255
+ +#4'f'#217#255#7'j'#226#255#5'h'#225#255#6'g'#223#255#8'h'#221#255#5'e'#216
+ +#255#3'f'#218#255#5'e'#218#255#4'd'#217#255#7'g'#221#255#6'f'#218#255#3'e'
+ +#213#255#8'f'#213#255#10'e'#210#255#12'V'#201#255#7'U'#177#255#16'Q'#169#255
+ +#13'Z'#163#255#20'&P'#255#3#24'>'#255'C'#184#231#255':'#187#244#255#23#137
+ +#188#255#26'i'#161#255#14'j'#161#255#20#151#208#255#23#185#247#255#26#185#251
+ +#255'+'#194#252#255','#171#229#255#10'Jq'#18'.?q'#224
+ +#8'!b'#255#7#30'm'#255#6#29'v'#255#4#26'{'#255#5#27'z'#255#8#30'}'#255#4#26
+ +'z'#255#8#27'{'#255#7#26'{'#255#7#26'{'#255#6#25'z'#255#7#25'z'#255#7#24'y'
+ +#255#8#25'y'#255#7#24's'#255#14#29'm'#255#16#28'f'#255#9#19'U'#255#9#18'N'
+ +#255#12#19'L'#255#11#19'G'#255#10#23'E'#255#16#23'='#255#17#23'>'#255#18#24
+ +'7'#255#6#15'0'#255#2#6'('#255#9'-o'#255#20'F'#160#255#10'L'#168#255#4'N'#169
+ +#255#9'N'#170#255#15'M'#172#255#15'P'#177#255#9'O'#181#255#13'U'#190#255#8'L'
+ ,#182#255#0'I'#184#255#10'a'#209#255#3'b'#217#255#6'g'#216#255#10'f'#217#255#4
+ +'b'#216#255#6'g'#223#255#7'e'#221#255#7'e'#222#255#6'd'#220#255#5'b'#219#255
+ +#6'd'#219#255#8'g'#220#255#7'g'#218#255#7'g'#216#255#5'e'#218#255#7'f'#219
+ +#255#7'g'#220#255#9'h'#223#255#4'd'#218#255#8'g'#222#255#7'f'#221#255#8'g'
+ +#222#255#5'e'#223#255#7'f'#221#255#6'f'#220#255#7'g'#220#255#5'h'#220#255#8
+ +'k'#223#255#6'f'#219#255#9'i'#222#255#13'W'#198#255#7'N'#192#255#4'I'#187#255
+ +#14'N'#191#255#13'H'#181#255#15'K'#178#255#2'D'#171#255#12'Q'#183#255#16'U'
+ +#185#255#15'X'#186#255#12'S'#176#255#11'L'#165#255#9'B'#153#255#12';'#148#255
+ +#7';'#151#255#13'E'#164#255#3'J'#173#255#11'N'#183#255#12'L'#182#255#9'P'#182
+ +#255#7'P'#178#255#6'K'#174#255#4'N'#185#255#15'i'#218#255#26#130#248#255#7'n'
+ +#229#255#1'b'#218#255#8'e'#222#255#5'b'#219#255#5'b'#219#255#5'c'#218#255#4
+ +'c'#218#255#9'j'#223#255#5'f'#219#255#4'd'#219#255#7'e'#224#255#5'b'#221#255
+ +#6'c'#223#255#5'b'#221#255#7'd'#223#255#5'c'#221#255#6'd'#222#255#6'd'#222
+ +#255#7'f'#223#255#4'e'#220#255#5'g'#219#255#6'f'#217#255#3'd'#214#255#7'e'
+ +#216#255#9'h'#219#255#5'c'#212#255#16'h'#215#255#18'i'#214#255#27't'#213#255
+ +')p'#199#255#20'<'#143#255#16'!i'#255#12#28'a'#255#10'!e'#255#11' e'#255#10
+ +#25'd'#255#9#23'j'#255#6#21'l'#255#7#26'r'#255#6#26'v'#255#6#25'z'#255#6#25
+ +'}'#255#6#25'~'#255#6#25'}'#255#7#26'}'#255#6#24'y'#255#5#23'z'#255#7#22'|'
+ +#255#8#23'}'#255#6#21'{'#255#7#22'|'#255#7#22'|'#255#7#22'|'#255#6#21'{'#255
+ +#6#21'{'#255#7#22'}'#255#6#23'}'#255#5#24'|'#255#5#23'}'#255#7#22'~'#255#9#23
+ +'~'#255#9#22'{'#255#9#24'w'#255#10#24'q'#255#11#25'j'#255#10#23'b'#255#9#20
+ +'X'#255#8#16'P'#255#8#15'O'#255#10#16'P'#255#9#17'N'#255#9#18'O'#255#9#17'O'
+ +#255#8#16'O'#255#9#17'P'#255#8#16'O'#255#7#15'N'#255#8#16'O'#255#8#16'P'#255
+ +#9#17'O'#255#9#17'N'#255#8#16'M'#255#9#16'M'#255#8#16'L'#255#9#17'M'#255#10
+ +#15'N'#255#9#15'M'#255#8#17'L'#255#8#16'N'#255#10#14'O'#255#8#14'N'#255#7#15
+ +'P'#255#6#15'N'#255#12#15'K'#252#20#19'B'#251#27#20'5'#164')'#21'&'#17#0#0#0
+ +#0#168#151#148#7#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#216#197#189#2'UR\'#23'CPz=%8n'#249#2#25'`'#255#13'!t'#255#7#27'v'#255#8#27
+ +'|'#255#7#26'{'#255#9#28'}'#255#6#25'{'#255#8#25'|'#255#7#24'z'#255#9#25'}'
+ +#255#9#24'}'#255#10#25'~'#255#9#26'z'#255#10#25'w'#255#8#22'n'#255#17#29'k'
+ +#255#17#28'a'#255#11#20'R'#255#10#20'N'#255#11#21'L'#255#16#21'H'#255#11#22
+ +'@'#255#17#23'8'#255#20#24'8'#255#16#21','#255#6#10'('#255#5#8''''#255#5'(i'
+ +#255#14'H'#164#255#5'L'#167#255#5'O'#170#255#17'O'#171#255#16'N'#163#255#23
+ +'\'#172#255#22'V'#166#255#11'7'#138#255#7'0'#137#255#0'S'#181#255#6'a'#209
+ +#255#3'a'#215#255#4'f'#215#255#7'e'#220#255#2'e'#219#255#10'i'#222#255#5'd'
+ +#219#255#6'f'#221#255#6'f'#221#255#6'f'#221#255#4'a'#218#255#7'e'#220#255#4
+ +'c'#217#255#5'e'#216#255#5'e'#218#255#6'f'#220#255#6'e'#221#255#7'f'#226#255
+ +#4'd'#226#255#6'd'#226#255#7'e'#226#255#8'e'#225#255#4'e'#227#255#6'f'#226
+ +#255#7'e'#223#255#6'e'#220#255#4'g'#221#255#9'i'#223#255#5'e'#218#255#9'h'
+ +#221#255#15'Z'#205#255#11'Q'#193#255#8'P'#190#255#14'Q'#190#255#9'M'#185#255
+ +#12'L'#182#255#8'1'#157#255#11'A'#162#255#10'N'#180#255#8'M'#180#255#9'P'#186
+ +#255#5'N'#188#255#8'N'#189#255#13'P'#192#255#8'L'#186#255#11'Q'#189#255#13'L'
+ +#188#255#11'K'#185#255#11'M'#188#255#11'K'#185#255#15'L'#188#255#10'F'#183
+ +#255#9'F'#184#255#1'B'#175#255#2'S'#200#255#14'e'#220#255#11'g'#222#255#4'a'
+ +#218#255#5'b'#220#255#7'b'#219#255#5'`'#217#255#4'a'#217#255#7'd'#219#255#4
+ +'a'#217#255#5'`'#220#255#6'a'#223#255#5'a'#223#255#7'c'#225#255#5'`'#222#255
+ +#7'd'#224#255#6'c'#218#255#4'a'#217#255#4'b'#217#255#7'g'#222#255#6'g'#222
+ +#255#5'g'#222#255#6'g'#224#255#6'f'#222#255#7'f'#218#255#9'g'#216#255#8'g'
+ +#211#255#19'o'#213#255#28'n'#208#255'*g'#190#255#12'0{'#255#14#20'['#255#5#20
+ +'H'#255#4#18'G'#255#4#14'J'#255#7#14'Q'#255#7#13'Z'#255#8#15'd'#255#7#19'p'
+ +#255#8#25'}'#255#8#29#131#255#5#26#129#255#6#25#128#255#8#24#127#255#7#23'|'
+ +#255#7#23'}'#255#6#25'|'#255#5#23'|'#255#7#23'}'#255#8#23'}'#255#7#22'}'#255
+ +#9#24'~'#255#7#22'{'#255#6#21'{'#255#8#23'}'#255#8#23'}'#255#7#21'}'#255#8#22
+ +'}'#255#8#22'}'#255#8#22'|'#255#8#23'}'#255#9#22'z'#255#11#23'u'#255#13#24'o'
+ +#255#13#24'j'#255#12#21'a'#255#8#17'W'#255#8#16'P'#255#12#17'P'#255#14#19'R'
+ +#255#12#18'Q'#255#9#16'O'#255#11#19'O'#255#10#18'N'#255#9#17'M'#255#9#16'O'
+ +#255#8#14'N'#255#9#16'O'#255#9#15'P'#255#8#14'O'#255#10#17'P'#255#11#17'P'
+ +#255#10#16'P'#255#9#14'O'#255#10#15'O'#255#11#15'O'#255#10#15'N'#255#10#15'L'
+ +#255#9#16'L'#255#11#18'O'#255#11#14'R'#255#9#14'O'#255#9#15'O'#255#10#15'O'
+ +#254#17#16'G'#251#24#18';'#245'"'#22'.Q)'#19#31#10#0#0#0#0#185#170#165#6#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ ,#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#136'~'#131#0#255#255#255#0
+ +'US_:BPw'#144#27'-f'#252#8#29'g'#255#9#28'r'#255#9#25'y'#255#8#27'{'#255#8#25
+ +'|'#255#8#26'{'#255#8#24'z'#255#8#23'|'#255#9#24'}'#255#9#24#127#255#9#24'~'
+ +#255#9#24'~'#255#9#25'y'#255#11#25'u'#255#10#22'j'#255#18#27'h'#255#16#26'^'
+ +#255#8#18'P'#255#9#17'K'#255#10#19'H'#255#13#20'D'#255#12#22'='#255#22#23'7'
+ +#255#20#23'1'#255#10#16'"'#255#6#11' '#255#2#5'&'#255#15'/j'#255#8'Q'#160#255
+ +#17'N'#153#255#23'O'#158#255'%U'#158#255'*]'#156#255#29'N'#132#255#7'"P'#255
+ +#10#11'?'#255#3#28'g'#255#7']'#187#255#3'['#206#255#10'a'#214#255#2'a'#210
+ +#255#8'a'#219#255#4'e'#220#255#10'c'#211#255#6'c'#218#255#7'd'#218#255#6'd'
+ +#219#255#8'c'#220#255#8'e'#222#255#8'e'#224#255#5'c'#220#255#8'h'#222#255#6
+ +'d'#219#255#7'e'#221#255#4'e'#220#255#7'h'#226#255#6'g'#227#255#6'e'#227#255
+ +#5'd'#226#255#7'f'#229#255#4'f'#230#255#4'f'#230#255#8'd'#227#255#6'f'#224
+ +#255#2'd'#218#255#9'f'#219#255#6'd'#218#255#8'd'#220#255#10'['#205#255#9'P'
+ +#190#255#5'N'#185#255#16'L'#183#255#9'J'#183#255#8'M'#187#255#14'<'#169#255#6
+ +'5'#152#255#2'>'#170#255#19'P'#187#255#13'K'#181#255#13'J'#180#255#12'L'#183
+ +#255#8'K'#184#255#9'J'#184#255#10'J'#185#255#7'L'#186#255#9'L'#187#255#11'K'
+ +#188#255#8'I'#186#255#6'J'#184#255#5'G'#181#255#7'G'#179#255#11'L'#183#255#10
+ +'I'#184#255#5'Q'#201#255#8'`'#216#255#4'`'#217#255#4'_'#221#255#7'_'#219#255
+ +#3'`'#215#255#10'a'#221#255#7'^'#218#255#8'_'#218#255#6'^'#220#255#6'`'#224
+ +#255#4'_'#223#255#4'_'#223#255#5'`'#223#255#5'a'#222#255#7'_'#219#255#8'b'
+ +#222#255#5'a'#221#255#8'd'#226#255#5'a'#225#255#8'c'#228#255#5'd'#226#255#6
+ +'f'#228#255#6'i'#221#255#12'j'#218#255#26'n'#216#255'-r'#209#255'''S'#163#255
+ +#16#31'd'#255#5#15'K'#255#2#18'J'#255#6#15'N'#255#11#14'R'#255#9#12'T'#255#5
+ +#14'\'#255#3#17'd'#255#6#22'q'#255#6#22'z'#255#7#22#128#255#6#23'|'#255#6#23
+ +'|'#255#8#23'}'#255#8#22'|'#255#7#22'{'#255#8#23'~'#255#7#21'|'#255#6#22'|'
+ +#255#6#20#127#255#8#22#128#255#7#22'}'#255#8#23'~'#255#6#21'|'#255#6#21'|'
+ +#255#6#21'{'#255#7#21'|'#255#7#21'{'#255#8#22'}'#255#7#21'|'#255#8#22'|'#255
+ +#9#24'{'#255#11#23'u'#255#12#24'm'#255#16#25'h'#255#15#23'`'#255#11#17'V'#255
+ +#9#15'Q'#255#12#16'R'#255#13#16'Q'#255#11#16'P'#255#11#17'P'#255#10#16'O'#255
+ +#11#16'N'#255#11#16'N'#255#12#17'O'#255#12#16'M'#255#11#16'O'#255#12#17'P'
+ +#255#11#16'P'#255#11#15'O'#255#10#14'O'#255#11#15'O'#255#10#14'P'#255#10#14
+ +'P'#255#10#14'O'#255#10#15'O'#255#12#15'O'#255#11#14'M'#255#10#15'L'#255#12
+ +#15'O'#255#13#14'Q'#255#13#15'Q'#255#11#16'O'#254#13#14'L'#253#20#17'C'#250
+ +#29#20'5'#213'%'#18'&*-'#22#28#8#127'g^'#3#211#202#198#12#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'XTe'#11'KMc=;Lz'#212#20'$a'#252#5#27
+ +'h'#255#8#29'v'#255#8#25'z'#255#5#26'x'#255#9#24'}'#255#9#26'{'#255#8#25'z'
+ +#255#8#24'|'#255#9#24'~'#255#9#24'~'#255#9#24#127#255#8#24'|'#255#9#26'y'#255
+ +#11#25's'#255#9#21'd'#255#17#25'c'#255#16#24'['#255#9#17'P'#255#11#18'I'#255
+ +#15#19'G'#255#13#20'C'#255#17#23'9'#255#26#25'2'#255#20#20''''#255#10#15#28
+ +#255#13#11#25#255#5#7#30#255#4#31'?'#255'''Y'#134#255'.X'#133#255')^'#135#255
+ +'(Uq'#255'!3T'#255#6#19'3'#255#0#8'"'#255#8#8','#255#7'.}'#255#6'g'#195#255#6
+ +'['#211#255#7'b'#212#255#1'd'#213#255#11'b'#220#255#5'c'#219#255#6'c'#210#255
+ +#9'd'#219#255#7'c'#218#255#6'b'#218#255#5'b'#219#255#6'c'#220#255#6'c'#220
+ +#255#7'f'#222#255#6'f'#221#255#5'b'#219#255#8'e'#222#255#7'g'#222#255#6'h'
+ +#223#255#6'g'#223#255#7'g'#226#255#6'f'#225#255#6'e'#227#255#10'c'#228#255#5
+ +'d'#228#255#11'a'#228#255#10'g'#230#255#2'b'#219#255#12'd'#218#255#5'd'#218
+ +#255#15'f'#225#255#15'b'#207#255#11'P'#192#255#10'I'#185#255#14'N'#183#255#15
+ +'M'#183#255#14'K'#185#255#15'M'#185#255#6'A'#162#255#9','#133#255#10'-'#135
+ +#255#9':'#152#255#10'H'#171#255#11'N'#180#255#8'K'#178#255#4'H'#175#255#6'L'
+ +#179#255#8'J'#186#255#10'I'#185#255#12'H'#185#255#12'K'#185#255#11'H'#181#255
+ +#13'F'#177#255#17'L'#181#255#6'K'#176#255#11'K'#183#255#6'>'#166#255#3'B'#171
+ +#255#9'^'#206#255#5'`'#217#255#10'^'#219#255#7'\'#218#255#7'^'#223#255#9'_'
+ +#222#255#10'b'#224#255#6'_'#222#255#5'`'#224#255#8'b'#227#255#6'`'#225#255#9
+ +'d'#228#255#5'a'#222#255#4'a'#225#255#4'a'#223#255#2'`'#223#255#7'd'#229#255
+ +#3'_'#226#255#6'a'#226#255#8'd'#223#255#10'd'#220#255#16'j'#212#255#27'l'#216
+ +#255'(d'#202#255#20'>'#137#255#9#30'Z'#255#5#15'M'#255#7#17'R'#255#13#18'O'
+ +#255#8#16'T'#255#6#14'W'#255#7#16'^'#255#11#21'l'#255#11#23'v'#255#9#23'z'
+ +#255#9#22'}'#255#9#23'~'#255#7#22'|'#255#8#23'}'#255#7#22'|'#255#8#23'~'#255
+ +#7#22'}'#255#9#24#127#255#7#22'}'#255#8#22#127#255#9#23#129#255#9#22#129#255
+ ,#8#23'~'#255#7#22'|'#255#7#22'|'#255#6#21'{'#255#7#21'{'#255#7#22'|'#255#5#20
+ +'{'#255#9#23'~'#255#7#22'|'#255#9#23'z'#255#10#25'u'#255#13#24'k'#255#13#26
+ +'d'#255#13#21'Y'#255#10#17'Q'#255#9#15'P'#255#11#16'Q'#255#11#16'P'#255#10#15
+ +'P'#255#11#16'Q'#255#11#16'P'#255#12#16'O'#255#12#17'P'#255#13#18'Q'#255#11
+ +#16'O'#255#11#16'M'#255#12#17'O'#255#12#17'P'#255#11#16'O'#255#12#16'Q'#255
+ +#11#16'O'#255#11#16'O'#255#11#16'O'#255#11#16'O'#255#10#15'N'#255#10#15'N'
+ +#255#12#16'P'#255#11#15'N'#255#11#14'O'#255#12#15'O'#255#12#14'O'#255#12#14
+ +'O'#255#11#14'M'#255#15#16'I'#252#22#17'>'#250' '#20'2'#162'('#20'$'#22'4'#21
+ +#24#2#182#166#163#6#227#221#215#7#226#219#216#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0'eV\'#0'xLN'#0'[Vb ?KmR0Au'#244#12#29'`'#252#13'"t'#255#8#31'{'#255#10
+ +#26'|'#255#5#27'z'#255#7#26'{'#255#7#27'|'#255#6#25'z'#255#6#26'}'#255#9#24
+ +'~'#255#8#23'}'#255#10#25'~'#255#8#25'z'#255#8#28'v'#255#12#28'q'#255#10#22
+ +'a'#255#13#22'Y'#255#17#25'V'#255#11#19'L'#255#12#16'F'#255#15#18'E'#255#16
+ +#21'A'#255#20#22'8'#255#21#22'('#255#17#18#29#255#14#13#24#255#17#10#22#255
+ +#11#10#21#255#8#19#22#255#29'/E'#255'4EU'#255'$,5'#255#16#22'"'#255#3#5' '
+ +#255#15#9'$'#255#7#8'.'#255#2'"h'#255#7'@'#155#255#5']'#193#255#10'c'#212#255
+ +#7'e'#216#255#6'g'#217#255#10'd'#219#255#5'd'#218#255#6'f'#215#255#11'h'#225
+ +#255#8'e'#222#255#8'e'#222#255#7'd'#221#255#8'e'#223#255#4'a'#218#255#9'g'
+ +#222#255#9'g'#221#255#8'h'#219#255#6'f'#218#255#8'i'#220#255#5'h'#219#255#8
+ +'k'#222#255#4'g'#220#255#7'h'#222#255#8'g'#222#255#4'd'#220#255#5'e'#221#255
+ +#7'e'#223#255#7'i'#226#255#7'd'#217#255#12'e'#212#255#14'j'#209#255#20'Y'#194
+ +#255#9'4'#145#255#4'L'#172#255#18'M'#182#255#12'J'#179#255#6'N'#181#255#8'I'
+ +#181#255#4'K'#184#255#13'P'#184#255#11'O'#179#255#14'D'#166#255#7'&'#131#255
+ +#8#31'x'#255#5','#133#255#1'8'#150#255#3'?'#167#255#16'F'#182#255#9'H'#184
+ +#255#7'H'#183#255#5'I'#181#255#8'J'#178#255#7'I'#172#255#16'L'#173#255#12'N'
+ +#169#255#15'V'#176#255#25'@'#147#255#0#29'l'#255#10'?'#160#255#10'Y'#212#255
+ +#8'_'#215#255#4'd'#213#255#7'^'#216#255#7'`'#217#255#3'`'#214#255#7'c'#219
+ +#255#4'b'#218#255#4'a'#219#255#8'f'#225#255#5'd'#221#255#5'd'#221#255#5'e'
+ +#221#255#5'd'#226#255#7'e'#228#255#7'e'#228#255#5'f'#230#255#2'e'#227#255#6
+ +'f'#223#255#9'f'#217#255#13'f'#211#255'"l'#211#255'&]'#183#255#20'1w'#255#3
+ +#22'O'#255#10#19'N'#255#12#18'P'#255#6#12'Q'#255#2#14'S'#255#2#15'^'#255#7#20
+ +'i'#255#9#23'q'#255#10#24'z'#255#9#23'}'#255#6#21'|'#255#7#23'}'#255#6#25'|'
+ +#255#6#23'|'#255#8#24'~'#255#5#22'{'#255#7#23'~'#255#7#23'~'#255#8#24#127#255
+ +#6#23'}'#255#7#22#129#255#8#23'~'#255#7#22'}'#255#7#22'}'#255#8#22'|'#255#7
+ +#22'|'#255#6#21'{'#255#7#22'{'#255#9#24'}'#255#5#22'{'#255#7#24'|'#255#7#24
+ +'u'#255#12#25'o'#255#12#24'f'#255#15#24'^'#255#9#18'Q'#255#6#14'G'#255#6#15
+ +'K'#255#8#18'O'#255#9#17'O'#255#9#16'O'#255#10#16'P'#255#10#16'Q'#255#9#15'P'
+ +#255#8#15'O'#255#11#17'P'#255#12#17'P'#255#12#17'P'#255#10#15'L'#255#11#16'N'
+ +#255#11#16'O'#255#9#14'M'#255#12#16'Q'#255#11#16'O'#255#11#16'O'#255#12#17'P'
+ +#255#11#16'O'#255#11#16'O'#255#10#15'N'#255#11#16'O'#255#10#15'N'#255#10#15
+ +'O'#255#12#14'O'#254#11#13'M'#255#11#14'M'#254#12#14'J'#253#18#17'D'#250#25
+ +#17'7'#250'%'#21',o7'#24#26#7'> !'#2#233#227#224#8#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'eV\'#13'_Wc):Gk'#161'$5n'#249#10#27'e'#253
+ +#6#31'r'#255#5#28'z'#255#11#30#129#255#2#27'y'#255#8#26'|'#255#7#27'{'#255#7
+ +#27'z'#255#6#25'z'#255#6#24'~'#255#6#24'}'#255#7#26'}'#255#7#26'{'#255#10#28
+ +'w'#255#13#29'r'#255#13#25'a'#255#10#19'Q'#255#14#22'P'#255#10#19'H'#255#10
+ +#18'D'#255#13#18'E'#255#11#20'>'#255#21#20'='#255#20#21'2'#255#10#16#28#255
+ +#19#15#21#255#17#13#21#255#11#15#19#255#16#16#12#255#16#9#15#255#2#13#10#255
+ +#4#12#9#255#7#11#30#255#6#9'$'#255#3#10'-'#255#2'*v'#255#4'c'#198#255#5'K'
+ +#181#255#4'S'#192#255#11'g'#212#255#4'd'#214#255#7'e'#216#255#8'c'#214#255#7
+ +'f'#216#255#6'g'#218#255#9'g'#221#255#6'd'#218#255#10'h'#222#255#7'f'#220#255
+ +#7'f'#220#255#4'd'#217#255#6'f'#217#255#7'h'#218#255#6'g'#216#255#8'i'#220
+ +#255#7'j'#221#255#6'h'#220#255#6'i'#220#255#4'f'#218#255#7'g'#218#255#8'h'
+ +#220#255#6'j'#223#255#4'g'#220#255#0'g'#218#255#4'm'#221#255#14'h'#213#255#9
+ +'e'#196#255#28'v'#195#255' T'#157#255#0#4'9'#255#17'1t'#255#11'G'#157#255#14
+ +'M'#176#255#14'S'#183#255#5'N'#180#255#11'K'#183#255#13'M'#183#255#6'K'#176
+ +#255#7'N'#181#255#11'Q'#187#255#10'M'#185#255#7'D'#177#255#14'H'#179#255#7'K'
+ +#177#255#3'P'#179#255#9'L'#180#255#9'L'#177#255#11'M'#172#255#17'O'#166#255
+ ,#18'Q'#159#255#27']'#164#255#31'R'#151#255#15'3v'#255#2#13'R'#255#10'='#147
+ +#255#2'Z'#196#255#2'_'#217#255#5'`'#217#255#5'd'#219#255#4'a'#214#255#5'b'
+ +#215#255#4'`'#213#255#7'd'#218#255#5'b'#218#255#5'b'#220#255#10'i'#226#255#6
+ +'d'#222#255#4'a'#220#255#6'd'#222#255#8'e'#224#255#7'c'#223#255#4'a'#220#255
+ +#7'f'#224#255#6'e'#220#255#8'e'#213#255#26'l'#210#255'!n'#206#255'&V'#173#255
+ +#7'!g'#255#9#18'N'#255#2#17'M'#255#1#16'V'#255#8#14'V'#255#11#14'Z'#255#0#18
+ +'e'#255#5#21't'#255#12#27'z'#255#7#24'x'#255#7#24'{'#255#6#22'z'#255#6#24'|'
+ +#255#7#26'}'#255#7#26'}'#255#7#24#128#255#7#23'~'#255#5#23'}'#255#6#23'~'#255
+ +#5#22'}'#255#6#24'~'#255#5#23'}'#255#7#24'~'#255#5#23'}'#255#7#23'}'#255#8#22
+ +'}'#255#7#22'|'#255#8#23'}'#255#6#22'{'#255#6#23'y'#255#6#23'x'#255#7#23's'
+ +#255#9#25'r'#255#10#24'j'#255#14#25'a'#255#14#23'Y'#255#11#18'M'#255#8#13'H'
+ +#255#10#14'G'#255#11#18'M'#255#11#19'P'#255#8#16'N'#255#10#17'P'#255#8#15'N'
+ +#255#8#15'O'#255#8#16'M'#255#8#16'N'#255#9#16'O'#255#9#16'O'#255#10#16'O'#255
+ +#10#16'M'#255#9#15'N'#255#8#14'M'#255#8#14'M'#255#10#15'P'#255#9#16'O'#255#9
+ +#16'O'#255#10#16'O'#255#10#15'N'#255#11#16'O'#255#10#15'N'#255#10#15'N'#255
+ +#11#16'O'#255#9#14'O'#255#10#15'N'#254#11#14'L'#253#14#15'K'#254#13#14'G'#251
+ +#21#19'B'#249#31#20'2'#244')'#19'%29'#28#31#14#0#0#0#0#236#231#229#1#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'dV\%\Ve-6Dl'#206#28'+h'
+ +#249#8#25'c'#253#8#30't'#255#8#27'|'#255#7#27'~'#255#6#27'}'#255#7#26'|'#255
+ +#8#27'}'#255#6#27'z'#255#8#28'~'#255#7#24'~'#255#9#26#128#255#8#25'}'#255#8
+ +#26'|'#255#9#27'y'#255#13#29'r'#255#13#25'd'#255#8#18'R'#255#9#17'K'#255#12
+ +#20'I'#255#11#19'F'#255#9#18'F'#255#11#21'B'#255#17#20'A'#255#18#20':'#255#14
+ +#19'&'#255#15#13#20#255#12#13#19#255#11#15#18#255#14#13#15#255#5#14#17#255#3
+ +#11#25#255#3#11#31#255#5#4''''#255#6#8'/'#255#10')s'#255#12']'#211#255#7'_'
+ +#215#255#14'^'#207#255#3'T'#196#255#2'['#203#255#5'b'#212#255#7'b'#211#255#6
+ +'`'#211#255#6'c'#215#255#6'e'#218#255#5'd'#216#255#4'd'#216#255#8'g'#220#255
+ +#6'f'#219#255#6'f'#220#255#8'j'#223#255#6'i'#220#255#6'i'#220#255#4'b'#219
+ +#255#9'i'#225#255#7'e'#224#255#2'c'#221#255#4'd'#223#255#8'g'#224#255#5'e'
+ +#219#255#8'e'#221#255#7'f'#222#255#9'g'#224#255#7'g'#227#255#8'f'#215#255#7
+ +'b'#206#255#20'q'#200#255#19'n'#180#255'&]'#146#255#0#14'+'#255#3#6'1'#255#4
+ +'+k'#255#12'R'#170#255#20'G'#176#255#18'K'#177#255#6'K'#178#255#5'J'#180#255
+ +#7'J'#182#255#13'I'#184#255#9'H'#185#255#12'H'#186#255#8'H'#185#255#10'O'#184
+ +#255#11'M'#181#255#10'L'#180#255#14'P'#176#255#15'P'#164#255#23'S'#156#255'*'
+ +']'#163#255'"R'#143#255#23''#255#18#22'5'#255#17#19'('#255#13#15#29#255#10#13#26#255#5#12
+ +#23#255#9#11#26#255#9#6' '#255#8#6'/'#255#8#22'P'#255#4'0'#136#255#14']'#202
+ +#255#9'e'#223#255#8'c'#212#255#13'd'#218#255#6'^'#211#255#3'Z'#207#255#9'c'
+ ,#215#255#9'c'#216#255#10'e'#219#255#8'e'#220#255#5'c'#218#255#7'e'#222#255#7
+ +'e'#221#255#8'g'#221#255#7'g'#221#255#6'g'#221#255#8'i'#223#255#5'f'#223#255
+ +#6'g'#223#255#4'a'#223#255#7'd'#226#255#7'd'#229#255#7'e'#229#255#4'c'#227
+ +#255#7'g'#229#255#7'e'#226#255#9'f'#226#255#5'e'#225#255#5'd'#224#255#9'd'
+ +#229#255#10'`'#211#255#4'b'#206#255#15'k'#197#255#24't'#188#255'8u'#172#255
+ +#13'!>'#255#2#18'%'#255#0#9'&'#255#23'3m'#255#25'H'#150#255#21'P'#175#255#11
+ +'F'#179#255#13'I'#180#255#9'G'#176#255#11'J'#180#255#10'I'#180#255#13'J'#183
+ +#255#15'J'#182#255#20'L'#175#255#26'N'#170#255#26'N'#161#255'%Y'#157#255'/`'
+ +#148#255',Os'#255#29''#255#9#12':'#255#9#13'@'#255#11#16'J'#255#11#18'P'#255#10#16'Q'#255#10#16
+ +'Q'#255#11#17'R'#255#10#16'P'#255#10#17'O'#255#9#16'O'#255#9#16'O'#255#9#16
+ +'O'#255#9#16'O'#255#10#16'O'#255#8#14'N'#255#9#15'O'#255#7#15'O'#255#9#16'O'
+ +#255#8#16'O'#255#9#15'N'#255#11#15'N'#255#10#16'Q'#255#8#14'P'#255#9#15'P'
+ +#255#9#15'P'#255#8#14'N'#255#8#14'O'#255#10#16'Q'#255#10#16'Q'#255#6#14'P'
+ +#253#9#16'P'#252#15#16'K'#251#20#17'A'#246#27#21'6'#233'$'#21','#144'.'#25'#'
+ +#7'>$('#1':'#31'$'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#229#227#223#5#255#255#255#0'`Z[WQPj29Gu'#247#15#31'^'#251#17#31'n'#254#8
+ +#28'z'#255#7#26'}'#255#11#28#128#255#10#26'}'#255#9#25'}'#255#9#24'}'#255#10
+ +#26'|'#255#11#26#128#255#9#24'~'#255#10#25#127#255#9#24'~'#255#10#25'~'#255#7
+ +#25'{'#255#11#26'x'#255#13#26'o'#255#15#25'c'#255#9#19'U'#255#11#19'M'#255#11
+ +#17'I'#255#11#18'J'#255#9#19'H'#255#10#19'I'#255#14#20'I'#255#14#18'F'#255#15
+ +#18'I'#255#12#17'L'#255#6#17'R'#255#4#17'V'#255#10'#t'#255#18'Q'#193#255#6']'
+ +#222#255#14'g'#220#255#4'h'#219#255#2'g'#224#255#9'd'#226#255#7'd'#224#255#6
+ +'d'#223#255#8'f'#225#255#5'd'#220#255#7'd'#221#255#6'c'#220#255#8'e'#222#255
+ +#7'd'#221#255#5'a'#218#255#6'a'#221#255#10'c'#225#255#7'c'#224#255#7'h'#228
+ +#255#3'f'#224#255#5'g'#224#255#7'i'#230#255#7'h'#233#255#7'g'#230#255#7'g'
+ +#231#255#7'f'#228#255#3'c'#225#255#6'c'#227#255#12'e'#230#255#4'`'#224#255#4
+ +'e'#226#255#8'e'#231#255#5'j'#233#255#11'\'#221#255#2'F'#195#255#8'd'#229#255
+ +#3'f'#220#255#12'g'#208#255#25't'#198#255#27'b'#147#255#4#20'/'#255#12#16#22
+ +#255#5#16#22#255#9#12#19#255#15#13#17#255#7#8#14#255#11#22' '#255#15'!$'#255
+ +#24'"+'#255#25#28','#255#16#21'"'#255#11#17#23#255#9#10#12#255#8#10#13#255#6
+ +#12#16#255#3#11#25#255#8#9'%'#255#4#3'%'#255#4#27'R'#255#2'C'#160#255#11']'
+ +#209#255#11'b'#217#255#3'c'#224#255#6'^'#222#255#6'^'#222#255#8'`'#223#255#5
+ +'_'#221#255#8'a'#226#255#8'`'#226#255#7'`'#226#255#8'b'#226#255#8'c'#225#255
+ +#8'c'#223#255#10'f'#224#255#7'd'#224#255#8'f'#227#255#6'e'#225#255#8'h'#226
+ +#255#7'g'#224#255#12'h'#213#255#18'i'#210#255')l'#207#255#26'@'#148#255#13#28
+ +'c'#255#6#18'U'#255#4#15'W'#255#3#14']'#255#4#18'l'#255#8#23'u'#255#9#25'|'
+ +#255#9#24'}'#255#9#24'|'#255#9#25'|'#255#9#24'}'#255#8#23#127#255#8#23'~'#255
+ +#9#24'~'#255#9#24#127#255#8#23#128#255#8#21#127#255#8#21'}'#255#6#21'|'#255#6
+ +#22'{'#255#8#23'}'#255#8#23'}'#255#8#23'}'#255#7#22'}'#255#8#23'}'#255#7#22
+ +'|'#255#8#23'}'#255#8#24'~'#255#8#22'|'#255#7#23'y'#255#8#24'z'#255#9#22'z'
+ +#255#10#26'v'#255#5#26'i'#255#12#23'^'#255#14#19'Q'#255#7#16'C'#255#9#14'?'
+ +#255#10#11'<'#255#7#11'='#255#7#15'F'#255#10#17'L'#255#10#16'P'#255#9#16'Q'
+ ,#255#8#17'P'#255#9#17'P'#255#9#15'O'#255#9#16'O'#255#10#16'O'#255#9#15'N'#255
+ +#10#16'N'#255#10#16'N'#255#10#16'N'#255#10#15'N'#255#9#16'O'#255#10#16'O'#255
+ +#11#17'P'#255#11#16'O'#255#11#15'O'#255#11#14'O'#255#10#15'Q'#255#9#15'Q'#255
+ +#10#16'S'#255#8#14'O'#255#9#14'O'#255#10#15'P'#255#11#16'Q'#255#11#16'P'#254
+ +#8#15'N'#252#10#15'J'#251#15#15'E'#250#24#18'='#239'"'#23'2'#203'&'#19'&J;!)'
+ +#3#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#212#207#199#12#255#255#255#3']VY]LRh;>Mz'#248#16'#_'#252#19'"n'#255#11#29
+ +'}'#255#5#28'{'#255#9#23'}'#255#10#27'|'#255#9#24'~'#255#8#24'|'#255#9#24'~'
+ +#255#9#24'~'#255#7#22'|'#255#9#24'~'#255#9#24'~'#255#9#24'~'#255#6#26'|'#255
+ +#10#27'{'#255#14#28't'#255#17#28'k'#255#10#21'W'#255#10#19'M'#255#9#17'I'#255
+ +#12#19'K'#255#10#17'H'#255#12#18'I'#255#13#19'H'#255#12#18'G'#255#12#18'H'
+ +#255#11#17'I'#255#8#16'N'#255#7#16'P'#255#3#14'P'#255#3'&~'#255#18'S'#193#255
+ +#16'h'#220#255#11'h'#221#255#6'e'#219#255#7'f'#225#255#7'f'#223#255#5'c'#222
+ +#255#7'f'#224#255#6'd'#222#255#9'f'#224#255#9'f'#224#255#6'd'#221#255#7'd'
+ +#221#255#8'f'#223#255#7'e'#223#255#6'f'#225#255#8'g'#226#255#6'c'#222#255#9
+ +'g'#222#255#9'h'#224#255#7'h'#225#255#8'i'#231#255#9'h'#229#255#9'g'#227#255
+ +#10'g'#225#255#5'd'#221#255#6'g'#225#255#7'g'#227#255#6'g'#228#255#7'g'#229
+ +#255#10'g'#224#255#6'i'#225#255#10'\'#211#255#2'I'#192#255#11'g'#221#255#5'h'
+ +#224#255#10'd'#211#255#14'm'#208#255#27'x'#194#255#8'F|'#255#11'">'#255#3#14
+ +#19#255#9#19#23#255#10#10#20#255#15#14#21#255#11#16#14#255#19#11#15#255#13#13
+ +#13#255#10#14#12#255#15#15#12#255#19#16#16#255#10#14#19#255#8#13#26#255#10#11
+ +'!'#255#12#5'!'#255#2#9'7'#255#8'.{'#255#12'S'#184#255#7'f'#215#255#10'f'#221
+ +#255#11'`'#218#255#6'a'#222#255#9'b'#224#255#5'^'#217#255#8'a'#221#255#6'`'
+ +#220#255#10'e'#224#255#8'c'#222#255#8'c'#222#255#6'c'#222#255#5'e'#220#255#5
+ +'b'#218#255#6'c'#220#255#6'd'#222#255#6'e'#224#255#5'e'#221#255#4'e'#217#255
+ +#7'i'#216#255#17'm'#215#255'#o'#204#255#25'H'#153#255#8#28'i'#255#7#18'Z'#255
+ +#5#17'X'#255#5#18']'#255#8#21'j'#255#9#25'y'#255#10#27'z'#255#10#26'{'#255#8
+ +#24'y'#255#10#25'|'#255#8#23'}'#255#10#25#127#255#9#24'~'#255#7#23'}'#255#7
+ +#23'}'#255#8#22'}'#255#10#24#127#255#8#23'}'#255#7#21'|'#255#8#23'|'#255#8#23
+ +'}'#255#8#22'|'#255#9#24'~'#255#8#23'}'#255#7#22'}'#255#7#22'}'#255#7#22'}'
+ +#255#7#22'|'#255#7#23'}'#255#3#24'}'#255#12#25'z'#255#10#24'x'#255#5#24'w'
+ +#255#6#25'p'#255#10#21'e'#255#7#25'b'#255#18'"b'#255#7#22'I'#255#9#17'A'#255
+ +#12#12'?'#255#10#14'B'#255#5#15'H'#255#9#17'N'#255#10#17'P'#255#9#17'P'#255
+ +#10#17'P'#255#10#17'P'#255#11#17'P'#255#12#17'P'#255#11#16'O'#255#11#16'O'
+ +#255#12#17'N'#255#12#17'N'#255#11#16'O'#255#11#16'O'#255#11#16'O'#255#12#17
+ +'P'#255#12#17'P'#255#12#17'P'#255#12#17'P'#255#11#16'P'#255#10#16'P'#255#9#15
+ +'O'#255#8#14'N'#255#8#15'O'#255#10#15'O'#255#11#16'O'#255#11#16'N'#254#12#17
+ +'O'#254#10#14'K'#252#15#17'K'#251#19#16'C'#247#31#20'9'#223'%'#20'-'#146'&'
+ +#20'('#23'@#'''#1'>$+'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#224#221#215'6'#0#0#0#0'^\\]EKaE;Kx'#250#22'+e'#252#12#30'h'
+ +#255#8#29'x'#255#7#29'|'#255#11#24#127#255#10#26'~'#255#8#28'~'#255#7#27'}'
+ +#255#8#28#127#255#10#30#128#255#7#25'~'#255#8#26#127#255#9#28#129#255#7#25'~'
+ +#255#7#26'~'#255#10#26'}'#255#11#26'y'#255#15#28'p'#255#13#26'c'#255#10#20'S'
+ +#255#9#18'L'#255#14#20'L'#255#11#18'I'#255#12#19'J'#255#14#20'J'#255#11#17'G'
+ +#255#14#19'J'#255#11#18'J'#255#10#17'M'#255#9#18'N'#255#7#13'Q'#255#4#15'M'
+ +#255#3'+'#129#255#9'U'#199#255#12'f'#216#255#9'f'#217#255#5'f'#222#255#9'd'
+ +#220#255#7'g'#222#255#9'h'#224#255#7'e'#223#255#9'g'#226#255#7'd'#223#255#6
+ +'c'#220#255#5'c'#219#255#6'd'#220#255#6'g'#218#255#6'h'#216#255#12'j'#220#255
+ +#7'g'#218#255#7'h'#219#255#9'k'#225#255#12'n'#229#255#8'm'#228#255#8'h'#230
+ +#255#3'f'#228#255#6'h'#229#255#9'f'#224#255#11'k'#225#255#0'h'#220#255#3'g'
+ +#224#255#10'b'#226#255#7'd'#222#255#7'f'#225#255#16'f'#223#255#3'O'#195#255#4
+ +'['#206#255#11'i'#225#255#5'g'#218#255#4'j'#214#255#8'l'#207#255#20'x'#205
+ +#255#25'a'#157#255#4'(C'#255#7#11#19#255#16#15#22#255#10#13#17#255#14#19#16
+ +#255#14#18#21#255#11#15#19#255#12#13#24#255#7#12#25#255#7#14#29#255#3#12#31
+ +#255#1#7'%'#255#6#10','#255#7#30'\'#255#10'L'#163#255#6'l'#211#255#3'd'#214
+ +#255#7'e'#215#255#1'e'#217#255#8'c'#221#255#8'a'#216#255#6'a'#221#255#8'c'
+ +#223#255#9'e'#222#255#6'b'#218#255#10'e'#222#255#7'd'#223#255#7'e'#222#255#6
+ +'d'#221#255#7'g'#221#255#4'c'#219#255#6'c'#223#255#5'b'#225#255#7'f'#228#255
+ ,#8'h'#225#255#9'h'#216#255#12'k'#210#255#29'p'#207#255#29'W'#171#255#13'%m'
+ +#255#11#19'\'#255#5#18'\'#255#5#22'd'#255#5#24'l'#255#10#26'x'#255#9#25'{'
+ +#255#8#26'z'#255#8#25'y'#255#7#24'z'#255#8#24'|'#255#7#22'|'#255#8#23'}'#255
+ +#10#24'~'#255#8#27'~'#255#7#25'~'#255#6#24'}'#255#7#26'~'#255#6#24'}'#255#6
+ +#23'|'#255#7#22'|'#255#8#23'}'#255#7#23'}'#255#8#22'}'#255#6#22'}'#255#7#22
+ +'}'#255#7#22'}'#255#7#22'|'#255#6#21'{'#255#9#24'~'#255#7#23'~'#255#9#23'y'
+ +#255#6#28'y'#255#6#27'r'#255#6#18'f'#255#6#24'o'#255#19'B'#148#255#21';'#135
+ +#255#11'"['#255#7#20'H'#255#9#12'C'#255#10#15'F'#255#8#19'K'#255#11#19'Q'#255
+ +#13#18'Q'#255#10#17'P'#255#10#17'Q'#255#10#17'P'#255#12#18'Q'#255#13#18'Q'
+ +#255#12#17'P'#255#12#17'P'#255#12#17'N'#255#11#16'M'#255#11#16'O'#255#10#15
+ +'N'#255#11#16'O'#255#11#16'O'#255#10#16'O'#255#11#17'P'#255#10#16'O'#255#10
+ +#16'O'#255#10#17'P'#255#10#17'P'#255#9#16'O'#255#8#15'N'#255#10#15'M'#255#11
+ +#16'L'#255#10#15'L'#255#10#15'L'#253#10#17'M'#251#12#14'G'#250#24#20'?'#239
+ +#30#16'3'#189''''#21'+L-'#23''''#7#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#194#191#177#1#218#214#209#12#132#139#134
+ +#17'aabNBG[P6Hs'#248#29'2n'#252#13#31'j'#255#7#29'w'#255#5#28'y'#255#9#23'~'
+ +#255#8#28'~'#255#10#26'~'#255#9#25'~'#255#9#25'~'#255#8#24'}'#255#9#25'}'#255
+ +#10#25#127#255#9#24'~'#255#9#24'~'#255#8#25'{'#255#8#24'{'#255#9#26'{'#255#12
+ +#28'u'#255#12#27'j'#255#8#20'Z'#255#6#17'N'#255#9#17'M'#255#10#17'H'#255#10
+ +#17'H'#255#11#18'I'#255#10#17'H'#255#10#18'I'#255#10#17'H'#255#10#17'J'#255
+ +#12#18'J'#255#6#15'P'#255#8#17'P'#255#0#15'Y'#255#8'5'#147#255#13'Y'#198#255
+ +#6'c'#216#255#4'b'#214#255#11'e'#218#255#8'i'#221#255#8'h'#221#255#6'e'#220
+ +#255#9'h'#224#255#7'e'#221#255#7'e'#219#255#6'e'#217#255#8'g'#219#255#14'j'
+ +#216#255#12'h'#213#255#10'h'#213#255#14'i'#215#255#26'l'#220#255#31'c'#212
+ +#255#6'>'#169#255#5'6'#156#255#18'V'#206#255#11'd'#222#255#6'h'#231#255#9'f'
+ +#226#255#13'g'#223#255#3'f'#220#255#3'f'#220#255#12'b'#221#255#10'd'#222#255
+ +#4'a'#224#255#9'c'#226#255#10'^'#212#255#0'Q'#200#255#9'_'#217#255#3'c'#219
+ +#255#2'e'#214#255#6'h'#211#255#10'k'#211#255#18'u'#208#255#30'p'#184#255#3':'
+ +'e'#255#0#22','#255#2#12#26#255#5#9#23#255#6#13#23#255#9#13#26#255#7#12#30
+ +#255#8#9#30#255#10#6#30#255#4#9'1'#255#9')j'#255#5'M'#157#255#12'i'#211#255#1
+ +'m'#215#255#1'e'#213#255#10'c'#210#255#9'f'#215#255#3'c'#214#255#4'd'#216#255
+ +#2'c'#217#255#4'b'#219#255#8'f'#222#255#8'c'#221#255#5'`'#218#255#7'b'#220
+ +#255#5'a'#220#255#5'b'#221#255#6'd'#223#255#5'c'#225#255#4'b'#223#255#5'c'
+ +#225#255#4'c'#225#255#7'g'#225#255#7'e'#218#255#12'e'#211#255#22'l'#212#255
+ +'"a'#188#255#0'"q'#255#9#20'['#255#5#16'['#255#4#20'h'#255#8#24'q'#255#7#25
+ +'t'#255#5#26'x'#255#8#25'z'#255#8#25'z'#255#8#24'{'#255#6#23'{'#255#7#25'|'
+ +#255#6#24'{'#255#7#26'}'#255#6#25'}'#255#6#25'}'#255#6#24'}'#255#5#24'|'#255
+ +#7#24'~'#255#8#23'~'#255#8#23'}'#255#8#23'}'#255#7#22'}'#255#6#22'}'#255#6#23
+ +'~'#255#5#22'}'#255#7#22'}'#255#9#24'~'#255#9#24'~'#255#6#22'{'#255#8#23'z'
+ +#255#10#23'y'#255#2#24'w'#255#2#27'v'#255#9#20'l'#255#6#21'i'#255#1'9'#148
+ +#255#30'h'#196#255#31'W'#170#255#7'''d'#255#1#18'K'#255#10#15'H'#255#8#16'H'
+ +#255#7#18'L'#255#10#18'O'#255#12#16'O'#255#11#15'O'#255#10#17'O'#255#10#17'P'
+ +#255#12#18'Q'#255#13#18'Q'#255#11#16'O'#255#11#16'O'#255#12#17'N'#255#12#17
+ +'N'#255#10#15'L'#255#10#15'M'#255#10#15'M'#255#9#15'N'#255#9#16'O'#255#8#15
+ +'N'#255#8#15'N'#255#9#16'O'#255#8#15'N'#255#8#15'N'#255#9#16'O'#255#8#15'N'
+ +#255#9#15'M'#255#11#16'N'#255#9#14'L'#254#11#16'M'#252#11#16'K'#251#17#19'C'
+ +#246#25#17':'#220'#'#21'/'#132'*'#22')'#29'4'#27'$'#0'7'#31')'#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#209#206#197#24#215
+ +#211#205'0'#131#140#135'/a`b8?EXX,?k'#245'&;y'#252#6#26'g'#255#12#31'v'#255#8
+ +#30'|'#255#6#25'}'#255#6#27'}'#255#8#24'{'#255#9#24'~'#255#10#26'}'#255#9#25
+ +'}'#255#9#25'}'#255#8#24'|'#255#9#25'}'#255#10#26'~'#255#10#26'}'#255#9#26'|'
+ +#255#8#25'z'#255#10#27'v'#255#12#30'q'#255#12#27'd'#255#6#20'T'#255#9#19'N'
+ +#255#9#17'J'#255#10#17'H'#255#11#18'H'#255#13#19'I'#255#9#15'G'#255#9#17'G'
+ +#255#12#17'G'#255#13#18'I'#255#11#18'H'#255#4#15'Q'#255#9#15'S'#255#7#23'c'
+ +#255#13'A'#169#255#7'b'#218#255#6'e'#217#255#8'd'#221#255#6'g'#216#255#5'g'
+ +#216#255#5'e'#218#255#8'i'#222#255#7'h'#219#255#9'i'#220#255#8'h'#217#255#7
+ +'g'#216#255#7'e'#214#255#9'e'#212#255#10'g'#216#255#28'm'#223#255#25'P'#190
+ +#255#16'*'#145#255#4#22'v'#255#9#20'r'#255#1#28#133#255#6'M'#184#255#7'a'#221
+ ,#255#4'a'#216#255#9'`'#222#255#1'd'#218#255#5'g'#219#255#8'c'#225#255#9'a'
+ +#216#255#8'c'#221#255#4'd'#219#255#12'f'#221#255#4'W'#206#255#6'Y'#212#255#7
+ +'b'#219#255#8'f'#220#255#3'e'#220#255#4'h'#219#255#6'i'#214#255#10'l'#209#255
+ +#14't'#201#255#20'['#158#255#9'%Z'#255#8#29'G'#255#7#21'3'#255#4#4'&'#255#4#3
+ +'+'#255#5#29'T'#255#4'?'#139#255#6'X'#183#255#10'h'#210#255#2'e'#217#255#6'd'
+ +#219#255#8'h'#221#255#9'b'#218#255#7'b'#222#255#2'e'#221#255#4'd'#218#255#8
+ +'e'#217#255#3'c'#222#255#4'c'#218#255#6'd'#219#255#7'c'#220#255#8'e'#221#255
+ +#6'b'#219#255#6'd'#222#255#7'e'#223#255#9'g'#227#255#3'e'#224#255#6'g'#227
+ +#255#6'f'#225#255#5'e'#220#255#6'f'#217#255#9'f'#212#255#17'h'#209#255'!q'
+ +#211#255#25'B'#148#255#2#26'f'#255#3#17'Z'#255#7#18'd'#255#10#25'r'#255#10#26
+ +'x'#255#9#25'w'#255#6#28'x'#255#6#24'y'#255#7#25'z'#255#7#24'|'#255#8#26'}'
+ +#255#8#26'}'#255#8#25'}'#255#7#23'|'#255#6#24'}'#255#7#23'|'#255#9#23'}'#255
+ +#8#23'~'#255#9#23#127#255#8#22#128#255#8#22#128#255#7#22'}'#255#8#24'~'#255#5
+ +#23'}'#255#5#23'}'#255#7#23'~'#255#8#24#127#255#7#22'|'#255#7#23'|'#255#6#22
+ +'y'#255#8#24'y'#255#5#21't'#255#4#28'x'#255#6#23'p'#255#6#20'k'#255#4'%'#127
+ +#255#4'N'#171#255#21'e'#194#255#26'_'#181#255#18'<'#130#255#3#22'T'#255#5#16
+ +'J'#255#9#18'M'#255#10#18'M'#255#9#17'L'#255#14#17'P'#255#14#17'O'#255#11#17
+ +'O'#255#11#17'O'#255#12#17'P'#255#12#17'P'#255#10#15'N'#255#12#17'P'#255#12
+ +#17'O'#255#12#17'N'#255#10#15'M'#255#11#17'O'#255#9#15'M'#255#8#15'N'#255#9
+ +#16'O'#255#9#16'O'#255#9#16'O'#255#9#16'O'#255#8#16'O'#255#8#14'N'#255#8#14
+ +'N'#255#10#16'P'#255#10#16'Q'#255#9#16'P'#255#11#15'O'#254#12#16'M'#252#16#17
+ +'G'#249#18#15'='#237#30#20'5'#174'%'#21',@-'#23'('#6#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#136#147#142'A_]a'#16''#239#27#18'2'#176'$'#22','
+ +'1*'#19'.'#1''''#23')'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#152#178#148#1#145#165#149#15#0#0#0#0
+ +#145#174#194#2#25'8b'#205#11'%\'#253#11#29'\'#255#3#20'^'#255#7#30'x'#255#5
+ +#29#128#255#8#28#127#255#6#24#127#255#7#25#127#255#8#26#128#255#7#26#128#255
+ +#6#24#127#255#7#24#128#255#6#24#127#255#7#25#128#255#6#25#128#255#8#25#127
+ +#255#7#23'}'#255#9#25#130#255#8#26#127#255#7#26'|'#255#8#28'u'#255#8#27'n'
+ +#255#8#23'a'#255#8#20'W'#255#7#18'M'#255#12#18'I'#255#11#18'G'#255#11#20'I'
+ +#255#13#20'I'#255#14#20'I'#255#9#19'I'#255#10#20'H'#255#7#20'L'#255#7#18'P'
+ +#255#5#16'S'#255#3#23'a'#255#13'='#156#255#5'\'#208#255#2'`'#213#255#7'd'#221
+ +#255#6'f'#227#255#5'h'#229#255#7'i'#227#255#8'j'#224#255#11'l'#220#255#11'j'
+ +#214#255#23'm'#217#255'"g'#205#255#15'4'#145#255#7#20'p'#255#7#28'x'#255#4#27
+ +'}'#255#7#25'{'#255#5#27'{'#255#3#30'{'#255#1#26'z'#255#9'E'#185#255#10'M'
+ +#191#255#9'g'#227#255#12'b'#222#255#9'f'#226#255#3'i'#228#255#8'f'#223#255#6
+ +'c'#224#255#8'c'#227#255#7'c'#229#255#5'c'#226#255#9'h'#228#255#4'c'#221#255
+ +#8'g'#226#255#4'h'#227#255#3'h'#227#255#0'g'#226#255#3'e'#223#255#7'd'#223
+ +#255#7'c'#221#255#5'd'#221#255#0'e'#219#255#0'd'#224#255#5'e'#223#255#9'g'
+ +#226#255#11'e'#224#255#10'f'#223#255#2'c'#222#255#4'f'#222#255#1'e'#218#255#6
+ +'e'#220#255#6'e'#221#255#8'f'#225#255#8'h'#228#255#7'g'#229#255#6'f'#227#255
+ +#4'd'#224#255#6'f'#225#255#5'f'#222#255#9'j'#225#255#9'j'#224#255#9'j'#224
+ +#255#8'i'#223#255#5'e'#223#255#5'g'#226#255#6'i'#229#255#6'i'#226#255#4'e'
+ +#229#255#4'h'#227#255#7'f'#217#255#10'h'#209#255' o'#210#255#28'M'#166#255#7
+ +#23'a'#255#11#19'['#255#4#17'_'#255#6#23'o'#255#8#26'{'#255#7#24'{'#255#9#26
+ +'{'#255#9#26'{'#255#7#24'~'#255#6#24'}'#255#8#26#127#255#6#24'}'#255#7#25'~'
+ +#255#8#24'}'#255#7#22'}'#255#8#23'~'#255#7#22'~'#255#9#23#129#255#9#23#129
+ +#255#7#23#127#255#6#23#127#255#5#22'~'#255#6#24'~'#255#8#25#127#255#6#24'}'
+ +#255#7#25'~'#255#7#24'~'#255#7#24#127#255#6#24#127#255#8#23'}'#255#6#22'z'
+ +#255#8#24'z'#255#6#24'x'#255#7#27'w'#255#1#24'm'#255#6#31'~'#255#2'<'#170#255
+ +#6'G'#178#255#6'F'#179#255#12'V'#202#255#19'\'#201#255#24'S'#184#255#14'-'
+ +#130#255#5#24'^'#255#5#19'W'#255#13#19'R'#255#8#18'P'#255#10#17'S'#255#9#16
+ +'P'#255#9#16'O'#255#11#18'Q'#255#8#14'O'#255#10#16'Q'#255#8#14'O'#255#9#15'P'
+ +#255#8#14'O'#255#9#16'O'#255#8#15'N'#255#10#17'P'#255#9#16'O'#255#10#17'P'
+ ,#255#10#17'P'#255#10#17'P'#255#9#16'O'#255#9#16'O'#255#10#15'M'#255#10#15'L'
+ +#255#11#16'L'#255#10#15'N'#255#7#15'M'#255#11#16'M'#255#16#17'G'#251#18#18'B'
+ +#247#26#19'8'#227'"'#21'-u+'#25'+'#18#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#149#174#150#31#142#165#149#3#0#0#0#0'$En'#145#8'#Y'#253#10#27'Y'#254#1#14'X'
+ +#255#10#24'p'#255#9#25'|'#255#10#25#129#255#5#25#129#255#7#26#130#255#7#26
+ +#130#255#7#26#129#255#7#26#129#255#7#26#129#255#6#25#128#255#6#25#128#255#4
+ +#23#127#255#7#25#128#255#6#24#128#255#7#25#130#255#9#26#130#255#7#26#127#255
+ +#7#27'{'#255#7#27'x'#255#11#29'o'#255#9#24'b'#255#5#18'R'#255#7#19'L'#255#10
+ +#18'I'#255#10#20'J'#255#9#17'I'#255#10#20'K'#255#10#21'G'#255#5#18'F'#255#15
+ +#18'I'#255#10#17'N'#255#2#15'Q'#255#5#15'W'#255#5#30'v'#255#8'T'#192#255#10
+ +'c'#216#255#8'g'#217#255#1'h'#217#255#3'l'#225#255#7'l'#223#255#8'o'#216#255
+ +#11'n'#213#255#19'm'#216#255#30'i'#213#255#11'>'#161#255#5#23's'#255#9#23'v'
+ +#255#1#28'~'#255#4#26'~'#255#9#24'z'#255#4#28'{'#255#4#31'u'#255#11' |'#255#9
+ +'#'#137#255#0#29'|'#255#6'Z'#204#255#10'c'#212#255#2'j'#218#255#7'e'#219#255
+ +#6'g'#218#255#6'g'#221#255#4'b'#224#255#4'b'#226#255#3'd'#226#255#8'j'#228
+ +#255#6'h'#225#255#4'f'#223#255#7'h'#222#255#8'h'#223#255#7'g'#222#255#5'e'
+ +#223#255#7'g'#224#255#5'f'#225#255#6'c'#221#255#8'b'#221#255#7'c'#220#255#8
+ +'e'#222#255#5'f'#224#255#5'j'#230#255#6'g'#227#255#10'c'#224#255#9'd'#224#255
+ +#8'e'#224#255#6'g'#223#255#6'e'#223#255#6'e'#224#255#6'e'#226#255#2'd'#225
+ +#255#3'e'#226#255#4'g'#225#255#7'k'#227#255#8'h'#224#255#6'g'#221#255#4'g'
+ +#220#255#5'h'#222#255#5'h'#224#255#2'f'#226#255#2'f'#229#255#4'h'#232#255#6
+ +'g'#227#255#5'j'#228#255#6'g'#221#255#11'g'#214#255#22'n'#212#255'!a'#190#255
+ +#8'(u'#255#9#20'Y'#255#2#17'\'#255#5#21'g'#255#8#25'w'#255#8#25'}'#255#7#24
+ +'{'#255#9#26'z'#255#8#26'{'#255#6#26#127#255#6#24'}'#255#7#25'~'#255#6#24'}'
+ +#255#5#24'}'#255#7#25'~'#255#6#23'~'#255#8#24'~'#255#8#23#128#255#8#22#128
+ +#255#7#22#128#255#4#21'~'#255#5#22#127#255#5#23'}'#255#7#24'~'#255#6#25#127
+ +#255#4#23'}'#255#6#24'~'#255#6#24'}'#255#6#22'~'#255#7#22#127#255#7#23'}'#255
+ +#7#22'{'#255#5#23'y'#255#6#25'x'#255#7#28'v'#255#2#25's'#255#14'4'#153#255#3
+ +'@'#177#255#9'D'#179#255#6'E'#181#255#2'J'#186#255#19'W'#194#255#23'P'#181
+ +#255#17'3'#140#255#2#23']'#255#7#19'V'#255#11#21'R'#255#8#16'O'#255#11#18'R'
+ +#255#7#16'P'#255#8#16'P'#255#11#18'Q'#255#9#15'P'#255#12#18'S'#255#7#15'O'
+ +#255#10#17'Q'#255#9#16'P'#255#10#18'Q'#255#8#16'N'#255#10#18'O'#255#9#17'N'
+ +#255#10#18'O'#255#9#17'O'#255#9#17'N'#255#9#16'O'#255#9#16'O'#255#8#15'L'#255
+ +#10#15'L'#255#10#15'L'#255#9#15'N'#255#8#15'N'#255#12#16'L'#254#17#17'E'#249
+ +#23#16'='#239#30#19'3'#187'%'#22'+D-'#27'('#7#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#152#177#149#0#149#174#155#17#141#165#148#17#0#0#0#0'Je'#140#28#13'''\'#245
+ +#15'#`'#255#3#19'X'#255#7#20'e'#255#9#24'w'#255#8#27#127#255#7#26#127#255#7
+ +#25#127#255#8#26#128#255#7#26#128#255#7#25#128#255#6#24#127#255#8#26#130#255
+ +#7#25#128#255#7#24#128#255#8#26#129#255#6#25#130#255#9#25#131#255#8#24#127
+ +#255#7#24'}'#255#7#25'|'#255#7#25'z'#255#9#27'v'#255#10#27'o'#255#9#25'e'#255
+ +#6#19'X'#255#6#17'O'#255#8#16'L'#255#9#17'K'#255#10#20'K'#255#11#18'G'#255#5
+ +#20'E'#255#11#18'E'#255#10#16'K'#255#4#19'N'#255#8#16'R'#255#1#17'b'#255#3'9'
+ +#147#255#10'a'#214#255#3'f'#209#255#3'g'#208#255#10'i'#212#255#14'n'#220#255
+ +#12'q'#216#255#20's'#221#255#30'o'#224#255#27'S'#179#255#0'!'#128#255#8#20'r'
+ +#255#10#28'y'#255#3#28'|'#255#5#24'}'#255#9#24'}'#255#6#27'{'#255#6#28'{'#255
+ +#7#28'|'#255#2#22't'#255#2#19'k'#255#1'E'#179#255#9'`'#215#255#4'd'#220#255
+ +#10'c'#215#255#7'i'#223#255#7'g'#224#255#4'b'#224#255#10'h'#232#255#6'f'#225
+ +#255#8'i'#226#255#6'i'#223#255#5'h'#223#255#5'j'#224#255#4'g'#224#255#5'e'
+ +#223#255#10'h'#225#255#9'g'#224#255#6'd'#221#255#8'f'#225#255#11'h'#228#255#5
+ +'c'#224#255#6'd'#225#255#6'e'#225#255#10'h'#229#255#8'g'#227#255#4'd'#224#255
+ +#5'f'#226#255#4'e'#225#255#7'k'#227#255#4'h'#224#255#7'f'#225#255#7'g'#226
+ +#255#7'g'#226#255#8'i'#228#255#5'i'#224#255#4'k'#225#255#6'i'#224#255#6'j'
+ +#223#255#9'k'#225#255#4'e'#220#255#8'g'#226#255#8'e'#230#255#6'c'#228#255#10
+ +'f'#231#255#6'i'#232#255#5'k'#230#255#9'g'#218#255#18'i'#213#255'%p'#217#255
+ +#18'A'#155#255#12#30'j'#255#8#16'^'#255#2#18'f'#255#9#24'w'#255#9#24#127#255
+ +#8#25#127#255#4#23'{'#255#8#24'{'#255#8#25'{'#255#7#24'~'#255#8#25#127#255#10
+ ,#26#128#255#8#25#127#255#7#25#127#255#7#26#127#255#5#23'}'#255#5#22#128#255#7
+ +#22#128#255#9#23#129#255#10#24#130#255#8#22#128#255#8#23#129#255#7#22'~'#255
+ +#7#24#127#255#6#23'~'#255#4#22'}'#255#6#24'~'#255#5#23'}'#255#6#23#128#255#9
+ +#23#129#255#6#21'|'#255#8#24'~'#255#4#23'x'#255#6#26'y'#255#5#26's'#255#2#28
+ +'{'#255#13':'#166#255#3'A'#175#255#12'F'#181#255#7'E'#181#255#0'C'#176#255#13
+ +'N'#185#255#20'L'#179#255#25'?'#152#255#0#21'^'#255#14#23'Y'#255#10#19'U'#255
+ +#6#15'O'#255#13#17'P'#255#10#15'O'#255#9#15'P'#255#10#16'Q'#255#9#14'O'#255
+ +#12#16'Q'#255#10#14'O'#255#11#16'Q'#255#10#15'O'#255#10#17'P'#255#9#17'N'#255
+ +#9#17'M'#255#9#17'M'#255#9#17'M'#255#10#18'O'#255#10#18'O'#255#10#16'P'#255
+ +#12#17'P'#255#10#17'O'#255#11#16'N'#255#12#17'O'#255#10#15'P'#255#9#15'P'#255
+ +#10#15'K'#252#19#17'B'#246#27#19'9'#220'"'#20'0'#128'*'#24'*'#31'0'#26'#'#1
+ +'-'#26'*'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#142#166#148#0#0#0#0#0'hk'#127#4']'
+ +'g'#140#19'&>s'#223#10'"_'#255#12#30'd'#255#3#17'd'#255#8#23'r'#255#8#28'z'
+ +#255#7#25'~'#255#7#25'~'#255#8#26#127#255#8#26#127#255#7#25'~'#255#8#26#127
+ +#255#9#28#128#255#8#26#127#255#8#25#128#255#8#25#128#255#8#24#130#255#11#24
+ +#131#255#7#22'~'#255#7#22'|'#255#7#22'|'#255#7#23'|'#255#8#23'~'#255#9#25'{'
+ +#255#10#28'u'#255#12#26'l'#255#6#19'_'#255#8#19'Y'#255#7#17'O'#255#10#19'L'
+ +#255#14#18'M'#255#10#22'H'#255#11#20'E'#255#11#17'J'#255#7#18'L'#255#10#17'M'
+ +#255#8#16'V'#255#7#28'l'#255#4'M'#187#255#13'c'#208#255#16'h'#216#255#17'g'
+ +#218#255#25'i'#222#255'%m'#221#255'(a'#203#255#28'E'#171#255#10'%'#131#255#5
+ +#23'v'#255#10#23'v'#255#10#28'|'#255#6#28#127#255#7#26#127#255#8#23'}'#255#10
+ +#25'~'#255#11#24#127#255#2#29'}'#255#5#24's'#255#8#21'r'#255#1':'#161#255#12
+ +'a'#218#255#6'a'#224#255#6'a'#217#255#6'c'#224#255#9'd'#227#255#4'^'#226#255
+ +#10'e'#232#255#4'`'#224#255#5'b'#224#255#5'd'#225#255#6'f'#227#255#6'g'#229
+ +#255#5'g'#228#255#6'f'#227#255#4'c'#226#255#5'b'#226#255#6'c'#228#255#6'c'
+ +#227#255#5'd'#228#255#3'a'#227#255#5'c'#229#255#6'f'#230#255#6'g'#231#255#7
+ +'h'#230#255#4'f'#228#255#5'f'#229#255#4'e'#228#255#5'g'#229#255#5'e'#230#255
+ +#6'c'#231#255#5'b'#230#255#2'`'#227#255#7'f'#230#255#5'e'#228#255#6'h'#230
+ +#255#6'i'#225#255#6'h'#224#255#7'j'#225#255#4'f'#222#255#5'g'#228#255#5'f'
+ +#230#255#3'e'#228#255#5'g'#231#255#0'h'#227#255#7'j'#222#255#15'i'#213#255#28
+ +'m'#210#255'#['#186#255#6'(y'#255#7#19'c'#255#5#17'b'#255#3#19'r'#255#9#24'}'
+ +#255#6#23'~'#255#9#25#131#255#9#23#127#255#11#26#129#255#9#24'~'#255#7#23#127
+ +#255#8#23#127#255#9#24#127#255#6#23'~'#255#6#23'~'#255#7#24#127#255#5#21#127
+ +#255#8#21#128#255#9#22#130#255#8#21#128#255#8#22#128#255#7#21#127#255#9#23
+ +#129#255#7#21#128#255#9#23#128#255#9#24'~'#255#9#24#127#255#8#24#127#255#7#24
+ +#127#255#5#21#127#255#6#22#128#255#6#22#128#255#7#25'~'#255#4#23'y'#255#6#26
+ +'y'#255#5#25'u'#255#5'$'#134#255#14'A'#174#255#7'A'#179#255#7'C'#178#255#6'D'
+ +#180#255#3'@'#174#255#21'O'#189#255#17'I'#178#255#26'@'#157#255#5#26'e'#255#9
+ +#21'X'#255#10#18'T'#255#7#16'P'#255#12#16'M'#255#11#15'N'#255#12#16'Q'#255#13
+ +#17'R'#255#11#15'P'#255#16#17'S'#255#15#15'Q'#255#15#17'R'#255#13#16'Q'#255
+ +#14#19'R'#255#10#17'P'#255#9#16'O'#255#9#16'O'#255#9#16'O'#255#11#16'O'#255
+ +#12#16'P'#255#11#16'P'#255#12#17'P'#255#10#15'P'#255#9#15'Q'#255#12#17'P'#255
+ +#10#16'O'#255#9#15'N'#253#16#19'G'#249#24#19':'#237' '#21'3'#176''''#22'*E/'
+ +#27''''#10#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'i'
+ +'ep'#11'ai'#135'W9L|'#255#13'%e'#254#14'"i'#255#8#21'h'#255#4#18'o'#255#7#26
+ +'v'#255#6#25'}'#255#8#26'~'#255#8#26'~'#255#8#26#127#255#7#25'~'#255#8#26#127
+ +#255#8#26#127#255#7#25'~'#255#6#25'~'#255#8#25#127#255#7#23#129#255#8#23#129
+ +#255#8#23#129#255#9#24#127#255#8#23'}'#255#8#23'}'#255#8#23'x'#255#7#24'w'
+ +#255#9#27'w'#255#8#27't'#255#11#27's'#255#13#28'm'#255#9#23'`'#255#6#19'W'
+ +#255#7#14'O'#255#9#17'J'#255#11#18'G'#255#15#18'K'#255#14#17'O'#255#10#19'O'
+ +#255#7#17'R'#255#3#13'T'#255#7'2'#142#255'*c'#208#255'$a'#221#255'*b'#217#255
+ +'''M'#184#255#17','#141#255#7#24's'#255#6#17'i'#255#7#21'r'#255#7#23'w'#255#5
+ +#23'x'#255#8#23'}'#255#8#24'~'#255#8#23'}'#255#6#22'|'#255#8#24'~'#255#9#21
+ +'{'#255#1#28'~'#255#4#26'z'#255#9#21'x'#255#0#27'q'#255#27'W'#192#255#9'e'
+ +#218#255#5'_'#217#255#3'`'#221#255#8'e'#228#255#7'b'#229#255#9'f'#232#255#6
+ +'c'#228#255#8'e'#230#255#8'e'#230#255#10'h'#233#255#11'k'#235#255#8'f'#231
+ ,#255#7'e'#230#255#7'e'#230#255#8'f'#232#255#9'g'#233#255#6'c'#231#255#6'e'
+ +#233#255#6'e'#227#255#8'g'#229#255#7'f'#228#255#4'd'#226#255#10'j'#232#255#5
+ +'e'#227#255#4'f'#228#255#6'f'#229#255#5'f'#231#255#6'e'#233#255#7'e'#232#255
+ +#6'c'#232#255#5'b'#232#255#8'e'#233#255#6'c'#229#255#7'd'#230#255#7'f'#229
+ +#255#8'i'#231#255#7'j'#229#255#4'g'#228#255#5'g'#229#255#5'k'#232#255#3'k'
+ +#229#255#5'l'#229#255#5'l'#222#255#18'n'#212#255#27'n'#209#255'''j'#201#255
+ +#19';'#141#255#4#20'`'#255#1#15'a'#255#5#17'k'#255#8#24'y'#255#9#24'}'#255#6
+ +#24'}'#255#9#27#127#255#7#22'}'#255#10#24#129#255#9#23#127#255#7#25'~'#255#8
+ +#24#127#255#7#23'~'#255#7#24#127#255#6#23'~'#255#6#24#127#255#5#22'~'#255#6
+ +#22#129#255#7#22#129#255#7#21#129#255#7#22#129#255#7#21#129#255#9#24#130#255
+ +#8#23#129#255#8#22#128#255#9#23#128#255#9#24#127#255#9#24'~'#255#9#23#129#255
+ +#5#21#127#255#8#24#131#255#4#20#127#255#8#26#128#255#8#27#127#255#7#24'y'#255
+ +#0#20't'#255#10'3'#151#255#8'?'#174#255#8'A'#178#255#9'G'#178#255#5'F'#178
+ +#255#7'@'#172#255#14'H'#178#255#14'H'#172#255#29'C'#156#255#1#23'^'#255#13#23
+ +'Y'#255#9#19'S'#255#9#19'P'#255#13#17'N'#255#11#18'P'#255#11#17'P'#255#13#18
+ +'Q'#255#12#17'P'#255#15#19'R'#255#14#16'O'#255#13#17'O'#255#11#16'N'#255#12
+ +#18'P'#255#10#17'P'#255#9#15'P'#255#10#15'P'#255#11#16'Q'#255#10#14'O'#255#11
+ +#15'P'#255#11#15'P'#255#12#15'Q'#255#11#17'S'#255#11#15'P'#255#12#16'P'#255
+ +#13#16'M'#253#12#16'J'#252#19#18'@'#245#29#20'3'#215'$'#21',f*'#24'*'#27'2'
+ +#28'&'#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'fZ_'
+ +#7'gfxgPZ'#130#255#20')d'#254#13'"k'#254#10#28'm'#255#1#17'k'#255#7#24't'#255
+ +#7#24'}'#255#8#26#127#255#6#26#128#255#8#26#129#255#9#26#128#255#9#26#127#255
+ +#8#26#128#255#7#26#129#255#5#23#127#255#8#24#128#255#6#22#128#255#8#24#130
+ +#255#8#24#130#255#8#25#128#255#9#25'~'#255#8#25#127#255#8#23'q'#255#7#21'n'
+ +#255#5#21'm'#255#5#19'l'#255#10#24'p'#255#14#28's'#255#12#29'o'#255#10#28'j'
+ +#255#10#21'T'#255#10#19'N'#255#7#14'F'#255#12#16'I'#255#11#15'L'#255#9#18'O'
+ +#255#4#18'R'#255#4#16'U'#255#4#25'f'#255')C'#164#255#29'9'#160#255#11'"'#130
+ +#255#3#18'n'#255#10#23'l'#255#7#22'k'#255#3#22'r'#255#7#24'u'#255#4#23'x'#255
+ +#7#27#127#255#4#22'|'#255#8#24#127#255#9#23#127#255#5#21'~'#255#8#25#129#255
+ +#11#22'z'#255#3#25'|'#255#6#23'}'#255#12#23'z'#255#3#17'['#255#0'"w'#255#10
+ +'Y'#198#255#12'h'#225#255#5'd'#222#255#6'h'#227#255#6'e'#227#255#9'c'#232#255
+ +#5'b'#230#255#6'e'#230#255#5'b'#227#255#8'c'#229#255#7'd'#229#255#5'b'#228
+ +#255#6'e'#230#255#6'e'#228#255#4'e'#228#255#6'f'#230#255#7'f'#232#255#8'h'
+ +#235#255#5'e'#227#255#7'h'#229#255#7'g'#230#255#6'f'#229#255#8'g'#230#255#3
+ +'c'#225#255#7'f'#228#255#7'f'#228#255#6'e'#227#255#7'f'#228#255#6'c'#228#255
+ +#9'e'#232#255#5'b'#227#255#7'd'#229#255#5'c'#225#255#7'e'#225#255#5'd'#228
+ +#255#4'f'#228#255#3'e'#226#255#6'f'#229#255#3'b'#224#255#6'j'#229#255#3'i'
+ +#221#255#10'k'#220#255#16'l'#215#255#29'p'#209#255'!h'#194#255#22'B'#150#255
+ +#8#23'a'#255#9#16'Y'#255#5#18'f'#255#5#21't'#255#8#25'{'#255#6#25'|'#255#6#24
+ +'{'#255#6#24'|'#255#7#23#127#255#9#24#129#255#8#24#127#255#8#25#127#255#5#23
+ +#127#255#4#22'~'#255#5#23#127#255#4#24'~'#255#6#24#127#255#5#23#127#255#6#22
+ +#127#255#6#22#128#255#6#21#127#255#8#24#129#255#6#22#127#255#8#24#128#255#8
+ +#22'~'#255#7#21'}'#255#7#22'~'#255#9#24#127#255#8#23#127#255#7#22#128#255#7
+ +#22#131#255#9#25#132#255#6#22#128#255#8#26#127#255#6#25'|'#255#6#24'y'#255#2
+ +#29#130#255#12'9'#164#255#9'A'#176#255#9'C'#179#255#6'E'#177#255#8'E'#178#255
+ +#7'?'#168#255#12'F'#171#255#11'A'#162#255#21';'#146#255#4#25'^'#255#10#22'W'
+ +#255#8#19'R'#255#7#16'N'#255#11#18'N'#255#10#17'Q'#255#10#17'O'#255#12#19'P'
+ +#255#11#16'N'#255#12#17'O'#255#11#16'N'#255#11#16'N'#255#11#16'M'#255#11#17
+ +'N'#255#11#16'P'#255#12#15'P'#255#12#16'R'#255#11#15'Q'#255#11#15'P'#255#11
+ +#15'Q'#255#12#16'Q'#255#12#16'R'#255#11#16'R'#255#8#16'O'#255#10#15'O'#254#12
+ +#15'L'#252#17#17'F'#248#24#20':'#234'"'#21'-'#150'('#25'+'#29'0'#29','#4'/'
+ +#25' '#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'k^^'#0'q_Y'
+ +#2'd[cTZ[u'#253'3>q'#253#10#27'^'#254#20'%r'#255#7#21'k'#255#6#19'n'#255#7#23
+ +'{'#255#8#26#128#255#6#24#128#255#10#25#132#255#10#25#130#255#11#26#129#255#7
+ +#23#128#255#6#25#130#255#5#25#130#255#7#26#131#255#8#24#130#255#9#24#130#255
+ +#7#23#129#255#7#24#128#255#8#25#128#255#8#26#127#255#7#23#127#255#7#24'z'#255
+ ,#5#24't'#255#7#21'l'#255#6#18'f'#255#7#18'e'#255#7#19'c'#255#13#25'f'#255#14
+ +#26'j'#255#15#25'e'#255#14#21'['#255#13#19'W'#255#9#16'R'#255#9#15'U'#255#9
+ +#15'Z'#255#6#12']'#255#2#14'b'#255#4#12'l'#255#3#14'l'#255#9#21's'#255#8#25
+ +'z'#255#8#24'y'#255#3#21'o'#255#8#23'y'#255#6#24'|'#255#5#22'|'#255#6#23'}'
+ +#255#5#22'~'#255#6#22#129#255#8#24#131#255#7#23#130#255#7#23#130#255#8#22'|'
+ +#255#7#24'|'#255#9#24'z'#255#9#27'u'#255#8#24'f'#255#3#11'Y'#255#3'"'#128#255
+ +#4'a'#207#255#8'c'#229#255#6'a'#223#255#10'e'#232#255#8'f'#235#255#6'h'#230
+ +#255#5'g'#228#255#5'd'#230#255#7'd'#226#255#7'b'#229#255#6'b'#229#255#6'b'
+ +#226#255#5'd'#226#255#8'g'#229#255#6'g'#228#255#4'd'#226#255#7'h'#229#255#4
+ +'e'#227#255#5'f'#229#255#3'd'#228#255#7'g'#233#255#7'e'#231#255#4'b'#228#255
+ +#7'e'#230#255#7'e'#230#255#4'd'#227#255#4'd'#228#255#5'c'#231#255#8'e'#236
+ +#255#7'e'#234#255#6'e'#233#255#6'e'#231#255#5'd'#230#255#6'd'#232#255#4'g'
+ +#233#255#3'f'#232#255#10'g'#235#255#6'g'#233#255#3'e'#226#255#6'l'#219#255#22
+ +'o'#221#255'#s'#212#255'%b'#184#255#5'''v'#255#4#16'U'#255#5#14'V'#255#3#17
+ +'_'#255#6#21'n'#255#11#26'y'#255#8#27'}'#255#8#25#127#255#8#24#129#255#8#23
+ +#130#255#7#22#131#255#7#22#131#255#7#23#130#255#8#24#131#255#8#25#131#255#7
+ +#23#129#255#7#23#128#255#7#24#127#255#5#23'}'#255#6#23#127#255#6#22#128#255#6
+ +#22#128#255#7#22'}'#255#10#25#128#255#8#23'}'#255#8#23'}'#255#8#23'}'#255#7
+ +#22'|'#255#7#22'|'#255#8#23'~'#255#8#23#129#255#8#22#129#255#9#23#130#255#8
+ +#23#130#255#8#24#129#255#6#24'~'#255#6#25'{'#255#4#23'w'#255#4'#'#143#255#18
+ +'?'#174#255#13'C'#179#255#5'B'#181#255#7'F'#183#255#4'@'#174#255#6'@'#169#255
+ +#12'F'#168#255#13'?'#159#255#22'9'#143#255#3#25']'#255#9#21'X'#255#7#19'T'
+ +#255#7#17'P'#255#12#17'N'#255#11#17'P'#255#11#17'P'#255#14#19'R'#255#12#17'P'
+ +#255#13#18'Q'#255#10#15'N'#255#11#16'O'#255#12#17'N'#255#13#18'P'#255#13#18
+ +'R'#255#12#16'Q'#255#14#17'S'#255#12#15'S'#255#13#16'T'#255#12#15'T'#255#11
+ +#15'P'#255#11#15'P'#255#11#16'O'#255#10#16'O'#253#11#17'N'#251#13#17'G'#248
+ +#21#18'<'#241#30#20'/'#209'('#26'*;3"2'#2#192#168#160#0'-'#28')'#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'm]\"^Vf'#224
+ +'HKr'#252#28')d'#254#15#31'j'#254#11#28'q'#255#4#22'o'#255#5#21'r'#255#12#27
+ +'~'#255#7#24'~'#255#5#23#129#255#8#24#130#255#7#23#129#255#6#22#128#255#7#25
+ +#133#255#5#26#131#255#5#24#129#255#7#25#132#255#6#24#131#255#8#24#130#255#8
+ +#24#130#255#9#25#130#255#9#26#130#255#9#24#132#255#10#26#130#255#8#28'~'#255
+ +#7#27'x'#255#10#28'x'#255#8#23'q'#255#7#18'j'#255#7#16'e'#255#5#14'_'#255#7
+ +#16'_'#255#6#16'\'#255#5#16'Y'#255#4#16'['#255#4#17'b'#255#5#19'j'#255#8#21
+ +'r'#255#6#22'u'#255#9#24'y'#255#7#22'y'#255#13#27'}'#255#9#26'z'#255#4#21'u'
+ +#255#3#21'w'#255#6#23'|'#255#6#23#127#255#6#22#128#255#6#22#129#255#7#23#130
+ +#255#8#22#132#255#7#24#131#255#5#22#129#255#5#23#131#255#6#23'}'#255#6#23'|'
+ +#255#8#26's'#255#19#24'q'#255#11#20'l'#255#7#18'W'#255#4#10'U'#255#7'-'#142
+ +#255#8'_'#222#255#4'Z'#217#255#8'c'#238#255#2'h'#236#255#4'k'#226#255#5'h'
+ +#230#255#7'g'#234#255#7'i'#228#255#10'f'#232#255#7'd'#230#255#4'a'#227#255#5
+ +'c'#228#255#7'f'#228#255#6'e'#226#255#6'e'#227#255#6'e'#227#255#7'h'#231#255
+ +#8'i'#233#255#4'e'#230#255#5'e'#231#255#4'e'#230#255#5'd'#229#255#6'e'#229
+ +#255#8'g'#228#255#4'e'#226#255#6'f'#228#255#8'g'#234#255#10'h'#238#255#7'e'
+ +#233#255#4'c'#231#255#6'd'#232#255#6'd'#233#255#9'd'#235#255#3'a'#231#255#2
+ +'b'#229#255#9'e'#233#255#7'g'#228#255#6'i'#221#255#23'o'#216#255' m'#205#255
+ +#28'M'#158#255#3#31'e'#255#14#18'S'#255#10#17'O'#255#4#17']'#255#1#18'm'#255
+ +#9#25'{'#255#7#27'{'#255#7#26'}'#255#6#24'~'#255#7#25#127#255#7#23#130#255#8
+ +#23#132#255#8#23#133#255#8#24#131#255#8#24#131#255#7#23#129#255#7#23#130#255
+ +#6#22#128#255#7#23#129#255#8#21#128#255#10#23#130#255#9#22#130#255#8#22#128
+ +#255#8#23#128#255#7#23#127#255#8#23#128#255#6#22'~'#255#8#24#128#255#7#22#127
+ +#255#6#22'~'#255#6#22'~'#255#7#21#127#255#7#21#127#255#9#24#129#255#7#22#127
+ +#255#9#23'}'#255#5#23'{'#255#7#27'|'#255#2#23'v'#255#5'0'#157#255#9'='#175
+ +#255#6'@'#179#255#7'F'#185#255#9'D'#183#255#7'>'#171#255#9'='#162#255#10'<'
+ +#156#255#16'<'#154#255#18'1'#133#255#9#27'_'#255#11#20'W'#255#9#18'U'#255#8
+ +#18'R'#255#10#16'N'#255#9#15'N'#255#10#16'O'#255#12#17'P'#255#12#17'P'#255#12
+ +#17'P'#255#13#18'Q'#255#13#18'Q'#255#12#17'P'#255#12#17'P'#255#12#16'Q'#255
+ +#12#16'Q'#255#12#16'Q'#255#11#15'P'#255#10#14'O'#255#10#14'O'#255#11#15'P'
+ +#255#11#15'P'#255#11#16'P'#253#9#16'O'#251#11#18'K'#248#16#19'B'#243#25#20'6'
+ +#218'$'#24'.o&'#23'.'#8#157#135#132#3#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ ,#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'lWY'#0#0#0#0#0'eV`}SOm'#242'08l'#253
+ +#16' g'#255#9#28'm'#255#7#26'o'#255#3#17'h'#255#6#24's'#255#7#27'|'#255#5#24
+ +#127#255#6#24'~'#255#7#24#128#255#6#23#128#255#8#26#132#255#8#27#132#255#7#26
+ +#131#255#7#25#132#255#7#25#132#255#6#24#132#255#7#24#131#255#7#23#130#255#7
+ +#23#130#255#6#22#131#255#9#25#130#255#5#23'~'#255#5#25'~'#255#4#23#127#255#8
+ +#26#128#255#8#25#127#255#7#26'}'#255#13#23'y'#255#12#23'z'#255#8#22'z'#255#10
+ +#25#127#255#5#22#127#255#7#24#129#255#5#24#129#255#5#24#131#255#5#26'}'#255#5
+ +#27'x'#255#9#26'{'#255#10#25'z'#255#5#22'p'#255#2#19'o'#255#7#23'~'#255#4#24
+ +'}'#255#7#22#129#255#8#24#131#255#8#24#131#255#9#25#132#255#5#23#131#255#6#24
+ +#131#255#4#22#129#255#6#24#131#255#8#23#128#255#1#26'z'#255#7#25't'#255#21#24
+ +'r'#255#12#25'i'#255#2#19'X'#255#4#14'X'#255#7#12'X'#255#7'0'#144#255#23'_'
+ +#213#255#8'Y'#217#255#11'X'#210#255#15'i'#226#255#2'g'#229#255#11'i'#230#255
+ +#6'i'#227#255#1'a'#223#255#6'g'#228#255#6'g'#229#255#9'i'#231#255#4'e'#227
+ +#255#3'd'#226#255#9'i'#231#255#6'f'#226#255#6'g'#230#255#7'h'#232#255#5'f'
+ +#230#255#8'i'#233#255#7'h'#232#255#6'g'#230#255#5'h'#226#255#4'h'#224#255#6
+ +'h'#223#255#7'i'#227#255#7'g'#231#255#5'e'#229#255#7'g'#231#255#4'c'#229#255
+ +#6'd'#232#255#8'f'#235#255#9'f'#235#255#7'f'#232#255#12'h'#233#255#13'j'#227
+ +#255#12'g'#219#255#25's'#214#255')h'#192#255#22'@'#140#255#8#23'\'#255#4#18
+ +'T'#255#2#14'O'#255#9#19'['#255#8#18'h'#255#5#22'u'#255#8#25#127#255#5#27'~'
+ +#255#7#26'~'#255#7#24'~'#255#7#24#128#255#9#24#132#255#9#24#133#255#8#22#133
+ +#255#9#24#134#255#8#24#132#255#7#24#132#255#8#23#132#255#6#21#129#255#9#24
+ +#133#255#6#22#130#255#7#24#131#255#7#23#130#255#5#22#128#255#6#22#128#255#6
+ +#22#128#255#7#23#130#255#6#22#129#255#7#23#130#255#5#21#128#255#5#21#129#255
+ +#6#22#128#255#6#22#128#255#8#23#129#255#9#23#129#255#9#24#128#255#10#24#127
+ +#255#8#26'~'#255#4#25'{'#255#0#24'z'#255#6':'#167#255#8'@'#176#255#4'?'#171
+ +#255#9'A'#173#255#8':'#163#255#2'.'#148#255#9'3'#149#255#12'8'#151#255#24'?'
+ +#155#255#13')y'#255#10#24'Z'#255#11#20'W'#255#11#19'W'#255#11#17'S'#255#12#17
+ +'Q'#255#10#16'P'#255#11#16'N'#255#11#16'N'#255#12#17'P'#255#12#17'P'#255#13
+ +#18'Q'#255#13#17'Q'#255#11#15'P'#255#13#17'R'#255#12#15'Q'#255#13#17'R'#255
+ +#12#16'Q'#255#12#16'Q'#255#11#17'O'#255#12#16'P'#255#11#15'P'#254#11#14'P'
+ +#254#10#15'P'#251#12#17'N'#248#15#17'E'#246#23#20'<'#233#30#21'3'#147'%'#24
+ +'-!3$5'#1'~ca'#0#164#143#140#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'kWY'#0'gJ5'#2'^Sj'#177'@Dn'#253#23'&c'#254
+ +#16'$n'#255#12#31'n'#255#5#22'i'#255#4#22'l'#255#7#26'x'#255#6#24'}'#255#6#24
+ +#128#255#5#24#128#255#5#24#128#255#8#25#131#255#6#24#130#255#8#26#132#255#7
+ +#25#132#255#7#25#132#255#7#24#133#255#7#25#132#255#6#24#130#255#7#24#130#255
+ +#4#24#133#255#5#24#133#255#4#25#130#255#6#24#129#255#7#24#129#255#8#26#131
+ +#255#5#24#127#255#7#27#127#255#2#23'}'#255#7#26#130#255#5#26#130#255#7#26#134
+ +#255#4#23#134#255#6#24#130#255#6#25#127#255#6#26'|'#255#7#27'|'#255#7#27'r'
+ +#255#8#22'p'#255#10#21'o'#255#3#17'h'#255#3#18'n'#255#9#24'|'#255#6#23'|'#255
+ +#7#24#128#255#8#25#129#255#7#24#128#255#7#23#129#255#6#24#129#255#7#24#129
+ +#255#6#24#129#255#7#25#130#255#9#23#128#255#4#26'{'#255#7#24'w'#255#8#28't'
+ +#255#14#30'j'#255#7#18'\'#255#4#16'W'#255#7#16'P'#255#1#12'N'#255#10'5'#162
+ +#255'#\'#206#255#3'1'#157#255#16'W'#205#255#11'o'#235#255#3'g'#217#255#6'h'
+ +#224#255#6'l'#228#255#6'l'#228#255#5'h'#227#255#8'i'#231#255#6'g'#229#255#5
+ +'e'#229#255#6'j'#231#255#3'g'#228#255#3'e'#227#255#7'h'#230#255#7'g'#231#255
+ +#9'i'#233#255#6'e'#229#255#6'f'#228#255#8'i'#229#255#6'h'#226#255#6'i'#228
+ +#255#5'f'#228#255#6'i'#233#255#4'g'#233#255#4'g'#232#255#9'i'#236#255#4'f'
+ +#234#255#3'f'#235#255#1'h'#232#255#3'e'#227#255#10'j'#229#255#18'l'#225#255
+ +#24'o'#217#255'&h'#193#255#17'7'#131#255#15#22'Y'#255#7#19'Q'#255#8#17'V'#255
+ +#5#13'Y'#255#6#15'd'#255#11#21's'#255#6#24'x'#255#5#26'~'#255#10#24'~'#255#9
+ +#26#129#255#6#22#129#255#8#24#131#255#9#23#134#255#8#21#134#255#6#22#134#255
+ +#7#23#133#255#7#22#133#255#7#24#133#255#6#23#132#255#5#21#130#255#7#24#132
+ +#255#6#22#129#255#6#22#127#255#6#23#127#255#5#21#127#255#6#21'~'#255#6#22'~'
+ +#255#6#22'~'#255#8#23#130#255#8#22#130#255#8#22#130#255#9#24#130#255#7#23#127
+ +#255#6#22#129#255#6#21#128#255#5#22#128#255#7#22#127#255#6#24'~'#255#8#26#127
+ +#255#4#25'~'#255#0'#'#140#255#4'C'#183#255#7'F'#187#255#3'E'#183#255#5'C'#179
+ ,#255#8'@'#171#255#5'9'#160#255#13'='#160#255#12'>'#157#255#22'?'#149#255#9'!'
+ +'p'#255#10#22'Y'#255#12#20'U'#255#10#17'S'#255#12#18'R'#255#14#19'R'#255#11
+ +#16'Q'#255#12#17'Q'#255#11#17'O'#255#11#17'O'#255#11#17'P'#255#12#18'Q'#255
+ +#12#17'Q'#255#11#16'P'#255#12#17'Q'#255#10#15'Q'#255#11#16'S'#255#10#15'O'
+ +#255#12#17'P'#255#10#17'P'#255#11#17'R'#254#12#17'R'#254#13#16'R'#252#13#16
+ +'O'#249#14#18'J'#246#19#17'@'#240#27#20'6'#191'!'#21'/I-'#30'/'#9#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'\LZARSo'#247'*7f'#254#6#29'`'#254#12'#p'#255
+ +#6#27'n'#255#1#20'k'#255#8#26'w'#255#11#27'~'#255#6#25#128#255#5#24#130#255#7
+ +#25#130#255#7#23#130#255#8#24#130#255#9#25#132#255#6#23#130#255#6#24#131#255
+ +#5#23#130#255#6#24#131#255#5#24#129#255#5#24#129#255#6#23#131#255#7#25#132
+ +#255#7#26#131#255#6#25#130#255#6#25#129#255#6#26#129#255#5#24#128#255#4#23
+ +#129#255#6#23'}'#255#5#23'}'#255#3#23'}'#255#5#24#129#255#5#23#132#255#5#24
+ +#128#255#7#24'~'#255#7#27'{'#255#7#27'u'#255#7#24'n'#255#7#21'i'#255#6#17'd'
+ +#255#4#18'g'#255#5#21'p'#255#7#25'y'#255#5#25'z'#255#7#25'~'#255#6#24'}'#255
+ +#6#24'}'#255#7#23#127#255#6#23'~'#255#6#23'~'#255#5#21'~'#255#6#22#128#255#6
+ +#23'~'#255#7#25'~'#255#9#26'z'#255#8#25'r'#255#14#31'p'#255#6#19'\'#255#3#14
+ +'R'#255#8#17'Q'#255#12#16'N'#255#0#14'T'#255#17'9'#147#255#16'5'#142#255#1#29
+ +'u'#255#17'U'#182#255#8'q'#229#255#11'h'#222#255#5'k'#226#255#5'j'#225#255#3
+ +'g'#224#255#6'i'#227#255#8'k'#229#255#5'g'#224#255#4'f'#224#255#5'g'#224#255
+ +#5'k'#225#255#6'j'#224#255#4'h'#224#255#6'i'#228#255#4'h'#228#255#4'g'#227
+ +#255#6'j'#229#255#2'f'#224#255#4'g'#227#255#1'g'#228#255#1'h'#230#255#5'k'
+ +#232#255#1'd'#226#255#9'f'#228#255#9'g'#228#255#6'g'#228#255#7'g'#222#255#8
+ +'j'#221#255#11'k'#218#255'"v'#215#255'!Y'#177#255#21'0|'#255#3#20'W'#255#8#20
+ +'T'#255#9#18'U'#255#5#14'V'#255#4#15'`'#255#9#22'p'#255#10#25'|'#255#3#21'z'
+ +#255#5#23'|'#255#7#24'|'#255#9#25#128#255#8#23#129#255#7#24#130#255#6#23#130
+ +#255#5#22#131#255#6#24#132#255#5#23#130#255#5#24#129#255#6#25#130#255#4#23
+ +#129#255#6#23#130#255#7#24#128#255#7#25'~'#255#5#24'|'#255#7#25'}'#255#7#23
+ +#127#255#7#22'|'#255#8#23'}'#255#6#21'{'#255#8#22#128#255#9#23#129#255#7#21
+ +'~'#255#8#23#127#255#7#22'}'#255#6#24'~'#255#7#23'|'#255#4#24'{'#255#5#23'}'
+ +#255#4#24'z'#255#7#28'}'#255#0#28#127#255#11'I'#183#255#13'b'#217#255#11'`'
+ +#215#255#15'a'#215#255#11'W'#202#255#12'P'#193#255#8'F'#175#255#10'@'#161#255
+ +#11'?'#155#255#19'9'#136#255#6#30'h'#255#9#19'Y'#255#12#21'T'#255#9#18'Q'#255
+ +#12#18'Q'#255#12#18'Q'#255#8#15'O'#255#10#17'P'#255#8#16'M'#255#9#17'N'#255#9
+ +#18'O'#255#10#18'Q'#255#10#18'Q'#255#7#16'P'#255#9#18'Q'#255#7#16'Q'#255#9#17
+ +'Q'#255#9#16'O'#255#10#16'P'#255#8#16'Q'#255#8#17'T'#255#8#17'R'#252#13#17'Q'
+ +#249#12#14'J'#248#15#18'E'#244#24#19';'#221#30#19'1y'''#24'.'#28'nZa'#3#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'?52'#0'YJQ''WP`'#216'HNs'#253#16'#['#255#11'"'
+ +'h'#255#9'!o'#255#4#25'l'#255#4#22'p'#255#9#26'y'#255#8#27#127#255#5#25#129
+ +#255#9#25#130#255#11#25#129#255#8#25#129#255#9#25#131#255#8#24#131#255#9#25
+ +#132#255#5#23#130#255#7#25#132#255#7#26#131#255#5#25#130#255#7#25#132#255#6
+ +#24#131#255#7#24#132#255#6#24#131#255#6#24#131#255#7#24#133#255#6#23#133#255
+ +#5#22#133#255#8#23#131#255#7#24#131#255#6#24#130#255#5#24#130#255#6#24#131
+ +#255#6#24#128#255#10#26'}'#255#8#26'u'#255#11#27'o'#255#11#23'h'#255#10#22'd'
+ +#255#6#17'`'#255#5#16'e'#255#6#22'p'#255#5#23'v'#255#5#24'z'#255#6#25'}'#255
+ +#6#24'}'#255#6#24'}'#255#7#24'~'#255#7#24'~'#255#9#25#131#255#6#22#128#255#7
+ +#23#129#255#6#24'}'#255#5#25'{'#255#7#24'y'#255#7#27't'#255#13#31'p'#255#12
+ +#27'b'#255#9#21'V'#255#9#19'N'#255#8#17'M'#255#9#19'I'#255#9#16'O'#255#11#31
+ +'a'#255#6#19'P'#255#6#23'c'#255#13'L'#185#255#1'i'#223#255#4'c'#221#255#9'h'
+ +#227#255#7'i'#227#255#6'j'#229#255#7'm'#232#255#6'i'#228#255#7'i'#226#255#9
+ +'k'#228#255#8'm'#226#255#6'j'#226#255#6'i'#225#255#8'j'#229#255#5'j'#230#255
+ +#1'e'#226#255#7'l'#233#255#3'g'#231#255#5'h'#233#255#5'h'#233#255#8'k'#236
+ +#255#5'j'#234#255#0'f'#230#255#5'i'#229#255#6'i'#225#255#6'i'#222#255#16'k'
+ +#223#255#17'k'#217#255'*v'#215#255#30'L'#158#255#22')i'#255#10#20'O'#255#6#18
+ +'O'#255#8#15'U'#255#9#15'Z'#255#5#15'_'#255#5#21'o'#255#7#26'|'#255#9#28#130
+ ,#255#4#23'|'#255#8#26#128#255#7#23'}'#255#7#26#129#255#5#24#127#255#6#25#127
+ +#255#6#26#130#255#5#24#129#255#7#26#130#255#5#24#127#255#5#24#127#255#4#23'~'
+ +#255#5#24#130#255#7#23#129#255#7#24#128#255#7#26'}'#255#6#25'|'#255#6#25'|'
+ +#255#8#26#127#255#8#23'}'#255#9#24'~'#255#7#22'|'#255#9#24#127#255#9#24#127
+ +#255#8#23'~'#255#9#24'~'#255#7#22'|'#255#6#24'~'#255#6#25'}'#255#6#25'}'#255
+ +#7#25'~'#255#9#25'~'#255#5#29#128#255#0'.'#149#255#13'^'#210#255#3'b'#216#255
+ +#3'^'#212#255#5'V'#203#255#5'M'#190#255#8'I'#183#255#7'C'#171#255#9'?'#159
+ +#255#17'B'#156#255#12'+w'#255#6#25']'#255#9#20'U'#255#11#21'S'#255#8#19'Q'
+ +#255#12#16'O'#255#10#16'O'#255#7#16'O'#255#9#20'O'#255#7#18'M'#255#9#19'O'
+ +#255#9#19'O'#255#7#18'N'#255#9#18'O'#255#7#16'P'#255#9#18'Q'#255#7#16'P'#255
+ +#8#18'R'#255#10#16'Q'#255#10#18'S'#255#7#16'S'#255#7#16'S'#253#8#16'P'#250#14
+ +#17'M'#248#17#17'F'#245#22#21'?'#239#29#19'3'#177'$'#22'.8SAM'#10#146'yx'#0
+ +#143'z|'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'PJL'#0'H'#162#255#18'='#154#255#22'8'#145#255#7#28'e'#255#9#21'X'#255#11#19'T'#255
+ +#10#20'R'#255#9#18'R'#255#15#16'Q'#255#13#15'P'#255#8#17'P'#255#10#17'Q'#255
+ +#10#17'Q'#255#10#17'P'#255#9#17'P'#255#8#17'O'#255#10#18'O'#255#7#17'M'#255#8
+ +#18'N'#255#9#17'P'#255#10#17'R'#255#10#16'Q'#255#10#18'T'#255#9#17'S'#254#8
+ +#17'R'#251#11#17'K'#248#16#19'G'#245#21#21'?'#242#29#21'3'#214'#'#21',\0 0'
+ +#14#131'lo'#4#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'\TT'#1'JCG'#28'B9C'
+ +#141'JE]'#251'=Do'#252'!3k'#254#9#30'f'#254#15'!o'#255#7#21'j'#255#0#14'e'
+ +#255#8#22'p'#255#10#26'v'#255#11#28'}'#255#10#24#128#255#10#27#128#255#8#24
+ +#128#255#7#23#130#255#8#24#131#255#9#25#132#255#9#23#131#255#9#22#132#255#10
+ +#22#132#255#7#26#132#255#5#23#129#255#7#24#130#255#6#23#130#255#6#24#129#255
+ +#6#23#131#255#6#23#131#255#8#24#134#255#7#24#130#255#6#25#130#255#4#24#129
+ +#255#6#25#127#255#6#27'}'#255#7#27'w'#255#8#26'o'#255#9#24'h'#255#10#19'b'
+ +#255#8#17'`'#255#5#14'`'#255#5#14'd'#255#7#18'k'#255#7#23'v'#255#6#25'{'#255
+ +#4#24'~'#255#6#24#129#255#6#24#128#255#6#24#127#255#5#24'~'#255#4#24'~'#255#5
+ +#24#127#255#4#23'~'#255#6#25#128#255#8#23#128#255#7#24#127#255#8#24'}'#255#6
+ +#24'x'#255#7#26's'#255#13#29'l'#255#7#19'Y'#255#8#17'Q'#255#13#17'N'#255#10
+ +#19'I'#255#11#18'J'#255#9#16'L'#255#12#15'K'#255#4#19'G'#255#2#14'I'#255#6' '
+ ,'g'#255#7'F'#171#255#27'i'#214#255#14'h'#218#255#14'i'#230#255#12'k'#230#255
+ +#5'k'#228#255#3'i'#227#255#13'k'#231#255#7'i'#230#255#7'i'#228#255#5'f'#223
+ +#255#8'h'#225#255#9'i'#227#255#5'e'#226#255#10'h'#230#255#8'd'#228#255#6'j'
+ +#231#255#11'j'#231#255#17'i'#231#255#14'g'#226#255#20'n'#225#255#30's'#224
+ +#255',r'#215#255'%['#189#255#28'<'#138#255#7#29'b'#255#7#18'N'#255#12#22'M'
+ +#255#9#18'O'#255#8#16'U'#255#5#12'Z'#255#4#14'\'#255#3#17'm'#255#9#25'{'#255
+ +#7#23#131#255#9#23#136#255#10#24#136#255#9#22#134#255#6#23#133#255#3#23#133
+ +#255#6#22#133#255#6#22#132#255#6#21#133#255#6#21#133#255#5#20#130#255#7#22
+ +#132#255#7#22#131#255#8#24#131#255#7#22#129#255#8#22#130#255#7#22#129#255#8
+ +#24#129#255#7#23'~'#255#8#24#128#255#7#23'~'#255#8#23#129#255#3#18'}'#255#9
+ +#24#131#255#6#22'}'#255#7#24'~'#255#6#23'|'#255#7#23'}'#255#8#23#127#255#8#23
+ +#127#255#8#23#129#255#8#22#127#255#4#24'~'#255#1#26'{'#255#7#23'y'#255#4#29
+ +#130#255#4'M'#184#255#10'Z'#210#255#9'W'#206#255#7'P'#196#255#7'F'#181#255#8
+ +'D'#171#255#5'?'#165#255#11'='#157#255#24'>'#151#255#20'.'#128#255#10#23'\'
+ +#255#11#19'U'#255#10#17'R'#255#12#17'R'#255#12#17'S'#255#16#16'S'#255#13#16
+ +'R'#255#10#17'R'#255#11#18'U'#255#10#16'Q'#255#11#17'R'#255#11#16'P'#255#11
+ +#16'P'#255#11#18'P'#255#11#17'N'#255#11#17'N'#255#11#15'P'#255#12#16'Q'#255
+ +#11#16'P'#255#11#17'R'#255#9#17'S'#251#10#17'O'#249#16#17'I'#246#18#19'@'#241
+ +#25#20'5'#230'$'#24')|*'#25'*'#20'^FJ'#6#161#137#137#0'mTX'#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0'WPQ'#31'A;Dx53D'#244'?Ag'#251'+6i'#252#14'!b'
+ +#254#12#30'h'#254#16' v'#255#9#26'r'#255#5#21'j'#255#6#22'h'#255#4#20'j'#255
+ +#9#25't'#255#7#26'w'#255#10#28'|'#255#7#24'~'#255#6#25#128#255#5#25#127#255#4
+ +#25#127#255#5#25'~'#255#5#26'~'#255#8#26#127#255#7#24'~'#255#6#24'}'#255#6#24
+ +'~'#255#8#24#129#255#7#23#130#255#7#23#131#255#8#23#132#255#8#24#130#255#8#25
+ +#132#255#6#25#129#255#8#27#128#255#6#25'z'#255#8#26's'#255#7#23'j'#255#7#20
+ +'b'#255#10#19'\'#255#7#18'\'#255#3#13']'#255#7#17'g'#255#7#19'n'#255#6#22'u'
+ +#255#7#26'|'#255#4#24'~'#255#7#24#127#255#6#24'|'#255#6#24'}'#255#6#24'}'#255
+ +#4#25'~'#255#5#25#127#255#3#22'}'#255#6#25#128#255#4#23#129#255#7#22#128#255
+ +#7#23'}'#255#8#25'{'#255#7#24'u'#255#12#30'o'#255#12#25'a'#255#8#19'S'#255#8
+ +#17'M'#255#9#18'M'#255#10#17'L'#255#11#17'L'#255#10#16'K'#255#12#19'O'#255#7
+ +#16'L'#255#5#15'M'#255#4#11'K'#255#12'%n'#255#22'J'#157#255#19'V'#189#255#20
+ +'b'#215#255#21'n'#236#255#8'j'#228#255#13'j'#227#255#12'j'#225#255#15'l'#226
+ +#255#17'm'#228#255#13'l'#227#255#11'j'#229#255#14'j'#228#255#17'l'#229#255#22
+ +'o'#231#255#24's'#227#255#26'o'#224#255'$p'#220#255'.i'#209#255'#Q'#174#255
+ +#27';'#145#255#22'-v'#255#7#24'['#255#4#17'O'#255#5#15'L'#255#9#18'N'#255#10
+ +#18'N'#255#9#18'Q'#255#6#15'V'#255#2#13'\'#255#6#18'g'#255#5#20'z'#255#11#26
+ +#128#255#10#24#130#255#9#22#131#255#9#23#134#255#8#22#133#255#9#22#132#255#8
+ +#23#130#255#7#23#129#255#5#22#128#255#7#23#131#255#8#23#134#255#7#21#133#255
+ +#6#21#132#255#6#21#131#255#8#22#133#255#8#23#130#255#8#22#130#255#7#22#128
+ +#255#10#24#128#255#9#24'~'#255#10#25#127#255#6#20'{'#255#7#21'|'#255#3#19'}'
+ +#255#8#24#129#255#6#23'~'#255#8#26#127#255#5#22'}'#255#6#23'~'#255#7#23#128
+ +#255#6#22#129#255#6#23#128#255#7#22#129#255#8#22#128#255#6#28#128#255#5#24'{'
+ +#255#4'0'#154#255#11'Z'#203#255#3'S'#198#255#6'M'#191#255#6'F'#181#255#6'@'
+ +#170#255#6'='#163#255#10'>'#163#255#18'>'#157#255#24'9'#143#255#13'!l'#255#11
+ +#20'X'#255#12#21'U'#255#11#18'S'#255#13#18'S'#255#14#17'R'#255#13#17'R'#255
+ +#12#16'S'#255#11#17'T'#255#10#16'R'#255#10#16'Q'#255#11#17'R'#255#9#16'P'#255
+ +#11#18'Q'#255#12#18'Q'#255#13#18'Q'#255#12#18'Q'#255#13#16'R'#255#12#15'Q'
+ +#255#11#14'Q'#254#12#16'S'#253#12#16'S'#249#16#17'N'#246#24#17'C'#242#26#21
+ +'9'#224'"'#20'+'#159'*'#23'%'#19'W;?'#8'u[Z'#2#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0']UT'#8'SMP'#132'64C'#247'*/M'#250'4'#165#255#8';'#160#255
+ +#18'>'#160#255#24';'#150#255#20'*{'#255#7#22'_'#255#9#17'U'#255#9#18'S'#255#9
+ +#19'S'#255#9#16'Q'#255#10#17'P'#255#11#18'Q'#255#12#18'R'#255#10#16'Q'#255#9
+ +#16'Q'#255#9#17'Q'#255#11#17'R'#255#9#16'O'#255#10#16'P'#255#10#16'P'#255#10
+ +#17'Q'#255#10#16'P'#255#8#15'P'#255#8#16'Q'#254#11#14'R'#254#14#14'Q'#250#16
+ +#16'M'#248#22#18'D'#242#31#20'7'#219'#'#20'-'#152','#24'&'#25'eJL'#8'^CF'#3#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'['
+ +'ST.LIR'#216'),G'#249' (P'#250'#1i'#252#28'-m'#253#12#30'j'#254#7#27'q'#255#9
+ +#27'y'#255#10#27'{'#255#10#28'z'#255#5#24'w'#255#9#26'g'#255#2#18'c'#255#3#17
+ +'e'#255#5#17'g'#255#4#18'g'#255#5#20'i'#255#3#17'h'#255#6#20'l'#255#1#16'k'
+ +#255#4#20'p'#255#2#18'q'#255#2#19't'#255#5#20'y'#255#5#23'|'#255#4#25'~'#255
+ +#7#26#128#255#8#26#127#255#7#26'|'#255#8#26'w'#255#9#26'o'#255#8#25'f'#255#9
+ +#23'^'#255#8#19'W'#255#12#21'X'#255#8#15'X'#255#4#12'['#255#6#18'f'#255#7#21
+ +'q'#255#5#22'w'#255#7#25'}'#255#5#24'{'#255#6#25'}'#255#6#24'}'#255#9#29#127
+ +#255#6#25'|'#255#8#27'~'#255#5#26'}'#255#5#26'~'#255#5#25'~'#255#6#26#127#255
+ +#5#24#127#255#6#26#128#255#6#26'}'#255#7#28'|'#255#3#25'x'#255#7#27'r'#255#12
+ +#28'h'#255#7#20'['#255#9#18'M'#255#9#18'N'#255#9#17'L'#255#9#17'L'#255#11#19
+ +'N'#255#12#19'N'#255#10#17'L'#255#11#19'N'#255#4#20'H'#255#6#20'L'#255#9#16
+ +'L'#255#9#22'L'#255#9#18'E'#255#10#14'D'#255#2#12'I'#255#5#30'a'#255#14'#a'
+ +#255#3#19'P'#255#0#14'I'#255#6#18'L'#255#4#17'K'#255#3#14'F'#255#7#17'F'#255
+ +#7#13'?'#255#0#11'C'#255#2#13'D'#255#5#14'D'#255#7#16'I'#255#8#16'J'#255#6#17
+ +'J'#255#7#16'K'#255#16#17'R'#255#7#19'L'#255#6#17'L'#255#5#15'K'#255#7#15'S'
+ +#255#5#14'X'#255#6#17'b'#255#7#22'p'#255#7#26'z'#255#6#22'z'#255#8#23'|'#255
+ +#8#22'}'#255#6#22'}'#255#7#23#129#255#6#22#128#255#6#24#128#255#5#23#127#255
+ +#5#23'~'#255#7#25#128#255#6#24#129#255#6#23#129#255#6#24#129#255#8#25#131#255
+ +#6#23#127#255#6#24#128#255#6#25#127#255#6#26'~'#255#7#25'}'#255#9#27#127#255
+ +#9#27'~'#255#5#22'y'#255#5#22'{'#255#7#23'}'#255#5#23#127#255#6#24#128#255#6
+ +#24#128#255#5#23'~'#255#6#24#127#255#5#23#127#255#5#24'~'#255#7#25#127#255#9
+ +#24#127#255#3#26'~'#255#6#24'|'#255#4#27'x'#255#1#28'z'#255#15'I'#175#255#20
+ +'R'#185#255#15'J'#173#255#12'F'#162#255#15'E'#161#255#21'A'#159#255#28'A'#155
+ +#255#29';'#144#255#20'*z'#255#9#24'b'#255#9#21'Y'#255#8#17'U'#255#8#18'S'#255
+ +#9#19'R'#255#8#18'Q'#255#7#17'O'#255#9#18'Q'#255#8#17'P'#255#7#16'P'#255#8#18
+ +'O'#255#8#18'P'#255#9#18'Q'#255#8#15'P'#255#8#16'P'#255#10#16'Q'#255#10#16'Q'
+ +#255#10#16'Q'#255#7#16'O'#254#7#18'P'#254#11#17'P'#252#15#17'J'#247#18#17'C'
+ +#243#27#21'8'#222'$'#21','#153')'#23'&'#30'('#18#26#0'eLN'#7#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'ZPT'#0#0#0#0#0
+ ,'VMWW>=T'#232'#(M'#250#18#30'O'#250#18'$\'#252#14'"g'#253#7#30'n'#255#6#26's'
+ +#255#9#28'{'#255#6#29#128#255#5#29#129#255#6#26#129#255#7#27#130#255#5#25'~'
+ +#255#6#24'|'#255#7#25'y'#255#8#25'y'#255#5#22'u'#255#9#26'y'#255#6#24'w'#255
+ +#9#28'{'#255#8#26'|'#255#8#25'}'#255#6#23'}'#255#7#27#127#255#5#26'~'#255#5
+ +#26'~'#255#5#25'y'#255#5#27'u'#255#7#27'o'#255#9#26'g'#255#9#24'`'#255#9#20
+ +'Y'#255#10#19'X'#255#11#18'Y'#255#6#12'T'#255#5#15']'#255#4#19'i'#255#5#23't'
+ +#255#4#23'y'#255#6#25'z'#255#6#24'z'#255#6#25'|'#255#5#24'|'#255#9#28#127#255
+ +#6#24'|'#255#7#25'}'#255#5#25'}'#255#6#26'|'#255#6#26'~'#255#7#26'}'#255#1#23
+ +'{'#255#5#26'~'#255#5#25'|'#255#4#25'z'#255#5#26'y'#255#9#28'u'#255#14#30'm'
+ +#255#8#23'c'#255#9#18'Q'#255#9#17'N'#255#8#16'J'#255#10#18'J'#255#6#15'I'#255
+ +#10#18'L'#255#10#18'L'#255#8#16'H'#255#8#19'I'#255#13#18'I'#255#6#18'F'#255#3
+ +#17'J'#255#4#18'K'#255#10#15'J'#255#10#15'H'#255#6#18'I'#255#3#15'F'#255#7#16
+ +'E'#255#8#16'E'#255#8#16'F'#255#6#16'G'#255#7#18'I'#255#5#18'G'#255#5#18'H'
+ +#255#10#17'G'#255#8#14'H'#255#6#16'J'#255#5#15'J'#255#10#18'M'#255#11#17'K'
+ +#255#6#18'K'#255#2#19'K'#255#6#17'K'#255#5#17'K'#255#6#16'Q'#255#4#15'X'#255
+ +#6#17'a'#255#9#24'm'#255#9#26'u'#255#6#26'{'#255#5#23'y'#255#7#24'|'#255#6#25
+ +'}'#255#7#25#127#255#6#25#129#255#5#23#127#255#7#25#129#255#6#23#129#255#6#24
+ +#127#255#5#24#128#255#6#25#129#255#5#24#130#255#5#24#129#255#6#25#129#255#6
+ +#25#127#255#5#25'~'#255#6#26'}'#255#5#24'{'#255#6#25'{'#255#6#26'z'#255#5#24
+ +'x'#255#4#23'y'#255#4#23'{'#255#6#23'~'#255#6#24#128#255#6#24#128#255#5#25
+ +#128#255#4#24#127#255#5#24#128#255#4#24'~'#255#6#24'~'#255#6#25'~'#255#9#23
+ +'~'#255#7#26'}'#255#5#25'y'#255#3#28'r'#255#6'!x'#255#26'B'#155#255#16':'#146
+ +#255#12'6'#139#255#14'2'#130#255#15'.~'#255#16'+x'#255#13'#n'#255#7#23'^'#255
+ +#4#18'U'#255#8#20'T'#255#9#20'U'#255#10#18'V'#255#9#18'T'#255#9#19'R'#255#8
+ +#18'Q'#255#6#17'N'#255#7#17'O'#255#7#17'N'#255#9#18'P'#255#8#18'O'#255#8#17
+ +'Q'#255#10#19'R'#255#8#18'R'#255#8#17'P'#255#11#17'R'#255#9#17'Q'#255#10#17
+ +'R'#255#7#18'P'#255#7#19'O'#253#11#20'J'#250#17#21'C'#245#22#21'9'#223#29#21
+ +'/'#151'$'#23')!=(+'#4'W=>'#4#0#0#0#0'dHH'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'EEd'#2'MD[u44X'#238#25
+ +'$R'#251#16#31'T'#251#11#28'_'#252#7#25'f'#253#4#19'g'#255#9#24'r'#255#9#28
+ +'|'#255#7#27#128#255#4#24'~'#255#5#23#129#255#6#24#132#255#6#24#132#255#7#25
+ +#129#255#7#26#128#255#6#25'~'#255#7#25#128#255#6#23#131#255#10#27#134#255#8
+ +#26#132#255#7#26#130#255#4#24#127#255#6#25#127#255#5#24'}'#255#6#26'~'#255#8
+ +#26'y'#255#6#25'q'#255#8#25'j'#255#7#22'`'#255#6#19'W'#255#12#21'Y'#255#10#19
+ +'W'#255#8#15'V'#255#6#13'W'#255#7#16'c'#255#6#20'o'#255#4#21'v'#255#6#21'z'
+ +#255#7#23'y'#255#6#21'z'#255#7#22'}'#255#5#24'{'#255#6#24'~'#255#5#23'|'#255
+ +#6#23'}'#255#7#24'~'#255#6#24'~'#255#7#25'~'#255#6#24'|'#255#3#23'|'#255#7#25
+ +'}'#255#8#23'|'#255#7#23'|'#255#5#24'z'#255#7#25'w'#255#10#26'q'#255#8#24'i'
+ +#255#11#21'Y'#255#7#16'Q'#255#8#17'L'#255#12#19'J'#255#8#17'J'#255#9#18'K'
+ +#255#8#17'J'#255#10#17'J'#255#10#17'J'#255#9#18'I'#255#8#16'J'#255#10#17'K'
+ +#255#7#16'K'#255#7#17'K'#255#7#17'L'#255#8#17'M'#255#9#18'M'#255#7#17'L'#255
+ +#6#16'K'#255#8#18'L'#255#6#16'I'#255#7#17'J'#255#7#17'G'#255#6#16'F'#255#9#19
+ +'I'#255#8#17'J'#255#10#17'L'#255#11#17'L'#255#11#19'K'#255#10#18'K'#255#9#17
+ +'L'#255#8#18'L'#255#8#17'N'#255#5#15'Q'#255#4#14'V'#255#7#18'd'#255#5#20'm'
+ +#255#9#26'x'#255#8#25'{'#255#8#25'~'#255#7#25'}'#255#6#25'}'#255#6#25'}'#255
+ +#8#25#127#255#8#25#127#255#6#23#127#255#5#21#127#255#7#23#129#255#6#24#130
+ +#255#4#22#130#255#4#23#132#255#4#22#130#255#5#22#131#255#4#23#129#255#4#23'}'
+ +#255#5#25#127#255#6#23'}'#255#7#24'|'#255#8#24'|'#255#7#23'y'#255#5#21'x'#255
+ +#7#22'{'#255#7#23'}'#255#7#23#127#255#8#23#129#255#6#22'~'#255#8#23#128#255#6
+ +#22#127#255#7#25#131#255#9#23#130#255#7#23'~'#255#8#24'|'#255#5#25'{'#255#7
+ +#26'u'#255#8#27'q'#255#6#24'h'#255#5#23'c'#255#9#27'e'#255#3#20'\'#255#5#17
+ +'W'#255#4#16'R'#255#4#17'R'#255#6#17'R'#255#7#18'Q'#255#10#19'P'#255#9#18'Q'
+ +#255#9#18'Q'#255#10#18'R'#255#9#18'S'#255#8#17'R'#255#8#18'R'#255#7#16'P'#255
+ +#8#17'Q'#255#7#17'P'#255#8#17'P'#255#8#17'Q'#255#8#17'O'#255#7#17'N'#255#8#17
+ +'P'#255#6#16'P'#255#8#17'Q'#255#10#16'Q'#255#9#16'O'#255#8#17'P'#254#7#15'N'
+ +#253#9#17'N'#251#15#19'G'#249#20#20'='#241#25#20'4'#162'!'#22'.)8#*'#7'C+-'#1
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ ,#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'PGO'#10'G@W'#150',,Q'#241#23#30'O'
+ +#247#13#25'X'#250#12#24'`'#251#11#21'e'#254#8#17'h'#255#9#21'r'#255#9#25'~'
+ +#255#7#23#127#255#7#22#131#255#8#23#135#255#7#24#135#255#7#24#135#255#7#24
+ +#134#255#8#25#134#255#6#23#134#255#10#21#135#255#10#23#135#255#8#22#133#255#7
+ +#22#129#255#10#25#130#255#9#25#127#255#10#25'}'#255#9#25'|'#255#10#24's'#255
+ +#8#23'l'#255#8#21'b'#255#7#20'Z'#255#9#20'U'#255#9#18'T'#255#8#17'S'#255#6#14
+ +'S'#255#4#10'Z'#255#9#17'h'#255#9#19'v'#255#7#20'|'#255#7#19'|'#255#9#23'|'
+ +#255#8#21'|'#255#8#23#127#255#6#23#128#255#6#22#127#255#6#23#127#255#6#22#128
+ +#255#6#22#128#255#6#22#128#255#5#22#128#255#6#22#128#255#6#22#129#255#7#23
+ +#127#255#8#22#127#255#7#22'~'#255#7#22#127#255#7#22'{'#255#8#25'w'#255#10#25
+ +'s'#255#10#21'`'#255#6#15'U'#255#7#15'N'#255#9#16'I'#255#11#18'J'#255#9#17'J'
+ +#255#11#17'K'#255#12#18'L'#255#13#17'K'#255#13#17'K'#255#12#15'K'#255#10#15
+ +'J'#255#12#17'L'#255#12#16'M'#255#12#15'L'#255#12#15'M'#255#11#16'M'#255#10
+ +#15'K'#255#10#16'J'#255#11#17'L'#255#11#18'L'#255#10#16'J'#255#10#17'J'#255
+ +#11#16'J'#255#9#15'F'#255#12#17'K'#255#11#16'K'#255#12#15'J'#255#10#16'K'#255
+ +#10#16'J'#255#8#15'L'#255#9#15'O'#255#3#13'Q'#255#6#16'X'#255#6#18'b'#255#8
+ +#21'm'#255#9#24'x'#255#8#23'}'#255#8#23'}'#255#9#24#127#255#9#24'~'#255#7#24
+ +'}'#255#7#23'~'#255#9#24#128#255#8#23#130#255#7#23#129#255#8#23#132#255#7#22
+ +#131#255#7#21#132#255#6#20#132#255#7#21#133#255#7#20#132#255#6#22#133#255#7
+ +#23#130#255#8#23#129#255#9#24#128#255#8#24'|'#255#9#24'|'#255#6#22'z'#255#6
+ +#21'z'#255#9#21'|'#255#9#22#127#255#8#22#127#255#8#22#129#255#9#21#129#255#9
+ +#21#129#255#9#22#129#255#10#23#132#255#10#23#133#255#9#21#131#255#7#20#127
+ +#255#9#24'}'#255#8#25'u'#255#9#25'q'#255#13#25'k'#255#12#21'_'#255#9#18'W'
+ +#255#9#19'W'#255#11#20'W'#255#12#18'S'#255#10#17'P'#255#12#18'R'#255#10#16'P'
+ +#255#9#16'O'#255#11#17'Q'#255#11#17'Q'#255#12#19'R'#255#11#17'S'#255#11#17'R'
+ +#255#11#16'Q'#255#11#17'R'#255#8#15'Q'#255#9#17'R'#255#8#16'S'#255#8#15'S'
+ +#255#8#16'S'#255#10#18'P'#255#10#16'P'#255#10#16'R'#255#10#16'S'#255#10#14'S'
+ +#255#13#16'R'#254#13#16'O'#254#13#16'M'#253#14#17'J'#251#17#19'E'#250#22#18
+ +'<'#243#29#22'3'#183' '#21'-52'#31''''#10'<%)'#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0'O@B'#7'D=N'#143',,G'#230#24#29'L'#242#16#26'T'
+ +#248#17#29'c'#252#11#23'i'#255#8#20'j'#255#5#20'r'#255#10#22'x'#255#12#25'~'
+ +#255#11#25#130#255#10#25#133#255#8#25#133#255#8#25#135#255#9#25#137#255#9#22
+ +#135#255#11#24#134#255#11#23#134#255#10#23#131#255#11#25#129#255#9#24'~'#255
+ +#12#26'{'#255#11#24's'#255#12#23'q'#255#12#21'f'#255#10#19'b'#255#11#19'['
+ +#255#10#21'U'#255#9#18'Q'#255#11#19'T'#255#9#18'U'#255#6#12'S'#255#3#15'_'
+ +#255#10#20'o'#255#9#20'x'#255#8#22#128#255#9#21#128#255#9#22'~'#255#10#24#128
+ +#255#9#23#129#255#9#23#129#255#9#22#129#255#9#23#129#255#9#23#128#255#6#20'~'
+ +#255#9#22#129#255#8#21#129#255#10#22#132#255#6#23#129#255#9#21#129#255#8#21
+ +#128#255#10#21#130#255#8#22#128#255#8#22#127#255#8#23'|'#255#9#25'z'#255#13
+ +#26'k'#255#9#18']'#255#8#17'R'#255#11#18'K'#255#13#17'H'#255#13#17'I'#255#12
+ +#16'K'#255#13#16'K'#255#13#17'K'#255#14#18'L'#255#12#16'J'#255#12#16'J'#255
+ +#13#17'L'#255#15#19'N'#255#14#18'M'#255#13#17'L'#255#11#17'N'#255#11#16'M'
+ +#255#9#14'L'#255#10#16'L'#255#11#15'K'#255#9#15'J'#255#11#15'K'#255#13#16'L'
+ +#255#11#17'J'#255#13#17'K'#255#13#17'K'#255#12#16'L'#255#12#18'N'#255#10#17
+ +'L'#255#8#15'Q'#255#8#14'T'#255#4#14'Z'#255#5#16'a'#255#5#19'i'#255#6#22'u'
+ +#255#6#21'z'#255#8#23#127#255#6#21'|'#255#9#24#127#255#9#22#129#255#7#21#128
+ +#255#8#21#129#255#9#22#130#255#8#24#130#255#9#24#134#255#7#22#133#255#9#23
+ +#134#255#8#22#133#255#8#22#134#255#8#22#134#255#9#24#135#255#10#22#132#255#11
+ +#24#131#255#10#24#127#255#9#23'|'#255#11#23'}'#255#9#21'z'#255#9#21'{'#255#10
+ +#22'|'#255#7#20'~'#255#9#21#129#255#9#21#131#255#9#21#132#255#8#20#129#255#10
+ +#21#129#255#8#21#129#255#8#21#131#255#9#22#132#255#11#22#132#255#9#22#127#255
+ +#9#25'z'#255#12#24't'#255#15#27'p'#255#16#22'd'#255#14#20'Y'#255#11#18'T'#255
+ +#14#21'X'#255#8#17'T'#255#9#18'U'#255#10#16'T'#255#12#18'V'#255#12#19'V'#255
+ +#9#17'T'#255#9#17'T'#255#11#18'U'#255#12#16'V'#255#12#16'V'#255#11#16'T'#255
+ +#11#17'U'#255#10#16'T'#255#6#15'R'#255#10#17'T'#255#10#17'T'#255#10#17'T'#255
+ ,#10#17'S'#255#11#17'R'#255#10#17'R'#255#10#17'T'#255#11#15'T'#254#14#14'S'
+ +#254#17#17'O'#253#17#17'H'#251#22#19'D'#250#23#22'>'#248#26#22'5'#241#31#19
+ +'-'#173'!'#20',.0'#29'$'#7'=$.'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0'NCL'#0#0#0#0#0'SDO'#18'H?Ms/.K'#188#26#28'I'#224#14#21'N'#244#13
+ +#24'^'#252#13#24'f'#254#11#20'h'#255#6#18'g'#255#9#22'o'#255#9#24'v'#255#8#24
+ +'{'#255#9#25#127#255#10#26#132#255#9#24#133#255#8#22#134#255#12#26#132#255#10
+ +#24#129#255#9#23#128#255#8#24'{'#255#9#24'x'#255#13#26'r'#255#12#24'j'#255#12
+ +#23'd'#255#13#21'^'#255#11#19'Y'#255#11#17'T'#255#12#19'V'#255#13#20'T'#255
+ +#10#18'S'#255#8#15'T'#255#6#13'V'#255#4#16'f'#255#10#23'r'#255#8#22'z'#255#8
+ +#22'~'#255#7#24'~'#255#7#24'~'#255#7#24'~'#255#5#22'~'#255#8#22'~'#255#8#22
+ +#127#255#9#24'~'#255#8#24#129#255#8#23#129#255#8#23#130#255#7#22#128#255#8#23
+ +#131#255#7#22#129#255#9#22#129#255#7#20#128#255#10#23#130#255#9#23#129#255#7
+ +#22'~'#255#8#22'|'#255#8#25'y'#255#11#27'q'#255#10#23'd'#255#6#16'P'#255#12
+ +#19'J'#255#11#17'H'#255#11#18'J'#255#13#17'K'#255#14#18'I'#255#10#16'K'#255
+ +#12#17'M'#255#11#17'L'#255#12#18'K'#255#10#14'I'#255#13#18'J'#255#11#17'J'
+ +#255#10#16'L'#255#11#16'M'#255#10#16'L'#255#10#16'K'#255#12#16'L'#255#11#17
+ +'L'#255#11#17'K'#255#11#18'L'#255#10#18'L'#255#9#16'K'#255#8#17'K'#255#9#16
+ +'N'#255#8#16'M'#255#9#16'N'#255#6#15'P'#255#4#13'T'#255#6#14'Z'#255#3#16'h'
+ +#255#9#21'r'#255#9#23'w'#255#9#23'~'#255#9#23#128#255#9#22#130#255#9#23#129
+ +#255#10#23#130#255#9#22#129#255#7#21#129#255#8#21#131#255#9#22#131#255#7#21
+ +#133#255#8#22#133#255#8#22#134#255#9#22#133#255#8#22#131#255#7#22#132#255#7
+ +#22#132#255#10#24#133#255#9#23#128#255#10#24#128#255#9#25'|'#255#7#24'z'#255
+ +#8#21'x'#255#7#20'v'#255#8#22'{'#255#9#22'}'#255#7#19'~'#255#10#22#131#255#11
+ +#23#134#255#8#20#132#255#6#20#130#255#10#23#132#255#8#21#130#255#10#23#132
+ +#255#9#22#130#255#10#24#130#255#9#23#127#255#9#24'y'#255#11#27'p'#255#13#26
+ +'h'#255#11#20'\'#255#12#18'S'#255#12#19'R'#255#13#20'T'#255#11#18'S'#255#12
+ +#17'S'#255#11#16'U'#255#11#17'V'#255#11#19'T'#255#10#16'R'#255#10#16'R'#255
+ +#12#16'T'#255#12#16'S'#255#13#16'U'#255#11#13'U'#255#11#16'U'#255#10#15'R'
+ +#255#11#16'Q'#255#11#16'R'#255#11#16'S'#255#13#17'S'#255#11#15'R'#255#10#15
+ +'P'#255#12#17'Q'#254#11#16'P'#255#14#16'O'#253#14#16'M'#252#18#19'G'#249#23
+ +#19'<'#238#26#20'5'#232#28#19','#198#31#19'''\ '#19''''#21'*'#24'!'#4';#)'#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'PCN'
+ +#0#20#0#0#0'H:D'#5'E:H23.Ew '#31'?'#194#18#22'C'#231#14#22'R'#249#16#23']'
+ +#253#11#25'a'#254#9#24'd'#255#6#20'h'#255#4#20'k'#254#6#24's'#255#7#25'x'#255
+ +#8#24'y'#255#8#24#127#255#9#25'}'#255#7#23'z'#255#9#25'z'#255#9#25'r'#255#10
+ +#24'l'#255#12#25'g'#255#10#22'`'#255#11#21']'#255#10#19'W'#255#10#19'R'#255
+ +#10#16'P'#255#13#19'W'#255#13#19'V'#255#10#19'S'#255#6#14'R'#255#7#15'Z'#255
+ +#1#17'j'#255#8#22's'#255#8#24'y'#255#7#23'{'#255#6#25'|'#255#7#26'}'#255#6#24
+ +'~'#255#6#23'~'#255#5#24'|'#255#6#24'}'#255#8#25#128#255#8#24#130#255#6#24
+ +#130#255#6#24#130#255#6#23#129#255#6#24#129#255#7#23#128#255#7#24'~'#255#7#23
+ +'}'#255#9#25#127#255#8#24'~'#255#7#22'|'#255#8#25'{'#255#8#25'w'#255#8#27's'
+ +#255#11#27'j'#255#8#20'W'#255#9#18'L'#255#10#17'I'#255#10#18'K'#255#9#16'I'
+ +#255#11#17'H'#255#8#17'K'#255#6#17'L'#255#6#18'L'#255#6#16'L'#255#8#17'M'#255
+ +#8#17'L'#255#8#15'I'#255#12#19'K'#255#6#16'K'#255#7#15'J'#255#8#16'I'#255#8
+ +#16'I'#255#8#17'J'#255#10#18'J'#255#8#16'K'#255#7#16'L'#255#7#18'O'#255#8#16
+ +'R'#255#6#15'V'#255#6#14'Y'#255#5#16'\'#255#4#18'c'#255#4#19'g'#255#8#23'q'
+ +#255#7#24'w'#255#8#26'|'#255#6#24'|'#255#9#25#128#255#8#23#128#255#7#22#129
+ +#255#8#23#129#255#8#24#129#255#8#24#130#255#7#24#130#255#6#23#129#255#5#23
+ +#132#255#6#22#132#255#8#24#133#255#8#24#133#255#6#24#130#255#8#24#128#255#7
+ +#23#129#255#7#24#130#255#9#24#128#255#8#24'{'#255#9#26'y'#255#7#22'u'#255#8
+ +#20't'#255#7#22'r'#255#8#23'w'#255#8#24'x'#255#6#22'{'#255#6#21'|'#255#8#22
+ +#129#255#8#21#130#255#9#22#131#255#4#21#130#255#8#24#133#255#7#23#128#255#9
+ ,#23#128#255#7#23'}'#255#7#24'}'#255#8#25'{'#255#8#25'w'#255#13#27'n'#255#11
+ +#24'e'#255#8#18'X'#255#9#18'S'#255#10#20'R'#255#9#20'S'#255#9#19'S'#255#8#17
+ +'Q'#255#10#19'R'#255#10#19'S'#255#11#20'T'#255#7#17'P'#255#9#17'Q'#255#10#17
+ +'R'#255#9#16'R'#255#10#17'T'#255#9#15'S'#255#11#18'T'#255#10#18'Q'#255#9#18
+ +'P'#255#7#15'O'#255#8#16'Q'#255#9#17'Q'#255#9#17'Q'#255#9#19'Q'#255#7#18'M'
+ +#254#12#19'L'#253#17#19'G'#250#20#18'@'#228#25#20'7'#191' '#21'-'#144#31#17
+ +'#M&'#15'('#7'!'#18#24#3','#23#23#1'.'#19#26#0'0'#28'"'#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0'L;A'#7':2?%));k'#26#29'='#187#17#24'C'#246#9#21'P'#253#13#25'X'#253
+ +#10#22'^'#253#9#23'e'#254#9#24'j'#254#8#24'm'#255#7#23'n'#255#9#23'r'#255#10
+ +#25'q'#255#9#24'n'#255#10#25'k'#255#10#24'g'#255#9#22'`'#255#11#23'\'#255#11
+ +#21'X'#255#11#20'V'#255#8#17'T'#255#8#18'O'#255#11#18'P'#255#14#19'V'#255#11
+ +#18'S'#255#8#18'Q'#255#1#12'R'#255#7#17'`'#255#3#21'm'#255#6#22's'#255#8#24
+ +'y'#255#7#23'{'#255#5#25'{'#255#6#25'|'#255#6#24'}'#255#5#22'}'#255#4#24'~'
+ +#255#5#24#127#255#6#25#128#255#6#25#130#255#6#25#130#255#6#25#129#255#6#25
+ +#128#255#5#24#127#255#4#24'}'#255#4#25'|'#255#6#25'z'#255#8#27'}'#255#4#24'{'
+ +#255#5#25'{'#255#6#25'z'#255#6#27'w'#255#7#27't'#255#9#28'o'#255#9#26'c'#255
+ +#6#18'T'#255#6#17'L'#255#9#17'K'#255#8#17'J'#255#11#18'K'#255#6#16'L'#255#8
+ +#20'S'#255#9#24'\'#255#8#24'^'#255#5#21'^'#255#5#19'Z'#255#5#16'S'#255#8#17
+ +'P'#255#6#18'M'#255#6#17'L'#255#8#17'K'#255#9#17'K'#255#8#17'K'#255#9#17'L'
+ +#255#7#16'L'#255#8#17'O'#255#4#18'S'#255#8#21'_'#255#8#21'f'#255#8#22'p'#255
+ +#7#24'v'#255#6#26'{'#255#3#25'|'#255#4#27'~'#255#8#26'~'#255#6#24'~'#255#6#23
+ +'~'#255#6#23'~'#255#5#24#127#255#6#24#127#255#4#24'~'#255#6#26#127#255#4#24
+ +'~'#255#5#24#127#255#3#24'~'#255#4#26#129#255#6#27#131#255#4#26#129#255#5#25
+ +#127#255#6#25#127#255#6#25'}'#255#7#25#127#255#9#24'}'#255#9#25'z'#255#9#25
+ +'u'#255#7#24'r'#255#5#22'm'#255#8#22'o'#255#6#23't'#255#7#24'x'#255#5#22'x'
+ +#255#6#22'z'#255#8#25'~'#255#8#24'~'#255#7#23'}'#255#10#24#129#255#5#24#127
+ +#255#8#25#129#255#6#25'}'#255#6#25'}'#255#4#25'|'#255#3#26'z'#255#7#27't'#255
+ +#7#25'p'#255#11#28'h'#255#9#22'`'#255#7#18'V'#255#9#18'S'#255#9#19'S'#255#9
+ +#19'T'#255#9#18'S'#255#9#19'S'#255#9#20'R'#255#8#20'Q'#255#9#19'Q'#255#9#18
+ +'Q'#255#8#17'P'#255#8#17'Q'#255#8#17'P'#255#9#18'Q'#255#9#16'R'#255#10#18'T'
+ +#255#9#18'T'#255#8#17'S'#255#7#15'S'#255#9#15'T'#255#8#17'Q'#255#10#17'N'#254
+ +#9#19'L'#255#12#19'G'#250#20#21'@'#236#29#23'5'#181'!'#23'/F+'#18#21#7#0#0#0
+ +#0#0#0#0#0'#'#21#25#2#0#0#0#0''''#17#23#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0'3*7'#2'+'':'#28#31#31'6e'#21#23'8'#192#17#18'9'#253
+ +#19#23'G'#251#15#21'P'#252#11#22'V'#252#10#23'Z'#253#9#22']'#253#8#21'_'#254
+ +#9#21'^'#254#8#21'^'#254#9#21'['#255#9#20'X'#255#10#20'V'#255#12#21'V'#255#8
+ +#18'R'#255#9#19'S'#255#7#18'Q'#255#9#19'O'#255#11#19'N'#255#12#18'R'#255#7#16
+ +'P'#255#6#16'O'#255#0#12'S'#255#7#18'c'#255#3#22'o'#255#6#24't'#255#8#24'z'
+ +#255#8#23'}'#255#7#25'~'#255#7#24'~'#255#7#24#127#255#5#22#127#255#4#23#127
+ +#255#6#24#129#255#7#24#130#255#6#25#131#255#6#24#130#255#5#24#129#255#5#24
+ +#128#255#5#24#127#255#8#25'~'#255#7#26'~'#255#6#25'{'#255#6#25'{'#255#5#25'|'
+ +#255#6#24'|'#255#4#23'z'#255#7#26'z'#255#7#26'v'#255#7#27'r'#255#7#27'k'#255
+ +#8#24'^'#255#8#18'P'#255#10#17'K'#255#9#16'K'#255#9#17'L'#255#5#16'K'#255#8
+ +#18'Q'#255#4#18'W'#255#11#25'f'#255#11#27'm'#255#9#26'n'#255#8#23'l'#255#8#23
+ +'j'#255#6#19'`'#255#5#18'_'#255#4#17'Z'#255#5#16'X'#255#4#15'W'#255#3#14'V'
+ +#255#4#15'W'#255#6#16'Z'#255#2#17'^'#255#5#19'f'#255#4#19'n'#255#2#18's'#255
+ +#5#20'z'#255#5#24'}'#255#2#23'|'#255#6#25#128#255#4#21'|'#255#7#23#127#255#7
+ +#24#127#255#6#23'~'#255#7#23'~'#255#7#24#127#255#4#23'~'#255#6#25#128#255#4
+ +#22'~'#255#6#26#130#255#5#24#128#255#6#26#131#255#5#26#130#255#5#26#128#255#5
+ +#25#127#255#6#25'~'#255#6#25'{'#255#8#27'~'#255#7#25'y'#255#6#23't'#255#5#22
+ ,'o'#255#4#21'n'#255#4#21'n'#255#7#23'u'#255#7#23'z'#255#5#21'z'#255#4#20'z'
+ +#255#5#23'}'#255#7#25#129#255#6#24#128#255#4#22'~'#255#6#23#127#255#4#22'~'
+ +#255#6#23#127#255#6#24'~'#255#7#24'~'#255#7#27'~'#255#6#26'y'#255#9#26't'#255
+ +#10#25'm'#255#10#25'`'#255#7#18'W'#255#7#15'R'#255#10#16'Q'#255#9#17'T'#255#8
+ +#16'S'#255#7#17'Q'#255#9#17'Q'#255#9#18'R'#255#8#17'Q'#255#8#17'Q'#255#8#18
+ +'Q'#255#9#17'R'#255#8#15'P'#255#9#17'P'#255#10#18'Q'#255#9#16'P'#255#11#17'Q'
+ +#255#9#16'Q'#255#10#16'S'#255#8#15'R'#255#14#16'R'#255#15#17'L'#254#15#18'F'
+ +#255#20#19'>'#238#26#21'7'#165'!'#21'-J'#0#0#0#0#0#0#0#0'#'#18'"'#0#0#0#0#0
+ +'%'#21#20#0#0#0#0#0'%'#21#24#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'+*6'#2'# 5'#26' '#30'3d'#28#24'1'#202
+ +#20#20'4'#255#14#20'='#251#13#22'G'#251#10#20'L'#251#9#20'P'#252#10#20'U'#252
+ +#10#21'U'#253#11#20'T'#253#11#21'T'#254#10#19'R'#254#7#18'Q'#255#7#17'P'#255
+ +#9#19'T'#255#10#18'U'#255#9#19'R'#255#10#18'P'#255#10#18'O'#255#8#17'N'#255#5
+ +#15'P'#255#1#12'W'#255#6#17'f'#255#4#21'q'#255#7#24'w'#255#7#22'|'#255#8#23
+ +'}'#255#6#22'}'#255#6#24'}'#255#6#24'~'#255#7#23#128#255#4#21#128#255#5#22
+ +#130#255#6#22#129#255#6#23#130#255#6#23#130#255#6#23#130#255#5#23#127#255#7
+ +#25#130#255#8#25#127#255#7#26'~'#255#6#25'|'#255#6#25'|'#255#6#25'}'#255#5#24
+ +'|'#255#6#21'z'#255#7#23'{'#255#6#26'v'#255#7#26't'#255#6#26'p'#255#10#26'h'
+ +#255#7#18'W'#255#8#16'N'#255#8#16'K'#255#10#16'J'#255#6#15'H'#255#9#18'M'#255
+ +#6#16'Q'#255#6#18'Y'#255#11#25'g'#255#8#27'n'#255#7#25'u'#255#9#25'z'#255#7
+ +#26'v'#255#9#26'u'#255#7#23't'#255#5#21'q'#255#7#24'p'#255#6#23'p'#255#7#24
+ +'q'#255#7#23's'#255#7#23't'#255#6#23't'#255#7#23'z'#255#7#23'}'#255#7#23'|'
+ +#255#7#23'}'#255#7#23'~'#255#8#23#127#255#6#23'~'#255#7#25#127#255#6#23'~'
+ +#255#7#24#127#255#6#23'~'#255#7#25#127#255#7#25#127#255#8#25#127#255#4#24#127
+ +#255#6#23#128#255#3#22#128#255#5#24#130#255#5#24#130#255#6#26#131#255#7#25
+ +#128#255#5#23'~'#255#5#24'y'#255#8#26'{'#255#7#25'x'#255#5#21't'#255#3#21'q'
+ +#255#5#23't'#255#5#24'w'#255#6#25'{'#255#4#21'z'#255#5#21'{'#255#5#22'}'#255
+ +#6#24#127#255#6#24#129#255#7#24#129#255#4#23#127#255#6#23#127#255#7#22#129
+ +#255#8#23#129#255#8#23#127#255#6#23'~'#255#5#23'|'#255#6#23'x'#255#9#24'q'
+ +#255#11#26'k'#255#13#23'\'#255#6#16'S'#255#7#15'Q'#255#11#17'R'#255#10#16'R'
+ +#255#9#16'R'#255#10#17'R'#255#9#17'Q'#255#9#17'Q'#255#8#17'P'#255#8#16'P'#255
+ +#10#15'R'#255#10#16'S'#255#10#16'Q'#255#8#15'O'#255#9#17'P'#255#9#17'O'#255#9
+ +#16'N'#255#9#17'O'#255#10#18'P'#255#11#17'O'#255#15#16'I'#254#21#20'B'#244#21
+ +#18'='#138#23#19'8'#20#0#0#0#0#0#0#0#0'"'#19'$'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0',$5'#3'/&4'#8'("2D'#30#27'0'#171
+ +#22#22'3'#249#14#18';'#252#13#21'C'#251#12#21'I'#251#14#23'K'#251#11#21'M'
+ +#251#10#20'M'#252#8#17'L'#254#6#15'M'#255#8#17'P'#254#10#20'S'#255#9#18'Q'
+ +#255#8#18'P'#255#9#20'N'#255#10#17'L'#255#8#16'K'#255#6#14'R'#255#5#15']'#255
+ +#7#20'j'#255#4#21's'#255#8#23'y'#255#7#22'|'#255#8#23'}'#255#7#21'{'#255#5#24
+ +'|'#255#6#23'}'#255#7#23#128#255#5#24#128#255#5#24#128#255#8#24#128#255#6#23
+ +#127#255#7#23#128#255#7#25#127#255#5#24'|'#255#5#24'|'#255#5#23'|'#255#7#26
+ +'~'#255#7#26'~'#255#8#26'~'#255#7#25'}'#255#5#24'|'#255#5#21'z'#255#7#22'{'
+ +#255#5#25'z'#255#8#25'y'#255#6#24'r'#255#9#26'l'#255#9#23'a'#255#6#18'S'#255
+ +#6#17'L'#255#11#18'K'#255#9#17'J'#255#10#16'L'#255#8#16'N'#255#5#15'S'#255#3
+ +#16'X'#255#7#24'e'#255#7#24'r'#255#7#24'y'#255#8#26'y'#255#8#26'{'#255#8#22
+ +'~'#255#10#25#127#255#5#24'|'#255#6#25'|'#255#6#24'{'#255#6#25'|'#255#6#24'}'
+ +#255#6#24'}'#255#7#23#127#255#6#23#127#255#6#22#127#255#6#22#127#255#6#23#127
+ +#255#7#23#128#255#7#25'}'#255#6#25'}'#255#5#23'|'#255#7#26'~'#255#6#24'}'#255
+ +#6#24'}'#255#7#26'~'#255#8#26'~'#255#3#22'}'#255#6#23#128#255#5#22#128#255#6
+ ,#24#129#255#10#25#131#255#8#23#128#255#8#24'~'#255#8#25'}'#255#7#25'z'#255#5
+ +#22'w'#255#5#21'v'#255#5#21'w'#255#7#22'x'#255#9#24'|'#255#7#24'~'#255#6#25
+ +#128#255#6#23#127#255#6#23#127#255#7#23#127#255#6#23#127#255#6#23#127#255#6
+ +#24'~'#255#5#23'}'#255#6#23'~'#255#8#21#129#255#8#23#129#255#7#23#127#255#6
+ +#24'}'#255#5#25'|'#255#9#24'w'#255#12#25'q'#255#13#25'i'#255#12#21'Y'#255#7
+ +#16'S'#255#9#18'R'#255#9#18'R'#255#11#18'S'#255#9#15'P'#255#10#16'Q'#255#11
+ +#17'R'#255#10#16'P'#255#11#18'Q'#255#11#17'Q'#255#10#16'Q'#255#9#15'P'#255#10
+ +#15'Q'#255#7#16'P'#255#9#17'P'#255#9#17'N'#255#10#19'M'#255#11#18'L'#254#14
+ +#19'H'#254#16#19'D'#253#22#20';'#232#24#21'8;"'#22'+'#7#25#8#23#1'K8?'#2#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'$&9'#3')%8'' 4y'#23#26'3'#198#13#21'6'#224
+ +#14#22'7'#245#11#19'='#247#9#18'B'#249#9#18'G'#251#8#18'M'#253#10#19'R'#254#9
+ +#19'R'#255#11#19'N'#254#10#19'O'#255#9#19'M'#255#10#17'O'#255#6#14'N'#255#5
+ +#11'U'#255#5#16'd'#255#5#18'p'#255#5#21'w'#255#8#23'|'#255#8#23'}'#255#8#22
+ +#128#255#8#23'~'#255#6#23'~'#255#6#23'~'#255#5#21#127#255#3#22'~'#255#4#23
+ +#127#255#8#24#129#255#8#24#129#255#6#23#127#255#6#23#127#255#5#22'|'#255#8#26
+ +'~'#255#7#25'~'#255#7#25'~'#255#7#24'~'#255#7#23#128#255#6#23#127#255#7#23
+ +#128#255#7#22'}'#255#7#22'}'#255#8#22#128#255#10#25#127#255#4#22's'#255#4#24
+ +'m'#255#11#27'k'#255#10#22'`'#255#7#17'R'#255#7#18'K'#255#10#17'J'#255#9#16
+ +'I'#255#10#16'K'#255#11#17'O'#255#4#15'Q'#255#6#17'['#255#6#21'i'#255#3#21's'
+ +#255#7#23'{'#255#8#23'}'#255#9#22#130#255#9#23#129#255#8#23'~'#255#9#24#127
+ +#255#8#23#128#255#7#22#129#255#7#22#129#255#7#22#129#255#7#22#131#255#8#23
+ +#132#255#6#21#130#255#5#21#130#255#6#23#130#255#5#24#130#255#7#24#128#255#7
+ +#23#128#255#6#23#128#255#7#24#129#255#7#24#129#255#7#24#128#255#8#24#129#255
+ +#8#25#129#255#7#22#129#255#6#22#129#255#9#24#130#255#10#24#129#255#9#24#127
+ +#255#8#24'}'#255#10#26'}'#255#8#24'y'#255#8#21'w'#255#8#20'v'#255#9#21'z'#255
+ +#6#19'{'#255#8#20'~'#255#9#22#129#255#8#23#132#255#5#23#132#255#8#24#131#255
+ +#9#25#132#255#8#24#131#255#8#24#131#255#7#23#129#255#6#22#129#255#7#22#129
+ +#255#8#24#129#255#7#23#129#255#7#23#128#255#7#24'~'#255#7#25'}'#255#8#24'y'
+ +#255#12#27'v'#255#14#25'k'#255#11#23'a'#255#10#18'U'#255#10#16'S'#255#12#17
+ +'S'#255#11#17'R'#255#13#19'T'#255#10#16'Q'#255#12#18'S'#255#10#16'Q'#255#10
+ +#16'P'#255#11#17'P'#255#10#16'P'#255#10#16'Q'#255#11#17'Q'#255#11#17'Q'#255
+ +#10#18'P'#255#11#17'P'#255#9#17'K'#255#10#16'H'#254#14#18'E'#254#19#19'?'#253
+ +#23#22'9'#254#29#23'6N/"9)L:F(UAI'#18'T>H'#2#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'^>1'#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#30#26'('#27#23#23'(a'#20#18'('#173#18#21
+ +'5'#205#18#22'>'#230#16#21'E'#247#15#21'J'#253#13#20'L'#253#12#18'K'#254#13
+ +#20'N'#255#9#17'L'#254#9#17'N'#255#6#13'Q'#255#6#13'Z'#255#7#18'j'#255#3#20
+ +'r'#255#6#22'y'#255#8#22'}'#255#8#22#127#255#8#22#128#255#7#23'~'#255#6#23'~'
+ +#255#6#24'~'#255#7#23#128#255#6#25#131#255#6#24#131#255#8#22#133#255#6#21#132
+ +#255#8#24#131#255#9#25#132#255#8#24#130#255#7#24#127#255#6#24'}'#255#5#23'}'
+ +#255#6#22#128#255#7#23#129#255#7#23#130#255#9#25#132#255#9#23#130#255#8#22
+ +#128#255#8#24#131#255#7#23'~'#255#6#26'y'#255#2#22'p'#255#9#25'p'#255#14#27
+ +'l'#255#8#19'['#255#9#18'Q'#255#11#18'M'#255#10#16'K'#255#12#16'I'#255#13#16
+ +'K'#255#9#13'I'#255#8#17'S'#255#9#18'a'#255#10#22'n'#255#7#25'y'#255#8#24'{'
+ +#255#9#24#128#255#8#22#127#255#9#24'~'#255#8#23'}'#255#8#23'~'#255#9#22#129
+ +#255#6#22#129#255#6#23#129#255#7#22#131#255#8#23#133#255#5#23#134#255#6#23
+ +#134#255#7#24#135#255#8#25#135#255#7#22#133#255#7#23#133#255#6#22#132#255#8
+ ,#24#134#255#8#23#134#255#8#23#134#255#5#21#132#255#7#23#134#255#9#24#132#255
+ +#5#21#127#255#8#23#129#255#9#24#127#255#9#23'{'#255#10#25'|'#255#10#25'y'#255
+ +#8#22'v'#255#7#23'x'#255#7#23'{'#255#5#20'z'#255#8#21#128#255#9#22#132#255#9
+ +#23#133#255#8#23#133#255#8#23#132#255#6#22#129#255#7#23#129#255#6#22#129#255
+ +#7#23#130#255#6#22#129#255#6#22#129#255#6#22#128#255#6#22#129#255#6#22#128
+ +#255#6#22'~'#255#6#25'|'#255#8#25'z'#255#8#25'v'#255#14#26'r'#255#13#23'f'
+ +#255#11#20'Y'#255#11#16'S'#255#10#16'S'#255#11#17'R'#255#10#17'R'#255#11#17
+ +'R'#255#10#16'Q'#255#12#18'S'#255#10#17'R'#255#8#17'Q'#255#8#17'P'#255#10#17
+ +'P'#255#10#17'P'#255#10#18'O'#255#11#18'N'#255#11#17'J'#255#10#17'I'#255#12
+ +#17'I'#255#14#19'I'#255#16#20'D'#253#19#18'='#252#26#24';'#242'%'#31'>'#142
+ +'&'#31';)'''#29'8'#15'B3?'#11'K9B'#6'[EI'#2'jRS'#5'jTR'#1#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'f@.'#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'`8&'#0#0#0#0#0'g@/'#1'e=0'#1'_8*'#1'_:,'#1'Z6'
+ +'+'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'^>1'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#137'kM'#0#142'mN'#0'M<6'#12''' .%'#22#20'1b'#20#21'7'#150#17
+ +#21';'#212#15#20'?'#248#13#20'B'#252#14#21'G'#252#9#17'H'#254#8#17'K'#255#4
+ +#12'P'#255#6#15'['#255#7#20'i'#255#5#22'r'#255#4#23'y'#255#6#25'|'#255#6#24
+ +'|'#255#6#23#127#255#6#24'~'#255#6#23'~'#255#6#24'~'#255#5#23'}'#255#4#21'~'
+ +#255#6#23#128#255#8#24#130#255#7#23#129#255#7#23#129#255#7#23#129#255#5#22'~'
+ +#255#7#24#127#255#7#25'~'#255#7#25#127#255#6#22#128#255#7#23#129#255#6#21#132
+ +#255#7#23#131#255#8#22#130#255#7#22#127#255#7#24#128#255#6#23'~'#255#6#27'{'
+ +#255#4#23't'#255#4#22'p'#255#12#28'n'#255#12#25'e'#255#7#17'W'#255#11#16'P'
+ +#255#13#17'M'#255#14#16'L'#255#17#19'L'#255#14#17'K'#255#7#14'N'#255#4#11'S'
+ +#255#12#20'd'#255#8#26't'#255#7#25'w'#255#7#23'{'#255#8#22'|'#255#8#23'}'#255
+ +#8#22'|'#255#7#22'}'#255#8#24#127#255#6#23#127#255#6#22#128#255#6#22#128#255
+ +#7#23#129#255#5#22#131#255#4#21#131#255#6#23#133#255#6#23#133#255#4#23#131
+ +#255#7#24#133#255#5#23#131#255#6#24#133#255#5#22#133#255#8#25#135#255#5#22
+ +#133#255#6#23#134#255#5#24#128#255#7#24#128#255#6#23'}'#255#7#22'|'#255#8#25
+ +'{'#255#6#24'y'#255#4#20'u'#255#7#23'w'#255#5#22'x'#255#6#22'{'#255#7#22#127
+ +#255#6#20#128#255#7#23#131#255#6#22#131#255#8#25#132#255#5#23#129#255#5#22
+ +#129#255#7#24#130#255#6#23#129#255#7#24#130#255#6#23#130#255#7#23#130#255#7
+ +#23#129#255#7#23#130#255#7#24#130#255#7#23'~'#255#6#24'}'#255#8#26'{'#255#10
+ +#26't'#255#13#26'm'#255#10#20'a'#255#9#18'W'#255#10#15'S'#255#10#16'S'#255#12
+ +#16'S'#255#14#18'S'#255#11#18'R'#255#10#16'Q'#255#8#17'R'#255#8#17'S'#255#9
+ +#19'S'#255#9#18'R'#254#8#18'O'#255#10#20'N'#255#7#17'L'#255#10#19'L'#255#8#16
+ +'E'#255#10#18'F'#255#13#17'D'#255#12#15'A'#254#11#15'>'#253#10#13'9'#252#16
+ +#15'6'#250#22#18'3'#245#30#23'4'#207'%'#31'8'#154'4(='#187'@0A'#148'O'#8'iC2(iD2'#31'gB1'#1'`9'''#1#0#0#0#0#0#0#0#0'_9*'#1
+ +'kF:'#4'a;/'#2']8+'#1'T/'''#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'L94'#0#0#0#0#0#0#0#0#0'8/4'
+ +#13'-(5#'#29#30'5@'#20#26'5'#128#15#23'6'#223#13#22';'#251#11#18'A'#252#9#18
+ +'J'#254#4#14'U'#255#9#19'b'#255#7#18'n'#255#7#20'w'#255#5#24'{'#255#6#24'|'
+ +#255#4#22'|'#255#5#23'}'#255#6#23#127#255#6#22#129#255#8#25#129#255#7#23#128
+ +#255#7#24#127#255#7#24#127#255#6#22#128#255#8#24#130#255#7#23#129#255#8#24
+ +#130#255#5#23'}'#255#7#24#127#255#4#23'}'#255#7#25#128#255#5#22#129#255#9#24
+ +#134#255#8#22#132#255#8#22#129#255#7#22#128#255#7#22'|'#255#4#20'z'#255#8#26
+ +'}'#255#7#24'|'#255#7#24'z'#255#3#19'r'#255#6#22'm'#255#15#28'l'#255#10#23'd'
+ +#255#9#18'R'#255#10#15'N'#255#8#14'J'#255#12#18'K'#255#12#17'K'#255#8#16'L'
+ +#255#4#13'N'#255#6#15'T'#255#5#19'a'#255#9#24'k'#255#8#25's'#255#7#25'x'#255
+ +#6#23'|'#255#7#23'}'#255#4#22'{'#255#6#26#128#255#8#24#130#255#7#23#129#255#6
+ +#22#128#255#5#21#127#255#6#25#132#255#6#23#133#255#7#24#135#255#5#23#134#255
+ ,#3#21#132#255#5#22#133#255#5#22#133#255#8#25#135#255#5#22#133#255#6#22#132
+ +#255#6#23#132#255#7#24#132#255#8#24#130#255#7#23'~'#255#7#22'}'#255#9#25'}'
+ +#255#5#22'w'#255#5#22'x'#255#4#20'y'#255#10#25#127#255#6#22'}'#255#7#23#127
+ +#255#7#22#129#255#5#21#128#255#7#23#130#255#7#22#131#255#7#22#131#255#6#22
+ +#131#255#6#23#130#255#7#25#132#255#4#22#129#255#6#24#132#255#5#23#132#255#8
+ +#24#130#255#8#24#131#255#8#24#131#255#10#25#129#255#7#23'~'#255#7#23'|'#255#9
+ +#26'y'#255#8#25'p'#255#9#22'f'#255#9#19'^'#255#12#19'Y'#255#10#18'U'#255#11
+ +#18'U'#255#11#17'R'#255#10#16'Q'#255#10#17'Q'#255#11#19'Q'#255#9#18'Q'#255#9
+ +#18'R'#255#8#16'P'#255#10#17'O'#254#9#19'M'#254#11#21'I'#254#10#16'E'#253#13
+ +#18'D'#253#12#17'@'#253#15#19'='#254#14#18'?'#254#14#16'>'#253#15#17';'#252
+ +#16#18':'#251#19#18';'#249#21#19'7'#243#25#20'6'#240#28#21'2'#238#30#22'-'
+ +#238'$'#27'-'#241'2#1'#240'=*6'#158'A-8%Q9F'#1'9$)'#1#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#136'k\'#0#0#0#0#0#0#0#0#0'yXF#'#130
+ +'`R'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'<26'#0#0#0#0#0'G;<'#2'>8>'#18',,>%'#29'!@W'#22
+ +#28'@'#183#15#22'B'#249#8#16'G'#252#4#13'U'#254#9#19'c'#255#9#18'p'#255#8#22
+ +'x'#255#3#21'{'#255#6#23#127#255#7#23#129#255#7#23#130#255#7#23#130#255#7#23
+ +#130#255#7#23#130#255#5#21#129#255#6#23'}'#255#7#24#127#255#5#21#127#255#8#24
+ +#130#255#5#21#127#255#8#24#131#255#5#21#127#255#7#24#127#255#4#23#129#255#6
+ +#25#131#255#4#21#132#255#7#22#132#255#9#22#132#255#9#22#130#255#8#22#128#255
+ +#9#22#127#255#5#21'x'#255#10#24'}'#255#7#23'|'#255#9#24'}'#255#9#25'{'#255#4
+ +#21'r'#255#9#23'p'#255#13#26'p'#255#14#23'^'#255#9#16'V'#255#7#16'P'#255#12
+ +#17'M'#255#11#17'J'#255#13#18'M'#255#11#17'L'#255#11#18'P'#255#7#14'Q'#255#8
+ +#19'Z'#255#9#22'g'#255#9#25'r'#255#5#23'w'#255#7#25'{'#255#5#22'z'#255#6#25
+ +'~'#255#5#22'~'#255#6#22#127#255#7#22#128#255#7#22#129#255#8#22#130#255#8#21
+ +#131#255#7#21#130#255#6#20#131#255#4#20#131#255#8#24#134#255#6#23#131#255#8
+ +#25#133#255#6#20#129#255#9#23#132#255#7#20#129#255#10#22#131#255#10#22#127
+ +#255#9#23'~'#255#7#22'|'#255#5#21'y'#255#5#20'y'#255#8#23'}'#255#7#20#127#255
+ +#10#22#134#255#7#23#129#255#7#23#130#255#6#22#130#255#7#23#130#255#8#24#131
+ +#255#9#24#133#255#6#22#131#255#7#23#133#255#6#22#130#255#8#23#130#255#5#21
+ +#131#255#8#23#133#255#6#20#131#255#6#21#132#255#6#22#130#255#6#22#129#255#10
+ +#25#128#255#8#23'}'#255#9#23'z'#255#12#25'u'#255#12#23'l'#255#12#20'c'#255#10
+ +#19']'#255#12#18'Y'#255#13#19'W'#255#12#17'U'#255#11#16'V'#255#9#16'U'#255#9
+ +#16'U'#254#9#17'R'#255#10#17'P'#254#12#18'N'#253#12#18'M'#252#13#19'L'#251#13
+ +#18'E'#252#17#21'>'#250#16#18'7'#245#21#20'4'#240#23#21'/'#246#25#22'*'#200
+ +#28#23'('#221'#'#27'+'#231'$'#28','#213'&'#31'1'#212'*"2'#208'0%5'#202'0&5'
+ +#193'.#0'#186') ,'#172''''#28''''#162'%'#21' '#169'&'#21#29#152'+'#24#31'p-'
+ +#26' "/'#27' '#3#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#166#143#135#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0'*&='#0'.+='#11'&&A)'#31'"Fi'#22#27'I'#196#12#19'N'#247
+ +#5#15'W'#253#9#20'd'#254#7#19'r'#255#8#23'y'#255#5#22'}'#255#7#23#129#255#8
+ +#24#131#255#7#23#130#255#5#21#128#255#6#22#129#255#7#23#130#255#7#23#130#255
+ +#5#21#127#255#8#24#130#255#6#22#130#255#7#23#131#255#6#22#129#255#8#23#132
+ +#255#6#22#128#255#7#23#130#255#4#21#130#255#7#23#132#255#6#21#131#255#9#24
+ +#134#255#8#22#132#255#8#22#133#255#8#21#130#255#10#22#132#255#7#20'|'#255#7
+ +#20'~'#255#9#23#128#255#8#23#128#255#8#23'}'#255#5#22'x'#255#8#21'q'#255#9#24
+ +'q'#255#15#27'n'#255#11#20'c'#255#6#15'W'#255#13#18'S'#255#12#16'L'#255#14#17
+ +'K'#255#10#14'I'#255#12#17'L'#255#11#17'L'#255#9#16'N'#255#6#15'T'#255#8#20
+ +']'#255#11#22'e'#255#14#26'm'#255#11#26'r'#255#10#26'x'#255#8#25'y'#255#10#26
+ ,'{'#255#8#23'{'#255#9#25'|'#255#9#22'{'#255#11#23'}'#255#9#22'{'#255#10#23'|'
+ +#255#10#25'{'#255#11#26'{'#255#8#23'{'#255#10#25'}'#255#9#22'{'#255#11#24'}'
+ +#255#9#22'{'#255#10#23'|'#255#15#25'z'#255#9#21'w'#255#5#19'w'#255#8#21'|'
+ +#255#9#23#128#255#11#25#133#255#7#21#131#255#9#23#134#255#6#21#131#255#6#21
+ +#132#255#7#23#130#255#8#24#130#255#8#22#128#255#9#22#129#255#8#21#128#255#9
+ +#21#129#255#8#23#131#255#7#23#131#255#6#20#131#255#9#22#134#255#9#21#133#255
+ +#9#21#134#255#9#23#133#255#9#22#130#255#10#25#128#255#9#24'}'#255#10#24'z'
+ +#255#14#23'r'#255#11#17'f'#255#15#20'b'#255#12#19'\'#255#12#18'X'#255#13#18
+ +'W'#255#11#16'V'#255#9#15'W'#254#9#15'W'#255#11#18'V'#254#11#17'Q'#253#16#19
+ +'L'#252#19#19'F'#250#22#21'?'#251#24#21';'#228#24#20'4'#185#26#20'.w'#31#22
+ +'(5'''#27' '#30'0'#31#28'!'#0#0#0#0#0#0#0#0#232#167']'#1#0#0#0#0#255#251#160
+ +#0'UBF'#4']KQ'#2'r]]'#1#139'kb'#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'H/'
+ +'*'#5'@)'''#10'G2.'#0'U0'#28#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'~_N'#0#0#0#0#0#0#0#0#0#0#0#0#0#150'{p'#0#0
+ +#0#0#0#0#0#0#0'~]P'#0'uRD'#0'b>0'#0'U3$'#3'N- '#5'H*'#29#4'D('#28#4'?%'#26#10
+ +'?$'#24#9'D'''#27#6'@#'#24#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0'.)<'#1'*'';'#22'"#?X'#28' F'#186#16#22'O'#237#8#18
+ +'['#252#9#22'g'#254#3#19'q'#255#6#23'{'#255#6#22#127#255#6#22#128#255#7#23
+ +#129#255#7#23#130#255#6#23#132#255#6#23#132#255#6#23#131#255#6#23#131#255#5
+ +#21#130#255#6#22#133#255#6#21#133#255#7#23#133#255#6#22#133#255#6#21#132#255
+ +#5#21#132#255#5#22#130#255#7#22#130#255#8#24#132#255#6#20#131#255#7#21#132
+ +#255#7#22#133#255#7#21#133#255#7#22#132#255#7#22#133#255#9#22#130#255#6#20
+ +#128#255#8#22#129#255#7#23#128#255#7#22'~'#255#8#23'|'#255#8#22't'#255#5#19
+ +'n'#255#6#24'r'#255#12#26'r'#255#8#21'e'#255#7#19'\'#255#6#17'S'#255#8#16'P'
+ +#255#10#16'L'#255#13#18'L'#255#11#18'J'#255#10#17'I'#255#8#16'K'#255#8#17'L'
+ +#255#7#16'O'#255#11#19'W'#255#11#22'_'#255#11#23'e'#255#5#22'h'#255#8#24'k'
+ +#255#8#24'm'#255#13#27'q'#255#12#25'q'#255#12#26'r'#255#13#26'r'#255#13#26'p'
+ +#255#14#28'm'#255#14#26'n'#255#11#24'm'#255#10#26'o'#255#9#24'o'#255#8#21'm'
+ +#255#8#20'k'#255#7#19'h'#255#5#19'o'#255#7#21't'#255#7#21'x'#255#8#21'~'#255
+ +#7#21#129#255#8#23#132#255#6#21#131#255#7#23#132#255#6#22#131#255#8#23#133
+ +#255#8#23#132#255#8#23#132#255#8#23#129#255#7#22#128#255#9#24#130#255#7#23
+ +#129#255#7#23#129#255#7#23#131#255#5#20#129#255#8#24#133#255#8#23#134#255#9
+ +#22#134#255#8#22#131#255#9#23#130#255#10#22#129#255#10#23'}'#255#12#24'v'#255
+ +#13#21'm'#255#15#20'f'#255#15#20'`'#255#13#18']'#255#11#17'X'#254#11#17'U'
+ +#255#9#16'U'#255#8#16'T'#254#8#16'S'#253#9#16'Q'#252#15#20'L'#250#20#21'C'
+ +#247#24#21'<'#242#28#21'5'#184' '#22'2O%'#24'0'#22'5%6'#2#0#0#0#0'u[M'#2'u[O'
+ +#1'hOD'#0'ZIE'#0'gUT'#0#0#0#0#0#0#0#0#0#0#0#0#0'cQT'#0'gRS'#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#147#130'}'#0#193#184#179#2'|f`'#6'Y?:'#7'S<8'#0'T/'#27#6#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#168#146#137#0#0#0#0#0'wUE'#0'yWJ'#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0'Z3#'#0'G)'#29#2'I+'#30#1'=%'#28#1':'#31#20#1'F)'#28
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0'0,A'#2',(>1'#31#31'?'#182#21#28'M'#241#8#18'X'#253#10#23'j'#254#3#21
+ +'s'#255#8#24'|'#255#8#23#129#255#7#23#129#255#7#23#130#255#7#23#130#255#7#22
+ +#132#255#8#22#133#255#8#23#132#255#6#23#132#255#7#23#129#255#7#23#130#255#8
+ +#23#131#255#9#24#133#255#7#22#132#255#8#23#133#255#8#22#133#255#8#22#133#255
+ +#7#22#132#255#9#24#134#255#6#20#132#255#8#22#134#255#9#23#135#255#8#22#134
+ +#255#8#22#134#255#7#22#132#255#6#24#130#255#7#22#128#255#8#22#128#255#8#22
+ +#127#255#7#23#127#255#8#23#127#255#9#23'}'#255#8#21'w'#255#3#19'p'#255#8#21
+ +'r'#255#13#24'r'#255#12#23'o'#255#11#23'm'#255#11#22'g'#255#9#18']'#255#10#16
+ +'T'#255#9#15'O'#255#9#18'N'#255#7#15'L'#255#11#18'O'#255#7#17'K'#255#7#16'M'
+ +#255#6#14'K'#255#6#15'M'#255#6#15'N'#255#9#19'Q'#255#8#17'Q'#255#10#19'T'#255
+ ,#9#17'S'#255#9#17'S'#255#10#18'T'#255#9#18'R'#255#6#16'['#255#7#15'Z'#255#6
+ +#13'W'#255#8#13'W'#255#6#13'Z'#255#4#12'^'#255#4#13'd'#255#5#16'm'#255#7#22
+ +'x'#255#9#23'|'#255#8#22'|'#255#8#22'~'#255#7#22#129#255#7#23#130#255#7#22
+ +#131#255#6#23#131#255#5#20#131#255#7#21#132#255#6#20#132#255#8#22#133#255#9
+ +#21#130#255#10#23#129#255#9#22#129#255#9#20#130#255#5#21#130#255#9#24#133#255
+ +#7#22#131#255#8#23#134#255#5#22#133#255#8#22#134#255#8#24#130#255#8#23'~'#255
+ +#9#25'~'#255#11#25'y'#255#10#23'n'#255#13#22'g'#255#15#21'a'#255#13#18']'#254
+ +#12#19'Y'#255#10#17'V'#254#12#18'S'#253#11#18'R'#253#12#17'O'#252#14#18'L'
+ +#251#17#21'G'#244#19#17'>'#231#28#23'4'#206'$'#25'.'#148'*'#28',:5#-'#9'S>?'
+ +#3'lTM'#1'rYN'#3't\O'#1#0#0#0#0'tZM'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0'U0'#28#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'G('#28#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'L:D'#2'*)B'#135#30'$O'#241#7#18'P'#253#11#24
+ +'h'#255#5#23'q'#255#9#24'|'#255#8#22#128#255#9#23#129#255#8#24#131#255#8#24
+ +#131#255#7#23#130#255#8#24#130#255#8#24#131#255#8#23#130#255#6#22#128#255#5
+ +#21#127#255#6#22#129#255#7#23#130#255#6#21#131#255#7#22#132#255#6#20#133#255
+ +#7#21#133#255#4#21#129#255#6#23#132#255#5#20#132#255#7#23#134#255#8#23#135
+ +#255#7#23#134#255#6#23#132#255#5#22#130#255#5#24#131#255#8#23#129#255#7#22'~'
+ +#255#7#21'~'#255#7#23#130#255#6#22#129#255#8#24#130#255#10#24#129#255#7#23'w'
+ +#255#7#20'u'#255#6#18'u'#255#8#19'w'#255#11#24'}'#255#9#23'{'#255#8#24'u'#255
+ +#8#24'p'#255#12#20'g'#255#10#19'd'#255#6#15']'#255#7#15'Z'#255#6#14'V'#255#6
+ +#13'R'#255#7#14'Q'#255#9#16'S'#255#6#13'S'#255#9#16'V'#255#8#15'U'#255#8#15
+ +'U'#255#8#15'U'#255#7#14'T'#255#6#13'R'#255#7#14'R'#255#8#13'U'#255#7#13'U'
+ +#255#7#14'Y'#255#8#16'c'#255#7#17'l'#255#8#20's'#255#8#22'z'#255#7#22'}'#255
+ +#10#23#128#255#6#20#127#255#9#23#130#255#8#20#128#255#8#24#131#255#8#24#131
+ +#255#7#23#130#255#6#22#129#255#8#23#132#255#7#22#132#255#8#22#134#255#9#22
+ +#133#255#9#22#130#255#9#21#129#255#8#20#128#255#9#20#131#255#10#21#134#255#10
+ +#22#135#255#7#21#132#255#8#22#133#255#7#21#132#255#7#21#131#255#9#23#128#255
+ +#8#23'}'#255#8#23'x'#255#10#24's'#255#12#23'k'#255#11#20'e'#255#13#18']'#255
+ +#13#17'Y'#254#13#18'W'#252#13#17'T'#251#14#19'R'#251#15#19'L'#252#19#20'G'
+ +#245#24#21'A'#220#27#21';'#163'!'#21'2e1!0,O:B'#12'iST'#5'iRQ'#2#0#0#0#0#0#0
+ +#0#0'qXO'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'4-Dj03\'#252#13#23'U'#255#10#22'g'#255#6
+ +#24's'#255#9#25'~'#255#9#23#130#255#7#23#129#255#7#24#131#255#8#25#132#255#8
+ +#25#132#255#6#24#131#255#7#26#131#255#5#24#129#255#8#23#130#255#9#25#132#255
+ +#7#23#130#255#8#24#131#255#8#23#132#255#8#23#131#255#8#22#133#255#7#21#133
+ +#255#5#23#130#255#7#24#132#255#6#23#133#255#6#23#134#255#7#24#134#255#6#23
+ +#133#255#6#23#132#255#5#23#130#255#7#24#131#255#9#24#128#255#8#23'}'#255#6#21
+ +'{'#255#7#22'~'#255#6#23#129#255#7#24#128#255#9#24#128#255#7#22#127#255#10#24
+ +#128#255#9#21'{'#255#5#19'y'#255#6#23'}'#255#5#22'}'#255#6#24#127#255#7#25
+ +#128#255#12#24'}'#255#11#24'|'#255#9#22'y'#255#10#23'x'#255#9#22't'#255#10#23
+ +'t'#255#7#20'p'#255#8#21'q'#255#5#20'k'#255#6#21'l'#255#5#20'j'#255#5#20'j'
+ +#255#6#22'k'#255#7#22'l'#255#5#20'l'#255#5#20'l'#255#7#18'n'#255#7#19'q'#255
+ +#6#22'x'#255#5#23'~'#255#6#25#130#255#5#23#131#255#6#23#130#255#8#24#128#255
+ ,#6#21#128#255#7#22#128#255#9#23#131#255#7#23#130#255#8#24#131#255#6#22#129
+ +#255#7#23#130#255#6#22#129#255#8#24#130#255#7#23#129#255#7#23#131#255#8#22
+ +#131#255#10#24#131#255#10#23#130#255#10#22#130#255#9#21#131#255#10#22#133#255
+ +#9#22#132#255#8#22#130#255#7#23#129#255#8#23#130#255#9#23#128#255#8#23'}'#255
+ +#9#24'{'#255#9#23't'#255#12#23'p'#255#12#24'i'#255#11#21'c'#254#12#18'Z'#253
+ +#13#19'W'#251#12#18'Q'#251#12#18'L'#250#16#21'G'#249#20#21'A'#238#25#23';'
+ +#171#31#22'4V3$13I5;$ZEG'#12'v`_'#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0'>4K?+-U'#255#19#31'['#255#12#23'g'#255#6#25'u'#255#10
+ +#25'~'#255#7#25#129#255#7#25#131#255#7#24#130#255#7#24#131#255#6#23#128#255#6
+ +#24#129#255#5#25#128#255#5#24#129#255#7#26#133#255#5#24#131#255#5#24#131#255
+ +#6#23#132#255#6#23#132#255#5#23#132#255#5#23#132#255#5#23#131#255#6#22#129
+ +#255#6#23#131#255#5#22#132#255#6#23#133#255#7#24#134#255#5#22#133#255#5#22
+ +#133#255#5#23#130#255#7#23#129#255#9#24#127#255#9#23'}'#255#7#22'{'#255#6#21
+ +'z'#255#9#23'~'#255#7#23'~'#255#7#21#127#255#5#23#132#255#6#24#129#255#7#24
+ +#127#255#6#24'|'#255#5#22'}'#255#7#24#128#255#7#24#130#255#6#22#130#255#4#20
+ +#127#255#7#24#129#255#5#22'~'#255#7#23#128#255#6#22#127#255#5#23#127#255#5#23
+ +#130#255#5#24#130#255#9#24#129#255#8#23#128#255#8#22#129#255#8#22#130#255#8
+ +#22#131#255#10#23#133#255#8#22#133#255#9#23#133#255#7#24#135#255#7#23#133#255
+ +#9#24#132#255#8#23#127#255#9#22#127#255#8#23#128#255#8#24#130#255#5#21#130
+ +#255#7#22'}'#255#9#24#128#255#6#21#128#255#8#22#130#255#6#21#130#255#6#22#130
+ +#255#8#23#132#255#7#23#131#255#7#24#129#255#6#23#129#255#7#23#130#255#7#23
+ +#130#255#6#22#128#255#6#22#129#255#7#23#130#255#6#22#131#255#6#23#132#255#8
+ +#22#128#255#8#22'~'#255#9#22'~'#255#8#23#128#255#7#24'~'#255#9#25'|'#255#8#24
+ +'y'#255#9#23'r'#255#10#24'm'#255#8#22'c'#253#9#20'\'#252#10#19'V'#251#11#20
+ +'P'#250#14#20'J'#248#15#19'D'#240#22#23'<'#209#27#23'4'#137'#'#25'/=5%0'#27
+ +'L9>'#11'^KM'#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0'M;S'#0'C7H"45T'#255#19#31'S'#255#11#21'^'#255#4#25'p'#255#9#27'y'
+ +#255#7#25#127#255#6#23#127#255#7#23#128#255#8#24#130#255#8#25#127#255#8#25
+ +#127#255#4#23#128#255#6#24#130#255#4#24#130#255#3#24#130#255#6#24#130#255#6
+ +#23#130#255#9#26#132#255#8#24#133#255#7#23#131#255#8#24#132#255#8#23#129#255
+ +#9#23#131#255#7#23#132#255#8#24#134#255#4#22#132#255#6#22#133#255#7#24#134
+ +#255#6#22#129#255#7#24#130#255#9#24#129#255#8#23'~'#255#9#24'}'#255#5#20'y'
+ +#255#3#19'x'#255#8#23'}'#255#7#22'~'#255#5#24#131#255#6#24#130#255#5#23#129
+ +#255#5#23#129#255#7#25#132#255#8#24#133#255#8#24#134#255#7#23#134#255#6#23
+ +#129#255#7#24#131#255#6#23#130#255#7#24#131#255#6#23#130#255#6#23#129#255#6
+ +#23#129#255#7#25#130#255#9#26#128#255#5#22#127#255#7#23#129#255#7#23#130#255
+ +#7#22#132#255#9#24#134#255#8#23#132#255#7#23#132#255#4#22#134#255#5#22#134
+ +#255#6#23#132#255#6#23#130#255#7#23#128#255#8#24#129#255#8#24#130#255#7#23
+ +#130#255#6#21#127#255#7#23#130#255#7#23#131#255#7#22#133#255#7#21#132#255#7
+ +#20#132#255#8#21#134#255#7#22#134#255#8#23#133#255#8#22#133#255#8#24#132#255
+ ,#9#25#132#255#8#24#131#255#7#23#130#255#7#23#130#255#6#22#128#255#6#22#131
+ +#255#8#22#129#255#8#23#127#255#7#22'}'#255#9#24#127#255#6#23'|'#255#8#24'z'
+ +#254#8#24'w'#255#12#23'o'#253#13#21'g'#251#11#19']'#250#12#20'W'#249#14#17'Q'
+ +#247#20#21'H'#244#24#21'?'#228#29#21'8'#164' '#22'.K)'#27'+'#22'@,5'#8'R<>'#3
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0'82J'#219'%-Y'#255#9#20'U'#255#5#28'm'#255#7#27
+ +'t'#255#5#24'y'#255#7#25'~'#255#7#24#127#255#7#23#129#255#6#23#127#255#8#24
+ +#129#255#4#24#128#255#5#22#130#255#6#25#129#255#6#25#130#255#8#24#130#255#7
+ +#23#128#255#6#23#127#255#6#22#128#255#8#22#128#255#9#23#129#255#7#21#127#255
+ +#8#21#129#255#8#22#130#255#8#24#133#255#8#23#133#255#5#20#130#255#6#22#129
+ +#255#10#22#130#255#6#21#131#255#7#23#129#255#7#22#127#255#10#25#127#255#7#22
+ +'|'#255#4#20'y'#255#4#20'x'#255#6#23'y'#255#5#22#129#255#6#23#130#255#5#22
+ +#129#255#3#21#128#255#4#21#131#255#5#22#132#255#6#23#134#255#8#25#136#255#6
+ +#24#131#255#3#21#128#255#5#23#130#255#6#24#131#255#6#24#131#255#5#23#130#255
+ +#5#22#131#255#7#24#133#255#9#24#131#255#7#23#128#255#6#22#128#255#7#23#130
+ +#255#6#22#130#255#7#22#132#255#8#22#134#255#7#21#134#255#5#24#139#255#4#23
+ +#136#255#5#25#136#255#7#24#134#255#4#22#129#255#5#22#129#255#7#22#129#255#7
+ +#23#130#255#7#23#130#255#7#23#130#255#7#22#132#255#8#22#134#255#6#23#135#255
+ +#5#22#135#255#5#22#135#255#3#21#135#255#4#21#132#255#5#22#134#255#6#22#132
+ +#255#8#23#131#255#7#23#130#255#6#22#129#255#8#24#130#255#7#23#129#255#7#22
+ +#132#255#9#22#130#255#9#22#128#255#9#23#129#255#10#22#127#254#9#24'}'#255#8
+ +#24'u'#253#12#26'o'#250#12#22'e'#249#12#21']'#248#11#19'T'#247#16#21'M'#246
+ +#22#23'F'#239#28#22'<'#197'"'#22'3j*'#27'.%9%,'#14'C.3'#3#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0'E:OC.0T'#255#19#30'Y'#255#5#28'j'#255#9#27't'#255#6
+ +#25'z'#255#8#26#128#255#9#25#130#255#7#23#131#255#7#23#130#255#8#24#131#255#5
+ +#23#130#255#5#23#130#255#6#23#132#255#7#25#132#255#8#25#131#255#6#24#127#255
+ +#7#23'~'#255#7#24#127#255#6#22#128#255#10#25#132#255#9#23#129#255#9#23#129
+ +#255#8#23#130#255#8#24#131#255#8#23#133#255#7#23#130#255#8#24#131#255#7#22
+ +#129#255#7#22#132#255#7#23#133#255#5#22#130#255#7#24#132#255#8#24#129#255#9
+ +#24'~'#255#7#22'{'#255#6#21'w'#255#8#23'}'#255#9#24#127#255#8#24#130#255#8#23
+ +#130#255#8#22#132#255#7#23#133#255#7#23#133#255#7#23#134#255#6#24#129#255#7
+ +#25#130#255#6#23#129#255#7#24#131#255#5#22#129#255#5#22#130#255#6#22#131#255
+ +#6#22#133#255#8#24#130#255#8#24#131#255#6#22#129#255#7#23#130#255#8#24#131
+ +#255#8#23#133#255#9#23#135#255#7#21#134#255#6#22#135#255#6#21#134#255#7#22
+ +#134#255#8#24#134#255#7#23#133#255#5#23#130#255#5#24#131#255#8#25#132#255#9
+ +#24#131#255#7#24#131#255#7#23#130#255#8#23#134#255#8#22#133#255#9#23#134#255
+ +#8#22#133#255#7#23#134#255#6#24#132#255#7#24#133#255#7#24#133#255#5#24#131
+ +#255#9#25#133#255#11#26#135#255#9#24#133#255#8#23#132#255#6#23#132#255#8#24
+ +#131#255#11#24#130#254#9#22'~'#255#10#23'|'#253#9#25'w'#250#10#24'o'#249#12
+ ,#25'g'#248#10#22'^'#247#11#22'S'#246#16#22'G'#243#22#22'>'#220#27#22'4'#160
+ +'!'#23'/F2#2'#27'@09'#6#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'L'
+ +';I'#0'K8A'#6';7S'#245#25#31'T'#255#12#28'g'#255#13#28's'#255#8#26#127#255#8
+ +#24'~'#255#9#26#131#255#9#22#133#255#9#23#133#255#9#23#133#255#9#24#134#255#7
+ +#23#133#255#7#22#133#255#7#23#134#255#6#23#131#255#7#24#131#255#8#24#130#255
+ +#9#23#129#255#7#22#129#255#9#24#132#255#8#23#131#255#9#23#132#255#8#23#133
+ +#255#7#22#133#255#6#22#132#255#8#23#132#255#9#24#133#255#8#23#132#255#6#23
+ +#133#255#7#23#134#255#6#21#133#255#8#22#133#255#9#24#132#255#10#23#130#255#12
+ +#25#130#255#6#21'z'#255#6#18'v'#255#8#21'y'#255#10#23'~'#255#9#22#130#255#9
+ +#22#132#255#8#22#133#255#9#23#134#255#10#23#135#255#7#23#129#255#9#25#132#255
+ +#7#23#129#255#7#23#129#255#6#22#130#255#6#22#130#255#8#23#133#255#8#24#133
+ +#255#7#22#131#255#8#24#133#255#7#23#131#255#7#23#132#255#8#24#132#255#7#22
+ +#132#255#9#24#135#255#8#22#135#255#10#23#134#255#9#22#133#255#8#22#132#255#8
+ +#23#134#255#7#22#133#255#6#22#132#255#6#22#131#255#7#23#132#255#9#23#132#255
+ +#7#21#130#255#8#22#131#255#10#24#133#255#6#22#130#255#7#23#131#255#7#23#131
+ +#255#7#23#131#255#6#23#131#255#7#23#132#255#8#24#133#255#6#22#132#255#8#22
+ +#134#255#9#23#136#255#8#22#134#255#7#22#134#255#6#23#132#254#6#24#131#255#9
+ +#23#127#254#9#23'~'#252#11#23'{'#250#13#25'u'#248#13#24'k'#247#14#23'_'#246
+ +#12#21'P'#243#15#22'F'#230#21#21';'#192#28#23'2s* .3A3<'#22'K'#3#0#0#0#0'F'
+ +'6='#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'C6Jg31Y'
+ +#255#14#19'T'#255#15#26'f'#255#9#24'|'#255#7#22'|'#255#8#24#130#255#10#23#135
+ +#255#10#22#134#255#10#21#134#255#10#21#134#255#8#23#136#255#8#22#135#255#8#22
+ +#134#255#8#22#134#255#8#22#134#255#11#24#132#255#9#22#130#255#8#22#129#255#9
+ +#23#129#255#8#23#133#255#7#22#133#255#7#21#133#255#7#21#133#255#7#21#134#255
+ +#9#23#136#255#8#22#134#255#9#23#134#255#8#21#134#255#9#23#135#255#7#21#133
+ +#255#10#22#134#255#11#24#134#255#9#21#129#255#9#22#128#255#9#22'}'#255#10#20
+ +'x'#255#7#20'x'#255#7#21'{'#255#8#22#127#255#11#24#133#255#8#22#133#255#6#21
+ +#132#255#8#21#133#255#10#22#133#255#9#21#132#255#10#23#133#255#11#24#134#255
+ +#9#21#132#255#9#21#133#255#9#21#133#255#10#21#135#255#11#23#135#255#11#23#135
+ +#255#10#23#132#255#9#21#131#255#10#23#133#255#9#21#132#255#10#22#134#255#10
+ +#21#134#255#7#20#132#255#9#22#134#255#9#22#134#255#9#22#134#255#9#22#134#255
+ +#10#23#135#255#9#22#135#255#9#21#134#255#10#23#133#255#10#22#132#255#9#22#132
+ +#255#10#22#134#255#9#21#133#255#10#21#134#255#10#21#135#255#10#21#134#255#9
+ +#22#134#255#9#23#135#255#8#21#134#255#9#22#138#255#10#22#137#255#10#21#136
+ +#255#9#20#134#255#10#20#134#255#11#22#134#254#10#22#132#252#12#21'~'#252#12
+ +#22'|'#249#16#23'w'#248#18#23'l'#246#17#22'^'#244#19#23'M'#230#23#25'?'#186
+ +#21#21'5k!'#26'/1=2<'#30'UFJ'#13'aQR'#1#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ ,#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'I8A'#0#148'3'#0#0'?7O'#170'"#S'#255#11
+ +#22'T'#255#10#26'r'#255#11#27'{'#255#8#23#129#255#9#24#134#255#10#22#134#255
+ +#10#22#133#255#10#22#133#255#9#23#135#255#10#24#137#255#8#22#135#255#10#24
+ +#137#255#10#23#135#255#10#23#134#255#10#23#132#255#8#22#129#255#10#23#129#255
+ +#7#22#132#255#8#22#133#255#8#23#134#255#7#22#133#255#8#22#134#255#7#22#134
+ +#255#6#22#134#255#5#22#134#255#7#21#133#255#9#22#135#255#9#22#134#255#9#21
+ +#133#255#6#21#131#255#10#23#132#255#9#22#130#255#9#21#128#255#11#24'~'#255#8
+ +#22'{'#255#6#21'{'#255#5#20'{'#255#8#23#127#255#8#22#128#255#8#24#129#255#9
+ +#24#132#255#11#24#133#255#9#22#132#255#10#22#133#255#11#23#134#255#9#21#133
+ +#255#9#21#133#255#10#21#134#255#10#21#135#255#12#25#136#255#10#22#133#255#10
+ +#22#133#255#10#23#133#255#12#25#135#255#10#21#134#255#10#20#135#255#10#21#135
+ +#255#8#20#132#255#10#21#133#255#9#21#133#255#11#22#134#255#11#22#134#255#10
+ +#21#134#255#10#21#134#255#11#22#135#255#10#23#132#255#10#23#132#255#9#22#132
+ +#255#11#24#135#255#10#22#134#255#11#22#134#255#11#22#135#255#10#20#135#255#10
+ +#21#135#255#13#23#138#255#9#19#136#255#13#22#139#255#11#22#138#255#10#21#136
+ +#255#10#21#135#255#11#22#135#255#11#22#135#254#12#22#132#253#14#23'~'#250#16
+ +#22'w'#248#19#25'k'#246#20#23'Y'#241#22#24'J'#207#24#24'>k'#31#27'03*#2-6,8'
+ +#29'>4<'#3#0#0#0#0'WKO'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'E:F'#19'0.R'#233#20#31'T'#255#5#21
+ +']'#255#10#28'q'#255#12#27#128#255#8#22#129#255#8#23#127#255#8#23#128#255#6
+ +#23#129#255#7#22#134#255#5#24#132#255#5#23#132#255#7#23#135#255#7#23#134#255
+ +#7#22#133#255#8#23#133#255#7#22#129#255#7#22#128#255#7#24#130#255#8#24#130
+ +#255#8#24#130#255#7#24#130#255#6#25#131#255#5#22#131#255#6#23#133#255#4#21
+ +#132#255#6#23#134#255#7#24#135#255#7#25#136#255#7#24#135#255#6#25#134#255#7
+ +#23#133#255#7#23#133#255#7#23#133#255#5#24#131#255#7#24#129#255#8#24'~'#255#8
+ +#23'}'#255#5#20'y'#255#5#19'x'#255#7#20'x'#255#10#25'|'#255#8#23'~'#255#8#23
+ +#127#255#9#22#129#255#9#22#130#255#8#23#131#255#7#22#130#255#7#22#130#255#9
+ +#24#132#255#5#22#128#255#6#23#130#255#6#23#130#255#6#23#130#255#5#22#129#255
+ +#6#22#132#255#7#23#134#255#8#23#135#255#8#22#134#255#7#21#133#255#6#20#132
+ +#255#8#22#134#255#10#25#135#255#6#22#130#255#7#23#131#255#6#22#130#255#7#22
+ +#129#255#9#23#131#255#7#21#129#255#9#23#132#255#9#23#134#255#8#21#133#255#8
+ +#22#133#255#8#22#133#255#8#21#133#255#9#23#135#255#9#21#134#255#8#22#134#255
+ +#9#22#133#255#8#21#132#255#10#23#132#255#10#23#132#255#9#22#130#253#9#22'z'
+ +#251#14#26's'#248#16#27'd'#247#21#26'S'#240#23#25'E'#187#26#25'7J(#18*"1<3)2'
+ +#20#255#255#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ ,#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'=8R'#145'%*'
+ +'R'#255#13#26'Z'#255#11#25'e'#255#11#27'w'#255#8#26#127#255#4#24#127#255#7#25
+ +#129#255#6#25#130#255#7#24#134#255#5#24#131#255#6#25#133#255#6#23#134#255#6
+ +#23#134#255#7#24#135#255#6#23#133#255#7#24#132#255#7#24#132#255#9#24#133#255
+ +#8#23#132#255#6#22#130#255#6#23#131#255#7#25#133#255#7#25#132#255#6#24#132
+ +#255#5#22#132#255#4#21#135#255#7#24#136#255#6#23#137#255#6#24#136#255#4#23
+ +#133#255#6#25#135#255#7#26#136#255#4#23#133#255#5#24#132#255#4#23#130#255#7
+ +#25#130#255#10#26#128#255#11#27'~'#255#6#21'y'#255#4#18't'#255#5#20't'#255#5
+ +#21'w'#255#8#22'{'#255#8#23'}'#255#8#22#127#255#9#24#130#255#8#22#129#255#6
+ +#21#129#255#8#24#130#255#4#23#131#255#6#25#132#255#5#24#130#255#6#25#131#255
+ +#5#21#128#255#7#24#132#255#8#24#133#255#8#25#134#255#7#23#135#255#7#23#135
+ +#255#6#22#134#255#6#22#133#255#6#23#131#255#5#21#130#255#6#23#130#255#7#25
+ +#132#255#7#22#132#255#9#24#134#255#7#22#132#255#9#23#133#255#9#24#132#255#8
+ +#22#130#255#8#23#131#255#10#24#133#255#6#22#133#255#8#22#134#255#7#22#134#255
+ +#7#21#133#255#5#21#132#255#5#24#132#255#8#25#131#254#7#24#127#254#12#26'y'
+ +#251#12#26'n'#250#18#27'^'#248#20#27'M'#241#25#27'>'#176#26#24'2D(#20*#0(0'''
+ +'2'#6#0#0#0#0'7-8'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'I=O+;6N'
+ +#255#21#31'N'#255#14#24'U'#255#7#24'g'#255#9#28'y'#255#6#25'~'#255#7#23#128
+ +#255#8#24#128#255#7#24#129#255#6#23#134#255#6#23#133#255#7#24#135#255#5#22
+ +#133#255#7#25#131#255#7#25#131#255#6#24#131#255#6#23#133#255#7#22#132#255#9
+ +#23#133#255#7#23#133#255#7#24#134#255#6#23#133#255#5#22#133#255#5#22#133#255
+ +#5#22#132#255#6#23#133#255#7#24#135#255#6#23#134#255#8#24#136#255#5#22#133
+ +#255#6#23#133#255#7#24#135#255#6#23#134#255#7#24#135#255#6#23#134#255#4#22
+ +#131#255#6#23#130#255#8#24#129#255#8#23#128#255#8#24#127#255#9#25#127#255#8
+ +#21'{'#255#6#19'y'#255#4#18'x'#255#4#17'y'#255#6#21#127#255#8#22#129#255#7#23
+ +#129#255#7#24#129#255#6#21#130#255#8#24#129#255#7#24#128#255#8#25#128#255#5
+ +#23'}'#255#6#22#127#255#5#21#127#255#6#22#129#255#6#21#132#255#7#21#133#255#7
+ +#21#133#255#7#21#132#255#8#23#133#255#8#23#133#255#7#22#132#255#9#23#134#255
+ +#6#22#134#255#7#23#135#255#6#22#134#255#7#21#133#255#8#22#133#255#6#21#131
+ +#255#9#23#133#255#7#21#131#255#5#20#131#255#8#22#133#255#10#22#133#255#9#22
+ +#133#255#8#23#132#255#5#22#128#254#8#23'z'#254#11#26'w'#253#18#31'j'#251#17
+ +#27'X'#250#21#26'E'#238#21#24'5'#134#25#24'.!)$1'#23'*%/'#14',#,'#1#0#0#0#0
+ +'929'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ ,#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'O=D'#0#0#0#0#0'M$3.J'#238'!&V'#254#10#23'Y'#255#7#26'm'#255#10#27'z'#255
+ +#6#26#128#255#7#26#131#255#8#26#133#255#6#23#134#255#6#24#132#255#6#24#132
+ +#255#7#26#132#255#8#25#132#255#4#23#128#255#6#25#130#255#6#24#132#255#6#26
+ +#132#255#5#24#129#255#6#25#130#255#6#23#127#255#9#25#127#255#7#25#132#255#6
+ +#25#131#255#7#25#133#255#8#26#133#255#6#24#131#255#7#24#133#255#6#23#132#255
+ +#5#23#132#255#6#25#134#255#5#24#133#255#7#24#132#255#7#25#131#255#7#24#131
+ +#255#6#24#131#255#6#25#133#255#7#25#134#255#4#22#137#255#4#22#137#255#5#23
+ +#138#255#7#24#139#255#6#23#137#255#7#23#136#255#8#24#136#255#8#25#135#255#5
+ +#26#132#255#6#27#133#255#4#25#131#255#4#25#130#255#6#26#130#255#4#24#130#255
+ +#7#25#130#255#6#24#129#255#6#23#134#255#7#24#134#255#4#21#131#255#7#23#135
+ +#255#6#23#135#255#6#21#133#255#8#24#135#255#9#24#136#255#5#21#133#255#7#25
+ +#134#255#4#25#133#255#6#26#132#255#4#24#132#255#4#23#131#255#6#24#132#255#6
+ +#23#129#254#6#26#129#255#8#25'}'#254#12#27's'#253#15#28'b'#251#21#28'Q'#241
+ +#26#28'@'#209'%&:'#132'LKU'#15#0#0#0#0'IHR'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'I1;'#0#0#0#0#0'=.<,21K'#254#31'(T'#255#7
+ +#23'W'#255#8#28'f'#255#7#28'v'#255#8#27'y'#255#6#27'|'#255#6#25#127#255#7#27
+ +#128#255#7#28'~'#255#6#28'~'#255#7#27'~'#255#6#27'|'#255#6#27'|'#255#5#26'z'
+ +#255#7#26'}'#255#7#27'~'#255#6#27'|'#255#5#26'z'#255#5#25'y'#255#5#28'{'#255
+ ,#6#28'|'#255#5#26'|'#255#7#28#127#255#5#25'}'#255#7#28#128#255#6#27#128#255#6
+ +#26#129#255#6#27#129#255#6#27#128#255#6#28#127#255#8#28#127#255#7#27'}'#255#4
+ +#26'|'#255#5#28'~'#255#6#28#127#255#5#27#129#255#5#27#128#255#6#28#129#255#6
+ +#28#129#255#7#30#128#255#3#27'|'#255#7#28'|'#255#6#28'{'#255#5#30#127#255#6
+ +#30#128#255#5#28'~'#255#4#27'|'#255#3#26'|'#255#5#28'~'#255#4#25'|'#255#6#26
+ +'}'#255#5#26'{'#255#8#29'}'#255#5#25'{'#255#8#26'~'#255#9#25#127#255#8#25#127
+ +#255#9#25#128#255#9#26#128#255#7#24#127#255#7#26#128#255#6#26'|'#255#4#26'z'
+ +#255#7#28'|'#255#7#28'|'#255#6#26'z'#254#7#27'x'#254#10#28'v'#252#13#28'm'
+ +#251#15#27'^'#249#20#29'N'#239#29' @'#206'++?qSP]'#21'OQa'#4#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +'D5='#0'1#'#27#0'30='#180':?U'#254'!.R'#255#17#31'L'#255#19'%^'#255#21'''e'
+ +#255#19'&j'#255#17'&m'#255#15'#j'#255#16'%j'#255#14'$g'#255#17'$i'#255#18'$e'
+ +#255#18'$e'#255#16' d'#255#16' e'#255#17'!g'#255#16' g'#255#13'!f'#255#13' e'
+ +#255#14'$h'#255#16'&j'#255#11' e'#255#15'%j'#255#15'$j'#255#16'%l'#255#15'$j'
+ +#255#14'"j'#255#15'#h'#255#15'#i'#255#15'#h'#255#15'"f'#255#18'$h'#255#16'#h'
+ +#255#15'#i'#255#17'%k'#255#18'$o'#255#16'"o'#255#19'$q'#255#16'"n'#255#17'#p'
+ +#255#14#31'j'#255#17'"m'#255#17'!k'#255#16'$j'#255#18'&l'#255#12' f'#255#17
+ +'"g'#255#17'#g'#255#18'%h'#255#18'$g'#255#20'%f'#255#18'#b'#255#19'$c'#255#19
+ +'$e'#255#17'$e'#255#19'%f'#255#18'"h'#255#19'%l'#255#17'"k'#255#18'"j'#255#16
+ +'"f'#255#17'%h'#255#16'$f'#255#15'"h'#254#16'#h'#252#18'#g'#251#19'%e'#251#19
+ +'#\'#250#25'#T'#250#28' G'#239'%&B'#210'55F'#145'HIW@HM_'#28' +N'#6#27'''K'#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'SD;'#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'PD:'#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0'1-2@.0:'#128'17J'#127#30'"='#127#12#27';'#127#18'"F'#127
+ +#20'&O'#127#18'$R'#127#18'$R'#127#18'%Q'#127#18'$N'#127#21'&P'#127#19'"E'#127
+ +#22'%I'#127#20'#I'#127#18' I'#127#20#31'J'#127#19#31'J'#127#20'#M'#127#20'$N'
+ +#127#20'#L'#127#19'#L'#127#15#30'H'#127#19'#L'#127#20'#M'#127#20'$M'#127#20
+ +'#L'#127#20'#L'#127#21'&N'#127#21'&N'#127#20'%M'#127#20'#L'#127#17'!J'#127#23
+ +'&O'#127#18'#M'#127#20'#P'#127#20'&M'#127#18'$K'#127#20'%N'#127#17'!J'#127#25
+ +'(T'#127#17'"J'#127#20'$M'#127#18'"K'#127#22'$Q'#127#22'&P'#127#14#30'H'#127
+ +#21'"K'#127#22'$J'#127#23'&J'#127#24'''K'#127#20'$G'#127#24'$I'#127#18'"F'
+ +#127#20'$H'#127#21'$H'#127#16'!F'#127#17'"L'#127#20'$R'#127#21'$R'#127#19'#M'
+ +#127#16' J'#127#20'&N'#127#21'&P~'#19'#P}'#20'$Q~'#18'"O}'#20'#H}'#20'!>}'#22
+ +#30'8{'#31'#7u-1Cf@BUM8>Y0'#26'&K'#27#27'''K'#15#27'''K'#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ ,#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'SD;'#2#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0'PD:'#15#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ ,#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ ,#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+]);
+
diff --git a/branches/script-component/Projects/SAMufasaGUI/simbasettings.lfm b/branches/script-component/Projects/SAMufasaGUI/simbasettings.lfm
new file mode 100644
index 0000000..a5f924b
--- /dev/null
+++ b/branches/script-component/Projects/SAMufasaGUI/simbasettings.lfm
@@ -0,0 +1,46 @@
+object SettingsForm: TSettingsForm
+ Left = 563
+ Height = 558
+ Top = 173
+ Width = 360
+ ActiveControl = SettingsTreeView
+ Caption = 'Simba Settings'
+ ClientHeight = 558
+ ClientWidth = 360
+ OnCreate = FormCreate
+ OnDestroy = FormDestroy
+ LCLVersion = '0.9.29'
+ object SettingsTreeView: TTreeView
+ Left = 16
+ Height = 473
+ Top = 16
+ Width = 324
+ Anchors = [akTop, akLeft, akRight, akBottom]
+ DefaultItemHeight = 19
+ ReadOnly = True
+ ScrollBars = ssAutoBoth
+ TabOrder = 0
+ OnDblClick = SettingsTreeViewDblClick
+ Options = [tvoAutoItemHeight, tvoHideSelection, tvoKeepCollapsedNodes, tvoReadOnly, tvoShowButtons, tvoShowLines, tvoShowRoot, tvoToolTips]
+ end
+ object SettingsFormButtonOK: TButton
+ Left = 265
+ Height = 25
+ Top = 511
+ Width = 75
+ Anchors = [akRight, akBottom]
+ Caption = 'OK'
+ OnClick = SettingsFormButtonOKClick
+ TabOrder = 1
+ end
+ object SettingsFormButtonCancel: TButton
+ Left = 16
+ Height = 25
+ Top = 511
+ Width = 75
+ Anchors = [akLeft, akBottom]
+ Caption = 'Cancel'
+ OnClick = SettingsFormButtonCancelClick
+ TabOrder = 2
+ end
+end
diff --git a/branches/script-component/Projects/SAMufasaGUI/simbasettings.lrs b/branches/script-component/Projects/SAMufasaGUI/simbasettings.lrs
new file mode 100644
index 0000000..b444b4e
--- /dev/null
+++ b/branches/script-component/Projects/SAMufasaGUI/simbasettings.lrs
@@ -0,0 +1,20 @@
+{ This is an automatically generated lazarus resource file }
+
+LazarusResources.Add('TSettingsForm','FORMDATA',[
+ 'TPF0'#13'TSettingsForm'#12'SettingsForm'#4'Left'#3'3'#2#6'Height'#3'.'#2#3'T'
+ +'op'#3#173#0#5'Width'#3'h'#1#13'ActiveControl'#7#16'SettingsTreeView'#7'Capt'
+ +'ion'#6#14'Simba Settings'#12'ClientHeight'#3'.'#2#11'ClientWidth'#3'h'#1#8
+ +'OnCreate'#7#10'FormCreate'#9'OnDestroy'#7#11'FormDestroy'#10'LCLVersion'#6#6
+ +'0.9.29'#0#9'TTreeView'#16'SettingsTreeView'#4'Left'#2#16#6'Height'#3#217#1#3
+ +'Top'#2#16#5'Width'#3'D'#1#7'Anchors'#11#5'akTop'#6'akLeft'#7'akRight'#8'akB'
+ +'ottom'#0#17'DefaultItemHeight'#2#19#8'ReadOnly'#9#10'ScrollBars'#7#10'ssAut'
+ +'oBoth'#8'TabOrder'#2#0#10'OnDblClick'#7#24'SettingsTreeViewDblClick'#7'Opti'
+ +'ons'#11#17'tvoAutoItemHeight'#16'tvoHideSelection'#21'tvoKeepCollapsedNodes'
+ +#11'tvoReadOnly'#14'tvoShowButtons'#12'tvoShowLines'#11'tvoShowRoot'#11'tvoT'
+ +'oolTips'#0#0#0#7'TButton'#20'SettingsFormButtonOK'#4'Left'#3#9#1#6'Height'#2
+ +#25#3'Top'#3#255#1#5'Width'#2'K'#7'Anchors'#11#7'akRight'#8'akBottom'#0#7'Ca'
+ +'ption'#6#2'OK'#7'OnClick'#7#25'SettingsFormButtonOKClick'#8'TabOrder'#2#1#0
+ +#0#7'TButton'#24'SettingsFormButtonCancel'#4'Left'#2#16#6'Height'#2#25#3'Top'
+ +#3#255#1#5'Width'#2'K'#7'Anchors'#11#6'akLeft'#8'akBottom'#0#7'Caption'#6#6
+ +'Cancel'#7'OnClick'#7#29'SettingsFormButtonCancelClick'#8'TabOrder'#2#2#0#0#0
+]);
diff --git a/branches/script-component/Projects/SAMufasaGUI/simbasettings.pas b/branches/script-component/Projects/SAMufasaGUI/simbasettings.pas
new file mode 100644
index 0000000..c3dbb92
--- /dev/null
+++ b/branches/script-component/Projects/SAMufasaGUI/simbasettings.pas
@@ -0,0 +1,122 @@
+unit simbasettings;
+
+{$mode objfpc} {$M+}
+
+interface
+
+uses
+ Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
+ ComCtrls, StdCtrls, settings;
+
+const
+ SimbaSettingsFile = 'settings.xml';
+
+type
+
+ { TSettingsForm }
+
+ TSettingsForm = class(TForm)
+ SettingsFormButtonCancel: TButton;
+ SettingsFormButtonOK: TButton;
+ SettingsTreeView: TTreeView;
+ Settings: TMMLSettings;
+ procedure SettingsFormButtonCancelClick(Sender: TObject);
+ procedure SettingsFormButtonOKClick(Sender: TObject);
+ procedure FormCreate(Sender: TObject);
+ procedure FormDestroy(Sender: TObject);
+ procedure SettingsTreeViewDblClick(Sender: TObject);
+ { private declarations }
+ public
+ procedure SaveCurrent;
+ procedure Reload;
+ { public declarations }
+ end;
+
+var
+ SettingsForm: TSettingsForm;
+
+implementation
+
+{ TSettingsForm }
+
+procedure TSettingsForm.FormCreate(Sender: TObject);
+
+begin
+ Settings := TMMLSettings.Create(SettingsTreeView.Items);
+ if not FileExists(SimbaSettingsFile) then
+ begin
+ SettingsTreeView.Items.Clear;
+ Settings.SaveToXML(SimbaSettingsFile);
+ end;
+
+ SettingsTreeView.Items.Clear;
+ Settings.LoadFromXML(SimbaSettingsFile);
+end;
+
+procedure TSettingsForm.SettingsFormButtonOKClick(Sender: TObject);
+begin
+ SettingsForm.Settings.SaveToXML(SimbaSettingsFile);
+ SettingsForm.ModalResult:=mrOK;
+end;
+
+procedure TSettingsForm.SettingsFormButtonCancelClick(Sender: TObject);
+begin
+ if not FileExists(SimbaSettingsFile) then
+ begin
+ SettingsForm.SettingsTreeView.Items.Clear;
+ SettingsForm.Settings.SaveToXML(SimbaSettingsFile);
+ SettingsForm.SettingsTreeView.Items.Clear;
+ SettingsForm.Settings.LoadFromXML(SimbaSettingsFile);
+ end;
+ SettingsForm.ModalResult:=mrOK;
+end;
+
+procedure TSettingsForm.FormDestroy(Sender: TObject);
+begin
+ Settings.Free;
+end;
+
+procedure TSettingsForm.SettingsTreeViewDblClick(Sender: TObject);
+var
+ p, pp: TPoint;
+ N: TTreeNode;
+ Path, NewVal: String;
+
+begin
+ p := Mouse.CursorPos;
+ pp := TSettingsForm(Sender).ScreenToClient(p);
+ N := SettingsTreeView.GetNodeAt(pp.x, pp.y);
+ if N <> nil then
+ if assigned(N.Data) then
+ begin
+ Path := Settings.GetNodePath(N.Parent);
+ NewVal := InputBox('Change Setting', 'Change value for ' + TSettingData(N.Data).Val,
+ Settings.GetKeyValue(Path));
+ writeln('NewVal: ' + NewVal);
+ Settings.SetKeyValue(Path, NewVal);
+ N.Text := NewVal;
+ end;
+end;
+
+procedure TSettingsForm.SaveCurrent;
+begin
+ Settings.SaveToXML(SimbaSettingsFile);
+end;
+
+procedure TSettingsForm.Reload;
+begin
+ if not FileExists(SimbaSettingsFile) then
+ begin
+ SettingsTreeView.Items.Clear;
+ Settings.SaveToXML(SimbaSettingsFile);
+ end;
+
+ SettingsTreeView.Items.Clear;
+ Settings.LoadFromXML(SimbaSettingsFile);
+end;
+
+initialization
+ {$I simbasettings.lrs}
+
+end.
+
diff --git a/branches/script-component/Projects/SAMufasaGUI/simpleanalyzer.pas b/branches/script-component/Projects/SAMufasaGUI/simpleanalyzer.pas
new file mode 100644
index 0000000..1738cab
--- /dev/null
+++ b/branches/script-component/Projects/SAMufasaGUI/simpleanalyzer.pas
@@ -0,0 +1,379 @@
+unit simpleanalyzer;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+ Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
+ StdCtrls, SynEdit, SynHighlighterPas, Clipbrd;
+
+type
+
+ TScriptVar = record
+ VarName, VarType : string;
+ end;
+
+ { TScriptMethod }
+
+ TScriptMethod = class(TObject)
+ BeginPos, EndPos : integer;
+ isFunction : Boolean;
+ Name : string;
+ Parameters,Vars : array of TScriptVar;
+ ParameterLen,VarLen : integer;
+ Returns : String;
+ Methods : Array of TScriptMethod;
+ MethodLen : Integer;
+ function AddMethod( iszehfunction : boolean; TheName : string): TScriptMethod;
+ procedure AddVar( TheName, TheType : string);
+ procedure AddParam( TheName : string);
+ constructor create( iszehfunction : Boolean; TheName : string);
+ function CreateMethodStr : string;
+ Destructor Destroy; override;
+ end;
+
+ { TScriptAnalyzer }
+
+ TScriptAnalyzer = class(TObject)
+ ScriptToAnalyze : string;
+ ScriptName : string;
+ Methods : Array of TScriptMethod;
+ MethodLen : Integer;
+ Main : TScriptMethod;
+ HasMain : boolean;
+ Vars : Array of TScriptVar;
+ VarLen : integer;
+ Function AddMethod( iszehfunction : boolean; Name : string): TScriptMethod;
+ procedure AddVar( TheName, TheType : string);
+ procedure analyze;
+ constructor create;
+ Destructor Destroy; override;
+ end;
+
+
+
+implementation
+
+uses
+ mPasLex,strutils;
+
+
+
+destructor TScriptAnalyzer.Destroy;
+var
+ i : integer;
+begin;
+ for i := 0 to MethodLen - 1 do
+ Self.Methods[i].Free;
+ Main.Free;
+ inherited;
+end;
+
+destructor TScriptMethod.Destroy;
+var
+ i : integer;
+begin;
+ for i := 0 to MethodLen - 1 do
+ Self.Methods[i].Free;
+ inherited;
+end;
+constructor TScriptMethod.create( iszehfunction : Boolean; TheName : string);
+begin;
+ inherited Create;
+ Self.isFunction := iszehfunction;
+ Self.Name := TheName;
+end;
+
+function TScriptMethod.CreateMethodStr: string;
+var
+ i : integer;
+ LastType : string;
+begin
+ if isFunction then
+ result := 'function ' + Name
+ else
+ result := 'procedure '+ name;
+ if ParameterLen > 0 then
+ begin;
+ result := result + '(';
+ LastType := '';
+ for i := 0 to ParameterLen - 1 do
+ begin;
+ if lasttype <> '' then
+ if lowercase(lasttype) <> lowercase(Parameters[i].VarType) then
+ result := result + ' : ' + LastType + '; '
+ else
+ result := result + ', ';
+ result := result + Parameters[i].VarName;
+ lasttype := Parameters[i].VarType;
+ end;
+ Result := result + ' : ' + Parameters[ParameterLen - 1].VarType + ')';
+ end;
+ if isFunction then
+ result := result + ' : ' + Returns
+ else
+ result := result + ';';
+end;
+
+constructor TScriptAnalyzer.create;
+begin;
+ inherited create;
+ ScriptName := 'Default';
+ Main := TScriptMethod.create(false,'!main');
+end;
+procedure TScriptMethod.addVar( TheName, TheType : string);
+begin;
+ inc(Self.VarLen);
+ SetLength(Self.Vars, self.varlen);
+ Self.Vars[Self.VarLen - 1].VarName := TheName;
+ Self.Vars[Self.VarLen - 1].VarType := TheType;
+end;
+procedure TScriptAnalyzer.AddVar( TheName, TheType : string);
+begin;
+ inc(Self.VarLen);
+ SetLength(Self.Vars, self.VarLen);
+ Self.Vars[Self.VarLen - 1].VarName := TheName;
+ Self.Vars[Self.VarLen - 1].VarType := TheType;
+end;
+function TScriptMethod.AddMethod( iszehfunction : boolean; TheName : string) : TScriptMethod;
+begin;
+ inc(Self.MethodLen);
+ SetLength(Self.Methods, Self.MethodLen);
+ Self.Methods[Self.Methodlen - 1] := TScriptMethod.create(iszehfunction,TheName);
+ Result :=Self.Methods[Self.Methodlen - 1];
+end;
+
+
+
+function TScriptAnalyzer.AddMethod( iszehfunction : boolean; Name : string) : TScriptMethod;
+begin;
+ inc(Self.MethodLen);
+ SetLength(Self.Methods, Self.MethodLen);
+ Self.Methods[Self.Methodlen - 1] := TScriptMethod.create(iszehfunction,Name);
+ Result :=Self.Methods[Self.Methodlen - 1];
+end;
+
+
+procedure TScriptMethod.AddParam(TheName: string);
+begin;
+ inc(Self.ParameterLen);
+ SetLength(Self.Parameters, self.ParameterLen);
+ Self.Parameters[Self.ParameterLen - 1].VarName := TheName;
+end;
+
+
+procedure TScriptAnalyzer.analyze;
+var
+ LastTk : TTokenKind;
+ StartPos,LastPos: integer;
+
+ LastTkString : string;
+ I : integer;
+ InMethod : Boolean;
+ ExpectingType : boolean; //Params and result
+ WaitingForResult : boolean;
+ StartParam : integer;
+ StartVar : integer;
+ Method : TScriptMethod;
+ InTypes : Boolean;
+ TempName : string;
+ BeginCount : integer;
+ InGlobal : boolean;
+ InParams : boolean;
+ InVarSection : Boolean;
+ Lex : TmwPasLex;
+begin
+ Lex := TmwPasLex.Create;
+ Lex.Origin := PChar(Self.ScriptToAnalyze);
+ InTypes := False;
+ InMethod := False;
+ InParams := False;
+ Method := nil;
+ BeginCount := 0;
+ ExpectingType := False;
+ WaitingForResult := False;
+ StartParam := 0;
+ InVarSection := False;
+ while (Lex.TokenID <> tkNull) do
+ begin;
+ LastTk := Lex.TokenID;
+ LastPos := Lex.RunPos;
+ Lex.NextNoJunk;
+ case LastTk of
+// tkInclude : ShowMessage(Lex.Token);
+// if (FParser.Token[Length(FParser.Token)] = '}') then
+// FIncludes.Add(StringReplace(LowerCase(Trim(Copy(FParser.Token, 11, Length(FParser.Token) - 11))), '/', '\', [rfReplaceAll]));
+ tkProgram : if Lex.TokenID = tkIdentifier then
+ Self.ScriptName := Lex.Token;
+ tkRoundOpen: begin;
+ LastTkString := Lex.Token;
+ if InMethod and InParams then
+ StartParam := 0;
+ end;
+ tkType : InVarSection := False;
+ tkBegin : begin;
+
+ InVarSection := False;
+ if InMethod then
+ inc(BeginCount)
+ else if BeginCount = 0 then
+ begin;
+ InVarSection := false;
+ InMethod := true;
+ HasMain := True;
+ Method := Main;
+ Main.BeginPos := LastPos - 4;
+ Inc(BeginCount);
+ end;
+ end;
+ tkCase : begin;
+ if InMethod then
+ inc(BeginCount);
+ end;
+ tkEnd : if InMethod then
+ begin;
+ Dec(BeginCount);
+ if BeginCount = 0 then
+ begin;
+ Method.EndPos := LastPos;
+ InMethod := False;
+ end;
+ end;
+ tkIdentifier: begin;
+ if (InMethod and InParams) or (InVarSection) then
+ begin;
+
+{ if ExpectingType then
+ begin;
+ FormAnalyzer.SynEdit1.Lines.add(copy( FormAnalyzer.SynEdit1.Lines.Text,StartPos, LastPos - StartPos));
+ LastTKString := copy( FormAnalyzer.SynEdit1.Lines.GetText,StartPos, Lex.TokenPos - StartPos);
+ for i := StartParam to Method.ParameterLen - 1 do
+ Method.Parameters[i].VarType := LastTkString;
+ end
+ else
+ Method.AddParam(LastTkString); }
+ if not ExpectingType and InVarSection then
+ Method.AddVar(LastTKString,'') else
+ if not ExpectingType then
+ Method.AddParam(LastTKString);
+ end;
+ end;
+ tkVar : begin;
+ if InMethod and Not InParams then
+ InVarSection := True;
+ if not InMethod then
+ begin;
+ Method := Main;
+ InGlobal := True;
+ InVarSection := True;
+
+ end;
+ if InVarSection then
+ StartVar := Method.VarLen;
+ LastTKString := Lex.Token;
+ end;
+ tkConst : begin;
+ if not InMethod then
+ InVarSection := false;
+ LastTKString := Lex.token;
+ end;
+ tkComma : begin;
+ LastTKString := Lex.Token;
+ end;
+ tkColon : begin;
+ LastTkString := Lex.Token;
+ if (InMethod and InParams) or InVarSection then
+ begin;
+ ExpectingType := True;
+ StartPos := LastPos;
+ end
+ else if InMethod and WaitingForresult then
+ begin;
+ Method.Returns := Lex.Token;
+ WaitingForResult := False;
+ end;
+ end;
+ tkSemiColon : begin;
+ if (InMethod and InParams) or (InVarSection) then
+ begin;
+ if ExpectingType then
+ begin;
+ LastTKString := Trim(copy( ScriptToAnalyze,StartPos + 1, LastPos - StartPos - 1));
+ if (InParams and InMethod) then
+ for i := StartParam to Method.ParameterLen - 1 do
+ Method.Parameters[i].VarType := LastTkString
+ else
+ for i := StartVar to Method.VarLen - 1 do
+ Method.Vars[i].VarType := LastTKString;
+ ExpectingType := False;
+ end;
+ LastTkString := Lex.Token;
+ StartParam := Method.ParameterLen;
+ StartVar := Method.VarLen;
+ end;
+ end;
+ tkRoundClose: if InMethod and InParams then
+ begin;
+ if ExpectingType then
+ begin;
+ LastTKString := Trim(copy(ScriptToAnalyze,StartPos + 2, LastPos - StartPos - 2));
+ for i := StartParam to Method.ParameterLen - 1 do
+ Method.Parameters[i].VarType := LastTkString;
+ ExpectingType := False;
+ end;
+ InParams := False;
+ end;
+ tkProcedure,
+ tkFunction : begin;
+ if (InVarSection or (InMethod and InParams)) and ExpectingType then
+ begin;
+ //Do nothing since the this procedure/function is a var ;-)
+ end else
+ begin;
+ if not InMethod then
+ InVarSection := False;
+ if (not InTypes) and (not InVarSection) then
+ begin;
+ WaitingForResult := LastTK = tkFunction;
+ if Lex.TokenID <> tkIdentifier then
+ begin;
+ Writeln('Analyzer: No method name -> exiting');
+ exit;
+ end;
+ TempName := Lex.Token;
+ Lex.NextNoJunk;
+ if Lex.TokenID = tkRoundOpen then
+ InParams := True
+ else if Lex.TokenID = tkPoint then
+ begin;
+ Writeln('Analyzer: In class definition?');
+ // FormAnalyzer.SynEdit2.Lines.add('In class definition *cough*');
+ Lex.NextNoJunk;
+ TempName := Lex.Token;
+ end else if ((Lex.TokenID = tkSemicolon) xor WaitingForResult) or ((Lex.TokenID = tkColon) xor WaitingForResult) then
+ begin;
+ InParams := False;
+ end else
+ begin;
+ Writeln('Analyzer: You''re missing some stuff in the procedure declaration');
+ Exit;
+ end;
+ if InMethod then
+ Method := Method.AddMethod(WaitingForResult,TempName)
+ else
+ Method := Self.AddMethod(WaitingForResult,TempName);
+ InMethod := true;
+ Method.BeginPos := LastPos - 5;
+
+ end;
+ end;
+ end;
+
+ end;
+// SynEdit2.Lines.Add(TokeToString(Lex.TokenID) + '-' + Lex.Token);
+ end;
+end;
+
+end.
+
diff --git a/branches/script-component/Projects/SAMufasaGUI/testunit.lfm b/branches/script-component/Projects/SAMufasaGUI/testunit.lfm
new file mode 100644
index 0000000..e19d125
--- /dev/null
+++ b/branches/script-component/Projects/SAMufasaGUI/testunit.lfm
@@ -0,0 +1,3081 @@
+object Form1: TForm1
+ Left = 1343
+ Height = 557
+ Top = 181
+ Width = 734
+ ActiveControl = ScriptPanel
+ Caption = 'THA FUKING SIMBA'
+ ClientHeight = 532
+ ClientWidth = 734
+ KeyPreview = True
+ Menu = MainMenu
+ OnClose = FormClose
+ OnCreate = FormCreate
+ OnDestroy = FormDestroy
+ OnShortCut = FormShortCuts
+ Position = poScreenCenter
+ LCLVersion = '0.9.29'
+ Visible = True
+ object ToolBar1: TToolBar
+ Left = 0
+ Height = 24
+ Top = 0
+ Width = 734
+ Caption = 'ToolBar1'
+ Images = Mufasa_Image_List
+ ParentShowHint = False
+ ShowHint = True
+ TabOrder = 0
+ object TB_Run: TToolButton
+ Left = 168
+ Hint = 'Run'
+ Top = 2
+ Action = ActionRunScript
+ ImageIndex = 6
+ end
+ object TB_Pause: TToolButton
+ Left = 191
+ Hint = 'Pause'
+ Top = 2
+ Action = ActionPauseScript
+ Enabled = False
+ ImageIndex = 5
+ end
+ object TB_Stop: TToolButton
+ Left = 214
+ Hint = 'Stop'
+ Top = 2
+ Action = ActionStopScript
+ Enabled = False
+ ImageIndex = 7
+ end
+ object ToolButton1: TToolButton
+ Left = 237
+ Top = 2
+ Width = 3
+ Caption = 'ToolButton1'
+ Style = tbsDivider
+ end
+ object TB_NewTab: TToolButton
+ Left = 240
+ Hint = 'Add tab'
+ Top = 2
+ Action = ActionNewTab
+ end
+ object TB_CloseTab: TToolButton
+ Left = 263
+ Hint = 'Close tab'
+ Top = 2
+ Action = ActionCloseTab
+ end
+ object ToolButton4: TToolButton
+ Left = 286
+ Top = 2
+ Width = 3
+ Caption = 'ToolButton4'
+ Style = tbsDivider
+ end
+ object TB_ClearDebug: TToolButton
+ Left = 289
+ Hint = 'Clear debug box'
+ Top = 2
+ Action = ActionClearDebug
+ end
+ object TB_PickColour: TToolButton
+ Left = 312
+ Hint = 'Pick a color'
+ Top = 2
+ Caption = 'TB_PickColour'
+ ImageIndex = 0
+ OnClick = ButtonPickClick
+ end
+ object TB_SelectClient: TToolButton
+ Left = 335
+ Hint = 'Select a client'
+ Top = 2
+ Caption = 'TB_SelectClient'
+ ImageIndex = 2
+ OnMouseDown = ButtonSelectorDown
+ end
+ object ToolButton8: TToolButton
+ Left = 358
+ Top = 2
+ Width = 3
+ Caption = 'ToolButton8'
+ Style = tbsDivider
+ end
+ object TB_ReloadPlugins: TToolButton
+ Left = 361
+ Hint = 'Reload plugins'
+ Top = 2
+ Caption = 'TB_ReloadPlugins'
+ Enabled = False
+ ImageIndex = 13
+ end
+ object TB_Tray: TToolButton
+ Left = 384
+ Hint = 'Minimize to tray'
+ Top = 2
+ Caption = 'TB_Tray'
+ ImageIndex = 17
+ OnClick = ButtonTrayClick
+ end
+ object TB_New: TToolButton
+ Left = 1
+ Hint = 'New'
+ Top = 2
+ Action = ActionNewScript
+ ParentShowHint = False
+ ShowHint = True
+ end
+ object ToolButton2: TToolButton
+ Left = 93
+ Top = 2
+ Width = 3
+ Caption = 'ToolButton2'
+ Style = tbsDivider
+ end
+ object TB_Open: TToolButton
+ Left = 24
+ Hint = 'Open'
+ Top = 2
+ Action = ActionOpenScript
+ ParentShowHint = False
+ ShowHint = True
+ end
+ object TB_Save: TToolButton
+ Left = 47
+ Hint = 'Save'
+ Top = 2
+ Action = ActionSaveScript
+ end
+ object TB_SaveAll: TToolButton
+ Left = 70
+ Hint = 'Save all'
+ Top = 2
+ Action = ActionSaveAll
+ Enabled = False
+ end
+ object ToolButton3: TToolButton
+ Left = 407
+ Top = 2
+ Width = 3
+ Caption = 'ToolButton3'
+ Style = tbsDivider
+ end
+ object TT_Update: TToolButton
+ Left = 410
+ Hint = 'A new update is available'
+ Top = 2
+ Caption = 'TT_Update'
+ ImageIndex = 1
+ Visible = False
+ OnClick = TT_UpdateClick
+ end
+ object TT_Cut: TToolButton
+ Left = 96
+ Top = 2
+ Caption = 'Cu&t'
+ ImageIndex = 3
+ OnClick = ActionCutExecute
+ end
+ object TT_Copy: TToolButton
+ Left = 119
+ Top = 2
+ Caption = '&Copy'
+ ImageIndex = 22
+ OnClick = ActionCopyExecute
+ end
+ object TT_Paste: TToolButton
+ Left = 142
+ Top = 2
+ Action = ActionPaste
+ end
+ object ToolButton9: TToolButton
+ Left = 165
+ Top = 2
+ Width = 3
+ Caption = 'ToolButton9'
+ Style = tbsDivider
+ end
+ end
+ object StatusBar: TStatusBar
+ Left = 0
+ Height = 21
+ Top = 511
+ Width = 734
+ Panels = <
+ item
+ Width = 60
+ end
+ item
+ Text = 'Untitled'
+ Width = 150
+ end
+ item
+ Width = 50
+ end>
+ SimplePanel = False
+ end
+ object PanelMemo: TPanel
+ Left = 0
+ Height = 154
+ Top = 357
+ Width = 734
+ Align = alBottom
+ ClientHeight = 154
+ ClientWidth = 734
+ TabOrder = 2
+ object Memo1: TMemo
+ Left = 1
+ Height = 152
+ Top = 1
+ Width = 732
+ Align = alClient
+ ScrollBars = ssAutoBoth
+ TabOrder = 0
+ end
+ end
+ object SplitterMemoSynedit: TSplitter
+ Cursor = crVSplit
+ Left = 0
+ Height = 5
+ Top = 352
+ Width = 734
+ Align = alBottom
+ ResizeAnchor = akBottom
+ end
+ object ScriptPanel: TPanel
+ Left = 0
+ Height = 328
+ Top = 24
+ Width = 734
+ Align = alClient
+ BevelOuter = bvNone
+ ClientHeight = 328
+ ClientWidth = 734
+ DockSite = True
+ TabOrder = 4
+ OnDockDrop = ScriptPanelDockDrop
+ OnDockOver = ScriptPanelDockOver
+ object PageControl1: TPageControl
+ Left = 155
+ Height = 293
+ Top = 0
+ Width = 579
+ Align = alClient
+ Images = Mufasa_Image_List
+ PopupMenu = TabPopup
+ TabOrder = 0
+ OnChange = PageControl1Change
+ OnChanging = PageControl1Changing
+ OnContextPopup = PageControl1ContextPopup
+ OnDragDrop = PageControl1DragDrop
+ OnDragOver = PageControl1DragOver
+ OnMouseDown = PageControl1MouseDown
+ OnMouseUp = PageControl1MouseUp
+ OnPageChanged = PageControl1Change
+ end
+ object SearchPanel: TPanel
+ Left = 0
+ Height = 35
+ Top = 293
+ Width = 734
+ Align = alBottom
+ BevelOuter = bvSpace
+ ClientHeight = 35
+ ClientWidth = 734
+ TabOrder = 1
+ Visible = False
+ object SpeedButtonSearch: TSpeedButton
+ Left = 32
+ Height = 19
+ Top = 7
+ Width = 16
+ Color = clBtnFace
+ Flat = True
+ Glyph.Data = {
+ 36090000424D3609000000000000360000002800000018000000180000000100
+ 2000000000000009000064000000640000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 00FF0000000000000000000000000000000000000000000000FF000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000FF0000
+ 00FF000000FF000000000000000000000000000000FF000000FF000000FF0000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 00FF000000FF000000FF00000000000000FF000000FF000000FF000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000FF000000FF000000FF000000FF000000FF00000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 000000000000000000FF000000FF000000FF0000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000FF000000FF000000FF000000FF000000FF00000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 00FF000000FF000000FF00000000000000FF000000FF000000FF000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000FF0000
+ 00FF000000FF000000000000000000000000000000FF000000FF000000FF0000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 00FF0000000000000000000000000000000000000000000000FF000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000
+ }
+ NumGlyphs = 0
+ OnClick = SpeedButtonSearchClick
+ end
+ object LabeledEditSearch: TLabeledEdit
+ Left = 104
+ Height = 27
+ Top = 6
+ Width = 174
+ EditLabel.AnchorSideLeft.Control = LabeledEditSearch
+ EditLabel.AnchorSideTop.Control = LabeledEditSearch
+ EditLabel.AnchorSideTop.Side = asrCenter
+ EditLabel.AnchorSideRight.Control = LabeledEditSearch
+ EditLabel.AnchorSideBottom.Control = LabeledEditSearch
+ EditLabel.Left = 65
+ EditLabel.Height = 18
+ EditLabel.Top = 10
+ EditLabel.Width = 36
+ EditLabel.Caption = 'Find: '
+ EditLabel.ParentColor = False
+ LabelPosition = lpLeft
+ TabOrder = 0
+ OnChange = EditSearchChange
+ OnEnter = LabeledEditSearchEnter
+ OnExit = LabeledEditSearchExit
+ OnKeyDown = LabeledEditSearchKeyDown
+ OnKeyPress = LabeledEditSearchKeyPress
+ end
+ object CheckBoxMatchCase: TCheckBox
+ Left = 320
+ Height = 22
+ Top = 7
+ Width = 98
+ Caption = 'Match case'
+ OnClick = CheckBoxMatchCaseClick
+ TabOrder = 1
+ end
+ end
+ object SplitterFunctionList: TSplitter
+ Left = 150
+ Height = 293
+ Top = 0
+ Width = 5
+ OnCanResize = SplitterFunctionListCanResize
+ Visible = False
+ end
+ inline frmFunctionList: TFunctionListFrame
+ Height = 293
+ Width = 150
+ ClientHeight = 293
+ ClientWidth = 150
+ OnEndDock = nil
+ TabOrder = 3
+ inherited FunctionList: TTreeView
+ Height = 244
+ Top = 22
+ Width = 150
+ DefaultItemHeight = 19
+ OnChange = FunctionListChange
+ OnDeletion = nil
+ OnEnter = FunctionListEnter
+ OnExit = FunctionListExit
+ end
+ inherited editSearchList: TEdit
+ Height = 27
+ Top = 266
+ Width = 150
+ OnExit = editSearchListExit
+ OnKeyDown = editSearchListKeyDown
+ OnKeyPress = editSearchListKeyPress
+ end
+ inherited FunctionListLabel: TLabel
+ Height = 18
+ Width = 146
+ end
+ end
+ end
+ object MainMenu: TMainMenu
+ left = 488
+ top = 144
+ object MenuFile: TMenuItem
+ Caption = '&File'
+ SubMenuImages = Mufasa_Image_List
+ object MenuItemNew: TMenuItem
+ Action = ActionNewScript
+ Bitmap.Data = {
+ 36040000424D3604000000000000360000002800000010000000100000000100
+ 2000000000000004000064000000640000000000000000000000FFFFFF00BB6A
+ 346BBA6530BCBB6631EDBA6630F7BA6630F7BA6630F7BA6530F7BA652FF7B965
+ 2EF7B9652EF7B9642EF7B9642EEFB7622CBDB7622E63FFFFFF00FFFFFF00BC69
+ 33DEF8F1EAF2F7ECDFFDF6EBDEFFF6EADEFFF6EADCFFF6EADCFFFAF3EBFFFAF3
+ EBFFFAF2EAFFFCF7F3FFFCF8F4FDFEFEFDF0B7602AD5FFFFFF00FFFFFF00BF71
+ 38F5F5EBDFFEFDBF68FFFCBD67FFFBBE65FFFCBE64FFFCBE64FFFCBD62FFFBBD
+ 63FFFBBC61FFFCBE60FFFCBC62FFFDFBF8FDB9642DF3FFFFFF00FFFFFF00C178
+ 3CF7F7EDE3FFFDC26EFFFFD8A0FFFFD79EFFFFD69BFFFFD798FFFFD696FFFFD6
+ 95FFFFD594FFFFD493FFFBBE65FFFBF7F4FFBB6731F7FFFFFF00FFFFFF00C47C
+ 40F7F7F0E6FFF8B455FFF7B456FFF7B554FFF8B453FFF8B253FFF7B352FFF7B3
+ 52FFF7B251FFF7B24FFFF7B24FFFFCF9F5FFBF6F36F7FFFFFF00FFFFFF00C580
+ 42F7F8F1E8FFFEE5D5FFFDE5D3FFFDE5D3FFFCE5D3FFFCE5D3FFFCE4D1FFFCE2
+ CEFFFCE2CCFFFBE0C9FFFBE1C8FFFDFAF7FFC1763BF7FFFFFF00FFFFFF00C582
+ 45F7F8F2EBFFFEE7D6FFFDE7D6FFFDE7D6FFFDE7D6FFFDE6D5FFFDE5D3FFFCE4
+ D1FFFCE2CDFFFBE1CBFFFBE1C9FFFBF7F2FFC57C3FF7FFFFFF00FFFFFF00C684
+ 47F7F9F3ECFFFEE8D6FFFEE8D7FFFDE7D6FFFDE7D6FFFDE7D5FFFDE5D3FFFBE4
+ D0FFFBE3CCFFFADFC7FFFADFC6FFFAF2EAFFC68042F7FFFFFF00FFFFFF00C688
+ 49F7F9F4EDFFFEE8D8FFFEE8D8FFFEE8D7FFFEE7D6FFFDE5D3FFFCE4D1FFFBE1
+ CCFFFAE0C7FFF9DDC3FFF8DCC2FFFAF4EDFFC68245F7FFFFFF00FFFFFF00C688
+ 4AF7F9F4EFFFFEE7D7FFFDE7D6FFFDE7D5FFFDE6D4FFFCE6D2FFFBE1CCFFFADF
+ C7FFF8DCC2FFF6DABDFFF6D8BBFFFAF4EFFFC68346F7FFFFFF00FFFFFF00C689
+ 4BF7F9F4F0FFFCE6D3FFFCE6D4FFFDE7D3FFFCE4D1FFFBE3CDFFFAE0C8FFF8DC
+ C2FFF5D6BBFFF3D4B5FFF1D2B3FFF8F4F0FFC48246F7FFFFFF00FFFFFF00C689
+ 4BF7F9F5F1FFFCE3CFFFFBE4D0FFFCE4CFFFFCE3CDFFFAE1CAFFF9DDC4FFF6D9
+ BCFFF4E9DFFFF7F2ECFFFBF7F3FFF5EFE9FFC27E45FBFFFFFF00FFFFFF00C689
+ 4CF6F9F5F1FFFCE3CDFFFBE3CEFFFBE3CDFFFBE2CBFFF9E0C8FFF8DCC2FFF5D6
+ BAFFFDFBF8FFFCE6CDFFFAE5C9FFE2B684FFBF7942A6FFFFFF00FFFFFF00C588
+ 4BEAFAF6F2FCFAE0C7FFFBE1C9FFFBE2C9FFFBE0C8FFF9DFC5FFF8DBC1FFF4D6
+ B8FFFFFBF8FFF6D8B4FFE1B07DFFDB9264F6B46B3E07FFFFFF00FFFFFF00C485
+ 49C3F7F2ECECF8F4EEFCF8F4EDFFF8F3EDFFF8F3EDFFF8F3EDFFF8F2ECFFF7F2
+ ECFFF2E6D7FFE2B27DFFDB9465F5B3683B07FFFFFF00FFFFFF00FFFFFF00C17D
+ 4460C88B4DBBC88C4FEEC88C4FF6C88C4FF7C88C4FF7C88D4FF7C98C4FF7C78B
+ 4FF7C5894BD4C4763B91B3683C06FFFFFF00FFFFFF00FFFFFF00
+ }
+ SubMenuImages = Mufasa_Image_List
+ OnClick = ActionNewExecute
+ end
+ object MenuItemDivider: TMenuItem
+ Caption = '-'
+ end
+ object MenuItemOpen: TMenuItem
+ Action = ActionOpenScript
+ Bitmap.Data = {
+ 36040000424D3604000000000000360000002800000010000000100000000100
+ 20000000000000040000640000006400000000000000000000002C86D8D12D88
+ D8F72D87D8F72D88D8F72D88D8F72D88D8F72D88D8F72D88D8F72D88D8F72D88
+ D8F72D88D8F72D87D8F72D88D8F72C86D8D1FFFFFF00FFFFFF00338ED9FBDCF0
+ FAFF98E1F6FF95E0F6FF92DFF6FF8EDEF5FF89DCF5FF85DAF4FF80D9F4FF7AD7
+ F3FF74D5F3FF70D3F2FFC2EAF8FF3594DAFFFFFFFF00FFFFFF003594DAF7EFFA
+ FEFF93E5F8FF8FE4F8FF89E3F8FF82E1F7FF7ADFF7FF71DEF6FF67DBF5FF5BD8
+ F4FF4DD4F3FF40D1F2FFCAF2FBFF3594DAFFFFFFFF00FFFFFF00369ADAF8F2FA
+ FDFF94E6F8FF92E5F8FF90E5F8FF8BE3F8FF86E2F7FF7FE1F7FF77DEF6FF6CDC
+ F6FF5ED9F4FF4FD5F3FFCCF2FBFF3594DAFFFFFFFF00FFFFFF0036A1DAF9F6FC
+ FEFF94E5F8FF93E5F8FF93E5F8FF91E5F8FF93DBE9FF93D7E3FF93D2DCFF90CE
+ D7FF8CC8CFFF86C1C6FFC9D8D6FF3594DAFFC57444E8CA7F53F137A6DAFAFEFF
+ FFFFF8FDFFFFF6FDFFFFF5FCFFFFF3FCFEFF9AE4F4FF9AE6F7FF9BE6F6FF9DE5
+ F5FF9EE5F5FF9FE5F4FFDAF3F8FF3594DAFFFDF4EEFFCA8054F935ABDAFAE8F6
+ FBFF70BCE7FF55AAE2FF4DA5E0FF91C9EBFFFAF3EFFFFDFEFDFFFFFDFCFFFFFD
+ FCFFFEFDFCFFFEFCFBFFFEFEFDFF3594DAFFEFF2E8FFCE8156FF36AADAF2F1FA
+ FDFF94DEF5FF93DCF4FF64BCE9FF3594DAFF3594DAFF3594DAFF3594DAFF3594
+ DAFF3594DAFF3594DAFF3594DAFF3594DAFFFBF6EFFFCC8355FE35AFDAF0F7FC
+ FEFF8EE4F8FF91DEF5FF9FE0F5FFACE1F6FFCA8452FFFFF7F1FFFFE9D9FFFFEA
+ DBFFFFE9D9FFFFE7D7FFFFE5D2FFFFE2CBFFFFF7F1FFCB8555FE36B3DAF8FDFE
+ FEFFFEFFFFFFFEFEFFFFFDFEFFFFFEFFFFFFE4BA91FFFFF7F0FFFFE7D5FFFDE7
+ D6FFFDE6D4FFFCE4D0FFFBE3CBFFFADCC2FFFEF3E8FFCC8656FE34B4D9D05EC2
+ E1FA60C3E2FA60C3E2FA60C3E2FA5FC3E2FAE4BB91FFFFF7F2FFFEE7D5FFFEE7
+ D5FFFDE5D1FFFAE0CAFFF9DEC4FFF7D9BCFFFDF2E7FFCC8757FEFFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00E4BB92FFFEF7F1FFFCE5D2FFFCE4
+ D1FFFBE2CCFFF9DDC4FFF6D7BBFFF3D1AFFFFAEFE4FFCC8758FEFFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00E4BB92FFFEF6F0FFFCE2CDFFFCE3
+ CDFFFADFC8FFF7D9BCFFF5E9DDFFFAF3EBFFFBF8F3FFCA8353FEFFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00E4BB93FFFEF5EDFFFCDEC5FFFBE0
+ C7FFF9DCC2FFF5D3B4FFFEF9F3FFFAE2C4FFECC193FFC37D4893FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00E5BE96FFFFFFFEFFFDF3E9FFFDF3
+ EAFFFCF2E8FFFAEFE3FFFAF2E7FFEABB88FFCF8555B3B4693D0CFFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00EAC39DFFE6BF96FFE4BB92FFE4BB
+ 92FFD1A06CF5D09E6DF6CC965FDAC479427EB2673C09FFFFFF00
+ }
+ OnClick = ActionOpenExecute
+ end
+ object MenuItemSave: TMenuItem
+ Action = ActionSaveScript
+ Bitmap.Data = {
+ 36040000424D3604000000000000360000002800000010000000100000000100
+ 2000000000000004000064000000640000000000000000000000BA6A368FB969
+ 35B5B86935EEB76835FFB56835FFB46734FFB26634FFB06533FFAE6433FFAC63
+ 32FFAA6232FFA96132FFA86031FFA76031FEA66031F1A86131C4BA6A35DEEBC6
+ ADFFEAC5ADFFFEFBF8FFFEFBF8FFFEFBF8FFFEFBF8FFFEFBF8FFFEFBF8FFFEFB
+ F8FFFEFBF8FFFEFBF8FFFEFBF8FFC89A7CFFC79879FFA76031EDBA6B37FEEDCA
+ B3FFE0A27AFFFEFAF7FF62C088FF62C088FF62C088FF62C088FF62C088FF62C0
+ 88FF62C088FF62C088FFFDF9F6FFCA8D65FFC99B7CFFA76031FEBB6C38FFEECC
+ B6FFE1A27AFFFEFAF7FFBFDCC2FFBFDCC2FFBFDCC2FFBFDCC2FFBFDCC2FFBFDC
+ C2FFBFDCC2FFBFDCC2FFFDF9F6FFCD9068FFCC9E81FFA86132FFBB6B38FFEFCE
+ B8FFE1A279FFFEFAF7FF62C088FF62C088FF62C088FF62C088FF62C088FF62C0
+ 88FF62C088FF62C088FFFDF9F6FFCF936AFFCEA384FFAA6132FFBA6A36FFEFD0
+ BBFFE2A27AFFFEFBF8FFFEFBF8FFFEFBF8FFFEFBF8FFFEFBF8FFFEFBF8FFFEFB
+ F8FFFEFBF8FFFEFBF8FFFEFBF8FFD3966DFFD2A78AFFAB6232FFBB6A36FFF0D2
+ BEFFE2A37AFFE2A37AFFE1A37AFFE2A37BFFE1A37BFFE0A178FFDE9F77FFDD9F
+ 76FFDC9D74FFD99B72FFD89971FFD69970FFD5AB8EFFAD6333FFBB6A36FFF2D5
+ C2FFE3A37AFFE3A37AFFE2A37BFFE2A37BFFE2A47BFFE1A279FFE0A178FFDEA0
+ 77FFDE9E75FFDC9D74FFDA9B73FFD99B73FFDAB095FFAF6433FFBB6A36FFF2D8
+ C5FFE3A47BFFE3A37AFFE3A47AFFE2A47BFFE2A37BFFE1A37BFFE1A279FFDFA0
+ 77FFDE9F76FFDD9E74FFDB9C72FFDC9D74FFDDB59AFFB16534FFBB6B36FFF4D9
+ C7FFE6A67DFFC88C64FFC98D65FFC98E67FFCB926CFFCB926DFFCA9069FFC88C
+ 65FFC88C64FFC88C64FFC88C64FFDA9C74FFE1BA9FFFB36634FFBB6B36FEF4DC
+ C9FFE7A77DFFF9ECE1FFF9ECE1FFF9EDE3FFFCF4EEFFFDFAF7FFFDF7F3FFFAED
+ E5FFF7E7DBFFF7E5D9FFF6E5D8FFDEA077FFE4BEA4FFB46734FFBC6B36FAF5DD
+ CCFFE7A87EFFFAF0E8FFFAF0E8FFC98D66FFFAF0E9FFFDF8F3FFFEFAF8FFFCF4
+ EFFFF9E9DFFFF7E7DBFFF7E5D9FFE0A278FFE7C2A9FFB66835FFBC6B36F0F6DF
+ D0FFE8A87EFFFCF6F1FFFCF6F1FFC88C64FFFAF1E9FFFBF4EEFFFDFAF7FFFDF9
+ F6FFFAF0E8FFF8E8DDFFF7E6DBFFE1A37AFFEFD5C3FFB76935FEBC6B36D8F6DF
+ D1FFE9AA80FFFEFAF6FFFDFAF6FFC88C64FFFBF3EEFFFBF1EAFFFCF6F2FFFEFB
+ F8FFFCF6F1FFF9ECE2FFF8E7DBFFEED0BAFFECD0BDFFBB703EF8BC6B369BF6E0
+ D1FFF7E0D1FFFEFBF8FFFEFBF7FFFDF9F6FFFCF5F0FFFAF0EAFFFBF2EDFFFDF9
+ F6FFFDFAF7FFFBF1EBFFF8E9DFFEECD0BDFBC9895EECB5693563BC6B3671BC6B
+ 3690BC6B36CCBC6B36EEBC6B36FABB6B36FEBB6B36FFBB6A36FFBB6A36FFBC6C
+ 39FFBD6E3BFFBB6D3AFFBB6B38EFBB703ECBB6693554FFFFFF00
+ }
+ OnClick = ActionSaveExecute
+ end
+ object MenuItemSaveAs: TMenuItem
+ Action = ActionSaveScriptAs
+ Caption = 'Save as...'
+ OnClick = ActionSaveAsExecute
+ end
+ object MenuItemSaveAll: TMenuItem
+ Action = ActionSaveAll
+ Enabled = False
+ Bitmap.Data = {
+ 36040000424D3604000000000000360000002800000010000000100000000100
+ 2000000000000004000064000000640000000000000000000000FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00BA6833C5C38458FFD38B68FFE18F70FFDC8D
+ 6CFFDA8B6DFFD78A6EFFCD8B6CFFAB6D44FFA65F2EFFFFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00C68355FFEFCEBAFFDDFFFFFF87EEC7FFA2F4
+ D7FFA2F6D7FF8CEEC7FFE0FFFFFFDDA285FFAB6A3EFFFFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00BA6833ACC38458DEC37F51FFEFB69AFFEAF3E8FF51BF84FF6FC9
+ 98FF71C999FF54BF84FFE4F4E9FFDD9C7BFFAA693AFFFFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00C68355DEEFCEBADEC48154FFEAB697FFF3F3EAFFEDF1E6FFEFF1
+ E6FFEFF0E6FFEDF1E5FFF3F5EDFFD59C79FFB07044FFFFFFFF00FFFFFF00BA68
+ 339BC38458C9C58053F8EEB296F8C98B61FFE6B592FFE2A781FFE1A781FFDEA3
+ 7DFFDCA17BFFDB9F79FFD99E77FFD49A73FFBB7E57FFFFFFFF00FFFFFF00C683
+ 55C9EFCEBAC9C78E66F8E0BC9CF8CA8D65FFEAB899FFDDA57EFFDDA680FFDBA3
+ 7CFFD9A07AFFD9A079FFD89F78FFD89E78FFBF845DFFFFFFFF00FFFFFF00C37F
+ 51C9EFB69AC9CC966FF8D6B691F8C8885DFFEFBFA1FFFDFCFAFFFEFCFBFFFEFD
+ FDFFFEFDFCFFFDFBFAFFFDFCFBFFDDA885FFC17F53FFFFFFFF00FFFFFF00C481
+ 54C9EAB697C9CE9873F8EABEA1F8C7865BFFEFC09EFFFFFFFFFFCC936EFFFFFF
+ FFFFFFFFFFFFFFFBF7FFFFF8F1FFE4AF8CFFC78A61FFFFFFFF00FFFFFF00C98B
+ 61C9E6B592C9CB8B61F8EEBC9EF8CC8D65FFF3CDB0FFFFFFFFFFE3C7B3FFFFFF
+ FFFFFFFFFFFFFFFFFFFFFFFFFFFFEABFA1FFC98960FFFFFFFF00FFFFFF00CA8D
+ 65C9EAB899C9C9895FF8EDBD9BF8D4976EFFD49E7BFFD09871FFD6A482FFCD8E
+ 68FFCD9069FFD09A75FFD19973FFC88B62FFAD5A2036FFFFFF00FFFFFF00C888
+ 5DC9EFBFA1C9D19975F8F4D2B8F8FFFFFFF8E6CDBBF8FFFFFEF8FFFFFFF8FBF6
+ F2F8F8F1EDF8EABFA1DEC98960DEFFFFFF00FFFFFF00FFFFFF00FFFFFF00C786
+ 5BC9EFC09EC9D9A27DF8D39D7AF8D5A380F8DAAE8FF8D29A77F8D29B77F8D29C
+ 77F8D09771F8C88B62DEAD5A202FFFFFFF00FFFFFF00FFFFFF00FFFFFF00CC8D
+ 65C9F3CDB0C9FFFFFFC9E3C7B3C9FFFFFFC9FFFFFFC9FFFFFFC9FFFFFFC9EABF
+ A1C9C98960C9FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00D497
+ 6EC9D49E7BC9D09871C9D6A482C9CD8E68C9CD9069C9D09A75C9D19973C9C88B
+ 62C9AD5A202BFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00
+ }
+ OnClick = ActionSaveAllExecute
+ end
+ object MenuItemDivider2: TMenuItem
+ Caption = '-'
+ end
+ object MenuItemNewTab: TMenuItem
+ Action = ActionNewTab
+ Bitmap.Data = {
+ 36040000424D3604000000000000360000002800000010000000100000000100
+ 2000000000000004000064000000640000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 000004390000066D0099056900CC066D00990439000000000000000000090000
+ 00160000001A0000001A0000001A0000001A0000001A0000001A0000001A0000
+ 001A0000001A0B8000D12BDF1AFF0B8000D100000016000000090D0D0D671010
+ 1085101010851010108510101085101010851010108510101085101010850E62
+ 04CF0E7E02E70E7E02E73DE22CFF0E7E02E70E7E02E70B5F02B02727277BEBEB
+ EBFFE7E7E7FFE7E7E7FFE7E7E7FFE7E7E7FFE7E7E7FFE7E7E7FFE7E7E7FF3BA5
+ 2FFF52E741FF52E741FF52E741FF52E741FF52E741FF128905E532323276EAEA
+ EAFFE2E2E2FFE2E2E2FFE2E2E2FFE2E2E2FFE2E2E2FFE2E2E2FFE2E2E2FF66B9
+ 5BFF3CAB2DFF3CAB2DFF66EB55FF3CAB2DFF3EAD2FFF1C7A11C838383873EDED
+ EDFFE6E6E6FFE6E6E6FFE6E6E6FFE6E6E6FFE6E6E6FFE6E6E6FFE6E6E6FFE6E6
+ E6FFE6E6E6FF3EB12EFF75EE64FF3EB12EFFEDEDEDFF383838733E3E3E71F0F0
+ F0FFEBEBEBFFEBEBEBFFEBEBEBFFEBEBEBFFEBEBEBFFEBEBEBFFEBEBEBFFEBEB
+ EBFFEBEBEBFF6BC45FFF40B62FFF6BC45FFFF0F0F0FF3E3E3E714444446EF3F3
+ F3FFEFEFEFFFEFEFEFFFEFEFEFFFEFEFEFFFEFEFEFFFEFEFEFFFEFEFEFFFEFEF
+ EFFFEFEFEFFFEFEFEFFFEFEFEFFFEFEFEFFFF3F3F3FF4444446E4949496CF7F7
+ F7FFF4F4F4FFF4F4F4FFF4F4F4FFF4F4F4FFF4F4F4FFF4F4F4FFF4F4F4FFF4F4
+ F4FFF4F4F4FFF4F4F4FFF4F4F4FFF4F4F4FFF7F7F7FF4949496C4D4D4D6AFAFA
+ FAFFF8F8F8FFF8F8F8FFF8F8F8FFF8F8F8FFF8F8F8FFF8F8F8FFF8F8F8FFF8F8
+ F8FFF8F8F8FFF8F8F8FFF8F8F8FFF8F8F8FFFAFAFAFF4D4D4D6A51515168FDFD
+ FDFFFCFCFCFFFCFCFCFFFCFCFCFFFCFCFCFFFCFCFCFFFCFCFCFFFCFCFCFFFCFC
+ FCFFFCFCFCFFFCFCFCFFFCFCFCFFFCFCFCFFFDFDFDFF5151516855555567FFFF
+ FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+ FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5555556750505069BBBB
+ BBFFBABABAFFB8B8B8FFB6B6B6FFB3B3B3FFB0B0B0FFAEAEAEFFABABABFFA8A8
+ A8FFA6A6A6FFA3A3A3FFA0A0A0FF9E9E9EFF9C9C9CFF030303665252525BC6C6
+ C6D4DCDCDCFFD8D9D9FFD5D5D5FFD0D1D1FFCCCCCCFFC8C8C8FFC6C6C6FFC6C5
+ C5FFC9C5C5FFCDC6C6FFD1C7C7FFD7CBCBFFC4B8B8D45252525B555555225555
+ 5559555555665555556655555566555555665555556655555566555555665555
+ 5566555555665555556655555566555555665555555955555522FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00
+ }
+ OnClick = ActionNewTabExecute
+ end
+ object MenuItemCloseTab: TMenuItem
+ Action = ActionCloseTab
+ Bitmap.Data = {
+ 36040000424D3604000000000000360000002800000010000000100000000100
+ 2000000000000004000064000000640000000000000000000000FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00000000090000
+ 00160000001A0000001A0000001A0000001A0000001A0000001A0000001A0000
+ 001A0000001A0000001A0000001A0000001A00000016000000090D0D0D671010
+ 1085101010851010108510101085101010851010108510101085101010850404
+ 5BCF020273E7020273E7020273E7020273E7020273E7020258B02727277BEBEB
+ EBFFE7E7E7FFE7E7E7FFE7E7E7FFE7E7E7FFE7E7E7FFE7E7E7FFE7E7E7FF2F2F
+ A7FF5E5EF7FF5E5EF7FF5E5EF7FF5E5EF7FF5E5EF7FF05058BE532323276EAEA
+ EAFFE2E2E2FFE2E2E2FFE2E2E2FFE2E2E2FFE2E2E2FFE2E2E2FFE2E2E2FF5B5B
+ BEFF2D2DB3FF2D2DB3FF2D2DB3FF2D2DB3FF2F2FB5FF111181C838383873EDED
+ EDFFE6E6E6FFE6E6E6FFE6E6E6FFE6E6E6FFE6E6E6FFE6E6E6FFE6E6E6FFE6E6
+ E6FFE6E6E6FFE6E6E6FFE6E6E6FFE6E6E6FFEDEDEDFF383838733E3E3E71F0F0
+ F0FFEBEBEBFFEBEBEBFFEBEBEBFFEBEBEBFFEBEBEBFFEBEBEBFFEBEBEBFFEBEB
+ EBFFEBEBEBFFEBEBEBFFEBEBEBFFEBEBEBFFF0F0F0FF3E3E3E714444446EF3F3
+ F3FFEFEFEFFFEFEFEFFFEFEFEFFFEFEFEFFFEFEFEFFFEFEFEFFFEFEFEFFFEFEF
+ EFFFEFEFEFFFEFEFEFFFEFEFEFFFEFEFEFFFF3F3F3FF4444446E4949496CF7F7
+ F7FFF4F4F4FFF4F4F4FFF4F4F4FFF4F4F4FFF4F4F4FFF4F4F4FFF4F4F4FFF4F4
+ F4FFF4F4F4FFF4F4F4FFF4F4F4FFF4F4F4FFF7F7F7FF4949496C4D4D4D6AFAFA
+ FAFFF8F8F8FFF8F8F8FFF8F8F8FFF8F8F8FFF8F8F8FFF8F8F8FFF8F8F8FFF8F8
+ F8FFF8F8F8FFF8F8F8FFF8F8F8FFF8F8F8FFFAFAFAFF4D4D4D6A51515168FDFD
+ FDFFFCFCFCFFFCFCFCFFFCFCFCFFFCFCFCFFFCFCFCFFFCFCFCFFFCFCFCFFFCFC
+ FCFFFCFCFCFFFCFCFCFFFCFCFCFFFCFCFCFFFDFDFDFF5151516855555567FFFF
+ FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+ FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5555556750505069BBBB
+ BBFFBABABAFFB8B8B8FFB6B6B6FFB3B3B3FFB0B0B0FFAEAEAEFFABABABFFA8A8
+ A8FFA6A6A6FFA3A3A3FFA0A0A0FF9E9E9EFF9C9C9CFF030303665252525BC6C6
+ C6D4DCDCDCFFD8D9D9FFD5D5D5FFD0D1D1FFCCCCCCFFC8C8C8FFC6C6C6FFC6C5
+ C5FFC9C5C5FFCDC6C6FFD1C7C7FFD7CBCBFFC4B8B8D45252525B555555225555
+ 5559555555665555556655555566555555665555556655555566555555665555
+ 5566555555665555556655555566555555665555555955555522FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00
+ }
+ OnClick = ActionCloseTabExecute
+ end
+ object MenuItemCloseTabs: TMenuItem
+ Caption = 'Close all tabs'
+ Bitmap.Data = {
+ 36040000424D3604000000000000360000002800000010000000100000000100
+ 20000000000000040000640000006400000000000000000000000000000A0000
+ 00180000001A0000001A0000001A0000001A0000001A0000001A0000001A0000
+ 001A0000001A000000190000000B000000000000770000008000111111651414
+ 1483141414831414148314141483141414831414148314141483141414831414
+ 148314141483141414831111116500005A0000007700000080002D2D2D78ECEC
+ ECFFE8E8E8FFE8E8E8FFE8E8E8FFE8E8E8FFE8E8E8FFE8E8E8FFE8E8E8FF5F5F
+ ADFF2F2F95FF303096FF050577E4000080CC000080CC0000849936363674EBEB
+ EBFFE4E4E4FFE4E4E4FFE4E4E4FFE4E4E4FFE4E4E4FFE4E4E4FFE4E4E4FF2E2E
+ A7FF5E5EF7FF5E5EF7FF5E5EF7FF5E5EF7FF5E5EF7FF000098CC3D3D3D71EFEF
+ EFFFEAEAEAFFEAEAEAFFEAEAEAFFEAEAEAFFEAEAEAFFEAEAEAFFEAEAEAFF5E5E
+ C2FF2F2FB5FF3030B6FF06069AE60000A3D10000A4D100007C9E4545456EF4F4
+ F4FFF0F0F0FFF0F0F0FFF0F0F0FFF0F0F0FFF0F0F0FFF0F0F0FFF0F0F0FFF0F0
+ F0FFF0F0F0FFF4F4F4FF313131B81414148314141483111111654B4B4B6BF8F8
+ F8FFF6F6F6FFF6F6F6FFF6F6F6FFF6F6F6FFF6F6F6FFF6F6F6FFF6F6F6FFF6F6
+ F6FFF6F6F6FFF8F8F8FFA6A6A6FFE8E8E8FFECECECFF2D2D2D7850505069FCFC
+ FCFFFBFBFBFFFBFBFBFFFBFBFBFFFBFBFBFFFBFBFBFFFBFBFBFFFBFBFBFFFBFB
+ FBFFFBFBFBFFFCFCFCFFA8A8A8FFE4E4E4FFEBEBEBFF3636367454545467FFFF
+ FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+ FFFFFFFFFFFFFFFFFFFFAEAEAEFFEAEAEAFFEFEFEFFF3D3D3D7150505069BBBB
+ BBFFB9B9B9FFB6B6B6FFB4B4B4FFB0B0B0FFADADADFFA9A9A9FFA6A6A6FFA2A2
+ A2FFA0A0A0FF9D9D9DFF919191FFF0F0F0FFF4F4F4FF4545456E5252525BC6C6
+ C6D4DBDBDBFFD6D6D6FFD1D1D1FFCBCCCCFFC7C7C7FFC6C4C4FFC8C5C5FFCEC6
+ C6FFD4C9C9FFD0C5C5FFBCBCBCFFF6F6F6FFF8F8F8FF4B4B4B6B555555225555
+ 555955555566535353A5B9B9B9FFB8B8B8FFB8B8B8FFB8B8B8FFB8B8B8FFB8B8
+ B8FFB8B8B8FFC1C1C1FFE5E5E5FFFBFBFBFFFCFCFCFF50505069555555005555
+ 55005555550054545467FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+ FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF54545467555555005454
+ 54005050500050505069BBBBBBFFB9B9B9FFB6B6B6FFB4B4B4FFB0B0B0FFADAD
+ ADFFA9A9A9FFA6A6A6FFA2A2A2FFA0A0A0FF9D9D9DFF03030366545454005252
+ 5200525252005252525BC6C6C6D4DBDBDBFFD6D6D6FFD1D1D1FFCBCCCCFFC7C7
+ C7FFC6C4C4FFC8C5C5FFCEC6C6FFD4C9C9FFC4B7B7D45252525B545454005454
+ 5400545454005555552255555559555555665555556655555566555555665555
+ 5566555555665555556655555566555555665555555955555522
+ }
+ ImageIndex = 20
+ OnClick = MenuItemCloseTabsClick
+ end
+ object MenuItemDivider6: TMenuItem
+ Caption = '-'
+ end
+ object MenuItemMainExit: TMenuItem
+ Action = ActionExit
+ Bitmap.Data = {
+ 36040000424D3604000000000000360000002800000010000000100000000100
+ 2000000000000004000064000000640000000000000000000000FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF001D63
+ 9B1619609839145D9562105A92880D5890A4135C92FC0C578FED999999FF7171
+ 71FF545454FF515151FF4F4F4FFF4C4C4CFF4A4A4AFF474747FF454545FF2567
+ 9DFF3274A8FF3D7CAFFF4784B5FF4E8ABAFF3E7EADFF0C578FEAFFFFFF00FFFF
+ FF00585858FFA2A2A2FFA2A2A2FFA3A3A3FFA4A4A4FFA4A4A4FFA5A5A5FF2F6F
+ A5FF78ABD2FF78ABD3FF73A7D1FF69A0CDFF407FAEFF0F5991EAFFFFFF00FFFF
+ FF005C5C5CFFA1A1A1FF3C7340FFA0A1A1FFA3A3A3FFA3A3A3FFA4A4A4FF3674
+ AAFF7DAFD4FF5B9AC9FF5495C7FF5896C8FF4180AEFF135C94EAFFFFFF00FFFF
+ FF00606060FFA0A0A0FF3D7641FF367139FFA2A2A2FFA2A2A2FFA3A3A3FF3D79
+ B0FF82B3D7FF629FCCFF5A9AC9FF5E9BCAFF4381AFFF196098EA37823EFF347E
+ 3BFF317937FF2E7534FF499150FF468F4CFF39733DFFA1A1A1FFA2A2A2FF457E
+ B4FF88B7D9FF67A3CFFF619ECCFF639FCCFF4583B1FF1F649CEA3B8742FF89CB
+ 92FF84C88DFF80C688FF7BC383FF77C17FFF478F4DFF3B743FFFA1A1A1FF4C84
+ BAFF8DBBDBFF6EA8D1FF66A6D1FF5FB4DFFF4785B1FF2569A1EA3E8B46FF8FCE
+ 99FF7DC687FF78C381FF73C07CFF74C07CFF79C281FF49904FFF547F57FF5489
+ BFFF94BFDDFF75ADD4FF63B8E1FF4BD4FFFF428BB8FF2C6EA6EA41904AFF94D2
+ 9FFF91D09AFF8DCD96FF89CB92FF84C88DFF519858FF417C46FF9F9F9FFF5A8E
+ C4FF98C3E0FF7CB3D7FF74AFD6FF5EC4EDFF4B88B3FF3473ABEA44944DFF4291
+ 4BFF3F8D48FF3D8945FF5DA465FF5AA061FF45834BFF9E9E9EFF9E9E9EFF6092
+ C9FF9EC7E2FF83B8DAFF7DB4D7FF7EB3D7FF4F89B4FF3B79B1EAFFFFFF00FFFF
+ FF00777777FF9A9A9AFF3D8A45FF498A4FFF9C9C9CFF9D9D9DFF9D9D9DFF6696
+ CCFFA2CBE3FF89BDDCFF83B9DAFF84B9DAFF518BB5FF437EB6EAFFFFFF00FFFF
+ FF007A7A7AFF999999FF529159FF999A99FF9B9B9BFF9C9C9CFF9C9C9CFF6C9A
+ D0FFA7CEE5FF8FC1DFFF89BDDCFF8BBDDCFF538DB6FF4B84BCEAFFFFFF00FFFF
+ FF007D7D7DFF999999FF999999FF9A9A9AFF9A9A9AFF9B9B9BFF9B9B9BFF6F9D
+ D3FFAAD1E7FFABD1E7FF98C7E1FF91C2DEFF568FB7FF5289C1EAFFFFFF00FFFF
+ FF00808080FF7E7E7EFF7C7C7CFF7A7A7AFF777777FF757575FF727272FF719E
+ D4FF6F9ED6FF87B2DCFFABD3E8FFA9D0E6FF5890B8FF598EC6EAFFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00709ED6DB6D9CD4FF85B1DAFF5A91B9FF6093CBEAFFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF006D9CD4896A9AD2FB6697CFEE
+ }
+ OnClick = ActionExitExecute
+ end
+ end
+ object MenuEdit: TMenuItem
+ Caption = '&Edit'
+ SubMenuImages = Mufasa_Image_List
+ OnClick = MenuEditClick
+ object MenuItemUndo: TMenuItem
+ Action = ActionUndo
+ Bitmap.Data = {
+ 36040000424D3604000000000000360000002800000010000000100000000100
+ 2000000000000004000064000000640000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 00000000000018A6C3691AA7C46900A0C4180000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 00000000000000A0C45D66DBEAB211A6C2AE0000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 00000000000000A0C42243C4DBFC43C5D8FE23A6C07F00000000000000000000
+ 00000000000000000000000000000000000000A0C4FF00000000000000000000
+ 000000000000000000000EAACBFE5DDAE9FE23A6C0EF00000000000000000000
+ 000000000000000000000000000000A0C4FF00A0C4FF00000000000000000000
+ 000000000000009EC11A02ACC8FF88E7F2FE11A2C2FF00000000000000000000
+ 00000000000005797D1100A0C4FF76EDFBFF00A0C4FF000000000000000000A0
+ C4300099B95000A0C4C96DE6F5FF76E2EFFF19A3C1FF00000000000000000000
+ 000005797D1100A0C4FF76EDFBFF76EDFBFF00A0C4FF00A0C4FF00A0C4FF00A0
+ C4FF01A9C4FF6EE1EEFF0FC9DFFF69E4F2FF1AA4C0F800000000000000000579
+ 7D1100A0C4FF76EDFBFF04C3DAFF76EDFBFF69EAF9FF69EAF9FF69EAF9FF69EA
+ F9FF05DDF7FF0AC8DFFF07C2D8FF6FDCEBFF1BA3BFF40000000005797E1100A0
+ C4FF79EDFBFF32E2F8FF2CDFF4FF04C0D6FF04C0D6FF04C0D6FF1DD2E8FF1DD2
+ E8FF1DD2E8FF0BC8DFFF6AE5F3FF1BABC5F815A0BCCB0000000000A0C4FFADF3
+ FBFF2FE0F6FF32E2F8FF32E2F7FF32E2F7FF2FE0F5FF29DBF1FF1DD2E8FF1DD2
+ E8FF1DD2E8FF36D9ECFF40CDE1FF16A1BDCA05797D0A0000000005797D0A00A0
+ C4FFADF3FBFF2FE0F6FF32E2F7FF29DBF1FF2FE0F5FF29DBF1FF16CDE3FF36D9
+ ECFF69E7F6FF41CEE3FE13A3C1E405797D320000000000000000000000000579
+ 7D1100A0C4FFADF3FBFF31E1F6FF20E3FAFF73ECFAFF6FEBFAFF6EE8F7FF6CE8
+ F7F814A1BCD414A3C1D505797D1C000000000000000000000000000000000000
+ 000005797D1100A0C4FFADF3FBFF25E4FBFF00A0C4FF00A0C4FF13A1BEE7159F
+ BBCF1BA1BBA4067A7C0B00000000000000000000000000000000000000000000
+ 00000000000005797D1100A0C4FFADF3FBFF00A0C4FF00000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 00000000000000000000009DBF1400A0C4FF00A0C4FF00000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 00000000000000000000000000000000000000A0C4FF00000000000000000000
+ 0000000000000000000000000000000000000000000000000000
+ }
+ OnClick = ActionUndoExecute
+ end
+ object MenuItemRedo: TMenuItem
+ Action = ActionRedo
+ Bitmap.Data = {
+ 36040000424D3604000000000000360000002800000010000000100000000100
+ 2000000000000004000064000000640000000000000000000000FFFFFF000000
+ 000000A0C4181AA7C46918A6C369000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000FFFFFF000000
+ 000011A6C2AE66DBEAB200A0C45D000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000FFFFFF0023A6
+ C07F43C5D8FE43C4DBFC00A0C422000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000FFFFFF0023A6
+ C0EF5DDAE9FE0EAACBFE000000000000000000000000000000000000000000A0
+ C4FF000000000000000000000000000000000000000000000000FFFFFF0011A2
+ C2FF88E7F2FE02ACC8FF009EC11A0000000000000000000000000000000000A0
+ C4FF00A0C4FF0000000000000000000000000000000000000000FFFFFF0019A3
+ C1FF76E2EFFF6DE6F5FF00A0C4C90099B95000A0C430000000000000000000A0
+ C4FF76EDFBFF00A0C4FF05797D11000000000000000000000000FFFFFF001AA4
+ C0F869E4F2FF0FC9DFFF6EE1EEFF01A9C4FF00A0C4FF00A0C4FF00A0C4FF00A0
+ C4FF76EDFBFF76EDFBFF00A0C4FF05797D110000000000000000FFFFFF001BA3
+ BFF46FDCEBFF07C2D8FF0AC8DFFF05DDF7FF69EAF9FF69EAF9FF69EAF9FF69EA
+ F9FF76EDFBFF04C3DAFF76EDFBFF00A0C4FF05797D1100000000FFFFFF0015A0
+ BCCB1BABC5F86AE5F3FF0BC8DFFF1DD2E8FF1DD2E8FF1DD2E8FF04C0D6FF04C0
+ D6FF04C0D6FF2CDFF4FF32E2F8FF79EDFBFF00A0C4FF05797E11FFFFFF000579
+ 7D0A16A1BDCA40CDE1FF36D9ECFF1DD2E8FF1DD2E8FF1DD2E8FF29DBF1FF2FE0
+ F5FF32E2F7FF32E2F7FF32E2F8FF2FE0F6FFADF3FBFF00A0C4FFFFFFFF000000
+ 000005797D3213A3C1E441CEE3FE69E7F6FF36D9ECFF16CDE3FF29DBF1FF2FE0
+ F5FF29DBF1FF32E2F7FF2FE0F6FFADF3FBFF00A0C4FF05797D0AFFFFFF000000
+ 00000000000005797D1C14A3C1D514A1BCD46CE8F7F86EE8F7FF6FEBFAFF73EC
+ FAFF20E3FAFF31E1F6FFADF3FBFF00A0C4FF05797D1100000000FFFFFF000000
+ 00000000000000000000067A7C0B1BA1BBA4159FBBCF13A1BEE700A0C4FF00A0
+ C4FF25E4FBFFADF3FBFF00A0C4FF05797D110000000000000000FFFFFF000000
+ 00000000000000000000000000000000000000000000000000000000000000A0
+ C4FFADF3FBFF00A0C4FF05797D11000000000000000000000000FFFFFF000000
+ 00000000000000000000000000000000000000000000000000000000000000A0
+ C4FF00A0C4FF009DBF1400000000000000000000000000000000FFFFFF000000
+ 00000000000000000000000000000000000000000000000000000000000000A0
+ C4FF000000000000000000000000000000000000000000000000
+ }
+ OnClick = ActionRedoExecute
+ end
+ object MenuItemDivider3: TMenuItem
+ Caption = '-'
+ end
+ object MenuItemCut: TMenuItem
+ Action = ActionCut
+ Bitmap.Data = {
+ 36040000424D3604000000000000360000002800000010000000100000000100
+ 2000000000000004000064000000640000000000000000000000FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00020D8C0A1C27A69F353F
+ C9F7222DAFB9030D8C1CFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00050F8D1F06108E26010B8A03FFFFFF00121C9B70404BD9FF2C35
+ BFDD3D47D1FF1D27A9A4FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF000F199763323DC7F83741CFFF1F29ABB0000A8618232DB4AF3540CCFD0009
+ 85181C27A895343EC5F8040E8C14FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF002F3ABDDE353FC9E52530B3C23F4ADDFF1F2AACC22430B2CB323CC6F2000A
+ 8603111B9D773741C8FF08128E20FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00323CC3EC232EADAFFFFFFF001A25A8994250D2FFCBA375FE414FD6FF1621
+ A39D2F39C0D42E38BEDF020D8B0AFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF001D28A99C3B46CCFF0812903A071190533B48D4FFDBBD9CFFEECCA6FF404C
+ DEFF3A43D1FF0F199869FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00030D8C1F2C35B9D73C46CFFF333ECAF23F4CD7FFD8BC9AFFF6EAE1FFBB92
+ 5ABF9462183B91611A01FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00030D8C1F1B26A7992A34BACC111C9D89BB9869CCF0E0D0FFB791
+ 5FC58F5D140BFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00000B8802FFFFFF00B48E5A90F6EADDFFE1CD
+ B4FFB18D5DBFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00B38C5789F1E2D4FFCEB2
+ 8EF4F5EBE0FFA67F4A9DFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00B1895384EEDFCEFF9766
+ 2065C2A37CDAE9D8C5FDA9824E7BFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00AF87507CE7D5C1FF9565
+ 1F2B8F5C121BC5A783E7D5BC9DE1B5936462FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00AC834B75DEC9AFFF9564
+ 1D1FFFFFFF0092601726C3A47CEBB59063CBFFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00AA81476FD6BD9FF79361
+ 1910FFFFFF00FFFFFF009666202CA9804BCBFFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00A87D4269CCB08BE0915D
+ 1409FFFFFF00FFFFFF00FFFFFF0092601706FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF009A6B2731AA7E43A19260
+ 1805FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00
+ }
+ OnClick = ActionCutExecute
+ end
+ object MenuItemCopy: TMenuItem
+ Action = ActionCopy
+ Bitmap.Data = {
+ 36040000424D3604000000000000360000002800000010000000100000000100
+ 2000000000000004000064000000640000000000000000000000FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00C57342C1C67545E6C87545FEC775
+ 45F3C87545F3C77545F3C77545F3C87546F4C57444E8CA7F53F1FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00C77949EDFCF3ECFFFAF1E8FFFAF0
+ E7FFFBF1E9FFFBF2EAFFFBF2EAFFFBF2EBFFFDF4EEFFCA8054F9FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00CF8253FFEFF1E7FFFFE9D9FFFFEA
+ DBFFFFE9D9FFFFE7D7FFFFE5D2FFFFE2CBFFEFF2E8FFCE8156FFFFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00CC8352FBFBF5EEFFFFE9D9FFFFEA
+ DBFFFFE9D9FFFFE7D7FFFFE5D2FFFFE2CBFFFBF6EFFFCC8355FEC7794AB9C879
+ 4BCEC87545DDC77545D4C87545D4C77545D4CA8452FFFFF7F1FFFFE9D9FFFFEA
+ DBFFFFE9D9FFFFE7D7FFFFE5D2FFFFE2CBFFFFF7F1FFCB8555FEC87C4ED3FCF3
+ ECDEFAF1E8DEFAF0E7DEFBF1E9DEFBF2EADEE4BA91FFFFF7F0FFFFE7D5FFFDE7
+ D6FFFDE6D4FFFCE4D0FFFBE3CBFFFADCC2FFFEF3E8FFCC8656FECF8253DEEFF1
+ E7DEFFE9D9DEFFEADBDEFFE9D9DEFFE7D7DEE4BB91FFFFF7F2FFFEE7D5FFFEE7
+ D5FFFDE5D1FFFAE0CAFFF9DEC4FFF7D9BCFFFDF2E7FFCC8757FECC8352DBFBF5
+ EEDEFFE9D9DEFFEADBDEFFE9D9DEFFE7D7DEE4BB92FFFEF7F1FFFCE5D2FFFCE4
+ D1FFFBE2CCFFF9DDC4FFF6D7BBFFF3D1AFFFFAEFE4FFCC8758FECA8452DBFFF7
+ F1DEFFE9D9DEFFEADBDEFFE9D9DEFFE7D7DEE4BB92FFFEF6F0FFFCE2CDFFFCE3
+ CDFFFADFC8FFF7D9BCFFF5E9DDFFFAF3EBFFFBF8F3FFCA8353FECB8553DBFFF7
+ F0DEFFE7D5DEFDE7D6DEFDE6D4DEFCE4D0DEE4BB93FFFEF5EDFFFCDEC5FFFBE0
+ C7FFF9DCC2FFF5D3B4FFFEF9F3FFFAE2C4FFECC193FFC37D4893CB8654DBFFF7
+ F2DEFEE7D5DEFEE7D5DEFDE5D1DEFAE0CADEE5BE96FFFFFFFEFFFDF3E9FFFDF3
+ EAFFFCF2E8FFFAEFE3FFFAF2E7FFEABB88FFCF8555B3B4693D0CCB8655DBFEF7
+ F1DEFCE5D2DEFCE4D1DEFBE2CCDEF9DDC4DEEAC39DFFE6BF96FFE4BB92FFE4BB
+ 92FFD1A06CF5D09E6DF6CC965FDAC479427EB2673C09FFFFFF00CB8655DBFEF6
+ F0DEFCE2CDDEFCE3CDDEFADFC8DEF7D9BCDEF5E9DDDEFAF3EBDEFBF8F3DECD95
+ 65DCFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00CB8656DAFEF5
+ EDDEFCDEC5DEFBE0C7DEF9DCC2DEF5D3B4DEFEF9F3DEFAE2C4DEECC193DEC37D
+ 4880FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00CA8554D0FFFF
+ FFDBFDF3E9DEFDF3EADEFCF2E8DEFAEFE3DEFAF2E7DEEABB88DECF85559CB469
+ 3D0AFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00C77947AACC86
+ 55CECC8857DECB8856DBCC8856DBCB8757DBCA8350D0C479426EB2673C08FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00
+ }
+ OnClick = ActionCopyExecute
+ end
+ object MenuItemPaste: TMenuItem
+ Action = ActionPaste
+ Bitmap.Data = {
+ 36040000424D3604000000000000360000002800000010000000100000000100
+ 2000000000000004000064000000640000000000000000000000FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF005E5E5E025B5B5B775858588A5555558A5252
+ 528A4F4F4F8A4C4C4C8A4A4A4A8A4848488A4646468A444444662063984A2063
+ 98CF206398FF206398FF206398FF246395FF587388FFF7F7F7FFF0F0F0FFF0F0
+ F0FFF0F0F0FFF0F0F0FFF0F0F0FFF0F0F0FFF3F3F3FA46464684206398C262A5
+ D7FF65A8DAFF64A6D9FF62A4D8FF629FD1FF758EA4FFEFEFEFFFE7E7E7FFE7E7
+ E7FFE7E7E7FFE7E7E7FFE6E6E6FFE6E6E6FFECECECFA49494984206398FF68AB
+ DCFF488ECFFF468BCEFF4387CDFF4484C6FF6885A1FFF0F0F0FFB4B4B4FFB4B4
+ B4FFB4B4B4FFB4B4B4FFB4B4B4FFB3B3B3FFEDEDEDFA4C4C4C84206398FF69AE
+ DCFF4A93D1FF488FD0FF468BCEFF4788C7FF6C88A3FFF0F0F0FFE8E8E8FFE8E8
+ E8FFE7E7E7FFE7E7E7FFE7E7E7FFE7E7E7FFEDEDEDFA4F4F4F84206398FF6BB1
+ DEFF4D97D3FF4B93D2FF488FD0FF4A8CC9FF6F8BA5FFF1F1F1FFB6B6B6FFB5B5
+ B5FFB5B5B5FFB4B4B4FFB4B4B4FFB4B4B4FFEDEDEDFA53535384206398FF6DB3
+ DFFF509CD5FF4E98D3FF4B94D1FF4C91CBFF708EA7FFF1F1F1FFE9E9E9FFE9E9
+ E9FFE8E8E8FFE8E8E8FFE8E8E8FFE7E7E7FFEDEDEDFA56565684206398FF70B5
+ E0FF529FD7FF509CD6FF4E98D4FF4F95CDFF7391AAFFF1F1F1FFB7B7B7FFB6B6
+ B6FFB6B6B6FFB6B6B6FFB5B5B5FFB5B5B5FFEEEEEEFA5A5A5A84206398FF73B7
+ E1FF57A3D7FF53A0D7FF509DD5FF5299CFFF7594ACFFF8F8F8FFF2F2F2FFF2F2
+ F2FFF2F2F2FFF2F2F2FFF2F2F2FFF1F1F1FFF4F4F4FA5E5E5E84206398FF76B9
+ E2FF5CA7D9FF58A4D8FF53A0D7FF539ED5FF618BA9FF6488A1FF6487A1FF6386
+ A0FF69879FFF4A6881FF6A6A6A8A6868688A6565658A62626263206398FF7ABB
+ E3FF61AADBFF5AA5D9FF53A0D7FF529FD7FF529FD7FF529FD7FF529FD7FF529F
+ D7FF62A3D8FF206398FFFFFFFF00FFFFFF00FFFFFF00FFFFFF00206398FF7CBD
+ E4FF65AEDDFF62ABDCFF5EA8DAFF5CA7D9FF5CA7D9FF5CA7D9FF5CA7D9FF529F
+ D7FF62A3D8FF206398FFFFFFFF00FFFFFF00FFFFFF00FFFFFF00206398FF7FBF
+ E4FF69B2DEFF4A9BDAFF4497DCFF4396DCFF4296DCFF4295DCFF4195DBFF519E
+ D6FF6CB2DEFF206398FFFFFFFF00FFFFFF00FFFFFF00FFFFFF00206398E071B3
+ DBFE7EBFE4FF4E9DDFFFB5EEFDFF75D4F0FF75D4F0FFB5EEFDFF4B9BDEFF6EB4
+ E0FF6DB3DFF9206398F3FFFFFF00FFFFFF00FFFFFF00FFFFFF00206398322063
+ 98B2206398FF3775A4FFB6EFFEFF80DBF3FF80DBF3FFB6EFFEFF2E6EA1FF2063
+ 98FF206398A520639853FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF002063982A206398FF206398FF206398FF206398FF206398FF206398F0FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00
+ }
+ OnClick = ActionPasteExecute
+ end
+ object MenuItemDelete: TMenuItem
+ Action = ActionDelete
+ Bitmap.Data = {
+ 36040000424D3604000000000000360000002800000010000000100000000100
+ 2000000000000004000064000000640000000000000000000000FFFFFF00FFFF
+ FF00000000060000000E000000160000001E000000250000002A0000002B0000
+ 0029000000240000001D000000150000000D00000004FFFFFF00FFFFFF00FFFF
+ FF000000FF010000D346FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF000000D3460000FF01FFFFFF00FFFFFF00FFFFFF000000
+ FF010000CE960000CEFF0000CE78FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF000000CE780000CFFF0000CF960000FF01FFFFFF00FFFFFF000000
+ C8460000C8FF0000C8FF0000C9FF0000CA78FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF000000CA780000C9FF0000C9FF0000C9FF0000C846FFFFFF00FFFFFF00FFFF
+ FF000000C1780000C3FF0000C3FF0000C3FF0000C478FFFFFF00FFFFFF000000
+ C4780000C3FF0000C3FF0000C3FF0000C478FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF000000BD780000BDFF0000BDFF0000BDFF0000BD780000BD780000
+ BDFF0000BDFF0000BDFF0000BD78FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF000000B7780000B7FF0000B7FF0000B7FF0000B7FF0000
+ B7FF0000B7FF0000B778FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF000000B0780000B1FF0000B1FF0000B1FF0000
+ B1FF0000B378FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF000000AA780000ABFF0000ABFF0000ABFF0000
+ ACFF0000AC78FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF000000A6780000A5FF0000A5FF0000A5FF0000A6FF0000
+ A6FF0000A6FF0000A678FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF0000009F7800009FFF00009FFF00009FFF00009F7800009F780000
+ A0FF0000A0FF0000A0FF00009F78FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF0000009978000099FF000099FF000099FF00009978FFFFFF00FFFFFF000000
+ 997800009AFF00009AFF00009AFF00009978FFFFFF00FFFFFF00FFFFFF000000
+ 9246000093FF000093FF000093FF00009578FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF0000009578000094FF000094FF000094FF00009546FFFFFF00FFFFFF000000
+ FF0100008D9600008DFF00008E78FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF0000008E7800008EFF00008F960000FF01FFFFFF00FFFFFF00FFFF
+ FF000000FF0100008746FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00000087460000FF01FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00
+ }
+ OnClick = ActionDeleteExecute
+ end
+ object MenuItemDivider4: TMenuItem
+ Caption = '-'
+ end
+ object MenuItemSelectAll: TMenuItem
+ Action = ActionSelectAll
+ OnClick = ActionSelectAllExecute
+ end
+ object MenuItemDivider5: TMenuItem
+ Caption = '-'
+ end
+ object MenuItemFind: TMenuItem
+ Action = ActionFindStart
+ Bitmap.Data = {
+ 36040000424D3604000000000000360000002800000010000000100000000100
+ 2000000000000004000064000000640000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000001010120020202CF141414FF393939CF000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 00000000000001010130020202EF151515FF3A3A3AFF606060FF000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 000001010130020202EF151515FF3B3B3BFF606060FF808080CF000000000000
+ 0000000000000000000000000000000000000000000000000000000000000101
+ 0130020202EF151515FF3B3B3BFF616161FF818181CF8C8C8C10000000000000
+ 0000000000008C8C8C508C8C8C9F8C8C8CBF8C8C8CBF8C8C8C8F545454500202
+ 02EF161616FF3B3B3BFF616161FF818181CF8C8C8C1000000000000000008C8C
+ 8C108C8C8CBF8C8C8CFFA29F9AFFBEB6ABFFB7B0A5FF9A9894FF8C8C8CFF6060
+ 60FF3C3C3CFF616161FF818181CF8C8C8C1000000000000000008C8C8C108C8C
+ 8CCFA29F9CFFE9DFCFFFFFF0DAFFFFEED5FFFFECD0FFFFEBCCFFDBCCB5FF9392
+ 90FF7C7C7CFF818181CF8C8C8C100000000000000000000000008C8C8C809393
+ 92FFF1E8DCFFFFF4E3FFFFF2DEFFFFF0D9FFFFEED5FFFFECD0FFFFEBCCFFDBCC
+ B5FF8C8C8CFF8C8C8C50000000000000000000000000000000008C8C8CEFBEBC
+ B7FFFFF7ECFFFFF5E7FFFFF4E2FFFFF2DEFFFFF0D9FFFFEED5FFFFECD0FFFFEB
+ CBFFA29E97FF8C8C8CAF000000000000000000000000000000008C8C8CFFE2DF
+ DAFFFFF9F0FFFFF7EBFFFFF5E7FFFFF4E2FFFFF2DDFFFFF0D9FFFFEED4FFFFEC
+ D0FFC6BBACFF8C8C8CCF000000000000000000000000000000008C8C8CFFE2E0
+ DDFFFFFBF4FFFFF9F0FFFFF7EBFFFFF5E6FFFFF3E2FFFFF2DDFFFFF0D9FFFFEE
+ D4FFC6BCAEFF8C8C8CEF000000000000000000000000000000008C8C8CFFD4D3
+ D2FFFFFCF9FFFFFBF4FFFFF9EFFFFFF7EBFFFFF5E6FFFFF3E2FFFFF2DDFFFFF2
+ DDFFB7B1A7FF8C8C8CBF000000000000000000000000000000008C8C8CAF9A9A
+ 9AFFFFFEFDFFFFFCF8FFFFFBF4FFFFF9EFFFFFF7EAFFFFF6E8FFFFFAF2FFF1E8
+ DBFF939291FF8C8C8C70000000000000000000000000000000008C8C8C308C8C
+ 8CFFB7B7B7FFFFFEFDFFFFFEFCFFFFFDF9FFFFFDF9FFFFFEFCFFF8F2E8FFA29F
+ 9CFF8C8C8CDF8C8C8C1000000000000000000000000000000000000000008C8C
+ 8C608C8C8CFF9A9A9AFFD4D3D2FFE2E1DFFFE2E0DCFFCDC9C3FF939392FF8C8C
+ 8CEF8C8C8C300000000000000000000000000000000000000000000000000000
+ 00008C8C8C308C8C8CAF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CEF8C8C8C9F8C8C
+ 8C10000000000000000000000000000000000000000000000000
+ }
+ OnClick = ActionFindstartExecute
+ end
+ object MenuItemFindNext: TMenuItem
+ Action = ActionFindNext
+ OnClick = ActionFindNextExecute
+ end
+ object MenuItemReplace: TMenuItem
+ Action = ActionReplace
+ OnClick = ActionReplaceExecute
+ end
+ end
+ object MenuItemScript: TMenuItem
+ Caption = '&Script'
+ SubMenuImages = Mufasa_Image_List
+ object MenuItemRun: TMenuItem
+ Action = ActionRunScript
+ Bitmap.Data = {
+ 36040000424D3604000000000000360000002800000010000000100000000100
+ 2000000000000004000064000000640000000000000000000000000000000000
+ 000004733AFF21824FFF638272FF000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 000004733AFF7ACFA4FF2C8C5AFF3D7659FFAEAEAEFF00000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 000004733AFF82D8ACFF76D6A6FF3C9D6AFF27744CFFACAEADFF000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 000009773FFF83DBAEFF1FC671FF72DEA7FF4BB27FFF177445FFA8ADAAFF0000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 000004733AFF83DCAFFF11C369FF1ACC73FF69DFA3FF5AC28DFF137643FF9EA7
+ A3FF000000000000000000000000000000000000000000000000000000000000
+ 000004733AFFA9DCC1FF10BD65FF11C167FF13C269FF59D395FF67C998FF167C
+ 47FF889C92FF0000000000000000000000000000000000000000000000000000
+ 000004733AFFA9DCC1FF0DB35EFF0EB660FF0EB660FF0DB45FFF47C484FF70CA
+ 9CFF1D824DFF678C79FF00000000000000000000000000000000000000000000
+ 000004733AFFA9DCC1FF0CAA58FF12AE5EFF15AF60FF16AD61FF13AA5DFF3AB6
+ 77FF75C79DFF288957FF4E8367FF000000000000000000000000000000000000
+ 000004733AFFA9DCC1FF2EAD6BFF2BAD6AFF27AB68FF22A964FF1CA55FFF41B2
+ 78FF78C69FFF298858FF678C79FF000000000000000000000000000000000000
+ 000004733AFFA9DCC1FF36AD70FF32AC6DFF2DAA6AFF28A866FF58BC89FF78C5
+ 9DFF1F804EFF839A8EFF00000000000000000000000000000000000000000000
+ 000004733AFFA9DCC1FF3EB176FF3AAF73FF36AE70FF6FC598FF71BF97FF187B
+ 49FFA6B0ABFF0000000000000000000000000000000000000000000000000000
+ 000004733AFFA9DCC1FF45B47BFF47B47CFF82CCA6FF67B68CFF177745FFC1C5
+ C3FF000000000000000000000000000000000000000000000000000000000000
+ 000004733AFFA5DABFFF57BB87FF90D2B0FF5BAB82FF23774CFFD4D5D4FF0000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 000004733AFFA9DCC1FF9BD5B7FF4C9F73FF3D7D5CFF00000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 000004733AFFA4D9BEFF3D9366FF5F8873FF0000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 000004733AFF2D8859FF859C90FF000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000
+ }
+ ImageIndex = 6
+ OnClick = ActionRunExecute
+ end
+ object MenuItemPause: TMenuItem
+ Action = ActionPauseScript
+ Bitmap.Data = {
+ 36040000424D3604000000000000360000002800000010000000100000000100
+ 2000000000000004000064000000640000000000000000000000EEEEEE00EEEE
+ EE00EEEEEE00987050FFA46534FFA46534FF987050FFFBE3BC00FBE3BC009870
+ 50FFA46534FFA46534FF987050FF000000000000000000000000987050009870
+ 5000987050009F683EFFC99C76FFCDA585FF9F683EFF98705000987050009F68
+ 3EFFC99C76FFCDA585FF9F683EFF000000000000000000000000A2663800A266
+ 3800A2663800A36535FFD7AC88FFE1C5ADFFA36535FFA2663800A2663800A365
+ 35FFD7AC88FFE1C5ADFFA36535FF000000000000000000000000A4653400A465
+ 3400A4653400A46534FFD8A981FFE6CCB5FFA46534FFA4653400A4653400A465
+ 34FFD8A981FFE6CCB5FFA46534FF000000000000000000000000A4653400A465
+ 3400A4653400A46534FFD7A77FFFE6CCB5FFA46534FFA4653400A4653400A465
+ 34FFD7A77FFFE6CCB5FFA46534FF000000000000000000000000A4653400A465
+ 3400A4653400A46534FFD7A981FFE6CDB6FFA46534FFA4653400A4653400A465
+ 34FFD7A981FFE6CDB6FFA46534FF000000000000000000000000A4653400A465
+ 3400A4653400A46534FFD8AB84FFE6CEB7FFA46534FFA4653400A4653400A465
+ 34FFD8AB84FFE6CEB7FFA46534FF000000000000000000000000A4653400A465
+ 3400A4653400A46534FFD9AE89FFE6CEB7FFA46534FFA4653400A4653400A465
+ 34FFD9AE89FFE6CEB7FFA46534FF000000000000000000000000A4653400A465
+ 3400A4653400A46534FFD9B08DFFE6CEB7FFA46534FFA4653400A4653400A465
+ 34FFD9B08DFFE6CEB7FFA46534FF000000000000000000000000A4653400A465
+ 3400A4653400A46534FFD9B28FFFE6CEB7FFA46534FFA4653400A4653400A465
+ 34FFD9B28FFFE6CEB7FFA46534FF000000000000000000000000A4653400A465
+ 3400A4653400A46534FFDAB391FFE6CEB7FFA46534FFA4653400A4653400A465
+ 34FFDAB391FFE6CEB7FFA46534FF000000000000000000000000A4653400A465
+ 3400A4653400A46534FFDAB593FFE6CFB9FFA46534FFA4653400A4653400A465
+ 34FFDAB593FFE6CFB9FFA46534FF000000000000000000000000A4653400A465
+ 3400A4653400A46534FFDBB694FFE7D1BBFFA46534FFA4653400A4653400A465
+ 34FFDBB694FFE7D1BBFFA46534FF000000000000000000000000A4653400A465
+ 3400A4653400A46534FFDDBC9DFFE7D1BCFFA46534FFA4653400A4653400A465
+ 34FFDDBC9DFFE7D1BCFFA46534FF000000000000000000000000996E4C00996E
+ 4C00996E4C00A26637FFDCBFA4FFDFC6AFFFA26637FF996E4C00996E4C00A266
+ 37FFDCBFA4FFDFC6AFFFA26637FF000000000000000000000000EEEEEE00EEEE
+ EE00EEEEEE00996E4CFFAB7143FFAC7244FF996E4CFFFBE3BC00FBE3BC00996E
+ 4CFFAB7143FFAC7244FF996E4CFF000000000000000000000000
+ }
+ ImageIndex = 5
+ OnClick = ActionPauseExecute
+ end
+ object MenuItemStop: TMenuItem
+ Action = ActionStopScript
+ Bitmap.Data = {
+ 36040000424D3604000000000000360000002800000010000000100000000100
+ 2000000000000004000064000000640000000000000000000000FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF004550BFE6393986E6393986E6393986E6393986E6393986E6393986E63939
+ 86E6393986E6393986E6393986E6393986E6FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF004550BFE68796F6FF7C8DF7FF7284F8FF687CF8FF5E73FAFF536AFAFF4A63
+ FAFF425CFBFF3A55FCFF334FFCFF393986E6FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF004550BFE6929EF5FF8796F6FF7C8DF7FF7285F8FF687CF9FF5E73F9FF546B
+ FAFF4B63FBFF425CFBFF3955FCFF393986E6FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF004550BFE69BA7F5FF929FF5FF8796F7FF7C8DF7FF7284F8FF677CF8FF5E73
+ F9FF546BFAFF4A63FBFF415CFBFF393986E6FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF004550BFE6A6AFF4FF9CA7F5FF919FF5FF8796F6FF7D8DF7FF7184F7FF687C
+ F8FF5D73F9FF546AFAFF4A63FBFF393986E6FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF004550BFE6AEB7F3FFA5AFF5FF9CA7F5FF919FF5FF8796F7FF7C8DF7FF7284
+ F8FF687BF9FF5D73F9FF536BFAFF393986E6FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF004550BFE6B7BEF3FFAFB7F4FFA6B0F4FF9BA8F5FF929FF6FF8796F6FF7C8D
+ F7FF7284F8FF677BF8FF5D73F9FF393986E6FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF004550BFE6BFC5F2FFB7BEF3FFAFB7F4FFA5AFF4FF9CA7F5FF929FF6FF8795
+ F6FF7D8DF7FF7284F8FF687CF8FF393986E6FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF004550BFE6C7CAF1FFBFC5F3FFB7BEF3FFAEB7F4FFA6AFF4FF9BA7F5FF929F
+ F6FF8796F6FF7C8DF7FF7284F7FF393986E6FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF004550BFE6CCD0F1FFC6CBF1FFBFC5F2FFB7BFF3FFAFB7F4FFA6AFF5FF9BA8
+ F5FF919FF6FF8796F6FF7D8DF7FF393986E6FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF004550BFE6D1D4F1FFCCD0F2FFC6CBF2FFBFC5F2FFB7BEF3FFAEB8F3FFA5AF
+ F4FF9BA8F4FF919FF5FF8795F6FF393986E6FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF004550BFE64550BFE64550BFE64550BFE64550BFE64550BFE64550BFE64550
+ BFE64550BFE64550BFE64550BFE64550BFE6FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00
+ }
+ ImageIndex = 7
+ OnClick = ActionStopExecute
+ end
+ end
+ object MenuView: TMenuItem
+ Caption = '&View'
+ object MenuItemColourHistory: TMenuItem
+ Caption = 'View &Colour History'
+ OnClick = MenuItemColourHistoryClick
+ end
+ object MenuItemDebugImage: TMenuItem
+ Caption = 'View &Debug Image'
+ OnClick = MenuItemDebugImageClick
+ end
+ object MenuItemFunctionList: TMenuItem
+ Caption = 'View &Function List'
+ OnClick = MenuItemFunctionListClick
+ end
+ object MenuViewSettings: TMenuItem
+ Caption = 'View Settings'
+ OnClick = MenuViewSettingsClick
+ end
+ end
+ object MenuExtra: TMenuItem
+ Caption = 'E&xtra'
+ object MenuitemFillFunctionList: TMenuItem
+ Caption = '&Fill Function List'
+ Bitmap.Data = {
+ 36040000424D3604000000000000360000002800000010000000100000000100
+ 2000000000000004000064000000640000000000000000000000FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF0039864003347E3A78FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF004191499C3B8842D2FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF004EA3579066B06EFF61AA68FF3D8B44FF37833EFF327B
+ 37FF2C7432EA276D2CB7236627701F61231DFFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF005BB4658473BD7CFF96D19FFF94CF9CFF8FCD96FF8ACA91FF85C7
+ 8BFF7ABE81FF65AD6CFF4B9251FF246829B020632439FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF0060BC6C8A79C483FF9ED7A7FF9BD4A4FF97D29FFF92CF9AFF8DCC
+ 95FF88CA90FF7AC282FF7EC485FF5DA463FF266B2AB02265251DFFFFFF00FFFF
+ FF00FFFFFF00FFFFFF0062BE6D937BC785FF77C281FF54AB5EFF4EA357FF499B
+ 51FF63AC6BFF83C38BFF87C98FFF82C689FF509756FF276D2C70FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF0063C06E9F5FBB6AD2FFFFFF00FFFFFF00FFFF
+ FF004B9E538D45964DE186C68EFF88C98FFF6FB376FF2E7633B745964D613F8E
+ 466139864061347E3A612E76336167C6730364C2707BFFFFFF00FFFFFF00FFFF
+ FF00FFFFFF004DA1558347994FED419149F63B8842F835803CE84DA155E84799
+ 4FF8419149F63B8842ED35803C83FFFFFF00FFFFFF00FFFFFF00FFFFFF001E5F
+ 217B1B5B1E0354AB5E614EA35761499B516143934B613D8B446154AB5EB780C3
+ 89FF8DCC95FF83C48AFF3D8B44E137833E8DFFFFFF00FFFFFF00FFFFFF002366
+ 27D21F61239FFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF005BB4657075BF
+ 7EFF98D2A1FF94CF9CFF86C78DFF5EA765FF398640FF347E3AFF2E7633FF4990
+ 4FFF458B4AFF20632493FFFFFF00FFFFFF00FFFFFF00FFFFFF0060BC6C1D5CB6
+ 67B085C98EFF9BD4A4FF8FCE98FF92CF9AFF8DCC95FF88CA90FF83C68BFF7EC4
+ 85FF79C17FFF478D4CFF2265258AFFFFFF00FFFFFF00FFFFFF00FFFFFF0062BE
+ 6D395EB968B079C383FF89CA92FF94D09CFF95D19EFF90CF99FF8CCB94FF87C9
+ 8FFF80C487FF4E9554FF276D2C84FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF0063C06E1D5FBB6A705BB465B756AD5FEA50A65AFF4B9E53FF45964DFF60A8
+ 68FF5BA262FF347E3A90FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF004799
+ 4FD24191499CFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF004EA3
+ 5778499B5103FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00
+ }
+ ShortCut = 16465
+ OnClick = MenuitemFillFunctionListClick
+ end
+ object UpdateMenuButton: TMenuItem
+ Caption = '&Update'
+ Bitmap.Data = {
+ 36040000424D3604000000000000360000002800000010000000100000000100
+ 2000000000000004000064000000640000000000000000000000FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00008AFF8B008A
+ FFF4008AFF8B008AFF96008AFFFF008AFF96008AFFF9008AFFDA008AFFC7008A
+ FF8D008AFFF6008AFF98008AFF96008AFFFF008AFF96FFFFFF00008AFFF4F4FA
+ FFFF008AFFF477C1FFFFFFFFFFFF77C1FFFFF9FCFFFFDAEEFFFFC7E5FFFF008A
+ FFF6F6FBFFFF98D0FFFF6FBDFFFFFFFFFFFF008AFFFFFFFFFF00008AFFF4F4FA
+ FFFF008AFFF4EEF7FFFFF4FAFFFF77C1FFFFE8F4FFFF008AFFE8008AFFC7038B
+ FFFFF9FCFFFFB7DEFFFFAAD8FFFFFBFDFFFF279CFFFF008AFF51008AFFF4F4FA
+ FFFF99D0FFFF77C1FFFFF4FAFFFF77C1FFFFF9FCFFFFDAEEFFFFC7E5FFFF9FD3
+ FFFFE4F3FFFFDCEFFFFFE3F2FFFFCDE8FFFFBADFFFFF008AFFBA008AFFF6F6FB
+ FFFFEEF7FFFF008AFFF4F4FAFFFF77C1FFFFE8F4FFFF008AFFE80C90FFFFEDF7
+ FFFF78C1FFFFBBE0FFFFBBE0FFFF56B1FFFFE3F2FFFF008AFFE3008AFFEEEEF7
+ FFFF44A9FFFF008AFFE8E8F4FFFF44A9FFFFF4FAFFFFDAEEFFFFCBE7FFFFABD8
+ FFFF0C90FFFF66B9FFFF66B9FFFF008AFFD7D7EDFFFF1895FFFF008AFF85008A
+ FFEE008AFF85008AFF7F008AFFE8008AFF8B008AFFF4008AFFDA008AFFCB008A
+ FFAB008AFF42008AFF66008AFF66008AFF6E008AFFD7008AFF6EFFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00
+ }
+ OnClick = UpdateMenuButtonClick
+ end
+ object MenuItemDivider9: TMenuItem
+ Caption = '-'
+ end
+ object MenuItemExportHTML: TMenuItem
+ Caption = '&Export script as HTML'
+ Bitmap.Data = {
+ 36040000424D3604000000000000360000002800000010000000100000000100
+ 2000000000000004000064000000640000000000000000000000FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00CD6E23FFC965
+ 1BFFC8601AFFC65918FFC25317FFC04E16FFBD4715FFBB4115FFB93E14FFB739
+ 13FFB63512FFB43312FFB43312FFB43312FFB43312FFB43312FFD27735FFE4AF
+ 87FFE3AB81FFE1A87BFFDFA376FFDEA171FFDC9D6DFFDB9968FFDA9763FFD994
+ 5EFFD7915BFFD78F57FFD58D54FFD58C53FFD58C53FFB43312FFD68443FFE7B5
+ 90FFE0A374FFDE9E6EFFDC9A67FFDB9560FFD9915AFFD78D53FFD5894DFFD385
+ 48FFD28143FFD07E3EFFCF7B39FFCE7935FFD58D54FFB43312FFDB8E53FFEABB
+ 99FFFCF6F2FFE1A679FFFCF5F1FFDD9D6BFFFCF6F2FFDA945EFFF7E9DEFFD68C
+ 51FFEFD1BAFFDEA477FFFDFAF7FFF7E8DDFFD78F59FFB63512FFE19762FFECC1
+ A1FFFCF7F3FFE5AD84FFFCF6F2FFE1A477FFFCF7F3FFDD9B69FFF8EBE0FFF0D3
+ BEFFF3DECEFFE0A97FFFFAF0E9FFD28344FFD9945EFFB73C13FFE2A06EFFEEC7
+ A8FFFEFDFCFFFDF7F3FFFEFAF8FFE3AC81FFFCF7F4FFE0A374FFF9ECE3FFFAF2
+ EBFFFDF8F4FFE3AE86FFFAF1EAFFD5894DFFDA9966FFBD4315FFE6A779FFF0CB
+ B0FFFDF8F5FFEABA98FFFDF8F4FFE7B38CFFFDF8F5FFE3AA80FFF9EEE5FFEECD
+ B4FFFDF8F5FFE5B38EFFFDF9F6FFD88F57FFDD9E6DFFC04E16FFEAAB80FFF2CF
+ B5FFFCF4EEFFECBF9FFFFBF3EDFFFDF8F4FFFDF7F4FFFCF7F3FFF4DBC9FFE7B4
+ 8EFFF7E6DAFFE3AD83FFF6E4D6FFDB9762FFDFA376FFC45918FFEAAB80FFF3D0
+ B7FFEFC6A9FFEFC4A6FFEEC2A2FFECBF9EFFEBBC98FFE9B893FFE8B48EFFE6B0
+ 88FFE3AC81FFE2A77BFFE0A374FFDE9E6EFFE2AA80FFC9621AFFEAAB80FFF3D0
+ B7FFF3D0B7FFF3D0B7FFF2D0B7FFF1CEB3FFF0CBB0FFEFC9ACFFEEC6A8FFEDC2
+ A3FFEBC09EFFEABB99FFE8B794FFE6B48FFFE4B089FFCD6E23FFEAAB80FFEAAB
+ 80FFEAAB80FFEAAB80FFEAAB80FFEAAB80FFE8A97CFFE6A477FFE2A070FFE29B
+ 6BFFE19762FFDD9059FFD98B52FFD88549FFD6803EFFD27735FFFFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00
+ }
+ OnClick = MenuItemExportHTMLClick
+ end
+ end
+ object MenuHelp: TMenuItem
+ Caption = '&Help'
+ object MenuItemAbout: TMenuItem
+ Caption = '&About'
+ Bitmap.Data = {
+ 36040000424D3604000000000000360000002800000010000000100000000100
+ 2000000000000004000064000000640000000000000000000000FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00AD744423AC72417DAA703FDBA86D3CF3A76B3AF3A569
+ 37DBA468357DA3663323FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00B57E5153B37C4EE6D7BBA3FFE9DACAFFECE0D1FFECE0D1FFE8D8
+ C8FFD3B59CFFA76C3AE6A66A3853FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00BD895F53BB875BF4E7D5C4FFE5D2BFFFC9A685FFB88E67FFB68A65FFC5A1
+ 80FFE0CCBAFFE3D0BEFFAB7040F4A96E3D53FFFFFF00FFFFFF00FFFFFF00C695
+ 6D22C3926AE5EAD8C9FFE3CDBAFFC0946BFFBA8C62FFCFB094FFCFB094FFB789
+ 5FFFB28761FFDAC0AAFFE4D1C0FFAE7546E5AD734322FFFFFF00FFFFFF00CC9E
+ 787EE4CCB9FFEAD6C5FFC79971FFBF9066FFBF9066FFF7F1ECFFF6F0EAFFB789
+ 5FFFB7895FFFB58963FFE2CEBBFFD9BDA6FFB27B4D7EFFFFFF00FFFFFF00D3A7
+ 84DBEFE1D3FFD9B595FFC7986CFFC39569FFC19367FFBF9066FFBF9066FFBB8B
+ 63FFB98A63FFB88A62FFCBA786FFEADCCCFFB88357DBFFFFFF00FFFFFF00D9B0
+ 8FF6F2E4D9FFD1A57AFFC5996BFFC4976AFFC49669FFFAF6F2FFF3EAE1FFC295
+ 6DFFBE8F65FFBE8F64FFC0956DFFEFE3D5FFBF8C61F6FFFFFF00FFFFFF00E0B9
+ 99F6F2E5DAFFD1A67EFFCC9D71FFC79A6CFFC5986BFFE2CCB6FFF8F3EEFFF6EE
+ E8FFD9BDA1FFC29468FFC59B71FFF0E2D6FFC5956CF6FFFFFF00FFFFFF00E6C1
+ A3DBF3E5D9FFDFBB9EFFCFA075FFCD9E72FFF5EBE3FFE4CBB4FFE7D3BFFFFBF8
+ F6FFE5D3BFFFC4986BFFD6B491FFEEE0D2FFCC9E78DBFFFFFF00FFFFFF00EBC9
+ AD7EF4E3D4FFEFDCCDFFD5A87EFFD0A077FFFBF8F5FFFCF8F5FFFCF8F5FFFBF8
+ F5FFD1A881FFCFA47BFFEAD5C3FFEAD4C2FFD2A7837EFFFFFF00FFFFFF00F1D0
+ B522EFCEB3E5F6E9DDFFECD8C6FFD7AC81FFDCBB9AFFF6ECE3FFF5ECE2FFE4C8
+ AEFFD2A77BFFE6CEBAFFF1E2D5FFDBB391E5D9B08E22FFFFFF00FFFFFF00FFFF
+ FF00F4D4BB53F2D2B8F4F7EADFFFEEDED0FFE3C1A7FFD8AE89FFD7AC86FFDDBB
+ 9CFFEBD6C7FFF3E6D9FFE3BE9FF4E1BB9C53FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00F6D8BF53F5D6BDE6F9E9DCFFF6E8DDFFF3E5DAFFF3E5DAFFF5E7
+ DCFFF5E4D6FFEBC8ACE6E9C6A953FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00F9DBC423F8DAC27DF7D8C0DBF6D7BEF3F4D5BCF3F3D3
+ B9DBF1D1B77DF0CFB423FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00
+ }
+ OnClick = MenuItemAboutClick
+ end
+ object MenuItemReportBug: TMenuItem
+ Caption = '&Report a Bug'
+ Bitmap.Data = {
+ 36040000424D3604000000000000360000002800000010000000100000000100
+ 2000000000000004000064000000640000000000000000000000FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00328AC5EC3087C4F62F85C3F62D83C2F62A80
+ BBFF297EBAFF287DBFF6267BBEF62579BDF62377BDF62276BCC3FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF003891C9E4DDECF6FFBDEEF9FFACEAF8FFABEA
+ F8FFABEAF8FFABEAF8FFADEAF8FFD4F3FBFFA4C8E4FF267BBEABFFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00338781C88EC2E1FF97E8F9FF61DCF6FF5BDB
+ F5FF3288C2FF5BDBF5FF6ADEF6FFB1E7F6FF2D83C2E92B81C12AFFFFFF00FFFF
+ FF00FFFFFF00FFFFFF002A7B2EC12B7A32FF4A9FBCFFABDBEFFF74E0F7FF58DA
+ F5FF58DAF5FF5DDBF5FF90E6F8FF92C1E1FF2F84B090FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF002F8733C1207423FF94C09DFF62AC99FF7BBDDFFFA2EAF9FF61DC
+ F6FF3187C2FF77E1F7FFB6DEF0FF3890BCE93891C90DFFFFFF00FFFFFF00FFFF
+ FF0035923A872D8C32FF77B582FF4D9E54FF79B38DFF4DA7AEFFACD9ECFF82E3
+ F8FF3388C2FFACEDFAFF439ECFFE419BCE53FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00329537F562AD68FF77BE91FF44A05DFF4B9F53FF72B499FF51AECFFFB4EB
+ F8FF8EE6F8FFB5DDEEFF3E969FFF2B784D17FFFFFF002066237CFFFFFF00FFFF
+ FF00339C38F852A959FF6DBC8CFF4DAA70FF429F5CFF4CA254FF6DBBB8FFA4D7
+ EBFFDCF4FBFF55B0D3FF2F824EFF247328FE237027FF226C26FFFFFFFF0034A4
+ 39C733A138FF339E38FF94CFACFF5CB47EFF4EAC72FF41A15DFF4FA75EFF60BB
+ D2FFABDBEDFF6CBABDFF2A7E2DFF26792AF42576296DFFFFFF0037AD3CFA36AA
+ 3BFF35A73AA238A53EEA50AD56FF8DCCA5FF5EB580FF4FAD73FF42A35DFF55B1
+ 86FF69C0D3FF8ABF9BFF29832EFF25593BAFFFFFFF00FFFFFF0038B13EF137AF
+ 3D23FFFFFF00FFFFFF0034A63AFE39A53FFF90CEA8FF62B984FF58B27BFF60B2
+ 76FF38973EFF29892DFF57A462FF265044DBFFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF0037AE3D4136AB3CFF38A93EF045AC4BFF9ED4ADFFA4D7B8FF85C3
+ 8EFF288F2DFF4FB75FFF97C8AAFF2C8D31FF2B8930FF2A852EFFFFFFFF00FFFF
+ FF00FFFFFF0038B33EF038B13DF8FFFFFF0038AC3DF135A83AFF34A539FF34A1
+ 39FF72C27EFFAFE3C2FF5F8C78FF32654D75FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF003AB740FF39B53F74FFFFFF00FFFFFF0037AD3CF836AA3BED467F
+ 66A53A8650F7339D3AFE3B715889FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF003BBB4123FFFFFF00FFFFFF00FFFFFF0038B23EFF37AF3DB24E8E
+ 6A2235A93B6534A63AF2FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF003AB73FFF39B43F41FFFF
+ FF0037AE3D5236AC3CF7FFFFFF00FFFFFF00FFFFFF00FFFFFF00
+ }
+ OnClick = MenuItemReportBugClick
+ end
+ end
+ end
+ object Mufasa_Image_List: TImageList
+ left = 448
+ top = 144
+ Bitmap = {
+ 4C691B0000001000000010000000424242004242420042424200424242004242
+ 420042424200424242004242420042424200424242004242420042424200A155
+ 42FFA15542FFA15542FF4242420E424242004242420042424200424242004242
+ 4200424242004242420042424200424242004242420042424200A15542FFFFDA
+ D0FFD05E42FFA15542FFA15542FF424242004242420042424200424242004242
+ 42004242420042424200424242004242420042424200A15542FFFFDAD0FFD05E
+ 42FFD05E42FFA15542FFA15542FF424242004242420042424200424242004242
+ 4200424242004242420042424200A15542FFA15542FFFFDAD0FFD05E42FFD05E
+ 42FFA15542FFA15542FFA15542FF424242004242420042424200424242004242
+ 42004242420042424200A15542FFFFDAD0FFA15542FFD05E42FFD05E42FFA155
+ 42FFA15542FFA15542FF42424263424242004242420042424200FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF004242420BA15542FFFFDAD0FFA15542FFD05E42FFA155
+ 42FFA15542FF424242634242424C424242004242420042424200FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00838383FFFFFFFFFFA15542FFFFDAD0FFA15542FFA155
+ 42FF424242634242424C42424219424242004242420042424200FFFFFF00FFFF
+ FF00FFFFFF00838383FFFFFFFFFFE5E5E5FFA1A1A1FFA15542FFFFDAD0FFA155
+ 42FF424242584242421C42424203424242004242420042424200FFFFFF00FFFF
+ FF00838383FFFFFFFFFFE5E5E5FFA1A1A1FF838383FF42424263A15542FF4242
+ 42604242424A4242420E42424200424242004242420042424200FFFFFF008383
+ 83FFFFFFFFFFE5E5E5FFA1A1A1FF838383FF424242634242424C424242274242
+ 423E424242194242420342424200424242004242420042424200838383FFFFFF
+ FFFFE5E5E5FFA1A1A1FF838383FF424242634242424C42424219424242064242
+ 420B4242420242424200424242004242420042424200838383FFFFFFFFFFE5E5
+ E5FFA1A1A1FF838383FF424242634242424C4242421942424203424242004242
+ 420042424200424242004242420042424200838383FFFFFFFFFFE5E5E5FFA1A1
+ A1FF838383FF424242634242424C424242194242420342424200424242004242
+ 420042424200424242004242420042424200838383FFE5E5E5FFA1A1A1FF8383
+ 83FF424242634242424C4242421942424203FFFFFF0042424200424242004242
+ 4200424242004242420042424200838383FFE5E5E5FF838383FF838383FF4242
+ 42634242424C4242421942424203FFFFFF00FFFFFF0042424200424242004242
+ 4200424242004242420042424200838383FF838383FF42424260424242584242
+ 424A424242194242420342424200424242004242420042424200424242004242
+ 42004242420042424200424242000000000000000000E1EEE1FFC5DCC5FFDBE9
+ DBFFF4F9F4FF0000000000000000000000000000000000000000000000000000
+ 00000000000000000000000000000000000000000000AED5B0FFD6F8E1FFCFFA
+ DDFFB5F8CCFF78D891FF408B40FF000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000CAE1CAFFC5F7
+ D5FF9CF4B9FF7DE49FFF0A590CFF000000BF00000000C3C4EDFF000000000000
+ 0000000000000000000000000000000000000000000095C495FFBBF3CEFF9DF0
+ BAFF6BD48EFF4E9A68FF0A440AFF000000BF00000000DDDDF6FF5257C7FF0000
+ 00000000000000000000000000000000000084C384FF86E3A5FF6CE092FF4BAA
+ 6BFF012F01FF2A593AFF365536FF000000BF0000000000000000B1B4EAFF3D46
+ C5FF000000000000000000000000E8F3E8FF88DD9FFF44CF72FF268E49FF343B
+ 34FF313A31FF213E2BFF5B725BFF000000BF0000000000000000E0E1F7FF2136
+ D3FF8284B9FF000000000000000061B161FF37C65EFF24994AFF304930FF0000
+ 00BF000000BF094009FF000000BF000000BF0000000000000000979DE8FF0019
+ C0FF151967FF00000000000000001B8E1BFF168B2EFF3B5E3BFF000000BF0000
+ 00BF00000000000000007887F1FF0000000000000000B9BFF6FF002CF1FF0014
+ 7DFF111434FF0000000000000000648C64FF155722FF3F443FFF000000BF0000
+ 000000000000C2C9F9FFA1BDFEFFEBEDFDFFE9EBFDFF3364FEFF022093FF000B
+ 3CFF39393FFF000000000000000000000000022E03FF243524FF000000BF0000
+ 0000000000008597FAFF8EB6FFFF687AEEFF709BFBFF11359CFF031241FF060A
+ 33FF000000BF00000000000000000000000000000000022702FF444C44FF0000
+ 0000000000001032FBFF72B2FFFF63A1F5FF365C9AFF132241FF050B37FF0000
+ 00BF000000BF00000000000000000000000000000000000000003D513DFF0000
+ 00BF000000000932B5FF537EA1FF355271FF1A2B41FF171C3BFF000000BF0000
+ 00BF000000000000000000000000000000000000000000000000000000000000
+ 00BF00000000172465FF1E2F41FF283641FF1E2F41FF142441FF010937FF0000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 00000000000000000000000000BF3A3A40FF25283DFF060D38FF25283DFF0000
+ 00BF000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0059AA
+ 834859AA83AB59AA83D259AA83FF59AA83D559AA83AE59AA8351FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0056A7801856A780C36CB3
+ 92FFA8D5C3FFC5E6DBFF71B797FFC6E6DCFFA9D6C4FF6FB594FF56A780C656A7
+ 801EFFFFFF00FFFFFF00FFFFFF00FFFFFF0052A27D1B53A37EE48FC6AEFFC8E8
+ DFFFDFF2ECFFF9FDFBFF77B899FFF8FCFBFFDCF1EBFFC7E7DEFF93C8B2FF55A4
+ 80E852A27D1EFFFFFF00FFFFFF00FFFFFF004D9D78C08CC3ABFFC3E6DCFFF5FB
+ F9FFC5E6DCFF9DD5C5FF5CAA87FF9FD6C5FFC9E8DFFFF4FAF9FFC0E4D9FF93C7
+ B2FF4D9D78CCFFFFFF00FFFFFF004898735160A787FFADDACBFFEFF8F5FF9BD2
+ C1FF82C7B2FF82C7B2FF56A482FF82C7B2FF82C7B2FF9CD3C2FFF0F8F6FFA9D8
+ CAFF65AA8BFF48987354FFFFFF0042916EAE90C5B0FFCDE8DFFFB6DDD0FF78C1
+ A9FF8DCAB6FFE4F3EEFF69A98DFFE2F2EDFF8BCAB5FF78C1A9FFB9DFD2FFC8E5
+ DCFF95C8B5FF42916EB4FFFFFF003C8B68DB81C2AAFFF1F9F6FF7CC1A9FF6EBB
+ A0FFE5F3EEFFABD8C8FF75BEA4FFB1DACCFFDDEFE9FF6EBBA0FF81C4ACFFF0F8
+ F5FF81C2ACFF3C8B68E7FFFFFF00368462F0418F6FFF5E9C82FF3F8E6DFF408E
+ 6EFF5E9C82FF64B497FF64B497FF68B699FF5D9C82FF408E6EFF408E6EFF5D9C
+ 82FF408E6EFF3B8766F9FFFFFF002F7D5DDE55A888FFF1F8F6FF6EB79CFF59AC
+ 8DFFE0EFEAFF99CCB9FF59AC8DFFA1D0BFFFD8EBE4FF59AC8DFF6EB79CFFEDF6
+ F3FF58AA8BFF2F7D5DE7FFFFFF00297657AB489879FFBDDDD1FFA8D3C2FF4FA5
+ 84FF68B295FFD8EBE4FF539177FFD1E8DFFF66B194FF4FA584FFAED6C7FFB7DA
+ CCFF469978FF297657B4FFFFFF0023705151358163FF57A887FFEDF6F3FF6CB3
+ 97FF459F7BFF459F7BFF287758FF459F7BFF459F7BFF73B79CFFF2F8F6FF5DAB
+ 8CFF388465FF23705157FFFFFF00FFFFFF001D694CCC308764FF72B69AFFF3F9
+ F7FFA3CFBDFF60AC8DFF217051FF65AF90FFA7D1C0FFF3F9F7FF70B598FF318A
+ 66FF1D694CB4FFFFFF00FFFFFF00FFFFFF00186447211A6649EA29815DFF50A2
+ 80FFB0D5C6FFEEF6F3FF438069FFECF5F1FFADD4C4FF4DA17EFF2A845FFF1B67
+ 49EB1864471BFFFFFF00FFFFFF00FFFFFF00FFFFFF00135F4215135F42AE1A6C
+ 4CFF25805BFF2B8D64FF166547FF2C8D65FF25815BFF1B6E4DFF135F42B7135F
+ 421BFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000F5A
+ 3F570F5A3FB70F5A3FF60F5A3FFF0F5A3FF60F5A3FBA0F5A3F5DFFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF009A6B2731AA7E43A192601805FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00A87D4269CCB08BE0915D1409FFFFFF00FFFFFF00FFFF
+ FF0092601706FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00AA81476FD6BD9FF793611910FFFFFF00FFFFFF009666
+ 202CA9804BCBFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00AC834B75DEC9AFFF95641D1FFFFFFF0092601726C3A4
+ 7CEBB59063CBFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00AF87507CE7D5C1FF95651F2B8F5C121BC5A783E7D5BC
+ 9DE1B5936462FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00B1895384EEDFCEFF97662065C2A37CDAE9D8C5FDA982
+ 4E7BFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00B38C5789F1E2D4FFCEB28EF4F5EBE0FFA67F4A9DFFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00000B8802FFFFFF00B48E5A90F6EADDFFE1CDB4FFB18D5DBFFFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00030D8C1F1B26
+ A7992A34BACC111C9D89BB9869CCF0E0D0FFB7915FC58F5D140BFFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00030D8C1F2C35B9D73C46
+ CFFF333ECAF23F4CD7FFD8BC9AFFF6EAE1FFBB925ABF9462183B91611A01FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF001D28A99C3B46CCFF0812
+ 903A071190533B48D4FFDBBD9CFFEECCA6FF404CDEFF3A43D1FF0F199869FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00323CC3EC232EADAFFFFF
+ FF001A25A8994250D2FFCBA375FE414FD6FF1621A39D2F39C0D42E38BEDF020D
+ 8B0AFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF002F3ABDDE353FC9E52530
+ B3C23F4ADDFF1F2AACC22430B2CB323CC6F2000A8603111B9D773741C8FF0812
+ 8E20FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000F199763323DC7F83741
+ CFFF1F29ABB0000A8618232DB4AF3540CCFD000985181C27A895343EC5F8040E
+ 8C14FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00050F8D1F0610
+ 8E26010B8A03FFFFFF00121C9B70404BD9FF2C35BFDD3D47D1FF1D27A9A4FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00020D8C0A1C27A69F353FC9F7222DAFB9030D8C1CFFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00000000000000000000000000212121006565
+ 65008B8B8B002502B0002502B2002502B3002602B5372602B47B2502B47C2502
+ B3382502AF002402AC002302A800000000001D1D1D005C5C5C00808080008686
+ 86008B8B8B002502B0002502B2002502B3382502B37CC9B8FDFFCAB9FEFF2502
+ B17E2502AF392402AC002302A800525252007373730079797900808080008686
+ 86008B8B8B002502B0002502B2392502B17EC6B5FCFFB6A5ECFFB8A7ECFFCAB9
+ FEFF2402AD812402AC3B2302A8006C6C6C007373730079797900808080008686
+ 86008B8B8B002502B0392502B07FC4B3FBFFB3A2EAFFB5A4EBFFB6A5ECFFB8A7
+ ECFFCAB9FEFF2402A9862302A83D6C6C6C007373730079797900808080008686
+ 86008A8A8A2F88888866C1B0F9FFB09FE9FFB2A1E9FFB3A2EAFFB5A4EBFFB6A5
+ ECFF9887DCFFAA99EEFF2302A58A6C6C6C007373730079797900808080008585
+ 852F83838366F8F8F8FFF5F5F5FFAE9DE8FFB09FE9FFB2A1E9FFB3A2EAFF9584
+ D9FF9786DBFFA998EDFF2202A18D6C6C6C0073737300797979007F7F7F2F7D7D
+ 7D66F6F6F6FFF2F2F2FFF2F2F2FFF2F2F2FFAE9DE8FFB09FE9FF9281D6FF9483
+ D8FFA695EAFF22029F9022029F416C6C6C00737373007878782F76767666F4F4
+ F4FFEFEFEFFFEFEFEFFFEFEFEFFFEFEFEFFFEFEFEFFF8E7DD2FF907FD4FFA392
+ E7FF21029D9221029C4221029E006C6C6C007272722F70707066F3F3F3FFECEC
+ ECFFECECECFFECECECFFECECECFFECECECFFCECECEFFD0D0D0FF9F8EE3FF2102
+ 9B9521029A4321029C0021029E006B6B6B2F69696966F1F1F1FFE9E9E9FFE9E9
+ E9FFE9E9E9FFE9E9E9FFE9E9E9FFCACACAFFCCCCCCFFDCDCDCFF363636662003
+ 98452102990021029C0021029E0063636366F0F0F0FFE6E6E6FFE6E6E6FFE6E6
+ E6FFE6E6E6FFE6E6E6FFC6C6C6FFC8C8C8FFD8D8D8FF272727662323232F2003
+ 9700210299001902750011014F0058585866F0F0F0FFE3E3E3FFE3E3E3FFE3E3
+ E3FFE3E3E3FFC2C2C2FFC4C4C4FFD4D4D4FF1A1A1A661616162F202020001803
+ 71000801260000000000000000004848482F3D3D3D66F0F0F0FFE1E1E1FFE1E1
+ E1FFBFBFBFFFC0C0C0FFD1D1D1FF0F0F0F660C0C0C2F0F0F0F00080808000000
+ 0000000000000000000000000000101010001E1E1E2F20202066DFDFDFFFCECE
+ CEFFCECECEFFCECECEFF050505660202022F0202020000000000000000000000
+ 00000000000000000000000000000000001100000026090909480A0A0A660505
+ 05660202026601010166000000400000001E00000019000000130000000E0000
+ 000900000005000000020000000000000009000000130000001A000000190000
+ 00180000001600000014000000120000000F0000000D0000000A000000070000
+ 0005000000030000000100000000EEEEEE00EEEEEE00EEEEEE00996E4CFFAB71
+ 43FFAC7244FF996E4CFFFBE3BC00FBE3BC00996E4CFFAB7143FFAC7244FF996E
+ 4CFF000000000000000000000000996E4C00996E4C00996E4C00A26637FFDCBF
+ A4FFDFC6AFFFA26637FF996E4C00996E4C00A26637FFDCBFA4FFDFC6AFFFA266
+ 37FF000000000000000000000000A4653400A4653400A4653400A46534FFDDBC
+ 9DFFE7D1BCFFA46534FFA4653400A4653400A46534FFDDBC9DFFE7D1BCFFA465
+ 34FF000000000000000000000000A4653400A4653400A4653400A46534FFDBB6
+ 94FFE7D1BBFFA46534FFA4653400A4653400A46534FFDBB694FFE7D1BBFFA465
+ 34FF000000000000000000000000A4653400A4653400A4653400A46534FFDAB5
+ 93FFE6CFB9FFA46534FFA4653400A4653400A46534FFDAB593FFE6CFB9FFA465
+ 34FF000000000000000000000000A4653400A4653400A4653400A46534FFDAB3
+ 91FFE6CEB7FFA46534FFA4653400A4653400A46534FFDAB391FFE6CEB7FFA465
+ 34FF000000000000000000000000A4653400A4653400A4653400A46534FFD9B2
+ 8FFFE6CEB7FFA46534FFA4653400A4653400A46534FFD9B28FFFE6CEB7FFA465
+ 34FF000000000000000000000000A4653400A4653400A4653400A46534FFD9B0
+ 8DFFE6CEB7FFA46534FFA4653400A4653400A46534FFD9B08DFFE6CEB7FFA465
+ 34FF000000000000000000000000A4653400A4653400A4653400A46534FFD9AE
+ 89FFE6CEB7FFA46534FFA4653400A4653400A46534FFD9AE89FFE6CEB7FFA465
+ 34FF000000000000000000000000A4653400A4653400A4653400A46534FFD8AB
+ 84FFE6CEB7FFA46534FFA4653400A4653400A46534FFD8AB84FFE6CEB7FFA465
+ 34FF000000000000000000000000A4653400A4653400A4653400A46534FFD7A9
+ 81FFE6CDB6FFA46534FFA4653400A4653400A46534FFD7A981FFE6CDB6FFA465
+ 34FF000000000000000000000000A4653400A4653400A4653400A46534FFD7A7
+ 7FFFE6CCB5FFA46534FFA4653400A4653400A46534FFD7A77FFFE6CCB5FFA465
+ 34FF000000000000000000000000A4653400A4653400A4653400A46534FFD8A9
+ 81FFE6CCB5FFA46534FFA4653400A4653400A46534FFD8A981FFE6CCB5FFA465
+ 34FF000000000000000000000000A2663800A2663800A2663800A36535FFD7AC
+ 88FFE1C5ADFFA36535FFA2663800A2663800A36535FFD7AC88FFE1C5ADFFA365
+ 35FF0000000000000000000000009870500098705000987050009F683EFFC99C
+ 76FFCDA585FF9F683EFF98705000987050009F683EFFC99C76FFCDA585FF9F68
+ 3EFF000000000000000000000000EEEEEE00EEEEEE00EEEEEE00987050FFA465
+ 34FFA46534FF987050FFFBE3BC00FBE3BC00987050FFA46534FFA46534FF9870
+ 50FF000000000000000000000000000000000000000004733AFF2D8859FF859C
+ 90FF000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000004733AFFA4D9BEFF3D93
+ 66FF5F8873FF0000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000004733AFFA9DCC1FF9BD5
+ B7FF4C9F73FF3D7D5CFF00000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000004733AFFA5DABFFF57BB
+ 87FF90D2B0FF5BAB82FF23774CFFD4D5D4FF0000000000000000000000000000
+ 0000000000000000000000000000000000000000000004733AFFA9DCC1FF45B4
+ 7BFF47B47CFF82CCA6FF67B68CFF177745FFC1C5C3FF00000000000000000000
+ 0000000000000000000000000000000000000000000004733AFFA9DCC1FF3EB1
+ 76FF3AAF73FF36AE70FF6FC598FF71BF97FF187B49FFA6B0ABFF000000000000
+ 0000000000000000000000000000000000000000000004733AFFA9DCC1FF36AD
+ 70FF32AC6DFF2DAA6AFF28A866FF58BC89FF78C59DFF1F804EFF839A8EFF0000
+ 0000000000000000000000000000000000000000000004733AFFA9DCC1FF2EAD
+ 6BFF2BAD6AFF27AB68FF22A964FF1CA55FFF41B278FF78C69FFF298858FF678C
+ 79FF000000000000000000000000000000000000000004733AFFA9DCC1FF0CAA
+ 58FF12AE5EFF15AF60FF16AD61FF13AA5DFF3AB677FF75C79DFF288957FF4E83
+ 67FF000000000000000000000000000000000000000004733AFFA9DCC1FF0DB3
+ 5EFF0EB660FF0EB660FF0DB45FFF47C484FF70CA9CFF1D824DFF678C79FF0000
+ 0000000000000000000000000000000000000000000004733AFFA9DCC1FF10BD
+ 65FF11C167FF13C269FF59D395FF67C998FF167C47FF889C92FF000000000000
+ 0000000000000000000000000000000000000000000004733AFF83DCAFFF11C3
+ 69FF1ACC73FF69DFA3FF5AC28DFF137643FF9EA7A3FF00000000000000000000
+ 0000000000000000000000000000000000000000000009773FFF83DBAEFF1FC6
+ 71FF72DEA7FF4BB27FFF177445FFA8ADAAFF0000000000000000000000000000
+ 0000000000000000000000000000000000000000000004733AFF82D8ACFF76D6
+ A6FF3C9D6AFF27744CFFACAEADFF000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000004733AFF7ACFA4FF2C8C
+ 5AFF3D7659FFAEAEAEFF00000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000004733AFF21824FFF6382
+ 72FF000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF004550BFE64550BFE64550
+ BFE64550BFE64550BFE64550BFE64550BFE64550BFE64550BFE64550BFE64550
+ BFE64550BFE6FFFFFF00FFFFFF00FFFFFF00FFFFFF004550BFE6D1D4F1FFCCD0
+ F2FFC6CBF2FFBFC5F2FFB7BEF3FFAEB8F3FFA5AFF4FF9BA8F4FF919FF5FF8795
+ F6FF393986E6FFFFFF00FFFFFF00FFFFFF00FFFFFF004550BFE6CCD0F1FFC6CB
+ F1FFBFC5F2FFB7BFF3FFAFB7F4FFA6AFF5FF9BA8F5FF919FF6FF8796F6FF7D8D
+ F7FF393986E6FFFFFF00FFFFFF00FFFFFF00FFFFFF004550BFE6C7CAF1FFBFC5
+ F3FFB7BEF3FFAEB7F4FFA6AFF4FF9BA7F5FF929FF6FF8796F6FF7C8DF7FF7284
+ F7FF393986E6FFFFFF00FFFFFF00FFFFFF00FFFFFF004550BFE6BFC5F2FFB7BE
+ F3FFAFB7F4FFA5AFF4FF9CA7F5FF929FF6FF8795F6FF7D8DF7FF7284F8FF687C
+ F8FF393986E6FFFFFF00FFFFFF00FFFFFF00FFFFFF004550BFE6B7BEF3FFAFB7
+ F4FFA6B0F4FF9BA8F5FF929FF6FF8796F6FF7C8DF7FF7284F8FF677BF8FF5D73
+ F9FF393986E6FFFFFF00FFFFFF00FFFFFF00FFFFFF004550BFE6AEB7F3FFA5AF
+ F5FF9CA7F5FF919FF5FF8796F7FF7C8DF7FF7284F8FF687BF9FF5D73F9FF536B
+ FAFF393986E6FFFFFF00FFFFFF00FFFFFF00FFFFFF004550BFE6A6AFF4FF9CA7
+ F5FF919FF5FF8796F6FF7D8DF7FF7184F7FF687CF8FF5D73F9FF546AFAFF4A63
+ FBFF393986E6FFFFFF00FFFFFF00FFFFFF00FFFFFF004550BFE69BA7F5FF929F
+ F5FF8796F7FF7C8DF7FF7284F8FF677CF8FF5E73F9FF546BFAFF4A63FBFF415C
+ FBFF393986E6FFFFFF00FFFFFF00FFFFFF00FFFFFF004550BFE6929EF5FF8796
+ F6FF7C8DF7FF7285F8FF687CF9FF5E73F9FF546BFAFF4B63FBFF425CFBFF3955
+ FCFF393986E6FFFFFF00FFFFFF00FFFFFF00FFFFFF004550BFE68796F6FF7C8D
+ F7FF7284F8FF687CF8FF5E73FAFF536AFAFF4A63FAFF425CFBFF3A55FCFF334F
+ FCFF393986E6FFFFFF00FFFFFF00FFFFFF00FFFFFF004550BFE6393986E63939
+ 86E6393986E6393986E6393986E6393986E6393986E6393986E6393986E63939
+ 86E6393986E6FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF007A5841077A553D067C563D047B573D067A58
+ 40257B5940277958420A0000000040435F040000000000000000000000000000
+ 00000000000000000000000000000000000000000000000000007B573D007755
+ 3E0DAB691B1A4B465B6D0636ABDF0235ADFF0236B0FB062B8DA4000000002230
+ 6300000000000000000000000000000000000000000000000000000000003C40
+ 681D19388ECF092E8EFD0135B1FF042894FF022F9FFE0132ABFF06247C870000
+ 0000000000000000000000000000000000000000000000000000000000000F36
+ 9DBC01299AFF0330A6FF042591FE052889FF011775FF0131ABFE012791FF071E
+ 6AAB00000000031B6D0000000000000000007F7266000000000000099A010332
+ ACE20F3A85F10B76EAFF0B7EF0FF125CABFF0971E5FF032894FF002CA2FE0019
+ 6DFF051B6BDD13266622000000000000000073665B06756C691D676B7A210841
+ B7EF137EECFF0C89FFFE1770CFFF2A78C8FF0A7BF3FF054BBAFF002BA0FF042A
+ 83FF00196DFE021766FF111D5F24747A8906706A642A78645728546482632180
+ E5FF165CB3FF1961BBFF3395F9FF0979F3FF0579F8FF0379FCFF04339EFF0529
+ 92FF022176FF001462FF03145FC87C88B10B818AAA29798C9F27428FDEBD124D
+ A1FF0E2F68FF3488E5FF379AFFFF147AEBFF0377F6FF0373EEFF025DD1FF0215
+ 74FF03218AFF021468FF010F5BED7A86A524708BA9186E90BA1F4898E7C63591
+ EEFF3A9BFFFF3495FBFF3286E7FF2082F2FF0075F4FF0073EEFF006FE8FF0216
+ 77FF01218BFF011A7DFF010B56FF000000008190A405000000004C96E0A53794
+ F8FF3493FAFF2F8EF9FF2F8DF9FF1E87F8FF0276F1FF0071EBFF0161D3FF011C
+ 84FF011E85FF001B7FFF010C5BFF0000000000000000000000003F93ECAC3294
+ FFFF3091FEFF2F8FFCFF2B86EFFF052688FF021571FF053090FF033C9EFF001D
+ 86FF021979FF001B7FFF000A5AFF0000000000000000000000002860B98D2E8B
+ FAFF2B86EFFF206DD4FF032C95FF00197CFF011573FF001473FF021A7DFF001C
+ 81FF021876FF00177AFF000958FF0000000000000000000000000F2C88890127
+ 99FF012491FF002392FF002491FF001778FF02136FFF021A7CFF011B7EFF0119
+ 7BFF011372FF011472FF01064FFF000000000000000000000000192A752A0223
+ 8BFF02228BFF00238FFF011C81FF021777FF011C7FFF001B7EFF00187AFF0111
+ 6CFF010E69FF000B61FF000541FF000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000FFFFFF00C17D4460C88B4DBBC88C4FEEC88C
+ 4FF6C88C4FF7C88C4FF7C88D4FF7C98C4FF7C78B4FF7C5894BD4C4763B91B368
+ 3C06FFFFFF00FFFFFF00FFFFFF00FFFFFF00C48549C3F7F2ECECF8F4EEFCF8F4
+ EDFFF8F3EDFFF8F3EDFFF8F3EDFFF8F2ECFFF7F2ECFFF2E6D7FFE2B27DFFDB94
+ 65F5B3683B07FFFFFF00FFFFFF00FFFFFF00C5884BEAFAF6F2FCFAE0C7FFFBE1
+ C9FFFBE2C9FFFBE0C8FFF9DFC5FFF8DBC1FFF4D6B8FFFFFBF8FFF6D8B4FFE1B0
+ 7DFFDB9264F6B46B3E07FFFFFF00FFFFFF00C6894CF6F9F5F1FFFCE3CDFFFBE3
+ CEFFFBE3CDFFFBE2CBFFF9E0C8FFF8DCC2FFF5D6BAFFFDFBF8FFFCE6CDFFFAE5
+ C9FFE2B684FFBF7942A6FFFFFF00FFFFFF00C6894BF7F9F5F1FFFCE3CFFFFBE4
+ D0FFFCE4CFFFFCE3CDFFFAE1CAFFF9DDC4FFF6D9BCFFF4E9DFFFF7F2ECFFFBF7
+ F3FFF5EFE9FFC27E45FBFFFFFF00FFFFFF00C6894BF7F9F4F0FFFCE6D3FFFCE6
+ D4FFFDE7D3FFFCE4D1FFFBE3CDFFFAE0C8FFF8DCC2FFF5D6BBFFF3D4B5FFF1D2
+ B3FFF8F4F0FFC48246F7FFFFFF00FFFFFF00C6884AF7F9F4EFFFFEE7D7FFFDE7
+ D6FFFDE7D5FFFDE6D4FFFCE6D2FFFBE1CCFFFADFC7FFF8DCC2FFF6DABDFFF6D8
+ BBFFFAF4EFFFC68346F7FFFFFF00FFFFFF00C68849F7F9F4EDFFFEE8D8FFFEE8
+ D8FFFEE8D7FFFEE7D6FFFDE5D3FFFCE4D1FFFBE1CCFFFAE0C7FFF9DDC3FFF8DC
+ C2FFFAF4EDFFC68245F7FFFFFF00FFFFFF00C68447F7F9F3ECFFFEE8D6FFFEE8
+ D7FFFDE7D6FFFDE7D6FFFDE7D5FFFDE5D3FFFBE4D0FFFBE3CCFFFADFC7FFFADF
+ C6FFFAF2EAFFC68042F7FFFFFF00FFFFFF00C58245F7F8F2EBFFFEE7D6FFFDE7
+ D6FFFDE7D6FFFDE7D6FFFDE6D5FFFDE5D3FFFCE4D1FFFCE2CDFFFBE1CBFFFBE1
+ C9FFFBF7F2FFC57C3FF7FFFFFF00FFFFFF00C58042F7F8F1E8FFFEE5D5FFFDE5
+ D3FFFDE5D3FFFCE5D3FFFCE5D3FFFCE4D1FFFCE2CEFFFCE2CCFFFBE0C9FFFBE1
+ C8FFFDFAF7FFC1763BF7FFFFFF00FFFFFF00C47C40F7F7F0E6FFF8B455FFF7B4
+ 56FFF7B554FFF8B453FFF8B253FFF7B352FFF7B352FFF7B251FFF7B24FFFF7B2
+ 4FFFFCF9F5FFBF6F36F7FFFFFF00FFFFFF00C1783CF7F7EDE3FFFDC26EFFFFD8
+ A0FFFFD79EFFFFD69BFFFFD798FFFFD696FFFFD695FFFFD594FFFFD493FFFBBE
+ 65FFFBF7F4FFBB6731F7FFFFFF00FFFFFF00BF7138F5F5EBDFFEFDBF68FFFCBD
+ 67FFFBBE65FFFCBE64FFFCBE64FFFCBD62FFFBBD63FFFBBC61FFFCBE60FFFCBC
+ 62FFFDFBF8FDB9642DF3FFFFFF00FFFFFF00BC6933DEF8F1EAF2F7ECDFFDF6EB
+ DEFFF6EADEFFF6EADCFFF6EADCFFFAF3EBFFFAF3EBFFFAF2EAFFFCF7F3FFFCF8
+ F4FDFEFEFDF0B7602AD5FFFFFF00FFFFFF00BB6A346BBA6530BCBB6631EDBA66
+ 30F7BA6630F7BA6630F7BA6530F7BA652FF7B9652EF7B9652EF7B9642EF7B964
+ 2EEFB7622CBDB7622E63FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00EAC39DFFE6BF96FFE4BB92FFE4BB92FFD1A06CF5D09E6DF6CC96
+ 5FDAC479427EB2673C09FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00E5BE96FFFFFFFEFFFDF3E9FFFDF3EAFFFCF2E8FFFAEFE3FFFAF2
+ E7FFEABB88FFCF8555B3B4693D0CFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00E4BB93FFFEF5EDFFFCDEC5FFFBE0C7FFF9DCC2FFF5D3B4FFFEF9
+ F3FFFAE2C4FFECC193FFC37D4893FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00E4BB92FFFEF6F0FFFCE2CDFFFCE3CDFFFADFC8FFF7D9BCFFF5E9
+ DDFFFAF3EBFFFBF8F3FFCA8353FEFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00E4BB92FFFEF7F1FFFCE5D2FFFCE4D1FFFBE2CCFFF9DDC4FFF6D7
+ BBFFF3D1AFFFFAEFE4FFCC8758FE34B4D9D05EC2E1FA60C3E2FA60C3E2FA60C3
+ E2FA5FC3E2FAE4BB91FFFFF7F2FFFEE7D5FFFEE7D5FFFDE5D1FFFAE0CAFFF9DE
+ C4FFF7D9BCFFFDF2E7FFCC8757FE36B3DAF8FDFEFEFFFEFFFFFFFEFEFFFFFDFE
+ FFFFFEFFFFFFE4BA91FFFFF7F0FFFFE7D5FFFDE7D6FFFDE6D4FFFCE4D0FFFBE3
+ CBFFFADCC2FFFEF3E8FFCC8656FE35AFDAF0F7FCFEFF8EE4F8FF91DEF5FF9FE0
+ F5FFACE1F6FFCA8452FFFFF7F1FFFFE9D9FFFFEADBFFFFE9D9FFFFE7D7FFFFE5
+ D2FFFFE2CBFFFFF7F1FFCB8555FE36AADAF2F1FAFDFF94DEF5FF93DCF4FF64BC
+ E9FF3594DAFF3594DAFF3594DAFF3594DAFF3594DAFF3594DAFF3594DAFF3594
+ DAFF3594DAFFFBF6EFFFCC8355FE35ABDAFAE8F6FBFF70BCE7FF55AAE2FF4DA5
+ E0FF91C9EBFFFAF3EFFFFDFEFDFFFFFDFCFFFFFDFCFFFEFDFCFFFEFCFBFFFEFE
+ FDFF3594DAFFEFF2E8FFCE8156FF37A6DAFAFEFFFFFFF8FDFFFFF6FDFFFFF5FC
+ FFFFF3FCFEFF9AE4F4FF9AE6F7FF9BE6F6FF9DE5F5FF9EE5F5FF9FE5F4FFDAF3
+ F8FF3594DAFFFDF4EEFFCA8054F936A1DAF9F6FCFEFF94E5F8FF93E5F8FF93E5
+ F8FF91E5F8FF93DBE9FF93D7E3FF93D2DCFF90CED7FF8CC8CFFF86C1C6FFC9D8
+ D6FF3594DAFFC57444E8CA7F53F1369ADAF8F2FAFDFF94E6F8FF92E5F8FF90E5
+ F8FF8BE3F8FF86E2F7FF7FE1F7FF77DEF6FF6CDCF6FF5ED9F4FF4FD5F3FFCCF2
+ FBFF3594DAFFFFFFFF00FFFFFF003594DAF7EFFAFEFF93E5F8FF8FE4F8FF89E3
+ F8FF82E1F7FF7ADFF7FF71DEF6FF67DBF5FF5BD8F4FF4DD4F3FF40D1F2FFCAF2
+ FBFF3594DAFFFFFFFF00FFFFFF00338ED9FBDCF0FAFF98E1F6FF95E0F6FF92DF
+ F6FF8EDEF5FF89DCF5FF85DAF4FF80D9F4FF7AD7F3FF74D5F3FF70D3F2FFC2EA
+ F8FF3594DAFFFFFFFF00FFFFFF002C86D8D12D88D8F72D87D8F72D88D8F72D88
+ D8F72D88D8F72D88D8F72D88D8F72D88D8F72D88D8F72D88D8F72D87D8F72D88
+ D8F72C86D8D1FFFFFF00FFFFFF00FFFFFF00FFFFFF002063982A206398FF2063
+ 98FF206398FF206398FF206398FF206398F0FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF0020639832206398B2206398FF3775A4FFB6EF
+ FEFF80DBF3FF80DBF3FFB6EFFEFF2E6EA1FF206398FF206398A520639853FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00206398E071B3DBFE7EBFE4FF4E9DDFFFB5EE
+ FDFF75D4F0FF75D4F0FFB5EEFDFF4B9BDEFF6EB4E0FF6DB3DFF9206398F3FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00206398FF7FBFE4FF69B2DEFF4A9BDAFF4497
+ DCFF4396DCFF4296DCFF4295DCFF4195DBFF519ED6FF6CB2DEFF206398FFFFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00206398FF7CBDE4FF65AEDDFF62ABDCFF5EA8
+ DAFF5CA7D9FF5CA7D9FF5CA7D9FF5CA7D9FF529FD7FF62A3D8FF206398FFFFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00206398FF7ABBE3FF61AADBFF5AA5D9FF53A0
+ D7FF529FD7FF529FD7FF529FD7FF529FD7FF529FD7FF62A3D8FF206398FFFFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00206398FF76B9E2FF5CA7D9FF58A4D8FF53A0
+ D7FF539ED5FF618BA9FF6488A1FF6487A1FF6386A0FF69879FFF4A6881FF6A6A
+ 6A8A6868688A6565658A62626263206398FF73B7E1FF57A3D7FF53A0D7FF509D
+ D5FF5299CFFF7594ACFFF8F8F8FFF2F2F2FFF2F2F2FFF2F2F2FFF2F2F2FFF2F2
+ F2FFF1F1F1FFF4F4F4FA5E5E5E84206398FF70B5E0FF529FD7FF509CD6FF4E98
+ D4FF4F95CDFF7391AAFFF1F1F1FFB7B7B7FFB6B6B6FFB6B6B6FFB6B6B6FFB5B5
+ B5FFB5B5B5FFEEEEEEFA5A5A5A84206398FF6DB3DFFF509CD5FF4E98D3FF4B94
+ D1FF4C91CBFF708EA7FFF1F1F1FFE9E9E9FFE9E9E9FFE8E8E8FFE8E8E8FFE8E8
+ E8FFE7E7E7FFEDEDEDFA56565684206398FF6BB1DEFF4D97D3FF4B93D2FF488F
+ D0FF4A8CC9FF6F8BA5FFF1F1F1FFB6B6B6FFB5B5B5FFB5B5B5FFB4B4B4FFB4B4
+ B4FFB4B4B4FFEDEDEDFA53535384206398FF69AEDCFF4A93D1FF488FD0FF468B
+ CEFF4788C7FF6C88A3FFF0F0F0FFE8E8E8FFE8E8E8FFE7E7E7FFE7E7E7FFE7E7
+ E7FFE7E7E7FFEDEDEDFA4F4F4F84206398FF68ABDCFF488ECFFF468BCEFF4387
+ CDFF4484C6FF6885A1FFF0F0F0FFB4B4B4FFB4B4B4FFB4B4B4FFB4B4B4FFB4B4
+ B4FFB3B3B3FFEDEDEDFA4C4C4C84206398C262A5D7FF65A8DAFF64A6D9FF62A4
+ D8FF629FD1FF758EA4FFEFEFEFFFE7E7E7FFE7E7E7FFE7E7E7FFE7E7E7FFE6E6
+ E6FFE6E6E6FFECECECFA494949842063984A206398CF206398FF206398FF2063
+ 98FF246395FF587388FFF7F7F7FFF0F0F0FFF0F0F0FFF0F0F0FFF0F0F0FFF0F0
+ F0FFF0F0F0FFF3F3F3FA46464684FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF005E5E5E025B5B5B775858588A5555558A5252528A4F4F4F8A4C4C4C8A4A4A
+ 4A8A4848488A4646468A44444466FFFFFF000000000000000000000000000000
+ 00000000000000000000000000000000000000A0C4FF00000000000000000000
+ 0000000000000000000000000000FFFFFF000000000000000000000000000000
+ 00000000000000000000000000000000000000A0C4FF00A0C4FF009DBF140000
+ 0000000000000000000000000000FFFFFF000000000000000000000000000000
+ 00000000000000000000000000000000000000A0C4FFADF3FBFF00A0C4FF0579
+ 7D11000000000000000000000000FFFFFF00000000000000000000000000067A
+ 7C0B1BA1BBA4159FBBCF13A1BEE700A0C4FF00A0C4FF25E4FBFFADF3FBFF00A0
+ C4FF05797D110000000000000000FFFFFF00000000000000000005797D1C14A3
+ C1D514A1BCD46CE8F7F86EE8F7FF6FEBFAFF73ECFAFF20E3FAFF31E1F6FFADF3
+ FBFF00A0C4FF05797D1100000000FFFFFF000000000005797D3213A3C1E441CE
+ E3FE69E7F6FF36D9ECFF16CDE3FF29DBF1FF2FE0F5FF29DBF1FF32E2F7FF2FE0
+ F6FFADF3FBFF00A0C4FF05797D0AFFFFFF0005797D0A16A1BDCA40CDE1FF36D9
+ ECFF1DD2E8FF1DD2E8FF1DD2E8FF29DBF1FF2FE0F5FF32E2F7FF32E2F7FF32E2
+ F8FF2FE0F6FFADF3FBFF00A0C4FFFFFFFF0015A0BCCB1BABC5F86AE5F3FF0BC8
+ DFFF1DD2E8FF1DD2E8FF1DD2E8FF04C0D6FF04C0D6FF04C0D6FF2CDFF4FF32E2
+ F8FF79EDFBFF00A0C4FF05797E11FFFFFF001BA3BFF46FDCEBFF07C2D8FF0AC8
+ DFFF05DDF7FF69EAF9FF69EAF9FF69EAF9FF69EAF9FF76EDFBFF04C3DAFF76ED
+ FBFF00A0C4FF05797D1100000000FFFFFF001AA4C0F869E4F2FF0FC9DFFF6EE1
+ EEFF01A9C4FF00A0C4FF00A0C4FF00A0C4FF00A0C4FF76EDFBFF76EDFBFF00A0
+ C4FF05797D110000000000000000FFFFFF0019A3C1FF76E2EFFF6DE6F5FF00A0
+ C4C90099B95000A0C430000000000000000000A0C4FF76EDFBFF00A0C4FF0579
+ 7D11000000000000000000000000FFFFFF0011A2C2FF88E7F2FE02ACC8FF009E
+ C11A0000000000000000000000000000000000A0C4FF00A0C4FF000000000000
+ 0000000000000000000000000000FFFFFF0023A6C0EF5DDAE9FE0EAACBFE0000
+ 00000000000000000000000000000000000000A0C4FF00000000000000000000
+ 0000000000000000000000000000FFFFFF0023A6C07F43C5D8FE43C4DBFC00A0
+ C422000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000FFFFFF000000000011A6C2AE66DBEAB200A0
+ C45D000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000FFFFFF000000000000A0C4181AA7C46918A6
+ C369000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000000000000000000000000000
+ 0000000000000000000000000000000000000000000067676AFF5D5D61FF5757
+ 5BFF535357FF4C4C50FF00000023FFFFFF000000000000000000000000000000
+ 0000000000000000000000000000000000000000000059595CFFC0C0C6F6C4C4
+ CAFFAFAFB4D9434347FF0000005FFFFFFF000000000000000000000000004040
+ FFFF3A3AFFFF3A3AFFFF3D3DFFFF000000230000000B4D4D50FFBFBFC5F6C2C2
+ C8FFB6B6BCCE414144FF0000006BFFFFFF0000000000000000002727FFFF1111
+ FFFF0B0BFFFF1818FFFF2B2BFFFF3030FFFF0000003B46464AFFBDBDC3F6C0C0
+ C6FFBEBEC4C3424246FF0000005FFFFFFF00000000002525FFFF0000FBFF0000
+ 00770000008F0000008F1A1AFFFF2121FFFF0D0DFFFF434347FFBBBBC1F6BBBB
+ C1FFB8B8BDC3454549FF0000005FFFFFFF003131FFFF0A0AFFFF000000770000
+ 0077000000470000002F1818FFFF1515FFFF0000FCFF404044FFB5B5BBF8B6B6
+ BCFFB2B2B7C3454549FF0000005FFFFFFF002323FFFF0000FBFF0000008F0000
+ 00470000000B000000002222FFFF0F0FFFFF0000EFFF3D3D40FF99999EE3A9A9
+ AED5ADADB39C414145FF0000005FFFFFFF001A1AFFFF0000F9FF0000008F0000
+ 002F00000000000000003030FFFF1010FFFF0000EAFF3C3C3FFF3D3D41FF4040
+ 44FF3F3F42FF3A3A3EFF0000006BFFFFFF001717FFFF0000FDFF0000008F0000
+ 002F00000000000000003939FFFF1616FFFF0000F1FF000000B30000008F0000
+ 006B0000005F0000006B0000005FFFFFFF001313FFFF0000FAFF0000008F1818
+ FFFF3A3AFFFF000000233737FFFF1919FFFF0000F8FF0000009B0000D1FF0000
+ C5FF000000530000003B00000023FFFFFF000404FFFF0000E9FF0000008F0000
+ 00471F1FFFFF2C2CFFFF2222FFFF0A0AFFFF0000EDFF0000D1FF0000BDFF0000
+ 006B000000530000001700000000FFFFFF000000EDFF0000D0FF0000008F0000
+ 003B0000F9FF0303FFFF0000FCFF0000E6FF0000C8FF0000ADFF0000A2FF0000
+ 008F000000470000000B00000000FFFFFF000000D8FF0000BFFF0000008F0000
+ 002F000000230000DEFF0000D1FF0000B9FF00009EFF00008CFF000000B30000
+ 0077000000230000000000000000FFFFFF00000000230000006B0000006B0000
+ 00230000000B0000003B0000B8FF00009CFF000087FF000000B3000000830000
+ 003B0000000B0000000000000000FFFFFF000000000B00000023000000230000
+ 000B000000000000000B0000003B00009FFF000000A7000000830000003B0000
+ 000B000000000000000000000000BC6B3671BC6B3690BC6B36CCBC6B36EEBC6B
+ 36FABB6B36FEBB6B36FFBB6A36FFBB6A36FFBC6C39FFBD6E3BFFBB6D3AFFBB6B
+ 38EFBB703ECBB6693554FFFFFF00BC6B369BF6E0D1FFF7E0D1FFFEFBF8FFFEFB
+ F7FFFDF9F6FFFCF5F0FFFAF0EAFFFBF2EDFFFDF9F6FFFDFAF7FFFBF1EBFFF8E9
+ DFFEECD0BDFBC9895EECB5693563BC6B36D8F6DFD1FFE9AA80FFFEFAF6FFFDFA
+ F6FFC88C64FFFBF3EEFFFBF1EAFFFCF6F2FFFEFBF8FFFCF6F1FFF9ECE2FFF8E7
+ DBFFEED0BAFFECD0BDFFBB703EF8BC6B36F0F6DFD0FFE8A87EFFFCF6F1FFFCF6
+ F1FFC88C64FFFAF1E9FFFBF4EEFFFDFAF7FFFDF9F6FFFAF0E8FFF8E8DDFFF7E6
+ DBFFE1A37AFFEFD5C3FFB76935FEBC6B36FAF5DDCCFFE7A87EFFFAF0E8FFFAF0
+ E8FFC98D66FFFAF0E9FFFDF8F3FFFEFAF8FFFCF4EFFFF9E9DFFFF7E7DBFFF7E5
+ D9FFE0A278FFE7C2A9FFB66835FFBB6B36FEF4DCC9FFE7A77DFFF9ECE1FFF9EC
+ E1FFF9EDE3FFFCF4EEFFFDFAF7FFFDF7F3FFFAEDE5FFF7E7DBFFF7E5D9FFF6E5
+ D8FFDEA077FFE4BEA4FFB46734FFBB6B36FFF4D9C7FFE6A67DFFC88C64FFC98D
+ 65FFC98E67FFCB926CFFCB926DFFCA9069FFC88C65FFC88C64FFC88C64FFC88C
+ 64FFDA9C74FFE1BA9FFFB36634FFBB6A36FFF2D8C5FFE3A47BFFE3A37AFFE3A4
+ 7AFFE2A47BFFE2A37BFFE1A37BFFE1A279FFDFA077FFDE9F76FFDD9E74FFDB9C
+ 72FFDC9D74FFDDB59AFFB16534FFBB6A36FFF2D5C2FFE3A37AFFE3A37AFFE2A3
+ 7BFFE2A37BFFE2A47BFFE1A279FFE0A178FFDEA077FFDE9E75FFDC9D74FFDA9B
+ 73FFD99B73FFDAB095FFAF6433FFBB6A36FFF0D2BEFFE2A37AFFE2A37AFFE1A3
+ 7AFFE2A37BFFE1A37BFFE0A178FFDE9F77FFDD9F76FFDC9D74FFD99B72FFD899
+ 71FFD69970FFD5AB8EFFAD6333FFBA6A36FFEFD0BBFFE2A27AFFFEFBF8FFFEFB
+ F8FFFEFBF8FFFEFBF8FFFEFBF8FFFEFBF8FFFEFBF8FFFEFBF8FFFEFBF8FFFEFB
+ F8FFD3966DFFD2A78AFFAB6232FFBB6B38FFEFCEB8FFE1A279FFFEFAF7FF62C0
+ 88FF62C088FF62C088FF62C088FF62C088FF62C088FF62C088FF62C088FFFDF9
+ F6FFCF936AFFCEA384FFAA6132FFBB6C38FFEECCB6FFE1A27AFFFEFAF7FFBFDC
+ C2FFBFDCC2FFBFDCC2FFBFDCC2FFBFDCC2FFBFDCC2FFBFDCC2FFBFDCC2FFFDF9
+ F6FFCD9068FFCC9E81FFA86132FFBA6B37FEEDCAB3FFE0A27AFFFEFAF7FF62C0
+ 88FF62C088FF62C088FF62C088FF62C088FF62C088FF62C088FF62C088FFFDF9
+ F6FFCA8D65FFC99B7CFFA76031FEBA6A35DEEBC6ADFFEAC5ADFFFEFBF8FFFEFB
+ F8FFFEFBF8FFFEFBF8FFFEFBF8FFFEFBF8FFFEFBF8FFFEFBF8FFFEFBF8FFFEFB
+ F8FFC89A7CFFC79879FFA76031EDBA6A368FB96935B5B86935EEB76835FFB568
+ 35FFB46734FFB26634FFB06533FFAE6433FFAC6332FFAA6232FFA96132FFA860
+ 31FFA76031FEA66031F1A86131C4FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00555555225555555955555566555555665555
+ 5566555555665555556655555566555555665555556655555566555555665555
+ 55665555556655555559555555225252525BC6C6C6D4DCDCDCFFD8D9D9FFD5D5
+ D5FFD0D1D1FFCCCCCCFFC8C8C8FFC6C6C6FFC6C5C5FFC9C5C5FFCDC6C6FFD1C7
+ C7FFD7CBCBFFC4B8B8D45252525B50505069BBBBBBFFBABABAFFB8B8B8FFB6B6
+ B6FFB3B3B3FFB0B0B0FFAEAEAEFFABABABFFA8A8A8FFA6A6A6FFA3A3A3FFA0A0
+ A0FF9E9E9EFF9C9C9CFF0303036655555567FFFFFFFFFFFFFFFFFFFFFFFFFFFF
+ FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+ FFFFFFFFFFFFFFFFFFFF5555556751515168FDFDFDFFFCFCFCFFFCFCFCFFFCFC
+ FCFFFCFCFCFFFCFCFCFFFCFCFCFFFCFCFCFFFCFCFCFFFCFCFCFFFCFCFCFFFCFC
+ FCFFFCFCFCFFFDFDFDFF515151684D4D4D6AFAFAFAFFF8F8F8FFF8F8F8FFF8F8
+ F8FFF8F8F8FFF8F8F8FFF8F8F8FFF8F8F8FFF8F8F8FFF8F8F8FFF8F8F8FFF8F8
+ F8FFF8F8F8FFFAFAFAFF4D4D4D6A4949496CF7F7F7FFF4F4F4FFF4F4F4FFF4F4
+ F4FFF4F4F4FFF4F4F4FFF4F4F4FFF4F4F4FFF4F4F4FFF4F4F4FFF4F4F4FFF4F4
+ F4FFF4F4F4FFF7F7F7FF4949496C4444446EF3F3F3FFEFEFEFFFEFEFEFFFEFEF
+ EFFFEFEFEFFFEFEFEFFFEFEFEFFFEFEFEFFFEFEFEFFFEFEFEFFFEFEFEFFFEFEF
+ EFFFEFEFEFFFF3F3F3FF4444446E3E3E3E71F0F0F0FFEBEBEBFFEBEBEBFFEBEB
+ EBFFEBEBEBFFEBEBEBFFEBEBEBFFEBEBEBFFEBEBEBFFEBEBEBFF6BC45FFF40B6
+ 2FFF6BC45FFFF0F0F0FF3E3E3E7138383873EDEDEDFFE6E6E6FFE6E6E6FFE6E6
+ E6FFE6E6E6FFE6E6E6FFE6E6E6FFE6E6E6FFE6E6E6FFE6E6E6FF3EB12EFF75EE
+ 64FF3EB12EFFEDEDEDFF3838387332323276EAEAEAFFE2E2E2FFE2E2E2FFE2E2
+ E2FFE2E2E2FFE2E2E2FFE2E2E2FFE2E2E2FF66B95BFF3CAB2DFF3CAB2DFF66EB
+ 55FF3CAB2DFF3EAD2FFF1C7A11C82727277BEBEBEBFFE7E7E7FFE7E7E7FFE7E7
+ E7FFE7E7E7FFE7E7E7FFE7E7E7FFE7E7E7FF3BA52FFF52E741FF52E741FF52E7
+ 41FF52E741FF52E741FF128905E50D0D0D671010108510101085101010851010
+ 1085101010851010108510101085101010850E6204CF0E7E02E70E7E02E73DE2
+ 2CFF0E7E02E70E7E02E70B5F02B000000009000000160000001A0000001A0000
+ 001A0000001A0000001A0000001A0000001A0000001A0000001A0B8000D12BDF
+ 1AFF0B8000D10000001600000009000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000004390000066D00990569
+ 00CC066D00990439000000000000FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00555555225555555955555566555555665555
+ 5566555555665555556655555566555555665555556655555566555555665555
+ 55665555556655555559555555225252525BC6C6C6D4DCDCDCFFD8D9D9FFD5D5
+ D5FFD0D1D1FFCCCCCCFFC8C8C8FFC6C6C6FFC6C5C5FFC9C5C5FFCDC6C6FFD1C7
+ C7FFD7CBCBFFC4B8B8D45252525B50505069BBBBBBFFBABABAFFB8B8B8FFB6B6
+ B6FFB3B3B3FFB0B0B0FFAEAEAEFFABABABFFA8A8A8FFA6A6A6FFA3A3A3FFA0A0
+ A0FF9E9E9EFF9C9C9CFF0303036655555567FFFFFFFFFFFFFFFFFFFFFFFFFFFF
+ FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+ FFFFFFFFFFFFFFFFFFFF5555556751515168FDFDFDFFFCFCFCFFFCFCFCFFFCFC
+ FCFFFCFCFCFFFCFCFCFFFCFCFCFFFCFCFCFFFCFCFCFFFCFCFCFFFCFCFCFFFCFC
+ FCFFFCFCFCFFFDFDFDFF515151684D4D4D6AFAFAFAFFF8F8F8FFF8F8F8FFF8F8
+ F8FFF8F8F8FFF8F8F8FFF8F8F8FFF8F8F8FFF8F8F8FFF8F8F8FFF8F8F8FFF8F8
+ F8FFF8F8F8FFFAFAFAFF4D4D4D6A4949496CF7F7F7FFF4F4F4FFF4F4F4FFF4F4
+ F4FFF4F4F4FFF4F4F4FFF4F4F4FFF4F4F4FFF4F4F4FFF4F4F4FFF4F4F4FFF4F4
+ F4FFF4F4F4FFF7F7F7FF4949496C4444446EF3F3F3FFEFEFEFFFEFEFEFFFEFEF
+ EFFFEFEFEFFFEFEFEFFFEFEFEFFFEFEFEFFFEFEFEFFFEFEFEFFFEFEFEFFFEFEF
+ EFFFEFEFEFFFF3F3F3FF4444446E3E3E3E71F0F0F0FFEBEBEBFFEBEBEBFFEBEB
+ EBFFEBEBEBFFEBEBEBFFEBEBEBFFEBEBEBFFEBEBEBFFEBEBEBFFEBEBEBFFEBEB
+ EBFFEBEBEBFFF0F0F0FF3E3E3E7138383873EDEDEDFFE6E6E6FFE6E6E6FFE6E6
+ E6FFE6E6E6FFE6E6E6FFE6E6E6FFE6E6E6FFE6E6E6FFE6E6E6FFE6E6E6FFE6E6
+ E6FFE6E6E6FFEDEDEDFF3838387332323276EAEAEAFFE2E2E2FFE2E2E2FFE2E2
+ E2FFE2E2E2FFE2E2E2FFE2E2E2FFE2E2E2FF5B5BBEFF2D2DB3FF2D2DB3FF2D2D
+ B3FF2D2DB3FF2F2FB5FF111181C82727277BEBEBEBFFE7E7E7FFE7E7E7FFE7E7
+ E7FFE7E7E7FFE7E7E7FFE7E7E7FFE7E7E7FF2F2FA7FF5E5EF7FF5E5EF7FF5E5E
+ F7FF5E5EF7FF5E5EF7FF05058BE50D0D0D671010108510101085101010851010
+ 10851010108510101085101010851010108504045BCF020273E7020273E70202
+ 73E7020273E7020273E7020258B000000009000000160000001A0000001A0000
+ 001A0000001A0000001A0000001A0000001A0000001A0000001A0000001A0000
+ 001A0000001A0000001600000009FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00000000000000000000000000000000000000
+ 0000000000000000000B000000230000002F0000002F0000002F0000002F0000
+ 00230000000BFFFFFF00FFFFFF00000000000000000000000000000000000000
+ 000B00000023000000478AD3FFFF5FC3FFFF28AEFFFF009FFFFF0088DAFF0077
+ BFFF00000017FFFFFF00FFFFFF000000000B000000230000002F0000002F0000
+ 004773CAFFFF67C6FFFF51BDFFFF0000006B0000003B0000002F0000002F0000
+ 00230000000BFFFFFF00FFFFFF000000001728AEFFFF1CAAFFFF13A6FFFF0CA4
+ FFFF009FFFFF0000005F0095EFFF007DC8FF0000002300000000000000000000
+ 000000000000FFFFFF00FFFFFF000000000B000000230000002F0000002F0000
+ 002F00000023000000170000004700639EFF000000470000000B000000000000
+ 000000000000FFFFFF00FFFFFF00000000000000000000000000000000000000
+ 0000000000000000000000000023005C94FF00456EFF00000023000000000000
+ 000000000000FFFFFF00FFFFFF00000000000000000000000000000000000000
+ 000000000000000000000000000B00000047005F98FF0000002F000000000000
+ 000000000000FFFFFF00FFFFFF00000000000000000000000000000000000000
+ 00000000000000000000000000000000002F008DE2FF0000002F000000000000
+ 000000000000FFFFFF00FFFFFF00000000000000000000000000000000000000
+ 00000000000000000000000000000000002F0097F2FF0000002F000000000000
+ 000000000000FFFFFF00FFFFFF00000000000000000000000000000000000000
+ 000000000000000000000000000B00000047008ADDFF0000002F000000000000
+ 000000000000FFFFFF00FFFFFF00000000000000000000000000000000000000
+ 00000000000000000000000000231BA9FFFF006FB2FF0000002F000000000000
+ 000000000000FFFFFF00FFFFFF000000000000000000000000000000000B0000
+ 00230000002F0000002F000000530086D7FF004B79FF00000023000000000000
+ 000000000000FFFFFF00FFFFFF000000000000000000000000000000001725AD
+ FFFF0AA3FFFF008ADEFF006CADFF00456FFF0000003B0000000B000000000000
+ 000000000000FFFFFF00FFFFFF000000000000000000000000000000000B0000
+ 00230000002F0000002F0000002F000000230000000B00000000000000000000
+ 000000000000FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00000000000000000000000000000000000000
+ 00000000000000A0C4FF00000000000000000000000000000000000000000000
+ 000000000000000000000000000000000000000000000000000000000000009D
+ BF1400A0C4FF00A0C4FF00000000000000000000000000000000000000000000
+ 000000000000000000000000000000000000000000000000000005797D1100A0
+ C4FFADF3FBFF00A0C4FF00000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000005797D1100A0C4FFADF3
+ FBFF25E4FBFF00A0C4FF00A0C4FF13A1BEE7159FBBCF1BA1BBA4067A7C0B0000
+ 00000000000000000000000000000000000005797D1100A0C4FFADF3FBFF31E1
+ F6FF20E3FAFF73ECFAFF6FEBFAFF6EE8F7FF6CE8F7F814A1BCD414A3C1D50579
+ 7D1C00000000000000000000000005797D0A00A0C4FFADF3FBFF2FE0F6FF32E2
+ F7FF29DBF1FF2FE0F5FF29DBF1FF16CDE3FF36D9ECFF69E7F6FF41CEE3FE13A3
+ C1E405797D32000000000000000000A0C4FFADF3FBFF2FE0F6FF32E2F8FF32E2
+ F7FF32E2F7FF2FE0F5FF29DBF1FF1DD2E8FF1DD2E8FF1DD2E8FF36D9ECFF40CD
+ E1FF16A1BDCA05797D0A0000000005797E1100A0C4FF79EDFBFF32E2F8FF2CDF
+ F4FF04C0D6FF04C0D6FF04C0D6FF1DD2E8FF1DD2E8FF1DD2E8FF0BC8DFFF6AE5
+ F3FF1BABC5F815A0BCCB000000000000000005797D1100A0C4FF76EDFBFF04C3
+ DAFF76EDFBFF69EAF9FF69EAF9FF69EAF9FF69EAF9FF05DDF7FF0AC8DFFF07C2
+ D8FF6FDCEBFF1BA3BFF400000000000000000000000005797D1100A0C4FF76ED
+ FBFF76EDFBFF00A0C4FF00A0C4FF00A0C4FF00A0C4FF01A9C4FF6EE1EEFF0FC9
+ DFFF69E4F2FF1AA4C0F80000000000000000000000000000000005797D1100A0
+ C4FF76EDFBFF00A0C4FF000000000000000000A0C4300099B95000A0C4C96DE6
+ F5FF76E2EFFF19A3C1FF00000000000000000000000000000000000000000000
+ 000000A0C4FF00A0C4FF00000000000000000000000000000000009EC11A02AC
+ C8FF88E7F2FE11A2C2FF00000000000000000000000000000000000000000000
+ 00000000000000A0C4FF00000000000000000000000000000000000000000EAA
+ CBFE5DDAE9FE23A6C0EF00000000000000000000000000000000000000000000
+ 000000000000000000000000000000000000000000000000000000A0C42243C4
+ DBFC43C5D8FE23A6C07F00000000000000000000000000000000000000000000
+ 000000000000000000000000000000000000000000000000000000A0C45D66DB
+ EAB211A6C2AE0000000000000000000000000000000000000000000000000000
+ 000000000000000000000000000000000000000000000000000018A6C3691AA7
+ C46900A0C4180000000000000000FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000A2000000A5000000A8000000
+ A91A0000AA6C0000AAA60000AAC40000AAC40000AAA60000AA6C0000A91A0000
+ A8000000A5000000A200FFFFFF00FFFFFF000000A2000000A5000000A84D0909
+ AEBF3737D0E35C5CEAF56A6AF3FD6969F2FD5B5BE9F53636CFE30909AEBF0000
+ A84D0000A5000000A200FFFFFF00FFFFFF000000A2000000A54D1010B1CD5B5B
+ E8F65F5FE7FF5B5BE3FF5B5BE3FF5B5BE3FF5B5BE3FF5F5FE7FF5858E4F60F0F
+ B0CD0000A54D0000A200FFFFFF00FFFFFF000000A11A0808A8BF5656E2F65151
+ D9FFFFFFFFFF4F4FD7FF4F4FD7FF4F4FD7FF4F4FD7FFFFFFFFFF5050D8FF4F4F
+ DCF60707A7BF0000A11AFFFFFF00FFFFFF0000009E6C3232C6E34949D1FFFFFF
+ FFFFFFFFFFFFFFFFFFFF4242CAFF4242CAFFFFFFFFFFFFFFFFFFFFFFFFFF4747
+ CFFF2A2ABDE300009E6CFFFFFF00FFFFFF0000009AA74747D3F53737BFFF2323
+ ABFFFFFFFFFFF7F7F7FFE8E8E8FFDEDEDEFFDBDBDBFFDDDDDDFF11119BFF1616
+ A0FF2727B4F500009AA7FFFFFF00FFFFFF00000096C44949D1FD3333BBFF2E2E
+ B8FF13139FFFCECECEFFD1D1D1FFD6D6D6FFDCDCDCFF11119EFF1111A1FF1111
+ A1FF1D1DACFD000096C4FFFFFF00FFFFFF00000092C44444CDFD2626B5FF1414
+ ABFF1111AAFFD1D1D1FFD6D6D6FFDCDCDCFFE2E2E2FF1111AAFF1111AAFF1111
+ AAFF1818AFFD000092C4FFFFFF00FFFFFF0000008DA72E2EC0F51212B4FF1111
+ B4FFD1D1D1FFD6D6D6FFDCDCDCFFE2E2E2FFE6E6E6FFEAEAEAFF1111B4FF1111
+ B4FF1212AFF500008DA7FFFFFF00FFFFFF000000896C1616AAE21616C1FFD1D1
+ D1FFD6D6D6FFDCDCDCFF1111ADFF1111ADFFEAEAEAFFEEEEEEFFEEEEEEFF1111
+ BEFF0909A1E30000896CFFFFFF00FFFFFF000000851A03038ABF1818C1F61212
+ B2FFDCDCDCFF1111B2FF1111C8FF1111C8FF1111B2FFEEEEEEFF1111B2FF0F0F
+ BCF6020289BF0000851AFFFFFF00FFFFFF000000830000007F4D040488CD1212
+ C4F61212B6FF1111D1FF1111D1FF1111D1FF1111D1FF1111B6FF0F0FC2F60303
+ 88CD00007F4D00008300FFFFFF00FFFFFF000000000000001F000000534D0202
+ 74BF08089DE30E0EC4F51111D4FD1111D4FD0E0EC4F508089DE3020274BF0000
+ 534D00001F0000000000FFFFFF00FFFFFF0000000004000000170000002B0000
+ 1A430000448000005AAB00005DC400005DC400005AAB0000448000001A430000
+ 002D0000001800000004FFFFFF00FFFFFF00000000020000000C000000160000
+ 001A0000001A0000001A0000001A0000001A0000001A0000001A0000001A0000
+ 00170000000C00000002FFFFFF00545454005454540054545400555555225555
+ 5559555555665555556655555566555555665555556655555566555555665555
+ 55665555556655555559555555225454540052525200525252005252525BC6C6
+ C6D4DBDBDBFFD6D6D6FFD1D1D1FFCBCCCCFFC7C7C7FFC6C4C4FFC8C5C5FFCEC6
+ C6FFD4C9C9FFC4B7B7D45252525B55555500545454005050500050505069BBBB
+ BBFFB9B9B9FFB6B6B6FFB4B4B4FFB0B0B0FFADADADFFA9A9A9FFA6A6A6FFA2A2
+ A2FFA0A0A0FF9D9D9DFF0303036655555500555555005555550054545467FFFF
+ FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+ FFFFFFFFFFFFFFFFFFFF54545467555555225555555955555566535353A5B9B9
+ B9FFB8B8B8FFB8B8B8FFB8B8B8FFB8B8B8FFB8B8B8FFB8B8B8FFC1C1C1FFE5E5
+ E5FFFBFBFBFFFCFCFCFF505050695252525BC6C6C6D4DBDBDBFFD6D6D6FFD1D1
+ D1FFCBCCCCFFC7C7C7FFC6C4C4FFC8C5C5FFCEC6C6FFD4C9C9FFD0C5C5FFBCBC
+ BCFFF6F6F6FFF8F8F8FF4B4B4B6B50505069BBBBBBFFB9B9B9FFB6B6B6FFB4B4
+ B4FFB0B0B0FFADADADFFA9A9A9FFA6A6A6FFA2A2A2FFA0A0A0FF9D9D9DFF9191
+ 91FFF0F0F0FFF4F4F4FF4545456E54545467FFFFFFFFFFFFFFFFFFFFFFFFFFFF
+ FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAEAE
+ AEFFEAEAEAFFEFEFEFFF3D3D3D7150505069FCFCFCFFFBFBFBFFFBFBFBFFFBFB
+ FBFFFBFBFBFFFBFBFBFFFBFBFBFFFBFBFBFFFBFBFBFFFBFBFBFFFCFCFCFFA8A8
+ A8FFE4E4E4FFEBEBEBFF363636744B4B4B6BF8F8F8FFF6F6F6FFF6F6F6FFF6F6
+ F6FFF6F6F6FFF6F6F6FFF6F6F6FFF6F6F6FFF6F6F6FFF6F6F6FFF8F8F8FFA6A6
+ A6FFE8E8E8FFECECECFF2D2D2D784545456EF4F4F4FFF0F0F0FFF0F0F0FFF0F0
+ F0FFF0F0F0FFF0F0F0FFF0F0F0FFF0F0F0FFF0F0F0FFF0F0F0FFF4F4F4FF3131
+ 31B81414148314141483111111653D3D3D71EFEFEFFFEAEAEAFFEAEAEAFFEAEA
+ EAFFEAEAEAFFEAEAEAFFEAEAEAFFEAEAEAFF5E5EC2FF2F2FB5FF3030B6FF0606
+ 9AE60000A3D10000A4D100007C9E36363674EBEBEBFFE4E4E4FFE4E4E4FFE4E4
+ E4FFE4E4E4FFE4E4E4FFE4E4E4FFE4E4E4FF2E2EA7FF5E5EF7FF5E5EF7FF5E5E
+ F7FF5E5EF7FF5E5EF7FF000098CC2D2D2D78ECECECFFE8E8E8FFE8E8E8FFE8E8
+ E8FFE8E8E8FFE8E8E8FFE8E8E8FFE8E8E8FF5F5FADFF2F2F95FF303096FF0505
+ 77E4000080CC000080CC00008499111111651414148314141483141414831414
+ 1483141414831414148314141483141414831414148314141483141414831111
+ 116500005A0000007700000080000000000A000000180000001A0000001A0000
+ 001A0000001A0000001A0000001A0000001A0000001A0000001A000000190000
+ 000B000000000000770000008000FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00D4976EC9D49E7BC9D09871C9D6A4
+ 82C9CD8E68C9CD9069C9D09A75C9D19973C9C88B62C9AD5A202BFFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00CC8D65C9F3CDB0C9FFFFFFC9E3C7
+ B3C9FFFFFFC9FFFFFFC9FFFFFFC9FFFFFFC9EABFA1C9C98960C9FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00C7865BC9EFC09EC9D9A27DF8D39D
+ 7AF8D5A380F8DAAE8FF8D29A77F8D29B77F8D29C77F8D09771F8C88B62DEAD5A
+ 202FFFFFFF00FFFFFF00FFFFFF00FFFFFF00C8885DC9EFBFA1C9D19975F8F4D2
+ B8F8FFFFFFF8E6CDBBF8FFFFFEF8FFFFFFF8FBF6F2F8F8F1EDF8EABFA1DEC989
+ 60DEFFFFFF00FFFFFF00FFFFFF00FFFFFF00CA8D65C9EAB899C9C9895FF8EDBD
+ 9BF8D4976EFFD49E7BFFD09871FFD6A482FFCD8E68FFCD9069FFD09A75FFD199
+ 73FFC88B62FFAD5A2036FFFFFF00FFFFFF00C98B61C9E6B592C9CB8B61F8EEBC
+ 9EF8CC8D65FFF3CDB0FFFFFFFFFFE3C7B3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+ FFFFEABFA1FFC98960FFFFFFFF00FFFFFF00C48154C9EAB697C9CE9873F8EABE
+ A1F8C7865BFFEFC09EFFFFFFFFFFCC936EFFFFFFFFFFFFFFFFFFFFFBF7FFFFF8
+ F1FFE4AF8CFFC78A61FFFFFFFF00FFFFFF00C37F51C9EFB69AC9CC966FF8D6B6
+ 91F8C8885DFFEFBFA1FFFDFCFAFFFEFCFBFFFEFDFDFFFEFDFCFFFDFBFAFFFDFC
+ FBFFDDA885FFC17F53FFFFFFFF00FFFFFF00C68355C9EFCEBAC9C78E66F8E0BC
+ 9CF8CA8D65FFEAB899FFDDA57EFFDDA680FFDBA37CFFD9A07AFFD9A079FFD89F
+ 78FFD89E78FFBF845DFFFFFFFF00FFFFFF00BA68339BC38458C9C58053F8EEB2
+ 96F8C98B61FFE6B592FFE2A781FFE1A781FFDEA37DFFDCA17BFFDB9F79FFD99E
+ 77FFD49A73FFBB7E57FFFFFFFF00FFFFFF00FFFFFF00FFFFFF00C68355DEEFCE
+ BADEC48154FFEAB697FFF3F3EAFFEDF1E6FFEFF1E6FFEFF0E6FFEDF1E5FFF3F5
+ EDFFD59C79FFB07044FFFFFFFF00FFFFFF00FFFFFF00FFFFFF00BA6833ACC384
+ 58DEC37F51FFEFB69AFFEAF3E8FF51BF84FF6FC998FF71C999FF54BF84FFE4F4
+ E9FFDD9C7BFFAA693AFFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00C68355FFEFCEBAFFDDFFFFFF87EEC7FFA2F4D7FFA2F6D7FF8CEEC7FFE0FF
+ FFFFDDA285FFAB6A3EFFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00BA6833C5C38458FFD38B68FFE18F70FFDC8D6CFFDA8B6DFFD78A6EFFCD8B
+ 6CFFAB6D44FFA65F2EFFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00C77947AACC8655CECC8857DECB8856DBCC88
+ 56DBCB8757DBCA8350D0C479426EB2673C08FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00CA8554D0FFFFFFDBFDF3E9DEFDF3EADEFCF2
+ E8DEFAEFE3DEFAF2E7DEEABB88DECF85559CB4693D0AFFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00CB8656DAFEF5EDDEFCDEC5DEFBE0C7DEF9DC
+ C2DEF5D3B4DEFEF9F3DEFAE2C4DEECC193DEC37D4880FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00CB8655DBFEF6F0DEFCE2CDDEFCE3CDDEFADF
+ C8DEF7D9BCDEF5E9DDDEFAF3EBDEFBF8F3DECD9565DCFFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00CB8655DBFEF7F1DEFCE5D2DEFCE4D1DEFBE2
+ CCDEF9DDC4DEEAC39DFFE6BF96FFE4BB92FFE4BB92FFD1A06CF5D09E6DF6CC96
+ 5FDAC479427EB2673C09FFFFFF00CB8654DBFFF7F2DEFEE7D5DEFEE7D5DEFDE5
+ D1DEFAE0CADEE5BE96FFFFFFFEFFFDF3E9FFFDF3EAFFFCF2E8FFFAEFE3FFFAF2
+ E7FFEABB88FFCF8555B3B4693D0CCB8553DBFFF7F0DEFFE7D5DEFDE7D6DEFDE6
+ D4DEFCE4D0DEE4BB93FFFEF5EDFFFCDEC5FFFBE0C7FFF9DCC2FFF5D3B4FFFEF9
+ F3FFFAE2C4FFECC193FFC37D4893CA8452DBFFF7F1DEFFE9D9DEFFEADBDEFFE9
+ D9DEFFE7D7DEE4BB92FFFEF6F0FFFCE2CDFFFCE3CDFFFADFC8FFF7D9BCFFF5E9
+ DDFFFAF3EBFFFBF8F3FFCA8353FECC8352DBFBF5EEDEFFE9D9DEFFEADBDEFFE9
+ D9DEFFE7D7DEE4BB92FFFEF7F1FFFCE5D2FFFCE4D1FFFBE2CCFFF9DDC4FFF6D7
+ BBFFF3D1AFFFFAEFE4FFCC8758FECF8253DEEFF1E7DEFFE9D9DEFFEADBDEFFE9
+ D9DEFFE7D7DEE4BB91FFFFF7F2FFFEE7D5FFFEE7D5FFFDE5D1FFFAE0CAFFF9DE
+ C4FFF7D9BCFFFDF2E7FFCC8757FEC87C4ED3FCF3ECDEFAF1E8DEFAF0E7DEFBF1
+ E9DEFBF2EADEE4BA91FFFFF7F0FFFFE7D5FFFDE7D6FFFDE6D4FFFCE4D0FFFBE3
+ CBFFFADCC2FFFEF3E8FFCC8656FEC7794AB9C8794BCEC87545DDC77545D4C875
+ 45D4C77545D4CA8452FFFFF7F1FFFFE9D9FFFFEADBFFFFE9D9FFFFE7D7FFFFE5
+ D2FFFFE2CBFFFFF7F1FFCB8555FEFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00CC8352FBFBF5EEFFFFE9D9FFFFEADBFFFFE9D9FFFFE7D7FFFFE5
+ D2FFFFE2CBFFFBF6EFFFCC8355FEFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00CF8253FFEFF1E7FFFFE9D9FFFFEADBFFFFE9D9FFFFE7D7FFFFE5
+ D2FFFFE2CBFFEFF2E8FFCE8156FFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00C77949EDFCF3ECFFFAF1E8FFFAF0E7FFFBF1E9FFFBF2EAFFFBF2
+ EAFFFBF2EBFFFDF4EEFFCA8054F9FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00C57342C1C67545E6C87545FEC77545F3C87545F3C77545F3C775
+ 45F3C87546F4C57444E8CA7F53F1FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000FF0100008746FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000
+ 87460000FF01FFFFFF00FFFFFF00FFFFFF000000FF0100008D9600008DFF0000
+ 8E78FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0000008E780000
+ 8EFF00008F960000FF01FFFFFF00FFFFFF0000009246000093FF000093FF0000
+ 93FF00009578FFFFFF00FFFFFF00FFFFFF00FFFFFF0000009578000094FF0000
+ 94FF000094FF00009546FFFFFF00FFFFFF00FFFFFF0000009978000099FF0000
+ 99FF000099FF00009978FFFFFF00FFFFFF000000997800009AFF00009AFF0000
+ 9AFF00009978FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0000009F780000
+ 9FFF00009FFF00009FFF00009F7800009F780000A0FF0000A0FF0000A0FF0000
+ 9F78FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000
+ A6780000A5FF0000A5FF0000A5FF0000A6FF0000A6FF0000A6FF0000A678FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF000000AA780000ABFF0000ABFF0000ABFF0000ACFF0000AC78FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF000000B0780000B1FF0000B1FF0000B1FF0000B1FF0000B378FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000
+ B7780000B7FF0000B7FF0000B7FF0000B7FF0000B7FF0000B7FF0000B778FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000BD780000
+ BDFF0000BDFF0000BDFF0000BD780000BD780000BDFF0000BDFF0000BDFF0000
+ BD78FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000C1780000C3FF0000
+ C3FF0000C3FF0000C478FFFFFF00FFFFFF000000C4780000C3FF0000C3FF0000
+ C3FF0000C478FFFFFF00FFFFFF00FFFFFF000000C8460000C8FF0000C8FF0000
+ C9FF0000CA78FFFFFF00FFFFFF00FFFFFF00FFFFFF000000CA780000C9FF0000
+ C9FF0000C9FF0000C846FFFFFF00FFFFFF000000FF010000CE960000CEFF0000
+ CE78FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000CE780000
+ CFFF0000CF960000FF01FFFFFF00FFFFFF00FFFFFF000000FF010000D346FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000
+ D3460000FF01FFFFFF00FFFFFF00FFFFFF00FFFFFF00000000060000000E0000
+ 00160000001E000000250000002A0000002B00000029000000240000001D0000
+ 00150000000D00000004FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF005A5A503C5A5A50C766665DFF74746BFF7474
+ 6BFF74746BFF74746BFF74746BFF74746BFF74746BFF74746BFF74746BFF7474
+ 6BFF66665DFF5A5A50C75A5A503C5A5A50CCBFBFB8FFF4F4F1FFF6F6F4FFF6F6
+ F4FFF6F6F4FFF6F6F4FFF6F6F4FFF6F6F4FFF6F6F4FFF6F6F4FFF6F6F4FFF6F6
+ F4FFF4F4F1FFBFBFB9FF5A5A50CC626258FFE6E6E0FFE3E3DAFFE1E1D8FFE1E1
+ D8FFDDDDD4FFDDDDD4FFE1E1D8FFE1E1D8FFDDDDD4FFDDDDD4FFE1E1D8FFE1E1
+ D8FFE3E3DAFFE7E7E1FF64645AFF68685EFFDADAD0FFD9D9CFFFD9D9CFFFD5D5
+ CBFF7D7D75FF84847CFFD5D5CDFFD5D5CDFF84847CFF7D7D75FFD5D5CBFFD9D9
+ CFFFD9D9CFFFDADAD0FF6C6C62FF65655BFFD6D6CCFFD6D6CCFFD2D2C8FF7A7A
+ 73FF4D4D43FF4D4D43FF7F7F78FF7F7F78FF4D4D43FF4D4D43FF7A7A73FFD2D2
+ C8FFD6D6CCFFD6D6CCFF69695FFF65655BFFD2D2C8FFD2D2C8FFCECEC6FF7676
+ 6EFF48483EFF48483EFF48483EFF48483EFF48483EFF48483EFF76766EFFCECE
+ C6FFD2D2C8FFD2D2C8FF69695FFF64645AFFCECEC4FFCECEC4FFCECEC4FFCECE
+ C6FF7A7A73FF424238FF424238FF424238FF424238FF7A7A73FFCECEC6FFCECE
+ C4FFCECEC4FFCECEC4FF68685EFF64645AFFCBCBC1FFCBCBC1FFCBCBC1FFC9C9
+ BFFF77776FFF3D3D33FF3D3D33FF3D3D33FF3D3D33FF77776FFFC9C9BFFFCBCB
+ C1FFCBCBC1FFCBCBC1FF68685EFF64645AFFC7C7BDFFC7C7BDFFC4C4BCFF7373
+ 6BFF38382EFF38382EFF38382EFF38382EFF38382EFF38382EFF73736BFFC4C4
+ BCFFC7C7BDFFC7C7BDFF67675DFF636359FFC3C3B9FFC3C3B9FFC7C7BEFF8383
+ 7DFF323228FF323228FF8D8D86FF8D8D86FF323228FF323228FF83837DFFC7C7
+ BEFFC3C3B9FFC3C3B9FF67675DFF64645AFFBFBFB5FFC0C0B6FFC0C0B6FFC7C7
+ BFFF8D8D86FF969690FFC5C5BCFFC5C5BCFF969690FF8D8D86FFC7C7BFFFC0C0
+ B6FFC0C0B6FFBFBFB5FF67675DFF69695FFFB0B0A6FFBABAB0FFBCBCB2FFBCBC
+ B2FFC4C4BBFFC2C2B9FFBCBCB2FFBCBCB2FFC2C2B9FFC4C4BBFFBCBCB2FFBCBC
+ B2FFBABAB0FFB0B0A6FF6D6D63FF888881D694948AFF95958BFF95958BFF9595
+ 8BFF95958BFF95958BFF95958BFF95958BFF95958BFF95958BFF95958BFF9595
+ 8BFF95958BFF95958BFF8B8B84D6BABAB65CB7B7B3D8A6A6A0F9A1A199FAA1A1
+ 99FAA1A199FAA1A19AFAA1A19AFAA1A19AFAA1A19BFAA1A19BFAA2A29BFAA2A2
+ 9BFAA7A7A1F9BABAB6D9BCBCB85DFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF006D9CD4896A9AD2FB6697CFEEFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00709ED6DB6D9C
+ D4FF85B1DAFF5A91B9FF6093CBEAFFFFFF00FFFFFF00808080FF7E7E7EFF7C7C
+ 7CFF7A7A7AFF777777FF757575FF727272FF719ED4FF6F9ED6FF87B2DCFFABD3
+ E8FFA9D0E6FF5890B8FF598EC6EAFFFFFF00FFFFFF007D7D7DFF999999FF9999
+ 99FF9A9A9AFF9A9A9AFF9B9B9BFF9B9B9BFF6F9DD3FFAAD1E7FFABD1E7FF98C7
+ E1FF91C2DEFF568FB7FF5289C1EAFFFFFF00FFFFFF007A7A7AFF999999FF5291
+ 59FF999A99FF9B9B9BFF9C9C9CFF9C9C9CFF6C9AD0FFA7CEE5FF8FC1DFFF89BD
+ DCFF8BBDDCFF538DB6FF4B84BCEAFFFFFF00FFFFFF00777777FF9A9A9AFF3D8A
+ 45FF498A4FFF9C9C9CFF9D9D9DFF9D9D9DFF6696CCFFA2CBE3FF89BDDCFF83B9
+ DAFF84B9DAFF518BB5FF437EB6EA44944DFF42914BFF3F8D48FF3D8945FF5DA4
+ 65FF5AA061FF45834BFF9E9E9EFF9E9E9EFF6092C9FF9EC7E2FF83B8DAFF7DB4
+ D7FF7EB3D7FF4F89B4FF3B79B1EA41904AFF94D29FFF91D09AFF8DCD96FF89CB
+ 92FF84C88DFF519858FF417C46FF9F9F9FFF5A8EC4FF98C3E0FF7CB3D7FF74AF
+ D6FF5EC4EDFF4B88B3FF3473ABEA3E8B46FF8FCE99FF7DC687FF78C381FF73C0
+ 7CFF74C07CFF79C281FF49904FFF547F57FF5489BFFF94BFDDFF75ADD4FF63B8
+ E1FF4BD4FFFF428BB8FF2C6EA6EA3B8742FF89CB92FF84C88DFF80C688FF7BC3
+ 83FF77C17FFF478F4DFF3B743FFFA1A1A1FF4C84BAFF8DBBDBFF6EA8D1FF66A6
+ D1FF5FB4DFFF4785B1FF2569A1EA37823EFF347E3BFF317937FF2E7534FF4991
+ 50FF468F4CFF39733DFFA1A1A1FFA2A2A2FF457EB4FF88B7D9FF67A3CFFF619E
+ CCFF639FCCFF4583B1FF1F649CEAFFFFFF00FFFFFF00606060FFA0A0A0FF3D76
+ 41FF367139FFA2A2A2FFA2A2A2FFA3A3A3FF3D79B0FF82B3D7FF629FCCFF5A9A
+ C9FF5E9BCAFF4381AFFF196098EAFFFFFF00FFFFFF005C5C5CFFA1A1A1FF3C73
+ 40FFA0A1A1FFA3A3A3FFA3A3A3FFA4A4A4FF3674AAFF7DAFD4FF5B9AC9FF5495
+ C7FF5896C8FF4180AEFF135C94EAFFFFFF00FFFFFF00585858FFA2A2A2FFA2A2
+ A2FFA3A3A3FFA4A4A4FFA4A4A4FFA5A5A5FF2F6FA5FF78ABD2FF78ABD3FF73A7
+ D1FF69A0CDFF407FAEFF0F5991EA999999FF717171FF545454FF515151FF4F4F
+ 4FFF4C4C4CFF4A4A4AFF474747FF454545FF25679DFF3274A8FF3D7CAFFF4784
+ B5FF4E8ABAFF3E7EADFF0C578FEAFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF001D639B1619609839145D9562105A
+ 92880D5890A4135C92FC0C578FED00000000000000008C8C8C308C8C8CAF8C8C
+ 8CFF8C8C8CFF8C8C8CFF8C8C8CEF8C8C8C9F8C8C8C1000000000000000000000
+ 0000000000000000000000000000000000008C8C8C608C8C8CFF9A9A9AFFD4D3
+ D2FFE2E1DFFFE2E0DCFFCDC9C3FF939392FF8C8C8CEF8C8C8C30000000000000
+ 00000000000000000000000000008C8C8C308C8C8CFFB7B7B7FFFFFEFDFFFFFE
+ FCFFFFFDF9FFFFFDF9FFFFFEFCFFF8F2E8FFA29F9CFF8C8C8CDF8C8C8C100000
+ 00000000000000000000000000008C8C8CAF9A9A9AFFFFFEFDFFFFFCF8FFFFFB
+ F4FFFFF9EFFFFFF7EAFFFFF6E8FFFFFAF2FFF1E8DBFF939291FF8C8C8C700000
+ 00000000000000000000000000008C8C8CFFD4D3D2FFFFFCF9FFFFFBF4FFFFF9
+ EFFFFFF7EBFFFFF5E6FFFFF3E2FFFFF2DDFFFFF2DDFFB7B1A7FF8C8C8CBF0000
+ 00000000000000000000000000008C8C8CFFE2E0DDFFFFFBF4FFFFF9F0FFFFF7
+ EBFFFFF5E6FFFFF3E2FFFFF2DDFFFFF0D9FFFFEED4FFC6BCAEFF8C8C8CEF0000
+ 00000000000000000000000000008C8C8CFFE2DFDAFFFFF9F0FFFFF7EBFFFFF5
+ E7FFFFF4E2FFFFF2DDFFFFF0D9FFFFEED4FFFFECD0FFC6BBACFF8C8C8CCF0000
+ 00000000000000000000000000008C8C8CEFBEBCB7FFFFF7ECFFFFF5E7FFFFF4
+ E2FFFFF2DEFFFFF0D9FFFFEED5FFFFECD0FFFFEBCBFFA29E97FF8C8C8CAF0000
+ 00000000000000000000000000008C8C8C80939392FFF1E8DCFFFFF4E3FFFFF2
+ DEFFFFF0D9FFFFEED5FFFFECD0FFFFEBCCFFDBCCB5FF8C8C8CFF8C8C8C500000
+ 00000000000000000000000000008C8C8C108C8C8CCFA29F9CFFE9DFCFFFFFF0
+ DAFFFFEED5FFFFECD0FFFFEBCCFFDBCCB5FF939290FF7C7C7CFF818181CF8C8C
+ 8C10000000000000000000000000000000008C8C8C108C8C8CBF8C8C8CFFA29F
+ 9AFFBEB6ABFFB7B0A5FF9A9894FF8C8C8CFF606060FF3C3C3CFF616161FF8181
+ 81CF8C8C8C1000000000000000000000000000000000000000008C8C8C508C8C
+ 8C9F8C8C8CBF8C8C8CBF8C8C8C8F54545450020202EF161616FF3B3B3BFF6161
+ 61FF818181CF8C8C8C1000000000000000000000000000000000000000000000
+ 00000000000000000000000000000000000001010130020202EF151515FF3B3B
+ 3BFF616161FF818181CF8C8C8C10000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000001010130020202EF1515
+ 15FF3B3B3BFF606060FF808080CF000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000010101300202
+ 02EF151515FF3A3A3AFF606060FF000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000101
+ 0120020202CF141414FF393939CF
+ }
+ end
+ object MTrayIcon: TTrayIcon
+ PopUpMenu = TrayPopup
+ Icon.Data = {
+ EE130000000001000100281E000001002000D813000016000000280000002800
+ 00003C0000000100200000000000000000000000000000000000000000000000
+ 00000C11450100000000465B8800000000001A396F33091E6FFF081972FF0919
+ 72FF071872FF081871FF0C3790FF1577DAFF157ADCFF167ADFFF1778E1FF1776
+ DCFF1257B3FF0C2978FF0A1761FF0A145FFF0A1560FF091561FF091560FF0915
+ 65FF09176EFF09166FFF09166FFF08166FFF091670FF09176DFF081669FF0B16
+ 62FF0C1346FF0D1145FF0C1143FF0C1043FF0C1043FF0C0F42FF0C0F43FF0C10
+ 44FF00000000000000000000000000000000102B71AF071A74FF081A74FF0919
+ 74FF081974FF081973FF1159B9FF187BE2FF197CE3FF177BE6FF187BE6FF187C
+ E6FF197DE8FF1878E1FF135BBCFF0B226FFF0A135FFF0B1462FF0A1563FF0A14
+ 63FF091464FF09176FFF081772FF081773FF091673FF081772FF09166EFF0A17
+ 6EFF0B1351FF0D1144FF0C1144FF0C1045FF0C1045FF0D1045FF0D1044FF0C10
+ 45FF00000000000000000000000032486C35081B68F9091978FE081977FF0719
+ 76FF071875FF071B73FF176ED4FF1A7FE4FF1A7CE6FF197DE9FF197DE7FF177E
+ E6FF187BE9FF187BE8FF177DE7FF186CCEFF0B1D6CFF0A1563FF0A1563FF0A16
+ 66FF091462FF091464FF091773FF071773FF071772FF071772FF091772FF0916
+ 72FF0B1662FF0C1147FF0C1047FF0B1146FF0A1045FF0A0F46FF0C0F44FF0C10
+ 45FF0000000000000000838986001E326982081C73FF081A77FF081A79FF0718
+ 78FF081876FF071C76FF187BE0FF1A7EE4FF187FE7FF187DE8FF187EE9FF187D
+ E9FF177DE8FF197DE8FF187EE8FF157FE8FF1561C4FF081664FF0B1563FF0A15
+ 65FF091664FF0A1462FF081566FF071772FF071874FF071776FF081772FF0716
+ 72FF081771FF0B124EFF0C1147FF0C1046FF0B1048FF0A1047FF0C1045FF0B10
+ 46FF000000007A7E74003E558B0012266E910A1B78FF081A78FF091978FF0719
+ 75FF081875FF071B75FF1C79E5FF1C7FE9FF1C81ECFF197EEBFF1A7CEAFF1A7D
+ E9FF1A7DE8FF197DE7FF187BE8FF197CE7FF1F81F1FF0B1E71FF0A1562FF0B15
+ 64FF091562FF091465FF091462FF09156BFF081773FF071677FF081876FF0816
+ 75FF081776FF0B155BFF0D1049FF0C0F49FF0B1049FF0C0F49FF0D0F45FF0C0E
+ 45FF000000000000000066727711132871BC081A78FF081979FF091977FF0817
+ 73FF081877FF071876FF185DB9FF255075FF213E5CFF306393FF1B63ADFF1D7E
+ E6FF1D7EEBFF1D7DE9FF1A7CECFF1A7CEBFF1B82F0FF11328CFF0A1462FF0A16
+ 64FF0B1466FF0A1465FF0A1461FF081466FF071776FF081677FF091677FF0816
+ 74FF081678FF0B1566FF0C114EFF0D114FFF0C104BFF0D1049FF0C1046FF0C0F
+ 47FF0000000068627F0006286B050D2478DA091A79FF0A1A78FF0A176FFF0817
+ 77FF091877FF071B78FF1763C7FF1D62A8FF1F3B5BFF788E9EFF6B80BAFF1D32
+ 64FF2074D3FF1E7DEBFF1E7BEAFF1C7CEAFF197EEEFF1455BCFF091262FF0B15
+ 64FF0B1565FF0B1462FF0A1463FF091366FF081775FF091777FF081676FF0915
+ 72FF081677FF09166EFF0A1159FF0D145EFF0D104AFF0D0F48FF0C0F43FF0D0E
+ 49FF7D7D8331000000006E788A3A072073E8091C78FF0A1B75FF081971FF0719
+ 78FF082583FF1776DEFF1B82E4FF1F78D7FF1868C0FF1580E7FF136AC7FF3578
+ BFFF234A6BFF196ABBFF1880E4FF197EE7FF1681EAFF0869D5FF0A3790FF091A
+ 67FF08145FFF091361FF081462FF082077FF081B7AFF081779FF081877FF0717
+ 72FF081779FF091872FF091261FF0B1768FF0B114CFF0D1048FF0B0F48FF0A0F
+ 49FF7E7C861A7F7A832559687B54091F6BFF091D7AFF091B72FF091873FF081D
+ 7BFF1468CDFF2880DAFF134291FF0C3282FF0C3281FF174C9CFF1F88F2FF1C80
+ E9FF1C7EE4FF1B63B1FF1A75D5FF1A7FE6FF1880EBFF0868D6FF0860D2FF0754
+ C0FF0746ABFF083D9EFF0740A4FF0C54C1FF092485FF081877FF091976FF0916
+ 71FF091778FF0A1771FF091368FF0C166EFF0D114CFF0C0F49FF0B0F4BFF0B0F
+ 4BFF000000006779792B3F6193730B1C64FF0A1354FF0C1C65FF09186CFF0C3C
+ 9EFF247CD6FF0A2666FF0D3A8DFF093587FF0D337FFF0E162EFF123971FF1F7E
+ E5FF1D7CE6FF1E7FEAFF1968C4FF1B7EE7FF197FEEFF0868D7FF0762D3FF085B
+ C9FF0660D3FF0662D4FF0863D4FF0960D1FF0C3BA2FF081778FF0B1A72FF0814
+ 60FF07177AFF0A1671FF08146DFF0B166FFF0D114CFF0C104AFF0B104BFE0C0F
+ 49FF000000000000000021508B2D0B246EFF0C1950FF0B154AFF071664FF1355
+ B8FF1265D0FF0F72EBFF0F79F4FF0D6AD7FF0E4BA4FF0F2859FF091333FF164E
+ A3FF1C80E7FF1D7FE8FF1D82ECFF196ED1FF1A80EBFF0960CDFF075FCEFF0762
+ D6FF0663D8FF0763D5FF085DCDFF065DCFFF0D4CBCFF071779FF0D1A68FF0811
+ 58FF081778FF0A166EFF081573FF0B166DFF0C114BFF0A104AFF0B0F4CFF0E11
+ 42E16F768F57000000000E3174020C246DAD0B134AFF0C1449FF09165DFF0C52
+ BAFF1173ECFF0D75F0FF0C73F0FF0C73F3FF0E77EEFF0F64CDFF0A3F9CFF0E51
+ B8FF1B7CE9FF1B7FECFF1A7FEFFF1B73D8FF1674DEFF0767DAFF0664D8FF0663
+ D6FF085ACAFF0759CFFF0764D6FF0662DBFF0D50C3FF091975FF0D1450FF0812
+ 5EFF08187AFF091571FF061679FF0C1668FF0D104BFF0C104CFE0D104AFF1715
+ 3D40566A7C124C6C832954809C180F34835A0A1D66FB0B1649FF081250FF0B5A
+ C7FF0A5FD1FF086AE2FF086AE3FF096AE6FF0A6DEAFF0C71F1FF0C74F9FF0C6E
+ E8FF1C7EEFFF1C80EFFF1A7CE9FF1769D1FF166BD4FF085BCAFF085DCEFF075C
+ CEFF0660D5FF0761DAFF0661DBFF0666DCFF0F44A7FF0A1764FF0A1048FF0714
+ 6CFF07177BFF07167AFF08167CFF0C1562FF0C114CFE0B104DFF100F46D33A2E
+ 431171A1C30F5087B12899947E0112398439071C79F80B1B60FF091857FF085A
+ C8FF075DCCFF0764D6FF0764D5FF0664D7FF0665DBFF0768DDFF0769E6FF0764
+ D9FF1A7CE7FF1B80ECFF116CDCFF075ACFFF0863D9FF0860D6FF075FD5FF075F
+ D3FF0763D9FF0662DCFF0664DAFF0768DDFF113482FF0C134CFF081054FF0818
+ 79FF081779FF07167BFF091877FF0C1053FF0C114EFF0B0F4CFF1C173D920000
+ 000000000000497CAA143F7CA73225568E3C09247EF60A1F7CFF0B1757FF0739
+ 92FF0767D9FF0A62D4FF0665D6FF0666D8FF0764D8FF0663DBFF0763DCFF0865
+ DBFF126EDDFF116FE4FF065DD4FF0763DBFF075FD5FF065ED5FF0663DBFF0662
+ DBFF0763DDFF0763DBFF0664DAFF0D69DBFF0B1B5AFF0A1047FF08156FFF0717
+ 7AFF07177CFF08177CFF0C1563FF0B1150FF0A104FFF0D1148FF27182A2DFFFF
+ FF015C5651045682A52D3F7BA63A3C628959092073F9071B7FFF0A1A68FF0817
+ 58FF136BC7FF2071B6FF0C61C8FF0766DBFF0665DCFF0666DBFF0664DEFF0859
+ C7FF1668D2FF157AECFF0667E1FF0661D9FF0662DDFF0664E0FF0663DBFF0763
+ DCFF0663DBFF0763D8FF0669DEFF104EAAFF091146FF07125FFF071678FF0717
+ 7CFF07177FFF0A1670FF0A1152FF0B1150FE0A1050FF14113FC600000000FFFF
+ FF057F7875080000000000000000223065310A1D77F8091A7FFF0B1A6BFF0B13
+ 4CFF103483FF174791FF0A4EB1FF0664D8FF0865DDFF0865E1FF0664E0FF0B5A
+ D0FF1E5086FF174270FF2080D9FF086CE1FF085DD7FF075CD5FF0662DDFF0663
+ DCFF0764DEFF0766E0FF0F60CAFF0E2164FF08125AFF081577FF07167EFF0917
+ 7EFF0C166EFF0C1355FF0C1151FF0C0E4EFF0E104BFF19133631000000000000
+ 0000000000000000000000000000162B6B71071C7AFE081A7CFF0C1964FF0C13
+ 42FF093480FF0E4BA9FF0655C1FF0666DAFF0667DBFF0667DEFF0667DFFF075F
+ D2FF0E49A0FF1762A8FF16539FFF0C66D2FF0666DDFF0764DCFF0760D9FF0762
+ D9FF0B66D5FF0E4399FF0B1D66FF07146BFF07177BFF07167EFF08177FFF0A16
+ 66FF0A1250FF091050FF09104FFF0A104FFF0E1148BF3F365203000000000000
+ 000000000000000000003A456C03182971B9081B7BFF091A7CFF0C1557FF1013
+ 36FF131E28FF0A1D4AFF075CCCFF0765DBFF0766DDFF0768DDFF0767DFFF0D4E
+ A7FF0C4CB4FF0A43A8FF0B4CB2FF114599FF0758CBFF0762DCFF0663E0FF0E66
+ DAFF102D79FF071468FF08187CFF07187EFF07167EFF081778FF0C155AFF0A10
+ 4FFF0A1050FF0B0F4FFF0B104FFF0B0F4EFE17134076FFFF0000BDB0AE000000
+ 000000000000000000008185950D1A2A71DD0A1A7DFF0A197FFF0C165DFF0C12
+ 47FF091B5AFF0865DCFF0766DDFF0867DEFF0A64DCFF0665E1FF0864E0FF0D53
+ 9EFF0D213FFF14294FFF11315EFF074BACFF0763E0FF0764DFFF0D64D4FF0F26
+ 75FF071370FF08187FFF08177DFF08177EFF07187BFF0C1C62FF0A0F48FF0B11
+ 51FF0B114EFF0A104FFE0A0F50FF0E0F48F124152B2300000000000000000000
+ 000000000000000000006F80880E0F246BC5091B7FFF071980FF091A79FF0A14
+ 51FF0B1145FF072D84FF066CE5FF1163CEFF072082FF0856C8FF0664DEFF0765
+ DCFF0861D2FF075ECBFF0662D7FF0767E0FF0767DFFF0767E0FF0D3A92FF0819
+ 78FF07197EFF08187FFF07187FFF07177DFF07207EFF0C3F9EFF0B1353FF0B10
+ 50FF0A1050FF0A114FFE0A104EFF18123B8C0000000000000000000000000000
+ 0000000000000000000056627B021E2C6AA4071A7AFF081A81FF081981FF0819
+ 78FF09165DFF091157FF103DA1FF0A1E81FF07177DFF082888FF0862DFFF0767
+ E7FF0666E5FF0666E6FF0667E5FF0665E7FF086AE7FF0F55B7FF0A1B76FF0918
+ 81FF071881FF071780FF081780FF07167DFF08319AFF0C3EA1FF0B1353FF0C10
+ 50FF0B1150FE0C1051FF111246E33718180A0000000028182900000000000000
+ 00000000000094AD9900000000003F4265660A1D6EFD08187FFE081984FF0718
+ 84FF071881FF07197CFF08146AFF06187DFF071880FF091769FF0B216BFF0954
+ BFFF066DECFF066CE9FF066CEEFF0E6CE6FF113D90FF081568FF071880FF0718
+ 83FF071881FF08177FFF08177EFF061C81FF0855C9FF0C3289FF0B1253FF0A11
+ 50FE0A1151FF0B114FFB18143D510000000022142F0000000000000000000000
+ 00000000000000000000000000004640472F1B2861EE071873FF071878FF0718
+ 7BFE08197EFF091864FF071369FF07197DFF06197FFF091A79FF0A124EFF0A10
+ 47FF0C276FFF0F3685FF112C74FF0B1450FF07105AFF08187FFF071781FF0817
+ 83FF08187EFF07177FFF07177FFF0A2B8BFF0C3792FF0C1B62FE091152FF0A11
+ 52FF0A114FFF19123E8F000000002D2036000000000000000000000000000000
+ 000000000000000000001F293C0000000000282A4E3910195BAF0A186AFF0917
+ 73FF0A165FFF091154FE071676FF07177FFF071881FF07187FFF091765FF0A11
+ 4BFF0A1357FF08104EFF081053FF071469FF07187CFF061881FF071882FF0718
+ 78FF08177BFF081781FF091878FF0A1357FF0A104FFF0A1152FE0A1052FF0E11
+ 4AB414123F540000000000000000000000000000000000000000000000000000
+ 000000000000000000006E4938006E4B3C0000000000000000001D182E240E15
+ 3E960B1449EF061059FF06177EFF061880FF061880FF071881FF081879FF0A13
+ 55FF091158FF09187DFF071881FF071783FF071883FF081880FF07177BFF0816
+ 81FF061881FF071780FE0B176BFF0B1152FF0A1251FD0B114BFF17153AAE6047
+ 410F000000001F11230000000000000000000000000000000000000000000000
+ 000000000000000000006E493800704D3B02674034004F342C00000000000000
+ 000028252D270A1563FF071883FF061882FF071783FF071785FF08177FFF0916
+ 74FF0A1361FF091461FF08156CFF091570FF081576FF08167CFF071682FF0816
+ 83FF081784FF0A187CFF0D135BFF0F124CCE1313416917162F37221C35362A1C
+ 2A293D2428010000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 00000000000018235EEF071882FF061883FF081782FF081884FF071682FF0717
+ 7EFF081784FF061782FF071781FF081784FF071783FF081683FF071785FF0818
+ 84FE081880FF0C1760FD18164075221834070000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000004136
+ 4900000000002F2C52410E1B70FF071887FF081785FF071786FF071787FF0717
+ 84FF071780FF081683FF081784FF081685FF081686FF081686FF091687FF0A16
+ 80FF101868BC211C34240000000000000000000000004F433900000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000E5C00000000002027526B0D1E6FE30A1D77E50B1C74E50A1D75E50A1D
+ 77E50B1D76E50A1D79E50A1D76E50B1D74E50B1C76E50A1C77E50C1C6FE81C23
+ 558F17191F04000000004539390053433B004F43390000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000F800000000000000F000000000000000F000000000000000E00000000000
+ 0000E000000000000000E000000000000000E000000000000000E00000000000
+ 0000E000000000000000E000000000000000E000000000000000E00000000100
+ 0000F000000001000000F000000001000000F000000003000000F00000000300
+ 0000F000000007000000F000000007000000E00000000F000000E00000000F00
+ 0000E00000000F000000E00000001F000000F00000003F000000F00000003F00
+ 0000F8000000FF000000FE000001FF000000FF80000FFF000000FF80003FFF00
+ 0000FFC0007FFF000000FFE000FFFF000000
+ }
+ Visible = True
+ OnClick = NoTray
+ left = 528
+ top = 104
+ end
+ object TrayPopup: TPopupMenu
+ Images = Mufasa_Image_List
+ OnPopup = TrayPopupPopup
+ left = 528
+ top = 144
+ object TrayStop: TMenuItem
+ Action = ActionStopScript
+ Enabled = False
+ OnClick = ActionStopExecute
+ end
+ object TrayPause: TMenuItem
+ Action = ActionPauseScript
+ Enabled = False
+ OnClick = ActionPauseExecute
+ end
+ object TrayPlay: TMenuItem
+ Action = ActionRunScript
+ OnClick = ActionRunExecute
+ end
+ object TrayDivider: TMenuItem
+ Caption = '-'
+ end
+ object MenuItemShow: TMenuItem
+ Caption = 'Show'
+ OnClick = MenuItemShowClick
+ end
+ object MenuItemHide: TMenuItem
+ Caption = 'Hide'
+ OnClick = MenuItemHideClick
+ end
+ object MenuItemExit: TMenuItem
+ Action = ActionExit
+ Bitmap.Data = {
+ 36040000424D3604000000000000360000002800000010000000100000000100
+ 2000000000000004000064000000640000000000000000000000FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF001D63
+ 9B1619609839145D9562105A92880D5890A4135C92FC0C578FED999999FF7171
+ 71FF545454FF515151FF4F4F4FFF4C4C4CFF4A4A4AFF474747FF454545FF2567
+ 9DFF3274A8FF3D7CAFFF4784B5FF4E8ABAFF3E7EADFF0C578FEAFFFFFF00FFFF
+ FF00585858FFA2A2A2FFA2A2A2FFA3A3A3FFA4A4A4FFA4A4A4FFA5A5A5FF2F6F
+ A5FF78ABD2FF78ABD3FF73A7D1FF69A0CDFF407FAEFF0F5991EAFFFFFF00FFFF
+ FF005C5C5CFFA1A1A1FF3C7340FFA0A1A1FFA3A3A3FFA3A3A3FFA4A4A4FF3674
+ AAFF7DAFD4FF5B9AC9FF5495C7FF5896C8FF4180AEFF135C94EAFFFFFF00FFFF
+ FF00606060FFA0A0A0FF3D7641FF367139FFA2A2A2FFA2A2A2FFA3A3A3FF3D79
+ B0FF82B3D7FF629FCCFF5A9AC9FF5E9BCAFF4381AFFF196098EA37823EFF347E
+ 3BFF317937FF2E7534FF499150FF468F4CFF39733DFFA1A1A1FFA2A2A2FF457E
+ B4FF88B7D9FF67A3CFFF619ECCFF639FCCFF4583B1FF1F649CEA3B8742FF89CB
+ 92FF84C88DFF80C688FF7BC383FF77C17FFF478F4DFF3B743FFFA1A1A1FF4C84
+ BAFF8DBBDBFF6EA8D1FF66A6D1FF5FB4DFFF4785B1FF2569A1EA3E8B46FF8FCE
+ 99FF7DC687FF78C381FF73C07CFF74C07CFF79C281FF49904FFF547F57FF5489
+ BFFF94BFDDFF75ADD4FF63B8E1FF4BD4FFFF428BB8FF2C6EA6EA41904AFF94D2
+ 9FFF91D09AFF8DCD96FF89CB92FF84C88DFF519858FF417C46FF9F9F9FFF5A8E
+ C4FF98C3E0FF7CB3D7FF74AFD6FF5EC4EDFF4B88B3FF3473ABEA44944DFF4291
+ 4BFF3F8D48FF3D8945FF5DA465FF5AA061FF45834BFF9E9E9EFF9E9E9EFF6092
+ C9FF9EC7E2FF83B8DAFF7DB4D7FF7EB3D7FF4F89B4FF3B79B1EAFFFFFF00FFFF
+ FF00777777FF9A9A9AFF3D8A45FF498A4FFF9C9C9CFF9D9D9DFF9D9D9DFF6696
+ CCFFA2CBE3FF89BDDCFF83B9DAFF84B9DAFF518BB5FF437EB6EAFFFFFF00FFFF
+ FF007A7A7AFF999999FF529159FF999A99FF9B9B9BFF9C9C9CFF9C9C9CFF6C9A
+ D0FFA7CEE5FF8FC1DFFF89BDDCFF8BBDDCFF538DB6FF4B84BCEAFFFFFF00FFFF
+ FF007D7D7DFF999999FF999999FF9A9A9AFF9A9A9AFF9B9B9BFF9B9B9BFF6F9D
+ D3FFAAD1E7FFABD1E7FF98C7E1FF91C2DEFF568FB7FF5289C1EAFFFFFF00FFFF
+ FF00808080FF7E7E7EFF7C7C7CFF7A7A7AFF777777FF757575FF727272FF719E
+ D4FF6F9ED6FF87B2DCFFABD3E8FFA9D0E6FF5890B8FF598EC6EAFFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00709ED6DB6D9CD4FF85B1DAFF5A91B9FF6093CBEAFFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF006D9CD4896A9AD2FB6697CFEE
+ }
+ OnClick = ActionExitExecute
+ end
+ end
+ object TabPopup: TPopupMenu
+ Images = Mufasa_Image_List
+ left = 488
+ top = 104
+ object MenuItemTabAdd: TMenuItem
+ Action = ActionNewTab
+ Bitmap.Data = {
+ 36040000424D3604000000000000360000002800000010000000100000000100
+ 2000000000000004000064000000640000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 000004390000066D0099056900CC066D00990439000000000000000000090000
+ 00160000001A0000001A0000001A0000001A0000001A0000001A0000001A0000
+ 001A0000001A0B8000D12BDF1AFF0B8000D100000016000000090D0D0D671010
+ 1085101010851010108510101085101010851010108510101085101010850E62
+ 04CF0E7E02E70E7E02E73DE22CFF0E7E02E70E7E02E70B5F02B02727277BEBEB
+ EBFFE7E7E7FFE7E7E7FFE7E7E7FFE7E7E7FFE7E7E7FFE7E7E7FFE7E7E7FF3BA5
+ 2FFF52E741FF52E741FF52E741FF52E741FF52E741FF128905E532323276EAEA
+ EAFFE2E2E2FFE2E2E2FFE2E2E2FFE2E2E2FFE2E2E2FFE2E2E2FFE2E2E2FF66B9
+ 5BFF3CAB2DFF3CAB2DFF66EB55FF3CAB2DFF3EAD2FFF1C7A11C838383873EDED
+ EDFFE6E6E6FFE6E6E6FFE6E6E6FFE6E6E6FFE6E6E6FFE6E6E6FFE6E6E6FFE6E6
+ E6FFE6E6E6FF3EB12EFF75EE64FF3EB12EFFEDEDEDFF383838733E3E3E71F0F0
+ F0FFEBEBEBFFEBEBEBFFEBEBEBFFEBEBEBFFEBEBEBFFEBEBEBFFEBEBEBFFEBEB
+ EBFFEBEBEBFF6BC45FFF40B62FFF6BC45FFFF0F0F0FF3E3E3E714444446EF3F3
+ F3FFEFEFEFFFEFEFEFFFEFEFEFFFEFEFEFFFEFEFEFFFEFEFEFFFEFEFEFFFEFEF
+ EFFFEFEFEFFFEFEFEFFFEFEFEFFFEFEFEFFFF3F3F3FF4444446E4949496CF7F7
+ F7FFF4F4F4FFF4F4F4FFF4F4F4FFF4F4F4FFF4F4F4FFF4F4F4FFF4F4F4FFF4F4
+ F4FFF4F4F4FFF4F4F4FFF4F4F4FFF4F4F4FFF7F7F7FF4949496C4D4D4D6AFAFA
+ FAFFF8F8F8FFF8F8F8FFF8F8F8FFF8F8F8FFF8F8F8FFF8F8F8FFF8F8F8FFF8F8
+ F8FFF8F8F8FFF8F8F8FFF8F8F8FFF8F8F8FFFAFAFAFF4D4D4D6A51515168FDFD
+ FDFFFCFCFCFFFCFCFCFFFCFCFCFFFCFCFCFFFCFCFCFFFCFCFCFFFCFCFCFFFCFC
+ FCFFFCFCFCFFFCFCFCFFFCFCFCFFFCFCFCFFFDFDFDFF5151516855555567FFFF
+ FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+ FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5555556750505069BBBB
+ BBFFBABABAFFB8B8B8FFB6B6B6FFB3B3B3FFB0B0B0FFAEAEAEFFABABABFFA8A8
+ A8FFA6A6A6FFA3A3A3FFA0A0A0FF9E9E9EFF9C9C9CFF030303665252525BC6C6
+ C6D4DCDCDCFFD8D9D9FFD5D5D5FFD0D1D1FFCCCCCCFFC8C8C8FFC6C6C6FFC6C5
+ C5FFC9C5C5FFCDC6C6FFD1C7C7FFD7CBCBFFC4B8B8D45252525B555555225555
+ 5559555555665555556655555566555555665555556655555566555555665555
+ 5566555555665555556655555566555555665555555955555522FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00
+ }
+ OnClick = ActionNewTabExecute
+ end
+ object MenuItemTabClose: TMenuItem
+ Caption = 'Close tab'
+ Bitmap.Data = {
+ 36040000424D3604000000000000360000002800000010000000100000000100
+ 2000000000000004000064000000640000000000000000000000FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00000000090000
+ 00160000001A0000001A0000001A0000001A0000001A0000001A0000001A0000
+ 001A0000001A0000001A0000001A0000001A00000016000000090D0D0D671010
+ 1085101010851010108510101085101010851010108510101085101010850404
+ 5BCF020273E7020273E7020273E7020273E7020273E7020258B02727277BEBEB
+ EBFFE7E7E7FFE7E7E7FFE7E7E7FFE7E7E7FFE7E7E7FFE7E7E7FFE7E7E7FF2F2F
+ A7FF5E5EF7FF5E5EF7FF5E5EF7FF5E5EF7FF5E5EF7FF05058BE532323276EAEA
+ EAFFE2E2E2FFE2E2E2FFE2E2E2FFE2E2E2FFE2E2E2FFE2E2E2FFE2E2E2FF5B5B
+ BEFF2D2DB3FF2D2DB3FF2D2DB3FF2D2DB3FF2F2FB5FF111181C838383873EDED
+ EDFFE6E6E6FFE6E6E6FFE6E6E6FFE6E6E6FFE6E6E6FFE6E6E6FFE6E6E6FFE6E6
+ E6FFE6E6E6FFE6E6E6FFE6E6E6FFE6E6E6FFEDEDEDFF383838733E3E3E71F0F0
+ F0FFEBEBEBFFEBEBEBFFEBEBEBFFEBEBEBFFEBEBEBFFEBEBEBFFEBEBEBFFEBEB
+ EBFFEBEBEBFFEBEBEBFFEBEBEBFFEBEBEBFFF0F0F0FF3E3E3E714444446EF3F3
+ F3FFEFEFEFFFEFEFEFFFEFEFEFFFEFEFEFFFEFEFEFFFEFEFEFFFEFEFEFFFEFEF
+ EFFFEFEFEFFFEFEFEFFFEFEFEFFFEFEFEFFFF3F3F3FF4444446E4949496CF7F7
+ F7FFF4F4F4FFF4F4F4FFF4F4F4FFF4F4F4FFF4F4F4FFF4F4F4FFF4F4F4FFF4F4
+ F4FFF4F4F4FFF4F4F4FFF4F4F4FFF4F4F4FFF7F7F7FF4949496C4D4D4D6AFAFA
+ FAFFF8F8F8FFF8F8F8FFF8F8F8FFF8F8F8FFF8F8F8FFF8F8F8FFF8F8F8FFF8F8
+ F8FFF8F8F8FFF8F8F8FFF8F8F8FFF8F8F8FFFAFAFAFF4D4D4D6A51515168FDFD
+ FDFFFCFCFCFFFCFCFCFFFCFCFCFFFCFCFCFFFCFCFCFFFCFCFCFFFCFCFCFFFCFC
+ FCFFFCFCFCFFFCFCFCFFFCFCFCFFFCFCFCFFFDFDFDFF5151516855555567FFFF
+ FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+ FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5555556750505069BBBB
+ BBFFBABABAFFB8B8B8FFB6B6B6FFB3B3B3FFB0B0B0FFAEAEAEFFABABABFFA8A8
+ A8FFA6A6A6FFA3A3A3FFA0A0A0FF9E9E9EFF9C9C9CFF030303665252525BC6C6
+ C6D4DCDCDCFFD8D9D9FFD5D5D5FFD0D1D1FFCCCCCCFFC8C8C8FFC6C6C6FFC6C5
+ C5FFC9C5C5FFCDC6C6FFD1C7C7FFD7CBCBFFC4B8B8D45252525B555555225555
+ 5559555555665555556655555566555555665555556655555566555555665555
+ 5566555555665555556655555566555555665555555955555522FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00
+ }
+ ImageIndex = 16
+ OnClick = MenuItemTabCloseClick
+ end
+ object MenuItemTabCloseOthers: TMenuItem
+ Caption = 'Close Other Tabs'
+ OnClick = MenuItemTabCloseOthersClick
+ end
+ end
+ object ActionList: TActionList
+ Images = Mufasa_Image_List
+ left = 448
+ top = 104
+ object ActionTabNext: TAction
+ Caption = 'Next tab'
+ OnExecute = ActionTabNextExecute
+ ShortCut = 16393
+ end
+ object ActionTabLast: TAction
+ Caption = 'Last tab'
+ OnExecute = ActionTabLastExecute
+ ShortCut = 24585
+ end
+ object ActionCloseTab: TAction
+ Caption = '&Close Tab'
+ ImageIndex = 16
+ OnExecute = ActionCloseTabExecute
+ SecondaryShortCuts.Strings = (
+ 'Ctrl+F4'
+ )
+ ShortCut = 16471
+ end
+ object ActionNewTab: TAction
+ Caption = 'New &Tab'
+ ImageIndex = 15
+ OnExecute = ActionNewTabExecute
+ ShortCut = 16468
+ end
+ object ActionNewScript: TAction
+ Caption = '&New'
+ ImageIndex = 9
+ OnExecute = ActionNewExecute
+ ShortCut = 16462
+ end
+ object ActionOpenScript: TAction
+ Caption = '&Open'
+ ImageIndex = 10
+ OnExecute = ActionOpenExecute
+ ShortCut = 16463
+ end
+ object ActionSaveScript: TAction
+ Caption = '&Save'
+ ImageIndex = 14
+ OnExecute = ActionSaveExecute
+ ShortCut = 16467
+ end
+ object ActionSaveScriptAs: TAction
+ Caption = 'Save as..'
+ OnExecute = ActionSaveAsExecute
+ end
+ object ActionRunScript: TAction
+ Caption = '&Run'
+ OnExecute = ActionRunExecute
+ ShortCut = 120
+ end
+ object ActionPauseScript: TAction
+ Caption = '&Pause'
+ OnExecute = ActionPauseExecute
+ end
+ object ActionStopScript: TAction
+ Caption = '&Stop'
+ OnExecute = ActionStopExecute
+ end
+ object ActionSaveAll: TAction
+ Caption = 'Save All'
+ ImageIndex = 21
+ OnExecute = ActionSaveAllExecute
+ ShortCut = 24659
+ end
+ object ActionClearDebug: TAction
+ Caption = 'Clear'
+ ImageIndex = 4
+ OnExecute = ActionClearDebugExecute
+ end
+ object ActionFindStart: TAction
+ Caption = '&Find ...'
+ ImageIndex = 26
+ OnExecute = ActionFindstartExecute
+ ShortCut = 16454
+ end
+ object ActionCut: TAction
+ Caption = 'Cu&t'
+ ImageIndex = 3
+ OnExecute = ActionCutExecute
+ ShortCut = 16472
+ end
+ object ActionCopy: TAction
+ Caption = '&Copy'
+ ImageIndex = 22
+ OnExecute = ActionCopyExecute
+ ShortCut = 16451
+ end
+ object ActionPaste: TAction
+ Caption = '&Paste'
+ ImageIndex = 11
+ OnExecute = ActionPasteExecute
+ ShortCut = 16470
+ end
+ object ActionDelete: TAction
+ Caption = '&Delete'
+ ImageIndex = 23
+ OnExecute = ActionDeleteExecute
+ ShortCut = 46
+ end
+ object ActionSelectAll: TAction
+ Caption = '&Select All'
+ OnExecute = ActionSelectAllExecute
+ ShortCut = 16449
+ end
+ object ActionUndo: TAction
+ Caption = '&Undo'
+ ImageIndex = 18
+ OnExecute = ActionUndoExecute
+ ShortCut = 16474
+ end
+ object ActionRedo: TAction
+ Caption = '&Redo'
+ ImageIndex = 12
+ OnExecute = ActionRedoExecute
+ ShortCut = 16473
+ end
+ object ActionFindNext: TAction
+ Caption = 'Find &next'
+ OnExecute = ActionFindNextExecute
+ ShortCut = 114
+ end
+ object ActionReplace: TAction
+ Caption = 'R&eplace...'
+ OnExecute = ActionReplaceExecute
+ ShortCut = 16466
+ end
+ object ActionExit: TAction
+ Caption = '&Exit'
+ ImageIndex = 25
+ OnExecute = ActionExitExecute
+ end
+ end
+ object DebugTimer: TTimer
+ OnTimer = ProcessDebugStream
+ left = 568
+ top = 104
+ end
+ object ScriptPopup: TPopupMenu
+ Images = Mufasa_Image_List
+ OnPopup = ScriptPopupPopup
+ left = 568
+ top = 144
+ object PopupItemUndo: TMenuItem
+ Action = ActionUndo
+ Bitmap.Data = {
+ 36040000424D3604000000000000360000002800000010000000100000000100
+ 2000000000000004000064000000640000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 00000000000018A6C3691AA7C46900A0C4180000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 00000000000000A0C45D66DBEAB211A6C2AE0000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 00000000000000A0C42243C4DBFC43C5D8FE23A6C07F00000000000000000000
+ 00000000000000000000000000000000000000A0C4FF00000000000000000000
+ 000000000000000000000EAACBFE5DDAE9FE23A6C0EF00000000000000000000
+ 000000000000000000000000000000A0C4FF00A0C4FF00000000000000000000
+ 000000000000009EC11A02ACC8FF88E7F2FE11A2C2FF00000000000000000000
+ 00000000000005797D1100A0C4FF76EDFBFF00A0C4FF000000000000000000A0
+ C4300099B95000A0C4C96DE6F5FF76E2EFFF19A3C1FF00000000000000000000
+ 000005797D1100A0C4FF76EDFBFF76EDFBFF00A0C4FF00A0C4FF00A0C4FF00A0
+ C4FF01A9C4FF6EE1EEFF0FC9DFFF69E4F2FF1AA4C0F800000000000000000579
+ 7D1100A0C4FF76EDFBFF04C3DAFF76EDFBFF69EAF9FF69EAF9FF69EAF9FF69EA
+ F9FF05DDF7FF0AC8DFFF07C2D8FF6FDCEBFF1BA3BFF40000000005797E1100A0
+ C4FF79EDFBFF32E2F8FF2CDFF4FF04C0D6FF04C0D6FF04C0D6FF1DD2E8FF1DD2
+ E8FF1DD2E8FF0BC8DFFF6AE5F3FF1BABC5F815A0BCCB0000000000A0C4FFADF3
+ FBFF2FE0F6FF32E2F8FF32E2F7FF32E2F7FF2FE0F5FF29DBF1FF1DD2E8FF1DD2
+ E8FF1DD2E8FF36D9ECFF40CDE1FF16A1BDCA05797D0A0000000005797D0A00A0
+ C4FFADF3FBFF2FE0F6FF32E2F7FF29DBF1FF2FE0F5FF29DBF1FF16CDE3FF36D9
+ ECFF69E7F6FF41CEE3FE13A3C1E405797D320000000000000000000000000579
+ 7D1100A0C4FFADF3FBFF31E1F6FF20E3FAFF73ECFAFF6FEBFAFF6EE8F7FF6CE8
+ F7F814A1BCD414A3C1D505797D1C000000000000000000000000000000000000
+ 000005797D1100A0C4FFADF3FBFF25E4FBFF00A0C4FF00A0C4FF13A1BEE7159F
+ BBCF1BA1BBA4067A7C0B00000000000000000000000000000000000000000000
+ 00000000000005797D1100A0C4FFADF3FBFF00A0C4FF00000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 00000000000000000000009DBF1400A0C4FF00A0C4FF00000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 00000000000000000000000000000000000000A0C4FF00000000000000000000
+ 0000000000000000000000000000000000000000000000000000
+ }
+ OnClick = ActionUndoExecute
+ end
+ object PopupItemRedo: TMenuItem
+ Action = ActionRedo
+ Bitmap.Data = {
+ 36040000424D3604000000000000360000002800000010000000100000000100
+ 2000000000000004000064000000640000000000000000000000FFFFFF000000
+ 000000A0C4181AA7C46918A6C369000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000FFFFFF000000
+ 000011A6C2AE66DBEAB200A0C45D000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000FFFFFF0023A6
+ C07F43C5D8FE43C4DBFC00A0C422000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000FFFFFF0023A6
+ C0EF5DDAE9FE0EAACBFE000000000000000000000000000000000000000000A0
+ C4FF000000000000000000000000000000000000000000000000FFFFFF0011A2
+ C2FF88E7F2FE02ACC8FF009EC11A0000000000000000000000000000000000A0
+ C4FF00A0C4FF0000000000000000000000000000000000000000FFFFFF0019A3
+ C1FF76E2EFFF6DE6F5FF00A0C4C90099B95000A0C430000000000000000000A0
+ C4FF76EDFBFF00A0C4FF05797D11000000000000000000000000FFFFFF001AA4
+ C0F869E4F2FF0FC9DFFF6EE1EEFF01A9C4FF00A0C4FF00A0C4FF00A0C4FF00A0
+ C4FF76EDFBFF76EDFBFF00A0C4FF05797D110000000000000000FFFFFF001BA3
+ BFF46FDCEBFF07C2D8FF0AC8DFFF05DDF7FF69EAF9FF69EAF9FF69EAF9FF69EA
+ F9FF76EDFBFF04C3DAFF76EDFBFF00A0C4FF05797D1100000000FFFFFF0015A0
+ BCCB1BABC5F86AE5F3FF0BC8DFFF1DD2E8FF1DD2E8FF1DD2E8FF04C0D6FF04C0
+ D6FF04C0D6FF2CDFF4FF32E2F8FF79EDFBFF00A0C4FF05797E11FFFFFF000579
+ 7D0A16A1BDCA40CDE1FF36D9ECFF1DD2E8FF1DD2E8FF1DD2E8FF29DBF1FF2FE0
+ F5FF32E2F7FF32E2F7FF32E2F8FF2FE0F6FFADF3FBFF00A0C4FFFFFFFF000000
+ 000005797D3213A3C1E441CEE3FE69E7F6FF36D9ECFF16CDE3FF29DBF1FF2FE0
+ F5FF29DBF1FF32E2F7FF2FE0F6FFADF3FBFF00A0C4FF05797D0AFFFFFF000000
+ 00000000000005797D1C14A3C1D514A1BCD46CE8F7F86EE8F7FF6FEBFAFF73EC
+ FAFF20E3FAFF31E1F6FFADF3FBFF00A0C4FF05797D1100000000FFFFFF000000
+ 00000000000000000000067A7C0B1BA1BBA4159FBBCF13A1BEE700A0C4FF00A0
+ C4FF25E4FBFFADF3FBFF00A0C4FF05797D110000000000000000FFFFFF000000
+ 00000000000000000000000000000000000000000000000000000000000000A0
+ C4FFADF3FBFF00A0C4FF05797D11000000000000000000000000FFFFFF000000
+ 00000000000000000000000000000000000000000000000000000000000000A0
+ C4FF00A0C4FF009DBF1400000000000000000000000000000000FFFFFF000000
+ 00000000000000000000000000000000000000000000000000000000000000A0
+ C4FF000000000000000000000000000000000000000000000000
+ }
+ OnClick = ActionRedoExecute
+ end
+ object PopupItemDivider1: TMenuItem
+ Caption = '-'
+ end
+ object PopupItemCut: TMenuItem
+ Action = ActionCut
+ Bitmap.Data = {
+ 36040000424D3604000000000000360000002800000010000000100000000100
+ 2000000000000004000064000000640000000000000000000000FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00020D8C0A1C27A69F353F
+ C9F7222DAFB9030D8C1CFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00050F8D1F06108E26010B8A03FFFFFF00121C9B70404BD9FF2C35
+ BFDD3D47D1FF1D27A9A4FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF000F199763323DC7F83741CFFF1F29ABB0000A8618232DB4AF3540CCFD0009
+ 85181C27A895343EC5F8040E8C14FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF002F3ABDDE353FC9E52530B3C23F4ADDFF1F2AACC22430B2CB323CC6F2000A
+ 8603111B9D773741C8FF08128E20FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00323CC3EC232EADAFFFFFFF001A25A8994250D2FFCBA375FE414FD6FF1621
+ A39D2F39C0D42E38BEDF020D8B0AFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF001D28A99C3B46CCFF0812903A071190533B48D4FFDBBD9CFFEECCA6FF404C
+ DEFF3A43D1FF0F199869FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00030D8C1F2C35B9D73C46CFFF333ECAF23F4CD7FFD8BC9AFFF6EAE1FFBB92
+ 5ABF9462183B91611A01FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00030D8C1F1B26A7992A34BACC111C9D89BB9869CCF0E0D0FFB791
+ 5FC58F5D140BFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00000B8802FFFFFF00B48E5A90F6EADDFFE1CD
+ B4FFB18D5DBFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00B38C5789F1E2D4FFCEB2
+ 8EF4F5EBE0FFA67F4A9DFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00B1895384EEDFCEFF9766
+ 2065C2A37CDAE9D8C5FDA9824E7BFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00AF87507CE7D5C1FF9565
+ 1F2B8F5C121BC5A783E7D5BC9DE1B5936462FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00AC834B75DEC9AFFF9564
+ 1D1FFFFFFF0092601726C3A47CEBB59063CBFFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00AA81476FD6BD9FF79361
+ 1910FFFFFF00FFFFFF009666202CA9804BCBFFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00A87D4269CCB08BE0915D
+ 1409FFFFFF00FFFFFF00FFFFFF0092601706FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF009A6B2731AA7E43A19260
+ 1805FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00
+ }
+ OnClick = ActionCutExecute
+ end
+ object PopupItemCopy: TMenuItem
+ Action = ActionCopy
+ Bitmap.Data = {
+ 36040000424D3604000000000000360000002800000010000000100000000100
+ 2000000000000004000064000000640000000000000000000000FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00C57342C1C67545E6C87545FEC775
+ 45F3C87545F3C77545F3C77545F3C87546F4C57444E8CA7F53F1FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00C77949EDFCF3ECFFFAF1E8FFFAF0
+ E7FFFBF1E9FFFBF2EAFFFBF2EAFFFBF2EBFFFDF4EEFFCA8054F9FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00CF8253FFEFF1E7FFFFE9D9FFFFEA
+ DBFFFFE9D9FFFFE7D7FFFFE5D2FFFFE2CBFFEFF2E8FFCE8156FFFFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00CC8352FBFBF5EEFFFFE9D9FFFFEA
+ DBFFFFE9D9FFFFE7D7FFFFE5D2FFFFE2CBFFFBF6EFFFCC8355FEC7794AB9C879
+ 4BCEC87545DDC77545D4C87545D4C77545D4CA8452FFFFF7F1FFFFE9D9FFFFEA
+ DBFFFFE9D9FFFFE7D7FFFFE5D2FFFFE2CBFFFFF7F1FFCB8555FEC87C4ED3FCF3
+ ECDEFAF1E8DEFAF0E7DEFBF1E9DEFBF2EADEE4BA91FFFFF7F0FFFFE7D5FFFDE7
+ D6FFFDE6D4FFFCE4D0FFFBE3CBFFFADCC2FFFEF3E8FFCC8656FECF8253DEEFF1
+ E7DEFFE9D9DEFFEADBDEFFE9D9DEFFE7D7DEE4BB91FFFFF7F2FFFEE7D5FFFEE7
+ D5FFFDE5D1FFFAE0CAFFF9DEC4FFF7D9BCFFFDF2E7FFCC8757FECC8352DBFBF5
+ EEDEFFE9D9DEFFEADBDEFFE9D9DEFFE7D7DEE4BB92FFFEF7F1FFFCE5D2FFFCE4
+ D1FFFBE2CCFFF9DDC4FFF6D7BBFFF3D1AFFFFAEFE4FFCC8758FECA8452DBFFF7
+ F1DEFFE9D9DEFFEADBDEFFE9D9DEFFE7D7DEE4BB92FFFEF6F0FFFCE2CDFFFCE3
+ CDFFFADFC8FFF7D9BCFFF5E9DDFFFAF3EBFFFBF8F3FFCA8353FECB8553DBFFF7
+ F0DEFFE7D5DEFDE7D6DEFDE6D4DEFCE4D0DEE4BB93FFFEF5EDFFFCDEC5FFFBE0
+ C7FFF9DCC2FFF5D3B4FFFEF9F3FFFAE2C4FFECC193FFC37D4893CB8654DBFFF7
+ F2DEFEE7D5DEFEE7D5DEFDE5D1DEFAE0CADEE5BE96FFFFFFFEFFFDF3E9FFFDF3
+ EAFFFCF2E8FFFAEFE3FFFAF2E7FFEABB88FFCF8555B3B4693D0CCB8655DBFEF7
+ F1DEFCE5D2DEFCE4D1DEFBE2CCDEF9DDC4DEEAC39DFFE6BF96FFE4BB92FFE4BB
+ 92FFD1A06CF5D09E6DF6CC965FDAC479427EB2673C09FFFFFF00CB8655DBFEF6
+ F0DEFCE2CDDEFCE3CDDEFADFC8DEF7D9BCDEF5E9DDDEFAF3EBDEFBF8F3DECD95
+ 65DCFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00CB8656DAFEF5
+ EDDEFCDEC5DEFBE0C7DEF9DCC2DEF5D3B4DEFEF9F3DEFAE2C4DEECC193DEC37D
+ 4880FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00CA8554D0FFFF
+ FFDBFDF3E9DEFDF3EADEFCF2E8DEFAEFE3DEFAF2E7DEEABB88DECF85559CB469
+ 3D0AFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00C77947AACC86
+ 55CECC8857DECB8856DBCC8856DBCB8757DBCA8350D0C479426EB2673C08FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00
+ }
+ OnClick = ActionCopyExecute
+ end
+ object PopupItemPaste: TMenuItem
+ Action = ActionPaste
+ Bitmap.Data = {
+ 36040000424D3604000000000000360000002800000010000000100000000100
+ 2000000000000004000064000000640000000000000000000000FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF005E5E5E025B5B5B775858588A5555558A5252
+ 528A4F4F4F8A4C4C4C8A4A4A4A8A4848488A4646468A444444662063984A2063
+ 98CF206398FF206398FF206398FF246395FF587388FFF7F7F7FFF0F0F0FFF0F0
+ F0FFF0F0F0FFF0F0F0FFF0F0F0FFF0F0F0FFF3F3F3FA46464684206398C262A5
+ D7FF65A8DAFF64A6D9FF62A4D8FF629FD1FF758EA4FFEFEFEFFFE7E7E7FFE7E7
+ E7FFE7E7E7FFE7E7E7FFE6E6E6FFE6E6E6FFECECECFA49494984206398FF68AB
+ DCFF488ECFFF468BCEFF4387CDFF4484C6FF6885A1FFF0F0F0FFB4B4B4FFB4B4
+ B4FFB4B4B4FFB4B4B4FFB4B4B4FFB3B3B3FFEDEDEDFA4C4C4C84206398FF69AE
+ DCFF4A93D1FF488FD0FF468BCEFF4788C7FF6C88A3FFF0F0F0FFE8E8E8FFE8E8
+ E8FFE7E7E7FFE7E7E7FFE7E7E7FFE7E7E7FFEDEDEDFA4F4F4F84206398FF6BB1
+ DEFF4D97D3FF4B93D2FF488FD0FF4A8CC9FF6F8BA5FFF1F1F1FFB6B6B6FFB5B5
+ B5FFB5B5B5FFB4B4B4FFB4B4B4FFB4B4B4FFEDEDEDFA53535384206398FF6DB3
+ DFFF509CD5FF4E98D3FF4B94D1FF4C91CBFF708EA7FFF1F1F1FFE9E9E9FFE9E9
+ E9FFE8E8E8FFE8E8E8FFE8E8E8FFE7E7E7FFEDEDEDFA56565684206398FF70B5
+ E0FF529FD7FF509CD6FF4E98D4FF4F95CDFF7391AAFFF1F1F1FFB7B7B7FFB6B6
+ B6FFB6B6B6FFB6B6B6FFB5B5B5FFB5B5B5FFEEEEEEFA5A5A5A84206398FF73B7
+ E1FF57A3D7FF53A0D7FF509DD5FF5299CFFF7594ACFFF8F8F8FFF2F2F2FFF2F2
+ F2FFF2F2F2FFF2F2F2FFF2F2F2FFF1F1F1FFF4F4F4FA5E5E5E84206398FF76B9
+ E2FF5CA7D9FF58A4D8FF53A0D7FF539ED5FF618BA9FF6488A1FF6487A1FF6386
+ A0FF69879FFF4A6881FF6A6A6A8A6868688A6565658A62626263206398FF7ABB
+ E3FF61AADBFF5AA5D9FF53A0D7FF529FD7FF529FD7FF529FD7FF529FD7FF529F
+ D7FF62A3D8FF206398FFFFFFFF00FFFFFF00FFFFFF00FFFFFF00206398FF7CBD
+ E4FF65AEDDFF62ABDCFF5EA8DAFF5CA7D9FF5CA7D9FF5CA7D9FF5CA7D9FF529F
+ D7FF62A3D8FF206398FFFFFFFF00FFFFFF00FFFFFF00FFFFFF00206398FF7FBF
+ E4FF69B2DEFF4A9BDAFF4497DCFF4396DCFF4296DCFF4295DCFF4195DBFF519E
+ D6FF6CB2DEFF206398FFFFFFFF00FFFFFF00FFFFFF00FFFFFF00206398E071B3
+ DBFE7EBFE4FF4E9DDFFFB5EEFDFF75D4F0FF75D4F0FFB5EEFDFF4B9BDEFF6EB4
+ E0FF6DB3DFF9206398F3FFFFFF00FFFFFF00FFFFFF00FFFFFF00206398322063
+ 98B2206398FF3775A4FFB6EFFEFF80DBF3FF80DBF3FFB6EFFEFF2E6EA1FF2063
+ 98FF206398A520639853FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF002063982A206398FF206398FF206398FF206398FF206398FF206398F0FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00
+ }
+ OnClick = ActionPasteExecute
+ end
+ object PopupItemDelete: TMenuItem
+ Action = ActionDelete
+ Bitmap.Data = {
+ 36040000424D3604000000000000360000002800000010000000100000000100
+ 2000000000000004000064000000640000000000000000000000FFFFFF00FFFF
+ FF00000000060000000E000000160000001E000000250000002A0000002B0000
+ 0029000000240000001D000000150000000D00000004FFFFFF00FFFFFF00FFFF
+ FF000000FF010000D346FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF000000D3460000FF01FFFFFF00FFFFFF00FFFFFF000000
+ FF010000CE960000CEFF0000CE78FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF000000CE780000CFFF0000CF960000FF01FFFFFF00FFFFFF000000
+ C8460000C8FF0000C8FF0000C9FF0000CA78FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF000000CA780000C9FF0000C9FF0000C9FF0000C846FFFFFF00FFFFFF00FFFF
+ FF000000C1780000C3FF0000C3FF0000C3FF0000C478FFFFFF00FFFFFF000000
+ C4780000C3FF0000C3FF0000C3FF0000C478FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF000000BD780000BDFF0000BDFF0000BDFF0000BD780000BD780000
+ BDFF0000BDFF0000BDFF0000BD78FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF000000B7780000B7FF0000B7FF0000B7FF0000B7FF0000
+ B7FF0000B7FF0000B778FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF000000B0780000B1FF0000B1FF0000B1FF0000
+ B1FF0000B378FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF000000AA780000ABFF0000ABFF0000ABFF0000
+ ACFF0000AC78FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF000000A6780000A5FF0000A5FF0000A5FF0000A6FF0000
+ A6FF0000A6FF0000A678FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF0000009F7800009FFF00009FFF00009FFF00009F7800009F780000
+ A0FF0000A0FF0000A0FF00009F78FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF0000009978000099FF000099FF000099FF00009978FFFFFF00FFFFFF000000
+ 997800009AFF00009AFF00009AFF00009978FFFFFF00FFFFFF00FFFFFF000000
+ 9246000093FF000093FF000093FF00009578FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF0000009578000094FF000094FF000094FF00009546FFFFFF00FFFFFF000000
+ FF0100008D9600008DFF00008E78FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF0000008E7800008EFF00008F960000FF01FFFFFF00FFFFFF00FFFF
+ FF000000FF0100008746FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00000087460000FF01FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00
+ }
+ OnClick = ActionDeleteExecute
+ end
+ object PopupItemDivider2: TMenuItem
+ Caption = '-'
+ end
+ object PopupItemSelectAll: TMenuItem
+ Action = ActionSelectAll
+ OnClick = ActionSelectAllExecute
+ end
+ object PopupItemDivider3: TMenuItem
+ Caption = '-'
+ end
+ object PopupItemFind: TMenuItem
+ Action = ActionFindNext
+ OnClick = ActionFindNextExecute
+ end
+ object PopupItemReplace: TMenuItem
+ Action = ActionReplace
+ Caption = 'Replace'
+ OnClick = ActionReplaceExecute
+ end
+ end
+ object dlgReplace: TReplaceDialog
+ Options = [frDown, frFindNext, frHideUpDown]
+ OnFind = dlgReplaceFind
+ OnReplace = dlgReplaceReplace
+ left = 608
+ top = 104
+ end
+ object UpdateTimer: TTimer
+ Interval = 10000
+ OnTimer = UpdateTimerCheck
+ left = 608
+ top = 144
+ end
+end
diff --git a/branches/script-component/Projects/SAMufasaGUI/testunit.lrs b/branches/script-component/Projects/SAMufasaGUI/testunit.lrs
new file mode 100644
index 0000000..6839c02
--- /dev/null
+++ b/branches/script-component/Projects/SAMufasaGUI/testunit.lrs
@@ -0,0 +1,3191 @@
+{ This is an automatically generated lazarus resource file }
+
+LazarusResources.Add('TForm1','FORMDATA',[
+ 'TPF0'#6'TForm1'#5'Form1'#4'Left'#3'?'#5#6'Height'#3'-'#2#3'Top'#3#181#0#5'Wi'
+ +'dth'#3#222#2#13'ActiveControl'#7#11'ScriptPanel'#7'Caption'#6#16'THA FUKING'
+ +' SIMBA'#12'ClientHeight'#3#20#2#11'ClientWidth'#3#222#2#10'KeyPreview'#9#4
+ +'Menu'#7#8'MainMenu'#7'OnClose'#7#9'FormClose'#8'OnCreate'#7#10'FormCreate'#9
+ +'OnDestroy'#7#11'FormDestroy'#10'OnShortCut'#7#13'FormShortCuts'#8'Position'
+ +#7#14'poScreenCenter'#10'LCLVersion'#6#6'0.9.29'#7'Visible'#9#0#8'TToolBar'#8
+ +'ToolBar1'#4'Left'#2#0#6'Height'#2#24#3'Top'#2#0#5'Width'#3#222#2#7'Caption'
+ +#6#8'ToolBar1'#6'Images'#7#17'Mufasa_Image_List'#14'ParentShowHint'#8#8'Show'
+ +'Hint'#9#8'TabOrder'#2#0#0#11'TToolButton'#6'TB_Run'#4'Left'#3#168#0#4'Hint'
+ +#6#3'Run'#3'Top'#2#2#6'Action'#7#15'ActionRunScript'#10'ImageIndex'#2#6#0#0
+ +#11'TToolButton'#8'TB_Pause'#4'Left'#3#191#0#4'Hint'#6#5'Pause'#3'Top'#2#2#6
+ +'Action'#7#17'ActionPauseScript'#7'Enabled'#8#10'ImageIndex'#2#5#0#0#11'TToo'
+ +'lButton'#7'TB_Stop'#4'Left'#3#214#0#4'Hint'#6#4'Stop'#3'Top'#2#2#6'Action'#7
+ +#16'ActionStopScript'#7'Enabled'#8#10'ImageIndex'#2#7#0#0#11'TToolButton'#11
+ +'ToolButton1'#4'Left'#3#237#0#3'Top'#2#2#5'Width'#2#3#7'Caption'#6#11'ToolBu'
+ +'tton1'#5'Style'#7#10'tbsDivider'#0#0#11'TToolButton'#9'TB_NewTab'#4'Left'#3
+ +#240#0#4'Hint'#6#7'Add tab'#3'Top'#2#2#6'Action'#7#12'ActionNewTab'#0#0#11'T'
+ +'ToolButton'#11'TB_CloseTab'#4'Left'#3#7#1#4'Hint'#6#9'Close tab'#3'Top'#2#2
+ +#6'Action'#7#14'ActionCloseTab'#0#0#11'TToolButton'#11'ToolButton4'#4'Left'#3
+ +#30#1#3'Top'#2#2#5'Width'#2#3#7'Caption'#6#11'ToolButton4'#5'Style'#7#10'tbs'
+ +'Divider'#0#0#11'TToolButton'#13'TB_ClearDebug'#4'Left'#3'!'#1#4'Hint'#6#15
+ +'Clear debug box'#3'Top'#2#2#6'Action'#7#16'ActionClearDebug'#0#0#11'TToolBu'
+ +'tton'#13'TB_PickColour'#4'Left'#3'8'#1#4'Hint'#6#12'Pick a color'#3'Top'#2#2
+ +#7'Caption'#6#13'TB_PickColour'#10'ImageIndex'#2#0#7'OnClick'#7#15'ButtonPic'
+ +'kClick'#0#0#11'TToolButton'#15'TB_SelectClient'#4'Left'#3'O'#1#4'Hint'#6#15
+ +'Select a client'#3'Top'#2#2#7'Caption'#6#15'TB_SelectClient'#10'ImageIndex'
+ +#2#2#11'OnMouseDown'#7#18'ButtonSelectorDown'#0#0#11'TToolButton'#11'ToolBut'
+ +'ton8'#4'Left'#3'f'#1#3'Top'#2#2#5'Width'#2#3#7'Caption'#6#11'ToolButton8'#5
+ +'Style'#7#10'tbsDivider'#0#0#11'TToolButton'#16'TB_ReloadPlugins'#4'Left'#3
+ +'i'#1#4'Hint'#6#14'Reload plugins'#3'Top'#2#2#7'Caption'#6#16'TB_ReloadPlugi'
+ +'ns'#7'Enabled'#8#10'ImageIndex'#2#13#0#0#11'TToolButton'#7'TB_Tray'#4'Left'
+ +#3#128#1#4'Hint'#6#16'Minimize to tray'#3'Top'#2#2#7'Caption'#6#7'TB_Tray'#10
+ +'ImageIndex'#2#17#7'OnClick'#7#15'ButtonTrayClick'#0#0#11'TToolButton'#6'TB_'
+ +'New'#4'Left'#2#1#4'Hint'#6#3'New'#3'Top'#2#2#6'Action'#7#15'ActionNewScript'
+ +#14'ParentShowHint'#8#8'ShowHint'#9#0#0#11'TToolButton'#11'ToolButton2'#4'Le'
+ +'ft'#2']'#3'Top'#2#2#5'Width'#2#3#7'Caption'#6#11'ToolButton2'#5'Style'#7#10
+ +'tbsDivider'#0#0#11'TToolButton'#7'TB_Open'#4'Left'#2#24#4'Hint'#6#4'Open'#3
+ +'Top'#2#2#6'Action'#7#16'ActionOpenScript'#14'ParentShowHint'#8#8'ShowHint'#9
+ +#0#0#11'TToolButton'#7'TB_Save'#4'Left'#2'/'#4'Hint'#6#4'Save'#3'Top'#2#2#6
+ +'Action'#7#16'ActionSaveScript'#0#0#11'TToolButton'#10'TB_SaveAll'#4'Left'#2
+ +'F'#4'Hint'#6#8'Save all'#3'Top'#2#2#6'Action'#7#13'ActionSaveAll'#7'Enabled'
+ +#8#0#0#11'TToolButton'#11'ToolButton3'#4'Left'#3#151#1#3'Top'#2#2#5'Width'#2
+ +#3#7'Caption'#6#11'ToolButton3'#5'Style'#7#10'tbsDivider'#0#0#11'TToolButton'
+ +#9'TT_Update'#4'Left'#3#154#1#4'Hint'#6#25'A new update is available'#3'Top'
+ +#2#2#7'Caption'#6#9'TT_Update'#10'ImageIndex'#2#1#7'Visible'#8#7'OnClick'#7
+ +#14'TT_UpdateClick'#0#0#11'TToolButton'#6'TT_Cut'#4'Left'#2'`'#3'Top'#2#2#7
+ +'Caption'#6#4'Cu&t'#10'ImageIndex'#2#3#7'OnClick'#7#16'ActionCutExecute'#0#0
+ +#11'TToolButton'#7'TT_Copy'#4'Left'#2'w'#3'Top'#2#2#7'Caption'#6#5'&Copy'#10
+ +'ImageIndex'#2#22#7'OnClick'#7#17'ActionCopyExecute'#0#0#11'TToolButton'#8'T'
+ +'T_Paste'#4'Left'#3#142#0#3'Top'#2#2#6'Action'#7#11'ActionPaste'#0#0#11'TToo'
+ +'lButton'#11'ToolButton9'#4'Left'#3#165#0#3'Top'#2#2#5'Width'#2#3#7'Caption'
+ +#6#11'ToolButton9'#5'Style'#7#10'tbsDivider'#0#0#0#10'TStatusBar'#9'StatusBa'
+ +'r'#4'Left'#2#0#6'Height'#2#21#3'Top'#3#255#1#5'Width'#3#222#2#6'Panels'#14#1
+ +#5'Width'#2'<'#0#1#4'Text'#6#8'Untitled'#5'Width'#3#150#0#0#1#5'Width'#2'2'#0
+ +#0#11'SimplePanel'#8#0#0#6'TPanel'#9'PanelMemo'#4'Left'#2#0#6'Height'#3#154#0
+ +#3'Top'#3'e'#1#5'Width'#3#222#2#5'Align'#7#8'alBottom'#12'ClientHeight'#3#154
+ +#0#11'ClientWidth'#3#222#2#8'TabOrder'#2#2#0#5'TMemo'#5'Memo1'#4'Left'#2#1#6
+ +'Height'#3#152#0#3'Top'#2#1#5'Width'#3#220#2#5'Align'#7#8'alClient'#10'Scrol'
+ +'lBars'#7#10'ssAutoBoth'#8'TabOrder'#2#0#0#0#0#9'TSplitter'#19'SplitterMemoS'
+ +'ynedit'#6'Cursor'#7#8'crVSplit'#4'Left'#2#0#6'Height'#2#5#3'Top'#3'`'#1#5'W'
+ +'idth'#3#222#2#5'Align'#7#8'alBottom'#12'ResizeAnchor'#7#8'akBottom'#0#0#6'T'
+ +'Panel'#11'ScriptPanel'#4'Left'#2#0#6'Height'#3'H'#1#3'Top'#2#24#5'Width'#3
+ +#222#2#5'Align'#7#8'alClient'#10'BevelOuter'#7#6'bvNone'#12'ClientHeight'#3
+ +'H'#1#11'ClientWidth'#3#222#2#8'DockSite'#9#8'TabOrder'#2#4#10'OnDockDrop'#7
+ ,#19'ScriptPanelDockDrop'#10'OnDockOver'#7#19'ScriptPanelDockOver'#0#12'TPage'
+ +'Control'#12'PageControl1'#4'Left'#3#155#0#6'Height'#3'%'#1#3'Top'#2#0#5'Wid'
+ +'th'#3'C'#2#5'Align'#7#8'alClient'#6'Images'#7#17'Mufasa_Image_List'#9'Popup'
+ +'Menu'#7#8'TabPopup'#8'TabOrder'#2#0#8'OnChange'#7#18'PageControl1Change'#10
+ +'OnChanging'#7#20'PageControl1Changing'#14'OnContextPopup'#7#24'PageControl1'
+ +'ContextPopup'#10'OnDragDrop'#7#20'PageControl1DragDrop'#10'OnDragOver'#7#20
+ +'PageControl1DragOver'#11'OnMouseDown'#7#21'PageControl1MouseDown'#9'OnMouse'
+ +'Up'#7#19'PageControl1MouseUp'#13'OnPageChanged'#7#18'PageControl1Change'#0#0
+ +#6'TPanel'#11'SearchPanel'#4'Left'#2#0#6'Height'#2'#'#3'Top'#3'%'#1#5'Width'
+ +#3#222#2#5'Align'#7#8'alBottom'#10'BevelOuter'#7#7'bvSpace'#12'ClientHeight'
+ +#2'#'#11'ClientWidth'#3#222#2#8'TabOrder'#2#1#7'Visible'#8#0#12'TSpeedButton'
+ +#17'SpeedButtonSearch'#4'Left'#2' '#6'Height'#2#19#3'Top'#2#7#5'Width'#2#16#5
+ +'Color'#7#9'clBtnFace'#4'Flat'#9#10'Glyph.Data'#10':'#9#0#0'6'#9#0#0'BM6'#9#0
+ +#0#0#0#0#0'6'#0#0#0'('#0#0#0#24#0#0#0#24#0#0#0#1#0' '#0#0#0#0#0#0#9#0#0'd'#0
+ +#0#0'd'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#255#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#255#0#0#0
+ +#255#0#0#0#255#0#0#0#0#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#255#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#255#0
+ +#0#0#255#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#0#0#0#0
+ +#255#0#0#0#255#0#0#0#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#255#0#0#0#255#0#0#0#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#255#0#0#0#255#0
+ +#0#0#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#255#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ ,#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#9'NumGlyphs'#2#0#7'OnClick'#7#22'SpeedButtonSearchClick'#0#0#12'TLa'
+ +'beledEdit'#17'LabeledEditSearch'#4'Left'#2'h'#6'Height'#2#27#3'Top'#2#6#5'W'
+ +'idth'#3#174#0' EditLabel.AnchorSideLeft.Control'#7#17'LabeledEditSearch'#31
+ +'EditLabel.AnchorSideTop.Control'#7#17'LabeledEditSearch'#28'EditLabel.Ancho'
+ +'rSideTop.Side'#7#9'asrCenter!EditLabel.AnchorSideRight.Control'#7#17'Labele'
+ +'dEditSearch"EditLabel.AnchorSideBottom.Control'#7#17'LabeledEditSearch'#14
+ +'EditLabel.Left'#2'A'#16'EditLabel.Height'#2#18#13'EditLabel.Top'#2#10#15'Ed'
+ +'itLabel.Width'#2'$'#17'EditLabel.Caption'#6#6'Find: '#21'EditLabel.ParentCo'
+ +'lor'#8#13'LabelPosition'#7#6'lpLeft'#8'TabOrder'#2#0#8'OnChange'#7#16'EditS'
+ +'earchChange'#7'OnEnter'#7#22'LabeledEditSearchEnter'#6'OnExit'#7#21'Labeled'
+ +'EditSearchExit'#9'OnKeyDown'#7#24'LabeledEditSearchKeyDown'#10'OnKeyPress'#7
+ +#25'LabeledEditSearchKeyPress'#0#0#9'TCheckBox'#17'CheckBoxMatchCase'#4'Left'
+ +#3'@'#1#6'Height'#2#22#3'Top'#2#7#5'Width'#2'b'#7'Caption'#6#10'Match case'#7
+ +'OnClick'#7#22'CheckBoxMatchCaseClick'#8'TabOrder'#2#1#0#0#0#9'TSplitter'#20
+ +'SplitterFunctionList'#4'Left'#3#150#0#6'Height'#3'%'#1#3'Top'#2#0#5'Width'#2
+ +#5#11'OnCanResize'#7#29'SplitterFunctionListCanResize'#7'Visible'#8#0#0#244
+ +#18'TFunctionListFrame'#15'frmFunctionList'#6'Height'#3'%'#1#5'Width'#3#150#0
+ +#12'ClientHeight'#3'%'#1#11'ClientWidth'#3#150#0#9'OnEndDock'#13#8'TabOrder'
+ +#2#3#0#241#9'TTreeView'#12'FunctionList'#6'Height'#3#244#0#3'Top'#2#22#5'Wid'
+ +'th'#3#150#0#17'DefaultItemHeight'#2#19#8'OnChange'#7#18'FunctionListChange'
+ +#10'OnDeletion'#13#7'OnEnter'#7#17'FunctionListEnter'#6'OnExit'#7#16'Functio'
+ +'nListExit'#0#0#241#5'TEdit'#14'editSearchList'#6'Height'#2#27#3'Top'#3#10#1
+ +#5'Width'#3#150#0#6'OnExit'#7#18'editSearchListExit'#9'OnKeyDown'#7#21'editS'
+ +'earchListKeyDown'#10'OnKeyPress'#7#22'editSearchListKeyPress'#0#0#241#6'TLa'
+ +'bel'#17'FunctionListLabel'#6'Height'#2#18#5'Width'#3#146#0#0#0#0#0#9'TMainM'
+ +'enu'#8'MainMenu'#4'left'#3#232#1#3'top'#3#144#0#0#9'TMenuItem'#8'MenuFile'#7
+ +'Caption'#6#5'&File'#13'SubMenuImages'#7#17'Mufasa_Image_List'#0#9'TMenuItem'
+ +#11'MenuItemNew'#6'Action'#7#15'ActionNewScript'#11'Bitmap.Data'#10':'#4#0#0
+ +'6'#4#0#0'BM6'#4#0#0#0#0#0#0'6'#0#0#0'('#0#0#0#16#0#0#0#16#0#0#0#1#0' '#0#0#0
+ +#0#0#0#4#0#0'd'#0#0#0'd'#0#0#0#0#0#0#0#0#0#0#0#255#255#255#0#187'j4k'#186'e0'
+ +#188#187'f1'#237#186'f0'#247#186'f0'#247#186'f0'#247#186'e0'#247#186'e/'#247
+ +#185'e.'#247#185'e.'#247#185'd.'#247#185'd.'#239#183'b,'#189#183'b.c'#255#255
+ +#255#0#255#255#255#0#188'i3'#222#248#241#234#242#247#236#223#253#246#235#222
+ +#255#246#234#222#255#246#234#220#255#246#234#220#255#250#243#235#255#250#243
+ +#235#255#250#242#234#255#252#247#243#255#252#248#244#253#254#254#253#240#183
+ +'`*'#213#255#255#255#0#255#255#255#0#191'q8'#245#245#235#223#254#253#191'h'
+ +#255#252#189'g'#255#251#190'e'#255#252#190'd'#255#252#190'd'#255#252#189'b'
+ +#255#251#189'c'#255#251#188'a'#255#252#190'`'#255#252#188'b'#255#253#251#248
+ +#253#185'd-'#243#255#255#255#0#255#255#255#0#193'x<'#247#247#237#227#255#253
+ +#194'n'#255#255#216#160#255#255#215#158#255#255#214#155#255#255#215#152#255
+ +#255#214#150#255#255#214#149#255#255#213#148#255#255#212#147#255#251#190'e'
+ +#255#251#247#244#255#187'g1'#247#255#255#255#0#255#255#255#0#196'|@'#247#247
+ +#240#230#255#248#180'U'#255#247#180'V'#255#247#181'T'#255#248#180'S'#255#248
+ +#178'S'#255#247#179'R'#255#247#179'R'#255#247#178'Q'#255#247#178'O'#255#247
+ +#178'O'#255#252#249#245#255#191'o6'#247#255#255#255#0#255#255#255#0#197#128
+ +'B'#247#248#241#232#255#254#229#213#255#253#229#211#255#253#229#211#255#252
+ +#229#211#255#252#229#211#255#252#228#209#255#252#226#206#255#252#226#204#255
+ +#251#224#201#255#251#225#200#255#253#250#247#255#193'v;'#247#255#255#255#0
+ +#255#255#255#0#197#130'E'#247#248#242#235#255#254#231#214#255#253#231#214#255
+ +#253#231#214#255#253#231#214#255#253#230#213#255#253#229#211#255#252#228#209
+ +#255#252#226#205#255#251#225#203#255#251#225#201#255#251#247#242#255#197'|?'
+ +#247#255#255#255#0#255#255#255#0#198#132'G'#247#249#243#236#255#254#232#214
+ ,#255#254#232#215#255#253#231#214#255#253#231#214#255#253#231#213#255#253#229
+ +#211#255#251#228#208#255#251#227#204#255#250#223#199#255#250#223#198#255#250
+ +#242#234#255#198#128'B'#247#255#255#255#0#255#255#255#0#198#136'I'#247#249
+ +#244#237#255#254#232#216#255#254#232#216#255#254#232#215#255#254#231#214#255
+ +#253#229#211#255#252#228#209#255#251#225#204#255#250#224#199#255#249#221#195
+ +#255#248#220#194#255#250#244#237#255#198#130'E'#247#255#255#255#0#255#255#255
+ +#0#198#136'J'#247#249#244#239#255#254#231#215#255#253#231#214#255#253#231#213
+ +#255#253#230#212#255#252#230#210#255#251#225#204#255#250#223#199#255#248#220
+ +#194#255#246#218#189#255#246#216#187#255#250#244#239#255#198#131'F'#247#255
+ +#255#255#0#255#255#255#0#198#137'K'#247#249#244#240#255#252#230#211#255#252
+ +#230#212#255#253#231#211#255#252#228#209#255#251#227#205#255#250#224#200#255
+ +#248#220#194#255#245#214#187#255#243#212#181#255#241#210#179#255#248#244#240
+ +#255#196#130'F'#247#255#255#255#0#255#255#255#0#198#137'K'#247#249#245#241
+ +#255#252#227#207#255#251#228#208#255#252#228#207#255#252#227#205#255#250#225
+ +#202#255#249#221#196#255#246#217#188#255#244#233#223#255#247#242#236#255#251
+ +#247#243#255#245#239#233#255#194'~E'#251#255#255#255#0#255#255#255#0#198#137
+ +'L'#246#249#245#241#255#252#227#205#255#251#227#206#255#251#227#205#255#251
+ +#226#203#255#249#224#200#255#248#220#194#255#245#214#186#255#253#251#248#255
+ +#252#230#205#255#250#229#201#255#226#182#132#255#191'yB'#166#255#255#255#0
+ +#255#255#255#0#197#136'K'#234#250#246#242#252#250#224#199#255#251#225#201#255
+ +#251#226#201#255#251#224#200#255#249#223#197#255#248#219#193#255#244#214#184
+ +#255#255#251#248#255#246#216#180#255#225#176'}'#255#219#146'd'#246#180'k>'#7
+ +#255#255#255#0#255#255#255#0#196#133'I'#195#247#242#236#236#248#244#238#252
+ +#248#244#237#255#248#243#237#255#248#243#237#255#248#243#237#255#248#242#236
+ +#255#247#242#236#255#242#230#215#255#226#178'}'#255#219#148'e'#245#179'h;'#7
+ +#255#255#255#0#255#255#255#0#255#255#255#0#193'}D`'#200#139'M'#187#200#140'O'
+ +#238#200#140'O'#246#200#140'O'#247#200#140'O'#247#200#141'O'#247#201#140'O'
+ +#247#199#139'O'#247#197#137'K'#212#196'v;'#145#179'h<'#6#255#255#255#0#255
+ +#255#255#0#255#255#255#0#13'SubMenuImages'#7#17'Mufasa_Image_List'#7'OnClick'
+ +#7#16'ActionNewExecute'#0#0#9'TMenuItem'#15'MenuItemDivider'#7'Caption'#6#1
+ +'-'#0#0#9'TMenuItem'#12'MenuItemOpen'#6'Action'#7#16'ActionOpenScript'#11'Bi'
+ +'tmap.Data'#10':'#4#0#0'6'#4#0#0'BM6'#4#0#0#0#0#0#0'6'#0#0#0'('#0#0#0#16#0#0
+ +#0#16#0#0#0#1#0' '#0#0#0#0#0#0#4#0#0'd'#0#0#0'd'#0#0#0#0#0#0#0#0#0#0#0','#134
+ +#216#209'-'#136#216#247'-'#135#216#247'-'#136#216#247'-'#136#216#247'-'#136
+ +#216#247'-'#136#216#247'-'#136#216#247'-'#136#216#247'-'#136#216#247'-'#136
+ +#216#247'-'#135#216#247'-'#136#216#247','#134#216#209#255#255#255#0#255#255
+ +#255#0'3'#142#217#251#220#240#250#255#152#225#246#255#149#224#246#255#146#223
+ +#246#255#142#222#245#255#137#220#245#255#133#218#244#255#128#217#244#255'z'
+ +#215#243#255't'#213#243#255'p'#211#242#255#194#234#248#255'5'#148#218#255#255
+ +#255#255#0#255#255#255#0'5'#148#218#247#239#250#254#255#147#229#248#255#143
+ +#228#248#255#137#227#248#255#130#225#247#255'z'#223#247#255'q'#222#246#255'g'
+ +#219#245#255'['#216#244#255'M'#212#243#255'@'#209#242#255#202#242#251#255'5'
+ +#148#218#255#255#255#255#0#255#255#255#0'6'#154#218#248#242#250#253#255#148
+ +#230#248#255#146#229#248#255#144#229#248#255#139#227#248#255#134#226#247#255
+ +#127#225#247#255'w'#222#246#255'l'#220#246#255'^'#217#244#255'O'#213#243#255
+ +#204#242#251#255'5'#148#218#255#255#255#255#0#255#255#255#0'6'#161#218#249
+ +#246#252#254#255#148#229#248#255#147#229#248#255#147#229#248#255#145#229#248
+ +#255#147#219#233#255#147#215#227#255#147#210#220#255#144#206#215#255#140#200
+ +#207#255#134#193#198#255#201#216#214#255'5'#148#218#255#197'tD'#232#202#127
+ +'S'#241'7'#166#218#250#254#255#255#255#248#253#255#255#246#253#255#255#245
+ +#252#255#255#243#252#254#255#154#228#244#255#154#230#247#255#155#230#246#255
+ +#157#229#245#255#158#229#245#255#159#229#244#255#218#243#248#255'5'#148#218
+ +#255#253#244#238#255#202#128'T'#249'5'#171#218#250#232#246#251#255'p'#188#231
+ +#255'U'#170#226#255'M'#165#224#255#145#201#235#255#250#243#239#255#253#254
+ +#253#255#255#253#252#255#255#253#252#255#254#253#252#255#254#252#251#255#254
+ +#254#253#255'5'#148#218#255#239#242#232#255#206#129'V'#255'6'#170#218#242#241
+ +#250#253#255#148#222#245#255#147#220#244#255'd'#188#233#255'5'#148#218#255'5'
+ +#148#218#255'5'#148#218#255'5'#148#218#255'5'#148#218#255'5'#148#218#255'5'
+ +#148#218#255'5'#148#218#255'5'#148#218#255#251#246#239#255#204#131'U'#254'5'
+ +#175#218#240#247#252#254#255#142#228#248#255#145#222#245#255#159#224#245#255
+ +#172#225#246#255#202#132'R'#255#255#247#241#255#255#233#217#255#255#234#219
+ +#255#255#233#217#255#255#231#215#255#255#229#210#255#255#226#203#255#255#247
+ +#241#255#203#133'U'#254'6'#179#218#248#253#254#254#255#254#255#255#255#254
+ +#254#255#255#253#254#255#255#254#255#255#255#228#186#145#255#255#247#240#255
+ ,#255#231#213#255#253#231#214#255#253#230#212#255#252#228#208#255#251#227#203
+ +#255#250#220#194#255#254#243#232#255#204#134'V'#254'4'#180#217#208'^'#194#225
+ +#250'`'#195#226#250'`'#195#226#250'`'#195#226#250'_'#195#226#250#228#187#145
+ +#255#255#247#242#255#254#231#213#255#254#231#213#255#253#229#209#255#250#224
+ +#202#255#249#222#196#255#247#217#188#255#253#242#231#255#204#135'W'#254#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#228#187#146#255#254#247#241#255#252#229#210#255#252#228#209#255#251
+ +#226#204#255#249#221#196#255#246#215#187#255#243#209#175#255#250#239#228#255
+ +#204#135'X'#254#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#228#187#146#255#254#246#240#255#252#226#205#255#252
+ +#227#205#255#250#223#200#255#247#217#188#255#245#233#221#255#250#243#235#255
+ +#251#248#243#255#202#131'S'#254#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#228#187#147#255#254#245#237#255#252
+ +#222#197#255#251#224#199#255#249#220#194#255#245#211#180#255#254#249#243#255
+ +#250#226#196#255#236#193#147#255#195'}H'#147#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#229#190#150#255#255#255
+ +#254#255#253#243#233#255#253#243#234#255#252#242#232#255#250#239#227#255#250
+ +#242#231#255#234#187#136#255#207#133'U'#179#180'i='#12#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#234#195#157
+ +#255#230#191#150#255#228#187#146#255#228#187#146#255#209#160'l'#245#208#158
+ +'m'#246#204#150'_'#218#196'yB~'#178'g<'#9#255#255#255#0#7'OnClick'#7#17'Acti'
+ +'onOpenExecute'#0#0#9'TMenuItem'#12'MenuItemSave'#6'Action'#7#16'ActionSaveS'
+ +'cript'#11'Bitmap.Data'#10':'#4#0#0'6'#4#0#0'BM6'#4#0#0#0#0#0#0'6'#0#0#0'('#0
+ +#0#0#16#0#0#0#16#0#0#0#1#0' '#0#0#0#0#0#0#4#0#0'd'#0#0#0'd'#0#0#0#0#0#0#0#0#0
+ +#0#0#186'j6'#143#185'i5'#181#184'i5'#238#183'h5'#255#181'h5'#255#180'g4'#255
+ +#178'f4'#255#176'e3'#255#174'd3'#255#172'c2'#255#170'b2'#255#169'a2'#255#168
+ +'`1'#255#167'`1'#254#166'`1'#241#168'a1'#196#186'j5'#222#235#198#173#255#234
+ +#197#173#255#254#251#248#255#254#251#248#255#254#251#248#255#254#251#248#255
+ +#254#251#248#255#254#251#248#255#254#251#248#255#254#251#248#255#254#251#248
+ +#255#254#251#248#255#200#154'|'#255#199#152'y'#255#167'`1'#237#186'k7'#254
+ +#237#202#179#255#224#162'z'#255#254#250#247#255'b'#192#136#255'b'#192#136#255
+ +'b'#192#136#255'b'#192#136#255'b'#192#136#255'b'#192#136#255'b'#192#136#255
+ +'b'#192#136#255#253#249#246#255#202#141'e'#255#201#155'|'#255#167'`1'#254#187
+ +'l8'#255#238#204#182#255#225#162'z'#255#254#250#247#255#191#220#194#255#191
+ +#220#194#255#191#220#194#255#191#220#194#255#191#220#194#255#191#220#194#255
+ +#191#220#194#255#191#220#194#255#253#249#246#255#205#144'h'#255#204#158#129
+ +#255#168'a2'#255#187'k8'#255#239#206#184#255#225#162'y'#255#254#250#247#255
+ +'b'#192#136#255'b'#192#136#255'b'#192#136#255'b'#192#136#255'b'#192#136#255
+ +'b'#192#136#255'b'#192#136#255'b'#192#136#255#253#249#246#255#207#147'j'#255
+ +#206#163#132#255#170'a2'#255#186'j6'#255#239#208#187#255#226#162'z'#255#254
+ +#251#248#255#254#251#248#255#254#251#248#255#254#251#248#255#254#251#248#255
+ +#254#251#248#255#254#251#248#255#254#251#248#255#254#251#248#255#254#251#248
+ +#255#211#150'm'#255#210#167#138#255#171'b2'#255#187'j6'#255#240#210#190#255
+ +#226#163'z'#255#226#163'z'#255#225#163'z'#255#226#163'{'#255#225#163'{'#255
+ +#224#161'x'#255#222#159'w'#255#221#159'v'#255#220#157't'#255#217#155'r'#255
+ +#216#153'q'#255#214#153'p'#255#213#171#142#255#173'c3'#255#187'j6'#255#242
+ +#213#194#255#227#163'z'#255#227#163'z'#255#226#163'{'#255#226#163'{'#255#226
+ +#164'{'#255#225#162'y'#255#224#161'x'#255#222#160'w'#255#222#158'u'#255#220
+ +#157't'#255#218#155's'#255#217#155's'#255#218#176#149#255#175'd3'#255#187'j6'
+ +#255#242#216#197#255#227#164'{'#255#227#163'z'#255#227#164'z'#255#226#164'{'
+ +#255#226#163'{'#255#225#163'{'#255#225#162'y'#255#223#160'w'#255#222#159'v'
+ +#255#221#158't'#255#219#156'r'#255#220#157't'#255#221#181#154#255#177'e4'#255
+ +#187'k6'#255#244#217#199#255#230#166'}'#255#200#140'd'#255#201#141'e'#255#201
+ +#142'g'#255#203#146'l'#255#203#146'm'#255#202#144'i'#255#200#140'e'#255#200
+ +#140'd'#255#200#140'd'#255#200#140'd'#255#218#156't'#255#225#186#159#255#179
+ +'f4'#255#187'k6'#254#244#220#201#255#231#167'}'#255#249#236#225#255#249#236
+ +#225#255#249#237#227#255#252#244#238#255#253#250#247#255#253#247#243#255#250
+ +#237#229#255#247#231#219#255#247#229#217#255#246#229#216#255#222#160'w'#255
+ +#228#190#164#255#180'g4'#255#188'k6'#250#245#221#204#255#231#168'~'#255#250
+ +#240#232#255#250#240#232#255#201#141'f'#255#250#240#233#255#253#248#243#255
+ +#254#250#248#255#252#244#239#255#249#233#223#255#247#231#219#255#247#229#217
+ +#255#224#162'x'#255#231#194#169#255#182'h5'#255#188'k6'#240#246#223#208#255
+ +#232#168'~'#255#252#246#241#255#252#246#241#255#200#140'd'#255#250#241#233
+ +#255#251#244#238#255#253#250#247#255#253#249#246#255#250#240#232#255#248#232
+ ,#221#255#247#230#219#255#225#163'z'#255#239#213#195#255#183'i5'#254#188'k6'
+ +#216#246#223#209#255#233#170#128#255#254#250#246#255#253#250#246#255#200#140
+ +'d'#255#251#243#238#255#251#241#234#255#252#246#242#255#254#251#248#255#252
+ +#246#241#255#249#236#226#255#248#231#219#255#238#208#186#255#236#208#189#255
+ +#187'p>'#248#188'k6'#155#246#224#209#255#247#224#209#255#254#251#248#255#254
+ +#251#247#255#253#249#246#255#252#245#240#255#250#240#234#255#251#242#237#255
+ +#253#249#246#255#253#250#247#255#251#241#235#255#248#233#223#254#236#208#189
+ +#251#201#137'^'#236#181'i5c'#188'k6q'#188'k6'#144#188'k6'#204#188'k6'#238#188
+ +'k6'#250#187'k6'#254#187'k6'#255#187'j6'#255#187'j6'#255#188'l9'#255#189'n;'
+ +#255#187'm:'#255#187'k8'#239#187'p>'#203#182'i5T'#255#255#255#0#7'OnClick'#7
+ +#17'ActionSaveExecute'#0#0#9'TMenuItem'#14'MenuItemSaveAs'#6'Action'#7#18'Ac'
+ +'tionSaveScriptAs'#7'Caption'#6#10'Save as...'#7'OnClick'#7#19'ActionSaveAsE'
+ +'xecute'#0#0#9'TMenuItem'#15'MenuItemSaveAll'#6'Action'#7#13'ActionSaveAll'#7
+ +'Enabled'#8#11'Bitmap.Data'#10':'#4#0#0'6'#4#0#0'BM6'#4#0#0#0#0#0#0'6'#0#0#0
+ +'('#0#0#0#16#0#0#0#16#0#0#0#1#0' '#0#0#0#0#0#0#4#0#0'd'#0#0#0'd'#0#0#0#0#0#0
+ +#0#0#0#0#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#186'h3'#197#195#132'X'#255#211#139'h'#255#225#143'p'#255#220#141'l'
+ +#255#218#139'm'#255#215#138'n'#255#205#139'l'#255#171'mD'#255#166'_.'#255#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#198#131'U'#255#239#206#186#255#221#255#255#255#135#238#199#255#162#244
+ +#215#255#162#246#215#255#140#238#199#255#224#255#255#255#221#162#133#255#171
+ +'j>'#255#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#186'h3'#172
+ +#195#132'X'#222#195#127'Q'#255#239#182#154#255#234#243#232#255'Q'#191#132#255
+ +'o'#201#152#255'q'#201#153#255'T'#191#132#255#228#244#233#255#221#156'{'#255
+ +#170'i:'#255#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#198#131
+ +'U'#222#239#206#186#222#196#129'T'#255#234#182#151#255#243#243#234#255#237
+ +#241#230#255#239#241#230#255#239#240#230#255#237#241#229#255#243#245#237#255
+ +#213#156'y'#255#176'pD'#255#255#255#255#0#255#255#255#0#186'h3'#155#195#132
+ +'X'#201#197#128'S'#248#238#178#150#248#201#139'a'#255#230#181#146#255#226#167
+ +#129#255#225#167#129#255#222#163'}'#255#220#161'{'#255#219#159'y'#255#217#158
+ +'w'#255#212#154's'#255#187'~W'#255#255#255#255#0#255#255#255#0#198#131'U'#201
+ +#239#206#186#201#199#142'f'#248#224#188#156#248#202#141'e'#255#234#184#153
+ +#255#221#165'~'#255#221#166#128#255#219#163'|'#255#217#160'z'#255#217#160'y'
+ +#255#216#159'x'#255#216#158'x'#255#191#132']'#255#255#255#255#0#255#255#255#0
+ +#195#127'Q'#201#239#182#154#201#204#150'o'#248#214#182#145#248#200#136']'#255
+ +#239#191#161#255#253#252#250#255#254#252#251#255#254#253#253#255#254#253#252
+ +#255#253#251#250#255#253#252#251#255#221#168#133#255#193#127'S'#255#255#255
+ +#255#0#255#255#255#0#196#129'T'#201#234#182#151#201#206#152's'#248#234#190
+ +#161#248#199#134'['#255#239#192#158#255#255#255#255#255#204#147'n'#255#255
+ +#255#255#255#255#255#255#255#255#251#247#255#255#248#241#255#228#175#140#255
+ +#199#138'a'#255#255#255#255#0#255#255#255#0#201#139'a'#201#230#181#146#201
+ +#203#139'a'#248#238#188#158#248#204#141'e'#255#243#205#176#255#255#255#255
+ +#255#227#199#179#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
+ +#255#255#234#191#161#255#201#137'`'#255#255#255#255#0#255#255#255#0#202#141
+ +'e'#201#234#184#153#201#201#137'_'#248#237#189#155#248#212#151'n'#255#212#158
+ +'{'#255#208#152'q'#255#214#164#130#255#205#142'h'#255#205#144'i'#255#208#154
+ +'u'#255#209#153's'#255#200#139'b'#255#173'Z 6'#255#255#255#0#255#255#255#0
+ +#200#136']'#201#239#191#161#201#209#153'u'#248#244#210#184#248#255#255#255
+ +#248#230#205#187#248#255#255#254#248#255#255#255#248#251#246#242#248#248#241
+ +#237#248#234#191#161#222#201#137'`'#222#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#199#134'['#201#239#192#158#201#217#162'}'#248#211#157'z'
+ +#248#213#163#128#248#218#174#143#248#210#154'w'#248#210#155'w'#248#210#156'w'
+ +#248#208#151'q'#248#200#139'b'#222#173'Z /'#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#204#141'e'#201#243#205#176#201#255#255#255#201#227
+ +#199#179#201#255#255#255#201#255#255#255#201#255#255#255#201#255#255#255#201
+ +#234#191#161#201#201#137'`'#201#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#212#151'n'#201#212#158'{'#201#208#152
+ +'q'#201#214#164#130#201#205#142'h'#201#205#144'i'#201#208#154'u'#201#209#153
+ +'s'#201#200#139'b'#201#173'Z +'#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ ,#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#7'OnClick'#7#20'ActionSaveAllExecute'#0#0#9'TMenuIt'
+ +'em'#16'MenuItemDivider2'#7'Caption'#6#1'-'#0#0#9'TMenuItem'#14'MenuItemNewT'
+ +'ab'#6'Action'#7#12'ActionNewTab'#11'Bitmap.Data'#10':'#4#0#0'6'#4#0#0'BM6'#4
+ +#0#0#0#0#0#0'6'#0#0#0'('#0#0#0#16#0#0#0#16#0#0#0#1#0' '#0#0#0#0#0#0#4#0#0'd'
+ +#0#0#0'd'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#4'9'#0#0#6'm'#0#153#5'i'#0#204#6'm'#0#153
+ +#4'9'#0#0#0#0#0#0#0#0#0#9#0#0#0#22#0#0#0#26#0#0#0#26#0#0#0#26#0#0#0#26#0#0#0
+ +#26#0#0#0#26#0#0#0#26#0#0#0#26#0#0#0#26#11#128#0#209'+'#223#26#255#11#128#0
+ +#209#0#0#0#22#0#0#0#9#13#13#13'g'#16#16#16#133#16#16#16#133#16#16#16#133#16
+ +#16#16#133#16#16#16#133#16#16#16#133#16#16#16#133#16#16#16#133#14'b'#4#207#14
+ +'~'#2#231#14'~'#2#231'='#226','#255#14'~'#2#231#14'~'#2#231#11'_'#2#176''''''
+ +'''{'#235#235#235#255#231#231#231#255#231#231#231#255#231#231#231#255#231#231
+ +#231#255#231#231#231#255#231#231#231#255#231#231#231#255';'#165'/'#255'R'#231
+ +'A'#255'R'#231'A'#255'R'#231'A'#255'R'#231'A'#255'R'#231'A'#255#18#137#5#229
+ +'222v'#234#234#234#255#226#226#226#255#226#226#226#255#226#226#226#255#226
+ +#226#226#255#226#226#226#255#226#226#226#255#226#226#226#255'f'#185'['#255'<'
+ +#171'-'#255'<'#171'-'#255'f'#235'U'#255'<'#171'-'#255'>'#173'/'#255#28'z'#17
+ +#200'888s'#237#237#237#255#230#230#230#255#230#230#230#255#230#230#230#255
+ +#230#230#230#255#230#230#230#255#230#230#230#255#230#230#230#255#230#230#230
+ +#255#230#230#230#255'>'#177'.'#255'u'#238'd'#255'>'#177'.'#255#237#237#237
+ +#255'888s>>>q'#240#240#240#255#235#235#235#255#235#235#235#255#235#235#235
+ +#255#235#235#235#255#235#235#235#255#235#235#235#255#235#235#235#255#235#235
+ +#235#255#235#235#235#255'k'#196'_'#255'@'#182'/'#255'k'#196'_'#255#240#240
+ +#240#255'>>>qDDDn'#243#243#243#255#239#239#239#255#239#239#239#255#239#239
+ +#239#255#239#239#239#255#239#239#239#255#239#239#239#255#239#239#239#255#239
+ +#239#239#255#239#239#239#255#239#239#239#255#239#239#239#255#239#239#239#255
+ +#243#243#243#255'DDDnIIIl'#247#247#247#255#244#244#244#255#244#244#244#255
+ +#244#244#244#255#244#244#244#255#244#244#244#255#244#244#244#255#244#244#244
+ +#255#244#244#244#255#244#244#244#255#244#244#244#255#244#244#244#255#244#244
+ +#244#255#247#247#247#255'IIIlMMMj'#250#250#250#255#248#248#248#255#248#248
+ +#248#255#248#248#248#255#248#248#248#255#248#248#248#255#248#248#248#255#248
+ +#248#248#255#248#248#248#255#248#248#248#255#248#248#248#255#248#248#248#255
+ +#248#248#248#255#250#250#250#255'MMMjQQQh'#253#253#253#255#252#252#252#255
+ +#252#252#252#255#252#252#252#255#252#252#252#255#252#252#252#255#252#252#252
+ +#255#252#252#252#255#252#252#252#255#252#252#252#255#252#252#252#255#252#252
+ +#252#255#252#252#252#255#253#253#253#255'QQQhUUUg'#255#255#255#255#255#255
+ +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
+ +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
+ +#255#255#255#255#255#255#255#255#255#255#255#255'UUUgPPPi'#187#187#187#255
+ +#186#186#186#255#184#184#184#255#182#182#182#255#179#179#179#255#176#176#176
+ +#255#174#174#174#255#171#171#171#255#168#168#168#255#166#166#166#255#163#163
+ +#163#255#160#160#160#255#158#158#158#255#156#156#156#255#3#3#3'fRRR['#198#198
+ +#198#212#220#220#220#255#216#217#217#255#213#213#213#255#208#209#209#255#204
+ +#204#204#255#200#200#200#255#198#198#198#255#198#197#197#255#201#197#197#255
+ +#205#198#198#255#209#199#199#255#215#203#203#255#196#184#184#212'RRR[UUU"UUU'
+ +'YUUUfUUUfUUUfUUUfUUUfUUUfUUUfUUUfUUUfUUUfUUUfUUUfUUUYUUU"'#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#7'OnClick'#7#19'Act'
+ +'ionNewTabExecute'#0#0#9'TMenuItem'#16'MenuItemCloseTab'#6'Action'#7#14'Acti'
+ +'onCloseTab'#11'Bitmap.Data'#10':'#4#0#0'6'#4#0#0'BM6'#4#0#0#0#0#0#0'6'#0#0#0
+ +'('#0#0#0#16#0#0#0#16#0#0#0#1#0' '#0#0#0#0#0#0#4#0#0'd'#0#0#0'd'#0#0#0#0#0#0
+ +#0#0#0#0#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#0#0#0#9#0#0#0#22#0#0#0#26#0#0#0#26#0#0#0#26#0#0#0#26#0#0#0#26#0#0
+ +#0#26#0#0#0#26#0#0#0#26#0#0#0#26#0#0#0#26#0#0#0#26#0#0#0#26#0#0#0#22#0#0#0#9
+ +#13#13#13'g'#16#16#16#133#16#16#16#133#16#16#16#133#16#16#16#133#16#16#16#133
+ +#16#16#16#133#16#16#16#133#16#16#16#133#4#4'['#207#2#2's'#231#2#2's'#231#2#2
+ +'s'#231#2#2's'#231#2#2's'#231#2#2'X'#176'''''''{'#235#235#235#255#231#231#231
+ +#255#231#231#231#255#231#231#231#255#231#231#231#255#231#231#231#255#231#231
+ +#231#255#231#231#231#255'//'#167#255'^^'#247#255'^^'#247#255'^^'#247#255'^^'
+ +#247#255'^^'#247#255#5#5#139#229'222v'#234#234#234#255#226#226#226#255#226
+ ,#226#226#255#226#226#226#255#226#226#226#255#226#226#226#255#226#226#226#255
+ +#226#226#226#255'[['#190#255'--'#179#255'--'#179#255'--'#179#255'--'#179#255
+ +'//'#181#255#17#17#129#200'888s'#237#237#237#255#230#230#230#255#230#230#230
+ +#255#230#230#230#255#230#230#230#255#230#230#230#255#230#230#230#255#230#230
+ +#230#255#230#230#230#255#230#230#230#255#230#230#230#255#230#230#230#255#230
+ +#230#230#255#237#237#237#255'888s>>>q'#240#240#240#255#235#235#235#255#235
+ +#235#235#255#235#235#235#255#235#235#235#255#235#235#235#255#235#235#235#255
+ +#235#235#235#255#235#235#235#255#235#235#235#255#235#235#235#255#235#235#235
+ +#255#235#235#235#255#240#240#240#255'>>>qDDDn'#243#243#243#255#239#239#239
+ +#255#239#239#239#255#239#239#239#255#239#239#239#255#239#239#239#255#239#239
+ +#239#255#239#239#239#255#239#239#239#255#239#239#239#255#239#239#239#255#239
+ +#239#239#255#239#239#239#255#243#243#243#255'DDDnIIIl'#247#247#247#255#244
+ +#244#244#255#244#244#244#255#244#244#244#255#244#244#244#255#244#244#244#255
+ +#244#244#244#255#244#244#244#255#244#244#244#255#244#244#244#255#244#244#244
+ +#255#244#244#244#255#244#244#244#255#247#247#247#255'IIIlMMMj'#250#250#250
+ +#255#248#248#248#255#248#248#248#255#248#248#248#255#248#248#248#255#248#248
+ +#248#255#248#248#248#255#248#248#248#255#248#248#248#255#248#248#248#255#248
+ +#248#248#255#248#248#248#255#248#248#248#255#250#250#250#255'MMMjQQQh'#253
+ +#253#253#255#252#252#252#255#252#252#252#255#252#252#252#255#252#252#252#255
+ +#252#252#252#255#252#252#252#255#252#252#252#255#252#252#252#255#252#252#252
+ +#255#252#252#252#255#252#252#252#255#252#252#252#255#253#253#253#255'QQQhUUU'
+ +'g'#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
+ +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
+ +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
+ +'UUUgPPPi'#187#187#187#255#186#186#186#255#184#184#184#255#182#182#182#255
+ +#179#179#179#255#176#176#176#255#174#174#174#255#171#171#171#255#168#168#168
+ +#255#166#166#166#255#163#163#163#255#160#160#160#255#158#158#158#255#156#156
+ +#156#255#3#3#3'fRRR['#198#198#198#212#220#220#220#255#216#217#217#255#213#213
+ +#213#255#208#209#209#255#204#204#204#255#200#200#200#255#198#198#198#255#198
+ +#197#197#255#201#197#197#255#205#198#198#255#209#199#199#255#215#203#203#255
+ +#196#184#184#212'RRR[UUU"UUUYUUUfUUUfUUUfUUUfUUUfUUUfUUUfUUUfUUUfUUUfUUUfUUU'
+ +'fUUUYUUU"'#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#7'OnClick'#7#21'ActionCloseTabExecute'#0#0#9'TMenuItem'#17'MenuIt'
+ +'emCloseTabs'#7'Caption'#6#14'Close all tabs'#11'Bitmap.Data'#10':'#4#0#0'6'
+ +#4#0#0'BM6'#4#0#0#0#0#0#0'6'#0#0#0'('#0#0#0#16#0#0#0#16#0#0#0#1#0' '#0#0#0#0
+ +#0#0#4#0#0'd'#0#0#0'd'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#10#0#0#0#24#0#0#0#26#0#0#0
+ +#26#0#0#0#26#0#0#0#26#0#0#0#26#0#0#0#26#0#0#0#26#0#0#0#26#0#0#0#26#0#0#0#25#0
+ +#0#0#11#0#0#0#0#0#0'w'#0#0#0#128#0#17#17#17'e'#20#20#20#131#20#20#20#131#20
+ +#20#20#131#20#20#20#131#20#20#20#131#20#20#20#131#20#20#20#131#20#20#20#131
+ +#20#20#20#131#20#20#20#131#20#20#20#131#17#17#17'e'#0#0'Z'#0#0#0'w'#0#0#0#128
+ +#0'---x'#236#236#236#255#232#232#232#255#232#232#232#255#232#232#232#255#232
+ +#232#232#255#232#232#232#255#232#232#232#255#232#232#232#255'__'#173#255'//'
+ +#149#255'00'#150#255#5#5'w'#228#0#0#128#204#0#0#128#204#0#0#132#153'666t'#235
+ +#235#235#255#228#228#228#255#228#228#228#255#228#228#228#255#228#228#228#255
+ +#228#228#228#255#228#228#228#255#228#228#228#255'..'#167#255'^^'#247#255'^^'
+ +#247#255'^^'#247#255'^^'#247#255'^^'#247#255#0#0#152#204'===q'#239#239#239
+ +#255#234#234#234#255#234#234#234#255#234#234#234#255#234#234#234#255#234#234
+ +#234#255#234#234#234#255#234#234#234#255'^^'#194#255'//'#181#255'00'#182#255
+ +#6#6#154#230#0#0#163#209#0#0#164#209#0#0'|'#158'EEEn'#244#244#244#255#240#240
+ +#240#255#240#240#240#255#240#240#240#255#240#240#240#255#240#240#240#255#240
+ +#240#240#255#240#240#240#255#240#240#240#255#240#240#240#255#244#244#244#255
+ +'111'#184#20#20#20#131#20#20#20#131#17#17#17'eKKKk'#248#248#248#255#246#246
+ +#246#255#246#246#246#255#246#246#246#255#246#246#246#255#246#246#246#255#246
+ +#246#246#255#246#246#246#255#246#246#246#255#246#246#246#255#248#248#248#255
+ +#166#166#166#255#232#232#232#255#236#236#236#255'---xPPPi'#252#252#252#255
+ +#251#251#251#255#251#251#251#255#251#251#251#255#251#251#251#255#251#251#251
+ +#255#251#251#251#255#251#251#251#255#251#251#251#255#251#251#251#255#252#252
+ +#252#255#168#168#168#255#228#228#228#255#235#235#235#255'666tTTTg'#255#255
+ +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
+ +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
+ +#255#255#255#255#174#174#174#255#234#234#234#255#239#239#239#255'===qPPPi'
+ +#187#187#187#255#185#185#185#255#182#182#182#255#180#180#180#255#176#176#176
+ ,#255#173#173#173#255#169#169#169#255#166#166#166#255#162#162#162#255#160#160
+ +#160#255#157#157#157#255#145#145#145#255#240#240#240#255#244#244#244#255'EEE'
+ +'nRRR['#198#198#198#212#219#219#219#255#214#214#214#255#209#209#209#255#203
+ +#204#204#255#199#199#199#255#198#196#196#255#200#197#197#255#206#198#198#255
+ +#212#201#201#255#208#197#197#255#188#188#188#255#246#246#246#255#248#248#248
+ +#255'KKKkUUU"UUUYUUUfSSS'#165#185#185#185#255#184#184#184#255#184#184#184#255
+ +#184#184#184#255#184#184#184#255#184#184#184#255#184#184#184#255#193#193#193
+ +#255#229#229#229#255#251#251#251#255#252#252#252#255'PPPiUUU'#0'UUU'#0'UUU'#0
+ +'TTTg'#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
+ +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
+ +#255#255#255#255#255#255#255#255'TTTgUUU'#0'TTT'#0'PPP'#0'PPPi'#187#187#187
+ +#255#185#185#185#255#182#182#182#255#180#180#180#255#176#176#176#255#173#173
+ +#173#255#169#169#169#255#166#166#166#255#162#162#162#255#160#160#160#255#157
+ +#157#157#255#3#3#3'fTTT'#0'RRR'#0'RRR'#0'RRR['#198#198#198#212#219#219#219
+ +#255#214#214#214#255#209#209#209#255#203#204#204#255#199#199#199#255#198#196
+ +#196#255#200#197#197#255#206#198#198#255#212#201#201#255#196#183#183#212'RRR'
+ +'[TTT'#0'TTT'#0'TTT'#0'UUU"UUUYUUUfUUUfUUUfUUUfUUUfUUUfUUUfUUUfUUUfUUUYUUU"'
+ +#10'ImageIndex'#2#20#7'OnClick'#7#22'MenuItemCloseTabsClick'#0#0#9'TMenuItem'
+ +#16'MenuItemDivider6'#7'Caption'#6#1'-'#0#0#9'TMenuItem'#16'MenuItemMainExit'
+ +#6'Action'#7#10'ActionExit'#11'Bitmap.Data'#10':'#4#0#0'6'#4#0#0'BM6'#4#0#0#0
+ +#0#0#0'6'#0#0#0'('#0#0#0#16#0#0#0#16#0#0#0#1#0' '#0#0#0#0#0#0#4#0#0'd'#0#0#0
+ +'d'#0#0#0#0#0#0#0#0#0#0#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#29'c'#155#22#25'`'#152'9'#20']'#149'b'#16'Z'#146#136#13'X'#144#164#19'\'#146
+ +#252#12'W'#143#237#153#153#153#255'qqq'#255'TTT'#255'QQQ'#255'OOO'#255'LLL'
+ +#255'JJJ'#255'GGG'#255'EEE'#255'%g'#157#255'2t'#168#255'=|'#175#255'G'#132
+ +#181#255'N'#138#186#255'>~'#173#255#12'W'#143#234#255#255#255#0#255#255#255#0
+ +'XXX'#255#162#162#162#255#162#162#162#255#163#163#163#255#164#164#164#255#164
+ +#164#164#255#165#165#165#255'/o'#165#255'x'#171#210#255'x'#171#211#255's'#167
+ +#209#255'i'#160#205#255'@'#127#174#255#15'Y'#145#234#255#255#255#0#255#255
+ +#255#0'\\\'#255#161#161#161#255''#255'4~;'#255'1y7'
+ +#255'.u4'#255'I'#145'P'#255'F'#143'L'#255'9s='#255#161#161#161#255#162#162
+ +#162#255'E~'#180#255#136#183#217#255'g'#163#207#255'a'#158#204#255'c'#159#204
+ +#255'E'#131#177#255#31'd'#156#234';'#135'B'#255#137#203#146#255#132#200#141
+ +#255#128#198#136#255'{'#195#131#255'w'#193#127#255'G'#143'M'#255';t?'#255#161
+ +#161#161#255'L'#132#186#255#141#187#219#255'n'#168#209#255'f'#166#209#255'_'
+ +#180#223#255'G'#133#177#255'%i'#161#234'>'#139'F'#255#143#206#153#255'}'#198
+ +#135#255'x'#195#129#255's'#192'|'#255't'#192'|'#255'y'#194#129#255'I'#144'O'
+ +#255'T'#127'W'#255'T'#137#191#255#148#191#221#255'u'#173#212#255'c'#184#225
+ +#255'K'#212#255#255'B'#139#184#255',n'#166#234'A'#144'J'#255#148#210#159#255
+ +#145#208#154#255#141#205#150#255#137#203#146#255#132#200#141#255'Q'#152'X'
+ +#255'A|F'#255#159#159#159#255'Z'#142#196#255#152#195#224#255'|'#179#215#255
+ +'t'#175#214#255'^'#196#237#255'K'#136#179#255'4s'#171#234'D'#148'M'#255'B'
+ +#145'K'#255'?'#141'H'#255'='#137'E'#255']'#164'e'#255'Z'#160'a'#255'E'#131'K'
+ +#255#158#158#158#255#158#158#158#255'`'#146#201#255#158#199#226#255#131#184
+ +#218#255'}'#180#215#255'~'#179#215#255'O'#137#180#255';y'#177#234#255#255#255
+ +#0#255#255#255#0'www'#255#154#154#154#255'='#138'E'#255'I'#138'O'#255#156#156
+ +#156#255#157#157#157#255#157#157#157#255'f'#150#204#255#162#203#227#255#137
+ +#189#220#255#131#185#218#255#132#185#218#255'Q'#139#181#255'C~'#182#234#255
+ +#255#255#0#255#255#255#0'zzz'#255#153#153#153#255'R'#145'Y'#255#153#154#153
+ +#255#155#155#155#255#156#156#156#255#156#156#156#255'l'#154#208#255#167#206
+ +#229#255#143#193#223#255#137#189#220#255#139#189#220#255'S'#141#182#255'K'
+ +#132#188#234#255#255#255#0#255#255#255#0'}}}'#255#153#153#153#255#153#153#153
+ +#255#154#154#154#255#154#154#154#255#155#155#155#255#155#155#155#255'o'#157
+ +#211#255#170#209#231#255#171#209#231#255#152#199#225#255#145#194#222#255'V'
+ +#143#183#255'R'#137#193#234#255#255#255#0#255#255#255#0#128#128#128#255'~~~'
+ +#255'|||'#255'zzz'#255'www'#255'uuu'#255'rrr'#255'q'#158#212#255'o'#158#214
+ +#255#135#178#220#255#171#211#232#255#169#208#230#255'X'#144#184#255'Y'#142
+ +#198#234#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255
+ ,#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0'p'#158#214#219'm'#156#212#255#133#177#218#255'Z'#145#185#255'`'
+ +#147#203#234#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0'm'#156#212#137'j'#154#210#251'f'
+ +#151#207#238#7'OnClick'#7#17'ActionExitExecute'#0#0#0#9'TMenuItem'#8'MenuEdi'
+ +'t'#7'Caption'#6#5'&Edit'#13'SubMenuImages'#7#17'Mufasa_Image_List'#7'OnClic'
+ +'k'#7#13'MenuEditClick'#0#9'TMenuItem'#12'MenuItemUndo'#6'Action'#7#10'Actio'
+ +'nUndo'#11'Bitmap.Data'#10':'#4#0#0'6'#4#0#0'BM6'#4#0#0#0#0#0#0'6'#0#0#0'('#0
+ +#0#0#16#0#0#0#16#0#0#0#1#0' '#0#0#0#0#0#0#4#0#0'd'#0#0#0'd'#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#24#166#195'i'#26#167#196'i'#0#160#196#24#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#160#196']f'#219#234#178#17#166#194#174#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#160#196'"C'#196#219#252'C'#197#216#254'#'#166#192#127#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#160#196#255#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#14#170#203#254']'#218#233#254'#'#166#192#239#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#160#196#255#0#160#196#255#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#158#193#26#2#172#200#255#136#231#242#254#17#162#194#255#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#5'y}'#17#0#160#196#255'v'#237#251#255#0#160#196
+ +#255#0#0#0#0#0#0#0#0#0#160#196'0'#0#153#185'P'#0#160#196#201'm'#230#245#255
+ +'v'#226#239#255#25#163#193#255#0#0#0#0#0#0#0#0#0#0#0#0#5'y}'#17#0#160#196#255
+ +'v'#237#251#255'v'#237#251#255#0#160#196#255#0#160#196#255#0#160#196#255#0
+ +#160#196#255#1#169#196#255'n'#225#238#255#15#201#223#255'i'#228#242#255#26
+ +#164#192#248#0#0#0#0#0#0#0#0#5'y}'#17#0#160#196#255'v'#237#251#255#4#195#218
+ +#255'v'#237#251#255'i'#234#249#255'i'#234#249#255'i'#234#249#255'i'#234#249
+ +#255#5#221#247#255#10#200#223#255#7#194#216#255'o'#220#235#255#27#163#191#244
+ +#0#0#0#0#5'y~'#17#0#160#196#255'y'#237#251#255'2'#226#248#255','#223#244#255
+ +#4#192#214#255#4#192#214#255#4#192#214#255#29#210#232#255#29#210#232#255#29
+ +#210#232#255#11#200#223#255'j'#229#243#255#27#171#197#248#21#160#188#203#0#0
+ +#0#0#0#160#196#255#173#243#251#255'/'#224#246#255'2'#226#248#255'2'#226#247
+ +#255'2'#226#247#255'/'#224#245#255')'#219#241#255#29#210#232#255#29#210#232
+ +#255#29#210#232#255'6'#217#236#255'@'#205#225#255#22#161#189#202#5'y}'#10#0#0
+ +#0#0#5'y}'#10#0#160#196#255#173#243#251#255'/'#224#246#255'2'#226#247#255')'
+ +#219#241#255'/'#224#245#255')'#219#241#255#22#205#227#255'6'#217#236#255'i'
+ +#231#246#255'A'#206#227#254#19#163#193#228#5'y}2'#0#0#0#0#0#0#0#0#0#0#0#0#5
+ +'y}'#17#0#160#196#255#173#243#251#255'1'#225#246#255' '#227#250#255's'#236
+ +#250#255'o'#235#250#255'n'#232#247#255'l'#232#247#248#20#161#188#212#20#163
+ +#193#213#5'y}'#28#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#5'y}'#17#0#160#196
+ +#255#173#243#251#255'%'#228#251#255#0#160#196#255#0#160#196#255#19#161#190
+ +#231#21#159#187#207#27#161#187#164#6'z|'#11#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#5'y}'#17#0#160#196#255#173#243#251#255#0#160#196#255#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#157#191#20#0#160#196#255#0#160#196#255#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#160#196#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#7'OnClick'#7#17'ActionUndoExecu'
+ +'te'#0#0#9'TMenuItem'#12'MenuItemRedo'#6'Action'#7#10'ActionRedo'#11'Bitmap.'
+ +'Data'#10':'#4#0#0'6'#4#0#0'BM6'#4#0#0#0#0#0#0'6'#0#0#0'('#0#0#0#16#0#0#0#16
+ +#0#0#0#1#0' '#0#0#0#0#0#0#4#0#0'd'#0#0#0'd'#0#0#0#0#0#0#0#0#0#0#0#255#255#255
+ +#0#0#0#0#0#0#160#196#24#26#167#196'i'#24#166#195'i'#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#255#255#255#0
+ +#0#0#0#0#17#166#194#174'f'#219#234#178#0#160#196']'#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#255#255#255#0
+ +'#'#166#192#127'C'#197#216#254'C'#196#219#252#0#160#196'"'#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#255
+ +#255#255#0'#'#166#192#239']'#218#233#254#14#170#203#254#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#160#196#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#255#255#255#0#17#162#194#255#136#231#242#254#2#172#200#255#0#158#193#26
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#160#196#255#0#160#196#255#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#255#255#255#0#25#163#193#255'v'#226#239#255'm'#230
+ +#245#255#0#160#196#201#0#153#185'P'#0#160#196'0'#0#0#0#0#0#0#0#0#0#160#196
+ +#255'v'#237#251#255#0#160#196#255#5'y}'#17#0#0#0#0#0#0#0#0#0#0#0#0#255#255
+ ,#255#0#26#164#192#248'i'#228#242#255#15#201#223#255'n'#225#238#255#1#169#196
+ +#255#0#160#196#255#0#160#196#255#0#160#196#255#0#160#196#255'v'#237#251#255
+ +'v'#237#251#255#0#160#196#255#5'y}'#17#0#0#0#0#0#0#0#0#255#255#255#0#27#163
+ +#191#244'o'#220#235#255#7#194#216#255#10#200#223#255#5#221#247#255'i'#234#249
+ +#255'i'#234#249#255'i'#234#249#255'i'#234#249#255'v'#237#251#255#4#195#218
+ +#255'v'#237#251#255#0#160#196#255#5'y}'#17#0#0#0#0#255#255#255#0#21#160#188
+ +#203#27#171#197#248'j'#229#243#255#11#200#223#255#29#210#232#255#29#210#232
+ +#255#29#210#232#255#4#192#214#255#4#192#214#255#4#192#214#255','#223#244#255
+ +'2'#226#248#255'y'#237#251#255#0#160#196#255#5'y~'#17#255#255#255#0#5'y}'#10
+ +#22#161#189#202'@'#205#225#255'6'#217#236#255#29#210#232#255#29#210#232#255
+ +#29#210#232#255')'#219#241#255'/'#224#245#255'2'#226#247#255'2'#226#247#255
+ +'2'#226#248#255'/'#224#246#255#173#243#251#255#0#160#196#255#255#255#255#0#0
+ +#0#0#0#5'y}2'#19#163#193#228'A'#206#227#254'i'#231#246#255'6'#217#236#255#22
+ +#205#227#255')'#219#241#255'/'#224#245#255')'#219#241#255'2'#226#247#255'/'
+ +#224#246#255#173#243#251#255#0#160#196#255#5'y}'#10#255#255#255#0#0#0#0#0#0#0
+ +#0#0#5'y}'#28#20#163#193#213#20#161#188#212'l'#232#247#248'n'#232#247#255'o'
+ +#235#250#255's'#236#250#255' '#227#250#255'1'#225#246#255#173#243#251#255#0
+ +#160#196#255#5'y}'#17#0#0#0#0#255#255#255#0#0#0#0#0#0#0#0#0#0#0#0#0#6'z|'#11
+ +#27#161#187#164#21#159#187#207#19#161#190#231#0#160#196#255#0#160#196#255'%'
+ +#228#251#255#173#243#251#255#0#160#196#255#5'y}'#17#0#0#0#0#0#0#0#0#255#255
+ +#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#160
+ +#196#255#173#243#251#255#0#160#196#255#5'y}'#17#0#0#0#0#0#0#0#0#0#0#0#0#255
+ +#255#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#160#196#255#0#160#196#255#0#157#191#20#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#255
+ +#255#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#160#196#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#7'OnClick'#7#17
+ +'ActionRedoExecute'#0#0#9'TMenuItem'#16'MenuItemDivider3'#7'Caption'#6#1'-'#0
+ +#0#9'TMenuItem'#11'MenuItemCut'#6'Action'#7#9'ActionCut'#11'Bitmap.Data'#10
+ +':'#4#0#0'6'#4#0#0'BM6'#4#0#0#0#0#0#0'6'#0#0#0'('#0#0#0#16#0#0#0#16#0#0#0#1#0
+ +' '#0#0#0#0#0#0#4#0#0'd'#0#0#0'd'#0#0#0#0#0#0#0#0#0#0#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#2#13#140#10#28''''#166#159'5?'#201#247'"-'#175#185#3#13#140#28#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#5#15#141#31#6#16#142'&'#1#11#138#3#255#255#255#0#18#28#155'p@K'
+ +#217#255',5'#191#221'=G'#209#255#29''''#169#164#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#15#25#151'c2='#199
+ +#248'7A'#207#255#31')'#171#176#0#10#134#24'#-'#180#175'5@'#204#253#0#9#133#24
+ +#28''''#168#149'4>'#197#248#4#14#140#20#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0'/:'#189#222'5?'#201#229'%0'#179#194'?J'
+ +#221#255#31'*'#172#194'$0'#178#203'2<'#198#242#0#10#134#3#17#27#157'w7A'#200
+ +#255#8#18#142' '#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0'2<'#195#236'#.'#173#175#255#255#255#0#26'%'#168#153'BP'#210#255
+ +#203#163'u'#254'AO'#214#255#22'!'#163#157'/9'#192#212'.8'#190#223#2#13#139#10
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#29'('
+ +#169#156';F'#204#255#8#18#144':'#7#17#144'S;H'#212#255#219#189#156#255#238
+ +#204#166#255'@L'#222#255':C'#209#255#15#25#152'i'#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#3#13#140#31',5'#185
+ +#215''#202#242'?L'#215#255#216#188#154#255#246#234#225#255#187
+ +#146'Z'#191#148'b'#24';'#145'a'#26#1#255#255#255#0#255#255#255#0#255#255#255
+ +#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#3#13#140#31#27'&'
+ +#167#153'*4'#186#204#17#28#157#137#187#152'i'#204#240#224#208#255#183#145'_'
+ +#197#143']'#20#11#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#0#11#136#2#255#255#255#0#180#142'Z'#144#246#234#221#255#225#205#180
+ +#255#177#141']'#191#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#179#140'W'#137#241#226#212#255#206#178
+ +#142#244#245#235#224#255#166#127'J'#157#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#177#137'S'#132#238#223#206#255#151
+ +'f e'#194#163'|'#218#233#216#197#253#169#130'N{'#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#175#135'P|'#231#213#193#255#149'e'#31
+ +'+'#143'\'#18#27#197#167#131#231#213#188#157#225#181#147'db'#255#255#255#0
+ ,#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#172#131'Ku'#222#201#175#255#149'd'#29
+ +#31#255#255#255#0#146'`'#23'&'#195#164'|'#235#181#144'c'#203#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#170#129'Go'#214#189#159#247#147'a'#25
+ +#16#255#255#255#0#255#255#255#0#150'f ,'#169#128'K'#203#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#168'}Bi'#204#176#139#224#145']'#20#9#255#255#255
+ +#0#255#255#255#0#255#255#255#0#146'`'#23#6#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#154'k''1'#170'~C'#161#146'`'#24#5#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#7'OnClick'#7
+ +#16'ActionCutExecute'#0#0#9'TMenuItem'#12'MenuItemCopy'#6'Action'#7#10'Actio'
+ +'nCopy'#11'Bitmap.Data'#10':'#4#0#0'6'#4#0#0'BM6'#4#0#0#0#0#0#0'6'#0#0#0'('#0
+ +#0#0#16#0#0#0#16#0#0#0#1#0' '#0#0#0#0#0#0#4#0#0'd'#0#0#0'd'#0#0#0#0#0#0#0#0#0
+ +#0#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#197'sB'#193#198'uE'#230#200'uE'#254#199'uE'#243#200'uE'#243
+ +#199'uE'#243#199'uE'#243#200'uF'#244#197'tD'#232#202#127'S'#241#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#199'y'
+ +'I'#237#252#243#236#255#250#241#232#255#250#240#231#255#251#241#233#255#251
+ +#242#234#255#251#242#234#255#251#242#235#255#253#244#238#255#202#128'T'#249
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#207#130'S'#255#239#241#231#255#255#233#217#255#255#234#219#255#255
+ +#233#217#255#255#231#215#255#255#229#210#255#255#226#203#255#239#242#232#255
+ +#206#129'V'#255#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#204#131'R'#251#251#245#238#255#255#233#217#255#255
+ +#234#219#255#255#233#217#255#255#231#215#255#255#229#210#255#255#226#203#255
+ +#251#246#239#255#204#131'U'#254#199'yJ'#185#200'yK'#206#200'uE'#221#199'uE'
+ +#212#200'uE'#212#199'uE'#212#202#132'R'#255#255#247#241#255#255#233#217#255
+ +#255#234#219#255#255#233#217#255#255#231#215#255#255#229#210#255#255#226#203
+ +#255#255#247#241#255#203#133'U'#254#200'|N'#211#252#243#236#222#250#241#232
+ +#222#250#240#231#222#251#241#233#222#251#242#234#222#228#186#145#255#255#247
+ +#240#255#255#231#213#255#253#231#214#255#253#230#212#255#252#228#208#255#251
+ +#227#203#255#250#220#194#255#254#243#232#255#204#134'V'#254#207#130'S'#222
+ +#239#241#231#222#255#233#217#222#255#234#219#222#255#233#217#222#255#231#215
+ +#222#228#187#145#255#255#247#242#255#254#231#213#255#254#231#213#255#253#229
+ +#209#255#250#224#202#255#249#222#196#255#247#217#188#255#253#242#231#255#204
+ +#135'W'#254#204#131'R'#219#251#245#238#222#255#233#217#222#255#234#219#222
+ +#255#233#217#222#255#231#215#222#228#187#146#255#254#247#241#255#252#229#210
+ +#255#252#228#209#255#251#226#204#255#249#221#196#255#246#215#187#255#243#209
+ +#175#255#250#239#228#255#204#135'X'#254#202#132'R'#219#255#247#241#222#255
+ +#233#217#222#255#234#219#222#255#233#217#222#255#231#215#222#228#187#146#255
+ +#254#246#240#255#252#226#205#255#252#227#205#255#250#223#200#255#247#217#188
+ +#255#245#233#221#255#250#243#235#255#251#248#243#255#202#131'S'#254#203#133
+ +'S'#219#255#247#240#222#255#231#213#222#253#231#214#222#253#230#212#222#252
+ +#228#208#222#228#187#147#255#254#245#237#255#252#222#197#255#251#224#199#255
+ +#249#220#194#255#245#211#180#255#254#249#243#255#250#226#196#255#236#193#147
+ +#255#195'}H'#147#203#134'T'#219#255#247#242#222#254#231#213#222#254#231#213
+ +#222#253#229#209#222#250#224#202#222#229#190#150#255#255#255#254#255#253#243
+ +#233#255#253#243#234#255#252#242#232#255#250#239#227#255#250#242#231#255#234
+ +#187#136#255#207#133'U'#179#180'i='#12#203#134'U'#219#254#247#241#222#252#229
+ +#210#222#252#228#209#222#251#226#204#222#249#221#196#222#234#195#157#255#230
+ +#191#150#255#228#187#146#255#228#187#146#255#209#160'l'#245#208#158'm'#246
+ +#204#150'_'#218#196'yB~'#178'g<'#9#255#255#255#0#203#134'U'#219#254#246#240
+ +#222#252#226#205#222#252#227#205#222#250#223#200#222#247#217#188#222#245#233
+ +#221#222#250#243#235#222#251#248#243#222#205#149'e'#220#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#203#134'V'#218
+ +#254#245#237#222#252#222#197#222#251#224#199#222#249#220#194#222#245#211#180
+ +#222#254#249#243#222#250#226#196#222#236#193#147#222#195'}H'#128#255#255#255
+ +#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#202
+ +#133'T'#208#255#255#255#219#253#243#233#222#253#243#234#222#252#242#232#222
+ +#250#239#227#222#250#242#231#222#234#187#136#222#207#133'U'#156#180'i='#10
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#199'yG'#170#204#134'U'#206#204#136'W'#222#203#136'V'#219#204#136
+ ,'V'#219#203#135'W'#219#202#131'P'#208#196'yBn'#178'g<'#8#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#7'OnClick'#7#17'ActionCopyExecute'#0#0#9'TMenuItem'#13'MenuItemPaste'
+ +#6'Action'#7#11'ActionPaste'#11'Bitmap.Data'#10':'#4#0#0'6'#4#0#0'BM6'#4#0#0
+ +#0#0#0#0'6'#0#0#0'('#0#0#0#16#0#0#0#16#0#0#0#1#0' '#0#0#0#0#0#0#4#0#0'd'#0#0
+ +#0'd'#0#0#0#0#0#0#0#0#0#0#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0'^^^'#2'[[[wXXX'#138'UUU'#138'RRR'#138'OOO'#138'LLL'#138
+ +'JJJ'#138'HHH'#138'FFF'#138'DDDf c'#152'J c'#152#207' c'#152#255' c'#152#255
+ +' c'#152#255'$c'#149#255'Xs'#136#255#247#247#247#255#240#240#240#255#240#240
+ +#240#255#240#240#240#255#240#240#240#255#240#240#240#255#240#240#240#255#243
+ +#243#243#250'FFF'#132' c'#152#194'b'#165#215#255'e'#168#218#255'd'#166#217
+ +#255'b'#164#216#255'b'#159#209#255'u'#142#164#255#239#239#239#255#231#231#231
+ +#255#231#231#231#255#231#231#231#255#231#231#231#255#230#230#230#255#230#230
+ +#230#255#236#236#236#250'III'#132' c'#152#255'h'#171#220#255'H'#142#207#255
+ +'F'#139#206#255'C'#135#205#255'D'#132#198#255'h'#133#161#255#240#240#240#255
+ +#180#180#180#255#180#180#180#255#180#180#180#255#180#180#180#255#180#180#180
+ +#255#179#179#179#255#237#237#237#250'LLL'#132' c'#152#255'i'#174#220#255'J'
+ +#147#209#255'H'#143#208#255'F'#139#206#255'G'#136#199#255'l'#136#163#255#240
+ +#240#240#255#232#232#232#255#232#232#232#255#231#231#231#255#231#231#231#255
+ +#231#231#231#255#231#231#231#255#237#237#237#250'OOO'#132' c'#152#255'k'#177
+ +#222#255'M'#151#211#255'K'#147#210#255'H'#143#208#255'J'#140#201#255'o'#139
+ +#165#255#241#241#241#255#182#182#182#255#181#181#181#255#181#181#181#255#180
+ +#180#180#255#180#180#180#255#180#180#180#255#237#237#237#250'SSS'#132' c'#152
+ +#255'm'#179#223#255'P'#156#213#255'N'#152#211#255'K'#148#209#255'L'#145#203
+ +#255'p'#142#167#255#241#241#241#255#233#233#233#255#233#233#233#255#232#232
+ +#232#255#232#232#232#255#232#232#232#255#231#231#231#255#237#237#237#250'VVV'
+ +#132' c'#152#255'p'#181#224#255'R'#159#215#255'P'#156#214#255'N'#152#212#255
+ +'O'#149#205#255's'#145#170#255#241#241#241#255#183#183#183#255#182#182#182
+ +#255#182#182#182#255#182#182#182#255#181#181#181#255#181#181#181#255#238#238
+ +#238#250'ZZZ'#132' c'#152#255's'#183#225#255'W'#163#215#255'S'#160#215#255'P'
+ +#157#213#255'R'#153#207#255'u'#148#172#255#248#248#248#255#242#242#242#255
+ +#242#242#242#255#242#242#242#255#242#242#242#255#242#242#242#255#241#241#241
+ +#255#244#244#244#250'^^^'#132' c'#152#255'v'#185#226#255'\'#167#217#255'X'
+ +#164#216#255'S'#160#215#255'S'#158#213#255'a'#139#169#255'd'#136#161#255'd'
+ +#135#161#255'c'#134#160#255'i'#135#159#255'Jh'#129#255'jjj'#138'hhh'#138'eee'
+ +#138'bbbc c'#152#255'z'#187#227#255'a'#170#219#255'Z'#165#217#255'S'#160#215
+ +#255'R'#159#215#255'R'#159#215#255'R'#159#215#255'R'#159#215#255'R'#159#215
+ +#255'b'#163#216#255' c'#152#255#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0' c'#152#255'|'#189#228#255'e'#174#221#255'b'#171#220#255'^'#168
+ +#218#255'\'#167#217#255'\'#167#217#255'\'#167#217#255'\'#167#217#255'R'#159
+ +#215#255'b'#163#216#255' c'#152#255#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0' c'#152#255#127#191#228#255'i'#178#222#255'J'#155#218#255'D'
+ +#151#220#255'C'#150#220#255'B'#150#220#255'B'#149#220#255'A'#149#219#255'Q'
+ +#158#214#255'l'#178#222#255' c'#152#255#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0' c'#152#224'q'#179#219#254'~'#191#228#255'N'#157#223#255
+ +#181#238#253#255'u'#212#240#255'u'#212#240#255#181#238#253#255'K'#155#222#255
+ +'n'#180#224#255'm'#179#223#249' c'#152#243#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0' c'#152'2 c'#152#178' c'#152#255'7u'#164#255#182#239
+ +#254#255#128#219#243#255#128#219#243#255#182#239#254#255'.n'#161#255' c'#152
+ +#255' c'#152#165' c'#152'S'#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0' c'#152'* c'#152#255' c'#152#255' c'#152
+ +#255' c'#152#255' c'#152#255' c'#152#240#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#7'OnClick'#7
+ +#18'ActionPasteExecute'#0#0#9'TMenuItem'#14'MenuItemDelete'#6'Action'#7#12'A'
+ +'ctionDelete'#11'Bitmap.Data'#10':'#4#0#0'6'#4#0#0'BM6'#4#0#0#0#0#0#0'6'#0#0
+ +#0'('#0#0#0#16#0#0#0#16#0#0#0#1#0' '#0#0#0#0#0#0#4#0#0'd'#0#0#0'd'#0#0#0#0#0
+ +#0#0#0#0#0#0#255#255#255#0#255#255#255#0#0#0#0#6#0#0#0#14#0#0#0#22#0#0#0#30#0
+ +#0#0'%'#0#0#0'*'#0#0#0'+'#0#0#0')'#0#0#0'$'#0#0#0#29#0#0#0#21#0#0#0#13#0#0#0
+ +#4#255#255#255#0#255#255#255#0#255#255#255#0#0#0#255#1#0#0#211'F'#255#255#255
+ +#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#0#0#211'F'#0#0#255#1#255#255#255#0#255#255#255#0#255
+ +#255#255#0#0#0#255#1#0#0#206#150#0#0#206#255#0#0#206'x'#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#0#0#206'x'#0#0
+ +#207#255#0#0#207#150#0#0#255#1#255#255#255#0#255#255#255#0#0#0#200'F'#0#0#200
+ ,#255#0#0#200#255#0#0#201#255#0#0#202'x'#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#0#0#202'x'#0#0#201#255#0#0#201#255#0#0#201#255#0#0#200
+ +'F'#255#255#255#0#255#255#255#0#255#255#255#0#0#0#193'x'#0#0#195#255#0#0#195
+ +#255#0#0#195#255#0#0#196'x'#255#255#255#0#255#255#255#0#0#0#196'x'#0#0#195
+ +#255#0#0#195#255#0#0#195#255#0#0#196'x'#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#0#0#189'x'#0#0#189#255#0#0#189#255#0#0#189
+ +#255#0#0#189'x'#0#0#189'x'#0#0#189#255#0#0#189#255#0#0#189#255#0#0#189'x'#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#0#0#183'x'#0#0#183#255#0#0#183#255#0#0#183#255#0#0#183
+ +#255#0#0#183#255#0#0#183#255#0#0#183'x'#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#0#0#176'x'#0#0#177#255#0#0#177#255#0#0#177#255#0#0#177#255#0#0
+ +#179'x'#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#0#0
+ +#170'x'#0#0#171#255#0#0#171#255#0#0#171#255#0#0#172#255#0#0#172'x'#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#0#0#166'x'#0#0#165#255#0#0#165#255
+ +#0#0#165#255#0#0#166#255#0#0#166#255#0#0#166#255#0#0#166'x'#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#0#0#159'x'#0#0#159#255#0#0#159#255#0#0#159#255#0#0#159'x'#0#0#159'x'#0
+ +#0#160#255#0#0#160#255#0#0#160#255#0#0#159'x'#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#0#0#153'x'#0#0#153#255#0#0#153#255#0#0
+ +#153#255#0#0#153'x'#255#255#255#0#255#255#255#0#0#0#153'x'#0#0#154#255#0#0
+ +#154#255#0#0#154#255#0#0#153'x'#255#255#255#0#255#255#255#0#255#255#255#0#0#0
+ +#146'F'#0#0#147#255#0#0#147#255#0#0#147#255#0#0#149'x'#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#0#0#149'x'#0#0#148#255#0#0#148#255#0#0#148
+ +#255#0#0#149'F'#255#255#255#0#255#255#255#0#0#0#255#1#0#0#141#150#0#0#141#255
+ +#0#0#142'x'#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#0#0#142'x'#0#0#142#255#0#0#143#150#0#0#255#1#255#255#255
+ +#0#255#255#255#0#255#255#255#0#0#0#255#1#0#0#135'F'#255#255#255#0#255#255#255
+ +#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#0#0#135'F'#0#0#255#1#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#7'OnClick'#7#19'Act'
+ +'ionDeleteExecute'#0#0#9'TMenuItem'#16'MenuItemDivider4'#7'Caption'#6#1'-'#0
+ +#0#9'TMenuItem'#17'MenuItemSelectAll'#6'Action'#7#15'ActionSelectAll'#7'OnCl'
+ +'ick'#7#22'ActionSelectAllExecute'#0#0#9'TMenuItem'#16'MenuItemDivider5'#7'C'
+ +'aption'#6#1'-'#0#0#9'TMenuItem'#12'MenuItemFind'#6'Action'#7#15'ActionFindS'
+ +'tart'#11'Bitmap.Data'#10':'#4#0#0'6'#4#0#0'BM6'#4#0#0#0#0#0#0'6'#0#0#0'('#0
+ +#0#0#16#0#0#0#16#0#0#0#1#0' '#0#0#0#0#0#0#4#0#0'd'#0#0#0'd'#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#1#1#1' '#2#2#2#207#20#20#20#255'999'#207#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#1#1#1'0'#2#2#2#239#21#21#21#255':::'#255'```'#255#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1#1#1'0'#2#2#2#239#21
+ +#21#21#255';;;'#255'```'#255#128#128#128#207#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1#1#1'0'#2#2#2#239#21#21#21#255';;;'
+ +#255'aaa'#255#129#129#129#207#140#140#140#16#0#0#0#0#0#0#0#0#0#0#0#0#140#140
+ +#140'P'#140#140#140#159#140#140#140#191#140#140#140#191#140#140#140#143'TTTP'
+ +#2#2#2#239#22#22#22#255';;;'#255'aaa'#255#129#129#129#207#140#140#140#16#0#0
+ +#0#0#0#0#0#0#140#140#140#16#140#140#140#191#140#140#140#255#162#159#154#255
+ +#190#182#171#255#183#176#165#255#154#152#148#255#140#140#140#255'```'#255'<<'
+ +'<'#255'aaa'#255#129#129#129#207#140#140#140#16#0#0#0#0#0#0#0#0#140#140#140
+ +#16#140#140#140#207#162#159#156#255#233#223#207#255#255#240#218#255#255#238
+ +#213#255#255#236#208#255#255#235#204#255#219#204#181#255#147#146#144#255'|||'
+ +#255#129#129#129#207#140#140#140#16#0#0#0#0#0#0#0#0#0#0#0#0#140#140#140#128
+ +#147#147#146#255#241#232#220#255#255#244#227#255#255#242#222#255#255#240#217
+ +#255#255#238#213#255#255#236#208#255#255#235#204#255#219#204#181#255#140#140
+ +#140#255#140#140#140'P'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#140#140#140#239#190
+ +#188#183#255#255#247#236#255#255#245#231#255#255#244#226#255#255#242#222#255
+ +#255#240#217#255#255#238#213#255#255#236#208#255#255#235#203#255#162#158#151
+ +#255#140#140#140#175#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#140#140#140#255#226#223
+ +#218#255#255#249#240#255#255#247#235#255#255#245#231#255#255#244#226#255#255
+ ,#242#221#255#255#240#217#255#255#238#212#255#255#236#208#255#198#187#172#255
+ +#140#140#140#207#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#140#140#140#255#226#224#221
+ +#255#255#251#244#255#255#249#240#255#255#247#235#255#255#245#230#255#255#243
+ +#226#255#255#242#221#255#255#240#217#255#255#238#212#255#198#188#174#255#140
+ +#140#140#239#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#140#140#140#255#212#211#210#255
+ +#255#252#249#255#255#251#244#255#255#249#239#255#255#247#235#255#255#245#230
+ +#255#255#243#226#255#255#242#221#255#255#242#221#255#183#177#167#255#140#140
+ +#140#191#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#140#140#140#175#154#154#154#255#255
+ +#254#253#255#255#252#248#255#255#251#244#255#255#249#239#255#255#247#234#255
+ +#255#246#232#255#255#250#242#255#241#232#219#255#147#146#145#255#140#140#140
+ +'p'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#140#140#140'0'#140#140#140#255#183#183
+ +#183#255#255#254#253#255#255#254#252#255#255#253#249#255#255#253#249#255#255
+ +#254#252#255#248#242#232#255#162#159#156#255#140#140#140#223#140#140#140#16#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#140#140#140'`'#140#140#140#255#154#154
+ +#154#255#212#211#210#255#226#225#223#255#226#224#220#255#205#201#195#255#147
+ +#147#146#255#140#140#140#239#140#140#140'0'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#140#140#140'0'#140#140#140#175#140#140#140#255#140#140
+ +#140#255#140#140#140#255#140#140#140#239#140#140#140#159#140#140#140#16#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#7'OnClick'#7#22'ActionFindstartEx'
+ +'ecute'#0#0#9'TMenuItem'#16'MenuItemFindNext'#6'Action'#7#14'ActionFindNext'
+ +#7'OnClick'#7#21'ActionFindNextExecute'#0#0#9'TMenuItem'#15'MenuItemReplace'
+ +#6'Action'#7#13'ActionReplace'#7'OnClick'#7#20'ActionReplaceExecute'#0#0#0#9
+ +'TMenuItem'#14'MenuItemScript'#7'Caption'#6#7'&Script'#13'SubMenuImages'#7#17
+ +'Mufasa_Image_List'#0#9'TMenuItem'#11'MenuItemRun'#6'Action'#7#15'ActionRunS'
+ +'cript'#11'Bitmap.Data'#10':'#4#0#0'6'#4#0#0'BM6'#4#0#0#0#0#0#0'6'#0#0#0'('#0
+ +#0#0#16#0#0#0#16#0#0#0#1#0' '#0#0#0#0#0#0#4#0#0'd'#0#0#0'd'#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#4's:'#255'!'#130'O'#255'c'#130'r'#255#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#4's:'#255'z'#207#164#255','#140'Z'#255'=vY'#255#174#174#174#255#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#4's:'#255#130#216#172#255'v'#214#166#255'<'#157'j'#255'''tL'#255
+ +#172#174#173#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#9'w?'#255#131#219#174#255#31#198'q'#255'r'#222#167#255
+ +'K'#178#127#255#23'tE'#255#168#173#170#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#4's:'#255#131#220#175#255#17#195'i'
+ +#255#26#204's'#255'i'#223#163#255'Z'#194#141#255#19'vC'#255#158#167#163#255#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#4's:'#255#169
+ +#220#193#255#16#189'e'#255#17#193'g'#255#19#194'i'#255'Y'#211#149#255'g'#201
+ +#152#255#22'|G'#255#136#156#146#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#4's:'#255#169#220#193#255#13#179'^'#255#14#182'`'#255#14#182
+ +'`'#255#13#180'_'#255'G'#196#132#255'p'#202#156#255#29#130'M'#255'g'#140'y'
+ +#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#4's:'#255#169#220#193
+ +#255#12#170'X'#255#18#174'^'#255#21#175'`'#255#22#173'a'#255#19#170']'#255':'
+ +#182'w'#255'u'#199#157#255'('#137'W'#255'N'#131'g'#255#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#4's:'#255#169#220#193#255'.'#173'k'#255'+'#173'j'#255''''
+ +#171'h'#255'"'#169'd'#255#28#165'_'#255'A'#178'x'#255'x'#198#159#255')'#136
+ +'X'#255'g'#140'y'#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#4's:'#255#169
+ +#220#193#255'6'#173'p'#255'2'#172'm'#255'-'#170'j'#255'('#168'f'#255'X'#188
+ +#137#255'x'#197#157#255#31#128'N'#255#131#154#142#255#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#4's:'#255#169#220#193#255'>'#177'v'#255':'#175's'
+ +#255'6'#174'p'#255'o'#197#152#255'q'#191#151#255#24'{I'#255#166#176#171#255#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#4's:'#255#169#220#193
+ +#255'E'#180'{'#255'G'#180'|'#255#130#204#166#255'g'#182#140#255#23'wE'#255
+ +#193#197#195#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#4's:'#255#165#218#191#255'W'#187#135#255#144#210#176#255'['#171#130#255
+ +'#wL'#255#212#213#212#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#4's:'#255#169#220#193#255#155#213#183#255'L'#159's'#255
+ +'=}\'#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#4's:'#255#164#217#190#255'='#147'f'#255'_'#136's'#255#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#4's:'#255'-'#136'Y'#255#133#156#144#255#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#10'Im'
+ +'ageIndex'#2#6#7'OnClick'#7#16'ActionRunExecute'#0#0#9'TMenuItem'#13'MenuIte'
+ +'mPause'#6'Action'#7#17'ActionPauseScript'#11'Bitmap.Data'#10':'#4#0#0'6'#4#0
+ ,#0'BM6'#4#0#0#0#0#0#0'6'#0#0#0'('#0#0#0#16#0#0#0#16#0#0#0#1#0' '#0#0#0#0#0#0
+ +#4#0#0'd'#0#0#0'd'#0#0#0#0#0#0#0#0#0#0#0#238#238#238#0#238#238#238#0#238#238
+ +#238#0#152'pP'#255#164'e4'#255#164'e4'#255#152'pP'#255#251#227#188#0#251#227
+ +#188#0#152'pP'#255#164'e4'#255#164'e4'#255#152'pP'#255#0#0#0#0#0#0#0#0#0#0#0
+ +#0#152'pP'#0#152'pP'#0#152'pP'#0#159'h>'#255#201#156'v'#255#205#165#133#255
+ +#159'h>'#255#152'pP'#0#152'pP'#0#159'h>'#255#201#156'v'#255#205#165#133#255
+ +#159'h>'#255#0#0#0#0#0#0#0#0#0#0#0#0#162'f8'#0#162'f8'#0#162'f8'#0#163'e5'
+ +#255#215#172#136#255#225#197#173#255#163'e5'#255#162'f8'#0#162'f8'#0#163'e5'
+ +#255#215#172#136#255#225#197#173#255#163'e5'#255#0#0#0#0#0#0#0#0#0#0#0#0#164
+ +'e4'#0#164'e4'#0#164'e4'#0#164'e4'#255#216#169#129#255#230#204#181#255#164'e'
+ +'4'#255#164'e4'#0#164'e4'#0#164'e4'#255#216#169#129#255#230#204#181#255#164
+ +'e4'#255#0#0#0#0#0#0#0#0#0#0#0#0#164'e4'#0#164'e4'#0#164'e4'#0#164'e4'#255
+ +#215#167#127#255#230#204#181#255#164'e4'#255#164'e4'#0#164'e4'#0#164'e4'#255
+ +#215#167#127#255#230#204#181#255#164'e4'#255#0#0#0#0#0#0#0#0#0#0#0#0#164'e4'
+ +#0#164'e4'#0#164'e4'#0#164'e4'#255#215#169#129#255#230#205#182#255#164'e4'
+ +#255#164'e4'#0#164'e4'#0#164'e4'#255#215#169#129#255#230#205#182#255#164'e4'
+ +#255#0#0#0#0#0#0#0#0#0#0#0#0#164'e4'#0#164'e4'#0#164'e4'#0#164'e4'#255#216
+ +#171#132#255#230#206#183#255#164'e4'#255#164'e4'#0#164'e4'#0#164'e4'#255#216
+ +#171#132#255#230#206#183#255#164'e4'#255#0#0#0#0#0#0#0#0#0#0#0#0#164'e4'#0
+ +#164'e4'#0#164'e4'#0#164'e4'#255#217#174#137#255#230#206#183#255#164'e4'#255
+ +#164'e4'#0#164'e4'#0#164'e4'#255#217#174#137#255#230#206#183#255#164'e4'#255
+ +#0#0#0#0#0#0#0#0#0#0#0#0#164'e4'#0#164'e4'#0#164'e4'#0#164'e4'#255#217#176
+ +#141#255#230#206#183#255#164'e4'#255#164'e4'#0#164'e4'#0#164'e4'#255#217#176
+ +#141#255#230#206#183#255#164'e4'#255#0#0#0#0#0#0#0#0#0#0#0#0#164'e4'#0#164'e'
+ +'4'#0#164'e4'#0#164'e4'#255#217#178#143#255#230#206#183#255#164'e4'#255#164
+ +'e4'#0#164'e4'#0#164'e4'#255#217#178#143#255#230#206#183#255#164'e4'#255#0#0
+ +#0#0#0#0#0#0#0#0#0#0#164'e4'#0#164'e4'#0#164'e4'#0#164'e4'#255#218#179#145
+ +#255#230#206#183#255#164'e4'#255#164'e4'#0#164'e4'#0#164'e4'#255#218#179#145
+ +#255#230#206#183#255#164'e4'#255#0#0#0#0#0#0#0#0#0#0#0#0#164'e4'#0#164'e4'#0
+ +#164'e4'#0#164'e4'#255#218#181#147#255#230#207#185#255#164'e4'#255#164'e4'#0
+ +#164'e4'#0#164'e4'#255#218#181#147#255#230#207#185#255#164'e4'#255#0#0#0#0#0
+ +#0#0#0#0#0#0#0#164'e4'#0#164'e4'#0#164'e4'#0#164'e4'#255#219#182#148#255#231
+ +#209#187#255#164'e4'#255#164'e4'#0#164'e4'#0#164'e4'#255#219#182#148#255#231
+ +#209#187#255#164'e4'#255#0#0#0#0#0#0#0#0#0#0#0#0#164'e4'#0#164'e4'#0#164'e4'
+ +#0#164'e4'#255#221#188#157#255#231#209#188#255#164'e4'#255#164'e4'#0#164'e4'
+ +#0#164'e4'#255#221#188#157#255#231#209#188#255#164'e4'#255#0#0#0#0#0#0#0#0#0
+ +#0#0#0#153'nL'#0#153'nL'#0#153'nL'#0#162'f7'#255#220#191#164#255#223#198#175
+ +#255#162'f7'#255#153'nL'#0#153'nL'#0#162'f7'#255#220#191#164#255#223#198#175
+ +#255#162'f7'#255#0#0#0#0#0#0#0#0#0#0#0#0#238#238#238#0#238#238#238#0#238#238
+ +#238#0#153'nL'#255#171'qC'#255#172'rD'#255#153'nL'#255#251#227#188#0#251#227
+ +#188#0#153'nL'#255#171'qC'#255#172'rD'#255#153'nL'#255#0#0#0#0#0#0#0#0#0#0#0
+ +#0#10'ImageIndex'#2#5#7'OnClick'#7#18'ActionPauseExecute'#0#0#9'TMenuItem'#12
+ +'MenuItemStop'#6'Action'#7#16'ActionStopScript'#11'Bitmap.Data'#10':'#4#0#0
+ +'6'#4#0#0'BM6'#4#0#0#0#0#0#0'6'#0#0#0'('#0#0#0#16#0#0#0#16#0#0#0#1#0' '#0#0#0
+ +#0#0#0#4#0#0'd'#0#0#0'd'#0#0#0#0#0#0#0#0#0#0#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +'EP'#191#230'99'#134#230'99'#134#230'99'#134#230'99'#134#230'99'#134#230'99'
+ +#134#230'99'#134#230'99'#134#230'99'#134#230'99'#134#230'99'#134#230#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0'EP'#191#230#135#150#246#255
+ +'|'#141#247#255'r'#132#248#255'h|'#248#255'^s'#250#255'Sj'#250#255'Jc'#250
+ +#255'B\'#251#255':U'#252#255'3O'#252#255'99'#134#230#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0'EP'#191#230#146#158#245#255#135#150#246
+ +#255'|'#141#247#255'r'#133#248#255'h|'#249#255'^s'#249#255'Tk'#250#255'Kc'
+ +#251#255'B\'#251#255'9U'#252#255'99'#134#230#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0'EP'#191#230#155#167#245#255#146#159#245#255#135#150
+ +#247#255'|'#141#247#255'r'#132#248#255'g|'#248#255'^s'#249#255'Tk'#250#255'J'
+ +'c'#251#255'A\'#251#255'99'#134#230#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0'EP'#191#230#166#175#244#255#156#167#245#255#145#159#245#255
+ +#135#150#246#255'}'#141#247#255'q'#132#247#255'h|'#248#255']s'#249#255'Tj'
+ ,#250#255'Jc'#251#255'99'#134#230#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0'EP'#191#230#174#183#243#255#165#175#245#255#156#167#245#255
+ +#145#159#245#255#135#150#247#255'|'#141#247#255'r'#132#248#255'h{'#249#255']'
+ +'s'#249#255'Sk'#250#255'99'#134#230#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0'EP'#191#230#183#190#243#255#175#183#244#255#166#176#244#255
+ +#155#168#245#255#146#159#246#255#135#150#246#255'|'#141#247#255'r'#132#248
+ +#255'g{'#248#255']s'#249#255'99'#134#230#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0'EP'#191#230#191#197#242#255#183#190#243#255#175#183#244
+ +#255#165#175#244#255#156#167#245#255#146#159#246#255#135#149#246#255'}'#141
+ +#247#255'r'#132#248#255'h|'#248#255'99'#134#230#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0'EP'#191#230#199#202#241#255#191#197#243#255#183
+ +#190#243#255#174#183#244#255#166#175#244#255#155#167#245#255#146#159#246#255
+ +#135#150#246#255'|'#141#247#255'r'#132#247#255'99'#134#230#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0'EP'#191#230#204#208#241#255#198#203
+ +#241#255#191#197#242#255#183#191#243#255#175#183#244#255#166#175#245#255#155
+ +#168#245#255#145#159#246#255#135#150#246#255'}'#141#247#255'99'#134#230#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0'EP'#191#230#209#212#241
+ +#255#204#208#242#255#198#203#242#255#191#197#242#255#183#190#243#255#174#184
+ +#243#255#165#175#244#255#155#168#244#255#145#159#245#255#135#149#246#255'99'
+ +#134#230#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0'EP'#191#230
+ +'EP'#191#230'EP'#191#230'EP'#191#230'EP'#191#230'EP'#191#230'EP'#191#230'EP'
+ +#191#230'EP'#191#230'EP'#191#230'EP'#191#230'EP'#191#230#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#10'ImageIndex'#2#7#7'OnClick'#7#17'ActionStopExecute'#0#0#0#9'TMe'
+ +'nuItem'#8'MenuView'#7'Caption'#6#5'&View'#0#9'TMenuItem'#21'MenuItemColourH'
+ +'istory'#7'Caption'#6#20'View &Colour History'#7'OnClick'#7#26'MenuItemColou'
+ +'rHistoryClick'#0#0#9'TMenuItem'#18'MenuItemDebugImage'#7'Caption'#6#17'View'
+ +' &Debug Image'#7'OnClick'#7#23'MenuItemDebugImageClick'#0#0#9'TMenuItem'#20
+ +'MenuItemFunctionList'#7'Caption'#6#19'View &Function List'#7'OnClick'#7#25
+ +'MenuItemFunctionListClick'#0#0#9'TMenuItem'#16'MenuViewSettings'#7'Caption'
+ +#6#13'View Settings'#7'OnClick'#7#21'MenuViewSettingsClick'#0#0#0#9'TMenuIte'
+ +'m'#9'MenuExtra'#7'Caption'#6#6'E&xtra'#0#9'TMenuItem'#24'MenuitemFillFuncti'
+ +'onList'#7'Caption'#6#19'&Fill Function List'#11'Bitmap.Data'#10':'#4#0#0'6'
+ +#4#0#0'BM6'#4#0#0#0#0#0#0'6'#0#0#0'('#0#0#0#16#0#0#0#16#0#0#0#1#0' '#0#0#0#0
+ +#0#0#4#0#0'd'#0#0#0'd'#0#0#0#0#0#0#0#0#0#0#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0'9'#134'@'#3'4~:x'#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0'A'#145'I'#156';'#136'B'#210#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0'N'#163'W'#144'f'#176'n'#255'a'#170'h'#255'='#139'D'#255'7'#131
+ +'>'#255'2{7'#255',t2'#234'''m,'#183'#f''p'#31'a#'#29#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0'['#180'e'#132's'#189'|'#255
+ +#150#209#159#255#148#207#156#255#143#205#150#255#138#202#145#255#133#199#139
+ +#255'z'#190#129#255'e'#173'l'#255'K'#146'Q'#255'$h)'#176' c$9'#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0'`'#188'l'#138'y'#196#131#255#158
+ +#215#167#255#155#212#164#255#151#210#159#255#146#207#154#255#141#204#149#255
+ +#136#202#144#255'z'#194#130#255'~'#196#133#255']'#164'c'#255'&k*'#176'"e%'#29
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0'b'#190'm'#147'{'#199
+ +#133#255'w'#194#129#255'T'#171'^'#255'N'#163'W'#255'I'#155'Q'#255'c'#172'k'
+ +#255#131#195#139#255#135#201#143#255#130#198#137#255'P'#151'V'#255'''m,p'#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0'c'#192'n'
+ +#159'_'#187'j'#210#255#255#255#0#255#255#255#0#255#255#255#0'K'#158'S'#141'E'
+ +#150'M'#225#134#198#142#255#136#201#143#255'o'#179'v'#255'.v3'#183'E'#150'Ma'
+ +'?'#142'Fa9'#134'@a4~:a.v3ag'#198's'#3'd'#194'p{'#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0'M'#161'U'#131'G'#153'O'#237'A'#145'I'#246';'#136
+ +'B'#248'5'#128'<'#232'M'#161'U'#232'G'#153'O'#248'A'#145'I'#246';'#136'B'#237
+ +'5'#128'<'#131#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#30'_!'
+ ,'{'#27'['#30#3'T'#171'^aN'#163'WaI'#155'QaC'#147'Ka='#139'DaT'#171'^'#183#128
+ +#195#137#255#141#204#149#255#131#196#138#255'='#139'D'#225'7'#131'>'#141#255
+ +#255#255#0#255#255#255#0#255#255#255#0'#f'''#210#31'a#'#159#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0'['#180'epu'#191'~'#255
+ +#152#210#161#255#148#207#156#255#134#199#141#255'^'#167'e'#255'9'#134'@'#255
+ +'4~:'#255'.v3'#255'I'#144'O'#255'E'#139'J'#255' c$'#147#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0'`'#188'l'#29'\'#182'g'#176#133#201#142#255
+ +#155#212#164#255#143#206#152#255#146#207#154#255#141#204#149#255#136#202#144
+ +#255#131#198#139#255'~'#196#133#255'y'#193#127#255'G'#141'L'#255'"e%'#138#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0'b'#190'm9^'#185'h'#176
+ +'y'#195#131#255#137#202#146#255#148#208#156#255#149#209#158#255#144#207#153
+ +#255#140#203#148#255#135#201#143#255#128#196#135#255'N'#149'T'#255'''m,'#132
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0'c'#192
+ +'n'#29'_'#187'jp['#180'e'#183'V'#173'_'#234'P'#166'Z'#255'K'#158'S'#255'E'
+ +#150'M'#255'`'#168'h'#255'['#162'b'#255'4~:'#144#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0'G'#153'O'#210'A'#145'I'#156#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0'N'#163'WxI'#155'Q'#3#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#8'ShortCut'#3'Q@'#7'OnClick'#7#29'MenuitemFillFunctionL'
+ +'istClick'#0#0#9'TMenuItem'#16'UpdateMenuButton'#7'Caption'#6#7'&Update'#11
+ +'Bitmap.Data'#10':'#4#0#0'6'#4#0#0'BM6'#4#0#0#0#0#0#0'6'#0#0#0'('#0#0#0#16#0
+ +#0#0#16#0#0#0#1#0' '#0#0#0#0#0#0#4#0#0'd'#0#0#0'd'#0#0#0#0#0#0#0#0#0#0#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#0#138
+ +#255#139#0#138#255#244#0#138#255#139#0#138#255#150#0#138#255#255#0#138#255
+ +#150#0#138#255#249#0#138#255#218#0#138#255#199#0#138#255#141#0#138#255#246#0
+ +#138#255#152#0#138#255#150#0#138#255#255#0#138#255#150#255#255#255#0#0#138
+ +#255#244#244#250#255#255#0#138#255#244'w'#193#255#255#255#255#255#255'w'#193
+ +#255#255#249#252#255#255#218#238#255#255#199#229#255#255#0#138#255#246#246
+ +#251#255#255#152#208#255#255'o'#189#255#255#255#255#255#255#0#138#255#255#255
+ +#255#255#0#0#138#255#244#244#250#255#255#0#138#255#244#238#247#255#255#244
+ +#250#255#255'w'#193#255#255#232#244#255#255#0#138#255#232#0#138#255#199#3#139
+ +#255#255#249#252#255#255#183#222#255#255#170#216#255#255#251#253#255#255''''
+ +#156#255#255#0#138#255'Q'#0#138#255#244#244#250#255#255#153#208#255#255'w'
+ +#193#255#255#244#250#255#255'w'#193#255#255#249#252#255#255#218#238#255#255
+ +#199#229#255#255#159#211#255#255#228#243#255#255#220#239#255#255#227#242#255
+ +#255#205#232#255#255#186#223#255#255#0#138#255#186#0#138#255#246#246#251#255
+ +#255#238#247#255#255#0#138#255#244#244#250#255#255'w'#193#255#255#232#244#255
+ +#255#0#138#255#232#12#144#255#255#237#247#255#255'x'#193#255#255#187#224#255
+ +#255#187#224#255#255'V'#177#255#255#227#242#255#255#0#138#255#227#0#138#255
+ +#238#238#247#255#255'D'#169#255#255#0#138#255#232#232#244#255#255'D'#169#255
+ +#255#244#250#255#255#218#238#255#255#203#231#255#255#171#216#255#255#12#144
+ +#255#255'f'#185#255#255'f'#185#255#255#0#138#255#215#215#237#255#255#24#149
+ +#255#255#0#138#255#133#0#138#255#238#0#138#255#133#0#138#255#127#0#138#255
+ +#232#0#138#255#139#0#138#255#244#0#138#255#218#0#138#255#203#0#138#255#171#0
+ +#138#255'B'#0#138#255'f'#0#138#255'f'#0#138#255'n'#0#138#255#215#0#138#255'n'
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ ,#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#7'OnClick'#7#21'UpdateMenuButtonClick'#0#0#9'TMenuItem'#16'MenuItemDivider9'
+ +#7'Caption'#6#1'-'#0#0#9'TMenuItem'#18'MenuItemExportHTML'#7'Caption'#6#22'&'
+ +'Export script as HTML'#11'Bitmap.Data'#10':'#4#0#0'6'#4#0#0'BM6'#4#0#0#0#0#0
+ +#0'6'#0#0#0'('#0#0#0#16#0#0#0#16#0#0#0#1#0' '#0#0#0#0#0#0#4#0#0'd'#0#0#0'd'#0
+ +#0#0#0#0#0#0#0#0#0#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#205'n#'#255#201'e'#27#255#200'`'#26#255#198'Y'#24#255
+ +#194'S'#23#255#192'N'#22#255#189'G'#21#255#187'A'#21#255#185'>'#20#255#183'9'
+ +#19#255#182'5'#18#255#180'3'#18#255#180'3'#18#255#180'3'#18#255#180'3'#18#255
+ +#180'3'#18#255#210'w5'#255#228#175#135#255#227#171#129#255#225#168'{'#255#223
+ +#163'v'#255#222#161'q'#255#220#157'm'#255#219#153'h'#255#218#151'c'#255#217
+ +#148'^'#255#215#145'['#255#215#143'W'#255#213#141'T'#255#213#140'S'#255#213
+ +#140'S'#255#180'3'#18#255#214#132'C'#255#231#181#144#255#224#163't'#255#222
+ +#158'n'#255#220#154'g'#255#219#149'`'#255#217#145'Z'#255#215#141'S'#255#213
+ +#137'M'#255#211#133'H'#255#210#129'C'#255#208'~>'#255#207'{9'#255#206'y5'#255
+ +#213#141'T'#255#180'3'#18#255#219#142'S'#255#234#187#153#255#252#246#242#255
+ +#225#166'y'#255#252#245#241#255#221#157'k'#255#252#246#242#255#218#148'^'#255
+ +#247#233#222#255#214#140'Q'#255#239#209#186#255#222#164'w'#255#253#250#247
+ +#255#247#232#221#255#215#143'Y'#255#182'5'#18#255#225#151'b'#255#236#193#161
+ +#255#252#247#243#255#229#173#132#255#252#246#242#255#225#164'w'#255#252#247
+ +#243#255#221#155'i'#255#248#235#224#255#240#211#190#255#243#222#206#255#224
+ +#169#127#255#250#240#233#255#210#131'D'#255#217#148'^'#255#183'<'#19#255#226
+ +#160'n'#255#238#199#168#255#254#253#252#255#253#247#243#255#254#250#248#255
+ +#227#172#129#255#252#247#244#255#224#163't'#255#249#236#227#255#250#242#235
+ +#255#253#248#244#255#227#174#134#255#250#241#234#255#213#137'M'#255#218#153
+ +'f'#255#189'C'#21#255#230#167'y'#255#240#203#176#255#253#248#245#255#234#186
+ +#152#255#253#248#244#255#231#179#140#255#253#248#245#255#227#170#128#255#249
+ +#238#229#255#238#205#180#255#253#248#245#255#229#179#142#255#253#249#246#255
+ +#216#143'W'#255#221#158'm'#255#192'N'#22#255#234#171#128#255#242#207#181#255
+ +#252#244#238#255#236#191#159#255#251#243#237#255#253#248#244#255#253#247#244
+ +#255#252#247#243#255#244#219#201#255#231#180#142#255#247#230#218#255#227#173
+ +#131#255#246#228#214#255#219#151'b'#255#223#163'v'#255#196'Y'#24#255#234#171
+ +#128#255#243#208#183#255#239#198#169#255#239#196#166#255#238#194#162#255#236
+ +#191#158#255#235#188#152#255#233#184#147#255#232#180#142#255#230#176#136#255
+ +#227#172#129#255#226#167'{'#255#224#163't'#255#222#158'n'#255#226#170#128#255
+ +#201'b'#26#255#234#171#128#255#243#208#183#255#243#208#183#255#243#208#183
+ +#255#242#208#183#255#241#206#179#255#240#203#176#255#239#201#172#255#238#198
+ +#168#255#237#194#163#255#235#192#158#255#234#187#153#255#232#183#148#255#230
+ +#180#143#255#228#176#137#255#205'n#'#255#234#171#128#255#234#171#128#255#234
+ +#171#128#255#234#171#128#255#234#171#128#255#234#171#128#255#232#169'|'#255
+ +#230#164'w'#255#226#160'p'#255#226#155'k'#255#225#151'b'#255#221#144'Y'#255
+ +#217#139'R'#255#216#133'I'#255#214#128'>'#255#210'w5'#255#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ ,#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#7'OnClick'#7#23'Men'
+ +'uItemExportHTMLClick'#0#0#0#9'TMenuItem'#8'MenuHelp'#7'Caption'#6#5'&Help'#0
+ +#9'TMenuItem'#13'MenuItemAbout'#7'Caption'#6#6'&About'#11'Bitmap.Data'#10':'
+ +#4#0#0'6'#4#0#0'BM6'#4#0#0#0#0#0#0'6'#0#0#0'('#0#0#0#16#0#0#0#16#0#0#0#1#0' '
+ +#0#0#0#0#0#0#4#0#0'd'#0#0#0'd'#0#0#0#0#0#0#0#0#0#0#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#173'tD#'#172'rA}'#170'p?'#219#168'm<'#243
+ +#167'k:'#243#165'i7'#219#164'h5}'#163'f3#'#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#181'~QS'
+ +#179'|N'#230#215#187#163#255#233#218#202#255#236#224#209#255#236#224#209#255
+ +#232#216#200#255#211#181#156#255#167'l:'#230#166'j8S'#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#189#137'_S'#187#135'['#244
+ +#231#213#196#255#229#210#191#255#201#166#133#255#184#142'g'#255#182#138'e'
+ +#255#197#161#128#255#224#204#186#255#227#208#190#255#171'p@'#244#169'n=S'#255
+ +#255#255#0#255#255#255#0#255#255#255#0#198#149'm"'#195#146'j'#229#234#216#201
+ +#255#227#205#186#255#192#148'k'#255#186#140'b'#255#207#176#148#255#207#176
+ +#148#255#183#137'_'#255#178#135'a'#255#218#192#170#255#228#209#192#255#174'u'
+ +'F'#229#173'sC"'#255#255#255#0#255#255#255#0#204#158'x~'#228#204#185#255#234
+ +#214#197#255#199#153'q'#255#191#144'f'#255#191#144'f'#255#247#241#236#255#246
+ +#240#234#255#183#137'_'#255#183#137'_'#255#181#137'c'#255#226#206#187#255#217
+ +#189#166#255#178'{M~'#255#255#255#0#255#255#255#0#211#167#132#219#239#225#211
+ +#255#217#181#149#255#199#152'l'#255#195#149'i'#255#193#147'g'#255#191#144'f'
+ +#255#191#144'f'#255#187#139'c'#255#185#138'c'#255#184#138'b'#255#203#167#134
+ +#255#234#220#204#255#184#131'W'#219#255#255#255#0#255#255#255#0#217#176#143
+ +#246#242#228#217#255#209#165'z'#255#197#153'k'#255#196#151'j'#255#196#150'i'
+ +#255#250#246#242#255#243#234#225#255#194#149'm'#255#190#143'e'#255#190#143'd'
+ +#255#192#149'm'#255#239#227#213#255#191#140'a'#246#255#255#255#0#255#255#255
+ +#0#224#185#153#246#242#229#218#255#209#166'~'#255#204#157'q'#255#199#154'l'
+ +#255#197#152'k'#255#226#204#182#255#248#243#238#255#246#238#232#255#217#189
+ +#161#255#194#148'h'#255#197#155'q'#255#240#226#214#255#197#149'l'#246#255#255
+ +#255#0#255#255#255#0#230#193#163#219#243#229#217#255#223#187#158#255#207#160
+ +'u'#255#205#158'r'#255#245#235#227#255#228#203#180#255#231#211#191#255#251
+ +#248#246#255#229#211#191#255#196#152'k'#255#214#180#145#255#238#224#210#255
+ +#204#158'x'#219#255#255#255#0#255#255#255#0#235#201#173'~'#244#227#212#255
+ +#239#220#205#255#213#168'~'#255#208#160'w'#255#251#248#245#255#252#248#245
+ +#255#252#248#245#255#251#248#245#255#209#168#129#255#207#164'{'#255#234#213
+ +#195#255#234#212#194#255#210#167#131'~'#255#255#255#0#255#255#255#0#241#208
+ +#181'"'#239#206#179#229#246#233#221#255#236#216#198#255#215#172#129#255#220
+ +#187#154#255#246#236#227#255#245#236#226#255#228#200#174#255#210#167'{'#255
+ +#230#206#186#255#241#226#213#255#219#179#145#229#217#176#142'"'#255#255#255#0
+ +#255#255#255#0#255#255#255#0#244#212#187'S'#242#210#184#244#247#234#223#255
+ +#238#222#208#255#227#193#167#255#216#174#137#255#215#172#134#255#221#187#156
+ +#255#235#214#199#255#243#230#217#255#227#190#159#244#225#187#156'S'#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#246#216#191'S'
+ +#245#214#189#230#249#233#220#255#246#232#221#255#243#229#218#255#243#229#218
+ +#255#245#231#220#255#245#228#214#255#235#200#172#230#233#198#169'S'#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#249#219#196'#'#248#218#194'}'#247#216#192#219#246#215#190#243
+ +#244#213#188#243#243#211#185#219#241#209#183'}'#240#207#180'#'#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#7'OnClick'#7#18'MenuItemAboutClic'
+ +'k'#0#0#9'TMenuItem'#17'MenuItemReportBug'#7'Caption'#6#13'&Report a Bug'#11
+ +'Bitmap.Data'#10':'#4#0#0'6'#4#0#0'BM6'#4#0#0#0#0#0#0'6'#0#0#0'('#0#0#0#16#0
+ +#0#0#16#0#0#0#1#0' '#0#0#0#0#0#0#4#0#0'd'#0#0#0'd'#0#0#0#0#0#0#0#0#0#0#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0'2'#138#197
+ +#236'0'#135#196#246'/'#133#195#246'-'#131#194#246'*'#128#187#255')~'#186#255
+ +'(}'#191#246'&{'#190#246'%y'#189#246'#w'#189#246'"v'#188#195#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0'8'#145#201#228#221
+ +#236#246#255#189#238#249#255#172#234#248#255#171#234#248#255#171#234#248#255
+ +#171#234#248#255#173#234#248#255#212#243#251#255#164#200#228#255'&{'#190#171
+ ,#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0'3'#135
+ +#129#200#142#194#225#255#151#232#249#255'a'#220#246#255'['#219#245#255'2'#136
+ +#194#255'['#219#245#255'j'#222#246#255#177#231#246#255'-'#131#194#233'+'#129
+ +#193'*'#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0'*{.'#193'+z2'
+ +#255'J'#159#188#255#171#219#239#255't'#224#247#255'X'#218#245#255'X'#218#245
+ +#255']'#219#245#255#144#230#248#255#146#193#225#255'/'#132#176#144#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0'/'#135'3'#193' t#'#255#148
+ +#192#157#255'b'#172#153#255'{'#189#223#255#162#234#249#255'a'#220#246#255'1'
+ +#135#194#255'w'#225#247#255#182#222#240#255'8'#144#188#233'8'#145#201#13#255
+ +#255#255#0#255#255#255#0#255#255#255#0'5'#146':'#135'-'#140'2'#255'w'#181#130
+ +#255'M'#158'T'#255'y'#179#141#255'M'#167#174#255#172#217#236#255#130#227#248
+ +#255'3'#136#194#255#172#237#250#255'C'#158#207#254'A'#155#206'S'#255#255#255
+ +#0#255#255#255#0#255#255#255#0#255#255#255#0'2'#149'7'#245'b'#173'h'#255'w'
+ +#190#145#255'D'#160']'#255'K'#159'S'#255'r'#180#153#255'Q'#174#207#255#180
+ +#235#248#255#142#230#248#255#181#221#238#255'>'#150#159#255'+xM'#23#255#255
+ +#255#0' f#|'#255#255#255#0#255#255#255#0'3'#156'8'#248'R'#169'Y'#255'm'#188
+ +#140#255'M'#170'p'#255'B'#159'\'#255'L'#162'T'#255'm'#187#184#255#164#215#235
+ +#255#220#244#251#255'U'#176#211#255'/'#130'N'#255'$s('#254'#p'''#255'"l&'#255
+ +#255#255#255#0'4'#164'9'#199'3'#161'8'#255'3'#158'8'#255#148#207#172#255'\'
+ +#180'~'#255'N'#172'r'#255'A'#161']'#255'O'#167'^'#255'`'#187#210#255#171#219
+ +#237#255'l'#186#189#255'*~-'#255'&y*'#244'%v)m'#255#255#255#0'7'#173'<'#250
+ +'6'#170';'#255'5'#167':'#162'8'#165'>'#234'P'#173'V'#255#141#204#165#255'^'
+ +#181#128#255'O'#173's'#255'B'#163']'#255'U'#177#134#255'i'#192#211#255#138
+ +#191#155#255')'#131'.'#255'%Y;'#175#255#255#255#0#255#255#255#0'8'#177'>'#241
+ +'7'#175'=#'#255#255#255#0#255#255#255#0'4'#166':'#254'9'#165'?'#255#144#206
+ +#168#255'b'#185#132#255'X'#178'{'#255'`'#178'v'#255'8'#151'>'#255')'#137'-'
+ +#255'W'#164'b'#255'&PD'#219#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0'7'#174'=A6'#171'<'#255'8'#169'>'#240'E'#172'K'#255#158
+ +#212#173#255#164#215#184#255#133#195#142#255'('#143'-'#255'O'#183'_'#255#151
+ +#200#170#255','#141'1'#255'+'#137'0'#255'*'#133'.'#255#255#255#255#0#255#255
+ +#255#0#255#255#255#0'8'#179'>'#240'8'#177'='#248#255#255#255#0'8'#172'='#241
+ +'5'#168':'#255'4'#165'9'#255'4'#161'9'#255'r'#194'~'#255#175#227#194#255'_'
+ +#140'x'#255'2eMu'#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0':'#183'@'#255'9'#181'?t'#255#255#255#0#255#255#255#0'7'#173'<'#248
+ +'6'#170';'#237'F'#127'f'#165':'#134'P'#247'3'#157':'#254';qX'#137#255#255#255
+ +#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0';'
+ +#187'A#'#255#255#255#0#255#255#255#0#255#255#255#0'8'#178'>'#255'7'#175'='
+ +#178'N'#142'j"5'#169';e4'#166':'#242#255#255#255#0#255#255#255#0#255#255#255
+ +#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0':'#183'?'#255'9'#180'?A'#255#255#255#0
+ +'7'#174'=R6'#172'<'#247#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255
+ +#0#7'OnClick'#7#22'MenuItemReportBugClick'#0#0#0#0#10'TImageList'#17'Mufasa_'
+ +'Image_List'#4'left'#3#192#1#3'top'#3#144#0#6'Bitmap'#10#14'l'#0#0'Li'#27#0#0
+ +#0#16#0#0#0#16#0#0#0'BBB'#0'BBB'#0'BBB'#0'BBB'#0'BBB'#0'BBB'#0'BBB'#0'BBB'#0
+ +'BBB'#0'BBB'#0'BBB'#0'BBB'#0#161'UB'#255#161'UB'#255#161'UB'#255'BBB'#14'BBB'
+ +#0'BBB'#0'BBB'#0'BBB'#0'BBB'#0'BBB'#0'BBB'#0'BBB'#0'BBB'#0'BBB'#0'BBB'#0#161
+ +'UB'#255#255#218#208#255#208'^B'#255#161'UB'#255#161'UB'#255'BBB'#0'BBB'#0'B'
+ +'BB'#0'BBB'#0'BBB'#0'BBB'#0'BBB'#0'BBB'#0'BBB'#0'BBB'#0#161'UB'#255#255#218
+ +#208#255#208'^B'#255#208'^B'#255#161'UB'#255#161'UB'#255'BBB'#0'BBB'#0'BBB'#0
+ +'BBB'#0'BBB'#0'BBB'#0'BBB'#0'BBB'#0#161'UB'#255#161'UB'#255#255#218#208#255
+ +#208'^B'#255#208'^B'#255#161'UB'#255#161'UB'#255#161'UB'#255'BBB'#0'BBB'#0'B'
+ +'BB'#0'BBB'#0'BBB'#0'BBB'#0'BBB'#0#161'UB'#255#255#218#208#255#161'UB'#255
+ +#208'^B'#255#208'^B'#255#161'UB'#255#161'UB'#255#161'UB'#255'BBBcBBB'#0'BBB'
+ +#0'BBB'#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0'BBB'#11#161
+ +'UB'#255#255#218#208#255#161'UB'#255#208'^B'#255#161'UB'#255#161'UB'#255'BBB'
+ +'cBBBLBBB'#0'BBB'#0'BBB'#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#131#131#131#255#255#255#255#255#161'UB'#255#255#218#208#255#161'UB'
+ +#255#161'UB'#255'BBBcBBBLBBB'#25'BBB'#0'BBB'#0'BBB'#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#131#131#131#255#255#255#255#255#229#229#229#255#161#161
+ +#161#255#161'UB'#255#255#218#208#255#161'UB'#255'BBBXBBB'#28'BBB'#3'BBB'#0'B'
+ +'BB'#0'BBB'#0#255#255#255#0#255#255#255#0#131#131#131#255#255#255#255#255#229
+ +#229#229#255#161#161#161#255#131#131#131#255'BBBc'#161'UB'#255'BBB`BBBJBBB'
+ +#14'BBB'#0'BBB'#0'BBB'#0'BBB'#0#255#255#255#0#131#131#131#255#255#255#255#255
+ +#229#229#229#255#161#161#161#255#131#131#131#255'BBBcBBBLBBB''BBB>BBB'#25'BB'
+ ,'B'#3'BBB'#0'BBB'#0'BBB'#0'BBB'#0#131#131#131#255#255#255#255#255#229#229#229
+ +#255#161#161#161#255#131#131#131#255'BBBcBBBLBBB'#25'BBB'#6'BBB'#11'BBB'#2'B'
+ +'BB'#0'BBB'#0'BBB'#0'BBB'#0#131#131#131#255#255#255#255#255#229#229#229#255
+ +#161#161#161#255#131#131#131#255'BBBcBBBLBBB'#25'BBB'#3'BBB'#0'BBB'#0'BBB'#0
+ +'BBB'#0'BBB'#0'BBB'#0#131#131#131#255#255#255#255#255#229#229#229#255#161#161
+ +#161#255#131#131#131#255'BBBcBBBLBBB'#25'BBB'#3'BBB'#0'BBB'#0'BBB'#0'BBB'#0
+ +'BBB'#0'BBB'#0'BBB'#0#131#131#131#255#229#229#229#255#161#161#161#255#131#131
+ +#131#255'BBBcBBBLBBB'#25'BBB'#3#255#255#255#0'BBB'#0'BBB'#0'BBB'#0'BBB'#0'BB'
+ +'B'#0'BBB'#0#131#131#131#255#229#229#229#255#131#131#131#255#131#131#131#255
+ +'BBBcBBBLBBB'#25'BBB'#3#255#255#255#0#255#255#255#0'BBB'#0'BBB'#0'BBB'#0'BBB'
+ +#0'BBB'#0'BBB'#0#131#131#131#255#131#131#131#255'BBB`BBBXBBBJBBB'#25'BBB'#3
+ +'BBB'#0'BBB'#0'BBB'#0'BBB'#0'BBB'#0'BBB'#0'BBB'#0'BBB'#0'BBB'#0#0#0#0#0#0#0#0
+ +#0#225#238#225#255#197#220#197#255#219#233#219#255#244#249#244#255#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#174#213#176#255#214#248#225#255#207#250#221#255#181#248#204#255'x'
+ +#216#145#255'@'#139'@'#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#202#225#202#255#197#247#213#255#156
+ +#244#185#255'}'#228#159#255#10'Y'#12#255#0#0#0#191#0#0#0#0#195#196#237#255#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#149#196#149#255#187
+ +#243#206#255#157#240#186#255'k'#212#142#255'N'#154'h'#255#10'D'#10#255#0#0#0
+ +#191#0#0#0#0#221#221#246#255'RW'#199#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#132#195#132#255#134#227#165#255'l'#224#146#255'K'#170'k'#255#1'/'#1#255
+ +'*Y:'#255'6U6'#255#0#0#0#191#0#0#0#0#0#0#0#0#177#180#234#255'=F'#197#255#0#0
+ +#0#0#0#0#0#0#0#0#0#0#232#243#232#255#136#221#159#255'D'#207'r'#255'&'#142'I'
+ +#255'4;4'#255'1:1'#255'!>+'#255'[r['#255#0#0#0#191#0#0#0#0#0#0#0#0#224#225
+ +#247#255'!6'#211#255#130#132#185#255#0#0#0#0#0#0#0#0'a'#177'a'#255'7'#198'^'
+ +#255'$'#153'J'#255'0I0'#255#0#0#0#191#0#0#0#191#9'@'#9#255#0#0#0#191#0#0#0
+ +#191#0#0#0#0#0#0#0#0#151#157#232#255#0#25#192#255#21#25'g'#255#0#0#0#0#0#0#0
+ +#0#27#142#27#255#22#139'.'#255';^;'#255#0#0#0#191#0#0#0#191#0#0#0#0#0#0#0#0
+ +'x'#135#241#255#0#0#0#0#0#0#0#0#185#191#246#255#0','#241#255#0#20'}'#255#17
+ +#20'4'#255#0#0#0#0#0#0#0#0'd'#140'd'#255#21'W"'#255'?D?'#255#0#0#0#191#0#0#0
+ +#0#0#0#0#0#194#201#249#255#161#189#254#255#235#237#253#255#233#235#253#255'3'
+ +'d'#254#255#2' '#147#255#0#11'<'#255'99?'#255#0#0#0#0#0#0#0#0#0#0#0#0#2'.'#3
+ +#255'$5$'#255#0#0#0#191#0#0#0#0#0#0#0#0#133#151#250#255#142#182#255#255'hz'
+ +#238#255'p'#155#251#255#17'5'#156#255#3#18'A'#255#6#10'3'#255#0#0#0#191#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#2''''#2#255'DLD'#255#0#0#0#0#0#0#0#0#16'2'#251#255
+ +'r'#178#255#255'c'#161#245#255'6\'#154#255#19'"A'#255#5#11'7'#255#0#0#0#191#0
+ +#0#0#191#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'=Q='#255#0#0#0#191#0#0#0#0#9
+ +'2'#181#255'S~'#161#255'5Rq'#255#26'+A'#255#23#28';'#255#0#0#0#191#0#0#0#191
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#191#0#0#0#0#23
+ +'$e'#255#30'/A'#255'(6A'#255#30'/A'#255#20'$A'#255#1#9'7'#255#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#191'::@'#255'%(='#255#6#13'8'#255'%(='#255#0#0#0#191#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0'Y'#170#131'HY'#170#131#171'Y'#170#131#210'Y'#170#131#255'Y'#170
+ +#131#213'Y'#170#131#174'Y'#170#131'Q'#255#255#255#0#255#255#255#0#255#255#255
+ +#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0'V'#167#128#24'V'
+ +#167#128#195'l'#179#146#255#168#213#195#255#197#230#219#255'q'#183#151#255
+ +#198#230#220#255#169#214#196#255'o'#181#148#255'V'#167#128#198'V'#167#128#30
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0'R'#162'}'#27'S'#163
+ +'~'#228#143#198#174#255#200#232#223#255#223#242#236#255#249#253#251#255'w'
+ +#184#153#255#248#252#251#255#220#241#235#255#199#231#222#255#147#200#178#255
+ +'U'#164#128#232'R'#162'}'#30#255#255#255#0#255#255#255#0#255#255#255#0'M'#157
+ +'x'#192#140#195#171#255#195#230#220#255#245#251#249#255#197#230#220#255#157
+ +#213#197#255'\'#170#135#255#159#214#197#255#201#232#223#255#244#250#249#255
+ +#192#228#217#255#147#199#178#255'M'#157'x'#204#255#255#255#0#255#255#255#0'H'
+ +#152'sQ`'#167#135#255#173#218#203#255#239#248#245#255#155#210#193#255#130#199
+ +#178#255#130#199#178#255'V'#164#130#255#130#199#178#255#130#199#178#255#156
+ ,#211#194#255#240#248#246#255#169#216#202#255'e'#170#139#255'H'#152'sT'#255
+ +#255#255#0'B'#145'n'#174#144#197#176#255#205#232#223#255#182#221#208#255'x'
+ +#193#169#255#141#202#182#255#228#243#238#255'i'#169#141#255#226#242#237#255
+ +#139#202#181#255'x'#193#169#255#185#223#210#255#200#229#220#255#149#200#181
+ +#255'B'#145'n'#180#255#255#255#0'<'#139'h'#219#129#194#170#255#241#249#246
+ +#255'|'#193#169#255'n'#187#160#255#229#243#238#255#171#216#200#255'u'#190#164
+ +#255#177#218#204#255#221#239#233#255'n'#187#160#255#129#196#172#255#240#248
+ +#245#255#129#194#172#255'<'#139'h'#231#255#255#255#0'6'#132'b'#240'A'#143'o'
+ +#255'^'#156#130#255'?'#142'm'#255'@'#142'n'#255'^'#156#130#255'd'#180#151#255
+ +'d'#180#151#255'h'#182#153#255']'#156#130#255'@'#142'n'#255'@'#142'n'#255']'
+ +#156#130#255'@'#142'n'#255';'#135'f'#249#255#255#255#0'/}]'#222'U'#168#136
+ +#255#241#248#246#255'n'#183#156#255'Y'#172#141#255#224#239#234#255#153#204
+ +#185#255'Y'#172#141#255#161#208#191#255#216#235#228#255'Y'#172#141#255'n'#183
+ +#156#255#237#246#243#255'X'#170#139#255'/}]'#231#255#255#255#0')vW'#171'H'
+ +#152'y'#255#189#221#209#255#168#211#194#255'O'#165#132#255'h'#178#149#255#216
+ +#235#228#255'S'#145'w'#255#209#232#223#255'f'#177#148#255'O'#165#132#255#174
+ +#214#199#255#183#218#204#255'F'#153'x'#255')vW'#180#255#255#255#0'#pQQ5'#129
+ +'c'#255'W'#168#135#255#237#246#243#255'l'#179#151#255'E'#159'{'#255'E'#159'{'
+ +#255'(wX'#255'E'#159'{'#255'E'#159'{'#255's'#183#156#255#242#248#246#255']'
+ +#171#140#255'8'#132'e'#255'#pQW'#255#255#255#0#255#255#255#0#29'iL'#204'0'
+ +#135'd'#255'r'#182#154#255#243#249#247#255#163#207#189#255'`'#172#141#255'!p'
+ +'Q'#255'e'#175#144#255#167#209#192#255#243#249#247#255'p'#181#152#255'1'#138
+ +'f'#255#29'iL'#180#255#255#255#0#255#255#255#0#255#255#255#0#24'dG!'#26'fI'
+ +#234')'#129']'#255'P'#162#128#255#176#213#198#255#238#246#243#255'C'#128'i'
+ +#255#236#245#241#255#173#212#196#255'M'#161'~'#255'*'#132'_'#255#27'gI'#235
+ +#24'dG'#27#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#19'_B'#21
+ +#19'_B'#174#26'lL'#255'%'#128'['#255'+'#141'd'#255#22'eG'#255','#141'e'#255
+ +'%'#129'['#255#27'nM'#255#19'_B'#183#19'_B'#27#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#15'Z?'
+ +'W'#15'Z?'#183#15'Z?'#246#15'Z?'#255#15'Z?'#246#15'Z?'#186#15'Z?]'#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#154'k''1'#170'~C'#161#146'`'#24#5#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#168'}Bi'#204#176#139#224#145']'#20#9#255#255#255#0#255#255#255#0#255#255#255
+ +#0#146'`'#23#6#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#170#129'G'
+ +'o'#214#189#159#247#147'a'#25#16#255#255#255#0#255#255#255#0#150'f ,'#169#128
+ +'K'#203#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#172#131'Ku'#222#201
+ +#175#255#149'd'#29#31#255#255#255#0#146'`'#23'&'#195#164'|'#235#181#144'c'
+ +#203#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#175#135'P|'#231#213
+ +#193#255#149'e'#31'+'#143'\'#18#27#197#167#131#231#213#188#157#225#181#147'd'
+ +'b'#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#177#137'S'#132#238#223
+ +#206#255#151'f e'#194#163'|'#218#233#216#197#253#169#130'N{'#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#179#140'W'#137#241#226
+ +#212#255#206#178#142#244#245#235#224#255#166#127'J'#157#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#0#11#136#2#255#255#255#0#180#142'Z'#144#246#234
+ +#221#255#225#205#180#255#177#141']'#191#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#3#13#140#31#27'&'#167#153'*4'#186#204#17#28#157#137#187#152'i'#204#240#224
+ +#208#255#183#145'_'#197#143']'#20#11#255#255#255#0#255#255#255#0#255#255#255
+ +#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#3#13#140#31',5'
+ +#185#215''#202#242'?L'#215#255#216#188#154#255#246#234#225#255
+ +#187#146'Z'#191#148'b'#24';'#145'a'#26#1#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#29'('#169#156';F'#204#255#8
+ +#18#144':'#7#17#144'S;H'#212#255#219#189#156#255#238#204#166#255'@L'#222#255
+ +':C'#209#255#15#25#152'i'#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0'2<'#195#236'#.'#173#175#255#255#255#0#26
+ ,'%'#168#153'BP'#210#255#203#163'u'#254'AO'#214#255#22'!'#163#157'/9'#192#212
+ +'.8'#190#223#2#13#139#10#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0'/:'#189#222'5?'#201#229'%0'#179#194'?J'#221#255#31'*'
+ +#172#194'$0'#178#203'2<'#198#242#0#10#134#3#17#27#157'w7A'#200#255#8#18#142
+ +' '#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#15
+ +#25#151'c2='#199#248'7A'#207#255#31')'#171#176#0#10#134#24'#-'#180#175'5@'
+ +#204#253#0#9#133#24#28''''#168#149'4>'#197#248#4#14#140#20#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#5#15#141
+ +#31#6#16#142'&'#1#11#138#3#255#255#255#0#18#28#155'p@K'#217#255',5'#191#221
+ +'=G'#209#255#29''''#169#164#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#2#13#140#10#28''''#166#159'5?'#201#247'"-'#175
+ +#185#3#13#140#28#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0'!!!'#0'eee'#0#139#139#139#0'%'#2#176#0'%'#2#178#0'%'#2
+ +#179#0'&'#2#181'7&'#2#180'{%'#2#180'|%'#2#179'8%'#2#175#0'$'#2#172#0'#'#2#168
+ +#0#0#0#0#0#29#29#29#0'\\\'#0#128#128#128#0#134#134#134#0#139#139#139#0'%'#2
+ +#176#0'%'#2#178#0'%'#2#179'8%'#2#179'|'#201#184#253#255#202#185#254#255'%'#2
+ +#177'~%'#2#175'9$'#2#172#0'#'#2#168#0'RRR'#0'sss'#0'yyy'#0#128#128#128#0#134
+ +#134#134#0#139#139#139#0'%'#2#176#0'%'#2#178'9%'#2#177'~'#198#181#252#255#182
+ +#165#236#255#184#167#236#255#202#185#254#255'$'#2#173#129'$'#2#172';#'#2#168
+ +#0'lll'#0'sss'#0'yyy'#0#128#128#128#0#134#134#134#0#139#139#139#0'%'#2#176'9'
+ +'%'#2#176#127#196#179#251#255#179#162#234#255#181#164#235#255#182#165#236#255
+ +#184#167#236#255#202#185#254#255'$'#2#169#134'#'#2#168'=lll'#0'sss'#0'yyy'#0
+ +#128#128#128#0#134#134#134#0#138#138#138'/'#136#136#136'f'#193#176#249#255
+ +#176#159#233#255#178#161#233#255#179#162#234#255#181#164#235#255#182#165#236
+ +#255#152#135#220#255#170#153#238#255'#'#2#165#138'lll'#0'sss'#0'yyy'#0#128
+ +#128#128#0#133#133#133'/'#131#131#131'f'#248#248#248#255#245#245#245#255#174
+ +#157#232#255#176#159#233#255#178#161#233#255#179#162#234#255#149#132#217#255
+ +#151#134#219#255#169#152#237#255'"'#2#161#141'lll'#0'sss'#0'yyy'#0#127#127
+ +#127'/}}}f'#246#246#246#255#242#242#242#255#242#242#242#255#242#242#242#255
+ +#174#157#232#255#176#159#233#255#146#129#214#255#148#131#216#255#166#149#234
+ +#255'"'#2#159#144'"'#2#159'Alll'#0'sss'#0'xxx/vvvf'#244#244#244#255#239#239
+ +#239#255#239#239#239#255#239#239#239#255#239#239#239#255#239#239#239#255#142
+ +'}'#210#255#144#127#212#255#163#146#231#255'!'#2#157#146'!'#2#156'B!'#2#158#0
+ +'lll'#0'rrr/pppf'#243#243#243#255#236#236#236#255#236#236#236#255#236#236#236
+ +#255#236#236#236#255#236#236#236#255#206#206#206#255#208#208#208#255#159#142
+ +#227#255'!'#2#155#149'!'#2#154'C!'#2#156#0'!'#2#158#0'kkk/iiif'#241#241#241
+ +#255#233#233#233#255#233#233#233#255#233#233#233#255#233#233#233#255#233#233
+ +#233#255#202#202#202#255#204#204#204#255#220#220#220#255'666f '#3#152'E!'#2
+ +#153#0'!'#2#156#0'!'#2#158#0'cccf'#240#240#240#255#230#230#230#255#230#230
+ +#230#255#230#230#230#255#230#230#230#255#230#230#230#255#198#198#198#255#200
+ +#200#200#255#216#216#216#255'''''''f###/ '#3#151#0'!'#2#153#0#25#2'u'#0#17#1
+ +'O'#0'XXXf'#240#240#240#255#227#227#227#255#227#227#227#255#227#227#227#255
+ +#227#227#227#255#194#194#194#255#196#196#196#255#212#212#212#255#26#26#26'f'
+ +#22#22#22'/ '#0#24#3'q'#0#8#1'&'#0#0#0#0#0#0#0#0#0'HHH/===f'#240#240#240
+ +#255#225#225#225#255#225#225#225#255#191#191#191#255#192#192#192#255#209#209
+ +#209#255#15#15#15'f'#12#12#12'/'#15#15#15#0#8#8#8#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#16#16#16#0#30#30#30'/ f'#223#223#223#255#206#206#206#255#206#206#206
+ +#255#206#206#206#255#5#5#5'f'#2#2#2'/'#2#2#2#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#17#0#0#0'&'#9#9#9'H'#10#10#10'f'#5#5#5'f'#2#2#2'f'#1
+ +#1#1'f'#0#0#0'@'#0#0#0#30#0#0#0#25#0#0#0#19#0#0#0#14#0#0#0#9#0#0#0#5#0#0#0#2
+ +#0#0#0#0#0#0#0#9#0#0#0#19#0#0#0#26#0#0#0#25#0#0#0#24#0#0#0#22#0#0#0#20#0#0#0
+ +#18#0#0#0#15#0#0#0#13#0#0#0#10#0#0#0#7#0#0#0#5#0#0#0#3#0#0#0#1#0#0#0#0#238
+ +#238#238#0#238#238#238#0#238#238#238#0#153'nL'#255#171'qC'#255#172'rD'#255
+ +#153'nL'#255#251#227#188#0#251#227#188#0#153'nL'#255#171'qC'#255#172'rD'#255
+ +#153'nL'#255#0#0#0#0#0#0#0#0#0#0#0#0#153'nL'#0#153'nL'#0#153'nL'#0#162'f7'
+ +#255#220#191#164#255#223#198#175#255#162'f7'#255#153'nL'#0#153'nL'#0#162'f7'
+ +#255#220#191#164#255#223#198#175#255#162'f7'#255#0#0#0#0#0#0#0#0#0#0#0#0#164
+ +'e4'#0#164'e4'#0#164'e4'#0#164'e4'#255#221#188#157#255#231#209#188#255#164'e'
+ +'4'#255#164'e4'#0#164'e4'#0#164'e4'#255#221#188#157#255#231#209#188#255#164
+ +'e4'#255#0#0#0#0#0#0#0#0#0#0#0#0#164'e4'#0#164'e4'#0#164'e4'#0#164'e4'#255
+ +#219#182#148#255#231#209#187#255#164'e4'#255#164'e4'#0#164'e4'#0#164'e4'#255
+ +#219#182#148#255#231#209#187#255#164'e4'#255#0#0#0#0#0#0#0#0#0#0#0#0#164'e4'
+ +#0#164'e4'#0#164'e4'#0#164'e4'#255#218#181#147#255#230#207#185#255#164'e4'
+ ,#255#164'e4'#0#164'e4'#0#164'e4'#255#218#181#147#255#230#207#185#255#164'e4'
+ +#255#0#0#0#0#0#0#0#0#0#0#0#0#164'e4'#0#164'e4'#0#164'e4'#0#164'e4'#255#218
+ +#179#145#255#230#206#183#255#164'e4'#255#164'e4'#0#164'e4'#0#164'e4'#255#218
+ +#179#145#255#230#206#183#255#164'e4'#255#0#0#0#0#0#0#0#0#0#0#0#0#164'e4'#0
+ +#164'e4'#0#164'e4'#0#164'e4'#255#217#178#143#255#230#206#183#255#164'e4'#255
+ +#164'e4'#0#164'e4'#0#164'e4'#255#217#178#143#255#230#206#183#255#164'e4'#255
+ +#0#0#0#0#0#0#0#0#0#0#0#0#164'e4'#0#164'e4'#0#164'e4'#0#164'e4'#255#217#176
+ +#141#255#230#206#183#255#164'e4'#255#164'e4'#0#164'e4'#0#164'e4'#255#217#176
+ +#141#255#230#206#183#255#164'e4'#255#0#0#0#0#0#0#0#0#0#0#0#0#164'e4'#0#164'e'
+ +'4'#0#164'e4'#0#164'e4'#255#217#174#137#255#230#206#183#255#164'e4'#255#164
+ +'e4'#0#164'e4'#0#164'e4'#255#217#174#137#255#230#206#183#255#164'e4'#255#0#0
+ +#0#0#0#0#0#0#0#0#0#0#164'e4'#0#164'e4'#0#164'e4'#0#164'e4'#255#216#171#132
+ +#255#230#206#183#255#164'e4'#255#164'e4'#0#164'e4'#0#164'e4'#255#216#171#132
+ +#255#230#206#183#255#164'e4'#255#0#0#0#0#0#0#0#0#0#0#0#0#164'e4'#0#164'e4'#0
+ +#164'e4'#0#164'e4'#255#215#169#129#255#230#205#182#255#164'e4'#255#164'e4'#0
+ +#164'e4'#0#164'e4'#255#215#169#129#255#230#205#182#255#164'e4'#255#0#0#0#0#0
+ +#0#0#0#0#0#0#0#164'e4'#0#164'e4'#0#164'e4'#0#164'e4'#255#215#167#127#255#230
+ +#204#181#255#164'e4'#255#164'e4'#0#164'e4'#0#164'e4'#255#215#167#127#255#230
+ +#204#181#255#164'e4'#255#0#0#0#0#0#0#0#0#0#0#0#0#164'e4'#0#164'e4'#0#164'e4'
+ +#0#164'e4'#255#216#169#129#255#230#204#181#255#164'e4'#255#164'e4'#0#164'e4'
+ +#0#164'e4'#255#216#169#129#255#230#204#181#255#164'e4'#255#0#0#0#0#0#0#0#0#0
+ +#0#0#0#162'f8'#0#162'f8'#0#162'f8'#0#163'e5'#255#215#172#136#255#225#197#173
+ +#255#163'e5'#255#162'f8'#0#162'f8'#0#163'e5'#255#215#172#136#255#225#197#173
+ +#255#163'e5'#255#0#0#0#0#0#0#0#0#0#0#0#0#152'pP'#0#152'pP'#0#152'pP'#0#159'h'
+ +'>'#255#201#156'v'#255#205#165#133#255#159'h>'#255#152'pP'#0#152'pP'#0#159'h'
+ +'>'#255#201#156'v'#255#205#165#133#255#159'h>'#255#0#0#0#0#0#0#0#0#0#0#0#0
+ +#238#238#238#0#238#238#238#0#238#238#238#0#152'pP'#255#164'e4'#255#164'e4'
+ +#255#152'pP'#255#251#227#188#0#251#227#188#0#152'pP'#255#164'e4'#255#164'e4'
+ +#255#152'pP'#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#4's:'#255'-'#136'Y'
+ +#255#133#156#144#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#4's:'#255#164#217#190#255'='
+ +#147'f'#255'_'#136's'#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#4's:'#255#169#220#193#255#155
+ +#213#183#255'L'#159's'#255'=}\'#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#4's:'#255#165#218#191#255'W'
+ +#187#135#255#144#210#176#255'['#171#130#255'#wL'#255#212#213#212#255#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#4's:'#255
+ +#169#220#193#255'E'#180'{'#255'G'#180'|'#255#130#204#166#255'g'#182#140#255
+ +#23'wE'#255#193#197#195#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#4's:'#255#169#220#193#255'>'#177'v'#255':'#175's'#255'6'#174
+ +'p'#255'o'#197#152#255'q'#191#151#255#24'{I'#255#166#176#171#255#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#4's:'#255#169#220#193#255'6'#173
+ +'p'#255'2'#172'm'#255'-'#170'j'#255'('#168'f'#255'X'#188#137#255'x'#197#157
+ +#255#31#128'N'#255#131#154#142#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#4's:'#255#169#220#193#255'.'#173'k'#255'+'#173'j'#255''''#171'h'#255
+ +'"'#169'd'#255#28#165'_'#255'A'#178'x'#255'x'#198#159#255')'#136'X'#255'g'
+ +#140'y'#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#4's:'#255#169#220#193#255
+ +#12#170'X'#255#18#174'^'#255#21#175'`'#255#22#173'a'#255#19#170']'#255':'#182
+ +'w'#255'u'#199#157#255'('#137'W'#255'N'#131'g'#255#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#4's:'#255#169#220#193#255#13#179'^'#255#14#182'`'#255#14#182
+ +'`'#255#13#180'_'#255'G'#196#132#255'p'#202#156#255#29#130'M'#255'g'#140'y'
+ +#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#4's:'#255#169#220#193
+ +#255#16#189'e'#255#17#193'g'#255#19#194'i'#255'Y'#211#149#255'g'#201#152#255
+ +#22'|G'#255#136#156#146#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#4's:'#255#131#220#175#255#17#195'i'#255#26#204's'#255'i'#223#163#255
+ +'Z'#194#141#255#19'vC'#255#158#167#163#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#9'w?'#255#131#219#174#255#31#198'q'#255'r'#222
+ +#167#255'K'#178#127#255#23'tE'#255#168#173#170#255#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#4's:'#255#130#216#172#255'v'
+ +#214#166#255'<'#157'j'#255'''tL'#255#172#174#173#255#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#4's:'#255'z'#207#164
+ +#255','#140'Z'#255'=vY'#255#174#174#174#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#4's:'#255'!'#130'O'
+ +#255'c'#130'r'#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ ,#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0'EP'#191#230'EP'#191
+ +#230'EP'#191#230'EP'#191#230'EP'#191#230'EP'#191#230'EP'#191#230'EP'#191#230
+ +'EP'#191#230'EP'#191#230'EP'#191#230'EP'#191#230#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0'EP'#191#230#209#212#241#255#204#208#242#255#198
+ +#203#242#255#191#197#242#255#183#190#243#255#174#184#243#255#165#175#244#255
+ +#155#168#244#255#145#159#245#255#135#149#246#255'99'#134#230#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0'EP'#191#230#204#208#241#255#198
+ +#203#241#255#191#197#242#255#183#191#243#255#175#183#244#255#166#175#245#255
+ +#155#168#245#255#145#159#246#255#135#150#246#255'}'#141#247#255'99'#134#230
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0'EP'#191#230#199#202
+ +#241#255#191#197#243#255#183#190#243#255#174#183#244#255#166#175#244#255#155
+ +#167#245#255#146#159#246#255#135#150#246#255'|'#141#247#255'r'#132#247#255'9'
+ +'9'#134#230#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0'EP'#191
+ +#230#191#197#242#255#183#190#243#255#175#183#244#255#165#175#244#255#156#167
+ +#245#255#146#159#246#255#135#149#246#255'}'#141#247#255'r'#132#248#255'h|'
+ +#248#255'99'#134#230#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +'EP'#191#230#183#190#243#255#175#183#244#255#166#176#244#255#155#168#245#255
+ +#146#159#246#255#135#150#246#255'|'#141#247#255'r'#132#248#255'g{'#248#255']'
+ +'s'#249#255'99'#134#230#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255
+ +#0'EP'#191#230#174#183#243#255#165#175#245#255#156#167#245#255#145#159#245
+ +#255#135#150#247#255'|'#141#247#255'r'#132#248#255'h{'#249#255']s'#249#255'S'
+ +'k'#250#255'99'#134#230#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255
+ +#0'EP'#191#230#166#175#244#255#156#167#245#255#145#159#245#255#135#150#246
+ +#255'}'#141#247#255'q'#132#247#255'h|'#248#255']s'#249#255'Tj'#250#255'Jc'
+ +#251#255'99'#134#230#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +'EP'#191#230#155#167#245#255#146#159#245#255#135#150#247#255'|'#141#247#255
+ +'r'#132#248#255'g|'#248#255'^s'#249#255'Tk'#250#255'Jc'#251#255'A\'#251#255
+ +'99'#134#230#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0'EP'#191
+ +#230#146#158#245#255#135#150#246#255'|'#141#247#255'r'#133#248#255'h|'#249
+ +#255'^s'#249#255'Tk'#250#255'Kc'#251#255'B\'#251#255'9U'#252#255'99'#134#230
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0'EP'#191#230#135#150
+ +#246#255'|'#141#247#255'r'#132#248#255'h|'#248#255'^s'#250#255'Sj'#250#255'J'
+ +'c'#250#255'B\'#251#255':U'#252#255'3O'#252#255'99'#134#230#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0'EP'#191#230'99'#134#230'99'#134#230'9'
+ +'9'#134#230'99'#134#230'99'#134#230'99'#134#230'99'#134#230'99'#134#230'99'
+ +#134#230'99'#134#230'99'#134#230#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0'zXA'#7'zU='#6
+ +'|V='#4'{W='#6'zX@%{Y@''yXB'#10#0#0#0#0'@C_'#4#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'{W='#0'wU>'#13#171'i'#27
+ +#26'KF[m'#6'6'#171#223#2'5'#173#255#2'6'#176#251#6'+'#141#164#0#0#0#0'"0c'#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'<@h'#29#25'8'#142
+ +#207#9'.'#142#253#1'5'#177#255#4'('#148#255#2'/'#159#254#1'2'#171#255#6'$|'
+ +#135#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#15'6'
+ +#157#188#1')'#154#255#3'0'#166#255#4'%'#145#254#5'('#137#255#1#23'u'#255#1'1'
+ +#171#254#1''''#145#255#7#30'j'#171#0#0#0#0#3#27'm'#0#0#0#0#0#0#0#0#0#127'rf'
+ +#0#0#0#0#0#0#9#154#1#3'2'#172#226#15':'#133#241#11'v'#234#255#11'~'#240#255
+ +#18'\'#171#255#9'q'#229#255#3'('#148#255#0','#162#254#0#25'm'#255#5#27'k'#221
+ +#19'&f"'#0#0#0#0#0#0#0#0'sf['#6'uli'#29'gkz!'#8'A'#183#239#19'~'#236#255#12
+ +#137#255#254#23'p'#207#255'*x'#200#255#10'{'#243#255#5'K'#186#255#0'+'#160
+ +#255#4'*'#131#255#0#25'm'#254#2#23'f'#255#17#29'_$tz'#137#6'pjd*xdW(Td'#130
+ +'c!'#128#229#255#22'\'#179#255#25'a'#187#255'3'#149#249#255#9'y'#243#255#5'y'
+ +#248#255#3'y'#252#255#4'3'#158#255#5')'#146#255#2'!v'#255#0#20'b'#255#3#20'_'
+ +#200'|'#136#177#11#129#138#170')y'#140#159'''B'#143#222#189#18'M'#161#255#14
+ ,'/h'#255'4'#136#229#255'7'#154#255#255#20'z'#235#255#3'w'#246#255#3's'#238
+ +#255#2']'#209#255#2#21't'#255#3'!'#138#255#2#20'h'#255#1#15'['#237'z'#134#165
+ +'$p'#139#169#24'n'#144#186#31'H'#152#231#198'5'#145#238#255':'#155#255#255'4'
+ +#149#251#255'2'#134#231#255' '#130#242#255#0'u'#244#255#0's'#238#255#0'o'#232
+ +#255#2#22'w'#255#1'!'#139#255#1#26'}'#255#1#11'V'#255#0#0#0#0#129#144#164#5#0
+ +#0#0#0'L'#150#224#165'7'#148#248#255'4'#147#250#255'/'#142#249#255'/'#141#249
+ +#255#30#135#248#255#2'v'#241#255#0'q'#235#255#1'a'#211#255#1#28#132#255#1#30
+ +#133#255#0#27#127#255#1#12'['#255#0#0#0#0#0#0#0#0#0#0#0#0'?'#147#236#172'2'
+ +#148#255#255'0'#145#254#255'/'#143#252#255'+'#134#239#255#5'&'#136#255#2#21
+ +'q'#255#5'0'#144#255#3'<'#158#255#0#29#134#255#2#25'y'#255#0#27#127#255#0#10
+ +'Z'#255#0#0#0#0#0#0#0#0#0#0#0#0'(`'#185#141'.'#139#250#255'+'#134#239#255' m'
+ +#212#255#3','#149#255#0#25'|'#255#1#21's'#255#0#20's'#255#2#26'}'#255#0#28
+ +#129#255#2#24'v'#255#0#23'z'#255#0#9'X'#255#0#0#0#0#0#0#0#0#0#0#0#0#15','#136
+ +#137#1''''#153#255#1'$'#145#255#0'#'#146#255#0'$'#145#255#0#23'x'#255#2#19'o'
+ +#255#2#26'|'#255#1#27'~'#255#1#25'{'#255#1#19'r'#255#1#20'r'#255#1#6'O'#255#0
+ +#0#0#0#0#0#0#0#0#0#0#0#25'*u*'#2'#'#139#255#2'"'#139#255#0'#'#143#255#1#28
+ +#129#255#2#23'w'#255#1#28#127#255#0#27'~'#255#0#24'z'#255#1#17'l'#255#1#14'i'
+ +#255#0#11'a'#255#0#5'A'#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#255#255#255#0#193'}D`'
+ +#200#139'M'#187#200#140'O'#238#200#140'O'#246#200#140'O'#247#200#140'O'#247
+ +#200#141'O'#247#201#140'O'#247#199#139'O'#247#197#137'K'#212#196'v;'#145#179
+ +'h<'#6#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#196#133'I'#195
+ +#247#242#236#236#248#244#238#252#248#244#237#255#248#243#237#255#248#243#237
+ +#255#248#243#237#255#248#242#236#255#247#242#236#255#242#230#215#255#226#178
+ +'}'#255#219#148'e'#245#179'h;'#7#255#255#255#0#255#255#255#0#255#255#255#0
+ +#197#136'K'#234#250#246#242#252#250#224#199#255#251#225#201#255#251#226#201
+ +#255#251#224#200#255#249#223#197#255#248#219#193#255#244#214#184#255#255#251
+ +#248#255#246#216#180#255#225#176'}'#255#219#146'd'#246#180'k>'#7#255#255#255
+ +#0#255#255#255#0#198#137'L'#246#249#245#241#255#252#227#205#255#251#227#206
+ +#255#251#227#205#255#251#226#203#255#249#224#200#255#248#220#194#255#245#214
+ +#186#255#253#251#248#255#252#230#205#255#250#229#201#255#226#182#132#255#191
+ +'yB'#166#255#255#255#0#255#255#255#0#198#137'K'#247#249#245#241#255#252#227
+ +#207#255#251#228#208#255#252#228#207#255#252#227#205#255#250#225#202#255#249
+ +#221#196#255#246#217#188#255#244#233#223#255#247#242#236#255#251#247#243#255
+ +#245#239#233#255#194'~E'#251#255#255#255#0#255#255#255#0#198#137'K'#247#249
+ +#244#240#255#252#230#211#255#252#230#212#255#253#231#211#255#252#228#209#255
+ +#251#227#205#255#250#224#200#255#248#220#194#255#245#214#187#255#243#212#181
+ +#255#241#210#179#255#248#244#240#255#196#130'F'#247#255#255#255#0#255#255#255
+ +#0#198#136'J'#247#249#244#239#255#254#231#215#255#253#231#214#255#253#231#213
+ +#255#253#230#212#255#252#230#210#255#251#225#204#255#250#223#199#255#248#220
+ +#194#255#246#218#189#255#246#216#187#255#250#244#239#255#198#131'F'#247#255
+ +#255#255#0#255#255#255#0#198#136'I'#247#249#244#237#255#254#232#216#255#254
+ +#232#216#255#254#232#215#255#254#231#214#255#253#229#211#255#252#228#209#255
+ +#251#225#204#255#250#224#199#255#249#221#195#255#248#220#194#255#250#244#237
+ +#255#198#130'E'#247#255#255#255#0#255#255#255#0#198#132'G'#247#249#243#236
+ +#255#254#232#214#255#254#232#215#255#253#231#214#255#253#231#214#255#253#231
+ +#213#255#253#229#211#255#251#228#208#255#251#227#204#255#250#223#199#255#250
+ +#223#198#255#250#242#234#255#198#128'B'#247#255#255#255#0#255#255#255#0#197
+ +#130'E'#247#248#242#235#255#254#231#214#255#253#231#214#255#253#231#214#255
+ +#253#231#214#255#253#230#213#255#253#229#211#255#252#228#209#255#252#226#205
+ +#255#251#225#203#255#251#225#201#255#251#247#242#255#197'|?'#247#255#255#255
+ +#0#255#255#255#0#197#128'B'#247#248#241#232#255#254#229#213#255#253#229#211
+ +#255#253#229#211#255#252#229#211#255#252#229#211#255#252#228#209#255#252#226
+ +#206#255#252#226#204#255#251#224#201#255#251#225#200#255#253#250#247#255#193
+ +'v;'#247#255#255#255#0#255#255#255#0#196'|@'#247#247#240#230#255#248#180'U'
+ +#255#247#180'V'#255#247#181'T'#255#248#180'S'#255#248#178'S'#255#247#179'R'
+ +#255#247#179'R'#255#247#178'Q'#255#247#178'O'#255#247#178'O'#255#252#249#245
+ +#255#191'o6'#247#255#255#255#0#255#255#255#0#193'x<'#247#247#237#227#255#253
+ +#194'n'#255#255#216#160#255#255#215#158#255#255#214#155#255#255#215#152#255
+ +#255#214#150#255#255#214#149#255#255#213#148#255#255#212#147#255#251#190'e'
+ +#255#251#247#244#255#187'g1'#247#255#255#255#0#255#255#255#0#191'q8'#245#245
+ +#235#223#254#253#191'h'#255#252#189'g'#255#251#190'e'#255#252#190'd'#255#252
+ ,#190'd'#255#252#189'b'#255#251#189'c'#255#251#188'a'#255#252#190'`'#255#252
+ +#188'b'#255#253#251#248#253#185'd-'#243#255#255#255#0#255#255#255#0#188'i3'
+ +#222#248#241#234#242#247#236#223#253#246#235#222#255#246#234#222#255#246#234
+ +#220#255#246#234#220#255#250#243#235#255#250#243#235#255#250#242#234#255#252
+ +#247#243#255#252#248#244#253#254#254#253#240#183'`*'#213#255#255#255#0#255
+ +#255#255#0#187'j4k'#186'e0'#188#187'f1'#237#186'f0'#247#186'f0'#247#186'f0'
+ +#247#186'e0'#247#186'e/'#247#185'e.'#247#185'e.'#247#185'd.'#247#185'd.'#239
+ +#183'b,'#189#183'b.c'#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#234#195#157#255#230#191#150#255
+ +#228#187#146#255#228#187#146#255#209#160'l'#245#208#158'm'#246#204#150'_'#218
+ +#196'yB~'#178'g<'#9#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#229#190#150#255#255#255#254#255
+ +#253#243#233#255#253#243#234#255#252#242#232#255#250#239#227#255#250#242#231
+ +#255#234#187#136#255#207#133'U'#179#180'i='#12#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#228#187#147#255#254
+ +#245#237#255#252#222#197#255#251#224#199#255#249#220#194#255#245#211#180#255
+ +#254#249#243#255#250#226#196#255#236#193#147#255#195'}H'#147#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#228
+ +#187#146#255#254#246#240#255#252#226#205#255#252#227#205#255#250#223#200#255
+ +#247#217#188#255#245#233#221#255#250#243#235#255#251#248#243#255#202#131'S'
+ +#254#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#228#187#146#255#254#247#241#255#252#229#210#255#252#228#209
+ +#255#251#226#204#255#249#221#196#255#246#215#187#255#243#209#175#255#250#239
+ +#228#255#204#135'X'#254'4'#180#217#208'^'#194#225#250'`'#195#226#250'`'#195
+ +#226#250'`'#195#226#250'_'#195#226#250#228#187#145#255#255#247#242#255#254
+ +#231#213#255#254#231#213#255#253#229#209#255#250#224#202#255#249#222#196#255
+ +#247#217#188#255#253#242#231#255#204#135'W'#254'6'#179#218#248#253#254#254
+ +#255#254#255#255#255#254#254#255#255#253#254#255#255#254#255#255#255#228#186
+ +#145#255#255#247#240#255#255#231#213#255#253#231#214#255#253#230#212#255#252
+ +#228#208#255#251#227#203#255#250#220#194#255#254#243#232#255#204#134'V'#254
+ +'5'#175#218#240#247#252#254#255#142#228#248#255#145#222#245#255#159#224#245
+ +#255#172#225#246#255#202#132'R'#255#255#247#241#255#255#233#217#255#255#234
+ +#219#255#255#233#217#255#255#231#215#255#255#229#210#255#255#226#203#255#255
+ +#247#241#255#203#133'U'#254'6'#170#218#242#241#250#253#255#148#222#245#255
+ +#147#220#244#255'd'#188#233#255'5'#148#218#255'5'#148#218#255'5'#148#218#255
+ +'5'#148#218#255'5'#148#218#255'5'#148#218#255'5'#148#218#255'5'#148#218#255
+ +'5'#148#218#255#251#246#239#255#204#131'U'#254'5'#171#218#250#232#246#251#255
+ +'p'#188#231#255'U'#170#226#255'M'#165#224#255#145#201#235#255#250#243#239#255
+ +#253#254#253#255#255#253#252#255#255#253#252#255#254#253#252#255#254#252#251
+ +#255#254#254#253#255'5'#148#218#255#239#242#232#255#206#129'V'#255'7'#166#218
+ +#250#254#255#255#255#248#253#255#255#246#253#255#255#245#252#255#255#243#252
+ +#254#255#154#228#244#255#154#230#247#255#155#230#246#255#157#229#245#255#158
+ +#229#245#255#159#229#244#255#218#243#248#255'5'#148#218#255#253#244#238#255
+ +#202#128'T'#249'6'#161#218#249#246#252#254#255#148#229#248#255#147#229#248
+ +#255#147#229#248#255#145#229#248#255#147#219#233#255#147#215#227#255#147#210
+ +#220#255#144#206#215#255#140#200#207#255#134#193#198#255#201#216#214#255'5'
+ +#148#218#255#197'tD'#232#202#127'S'#241'6'#154#218#248#242#250#253#255#148
+ +#230#248#255#146#229#248#255#144#229#248#255#139#227#248#255#134#226#247#255
+ +#127#225#247#255'w'#222#246#255'l'#220#246#255'^'#217#244#255'O'#213#243#255
+ +#204#242#251#255'5'#148#218#255#255#255#255#0#255#255#255#0'5'#148#218#247
+ +#239#250#254#255#147#229#248#255#143#228#248#255#137#227#248#255#130#225#247
+ +#255'z'#223#247#255'q'#222#246#255'g'#219#245#255'['#216#244#255'M'#212#243
+ +#255'@'#209#242#255#202#242#251#255'5'#148#218#255#255#255#255#0#255#255#255
+ +#0'3'#142#217#251#220#240#250#255#152#225#246#255#149#224#246#255#146#223#246
+ +#255#142#222#245#255#137#220#245#255#133#218#244#255#128#217#244#255'z'#215
+ +#243#255't'#213#243#255'p'#211#242#255#194#234#248#255'5'#148#218#255#255#255
+ +#255#0#255#255#255#0','#134#216#209'-'#136#216#247'-'#135#216#247'-'#136#216
+ +#247'-'#136#216#247'-'#136#216#247'-'#136#216#247'-'#136#216#247'-'#136#216
+ +#247'-'#136#216#247'-'#136#216#247'-'#135#216#247'-'#136#216#247','#134#216
+ +#209#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0' c'#152'* c'#152
+ +#255' c'#152#255' c'#152#255' c'#152#255' c'#152#255' c'#152#240#255#255#255
+ +#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0' c'#152'2 c'#152#178' c'#152#255'7u'#164#255#182#239#254#255#128
+ +#219#243#255#128#219#243#255#182#239#254#255'.n'#161#255' c'#152#255' c'#152
+ ,#165' c'#152'S'#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0' c'
+ +#152#224'q'#179#219#254'~'#191#228#255'N'#157#223#255#181#238#253#255'u'#212
+ +#240#255'u'#212#240#255#181#238#253#255'K'#155#222#255'n'#180#224#255'm'#179
+ +#223#249' c'#152#243#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +' c'#152#255#127#191#228#255'i'#178#222#255'J'#155#218#255'D'#151#220#255'C'
+ +#150#220#255'B'#150#220#255'B'#149#220#255'A'#149#219#255'Q'#158#214#255'l'
+ +#178#222#255' c'#152#255#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0' c'#152#255'|'#189#228#255'e'#174#221#255'b'#171#220#255'^'#168#218
+ +#255'\'#167#217#255'\'#167#217#255'\'#167#217#255'\'#167#217#255'R'#159#215
+ +#255'b'#163#216#255' c'#152#255#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0' c'#152#255'z'#187#227#255'a'#170#219#255'Z'#165#217#255'S'#160
+ +#215#255'R'#159#215#255'R'#159#215#255'R'#159#215#255'R'#159#215#255'R'#159
+ +#215#255'b'#163#216#255' c'#152#255#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0' c'#152#255'v'#185#226#255'\'#167#217#255'X'#164#216#255'S'
+ +#160#215#255'S'#158#213#255'a'#139#169#255'd'#136#161#255'd'#135#161#255'c'
+ +#134#160#255'i'#135#159#255'Jh'#129#255'jjj'#138'hhh'#138'eee'#138'bbbc c'
+ +#152#255's'#183#225#255'W'#163#215#255'S'#160#215#255'P'#157#213#255'R'#153
+ +#207#255'u'#148#172#255#248#248#248#255#242#242#242#255#242#242#242#255#242
+ +#242#242#255#242#242#242#255#242#242#242#255#241#241#241#255#244#244#244#250
+ +'^^^'#132' c'#152#255'p'#181#224#255'R'#159#215#255'P'#156#214#255'N'#152#212
+ +#255'O'#149#205#255's'#145#170#255#241#241#241#255#183#183#183#255#182#182
+ +#182#255#182#182#182#255#182#182#182#255#181#181#181#255#181#181#181#255#238
+ +#238#238#250'ZZZ'#132' c'#152#255'm'#179#223#255'P'#156#213#255'N'#152#211
+ +#255'K'#148#209#255'L'#145#203#255'p'#142#167#255#241#241#241#255#233#233#233
+ +#255#233#233#233#255#232#232#232#255#232#232#232#255#232#232#232#255#231#231
+ +#231#255#237#237#237#250'VVV'#132' c'#152#255'k'#177#222#255'M'#151#211#255
+ +'K'#147#210#255'H'#143#208#255'J'#140#201#255'o'#139#165#255#241#241#241#255
+ +#182#182#182#255#181#181#181#255#181#181#181#255#180#180#180#255#180#180#180
+ +#255#180#180#180#255#237#237#237#250'SSS'#132' c'#152#255'i'#174#220#255'J'
+ +#147#209#255'H'#143#208#255'F'#139#206#255'G'#136#199#255'l'#136#163#255#240
+ +#240#240#255#232#232#232#255#232#232#232#255#231#231#231#255#231#231#231#255
+ +#231#231#231#255#231#231#231#255#237#237#237#250'OOO'#132' c'#152#255'h'#171
+ +#220#255'H'#142#207#255'F'#139#206#255'C'#135#205#255'D'#132#198#255'h'#133
+ +#161#255#240#240#240#255#180#180#180#255#180#180#180#255#180#180#180#255#180
+ +#180#180#255#180#180#180#255#179#179#179#255#237#237#237#250'LLL'#132' c'#152
+ +#194'b'#165#215#255'e'#168#218#255'd'#166#217#255'b'#164#216#255'b'#159#209
+ +#255'u'#142#164#255#239#239#239#255#231#231#231#255#231#231#231#255#231#231
+ +#231#255#231#231#231#255#230#230#230#255#230#230#230#255#236#236#236#250'III'
+ +#132' c'#152'J c'#152#207' c'#152#255' c'#152#255' c'#152#255'$c'#149#255'Xs'
+ +#136#255#247#247#247#255#240#240#240#255#240#240#240#255#240#240#240#255#240
+ +#240#240#255#240#240#240#255#240#240#240#255#243#243#243#250'FFF'#132#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0'^^^'#2'[[[wXX'
+ +'X'#138'UUU'#138'RRR'#138'OOO'#138'LLL'#138'JJJ'#138'HHH'#138'FFF'#138'DDDf'
+ +#255#255#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#160#196#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#255#255#255
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#160#196
+ +#255#0#160#196#255#0#157#191#20#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#255#255#255#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#160#196
+ +#255#173#243#251#255#0#160#196#255#5'y}'#17#0#0#0#0#0#0#0#0#0#0#0#0#255#255
+ +#255#0#0#0#0#0#0#0#0#0#0#0#0#0#6'z|'#11#27#161#187#164#21#159#187#207#19#161
+ +#190#231#0#160#196#255#0#160#196#255'%'#228#251#255#173#243#251#255#0#160#196
+ +#255#5'y}'#17#0#0#0#0#0#0#0#0#255#255#255#0#0#0#0#0#0#0#0#0#5'y}'#28#20#163
+ +#193#213#20#161#188#212'l'#232#247#248'n'#232#247#255'o'#235#250#255's'#236
+ +#250#255' '#227#250#255'1'#225#246#255#173#243#251#255#0#160#196#255#5'y}'#17
+ +#0#0#0#0#255#255#255#0#0#0#0#0#5'y}2'#19#163#193#228'A'#206#227#254'i'#231
+ +#246#255'6'#217#236#255#22#205#227#255')'#219#241#255'/'#224#245#255')'#219
+ +#241#255'2'#226#247#255'/'#224#246#255#173#243#251#255#0#160#196#255#5'y}'#10
+ +#255#255#255#0#5'y}'#10#22#161#189#202'@'#205#225#255'6'#217#236#255#29#210
+ +#232#255#29#210#232#255#29#210#232#255')'#219#241#255'/'#224#245#255'2'#226
+ +#247#255'2'#226#247#255'2'#226#248#255'/'#224#246#255#173#243#251#255#0#160
+ +#196#255#255#255#255#0#21#160#188#203#27#171#197#248'j'#229#243#255#11#200
+ +#223#255#29#210#232#255#29#210#232#255#29#210#232#255#4#192#214#255#4#192#214
+ +#255#4#192#214#255','#223#244#255'2'#226#248#255'y'#237#251#255#0#160#196#255
+ +#5'y~'#17#255#255#255#0#27#163#191#244'o'#220#235#255#7#194#216#255#10#200
+ ,#223#255#5#221#247#255'i'#234#249#255'i'#234#249#255'i'#234#249#255'i'#234
+ +#249#255'v'#237#251#255#4#195#218#255'v'#237#251#255#0#160#196#255#5'y}'#17#0
+ +#0#0#0#255#255#255#0#26#164#192#248'i'#228#242#255#15#201#223#255'n'#225#238
+ +#255#1#169#196#255#0#160#196#255#0#160#196#255#0#160#196#255#0#160#196#255'v'
+ +#237#251#255'v'#237#251#255#0#160#196#255#5'y}'#17#0#0#0#0#0#0#0#0#255#255
+ +#255#0#25#163#193#255'v'#226#239#255'm'#230#245#255#0#160#196#201#0#153#185
+ +'P'#0#160#196'0'#0#0#0#0#0#0#0#0#0#160#196#255'v'#237#251#255#0#160#196#255#5
+ +'y}'#17#0#0#0#0#0#0#0#0#0#0#0#0#255#255#255#0#17#162#194#255#136#231#242#254
+ +#2#172#200#255#0#158#193#26#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#160#196#255#0
+ +#160#196#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#255#255#255#0'#'#166#192
+ +#239']'#218#233#254#14#170#203#254#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#160#196#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#255#255#255#0'#'
+ +#166#192#127'C'#197#216#254'C'#196#219#252#0#160#196'"'#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#255#255
+ +#255#0#0#0#0#0#17#166#194#174'f'#219#234#178#0#160#196']'#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#255#255
+ +#255#0#0#0#0#0#0#160#196#24#26#167#196'i'#24#166#195'i'#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0'ggj'#255']]a'#255'WW['#255'SSW'#255'LLP'#255#0#0#0'#'#255#255#255#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'YY\'#255
+ +#192#192#198#246#196#196#202#255#175#175#180#217'CCG'#255#0#0#0'_'#255#255
+ +#255#0#0#0#0#0#0#0#0#0#0#0#0#0'@@'#255#255'::'#255#255'::'#255#255'=='#255
+ +#255#0#0#0'#'#0#0#0#11'MMP'#255#191#191#197#246#194#194#200#255#182#182#188
+ +#206'AAD'#255#0#0#0'k'#255#255#255#0#0#0#0#0#0#0#0#0''''''#255#255#17#17#255
+ +#255#11#11#255#255#24#24#255#255'++'#255#255'00'#255#255#0#0#0';FFJ'#255#189
+ +#189#195#246#192#192#198#255#190#190#196#195'BBF'#255#0#0#0'_'#255#255#255#0
+ +#0#0#0#0'%%'#255#255#0#0#251#255#0#0#0'w'#0#0#0#143#0#0#0#143#26#26#255#255
+ +'!!'#255#255#13#13#255#255'CCG'#255#187#187#193#246#187#187#193#255#184#184
+ +#189#195'EEI'#255#0#0#0'_'#255#255#255#0'11'#255#255#10#10#255#255#0#0#0'w'#0
+ +#0#0'w'#0#0#0'G'#0#0#0'/'#24#24#255#255#21#21#255#255#0#0#252#255'@@D'#255
+ +#181#181#187#248#182#182#188#255#178#178#183#195'EEI'#255#0#0#0'_'#255#255
+ +#255#0'##'#255#255#0#0#251#255#0#0#0#143#0#0#0'G'#0#0#0#11#0#0#0#0'""'#255
+ +#255#15#15#255#255#0#0#239#255'==@'#255#153#153#158#227#169#169#174#213#173
+ +#173#179#156'AAE'#255#0#0#0'_'#255#255#255#0#26#26#255#255#0#0#249#255#0#0#0
+ +#143#0#0#0'/'#0#0#0#0#0#0#0#0'00'#255#255#16#16#255#255#0#0#234#255'<'#255
+ +'==A'#255'@@D'#255'??B'#255'::>'#255#0#0#0'k'#255#255#255#0#23#23#255#255#0#0
+ +#253#255#0#0#0#143#0#0#0'/'#0#0#0#0#0#0#0#0'99'#255#255#22#22#255#255#0#0#241
+ +#255#0#0#0#179#0#0#0#143#0#0#0'k'#0#0#0'_'#0#0#0'k'#0#0#0'_'#255#255#255#0#19
+ +#19#255#255#0#0#250#255#0#0#0#143#24#24#255#255'::'#255#255#0#0#0'#77'#255
+ +#255#25#25#255#255#0#0#248#255#0#0#0#155#0#0#209#255#0#0#197#255#0#0#0'S'#0#0
+ +#0';'#0#0#0'#'#255#255#255#0#4#4#255#255#0#0#233#255#0#0#0#143#0#0#0'G'#31#31
+ +#255#255',,'#255#255'""'#255#255#10#10#255#255#0#0#237#255#0#0#209#255#0#0
+ +#189#255#0#0#0'k'#0#0#0'S'#0#0#0#23#0#0#0#0#255#255#255#0#0#0#237#255#0#0#208
+ +#255#0#0#0#143#0#0#0';'#0#0#249#255#3#3#255#255#0#0#252#255#0#0#230#255#0#0
+ +#200#255#0#0#173#255#0#0#162#255#0#0#0#143#0#0#0'G'#0#0#0#11#0#0#0#0#255#255
+ +#255#0#0#0#216#255#0#0#191#255#0#0#0#143#0#0#0'/'#0#0#0'#'#0#0#222#255#0#0
+ +#209#255#0#0#185#255#0#0#158#255#0#0#140#255#0#0#0#179#0#0#0'w'#0#0#0'#'#0#0
+ +#0#0#0#0#0#0#255#255#255#0#0#0#0'#'#0#0#0'k'#0#0#0'k'#0#0#0'#'#0#0#0#11#0#0#0
+ +';'#0#0#184#255#0#0#156#255#0#0#135#255#0#0#0#179#0#0#0#131#0#0#0';'#0#0#0#11
+ +#0#0#0#0#0#0#0#0#255#255#255#0#0#0#0#11#0#0#0'#'#0#0#0'#'#0#0#0#11#0#0#0#0#0
+ +#0#0#11#0#0#0';'#0#0#159#255#0#0#0#167#0#0#0#131#0#0#0';'#0#0#0#11#0#0#0#0#0
+ +#0#0#0#0#0#0#0#188'k6q'#188'k6'#144#188'k6'#204#188'k6'#238#188'k6'#250#187
+ +'k6'#254#187'k6'#255#187'j6'#255#187'j6'#255#188'l9'#255#189'n;'#255#187'm:'
+ +#255#187'k8'#239#187'p>'#203#182'i5T'#255#255#255#0#188'k6'#155#246#224#209
+ +#255#247#224#209#255#254#251#248#255#254#251#247#255#253#249#246#255#252#245
+ +#240#255#250#240#234#255#251#242#237#255#253#249#246#255#253#250#247#255#251
+ +#241#235#255#248#233#223#254#236#208#189#251#201#137'^'#236#181'i5c'#188'k6'
+ +#216#246#223#209#255#233#170#128#255#254#250#246#255#253#250#246#255#200#140
+ +'d'#255#251#243#238#255#251#241#234#255#252#246#242#255#254#251#248#255#252
+ +#246#241#255#249#236#226#255#248#231#219#255#238#208#186#255#236#208#189#255
+ ,#187'p>'#248#188'k6'#240#246#223#208#255#232#168'~'#255#252#246#241#255#252
+ +#246#241#255#200#140'd'#255#250#241#233#255#251#244#238#255#253#250#247#255
+ +#253#249#246#255#250#240#232#255#248#232#221#255#247#230#219#255#225#163'z'
+ +#255#239#213#195#255#183'i5'#254#188'k6'#250#245#221#204#255#231#168'~'#255
+ +#250#240#232#255#250#240#232#255#201#141'f'#255#250#240#233#255#253#248#243
+ +#255#254#250#248#255#252#244#239#255#249#233#223#255#247#231#219#255#247#229
+ +#217#255#224#162'x'#255#231#194#169#255#182'h5'#255#187'k6'#254#244#220#201
+ +#255#231#167'}'#255#249#236#225#255#249#236#225#255#249#237#227#255#252#244
+ +#238#255#253#250#247#255#253#247#243#255#250#237#229#255#247#231#219#255#247
+ +#229#217#255#246#229#216#255#222#160'w'#255#228#190#164#255#180'g4'#255#187
+ +'k6'#255#244#217#199#255#230#166'}'#255#200#140'd'#255#201#141'e'#255#201#142
+ +'g'#255#203#146'l'#255#203#146'm'#255#202#144'i'#255#200#140'e'#255#200#140
+ +'d'#255#200#140'd'#255#200#140'd'#255#218#156't'#255#225#186#159#255#179'f4'
+ +#255#187'j6'#255#242#216#197#255#227#164'{'#255#227#163'z'#255#227#164'z'#255
+ +#226#164'{'#255#226#163'{'#255#225#163'{'#255#225#162'y'#255#223#160'w'#255
+ +#222#159'v'#255#221#158't'#255#219#156'r'#255#220#157't'#255#221#181#154#255
+ +#177'e4'#255#187'j6'#255#242#213#194#255#227#163'z'#255#227#163'z'#255#226
+ +#163'{'#255#226#163'{'#255#226#164'{'#255#225#162'y'#255#224#161'x'#255#222
+ +#160'w'#255#222#158'u'#255#220#157't'#255#218#155's'#255#217#155's'#255#218
+ +#176#149#255#175'd3'#255#187'j6'#255#240#210#190#255#226#163'z'#255#226#163
+ +'z'#255#225#163'z'#255#226#163'{'#255#225#163'{'#255#224#161'x'#255#222#159
+ +'w'#255#221#159'v'#255#220#157't'#255#217#155'r'#255#216#153'q'#255#214#153
+ +'p'#255#213#171#142#255#173'c3'#255#186'j6'#255#239#208#187#255#226#162'z'
+ +#255#254#251#248#255#254#251#248#255#254#251#248#255#254#251#248#255#254#251
+ +#248#255#254#251#248#255#254#251#248#255#254#251#248#255#254#251#248#255#254
+ +#251#248#255#211#150'm'#255#210#167#138#255#171'b2'#255#187'k8'#255#239#206
+ +#184#255#225#162'y'#255#254#250#247#255'b'#192#136#255'b'#192#136#255'b'#192
+ +#136#255'b'#192#136#255'b'#192#136#255'b'#192#136#255'b'#192#136#255'b'#192
+ +#136#255#253#249#246#255#207#147'j'#255#206#163#132#255#170'a2'#255#187'l8'
+ +#255#238#204#182#255#225#162'z'#255#254#250#247#255#191#220#194#255#191#220
+ +#194#255#191#220#194#255#191#220#194#255#191#220#194#255#191#220#194#255#191
+ +#220#194#255#191#220#194#255#253#249#246#255#205#144'h'#255#204#158#129#255
+ +#168'a2'#255#186'k7'#254#237#202#179#255#224#162'z'#255#254#250#247#255'b'
+ +#192#136#255'b'#192#136#255'b'#192#136#255'b'#192#136#255'b'#192#136#255'b'
+ +#192#136#255'b'#192#136#255'b'#192#136#255#253#249#246#255#202#141'e'#255#201
+ +#155'|'#255#167'`1'#254#186'j5'#222#235#198#173#255#234#197#173#255#254#251
+ +#248#255#254#251#248#255#254#251#248#255#254#251#248#255#254#251#248#255#254
+ +#251#248#255#254#251#248#255#254#251#248#255#254#251#248#255#254#251#248#255
+ +#200#154'|'#255#199#152'y'#255#167'`1'#237#186'j6'#143#185'i5'#181#184'i5'
+ +#238#183'h5'#255#181'h5'#255#180'g4'#255#178'f4'#255#176'e3'#255#174'd3'#255
+ +#172'c2'#255#170'b2'#255#169'a2'#255#168'`1'#255#167'`1'#254#166'`1'#241#168
+ +'a1'#196#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255
+ +#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0'UUU"UUUYUUUfUUUfUUUfUUUfUUUfUUUfUUUfUUUfUUUfUUUfUUUfUUUfUUUYUUU"RRR['
+ +#198#198#198#212#220#220#220#255#216#217#217#255#213#213#213#255#208#209#209
+ +#255#204#204#204#255#200#200#200#255#198#198#198#255#198#197#197#255#201#197
+ +#197#255#205#198#198#255#209#199#199#255#215#203#203#255#196#184#184#212'RRR'
+ +'[PPPi'#187#187#187#255#186#186#186#255#184#184#184#255#182#182#182#255#179
+ +#179#179#255#176#176#176#255#174#174#174#255#171#171#171#255#168#168#168#255
+ +#166#166#166#255#163#163#163#255#160#160#160#255#158#158#158#255#156#156#156
+ +#255#3#3#3'fUUUg'#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
+ +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
+ +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
+ +#255#255#255'UUUgQQQh'#253#253#253#255#252#252#252#255#252#252#252#255#252
+ +#252#252#255#252#252#252#255#252#252#252#255#252#252#252#255#252#252#252#255
+ +#252#252#252#255#252#252#252#255#252#252#252#255#252#252#252#255#252#252#252
+ +#255#253#253#253#255'QQQhMMMj'#250#250#250#255#248#248#248#255#248#248#248
+ +#255#248#248#248#255#248#248#248#255#248#248#248#255#248#248#248#255#248#248
+ +#248#255#248#248#248#255#248#248#248#255#248#248#248#255#248#248#248#255#248
+ +#248#248#255#250#250#250#255'MMMjIIIl'#247#247#247#255#244#244#244#255#244
+ +#244#244#255#244#244#244#255#244#244#244#255#244#244#244#255#244#244#244#255
+ +#244#244#244#255#244#244#244#255#244#244#244#255#244#244#244#255#244#244#244
+ +#255#244#244#244#255#247#247#247#255'IIIlDDDn'#243#243#243#255#239#239#239
+ ,#255#239#239#239#255#239#239#239#255#239#239#239#255#239#239#239#255#239#239
+ +#239#255#239#239#239#255#239#239#239#255#239#239#239#255#239#239#239#255#239
+ +#239#239#255#239#239#239#255#243#243#243#255'DDDn>>>q'#240#240#240#255#235
+ +#235#235#255#235#235#235#255#235#235#235#255#235#235#235#255#235#235#235#255
+ +#235#235#235#255#235#235#235#255#235#235#235#255#235#235#235#255'k'#196'_'
+ +#255'@'#182'/'#255'k'#196'_'#255#240#240#240#255'>>>q888s'#237#237#237#255
+ +#230#230#230#255#230#230#230#255#230#230#230#255#230#230#230#255#230#230#230
+ +#255#230#230#230#255#230#230#230#255#230#230#230#255#230#230#230#255'>'#177
+ +'.'#255'u'#238'd'#255'>'#177'.'#255#237#237#237#255'888s222v'#234#234#234#255
+ +#226#226#226#255#226#226#226#255#226#226#226#255#226#226#226#255#226#226#226
+ +#255#226#226#226#255#226#226#226#255'f'#185'['#255'<'#171'-'#255'<'#171'-'
+ +#255'f'#235'U'#255'<'#171'-'#255'>'#173'/'#255#28'z'#17#200'''''''{'#235#235
+ +#235#255#231#231#231#255#231#231#231#255#231#231#231#255#231#231#231#255#231
+ +#231#231#255#231#231#231#255#231#231#231#255';'#165'/'#255'R'#231'A'#255'R'
+ +#231'A'#255'R'#231'A'#255'R'#231'A'#255'R'#231'A'#255#18#137#5#229#13#13#13
+ +'g'#16#16#16#133#16#16#16#133#16#16#16#133#16#16#16#133#16#16#16#133#16#16#16
+ +#133#16#16#16#133#16#16#16#133#14'b'#4#207#14'~'#2#231#14'~'#2#231'='#226','
+ +#255#14'~'#2#231#14'~'#2#231#11'_'#2#176#0#0#0#9#0#0#0#22#0#0#0#26#0#0#0#26#0
+ +#0#0#26#0#0#0#26#0#0#0#26#0#0#0#26#0#0#0#26#0#0#0#26#0#0#0#26#11#128#0#209'+'
+ +#223#26#255#11#128#0#209#0#0#0#22#0#0#0#9#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#4'9'#0#0#6'm'#0#153#5'i'#0#204#6
+ +'m'#0#153#4'9'#0#0#0#0#0#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0'UUU"UUUYUUUfUUUfUUUfUUUfUUUfUUUfUUUfUUUfUUUfUUUfUUU'
+ +'fUUUfUUUYUUU"RRR['#198#198#198#212#220#220#220#255#216#217#217#255#213#213
+ +#213#255#208#209#209#255#204#204#204#255#200#200#200#255#198#198#198#255#198
+ +#197#197#255#201#197#197#255#205#198#198#255#209#199#199#255#215#203#203#255
+ +#196#184#184#212'RRR[PPPi'#187#187#187#255#186#186#186#255#184#184#184#255
+ +#182#182#182#255#179#179#179#255#176#176#176#255#174#174#174#255#171#171#171
+ +#255#168#168#168#255#166#166#166#255#163#163#163#255#160#160#160#255#158#158
+ +#158#255#156#156#156#255#3#3#3'fUUUg'#255#255#255#255#255#255#255#255#255#255
+ +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
+ +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
+ +#255#255#255#255#255#255#255#255'UUUgQQQh'#253#253#253#255#252#252#252#255
+ +#252#252#252#255#252#252#252#255#252#252#252#255#252#252#252#255#252#252#252
+ +#255#252#252#252#255#252#252#252#255#252#252#252#255#252#252#252#255#252#252
+ +#252#255#252#252#252#255#253#253#253#255'QQQhMMMj'#250#250#250#255#248#248
+ +#248#255#248#248#248#255#248#248#248#255#248#248#248#255#248#248#248#255#248
+ +#248#248#255#248#248#248#255#248#248#248#255#248#248#248#255#248#248#248#255
+ +#248#248#248#255#248#248#248#255#250#250#250#255'MMMjIIIl'#247#247#247#255
+ +#244#244#244#255#244#244#244#255#244#244#244#255#244#244#244#255#244#244#244
+ +#255#244#244#244#255#244#244#244#255#244#244#244#255#244#244#244#255#244#244
+ +#244#255#244#244#244#255#244#244#244#255#247#247#247#255'IIIlDDDn'#243#243
+ +#243#255#239#239#239#255#239#239#239#255#239#239#239#255#239#239#239#255#239
+ +#239#239#255#239#239#239#255#239#239#239#255#239#239#239#255#239#239#239#255
+ +#239#239#239#255#239#239#239#255#239#239#239#255#243#243#243#255'DDDn>>>q'
+ +#240#240#240#255#235#235#235#255#235#235#235#255#235#235#235#255#235#235#235
+ +#255#235#235#235#255#235#235#235#255#235#235#235#255#235#235#235#255#235#235
+ +#235#255#235#235#235#255#235#235#235#255#235#235#235#255#240#240#240#255'>>>'
+ +'q888s'#237#237#237#255#230#230#230#255#230#230#230#255#230#230#230#255#230
+ +#230#230#255#230#230#230#255#230#230#230#255#230#230#230#255#230#230#230#255
+ +#230#230#230#255#230#230#230#255#230#230#230#255#230#230#230#255#237#237#237
+ +#255'888s222v'#234#234#234#255#226#226#226#255#226#226#226#255#226#226#226
+ +#255#226#226#226#255#226#226#226#255#226#226#226#255#226#226#226#255'[['#190
+ +#255'--'#179#255'--'#179#255'--'#179#255'--'#179#255'//'#181#255#17#17#129
+ +#200'''''''{'#235#235#235#255#231#231#231#255#231#231#231#255#231#231#231#255
+ +#231#231#231#255#231#231#231#255#231#231#231#255#231#231#231#255'//'#167#255
+ +'^^'#247#255'^^'#247#255'^^'#247#255'^^'#247#255'^^'#247#255#5#5#139#229#13
+ +#13#13'g'#16#16#16#133#16#16#16#133#16#16#16#133#16#16#16#133#16#16#16#133#16
+ +#16#16#133#16#16#16#133#16#16#16#133#4#4'['#207#2#2's'#231#2#2's'#231#2#2's'
+ +#231#2#2's'#231#2#2's'#231#2#2'X'#176#0#0#0#9#0#0#0#22#0#0#0#26#0#0#0#26#0#0
+ +#0#26#0#0#0#26#0#0#0#26#0#0#0#26#0#0#0#26#0#0#0#26#0#0#0#26#0#0#0#26#0#0#0#26
+ +#0#0#0#26#0#0#0#22#0#0#0#9#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ ,#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#11#0#0#0'#'#0#0#0'/'#0#0#0'/'#0#0#0'/'#0#0#0'/'#0#0#0'#'#0#0#0#11#255#255
+ +#255#0#255#255#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#11#0#0#0'#'#0#0#0
+ +'G'#138#211#255#255'_'#195#255#255'('#174#255#255#0#159#255#255#0#136#218#255
+ +#0'w'#191#255#0#0#0#23#255#255#255#0#255#255#255#0#0#0#0#11#0#0#0'#'#0#0#0'/'
+ +#0#0#0'/'#0#0#0'Gs'#202#255#255'g'#198#255#255'Q'#189#255#255#0#0#0'k'#0#0#0
+ +';'#0#0#0'/'#0#0#0'/'#0#0#0'#'#0#0#0#11#255#255#255#0#255#255#255#0#0#0#0#23
+ +'('#174#255#255#28#170#255#255#19#166#255#255#12#164#255#255#0#159#255#255#0
+ +#0#0'_'#0#149#239#255#0'}'#200#255#0#0#0'#'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#255#255#255#0#255#255#255#0#0#0#0#11#0#0#0'#'#0#0#0'/'#0#0#0'/'#0#0#0'/'#0#0
+ +#0'#'#0#0#0#23#0#0#0'G'#0'c'#158#255#0#0#0'G'#0#0#0#11#0#0#0#0#0#0#0#0#0#0#0
+ +#0#255#255#255#0#255#255#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0'#'#0'\'#148#255#0'En'#255#0#0#0'#'#0#0#0#0#0#0#0#0#0#0#0#0
+ +#255#255#255#0#255#255#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#11#0#0#0'G'#0'_'#152#255#0#0#0'/'#0#0#0#0#0#0#0#0#0#0#0#0#255
+ +#255#255#0#255#255#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0'/'#0#141#226#255#0#0#0'/'#0#0#0#0#0#0#0#0#0#0#0#0#255#255
+ +#255#0#255#255#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0'/'#0#151#242#255#0#0#0'/'#0#0#0#0#0#0#0#0#0#0#0#0#255#255#255
+ +#0#255#255#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#11#0#0#0'G'#0#138#221#255#0#0#0'/'#0#0#0#0#0#0#0#0#0#0#0#0#255#255#255#0
+ +#255#255#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +'#'#27#169#255#255#0'o'#178#255#0#0#0'/'#0#0#0#0#0#0#0#0#0#0#0#0#255#255#255
+ +#0#255#255#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#11#0#0#0'#'#0#0#0'/'#0#0#0'/'
+ +#0#0#0'S'#0#134#215#255#0'Ky'#255#0#0#0'#'#0#0#0#0#0#0#0#0#0#0#0#0#255#255
+ +#255#0#255#255#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#23'%'#173#255#255#10#163
+ +#255#255#0#138#222#255#0'l'#173#255#0'Eo'#255#0#0#0';'#0#0#0#11#0#0#0#0#0#0#0
+ +#0#0#0#0#0#255#255#255#0#255#255#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#11#0#0#0
+ +'#'#0#0#0'/'#0#0#0'/'#0#0#0'/'#0#0#0'#'#0#0#0#11#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#160#196#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#157#191#20#0#160#196#255#0
+ +#160#196#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#5'y}'#17#0#160#196#255#173#243#251#255#0#160
+ +#196#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#5'y}'#17#0#160#196#255#173#243#251#255'%'#228#251#255#0
+ +#160#196#255#0#160#196#255#19#161#190#231#21#159#187#207#27#161#187#164#6'z|'
+ +#11#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#5'y}'#17#0#160#196#255#173#243
+ +#251#255'1'#225#246#255' '#227#250#255's'#236#250#255'o'#235#250#255'n'#232
+ +#247#255'l'#232#247#248#20#161#188#212#20#163#193#213#5'y}'#28#0#0#0#0#0#0#0
+ +#0#0#0#0#0#5'y}'#10#0#160#196#255#173#243#251#255'/'#224#246#255'2'#226#247
+ +#255')'#219#241#255'/'#224#245#255')'#219#241#255#22#205#227#255'6'#217#236
+ +#255'i'#231#246#255'A'#206#227#254#19#163#193#228#5'y}2'#0#0#0#0#0#0#0#0#0
+ +#160#196#255#173#243#251#255'/'#224#246#255'2'#226#248#255'2'#226#247#255'2'
+ +#226#247#255'/'#224#245#255')'#219#241#255#29#210#232#255#29#210#232#255#29
+ +#210#232#255'6'#217#236#255'@'#205#225#255#22#161#189#202#5'y}'#10#0#0#0#0#5
+ +'y~'#17#0#160#196#255'y'#237#251#255'2'#226#248#255','#223#244#255#4#192#214
+ +#255#4#192#214#255#4#192#214#255#29#210#232#255#29#210#232#255#29#210#232#255
+ +#11#200#223#255'j'#229#243#255#27#171#197#248#21#160#188#203#0#0#0#0#0#0#0#0
+ +#5'y}'#17#0#160#196#255'v'#237#251#255#4#195#218#255'v'#237#251#255'i'#234
+ +#249#255'i'#234#249#255'i'#234#249#255'i'#234#249#255#5#221#247#255#10#200
+ +#223#255#7#194#216#255'o'#220#235#255#27#163#191#244#0#0#0#0#0#0#0#0#0#0#0#0
+ +#5'y}'#17#0#160#196#255'v'#237#251#255'v'#237#251#255#0#160#196#255#0#160#196
+ +#255#0#160#196#255#0#160#196#255#1#169#196#255'n'#225#238#255#15#201#223#255
+ +'i'#228#242#255#26#164#192#248#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#5'y}'#17#0#160
+ +#196#255'v'#237#251#255#0#160#196#255#0#0#0#0#0#0#0#0#0#160#196'0'#0#153#185
+ ,'P'#0#160#196#201'm'#230#245#255'v'#226#239#255#25#163#193#255#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#160#196#255#0#160#196#255#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#158#193#26#2#172#200#255#136#231#242#254#17#162#194#255
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#160#196#255#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#14#170#203#254']'#218#233#254'#'#166#192
+ +#239#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#160#196'"C'#196#219#252'C'#197#216#254'#'#166#192
+ +#127#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#160#196']f'#219#234#178#17#166#194#174#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#24#166#195'i'#26#167#196'i'#0#160#196#24#0#0#0#0#0#0#0#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#0#0#162#0#0#0#165#0#0#0#168#0#0#0#169#26#0#0#170'l'#0#0#170#166#0
+ +#0#170#196#0#0#170#196#0#0#170#166#0#0#170'l'#0#0#169#26#0#0#168#0#0#0#165#0
+ +#0#0#162#0#255#255#255#0#255#255#255#0#0#0#162#0#0#0#165#0#0#0#168'M'#9#9#174
+ +#191'77'#208#227'\\'#234#245'jj'#243#253'ii'#242#253'[['#233#245'66'#207#227
+ +#9#9#174#191#0#0#168'M'#0#0#165#0#0#0#162#0#255#255#255#0#255#255#255#0#0#0
+ +#162#0#0#0#165'M'#16#16#177#205'[['#232#246'__'#231#255'[['#227#255'[['#227
+ +#255'[['#227#255'[['#227#255'__'#231#255'XX'#228#246#15#15#176#205#0#0#165'M'
+ +#0#0#162#0#255#255#255#0#255#255#255#0#0#0#161#26#8#8#168#191'VV'#226#246'QQ'
+ +#217#255#255#255#255#255'OO'#215#255'OO'#215#255'OO'#215#255'OO'#215#255#255
+ +#255#255#255'PP'#216#255'OO'#220#246#7#7#167#191#0#0#161#26#255#255#255#0#255
+ +#255#255#0#0#0#158'l22'#198#227'II'#209#255#255#255#255#255#255#255#255#255
+ +#255#255#255#255'BB'#202#255'BB'#202#255#255#255#255#255#255#255#255#255#255
+ +#255#255#255'GG'#207#255'**'#189#227#0#0#158'l'#255#255#255#0#255#255#255#0#0
+ +#0#154#167'GG'#211#245'77'#191#255'##'#171#255#255#255#255#255#247#247#247
+ +#255#232#232#232#255#222#222#222#255#219#219#219#255#221#221#221#255#17#17
+ +#155#255#22#22#160#255''''''#180#245#0#0#154#167#255#255#255#0#255#255#255#0
+ +#0#0#150#196'II'#209#253'33'#187#255'..'#184#255#19#19#159#255#206#206#206
+ +#255#209#209#209#255#214#214#214#255#220#220#220#255#17#17#158#255#17#17#161
+ +#255#17#17#161#255#29#29#172#253#0#0#150#196#255#255#255#0#255#255#255#0#0#0
+ +#146#196'DD'#205#253'&&'#181#255#20#20#171#255#17#17#170#255#209#209#209#255
+ +#214#214#214#255#220#220#220#255#226#226#226#255#17#17#170#255#17#17#170#255
+ +#17#17#170#255#24#24#175#253#0#0#146#196#255#255#255#0#255#255#255#0#0#0#141
+ +#167'..'#192#245#18#18#180#255#17#17#180#255#209#209#209#255#214#214#214#255
+ +#220#220#220#255#226#226#226#255#230#230#230#255#234#234#234#255#17#17#180
+ +#255#17#17#180#255#18#18#175#245#0#0#141#167#255#255#255#0#255#255#255#0#0#0
+ +#137'l'#22#22#170#226#22#22#193#255#209#209#209#255#214#214#214#255#220#220
+ +#220#255#17#17#173#255#17#17#173#255#234#234#234#255#238#238#238#255#238#238
+ +#238#255#17#17#190#255#9#9#161#227#0#0#137'l'#255#255#255#0#255#255#255#0#0#0
+ +#133#26#3#3#138#191#24#24#193#246#18#18#178#255#220#220#220#255#17#17#178#255
+ +#17#17#200#255#17#17#200#255#17#17#178#255#238#238#238#255#17#17#178#255#15
+ +#15#188#246#2#2#137#191#0#0#133#26#255#255#255#0#255#255#255#0#0#0#131#0#0#0
+ +#127'M'#4#4#136#205#18#18#196#246#18#18#182#255#17#17#209#255#17#17#209#255
+ +#17#17#209#255#17#17#209#255#17#17#182#255#15#15#194#246#3#3#136#205#0#0#127
+ +'M'#0#0#131#0#255#255#255#0#255#255#255#0#0#0#0#0#0#0#31#0#0#0'SM'#2#2't'#191
+ +#8#8#157#227#14#14#196#245#17#17#212#253#17#17#212#253#14#14#196#245#8#8#157
+ +#227#2#2't'#191#0#0'SM'#0#0#31#0#0#0#0#0#255#255#255#0#255#255#255#0#0#0#0#4
+ +#0#0#0#23#0#0#0'+'#0#0#26'C'#0#0'D'#128#0#0'Z'#171#0#0']'#196#0#0']'#196#0#0
+ +'Z'#171#0#0'D'#128#0#0#26'C'#0#0#0'-'#0#0#0#24#0#0#0#4#255#255#255#0#255#255
+ +#255#0#0#0#0#2#0#0#0#12#0#0#0#22#0#0#0#26#0#0#0#26#0#0#0#26#0#0#0#26#0#0#0#26
+ +#0#0#0#26#0#0#0#26#0#0#0#26#0#0#0#23#0#0#0#12#0#0#0#2#255#255#255#0'TTT'#0'T'
+ +'TT'#0'TTT'#0'UUU"UUUYUUUfUUUfUUUfUUUfUUUfUUUfUUUfUUUfUUUfUUUYUUU"TTT'#0'RRR'
+ +#0'RRR'#0'RRR['#198#198#198#212#219#219#219#255#214#214#214#255#209#209#209
+ +#255#203#204#204#255#199#199#199#255#198#196#196#255#200#197#197#255#206#198
+ +#198#255#212#201#201#255#196#183#183#212'RRR[UUU'#0'TTT'#0'PPP'#0'PPPi'#187
+ +#187#187#255#185#185#185#255#182#182#182#255#180#180#180#255#176#176#176#255
+ +#173#173#173#255#169#169#169#255#166#166#166#255#162#162#162#255#160#160#160
+ +#255#157#157#157#255#3#3#3'fUUU'#0'UUU'#0'UUU'#0'TTTg'#255#255#255#255#255
+ +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
+ +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
+ +#255'TTTgUUU"UUUYUUUfSSS'#165#185#185#185#255#184#184#184#255#184#184#184#255
+ ,#184#184#184#255#184#184#184#255#184#184#184#255#184#184#184#255#193#193#193
+ +#255#229#229#229#255#251#251#251#255#252#252#252#255'PPPiRRR['#198#198#198
+ +#212#219#219#219#255#214#214#214#255#209#209#209#255#203#204#204#255#199#199
+ +#199#255#198#196#196#255#200#197#197#255#206#198#198#255#212#201#201#255#208
+ +#197#197#255#188#188#188#255#246#246#246#255#248#248#248#255'KKKkPPPi'#187
+ +#187#187#255#185#185#185#255#182#182#182#255#180#180#180#255#176#176#176#255
+ +#173#173#173#255#169#169#169#255#166#166#166#255#162#162#162#255#160#160#160
+ +#255#157#157#157#255#145#145#145#255#240#240#240#255#244#244#244#255'EEEnTTT'
+ +'g'#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
+ +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
+ +#255#255#255#255#255#255#255#174#174#174#255#234#234#234#255#239#239#239#255
+ +'===qPPPi'#252#252#252#255#251#251#251#255#251#251#251#255#251#251#251#255
+ +#251#251#251#255#251#251#251#255#251#251#251#255#251#251#251#255#251#251#251
+ +#255#251#251#251#255#252#252#252#255#168#168#168#255#228#228#228#255#235#235
+ +#235#255'666tKKKk'#248#248#248#255#246#246#246#255#246#246#246#255#246#246
+ +#246#255#246#246#246#255#246#246#246#255#246#246#246#255#246#246#246#255#246
+ +#246#246#255#246#246#246#255#248#248#248#255#166#166#166#255#232#232#232#255
+ +#236#236#236#255'---xEEEn'#244#244#244#255#240#240#240#255#240#240#240#255
+ +#240#240#240#255#240#240#240#255#240#240#240#255#240#240#240#255#240#240#240
+ +#255#240#240#240#255#240#240#240#255#244#244#244#255'111'#184#20#20#20#131#20
+ +#20#20#131#17#17#17'e===q'#239#239#239#255#234#234#234#255#234#234#234#255
+ +#234#234#234#255#234#234#234#255#234#234#234#255#234#234#234#255#234#234#234
+ +#255'^^'#194#255'//'#181#255'00'#182#255#6#6#154#230#0#0#163#209#0#0#164#209
+ +#0#0'|'#158'666t'#235#235#235#255#228#228#228#255#228#228#228#255#228#228#228
+ +#255#228#228#228#255#228#228#228#255#228#228#228#255#228#228#228#255'..'#167
+ +#255'^^'#247#255'^^'#247#255'^^'#247#255'^^'#247#255'^^'#247#255#0#0#152#204
+ +'---x'#236#236#236#255#232#232#232#255#232#232#232#255#232#232#232#255#232
+ +#232#232#255#232#232#232#255#232#232#232#255#232#232#232#255'__'#173#255'//'
+ +#149#255'00'#150#255#5#5'w'#228#0#0#128#204#0#0#128#204#0#0#132#153#17#17#17
+ +'e'#20#20#20#131#20#20#20#131#20#20#20#131#20#20#20#131#20#20#20#131#20#20#20
+ +#131#20#20#20#131#20#20#20#131#20#20#20#131#20#20#20#131#20#20#20#131#17#17
+ +#17'e'#0#0'Z'#0#0#0'w'#0#0#0#128#0#0#0#0#10#0#0#0#24#0#0#0#26#0#0#0#26#0#0#0
+ +#26#0#0#0#26#0#0#0#26#0#0#0#26#0#0#0#26#0#0#0#26#0#0#0#26#0#0#0#25#0#0#0#11#0
+ +#0#0#0#0#0'w'#0#0#0#128#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#212#151'n'#201#212#158'{'#201#208#152
+ +'q'#201#214#164#130#201#205#142'h'#201#205#144'i'#201#208#154'u'#201#209#153
+ +'s'#201#200#139'b'#201#173'Z +'#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#204#141'e'#201#243#205#176#201#255#255
+ +#255#201#227#199#179#201#255#255#255#201#255#255#255#201#255#255#255#201#255
+ +#255#255#201#234#191#161#201#201#137'`'#201#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#199#134'['#201#239#192
+ +#158#201#217#162'}'#248#211#157'z'#248#213#163#128#248#218#174#143#248#210
+ +#154'w'#248#210#155'w'#248#210#156'w'#248#208#151'q'#248#200#139'b'#222#173
+ +'Z /'#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#200#136']'#201
+ +#239#191#161#201#209#153'u'#248#244#210#184#248#255#255#255#248#230#205#187
+ +#248#255#255#254#248#255#255#255#248#251#246#242#248#248#241#237#248#234#191
+ +#161#222#201#137'`'#222#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255
+ +#0#202#141'e'#201#234#184#153#201#201#137'_'#248#237#189#155#248#212#151'n'
+ +#255#212#158'{'#255#208#152'q'#255#214#164#130#255#205#142'h'#255#205#144'i'
+ +#255#208#154'u'#255#209#153's'#255#200#139'b'#255#173'Z 6'#255#255#255#0#255
+ +#255#255#0#201#139'a'#201#230#181#146#201#203#139'a'#248#238#188#158#248#204
+ +#141'e'#255#243#205#176#255#255#255#255#255#227#199#179#255#255#255#255#255
+ +#255#255#255#255#255#255#255#255#255#255#255#255#234#191#161#255#201#137'`'
+ +#255#255#255#255#0#255#255#255#0#196#129'T'#201#234#182#151#201#206#152's'
+ +#248#234#190#161#248#199#134'['#255#239#192#158#255#255#255#255#255#204#147
+ +'n'#255#255#255#255#255#255#255#255#255#255#251#247#255#255#248#241#255#228
+ +#175#140#255#199#138'a'#255#255#255#255#0#255#255#255#0#195#127'Q'#201#239
+ +#182#154#201#204#150'o'#248#214#182#145#248#200#136']'#255#239#191#161#255
+ +#253#252#250#255#254#252#251#255#254#253#253#255#254#253#252#255#253#251#250
+ +#255#253#252#251#255#221#168#133#255#193#127'S'#255#255#255#255#0#255#255#255
+ +#0#198#131'U'#201#239#206#186#201#199#142'f'#248#224#188#156#248#202#141'e'
+ +#255#234#184#153#255#221#165'~'#255#221#166#128#255#219#163'|'#255#217#160'z'
+ ,#255#217#160'y'#255#216#159'x'#255#216#158'x'#255#191#132']'#255#255#255#255
+ +#0#255#255#255#0#186'h3'#155#195#132'X'#201#197#128'S'#248#238#178#150#248
+ +#201#139'a'#255#230#181#146#255#226#167#129#255#225#167#129#255#222#163'}'
+ +#255#220#161'{'#255#219#159'y'#255#217#158'w'#255#212#154's'#255#187'~W'#255
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#198#131'U'#222#239
+ +#206#186#222#196#129'T'#255#234#182#151#255#243#243#234#255#237#241#230#255
+ +#239#241#230#255#239#240#230#255#237#241#229#255#243#245#237#255#213#156'y'
+ +#255#176'pD'#255#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#186
+ +'h3'#172#195#132'X'#222#195#127'Q'#255#239#182#154#255#234#243#232#255'Q'#191
+ +#132#255'o'#201#152#255'q'#201#153#255'T'#191#132#255#228#244#233#255#221#156
+ +'{'#255#170'i:'#255#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#198#131'U'#255#239#206#186#255#221#255#255#255
+ +#135#238#199#255#162#244#215#255#162#246#215#255#140#238#199#255#224#255#255
+ +#255#221#162#133#255#171'j>'#255#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#186'h3'#197#195#132'X'#255#211#139
+ +'h'#255#225#143'p'#255#220#141'l'#255#218#139'm'#255#215#138'n'#255#205#139
+ +'l'#255#171'mD'#255#166'_.'#255#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#199'yG'#170#204#134'U'#206#204#136
+ +'W'#222#203#136'V'#219#204#136'V'#219#203#135'W'#219#202#131'P'#208#196'yBn'
+ +#178'g<'#8#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#202#133'T'#208#255#255#255#219#253#243#233
+ +#222#253#243#234#222#252#242#232#222#250#239#227#222#250#242#231#222#234#187
+ +#136#222#207#133'U'#156#180'i='#10#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#203#134'V'#218#254#245#237#222#252
+ +#222#197#222#251#224#199#222#249#220#194#222#245#211#180#222#254#249#243#222
+ +#250#226#196#222#236#193#147#222#195'}H'#128#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#203#134'U'#219#254#246
+ +#240#222#252#226#205#222#252#227#205#222#250#223#200#222#247#217#188#222#245
+ +#233#221#222#250#243#235#222#251#248#243#222#205#149'e'#220#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#203#134'U'
+ +#219#254#247#241#222#252#229#210#222#252#228#209#222#251#226#204#222#249#221
+ +#196#222#234#195#157#255#230#191#150#255#228#187#146#255#228#187#146#255#209
+ +#160'l'#245#208#158'm'#246#204#150'_'#218#196'yB~'#178'g<'#9#255#255#255#0
+ +#203#134'T'#219#255#247#242#222#254#231#213#222#254#231#213#222#253#229#209
+ +#222#250#224#202#222#229#190#150#255#255#255#254#255#253#243#233#255#253#243
+ +#234#255#252#242#232#255#250#239#227#255#250#242#231#255#234#187#136#255#207
+ +#133'U'#179#180'i='#12#203#133'S'#219#255#247#240#222#255#231#213#222#253#231
+ +#214#222#253#230#212#222#252#228#208#222#228#187#147#255#254#245#237#255#252
+ +#222#197#255#251#224#199#255#249#220#194#255#245#211#180#255#254#249#243#255
+ +#250#226#196#255#236#193#147#255#195'}H'#147#202#132'R'#219#255#247#241#222
+ +#255#233#217#222#255#234#219#222#255#233#217#222#255#231#215#222#228#187#146
+ +#255#254#246#240#255#252#226#205#255#252#227#205#255#250#223#200#255#247#217
+ +#188#255#245#233#221#255#250#243#235#255#251#248#243#255#202#131'S'#254#204
+ +#131'R'#219#251#245#238#222#255#233#217#222#255#234#219#222#255#233#217#222
+ +#255#231#215#222#228#187#146#255#254#247#241#255#252#229#210#255#252#228#209
+ +#255#251#226#204#255#249#221#196#255#246#215#187#255#243#209#175#255#250#239
+ +#228#255#204#135'X'#254#207#130'S'#222#239#241#231#222#255#233#217#222#255
+ +#234#219#222#255#233#217#222#255#231#215#222#228#187#145#255#255#247#242#255
+ +#254#231#213#255#254#231#213#255#253#229#209#255#250#224#202#255#249#222#196
+ +#255#247#217#188#255#253#242#231#255#204#135'W'#254#200'|N'#211#252#243#236
+ +#222#250#241#232#222#250#240#231#222#251#241#233#222#251#242#234#222#228#186
+ +#145#255#255#247#240#255#255#231#213#255#253#231#214#255#253#230#212#255#252
+ +#228#208#255#251#227#203#255#250#220#194#255#254#243#232#255#204#134'V'#254
+ +#199'yJ'#185#200'yK'#206#200'uE'#221#199'uE'#212#200'uE'#212#199'uE'#212#202
+ +#132'R'#255#255#247#241#255#255#233#217#255#255#234#219#255#255#233#217#255
+ +#255#231#215#255#255#229#210#255#255#226#203#255#255#247#241#255#203#133'U'
+ +#254#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#204#131'R'#251#251#245#238#255#255#233#217#255#255#234#219#255
+ +#255#233#217#255#255#231#215#255#255#229#210#255#255#226#203#255#251#246#239
+ +#255#204#131'U'#254#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#207#130'S'#255#239#241#231#255#255#233#217#255
+ +#255#234#219#255#255#233#217#255#255#231#215#255#255#229#210#255#255#226#203
+ ,#255#239#242#232#255#206#129'V'#255#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#199'yI'#237#252#243#236#255#250
+ +#241#232#255#250#240#231#255#251#241#233#255#251#242#234#255#251#242#234#255
+ +#251#242#235#255#253#244#238#255#202#128'T'#249#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#197'sB'#193#198'uE'
+ +#230#200'uE'#254#199'uE'#243#200'uE'#243#199'uE'#243#199'uE'#243#200'uF'#244
+ +#197'tD'#232#202#127'S'#241#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#0#0#255#1#0#0#135'F'#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#0#0#135'F'#0#0#255#1#255#255#255#0#255#255
+ +#255#0#255#255#255#0#0#0#255#1#0#0#141#150#0#0#141#255#0#0#142'x'#255#255#255
+ +#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#0#0
+ +#142'x'#0#0#142#255#0#0#143#150#0#0#255#1#255#255#255#0#255#255#255#0#0#0#146
+ +'F'#0#0#147#255#0#0#147#255#0#0#147#255#0#0#149'x'#255#255#255#0#255#255#255
+ +#0#255#255#255#0#255#255#255#0#0#0#149'x'#0#0#148#255#0#0#148#255#0#0#148#255
+ +#0#0#149'F'#255#255#255#0#255#255#255#0#255#255#255#0#0#0#153'x'#0#0#153#255
+ +#0#0#153#255#0#0#153#255#0#0#153'x'#255#255#255#0#255#255#255#0#0#0#153'x'#0
+ +#0#154#255#0#0#154#255#0#0#154#255#0#0#153'x'#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#0#0#159'x'#0#0#159#255#0#0#159#255#0#0
+ +#159#255#0#0#159'x'#0#0#159'x'#0#0#160#255#0#0#160#255#0#0#160#255#0#0#159'x'
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#0#0#166'x'#0#0#165#255#0#0#165#255#0#0#165#255#0#0
+ +#166#255#0#0#166#255#0#0#166#255#0#0#166'x'#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#0#0#170'x'#0#0#171#255#0#0#171#255#0#0#171#255#0#0#172
+ +#255#0#0#172'x'#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#0#0#176'x'#0#0#177#255#0#0#177#255#0#0#177#255#0#0#177#255#0#0#179'x'
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#0#0#183'x'#0#0#183#255#0
+ +#0#183#255#0#0#183#255#0#0#183#255#0#0#183#255#0#0#183#255#0#0#183'x'#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#0#0#189'x'#0#0#189#255#0#0#189#255#0#0#189#255#0#0#189'x'#0#0
+ +#189'x'#0#0#189#255#0#0#189#255#0#0#189#255#0#0#189'x'#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#0#0#193'x'#0#0#195#255#0#0
+ +#195#255#0#0#195#255#0#0#196'x'#255#255#255#0#255#255#255#0#0#0#196'x'#0#0
+ +#195#255#0#0#195#255#0#0#195#255#0#0#196'x'#255#255#255#0#255#255#255#0#255
+ +#255#255#0#0#0#200'F'#0#0#200#255#0#0#200#255#0#0#201#255#0#0#202'x'#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#0#0#202'x'#0#0#201#255#0#0
+ +#201#255#0#0#201#255#0#0#200'F'#255#255#255#0#255#255#255#0#0#0#255#1#0#0#206
+ +#150#0#0#206#255#0#0#206'x'#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#0#0#206'x'#0#0#207#255#0#0#207#150#0#0#255
+ +#1#255#255#255#0#255#255#255#0#255#255#255#0#0#0#255#1#0#0#211'F'#255#255#255
+ +#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#0#0#211'F'#0#0#255#1#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#0#0#0#6#0#0#0#14#0#0#0#22#0#0#0#30#0#0#0'%'#0#0#0'*'
+ +#0#0#0'+'#0#0#0')'#0#0#0'$'#0#0#0#29#0#0#0#21#0#0#0#13#0#0#0#4#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +'ZZP'#255'HH>'#255'HH>'
+ +#255'HH>'#255'HH>'#255'HH>'#255'vvn'#255#206#206#198#255#210#210#200#255#210
+ +#210#200#255'ii_'#255'ddZ'#255#206#206#196#255#206#206#196#255#206#206#196
+ +#255#206#206#198#255'zzs'#255'BB8'#255'BB8'#255'BB8'#255'BB8'#255'zzs'#255
+ +#206#206#198#255#206#206#196#255#206#206#196#255#206#206#196#255'hh^'#255'dd'
+ +'Z'#255#203#203#193#255#203#203#193#255#203#203#193#255#201#201#191#255'wwo'
+ +#255'==3'#255'==3'#255'==3'#255'==3'#255'wwo'#255#201#201#191#255#203#203#193
+ +#255#203#203#193#255#203#203#193#255'hh^'#255'ddZ'#255#199#199#189#255#199
+ +#199#189#255#196#196#188#255'ssk'#255'88.'#255'88.'#255'88.'#255'88.'#255'88'
+ +'.'#255'88.'#255'ssk'#255#196#196#188#255#199#199#189#255#199#199#189#255'gg'
+ +']'#255'ccY'#255#195#195#185#255#195#195#185#255#199#199#190#255#131#131'}'
+ +#255'22('#255'22('#255#141#141#134#255#141#141#134#255'22('#255'22('#255#131
+ +#131'}'#255#199#199#190#255#195#195#185#255#195#195#185#255'gg]'#255'ddZ'#255
+ +#191#191#181#255#192#192#182#255#192#192#182#255#199#199#191#255#141#141#134
+ +#255#150#150#144#255#197#197#188#255#197#197#188#255#150#150#144#255#141#141
+ +#134#255#199#199#191#255#192#192#182#255#192#192#182#255#191#191#181#255'gg]'
+ +#255'ii_'#255#176#176#166#255#186#186#176#255#188#188#178#255#188#188#178#255
+ +#196#196#187#255#194#194#185#255#188#188#178#255#188#188#178#255#194#194#185
+ +#255#196#196#187#255#188#188#178#255#188#188#178#255#186#186#176#255#176#176
+ +#166#255'mmc'#255#136#136#129#214#148#148#138#255#149#149#139#255#149#149#139
+ +#255#149#149#139#255#149#149#139#255#149#149#139#255#149#149#139#255#149#149
+ +#139#255#149#149#139#255#149#149#139#255#149#149#139#255#149#149#139#255#149
+ +#149#139#255#149#149#139#255#139#139#132#214#186#186#182'\'#183#183#179#216
+ +#166#166#160#249#161#161#153#250#161#161#153#250#161#161#153#250#161#161#154
+ +#250#161#161#154#250#161#161#154#250#161#161#155#250#161#161#155#250#162#162
+ +#155#250#162#162#155#250#167#167#161#249#186#186#182#217#188#188#184']'#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0'm'#156#212#137'j'#154#210#251'f'#151#207#238#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +'p'#158#214#219'm'#156#212#255#133#177#218#255'Z'#145#185#255'`'#147#203#234
+ +#255#255#255#0#255#255#255#0#128#128#128#255'~~~'#255'|||'#255'zzz'#255'www'
+ +#255'uuu'#255'rrr'#255'q'#158#212#255'o'#158#214#255#135#178#220#255#171#211
+ +#232#255#169#208#230#255'X'#144#184#255'Y'#142#198#234#255#255#255#0#255#255
+ +#255#0'}}}'#255#153#153#153#255#153#153#153#255#154#154#154#255#154#154#154
+ +#255#155#155#155#255#155#155#155#255'o'#157#211#255#170#209#231#255#171#209
+ +#231#255#152#199#225#255#145#194#222#255'V'#143#183#255'R'#137#193#234#255
+ +#255#255#0#255#255#255#0'zzz'#255#153#153#153#255'R'#145'Y'#255#153#154#153
+ +#255#155#155#155#255#156#156#156#255#156#156#156#255'l'#154#208#255#167#206
+ +#229#255#143#193#223#255#137#189#220#255#139#189#220#255'S'#141#182#255'K'
+ +#132#188#234#255#255#255#0#255#255#255#0'www'#255#154#154#154#255'='#138'E'
+ +#255'I'#138'O'#255#156#156#156#255#157#157#157#255#157#157#157#255'f'#150#204
+ +#255#162#203#227#255#137#189#220#255#131#185#218#255#132#185#218#255'Q'#139
+ +#181#255'C~'#182#234'D'#148'M'#255'B'#145'K'#255'?'#141'H'#255'='#137'E'#255
+ +']'#164'e'#255'Z'#160'a'#255'E'#131'K'#255#158#158#158#255#158#158#158#255'`'
+ +#146#201#255#158#199#226#255#131#184#218#255'}'#180#215#255'~'#179#215#255'O'
+ +#137#180#255';y'#177#234'A'#144'J'#255#148#210#159#255#145#208#154#255#141
+ +#205#150#255#137#203#146#255#132#200#141#255'Q'#152'X'#255'A|F'#255#159#159
+ +#159#255'Z'#142#196#255#152#195#224#255'|'#179#215#255't'#175#214#255'^'#196
+ +#237#255'K'#136#179#255'4s'#171#234'>'#139'F'#255#143#206#153#255'}'#198#135
+ +#255'x'#195#129#255's'#192'|'#255't'#192'|'#255'y'#194#129#255'I'#144'O'#255
+ +'T'#127'W'#255'T'#137#191#255#148#191#221#255'u'#173#212#255'c'#184#225#255
+ +'K'#212#255#255'B'#139#184#255',n'#166#234';'#135'B'#255#137#203#146#255#132
+ +#200#141#255#128#198#136#255'{'#195#131#255'w'#193#127#255'G'#143'M'#255';t?'
+ +#255#161#161#161#255'L'#132#186#255#141#187#219#255'n'#168#209#255'f'#166#209
+ +#255'_'#180#223#255'G'#133#177#255'%i'#161#234'7'#130'>'#255'4~;'#255'1y7'
+ +#255'.u4'#255'I'#145'P'#255'F'#143'L'#255'9s='#255#161#161#161#255#162#162
+ +#162#255'E~'#180#255#136#183#217#255'g'#163#207#255'a'#158#204#255'c'#159#204
+ ,#255'E'#131#177#255#31'd'#156#234#255#255#255#0#255#255#255#0'```'#255#160
+ +#160#160#255'=vA'#255'6q9'#255#162#162#162#255#162#162#162#255#163#163#163
+ +#255'=y'#176#255#130#179#215#255'b'#159#204#255'Z'#154#201#255'^'#155#202#255
+ +'C'#129#175#255#25'`'#152#234#255#255#255#0#255#255#255#0'\\\'#255#161#161
+ +#161#255'~'#173#255#12'W'#143#234#255#255#255
+ +#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#29'c'#155#22#25'`'#152'9'#20']'#149'b'
+ +#16'Z'#146#136#13'X'#144#164#19'\'#146#252#12'W'#143#237#0#0#0#0#0#0#0#0#140
+ +#140#140'0'#140#140#140#175#140#140#140#255#140#140#140#255#140#140#140#255
+ +#140#140#140#239#140#140#140#159#140#140#140#16#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#140#140#140'`'#140#140#140#255#154#154#154#255#212
+ +#211#210#255#226#225#223#255#226#224#220#255#205#201#195#255#147#147#146#255
+ +#140#140#140#239#140#140#140'0'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#140
+ +#140#140'0'#140#140#140#255#183#183#183#255#255#254#253#255#255#254#252#255
+ +#255#253#249#255#255#253#249#255#255#254#252#255#248#242#232#255#162#159#156
+ +#255#140#140#140#223#140#140#140#16#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#140#140
+ +#140#175#154#154#154#255#255#254#253#255#255#252#248#255#255#251#244#255#255
+ +#249#239#255#255#247#234#255#255#246#232#255#255#250#242#255#241#232#219#255
+ +#147#146#145#255#140#140#140'p'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#140#140#140
+ +#255#212#211#210#255#255#252#249#255#255#251#244#255#255#249#239#255#255#247
+ +#235#255#255#245#230#255#255#243#226#255#255#242#221#255#255#242#221#255#183
+ +#177#167#255#140#140#140#191#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#140#140#140#255
+ +#226#224#221#255#255#251#244#255#255#249#240#255#255#247#235#255#255#245#230
+ +#255#255#243#226#255#255#242#221#255#255#240#217#255#255#238#212#255#198#188
+ +#174#255#140#140#140#239#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#140#140#140#255#226
+ +#223#218#255#255#249#240#255#255#247#235#255#255#245#231#255#255#244#226#255
+ +#255#242#221#255#255#240#217#255#255#238#212#255#255#236#208#255#198#187#172
+ +#255#140#140#140#207#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#140#140#140#239#190#188
+ +#183#255#255#247#236#255#255#245#231#255#255#244#226#255#255#242#222#255#255
+ +#240#217#255#255#238#213#255#255#236#208#255#255#235#203#255#162#158#151#255
+ +#140#140#140#175#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#140#140#140#128#147#147#146
+ +#255#241#232#220#255#255#244#227#255#255#242#222#255#255#240#217#255#255#238
+ +#213#255#255#236#208#255#255#235#204#255#219#204#181#255#140#140#140#255#140
+ +#140#140'P'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#140#140#140#16#140#140#140#207
+ +#162#159#156#255#233#223#207#255#255#240#218#255#255#238#213#255#255#236#208
+ +#255#255#235#204#255#219#204#181#255#147#146#144#255'|||'#255#129#129#129#207
+ +#140#140#140#16#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#140#140#140#16#140#140#140
+ +#191#140#140#140#255#162#159#154#255#190#182#171#255#183#176#165#255#154#152
+ +#148#255#140#140#140#255'```'#255'<<<'#255'aaa'#255#129#129#129#207#140#140
+ +#140#16#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#140#140#140'P'#140#140#140
+ +#159#140#140#140#191#140#140#140#191#140#140#140#143'TTTP'#2#2#2#239#22#22#22
+ +#255';;;'#255'aaa'#255#129#129#129#207#140#140#140#16#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1#1#1'0'#2#2#2#239
+ +#21#21#21#255';;;'#255'aaa'#255#129#129#129#207#140#140#140#16#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1#1#1'0'#2
+ +#2#2#239#21#21#21#255';;;'#255'```'#255#128#128#128#207#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1#1#1'0'#2
+ +#2#2#239#21#21#21#255':::'#255'```'#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#1#1#1' '#2#2#2#207
+ +#20#20#20#255'999'#207#0#0#9'TTrayIcon'#9'MTrayIcon'#9'PopUpMenu'#7#9'TrayPo'
+ +'pup'#9'Icon.Data'#10#242#19#0#0#238#19#0#0#0#0#1#0#1#0'('#30#0#0#1#0' '#0
+ +#216#19#0#0#22#0#0#0'('#0#0#0'('#0#0#0'<'#0#0#0#1#0' '#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#12#17'E'#1#0#0#0#0'F['#136#0#0#0#0#0#26'9o3'#9
+ +#30'o'#255#8#25'r'#255#9#25'r'#255#7#24'r'#255#8#24'q'#255#12'7'#144#255#21
+ +'w'#218#255#21'z'#220#255#22'z'#223#255#23'x'#225#255#23'v'#220#255#18'W'#179
+ +#255#12')x'#255#10#23'a'#255#10#20'_'#255#10#21'`'#255#9#21'a'#255#9#21'`'
+ +#255#9#21'e'#255#9#23'n'#255#9#22'o'#255#9#22'o'#255#8#22'o'#255#9#22'p'#255
+ ,#9#23'm'#255#8#22'i'#255#11#22'b'#255#12#19'F'#255#13#17'E'#255#12#17'C'#255
+ +#12#16'C'#255#12#16'C'#255#12#15'B'#255#12#15'C'#255#12#16'D'#255#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#16'+q'#175#7#26't'#255#8#26't'#255#9#25't'#255#8#25't'
+ +#255#8#25's'#255#17'Y'#185#255#24'{'#226#255#25'|'#227#255#23'{'#230#255#24
+ +'{'#230#255#24'|'#230#255#25'}'#232#255#24'x'#225#255#19'['#188#255#11'"o'
+ +#255#10#19'_'#255#11#20'b'#255#10#21'c'#255#10#20'c'#255#9#20'd'#255#9#23'o'
+ +#255#8#23'r'#255#8#23's'#255#9#22's'#255#8#23'r'#255#9#22'n'#255#10#23'n'#255
+ +#11#19'Q'#255#13#17'D'#255#12#17'D'#255#12#16'E'#255#12#16'E'#255#13#16'E'
+ +#255#13#16'D'#255#12#16'E'#255#0#0#0#0#0#0#0#0#0#0#0#0'2Hl5'#8#27'h'#249#9#25
+ +'x'#254#8#25'w'#255#7#25'v'#255#7#24'u'#255#7#27's'#255#23'n'#212#255#26#127
+ +#228#255#26'|'#230#255#25'}'#233#255#25'}'#231#255#23'~'#230#255#24'{'#233
+ +#255#24'{'#232#255#23'}'#231#255#24'l'#206#255#11#29'l'#255#10#21'c'#255#10
+ +#21'c'#255#10#22'f'#255#9#20'b'#255#9#20'd'#255#9#23's'#255#7#23's'#255#7#23
+ +'r'#255#7#23'r'#255#9#23'r'#255#9#22'r'#255#11#22'b'#255#12#17'G'#255#12#16
+ +'G'#255#11#17'F'#255#10#16'E'#255#10#15'F'#255#12#15'D'#255#12#16'E'#255#0#0
+ +#0#0#0#0#0#0#131#137#134#0#30'2i'#130#8#28's'#255#8#26'w'#255#8#26'y'#255#7
+ +#24'x'#255#8#24'v'#255#7#28'v'#255#24'{'#224#255#26'~'#228#255#24#127#231#255
+ +#24'}'#232#255#24'~'#233#255#24'}'#233#255#23'}'#232#255#25'}'#232#255#24'~'
+ +#232#255#21#127#232#255#21'a'#196#255#8#22'd'#255#11#21'c'#255#10#21'e'#255#9
+ +#22'd'#255#10#20'b'#255#8#21'f'#255#7#23'r'#255#7#24't'#255#7#23'v'#255#8#23
+ +'r'#255#7#22'r'#255#8#23'q'#255#11#18'N'#255#12#17'G'#255#12#16'F'#255#11#16
+ +'H'#255#10#16'G'#255#12#16'E'#255#11#16'F'#255#0#0#0#0'z~t'#0'>U'#139#0#18'&'
+ +'n'#145#10#27'x'#255#8#26'x'#255#9#25'x'#255#7#25'u'#255#8#24'u'#255#7#27'u'
+ +#255#28'y'#229#255#28#127#233#255#28#129#236#255#25'~'#235#255#26'|'#234#255
+ +#26'}'#233#255#26'}'#232#255#25'}'#231#255#24'{'#232#255#25'|'#231#255#31#129
+ +#241#255#11#30'q'#255#10#21'b'#255#11#21'd'#255#9#21'b'#255#9#20'e'#255#9#20
+ +'b'#255#9#21'k'#255#8#23's'#255#7#22'w'#255#8#24'v'#255#8#22'u'#255#8#23'v'
+ +#255#11#21'['#255#13#16'I'#255#12#15'I'#255#11#16'I'#255#12#15'I'#255#13#15
+ +'E'#255#12#14'E'#255#0#0#0#0#0#0#0#0'frw'#17#19'(q'#188#8#26'x'#255#8#25'y'
+ +#255#9#25'w'#255#8#23's'#255#8#24'w'#255#7#24'v'#255#24']'#185#255'%Pu'#255
+ +'!>\'#255'0c'#147#255#27'c'#173#255#29'~'#230#255#29'~'#235#255#29'}'#233#255
+ +#26'|'#236#255#26'|'#235#255#27#130#240#255#17'2'#140#255#10#20'b'#255#10#22
+ +'d'#255#11#20'f'#255#10#20'e'#255#10#20'a'#255#8#20'f'#255#7#23'v'#255#8#22
+ +'w'#255#9#22'w'#255#8#22't'#255#8#22'x'#255#11#21'f'#255#12#17'N'#255#13#17
+ +'O'#255#12#16'K'#255#13#16'I'#255#12#16'F'#255#12#15'G'#255#0#0#0#0'hb'#127#0
+ +#6'(k'#5#13'$x'#218#9#26'y'#255#10#26'x'#255#10#23'o'#255#8#23'w'#255#9#24'w'
+ +#255#7#27'x'#255#23'c'#199#255#29'b'#168#255#31';['#255'x'#142#158#255'k'#128
+ +#186#255#29'2d'#255' t'#211#255#30'}'#235#255#30'{'#234#255#28'|'#234#255#25
+ +'~'#238#255#20'U'#188#255#9#18'b'#255#11#21'd'#255#11#21'e'#255#11#20'b'#255
+ +#10#20'c'#255#9#19'f'#255#8#23'u'#255#9#23'w'#255#8#22'v'#255#9#21'r'#255#8
+ +#22'w'#255#9#22'n'#255#10#17'Y'#255#13#20'^'#255#13#16'J'#255#13#15'H'#255#12
+ +#15'C'#255#13#14'I'#255'}}'#131'1'#0#0#0#0'nx'#138':'#7' s'#232#9#28'x'#255
+ +#10#27'u'#255#8#25'q'#255#7#25'x'#255#8'%'#131#255#23'v'#222#255#27#130#228
+ +#255#31'x'#215#255#24'h'#192#255#21#128#231#255#19'j'#199#255'5x'#191#255'#J'
+ +'k'#255#25'j'#187#255#24#128#228#255#25'~'#231#255#22#129#234#255#8'i'#213
+ +#255#10'7'#144#255#9#26'g'#255#8#20'_'#255#9#19'a'#255#8#20'b'#255#8' w'#255
+ +#8#27'z'#255#8#23'y'#255#8#24'w'#255#7#23'r'#255#8#23'y'#255#9#24'r'#255#9#18
+ +'a'#255#11#23'h'#255#11#17'L'#255#13#16'H'#255#11#15'H'#255#10#15'I'#255'~|'
+ +#134#26#127'z'#131'%Yh{T'#9#31'k'#255#9#29'z'#255#9#27'r'#255#9#24's'#255#8
+ +#29'{'#255#20'h'#205#255'('#128#218#255#19'B'#145#255#12'2'#130#255#12'2'#129
+ +#255#23'L'#156#255#31#136#242#255#28#128#233#255#28'~'#228#255#27'c'#177#255
+ +#26'u'#213#255#26#127#230#255#24#128#235#255#8'h'#214#255#8'`'#210#255#7'T'
+ +#192#255#7'F'#171#255#8'='#158#255#7'@'#164#255#12'T'#193#255#9'$'#133#255#8
+ +#24'w'#255#9#25'v'#255#9#22'q'#255#9#23'x'#255#10#23'q'#255#9#19'h'#255#12#22
+ +'n'#255#13#17'L'#255#12#15'I'#255#11#15'K'#255#11#15'K'#255#0#0#0#0'gyy+?a'
+ +#147's'#11#28'd'#255#10#19'T'#255#12#28'e'#255#9#24'l'#255#12'<'#158#255'$|'
+ +#214#255#10'&f'#255#13':'#141#255#9'5'#135#255#13'3'#127#255#14#22'.'#255#18
+ +'9q'#255#31'~'#229#255#29'|'#230#255#30#127#234#255#25'h'#196#255#27'~'#231
+ +#255#25#127#238#255#8'h'#215#255#7'b'#211#255#8'['#201#255#6'`'#211#255#6'b'
+ +#212#255#8'c'#212#255#9'`'#209#255#12';'#162#255#8#23'x'#255#11#26'r'#255#8
+ +#20'`'#255#7#23'z'#255#10#22'q'#255#8#20'm'#255#11#22'o'#255#13#17'L'#255#12
+ +#16'J'#255#11#16'K'#254#12#15'I'#255#0#0#0#0#0#0#0#0'!P'#139'-'#11'$n'#255#12
+ +#25'P'#255#11#21'J'#255#7#22'd'#255#19'U'#184#255#18'e'#208#255#15'r'#235#255
+ +#15'y'#244#255#13'j'#215#255#14'K'#164#255#15'(Y'#255#9#19'3'#255#22'N'#163
+ ,#255#28#128#231#255#29#127#232#255#29#130#236#255#25'n'#209#255#26#128#235
+ +#255#9'`'#205#255#7'_'#206#255#7'b'#214#255#6'c'#216#255#7'c'#213#255#8']'
+ +#205#255#6']'#207#255#13'L'#188#255#7#23'y'#255#13#26'h'#255#8#17'X'#255#8#23
+ +'x'#255#10#22'n'#255#8#21's'#255#11#22'm'#255#12#17'K'#255#10#16'J'#255#11#15
+ +'L'#255#14#17'B'#225'ov'#143'W'#0#0#0#0#14'1t'#2#12'$m'#173#11#19'J'#255#12
+ +#20'I'#255#9#22']'#255#12'R'#186#255#17's'#236#255#13'u'#240#255#12's'#240
+ +#255#12's'#243#255#14'w'#238#255#15'd'#205#255#10'?'#156#255#14'Q'#184#255#27
+ +'|'#233#255#27#127#236#255#26#127#239#255#27's'#216#255#22't'#222#255#7'g'
+ +#218#255#6'd'#216#255#6'c'#214#255#8'Z'#202#255#7'Y'#207#255#7'd'#214#255#6
+ +'b'#219#255#13'P'#195#255#9#25'u'#255#13#20'P'#255#8#18'^'#255#8#24'z'#255#9
+ +#21'q'#255#6#22'y'#255#12#22'h'#255#13#16'K'#255#12#16'L'#254#13#16'J'#255#23
+ +#21'=@Vj|'#18'Ll'#131')T'#128#156#24#15'4'#131'Z'#10#29'f'#251#11#22'I'#255#8
+ +#18'P'#255#11'Z'#199#255#10'_'#209#255#8'j'#226#255#8'j'#227#255#9'j'#230#255
+ +#10'm'#234#255#12'q'#241#255#12't'#249#255#12'n'#232#255#28'~'#239#255#28#128
+ +#239#255#26'|'#233#255#23'i'#209#255#22'k'#212#255#8'['#202#255#8']'#206#255
+ +#7'\'#206#255#6'`'#213#255#7'a'#218#255#6'a'#219#255#6'f'#220#255#15'D'#167
+ +#255#10#23'd'#255#10#16'H'#255#7#20'l'#255#7#23'{'#255#7#22'z'#255#8#22'|'
+ +#255#12#21'b'#255#12#17'L'#254#11#16'M'#255#16#15'F'#211':.C'#17'q'#161#195
+ +#15'P'#135#177'('#153#148'~'#1#18'9'#132'9'#7#28'y'#248#11#27'`'#255#9#24'W'
+ +#255#8'Z'#200#255#7']'#204#255#7'd'#214#255#7'd'#213#255#6'd'#215#255#6'e'
+ +#219#255#7'h'#221#255#7'i'#230#255#7'd'#217#255#26'|'#231#255#27#128#236#255
+ +#17'l'#220#255#7'Z'#207#255#8'c'#217#255#8'`'#214#255#7'_'#213#255#7'_'#211
+ +#255#7'c'#217#255#6'b'#220#255#6'd'#218#255#7'h'#221#255#17'4'#130#255#12#19
+ +'L'#255#8#16'T'#255#8#24'y'#255#8#23'y'#255#7#22'{'#255#9#24'w'#255#12#16'S'
+ +#255#12#17'N'#255#11#15'L'#255#28#23'='#146#0#0#0#0#0#0#0#0'I|'#170#20'?|'
+ +#167'2%V'#142'<'#9'$~'#246#10#31'|'#255#11#23'W'#255#7'9'#146#255#7'g'#217
+ +#255#10'b'#212#255#6'e'#214#255#6'f'#216#255#7'd'#216#255#6'c'#219#255#7'c'
+ +#220#255#8'e'#219#255#18'n'#221#255#17'o'#228#255#6']'#212#255#7'c'#219#255#7
+ +'_'#213#255#6'^'#213#255#6'c'#219#255#6'b'#219#255#7'c'#221#255#7'c'#219#255
+ +#6'd'#218#255#13'i'#219#255#11#27'Z'#255#10#16'G'#255#8#21'o'#255#7#23'z'#255
+ +#7#23'|'#255#8#23'|'#255#12#21'c'#255#11#17'P'#255#10#16'O'#255#13#17'H'#255
+ +''''#24'*-'#255#255#255#1'\VQ'#4'V'#130#165'-?{'#166':'#161#255#11#19'S'
+ +#255#12#16'P'#255#11#17'P'#254#12#16'Q'#255#17#18'F'#227'7'#24#24#10#0#0#0#0
+ +'('#24')'#0#0#0#0#0#0#0#0#0#0#0#0#0#148#173#153#0#0#0#0#0'?Bef'#10#29'n'#253
+ +#8#24#127#254#8#25#132#255#7#24#132#255#7#24#129#255#7#25'|'#255#8#20'j'#255
+ +#6#24'}'#255#7#24#128#255#9#23'i'#255#11'!k'#255#9'T'#191#255#6'm'#236#255#6
+ +'l'#233#255#6'l'#238#255#14'l'#230#255#17'='#144#255#8#21'h'#255#7#24#128#255
+ +#7#24#131#255#7#24#129#255#8#23#127#255#8#23'~'#255#6#28#129#255#8'U'#201#255
+ +#12'2'#137#255#11#18'S'#255#10#17'P'#254#10#17'Q'#255#11#17'O'#251#24#20'=Q'
+ +#0#0#0#0'"'#20'/'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'F@G/'#27
+ +'(a'#238#7#24's'#255#7#24'x'#255#7#24'{'#254#8#25'~'#255#9#24'd'#255#7#19'i'
+ +#255#7#25'}'#255#6#25#127#255#9#26'y'#255#10#18'N'#255#10#16'G'#255#12'''o'
+ +#255#15'6'#133#255#17',t'#255#11#20'P'#255#7#16'Z'#255#8#24#127#255#7#23#129
+ +#255#8#23#131#255#8#24'~'#255#7#23#127#255#7#23#127#255#10'+'#139#255#12'7'
+ +#146#255#12#27'b'#254#9#17'R'#255#10#17'R'#255#10#17'O'#255#25#18'>'#143#0#0
+ +#0#0'- 6'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#31')<'#0#0#0#0#0
+ +'(*N9'#16#25'['#175#10#24'j'#255#9#23's'#255#10#22'_'#255#9#17'T'#254#7#22'v'
+ +#255#7#23#127#255#7#24#129#255#7#24#127#255#9#23'e'#255#10#17'K'#255#10#19'W'
+ +#255#8#16'N'#255#8#16'S'#255#7#20'i'#255#7#24'|'#255#6#24#129#255#7#24#130
+ +#255#7#24'x'#255#8#23'{'#255#8#23#129#255#9#24'x'#255#10#19'W'#255#10#16'O'
+ +#255#10#17'R'#254#10#16'R'#255#14#17'J'#180#20#18'?T'#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'nI8'#0'nK<'#0#0#0#0#0#0#0#0
+ +#0#29#24'.$'#14#21'>'#150#11#20'I'#239#6#16'Y'#255#6#23'~'#255#6#24#128#255#6
+ +#24#128#255#7#24#129#255#8#24'y'#255#10#19'U'#255#9#17'X'#255#9#24'}'#255#7
+ +#24#129#255#7#23#131#255#7#24#131#255#8#24#128#255#7#23'{'#255#8#22#129#255#6
+ +#24#129#255#7#23#128#254#11#23'k'#255#11#17'R'#255#10#18'Q'#253#11#17'K'#255
+ +#23#21':'#174'`GA'#15#0#0#0#0#31#17'#'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0'nI8'#0'pM;'#2'g@4'#0'O4,'#0#0#0#0#0#0#0#0#0'(%-'
+ +''''#10#21'c'#255#7#24#131#255#6#24#130#255#7#23#131#255#7#23#133#255#8#23
+ +#127#255#9#22't'#255#10#19'a'#255#9#20'a'#255#8#21'l'#255#9#21'p'#255#8#21'v'
+ +#255#8#22'|'#255#7#22#130#255#8#22#131#255#8#23#132#255#10#24'|'#255#13#19'['
+ +#255#15#18'L'#206#19#19'Ai'#23#22'/7"'#28'56*'#28'*)=$('#1#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#24'#^'#239#7#24#130#255#6#24#131#255#8#23
+ +#130#255#8#24#132#255#7#22#130#255#7#23'~'#255#8#23#132#255#6#23#130#255#7#23
+ +#129#255#8#23#132#255#7#23#131#255#8#22#131#255#7#23#133#255#8#24#132#254#8
+ +#24#128#255#12#23'`'#253#24#22'@u"'#24'4'#7#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'A6I'#0#0#0#0#0'/,RA'#14#27'p'#255
+ +#7#24#135#255#8#23#133#255#7#23#134#255#7#23#135#255#7#23#132#255#7#23#128
+ +#255#8#22#131#255#8#23#132#255#8#22#133#255#8#22#134#255#8#22#134#255#9#22
+ +#135#255#10#22#128#255#16#24'h'#188'!'#28'4$'#0#0#0#0#0#0#0#0#0#0#0#0'OC9'#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#14'\'
+ +#0#0#0#0#0' ''Rk'#13#30'o'#227#10#29'w'#229#11#28't'#229#10#29'u'#229#10#29
+ +'w'#229#11#29'v'#229#10#29'y'#229#10#29'v'#229#11#29't'#229#11#28'v'#229#10
+ +#28'w'#229#12#28'o'#232#28'#U'#143#23#25#31#4#0#0#0#0'E99'#0'SC;'#0'OC9'#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#248#0#0#0#0#0#0#0#240#0#0#0#0#0#0#0#240#0#0#0#0#0#0#0#224#0#0#0#0
+ +#0#0#0#224#0#0#0#0#0#0#0#224#0#0#0#0#0#0#0#224#0#0#0#0#0#0#0#224#0#0#0#0#0#0
+ +#0#224#0#0#0#0#0#0#0#224#0#0#0#0#0#0#0#224#0#0#0#0#0#0#0#224#0#0#0#1#0#0#0
+ +#240#0#0#0#1#0#0#0#240#0#0#0#1#0#0#0#240#0#0#0#3#0#0#0#240#0#0#0#3#0#0#0#240
+ +#0#0#0#7#0#0#0#240#0#0#0#7#0#0#0#224#0#0#0#15#0#0#0#224#0#0#0#15#0#0#0#224#0
+ +#0#0#15#0#0#0#224#0#0#0#31#0#0#0#240#0#0#0'?'#0#0#0#240#0#0#0'?'#0#0#0#248#0
+ +#0#0#255#0#0#0#254#0#0#1#255#0#0#0#255#128#0#15#255#0#0#0#255#128#0'?'#255#0
+ ,#0#0#255#192#0#127#255#0#0#0#255#224#0#255#255#0#0#0#7'Visible'#9#7'OnClick'
+ +#7#6'NoTray'#4'left'#3#16#2#3'top'#2'h'#0#0#10'TPopupMenu'#9'TrayPopup'#6'Im'
+ +'ages'#7#17'Mufasa_Image_List'#7'OnPopup'#7#14'TrayPopupPopup'#4'left'#3#16#2
+ +#3'top'#3#144#0#0#9'TMenuItem'#8'TrayStop'#6'Action'#7#16'ActionStopScript'#7
+ +'Enabled'#8#7'OnClick'#7#17'ActionStopExecute'#0#0#9'TMenuItem'#9'TrayPause'
+ +#6'Action'#7#17'ActionPauseScript'#7'Enabled'#8#7'OnClick'#7#18'ActionPauseE'
+ +'xecute'#0#0#9'TMenuItem'#8'TrayPlay'#6'Action'#7#15'ActionRunScript'#7'OnCl'
+ +'ick'#7#16'ActionRunExecute'#0#0#9'TMenuItem'#11'TrayDivider'#7'Caption'#6#1
+ +'-'#0#0#9'TMenuItem'#12'MenuItemShow'#7'Caption'#6#4'Show'#7'OnClick'#7#17'M'
+ +'enuItemShowClick'#0#0#9'TMenuItem'#12'MenuItemHide'#7'Caption'#6#4'Hide'#7
+ +'OnClick'#7#17'MenuItemHideClick'#0#0#9'TMenuItem'#12'MenuItemExit'#6'Action'
+ +#7#10'ActionExit'#11'Bitmap.Data'#10':'#4#0#0'6'#4#0#0'BM6'#4#0#0#0#0#0#0'6'
+ +#0#0#0'('#0#0#0#16#0#0#0#16#0#0#0#1#0' '#0#0#0#0#0#0#4#0#0'd'#0#0#0'd'#0#0#0
+ +#0#0#0#0#0#0#0#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#29'c'#155
+ +#22#25'`'#152'9'#20']'#149'b'#16'Z'#146#136#13'X'#144#164#19'\'#146#252#12'W'
+ +#143#237#153#153#153#255'qqq'#255'TTT'#255'QQQ'#255'OOO'#255'LLL'#255'JJJ'
+ +#255'GGG'#255'EEE'#255'%g'#157#255'2t'#168#255'=|'#175#255'G'#132#181#255'N'
+ +#138#186#255'>~'#173#255#12'W'#143#234#255#255#255#0#255#255#255#0'XXX'#255
+ +#162#162#162#255#162#162#162#255#163#163#163#255#164#164#164#255#164#164#164
+ +#255#165#165#165#255'/o'#165#255'x'#171#210#255'x'#171#211#255's'#167#209#255
+ +'i'#160#205#255'@'#127#174#255#15'Y'#145#234#255#255#255#0#255#255#255#0'\\\'
+ +#255#161#161#161#255''#255'4~;'#255'1y7'#255'.u4'
+ +#255'I'#145'P'#255'F'#143'L'#255'9s='#255#161#161#161#255#162#162#162#255'E~'
+ +#180#255#136#183#217#255'g'#163#207#255'a'#158#204#255'c'#159#204#255'E'#131
+ +#177#255#31'd'#156#234';'#135'B'#255#137#203#146#255#132#200#141#255#128#198
+ +#136#255'{'#195#131#255'w'#193#127#255'G'#143'M'#255';t?'#255#161#161#161#255
+ +'L'#132#186#255#141#187#219#255'n'#168#209#255'f'#166#209#255'_'#180#223#255
+ +'G'#133#177#255'%i'#161#234'>'#139'F'#255#143#206#153#255'}'#198#135#255'x'
+ +#195#129#255's'#192'|'#255't'#192'|'#255'y'#194#129#255'I'#144'O'#255'T'#127
+ +'W'#255'T'#137#191#255#148#191#221#255'u'#173#212#255'c'#184#225#255'K'#212
+ +#255#255'B'#139#184#255',n'#166#234'A'#144'J'#255#148#210#159#255#145#208#154
+ +#255#141#205#150#255#137#203#146#255#132#200#141#255'Q'#152'X'#255'A|F'#255
+ +#159#159#159#255'Z'#142#196#255#152#195#224#255'|'#179#215#255't'#175#214#255
+ +'^'#196#237#255'K'#136#179#255'4s'#171#234'D'#148'M'#255'B'#145'K'#255'?'#141
+ +'H'#255'='#137'E'#255']'#164'e'#255'Z'#160'a'#255'E'#131'K'#255#158#158#158
+ +#255#158#158#158#255'`'#146#201#255#158#199#226#255#131#184#218#255'}'#180
+ +#215#255'~'#179#215#255'O'#137#180#255';y'#177#234#255#255#255#0#255#255#255
+ +#0'www'#255#154#154#154#255'='#138'E'#255'I'#138'O'#255#156#156#156#255#157
+ +#157#157#255#157#157#157#255'f'#150#204#255#162#203#227#255#137#189#220#255
+ +#131#185#218#255#132#185#218#255'Q'#139#181#255'C~'#182#234#255#255#255#0#255
+ +#255#255#0'zzz'#255#153#153#153#255'R'#145'Y'#255#153#154#153#255#155#155#155
+ +#255#156#156#156#255#156#156#156#255'l'#154#208#255#167#206#229#255#143#193
+ +#223#255#137#189#220#255#139#189#220#255'S'#141#182#255'K'#132#188#234#255
+ +#255#255#0#255#255#255#0'}}}'#255#153#153#153#255#153#153#153#255#154#154#154
+ +#255#154#154#154#255#155#155#155#255#155#155#155#255'o'#157#211#255#170#209
+ +#231#255#171#209#231#255#152#199#225#255#145#194#222#255'V'#143#183#255'R'
+ +#137#193#234#255#255#255#0#255#255#255#0#128#128#128#255'~~~'#255'|||'#255'z'
+ +'zz'#255'www'#255'uuu'#255'rrr'#255'q'#158#212#255'o'#158#214#255#135#178#220
+ +#255#171#211#232#255#169#208#230#255'X'#144#184#255'Y'#142#198#234#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0'p'#158
+ +#214#219'm'#156#212#255#133#177#218#255'Z'#145#185#255'`'#147#203#234#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0'm'#156#212#137'j'#154#210#251'f'#151#207#238#7'OnCl'
+ +'ick'#7#17'ActionExitExecute'#0#0#0#10'TPopupMenu'#8'TabPopup'#6'Images'#7#17
+ +'Mufasa_Image_List'#4'left'#3#232#1#3'top'#2'h'#0#9'TMenuItem'#14'MenuItemTa'
+ +'bAdd'#6'Action'#7#12'ActionNewTab'#11'Bitmap.Data'#10':'#4#0#0'6'#4#0#0'BM6'
+ ,#4#0#0#0#0#0#0'6'#0#0#0'('#0#0#0#16#0#0#0#16#0#0#0#1#0' '#0#0#0#0#0#0#4#0#0
+ +'d'#0#0#0'd'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#4'9'#0#0#6'm'#0#153#5'i'#0#204#6'm'#0
+ +#153#4'9'#0#0#0#0#0#0#0#0#0#9#0#0#0#22#0#0#0#26#0#0#0#26#0#0#0#26#0#0#0#26#0
+ +#0#0#26#0#0#0#26#0#0#0#26#0#0#0#26#0#0#0#26#11#128#0#209'+'#223#26#255#11#128
+ +#0#209#0#0#0#22#0#0#0#9#13#13#13'g'#16#16#16#133#16#16#16#133#16#16#16#133#16
+ +#16#16#133#16#16#16#133#16#16#16#133#16#16#16#133#16#16#16#133#14'b'#4#207#14
+ +'~'#2#231#14'~'#2#231'='#226','#255#14'~'#2#231#14'~'#2#231#11'_'#2#176''''''
+ +'''{'#235#235#235#255#231#231#231#255#231#231#231#255#231#231#231#255#231#231
+ +#231#255#231#231#231#255#231#231#231#255#231#231#231#255';'#165'/'#255'R'#231
+ +'A'#255'R'#231'A'#255'R'#231'A'#255'R'#231'A'#255'R'#231'A'#255#18#137#5#229
+ +'222v'#234#234#234#255#226#226#226#255#226#226#226#255#226#226#226#255#226
+ +#226#226#255#226#226#226#255#226#226#226#255#226#226#226#255'f'#185'['#255'<'
+ +#171'-'#255'<'#171'-'#255'f'#235'U'#255'<'#171'-'#255'>'#173'/'#255#28'z'#17
+ +#200'888s'#237#237#237#255#230#230#230#255#230#230#230#255#230#230#230#255
+ +#230#230#230#255#230#230#230#255#230#230#230#255#230#230#230#255#230#230#230
+ +#255#230#230#230#255'>'#177'.'#255'u'#238'd'#255'>'#177'.'#255#237#237#237
+ +#255'888s>>>q'#240#240#240#255#235#235#235#255#235#235#235#255#235#235#235
+ +#255#235#235#235#255#235#235#235#255#235#235#235#255#235#235#235#255#235#235
+ +#235#255#235#235#235#255'k'#196'_'#255'@'#182'/'#255'k'#196'_'#255#240#240
+ +#240#255'>>>qDDDn'#243#243#243#255#239#239#239#255#239#239#239#255#239#239
+ +#239#255#239#239#239#255#239#239#239#255#239#239#239#255#239#239#239#255#239
+ +#239#239#255#239#239#239#255#239#239#239#255#239#239#239#255#239#239#239#255
+ +#243#243#243#255'DDDnIIIl'#247#247#247#255#244#244#244#255#244#244#244#255
+ +#244#244#244#255#244#244#244#255#244#244#244#255#244#244#244#255#244#244#244
+ +#255#244#244#244#255#244#244#244#255#244#244#244#255#244#244#244#255#244#244
+ +#244#255#247#247#247#255'IIIlMMMj'#250#250#250#255#248#248#248#255#248#248
+ +#248#255#248#248#248#255#248#248#248#255#248#248#248#255#248#248#248#255#248
+ +#248#248#255#248#248#248#255#248#248#248#255#248#248#248#255#248#248#248#255
+ +#248#248#248#255#250#250#250#255'MMMjQQQh'#253#253#253#255#252#252#252#255
+ +#252#252#252#255#252#252#252#255#252#252#252#255#252#252#252#255#252#252#252
+ +#255#252#252#252#255#252#252#252#255#252#252#252#255#252#252#252#255#252#252
+ +#252#255#252#252#252#255#253#253#253#255'QQQhUUUg'#255#255#255#255#255#255
+ +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
+ +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
+ +#255#255#255#255#255#255#255#255#255#255#255#255'UUUgPPPi'#187#187#187#255
+ +#186#186#186#255#184#184#184#255#182#182#182#255#179#179#179#255#176#176#176
+ +#255#174#174#174#255#171#171#171#255#168#168#168#255#166#166#166#255#163#163
+ +#163#255#160#160#160#255#158#158#158#255#156#156#156#255#3#3#3'fRRR['#198#198
+ +#198#212#220#220#220#255#216#217#217#255#213#213#213#255#208#209#209#255#204
+ +#204#204#255#200#200#200#255#198#198#198#255#198#197#197#255#201#197#197#255
+ +#205#198#198#255#209#199#199#255#215#203#203#255#196#184#184#212'RRR[UUU"UUU'
+ +'YUUUfUUUfUUUfUUUfUUUfUUUfUUUfUUUfUUUfUUUfUUUfUUUfUUUYUUU"'#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#7'OnClick'#7#19'Act'
+ +'ionNewTabExecute'#0#0#9'TMenuItem'#16'MenuItemTabClose'#7'Caption'#6#9'Clos'
+ +'e tab'#11'Bitmap.Data'#10':'#4#0#0'6'#4#0#0'BM6'#4#0#0#0#0#0#0'6'#0#0#0'('#0
+ +#0#0#16#0#0#0#16#0#0#0#1#0' '#0#0#0#0#0#0#4#0#0'd'#0#0#0'd'#0#0#0#0#0#0#0#0#0
+ +#0#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#0#0#0#9#0#0#0#22#0#0#0#26#0#0#0#26#0#0#0#26#0#0#0#26#0#0#0#26#0#0#0#26
+ +#0#0#0#26#0#0#0#26#0#0#0#26#0#0#0#26#0#0#0#26#0#0#0#26#0#0#0#22#0#0#0#9#13#13
+ +#13'g'#16#16#16#133#16#16#16#133#16#16#16#133#16#16#16#133#16#16#16#133#16#16
+ +#16#133#16#16#16#133#16#16#16#133#4#4'['#207#2#2's'#231#2#2's'#231#2#2's'#231
+ +#2#2's'#231#2#2's'#231#2#2'X'#176'''''''{'#235#235#235#255#231#231#231#255
+ +#231#231#231#255#231#231#231#255#231#231#231#255#231#231#231#255#231#231#231
+ +#255#231#231#231#255'//'#167#255'^^'#247#255'^^'#247#255'^^'#247#255'^^'#247
+ +#255'^^'#247#255#5#5#139#229'222v'#234#234#234#255#226#226#226#255#226#226
+ +#226#255#226#226#226#255#226#226#226#255#226#226#226#255#226#226#226#255#226
+ +#226#226#255'[['#190#255'--'#179#255'--'#179#255'--'#179#255'--'#179#255'//'
+ +#181#255#17#17#129#200'888s'#237#237#237#255#230#230#230#255#230#230#230#255
+ +#230#230#230#255#230#230#230#255#230#230#230#255#230#230#230#255#230#230#230
+ ,#255#230#230#230#255#230#230#230#255#230#230#230#255#230#230#230#255#230#230
+ +#230#255#237#237#237#255'888s>>>q'#240#240#240#255#235#235#235#255#235#235
+ +#235#255#235#235#235#255#235#235#235#255#235#235#235#255#235#235#235#255#235
+ +#235#235#255#235#235#235#255#235#235#235#255#235#235#235#255#235#235#235#255
+ +#235#235#235#255#240#240#240#255'>>>qDDDn'#243#243#243#255#239#239#239#255
+ +#239#239#239#255#239#239#239#255#239#239#239#255#239#239#239#255#239#239#239
+ +#255#239#239#239#255#239#239#239#255#239#239#239#255#239#239#239#255#239#239
+ +#239#255#239#239#239#255#243#243#243#255'DDDnIIIl'#247#247#247#255#244#244
+ +#244#255#244#244#244#255#244#244#244#255#244#244#244#255#244#244#244#255#244
+ +#244#244#255#244#244#244#255#244#244#244#255#244#244#244#255#244#244#244#255
+ +#244#244#244#255#244#244#244#255#247#247#247#255'IIIlMMMj'#250#250#250#255
+ +#248#248#248#255#248#248#248#255#248#248#248#255#248#248#248#255#248#248#248
+ +#255#248#248#248#255#248#248#248#255#248#248#248#255#248#248#248#255#248#248
+ +#248#255#248#248#248#255#248#248#248#255#250#250#250#255'MMMjQQQh'#253#253
+ +#253#255#252#252#252#255#252#252#252#255#252#252#252#255#252#252#252#255#252
+ +#252#252#255#252#252#252#255#252#252#252#255#252#252#252#255#252#252#252#255
+ +#252#252#252#255#252#252#252#255#252#252#252#255#253#253#253#255'QQQhUUUg'
+ +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
+ +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255
+ +#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255#255'UUU'
+ +'gPPPi'#187#187#187#255#186#186#186#255#184#184#184#255#182#182#182#255#179
+ +#179#179#255#176#176#176#255#174#174#174#255#171#171#171#255#168#168#168#255
+ +#166#166#166#255#163#163#163#255#160#160#160#255#158#158#158#255#156#156#156
+ +#255#3#3#3'fRRR['#198#198#198#212#220#220#220#255#216#217#217#255#213#213#213
+ +#255#208#209#209#255#204#204#204#255#200#200#200#255#198#198#198#255#198#197
+ +#197#255#201#197#197#255#205#198#198#255#209#199#199#255#215#203#203#255#196
+ +#184#184#212'RRR[UUU"UUUYUUUfUUUfUUUfUUUfUUUfUUUfUUUfUUUfUUUfUUUfUUUfUUUfUUU'
+ +'YUUU"'#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#10'ImageIndex'#2#16#7'OnClick'#7#21'MenuItemTabCloseClick'#0#0#9'TMen'
+ +'uItem'#22'MenuItemTabCloseOthers'#7'Caption'#6#16'Close Other Tabs'#7'OnCli'
+ +'ck'#7#27'MenuItemTabCloseOthersClick'#0#0#0#11'TActionList'#10'ActionList'#6
+ +'Images'#7#17'Mufasa_Image_List'#4'left'#3#192#1#3'top'#2'h'#0#7'TAction'#13
+ +'ActionTabNext'#7'Caption'#6#8'Next tab'#9'OnExecute'#7#20'ActionTabNextExec'
+ +'ute'#8'ShortCut'#3#9'@'#0#0#7'TAction'#13'ActionTabLast'#7'Caption'#6#8'Las'
+ +'t tab'#9'OnExecute'#7#20'ActionTabLastExecute'#8'ShortCut'#3#9'`'#0#0#7'TAc'
+ +'tion'#14'ActionCloseTab'#7'Caption'#6#10'&Close Tab'#10'ImageIndex'#2#16#9
+ +'OnExecute'#7#21'ActionCloseTabExecute'#26'SecondaryShortCuts.Strings'#1#6#7
+ +'Ctrl+F4'#0#8'ShortCut'#3'W@'#0#0#7'TAction'#12'ActionNewTab'#7'Caption'#6#8
+ +'New &Tab'#10'ImageIndex'#2#15#9'OnExecute'#7#19'ActionNewTabExecute'#8'Shor'
+ +'tCut'#3'T@'#0#0#7'TAction'#15'ActionNewScript'#7'Caption'#6#4'&New'#10'Imag'
+ +'eIndex'#2#9#9'OnExecute'#7#16'ActionNewExecute'#8'ShortCut'#3'N@'#0#0#7'TAc'
+ +'tion'#16'ActionOpenScript'#7'Caption'#6#5'&Open'#10'ImageIndex'#2#10#9'OnEx'
+ +'ecute'#7#17'ActionOpenExecute'#8'ShortCut'#3'O@'#0#0#7'TAction'#16'ActionSa'
+ +'veScript'#7'Caption'#6#5'&Save'#10'ImageIndex'#2#14#9'OnExecute'#7#17'Actio'
+ +'nSaveExecute'#8'ShortCut'#3'S@'#0#0#7'TAction'#18'ActionSaveScriptAs'#7'Cap'
+ +'tion'#6#9'Save as..'#9'OnExecute'#7#19'ActionSaveAsExecute'#0#0#7'TAction'
+ +#15'ActionRunScript'#7'Caption'#6#4'&Run'#9'OnExecute'#7#16'ActionRunExecute'
+ +#8'ShortCut'#2'x'#0#0#7'TAction'#17'ActionPauseScript'#7'Caption'#6#6'&Pause'
+ +#9'OnExecute'#7#18'ActionPauseExecute'#0#0#7'TAction'#16'ActionStopScript'#7
+ +'Caption'#6#5'&Stop'#9'OnExecute'#7#17'ActionStopExecute'#0#0#7'TAction'#13
+ +'ActionSaveAll'#7'Caption'#6#8'Save All'#10'ImageIndex'#2#21#9'OnExecute'#7
+ +#20'ActionSaveAllExecute'#8'ShortCut'#3'S`'#0#0#7'TAction'#16'ActionClearDeb'
+ +'ug'#7'Caption'#6#5'Clear'#10'ImageIndex'#2#4#9'OnExecute'#7#23'ActionClearD'
+ +'ebugExecute'#0#0#7'TAction'#15'ActionFindStart'#7'Caption'#6#9'&Find ...'#10
+ +'ImageIndex'#2#26#9'OnExecute'#7#22'ActionFindstartExecute'#8'ShortCut'#3'F@'
+ +#0#0#7'TAction'#9'ActionCut'#7'Caption'#6#4'Cu&t'#10'ImageIndex'#2#3#9'OnExe'
+ +'cute'#7#16'ActionCutExecute'#8'ShortCut'#3'X@'#0#0#7'TAction'#10'ActionCopy'
+ +#7'Caption'#6#5'&Copy'#10'ImageIndex'#2#22#9'OnExecute'#7#17'ActionCopyExecu'
+ +'te'#8'ShortCut'#3'C@'#0#0#7'TAction'#11'ActionPaste'#7'Caption'#6#6'&Paste'
+ +#10'ImageIndex'#2#11#9'OnExecute'#7#18'ActionPasteExecute'#8'ShortCut'#3'V@'
+ +#0#0#7'TAction'#12'ActionDelete'#7'Caption'#6#7'&Delete'#10'ImageIndex'#2#23
+ +#9'OnExecute'#7#19'ActionDeleteExecute'#8'ShortCut'#2'.'#0#0#7'TAction'#15'A'
+ ,'ctionSelectAll'#7'Caption'#6#11'&Select All'#9'OnExecute'#7#22'ActionSelect'
+ +'AllExecute'#8'ShortCut'#3'A@'#0#0#7'TAction'#10'ActionUndo'#7'Caption'#6#5
+ +'&Undo'#10'ImageIndex'#2#18#9'OnExecute'#7#17'ActionUndoExecute'#8'ShortCut'
+ +#3'Z@'#0#0#7'TAction'#10'ActionRedo'#7'Caption'#6#5'&Redo'#10'ImageIndex'#2
+ +#12#9'OnExecute'#7#17'ActionRedoExecute'#8'ShortCut'#3'Y@'#0#0#7'TAction'#14
+ +'ActionFindNext'#7'Caption'#6#10'Find &next'#9'OnExecute'#7#21'ActionFindNex'
+ +'tExecute'#8'ShortCut'#2'r'#0#0#7'TAction'#13'ActionReplace'#7'Caption'#6#11
+ +'R&eplace...'#9'OnExecute'#7#20'ActionReplaceExecute'#8'ShortCut'#3'R@'#0#0#7
+ +'TAction'#10'ActionExit'#7'Caption'#6#5'&Exit'#10'ImageIndex'#2#25#9'OnExecu'
+ +'te'#7#17'ActionExitExecute'#0#0#0#6'TTimer'#10'DebugTimer'#7'OnTimer'#7#18
+ +'ProcessDebugStream'#4'left'#3'8'#2#3'top'#2'h'#0#0#10'TPopupMenu'#11'Script'
+ +'Popup'#6'Images'#7#17'Mufasa_Image_List'#7'OnPopup'#7#16'ScriptPopupPopup'#4
+ +'left'#3'8'#2#3'top'#3#144#0#0#9'TMenuItem'#13'PopupItemUndo'#6'Action'#7#10
+ +'ActionUndo'#11'Bitmap.Data'#10':'#4#0#0'6'#4#0#0'BM6'#4#0#0#0#0#0#0'6'#0#0#0
+ +'('#0#0#0#16#0#0#0#16#0#0#0#1#0' '#0#0#0#0#0#0#4#0#0'd'#0#0#0'd'#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#24#166#195'i'#26#167#196'i'#0#160#196#24#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#160#196']f'#219#234#178#17#166#194#174#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#160#196'"C'#196#219#252'C'#197#216#254'#'#166#192#127#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#160#196#255#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#14#170#203#254']'#218#233#254'#'#166#192#239#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#160#196#255#0#160#196#255#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#158#193#26#2#172#200#255#136#231#242#254#17#162#194
+ +#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#5'y}'#17#0#160#196#255'v'#237#251#255#0
+ +#160#196#255#0#0#0#0#0#0#0#0#0#160#196'0'#0#153#185'P'#0#160#196#201'm'#230
+ +#245#255'v'#226#239#255#25#163#193#255#0#0#0#0#0#0#0#0#0#0#0#0#5'y}'#17#0#160
+ +#196#255'v'#237#251#255'v'#237#251#255#0#160#196#255#0#160#196#255#0#160#196
+ +#255#0#160#196#255#1#169#196#255'n'#225#238#255#15#201#223#255'i'#228#242#255
+ +#26#164#192#248#0#0#0#0#0#0#0#0#5'y}'#17#0#160#196#255'v'#237#251#255#4#195
+ +#218#255'v'#237#251#255'i'#234#249#255'i'#234#249#255'i'#234#249#255'i'#234
+ +#249#255#5#221#247#255#10#200#223#255#7#194#216#255'o'#220#235#255#27#163#191
+ +#244#0#0#0#0#5'y~'#17#0#160#196#255'y'#237#251#255'2'#226#248#255','#223#244
+ +#255#4#192#214#255#4#192#214#255#4#192#214#255#29#210#232#255#29#210#232#255
+ +#29#210#232#255#11#200#223#255'j'#229#243#255#27#171#197#248#21#160#188#203#0
+ +#0#0#0#0#160#196#255#173#243#251#255'/'#224#246#255'2'#226#248#255'2'#226#247
+ +#255'2'#226#247#255'/'#224#245#255')'#219#241#255#29#210#232#255#29#210#232
+ +#255#29#210#232#255'6'#217#236#255'@'#205#225#255#22#161#189#202#5'y}'#10#0#0
+ +#0#0#5'y}'#10#0#160#196#255#173#243#251#255'/'#224#246#255'2'#226#247#255')'
+ +#219#241#255'/'#224#245#255')'#219#241#255#22#205#227#255'6'#217#236#255'i'
+ +#231#246#255'A'#206#227#254#19#163#193#228#5'y}2'#0#0#0#0#0#0#0#0#0#0#0#0#5
+ +'y}'#17#0#160#196#255#173#243#251#255'1'#225#246#255' '#227#250#255's'#236
+ +#250#255'o'#235#250#255'n'#232#247#255'l'#232#247#248#20#161#188#212#20#163
+ +#193#213#5'y}'#28#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#5'y}'#17#0#160#196
+ +#255#173#243#251#255'%'#228#251#255#0#160#196#255#0#160#196#255#19#161#190
+ +#231#21#159#187#207#27#161#187#164#6'z|'#11#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#5'y}'#17#0#160#196#255#173#243#251#255#0#160#196#255#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#157#191#20#0#160#196#255#0#160#196#255#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#160#196#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#7'OnClick'#7#17'ActionUndoExecu'
+ +'te'#0#0#9'TMenuItem'#13'PopupItemRedo'#6'Action'#7#10'ActionRedo'#11'Bitmap'
+ +'.Data'#10':'#4#0#0'6'#4#0#0'BM6'#4#0#0#0#0#0#0'6'#0#0#0'('#0#0#0#16#0#0#0#16
+ +#0#0#0#1#0' '#0#0#0#0#0#0#4#0#0'd'#0#0#0'd'#0#0#0#0#0#0#0#0#0#0#0#255#255#255
+ +#0#0#0#0#0#0#160#196#24#26#167#196'i'#24#166#195'i'#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#255#255#255#0
+ +#0#0#0#0#17#166#194#174'f'#219#234#178#0#160#196']'#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#255#255#255#0
+ +'#'#166#192#127'C'#197#216#254'C'#196#219#252#0#160#196'"'#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#255
+ +#255#255#0'#'#166#192#239']'#218#233#254#14#170#203#254#0#0#0#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#160#196#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ ,#0#0#255#255#255#0#17#162#194#255#136#231#242#254#2#172#200#255#0#158#193#26
+ +#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#160#196#255#0#160#196#255#0#0#0#0#0#0#0#0
+ +#0#0#0#0#0#0#0#0#0#0#0#0#255#255#255#0#25#163#193#255'v'#226#239#255'm'#230
+ +#245#255#0#160#196#201#0#153#185'P'#0#160#196'0'#0#0#0#0#0#0#0#0#0#160#196
+ +#255'v'#237#251#255#0#160#196#255#5'y}'#17#0#0#0#0#0#0#0#0#0#0#0#0#255#255
+ +#255#0#26#164#192#248'i'#228#242#255#15#201#223#255'n'#225#238#255#1#169#196
+ +#255#0#160#196#255#0#160#196#255#0#160#196#255#0#160#196#255'v'#237#251#255
+ +'v'#237#251#255#0#160#196#255#5'y}'#17#0#0#0#0#0#0#0#0#255#255#255#0#27#163
+ +#191#244'o'#220#235#255#7#194#216#255#10#200#223#255#5#221#247#255'i'#234#249
+ +#255'i'#234#249#255'i'#234#249#255'i'#234#249#255'v'#237#251#255#4#195#218
+ +#255'v'#237#251#255#0#160#196#255#5'y}'#17#0#0#0#0#255#255#255#0#21#160#188
+ +#203#27#171#197#248'j'#229#243#255#11#200#223#255#29#210#232#255#29#210#232
+ +#255#29#210#232#255#4#192#214#255#4#192#214#255#4#192#214#255','#223#244#255
+ +'2'#226#248#255'y'#237#251#255#0#160#196#255#5'y~'#17#255#255#255#0#5'y}'#10
+ +#22#161#189#202'@'#205#225#255'6'#217#236#255#29#210#232#255#29#210#232#255
+ +#29#210#232#255')'#219#241#255'/'#224#245#255'2'#226#247#255'2'#226#247#255
+ +'2'#226#248#255'/'#224#246#255#173#243#251#255#0#160#196#255#255#255#255#0#0
+ +#0#0#0#5'y}2'#19#163#193#228'A'#206#227#254'i'#231#246#255'6'#217#236#255#22
+ +#205#227#255')'#219#241#255'/'#224#245#255')'#219#241#255'2'#226#247#255'/'
+ +#224#246#255#173#243#251#255#0#160#196#255#5'y}'#10#255#255#255#0#0#0#0#0#0#0
+ +#0#0#5'y}'#28#20#163#193#213#20#161#188#212'l'#232#247#248'n'#232#247#255'o'
+ +#235#250#255's'#236#250#255' '#227#250#255'1'#225#246#255#173#243#251#255#0
+ +#160#196#255#5'y}'#17#0#0#0#0#255#255#255#0#0#0#0#0#0#0#0#0#0#0#0#0#6'z|'#11
+ +#27#161#187#164#21#159#187#207#19#161#190#231#0#160#196#255#0#160#196#255'%'
+ +#228#251#255#173#243#251#255#0#160#196#255#5'y}'#17#0#0#0#0#0#0#0#0#255#255
+ +#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#160
+ +#196#255#173#243#251#255#0#160#196#255#5'y}'#17#0#0#0#0#0#0#0#0#0#0#0#0#255
+ +#255#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#160#196#255#0#160#196#255#0#157#191#20#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#255
+ +#255#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
+ +#160#196#255#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#7'OnClick'#7#17
+ +'ActionRedoExecute'#0#0#9'TMenuItem'#17'PopupItemDivider1'#7'Caption'#6#1'-'
+ +#0#0#9'TMenuItem'#12'PopupItemCut'#6'Action'#7#9'ActionCut'#11'Bitmap.Data'
+ +#10':'#4#0#0'6'#4#0#0'BM6'#4#0#0#0#0#0#0'6'#0#0#0'('#0#0#0#16#0#0#0#16#0#0#0
+ +#1#0' '#0#0#0#0#0#0#4#0#0'd'#0#0#0'd'#0#0#0#0#0#0#0#0#0#0#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#2#13#140#10#28''''#166#159'5?'#201#247'"-'#175#185#3#13#140#28#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#5#15#141#31#6#16#142'&'#1#11#138#3#255#255#255#0#18#28#155'p@'
+ +'K'#217#255',5'#191#221'=G'#209#255#29''''#169#164#255#255#255#0#255#255#255
+ +#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#15#25#151'c2='#199
+ +#248'7A'#207#255#31')'#171#176#0#10#134#24'#-'#180#175'5@'#204#253#0#9#133#24
+ +#28''''#168#149'4>'#197#248#4#14#140#20#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0'/:'#189#222'5?'#201#229'%0'#179#194'?J'
+ +#221#255#31'*'#172#194'$0'#178#203'2<'#198#242#0#10#134#3#17#27#157'w7A'#200
+ +#255#8#18#142' '#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0'2<'#195#236'#.'#173#175#255#255#255#0#26'%'#168#153'BP'#210#255
+ +#203#163'u'#254'AO'#214#255#22'!'#163#157'/9'#192#212'.8'#190#223#2#13#139#10
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#29'('
+ +#169#156';F'#204#255#8#18#144':'#7#17#144'S;H'#212#255#219#189#156#255#238
+ +#204#166#255'@L'#222#255':C'#209#255#15#25#152'i'#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#3#13#140#31',5'#185
+ +#215''#202#242'?L'#215#255#216#188#154#255#246#234#225#255#187
+ +#146'Z'#191#148'b'#24';'#145'a'#26#1#255#255#255#0#255#255#255#0#255#255#255
+ +#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#3#13#140#31#27'&'
+ +#167#153'*4'#186#204#17#28#157#137#187#152'i'#204#240#224#208#255#183#145'_'
+ +#197#143']'#20#11#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#0#11#136#2#255#255#255#0#180#142'Z'#144#246#234#221#255#225#205#180
+ +#255#177#141']'#191#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#179#140'W'#137#241#226#212#255#206#178
+ +#142#244#245#235#224#255#166#127'J'#157#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ ,#255#255#255#0#255#255#255#0#255#255#255#0#177#137'S'#132#238#223#206#255#151
+ +'f e'#194#163'|'#218#233#216#197#253#169#130'N{'#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#175#135'P|'#231#213#193#255#149'e'#31
+ +'+'#143'\'#18#27#197#167#131#231#213#188#157#225#181#147'db'#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#172#131'Ku'#222#201#175#255#149'd'#29
+ +#31#255#255#255#0#146'`'#23'&'#195#164'|'#235#181#144'c'#203#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#170#129'Go'#214#189#159#247#147'a'#25
+ +#16#255#255#255#0#255#255#255#0#150'f ,'#169#128'K'#203#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#168'}Bi'#204#176#139#224#145']'#20#9#255#255#255
+ +#0#255#255#255#0#255#255#255#0#146'`'#23#6#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#154'k''1'#170'~C'#161#146'`'#24#5#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#7'OnClick'#7
+ +#16'ActionCutExecute'#0#0#9'TMenuItem'#13'PopupItemCopy'#6'Action'#7#10'Acti'
+ +'onCopy'#11'Bitmap.Data'#10':'#4#0#0'6'#4#0#0'BM6'#4#0#0#0#0#0#0'6'#0#0#0'('
+ +#0#0#0#16#0#0#0#16#0#0#0#1#0' '#0#0#0#0#0#0#4#0#0'd'#0#0#0'd'#0#0#0#0#0#0#0#0
+ +#0#0#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#197'sB'#193#198'uE'#230#200'uE'#254#199'uE'#243#200'uE'#243
+ +#199'uE'#243#199'uE'#243#200'uF'#244#197'tD'#232#202#127'S'#241#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#199'y'
+ +'I'#237#252#243#236#255#250#241#232#255#250#240#231#255#251#241#233#255#251
+ +#242#234#255#251#242#234#255#251#242#235#255#253#244#238#255#202#128'T'#249
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#207#130'S'#255#239#241#231#255#255#233#217#255#255#234#219#255#255
+ +#233#217#255#255#231#215#255#255#229#210#255#255#226#203#255#239#242#232#255
+ +#206#129'V'#255#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#204#131'R'#251#251#245#238#255#255#233#217#255#255
+ +#234#219#255#255#233#217#255#255#231#215#255#255#229#210#255#255#226#203#255
+ +#251#246#239#255#204#131'U'#254#199'yJ'#185#200'yK'#206#200'uE'#221#199'uE'
+ +#212#200'uE'#212#199'uE'#212#202#132'R'#255#255#247#241#255#255#233#217#255
+ +#255#234#219#255#255#233#217#255#255#231#215#255#255#229#210#255#255#226#203
+ +#255#255#247#241#255#203#133'U'#254#200'|N'#211#252#243#236#222#250#241#232
+ +#222#250#240#231#222#251#241#233#222#251#242#234#222#228#186#145#255#255#247
+ +#240#255#255#231#213#255#253#231#214#255#253#230#212#255#252#228#208#255#251
+ +#227#203#255#250#220#194#255#254#243#232#255#204#134'V'#254#207#130'S'#222
+ +#239#241#231#222#255#233#217#222#255#234#219#222#255#233#217#222#255#231#215
+ +#222#228#187#145#255#255#247#242#255#254#231#213#255#254#231#213#255#253#229
+ +#209#255#250#224#202#255#249#222#196#255#247#217#188#255#253#242#231#255#204
+ +#135'W'#254#204#131'R'#219#251#245#238#222#255#233#217#222#255#234#219#222
+ +#255#233#217#222#255#231#215#222#228#187#146#255#254#247#241#255#252#229#210
+ +#255#252#228#209#255#251#226#204#255#249#221#196#255#246#215#187#255#243#209
+ +#175#255#250#239#228#255#204#135'X'#254#202#132'R'#219#255#247#241#222#255
+ +#233#217#222#255#234#219#222#255#233#217#222#255#231#215#222#228#187#146#255
+ +#254#246#240#255#252#226#205#255#252#227#205#255#250#223#200#255#247#217#188
+ +#255#245#233#221#255#250#243#235#255#251#248#243#255#202#131'S'#254#203#133
+ +'S'#219#255#247#240#222#255#231#213#222#253#231#214#222#253#230#212#222#252
+ +#228#208#222#228#187#147#255#254#245#237#255#252#222#197#255#251#224#199#255
+ +#249#220#194#255#245#211#180#255#254#249#243#255#250#226#196#255#236#193#147
+ +#255#195'}H'#147#203#134'T'#219#255#247#242#222#254#231#213#222#254#231#213
+ +#222#253#229#209#222#250#224#202#222#229#190#150#255#255#255#254#255#253#243
+ +#233#255#253#243#234#255#252#242#232#255#250#239#227#255#250#242#231#255#234
+ +#187#136#255#207#133'U'#179#180'i='#12#203#134'U'#219#254#247#241#222#252#229
+ +#210#222#252#228#209#222#251#226#204#222#249#221#196#222#234#195#157#255#230
+ +#191#150#255#228#187#146#255#228#187#146#255#209#160'l'#245#208#158'm'#246
+ +#204#150'_'#218#196'yB~'#178'g<'#9#255#255#255#0#203#134'U'#219#254#246#240
+ +#222#252#226#205#222#252#227#205#222#250#223#200#222#247#217#188#222#245#233
+ +#221#222#250#243#235#222#251#248#243#222#205#149'e'#220#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#203#134'V'#218
+ +#254#245#237#222#252#222#197#222#251#224#199#222#249#220#194#222#245#211#180
+ +#222#254#249#243#222#250#226#196#222#236#193#147#222#195'}H'#128#255#255#255
+ ,#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#202
+ +#133'T'#208#255#255#255#219#253#243#233#222#253#243#234#222#252#242#232#222
+ +#250#239#227#222#250#242#231#222#234#187#136#222#207#133'U'#156#180'i='#10
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#199'yG'#170#204#134'U'#206#204#136'W'#222#203#136'V'#219#204#136
+ +'V'#219#203#135'W'#219#202#131'P'#208#196'yBn'#178'g<'#8#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#7'OnClick'#7#17'ActionCopyExecute'#0#0#9'TMenuItem'#14'PopupItemPaste'
+ +#6'Action'#7#11'ActionPaste'#11'Bitmap.Data'#10':'#4#0#0'6'#4#0#0'BM6'#4#0#0
+ +#0#0#0#0'6'#0#0#0'('#0#0#0#16#0#0#0#16#0#0#0#1#0' '#0#0#0#0#0#0#4#0#0'd'#0#0
+ +#0'd'#0#0#0#0#0#0#0#0#0#0#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0'^^^'#2'[[[wXXX'#138'UUU'#138'RRR'#138'OOO'#138'LLL'#138
+ +'JJJ'#138'HHH'#138'FFF'#138'DDDf c'#152'J c'#152#207' c'#152#255' c'#152#255
+ +' c'#152#255'$c'#149#255'Xs'#136#255#247#247#247#255#240#240#240#255#240#240
+ +#240#255#240#240#240#255#240#240#240#255#240#240#240#255#240#240#240#255#243
+ +#243#243#250'FFF'#132' c'#152#194'b'#165#215#255'e'#168#218#255'd'#166#217
+ +#255'b'#164#216#255'b'#159#209#255'u'#142#164#255#239#239#239#255#231#231#231
+ +#255#231#231#231#255#231#231#231#255#231#231#231#255#230#230#230#255#230#230
+ +#230#255#236#236#236#250'III'#132' c'#152#255'h'#171#220#255'H'#142#207#255
+ +'F'#139#206#255'C'#135#205#255'D'#132#198#255'h'#133#161#255#240#240#240#255
+ +#180#180#180#255#180#180#180#255#180#180#180#255#180#180#180#255#180#180#180
+ +#255#179#179#179#255#237#237#237#250'LLL'#132' c'#152#255'i'#174#220#255'J'
+ +#147#209#255'H'#143#208#255'F'#139#206#255'G'#136#199#255'l'#136#163#255#240
+ +#240#240#255#232#232#232#255#232#232#232#255#231#231#231#255#231#231#231#255
+ +#231#231#231#255#231#231#231#255#237#237#237#250'OOO'#132' c'#152#255'k'#177
+ +#222#255'M'#151#211#255'K'#147#210#255'H'#143#208#255'J'#140#201#255'o'#139
+ +#165#255#241#241#241#255#182#182#182#255#181#181#181#255#181#181#181#255#180
+ +#180#180#255#180#180#180#255#180#180#180#255#237#237#237#250'SSS'#132' c'#152
+ +#255'm'#179#223#255'P'#156#213#255'N'#152#211#255'K'#148#209#255'L'#145#203
+ +#255'p'#142#167#255#241#241#241#255#233#233#233#255#233#233#233#255#232#232
+ +#232#255#232#232#232#255#232#232#232#255#231#231#231#255#237#237#237#250'VVV'
+ +#132' c'#152#255'p'#181#224#255'R'#159#215#255'P'#156#214#255'N'#152#212#255
+ +'O'#149#205#255's'#145#170#255#241#241#241#255#183#183#183#255#182#182#182
+ +#255#182#182#182#255#182#182#182#255#181#181#181#255#181#181#181#255#238#238
+ +#238#250'ZZZ'#132' c'#152#255's'#183#225#255'W'#163#215#255'S'#160#215#255'P'
+ +#157#213#255'R'#153#207#255'u'#148#172#255#248#248#248#255#242#242#242#255
+ +#242#242#242#255#242#242#242#255#242#242#242#255#242#242#242#255#241#241#241
+ +#255#244#244#244#250'^^^'#132' c'#152#255'v'#185#226#255'\'#167#217#255'X'
+ +#164#216#255'S'#160#215#255'S'#158#213#255'a'#139#169#255'd'#136#161#255'd'
+ +#135#161#255'c'#134#160#255'i'#135#159#255'Jh'#129#255'jjj'#138'hhh'#138'eee'
+ +#138'bbbc c'#152#255'z'#187#227#255'a'#170#219#255'Z'#165#217#255'S'#160#215
+ +#255'R'#159#215#255'R'#159#215#255'R'#159#215#255'R'#159#215#255'R'#159#215
+ +#255'b'#163#216#255' c'#152#255#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0' c'#152#255'|'#189#228#255'e'#174#221#255'b'#171#220#255'^'#168
+ +#218#255'\'#167#217#255'\'#167#217#255'\'#167#217#255'\'#167#217#255'R'#159
+ +#215#255'b'#163#216#255' c'#152#255#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0' c'#152#255#127#191#228#255'i'#178#222#255'J'#155#218#255'D'
+ +#151#220#255'C'#150#220#255'B'#150#220#255'B'#149#220#255'A'#149#219#255'Q'
+ +#158#214#255'l'#178#222#255' c'#152#255#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0' c'#152#224'q'#179#219#254'~'#191#228#255'N'#157#223#255
+ +#181#238#253#255'u'#212#240#255'u'#212#240#255#181#238#253#255'K'#155#222#255
+ +'n'#180#224#255'm'#179#223#249' c'#152#243#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0' c'#152'2 c'#152#178' c'#152#255'7u'#164#255#182#239
+ +#254#255#128#219#243#255#128#219#243#255#182#239#254#255'.n'#161#255' c'#152
+ +#255' c'#152#165' c'#152'S'#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0' c'#152'* c'#152#255' c'#152#255' c'#152
+ +#255' c'#152#255' c'#152#255' c'#152#240#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#7'OnClick'#7
+ +#18'ActionPasteExecute'#0#0#9'TMenuItem'#15'PopupItemDelete'#6'Action'#7#12
+ +'ActionDelete'#11'Bitmap.Data'#10':'#4#0#0'6'#4#0#0'BM6'#4#0#0#0#0#0#0'6'#0#0
+ +#0'('#0#0#0#16#0#0#0#16#0#0#0#1#0' '#0#0#0#0#0#0#4#0#0'd'#0#0#0'd'#0#0#0#0#0
+ +#0#0#0#0#0#0#255#255#255#0#255#255#255#0#0#0#0#6#0#0#0#14#0#0#0#22#0#0#0#30#0
+ +#0#0'%'#0#0#0'*'#0#0#0'+'#0#0#0')'#0#0#0'$'#0#0#0#29#0#0#0#21#0#0#0#13#0#0#0
+ +#4#255#255#255#0#255#255#255#0#255#255#255#0#0#0#255#1#0#0#211'F'#255#255#255
+ ,#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#0#0#211'F'#0#0#255#1#255#255#255#0#255#255#255#0#255
+ +#255#255#0#0#0#255#1#0#0#206#150#0#0#206#255#0#0#206'x'#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#0#0#206'x'#0#0
+ +#207#255#0#0#207#150#0#0#255#1#255#255#255#0#255#255#255#0#0#0#200'F'#0#0#200
+ +#255#0#0#200#255#0#0#201#255#0#0#202'x'#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#0#0#202'x'#0#0#201#255#0#0#201#255#0#0#201#255#0#0#200
+ +'F'#255#255#255#0#255#255#255#0#255#255#255#0#0#0#193'x'#0#0#195#255#0#0#195
+ +#255#0#0#195#255#0#0#196'x'#255#255#255#0#255#255#255#0#0#0#196'x'#0#0#195
+ +#255#0#0#195#255#0#0#195#255#0#0#196'x'#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#0#0#189'x'#0#0#189#255#0#0#189#255#0#0#189
+ +#255#0#0#189'x'#0#0#189'x'#0#0#189#255#0#0#189#255#0#0#189#255#0#0#189'x'#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#0#0#183'x'#0#0#183#255#0#0#183#255#0#0#183#255#0#0#183
+ +#255#0#0#183#255#0#0#183#255#0#0#183'x'#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#0#0#176'x'#0#0#177#255#0#0#177#255#0#0#177#255#0#0#177#255#0#0
+ +#179'x'#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#0#0
+ +#170'x'#0#0#171#255#0#0#171#255#0#0#171#255#0#0#172#255#0#0#172'x'#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#0#0#166'x'#0#0#165#255#0#0#165#255
+ +#0#0#165#255#0#0#166#255#0#0#166#255#0#0#166#255#0#0#166'x'#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#0#0#159'x'#0#0#159#255#0#0#159#255#0#0#159#255#0#0#159'x'#0#0#159'x'#0
+ +#0#160#255#0#0#160#255#0#0#160#255#0#0#159'x'#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#0#0#153'x'#0#0#153#255#0#0#153#255#0#0
+ +#153#255#0#0#153'x'#255#255#255#0#255#255#255#0#0#0#153'x'#0#0#154#255#0#0
+ +#154#255#0#0#154#255#0#0#153'x'#255#255#255#0#255#255#255#0#255#255#255#0#0#0
+ +#146'F'#0#0#147#255#0#0#147#255#0#0#147#255#0#0#149'x'#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#0#0#149'x'#0#0#148#255#0#0#148#255#0#0#148
+ +#255#0#0#149'F'#255#255#255#0#255#255#255#0#0#0#255#1#0#0#141#150#0#0#141#255
+ +#0#0#142'x'#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#0#0#142'x'#0#0#142#255#0#0#143#150#0#0#255#1#255#255#255
+ +#0#255#255#255#0#255#255#255#0#0#0#255#1#0#0#135'F'#255#255#255#0#255#255#255
+ +#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#0#0#135'F'#0#0#255#1#255#255#255#0#255#255#255#0#255#255#255#0#255
+ +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+ +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0
+ +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#7'OnClick'#7#19'Act'
+ +'ionDeleteExecute'#0#0#9'TMenuItem'#17'PopupItemDivider2'#7'Caption'#6#1'-'#0
+ +#0#9'TMenuItem'#18'PopupItemSelectAll'#6'Action'#7#15'ActionSelectAll'#7'OnC'
+ +'lick'#7#22'ActionSelectAllExecute'#0#0#9'TMenuItem'#17'PopupItemDivider3'#7
+ +'Caption'#6#1'-'#0#0#9'TMenuItem'#13'PopupItemFind'#6'Action'#7#14'ActionFin'
+ +'dNext'#7'OnClick'#7#21'ActionFindNextExecute'#0#0#9'TMenuItem'#16'PopupItem'
+ +'Replace'#6'Action'#7#13'ActionReplace'#7'Caption'#6#7'Replace'#7'OnClick'#7
+ +#20'ActionReplaceExecute'#0#0#0#14'TReplaceDialog'#10'dlgReplace'#7'Options'
+ +#11#6'frDown'#10'frFindNext'#12'frHideUpDown'#0#6'OnFind'#7#14'dlgReplaceFin'
+ +'d'#9'OnReplace'#7#17'dlgReplaceReplace'#4'left'#3'`'#2#3'top'#2'h'#0#0#6'TT'
+ +'imer'#11'UpdateTimer'#8'Interval'#3#16''''#7'OnTimer'#7#16'UpdateTimerCheck'
+ +#4'left'#3'`'#2#3'top'#3#144#0#0#0#0
+]);
\ No newline at end of file
diff --git a/branches/script-component/Projects/SAMufasaGUI/testunit.pas b/branches/script-component/Projects/SAMufasaGUI/testunit.pas
new file mode 100644
index 0000000..f344a3d
--- /dev/null
+++ b/branches/script-component/Projects/SAMufasaGUI/testunit.pas
@@ -0,0 +1,1880 @@
+{
+ This file is part of the Mufasa Macro Library (MML)
+ Copyright (c) 2009 by Raymond van Venetië and Merlijn Wajer
+
+ MML is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ MML is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with MML. If not, see .
+
+ See the file COPYING, included in this distribution,
+ for details about the copyright.
+
+ TestUnit/GUI for the Mufasa Macro Library
+}
+
+unit TestUnit;
+
+{$undef EditButtons}
+{$Undef ProcessMessages} //Define this for processmessages in ThreadSafeCall
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+ {$ifdef linux}cthreads,{$endif}Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
+ StdCtrls, Menus, ComCtrls, ExtCtrls, SynEdit, SynHighlighterPas, SynMemo,
+ //Client,
+ MufasaTypes,
+ mmlpsthread,synedittypes,
+ {$IFDEF MSWINDOWS} os_windows, {$ENDIF} //For ColorPicker etc.
+ {$IFDEF LINUX} os_linux, {$ENDIF} //For ColorPicker etc.
+ colourpicker, framescript, windowselector, lcltype, ActnList, StdActns,
+ SynExportHTML, SynEditKeyCmds, SynEditHighlighter, SynEditMarkupSpecialLine,
+ SynEditMarkupHighAll, SynEditMiscClasses, LMessages, Buttons, PairSplitter,
+ ColorBox , about, framefunctionlist, ocr, updateform, simbasettings;
+
+const
+ SimbaVersion = 462;
+
+type
+
+ { TMufasaTab }
+
+ TMufasaTab = class(Tobject)
+ private
+ PageCtrl : TPageControl;
+ public
+ TabSheet : TTabsheet;
+ ScriptFrame : TScriptFrame;
+ procedure Clear;//This will 'reset' the ScriptFrame
+ constructor Create(Page : TPageControl);
+ destructor Destroy; override;
+ end;
+
+// Tab
+ { TForm1 }
+
+ TForm1 = class(TForm)
+ ActionExit: TAction;
+ ActionReplace: TAction;
+ ActionFindNext: TAction;
+ ActionRedo: TAction;
+ ActionUndo: TAction;
+ ActionSelectAll: TAction;
+ ActionDelete: TAction;
+ ActionPaste: TAction;
+ ActionCopy: TAction;
+ ActionCut: TAction;
+ ActionFindStart: TAction;
+ ActionClearDebug: TAction;
+ ActionSaveAll: TAction;
+ ActionStopScript: TAction;
+ ActionSaveScript: TAction;
+ ActionSaveScriptAs: TAction;
+ ActionRunScript: TAction;
+ ActionPauseScript: TAction;
+ ActionNewScript: TAction;
+ ActionOpenScript: TAction;
+ ActionNewTab: TAction;
+ ActionCloseTab: TAction;
+ ActionTabLast: TAction;
+ ActionTabNext: TAction;
+ ActionList: TActionList;
+ CheckBoxMatchCase: TCheckBox;
+ frmFunctionList: TFunctionListFrame;
+ LabeledEditSearch: TLabeledEdit;
+ MainMenu: TMainMenu;
+ Memo1: TMemo;
+ MenuFile: TMenuItem;
+ MenuEdit: TMenuItem;
+ MenuHelp: TMenuItem;
+ MenuExtra: TMenuItem;
+ MenuItemAbout: TMenuItem;
+ MenuItemReportBug: TMenuItem;
+ MenuViewSettings: TMenuItem;
+ MenuItemExportHTML: TMenuItem;
+ MenuItemDivider9: TMenuItem;
+ TT_Cut: TToolButton;
+ TT_Copy: TToolButton;
+ TT_Paste: TToolButton;
+ ToolButton9: TToolButton;
+ UpdateTimer: TTimer;
+ ToolButton3: TToolButton;
+ TT_Update: TToolButton;
+ UpdateMenuButton: TMenuItem;
+ MenuitemFillFunctionList: TMenuItem;
+ MenuItemFunctionList: TMenuItem;
+ MenuItemHide: TMenuItem;
+ MenuItemDebugImage: TMenuItem;
+ MenuItemMainExit: TMenuItem;
+ MenuItemDivider6: TMenuItem;
+ PopupItemReplace: TMenuItem;
+ MenuItemReplace: TMenuItem;
+ dlgReplace: TReplaceDialog;
+ MenuItemColourHistory: TMenuItem;
+ MenuView: TMenuItem;
+ MenuItemFindNext: TMenuItem;
+ PopupItemDelete: TMenuItem;
+ MenuItemDelete: TMenuItem;
+ MenuItemDivider5: TMenuItem;
+ MenuItemSelectAll: TMenuItem;
+ PopupItemSelectAll: TMenuItem;
+ PopupItemDivider2: TMenuItem;
+ PopupItemPaste: TMenuItem;
+ PopupItemCopy: TMenuItem;
+ PopupItemCut: TMenuItem;
+ PopupItemDivider1: TMenuItem;
+ PopupItemRedo: TMenuItem;
+ PopupItemUndo: TMenuItem;
+ PopupItemDivider3: TMenuItem;
+ PopupItemFind: TMenuItem;
+ MenuItemFind: TMenuItem;
+ MenuItemDivider4: TMenuItem;
+ MenuItemDivider3: TMenuItem;
+ MenuItemCopy: TMenuItem;
+ MenuItemSaveAll: TMenuItem;
+ MenuItemTabCloseOthers: TMenuItem;
+ MenuItemTabAdd: TMenuItem;
+ MenuItemTabClose: TMenuItem;
+ MenuItemCloseTabs: TMenuItem;
+ MenuItemCloseTab: TMenuItem;
+ MenuItemNewTab: TMenuItem;
+ MenuItemDivider2: TMenuItem;
+ MenuItemDivider: TMenuItem;
+ PageControl1: TPageControl;
+ ScriptPopup: TPopupMenu;
+ SearchPanel: TPanel;
+ ScriptPanel: TPanel;
+ SpeedButtonSearch: TSpeedButton;
+ SplitterFunctionList: TSplitter;
+ TabPopup: TPopupMenu;
+ TB_SaveAll: TToolButton;
+ DebugTimer: TTimer;
+ TrayDivider: TMenuItem;
+ TrayPlay: TMenuItem;
+ TrayStop: TMenuItem;
+ TrayPause: TMenuItem;
+ MenuItemPause: TMenuItem;
+ MenuItemStop: TMenuItem;
+ MenuItemShow: TMenuItem;
+ MenuItemExit: TMenuItem;
+ MenuItemCut: TMenuItem;
+ MenuItemPaste: TMenuItem;
+ MenuItemNew: TMenuItem;
+ MenuItemSaveAs: TMenuItem;
+ MenuItemOpen: TMenuItem;
+ MenuItemRedo: TMenuItem;
+ MenuItemUndo: TMenuItem;
+ MenuItemSave: TMenuItem;
+ Mufasa_Image_List: TImageList;
+ MainMenu1: TMainMenu;
+ MenuItemScript: TMenuItem;
+ MenuItemRun: TMenuItem;
+ PanelMemo: TPanel;
+ SplitterMemoSynedit: TSplitter;
+ TrayPopup: TPopupMenu;
+ StatusBar: TStatusBar;
+ ToolBar1: TToolBar;
+ TB_Run: TToolButton;
+ TB_Pause: TToolButton;
+ TB_Stop: TToolButton;
+ ToolButton1: TToolButton;
+ TB_ReloadPlugins: TToolButton;
+ TB_Tray: TToolButton;
+ TB_NewTab: TToolButton;
+ TB_CloseTab: TToolButton;
+ TB_New: TToolButton;
+ ToolButton2: TToolButton;
+ TB_Open: TToolButton;
+ TB_Save: TToolButton;
+ ToolButton4: TToolButton;
+ TB_ClearDebug: TToolButton;
+ TB_PickColour: TToolButton;
+ TB_SelectClient: TToolButton;
+ ToolButton8: TToolButton;
+ MTrayIcon: TTrayIcon;
+ procedure ActionClearDebugExecute(Sender: TObject);
+ procedure ActionCloseTabExecute(Sender: TObject);
+ procedure ActionCopyExecute(Sender: TObject);
+ procedure ActionCutExecute(Sender: TObject);
+ procedure ActionDeleteExecute(Sender: TObject);
+ procedure ActionExitExecute(Sender: TObject);
+ procedure ActionFindNextExecute(Sender: TObject);
+ procedure ActionFindstartExecute(Sender: TObject);
+ procedure ActionNewExecute(Sender: TObject);
+ procedure ActionNewTabExecute(Sender: TObject);
+ procedure ActionOpenExecute(Sender: TObject);
+ procedure ActionPasteExecute(Sender: TObject);
+ procedure ActionPauseExecute(Sender: TObject);
+ procedure ActionRedoExecute(Sender: TObject);
+ procedure ActionReplaceExecute(Sender: TObject);
+ procedure ActionRunExecute(Sender: TObject);
+ procedure ActionSaveAllExecute(Sender: TObject);
+ procedure ActionSaveAsExecute(Sender: TObject);
+ procedure ActionSaveExecute(Sender: TObject);
+ procedure ActionSelectAllExecute(Sender: TObject);
+ procedure ActionStopExecute(Sender: TObject);
+ procedure ActionTabLastExecute(Sender: TObject);
+ procedure ActionTabNextExecute(Sender: TObject);
+ procedure ActionUndoExecute(Sender: TObject);
+ procedure CheckBoxMatchCaseClick(Sender: TObject);
+ procedure CloseFindPanel;
+ procedure editSearchListExit(Sender: TObject);
+ procedure editSearchListKeyDown(Sender: TObject; var Key: Word;
+ Shift: TShiftState);
+ procedure editSearchListKeyPress(Sender: TObject; var Key: char);
+ procedure FunctionListChange(Sender: TObject; Node: TTreeNode);
+ procedure FunctionListEnter(Sender: TObject);
+ procedure FunctionListExit(Sender: TObject);
+ procedure MenuItemColourHistoryClick(Sender: TObject);
+ procedure dlgReplaceFind(Sender: TObject);
+ procedure dlgReplaceReplace(Sender: TObject);
+ procedure EditSearchChange(Sender: TObject);
+ procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
+ procedure FormCreate(Sender: TObject);
+ procedure FormDestroy(Sender: TObject);
+ procedure FormShortCuts(var Msg: TLMKey; var Handled: Boolean);
+ procedure LabeledEditSearchEnter(Sender: TObject);
+ procedure LabeledEditSearchExit(Sender: TObject);
+ procedure LabeledEditSearchKeyDown(Sender: TObject; var Key: Word;
+ Shift: TShiftState);
+ procedure LabeledEditSearchKeyPress(Sender: TObject; var Key: char);
+ procedure MenuEditClick(Sender: TObject);
+ procedure MenuItemAboutClick(Sender: TObject);
+ procedure MenuItemCloseTabsClick(Sender: TObject);
+ procedure MenuItemDebugImageClick(Sender: TObject);
+ procedure MenuItemExportHTMLClick(Sender: TObject);
+ procedure MenuitemFillFunctionListClick(Sender: TObject);
+ procedure MenuItemHideClick(Sender: TObject);
+ procedure MenuItemReportBugClick(Sender: TObject);
+ procedure MenuItemShowClick(Sender: TObject);
+ procedure MenuItemTabCloseClick(Sender: TObject);
+ procedure MenuItemTabCloseOthersClick(Sender: TObject);
+ procedure MenuItemFunctionListClick(Sender: TObject);
+ procedure MenuViewSettingsClick(Sender: TObject);
+ procedure OnLinePSScript(Sender: TObject);
+ procedure ButtonPickClick(Sender: TObject);
+ procedure ButtonSelectorDown(Sender: TObject; Button: TMouseButton;
+ Shift: TShiftState; X, Y: Integer);
+ procedure NoTray(Sender: TObject);
+ procedure PageControl1Change(Sender: TObject);
+ procedure ButtonTrayClick(Sender: TObject);
+ procedure PageControl1Changing(Sender: TObject; var AllowChange: Boolean);
+ procedure PageControl1ContextPopup(Sender: TObject; MousePos: TPoint;
+ var Handled: Boolean);
+ procedure PageControl1DragDrop(Sender, Source: TObject; X, Y: Integer);
+ procedure PageControl1DragOver(Sender, Source: TObject; X, Y: Integer;
+ State: TDragState; var Accept: Boolean);
+ procedure PageControl1MouseDown(Sender: TObject; Button: TMouseButton;
+ Shift: TShiftState; X, Y: Integer);
+ procedure PageControl1MouseUp(Sender: TObject; Button: TMouseButton;
+ Shift: TShiftState; X, Y: Integer);
+ procedure PopupItemFindClick(Sender: TObject);
+ procedure ProcessDebugStream(Sender: TObject);
+ procedure ScriptPanelDockDrop(Sender: TObject; Source: TDragDockObject; X,
+ Y: Integer);
+ procedure ScriptPanelDockOver(Sender: TObject; Source: TDragDockObject; X,
+ Y: Integer; State: TDragState; var Accept: Boolean);
+ procedure ScriptPopupPopup(Sender: TObject);
+ procedure SpeedButtonSearchClick(Sender: TObject);
+ procedure SplitterFunctionListCanResize(Sender: TObject; var NewSize: Integer;
+ var Accept: Boolean);
+ procedure TrayPopupPopup(Sender: TObject);
+ procedure TT_UpdateClick(Sender: TObject);
+ procedure UpdateMenuButtonClick(Sender: TObject);
+ procedure UpdateTimerCheck(Sender: TObject);
+ private
+ PopupTab : integer;
+ FirstRun : boolean;//Only show the warnings the first run (path not existing one's)
+ SearchStart : TPoint;
+ LastTab : integer;
+ function GetScriptState: TScriptState;
+ procedure SetScriptState(const State: TScriptState);
+ function LoadSettingDef(Key : string; Def : string) : string;
+ public
+ DebugStream: String;
+ SearchString : string;
+ CurrScript : TScriptFrame; //The current scriptframe
+ CurrTab : TMufasaTab; //The current TMufasaTab
+ Tabs : TList;
+ Manager: TIOManager;
+ OCR_Fonts: TMOCR;
+ Picker: TMColorPicker;
+ Selector: TMWindowSelector;
+ procedure FunctionListShown( ShowIt : boolean);
+ property ScriptState : TScriptState read GetScriptState write SetScriptState;
+ procedure SafeCallThread;
+ function OpenScript : boolean;
+ function LoadScriptFile(filename : string) : boolean;
+ function SaveCurrentScript : boolean;
+ function SaveCurrentScriptAs : boolean;
+ function CanExitOrOpen : boolean;
+ function ClearScript : boolean;
+ procedure RunScript;
+ procedure PauseScript;
+ procedure StopScript;
+ procedure AddTab;
+ procedure StopCodeCompletion;
+ function DeleteTab( TabIndex : integer; CloseLast : boolean; Silent : boolean = false) : boolean;
+ procedure ClearTab( TabIndex : integer);
+ procedure CloseTabs(Exclude: integer = -1; Silent : boolean = false); //-1 for no exclusion
+ procedure SetEditActions;
+ procedure DoSearch(Next : boolean; HighlightAll : boolean);
+ procedure RefreshTab;//Refreshes all the form items that depend on the Script (Panels, title etc.)
+ procedure RefreshTabSender(sender : PtrInt);
+ end;
+
+ procedure formWriteln( S : String);
+ function GetMethodName( Decl : string; PlusNextChar : boolean) : string;
+
+const
+ // Rip Mufasa -> Simba ftw
+ //WindowTitle = 'Mufasa v2 - %s';//Title, where %s = the place of the filename.
+ WindowTitle = 'Simba - %s';//Title, where %s = the place of the filename.
+ Panel_State = 0;
+ Panel_ScriptName = 1;
+ Panel_ScriptPath = 2;
+ Image_Stop = 7;
+ Image_Terminate = 19;
+var
+ Form1: TForm1;
+ MainDir : string;
+ CurrentSyncInfo : TSyncInfo;//We need this for SafeCallThread
+
+implementation
+uses
+ lclintf,plugins,
+ syncobjs, // for the critical sections
+ debugimage,
+ bitmaps,
+ colourhistory,
+ simpleanalyzer,
+ math;
+
+//{$ifdef mswindows}
+
+var
+ DebugCriticalSection: syncobjs.TCriticalSection;
+
+procedure TForm1.ProcessDebugStream(Sender: TObject);
+
+begin
+ if length(DebugStream) = 0 then
+ Exit;
+
+ // cut off 1 newline char
+
+ DebugCriticalSection.Enter;
+
+ try
+ setlength(DebugStream, length(DebugStream) - 1);
+ Memo1.Lines.Add(DebugStream);
+ SetLength(DebugStream, 0);
+ finally
+ DebugCriticalSection.Leave;
+ end;
+end;
+
+procedure TForm1.ScriptPanelDockDrop(Sender: TObject; Source: TDragDockObject;
+ X, Y: Integer);
+begin
+ if(X <= (ScriptPanel.Width div 2))then
+ begin
+ frmFunctionList.Align := alLeft;
+ PageControl1.Align := alRight;
+ SplitterFunctionList.ResizeAnchor := akLeft;
+ SplitterFunctionList.Align := alLeft;
+ SplitterFunctionList.Left := frmFunctionList.Left + frmFunctionList.Width;
+ end else begin
+ frmFunctionList.Align := alRight;
+ PageControl1.Align := alLeft;
+ SplitterFunctionList.ResizeAnchor := akRight;
+ SplitterFunctionList.Align := alRight;
+ SplitterFunctionList.Left := frmFunctionList.Left;
+ end;
+ PageControl1.Width := ScriptPanel.Width - (Source.DockRect.Right - Source.DockRect.Left);
+ frmFunctionList.Width := ScriptPanel.Width - PageControl1.Width;
+ PageControl1.Align := alClient;
+ SplitterFunctionList.Show;
+end;
+
+procedure TForm1.ScriptPanelDockOver(Sender: TObject; Source: TDragDockObject; //is there a better way to do all of this?
+ X, Y: Integer; State: TDragState; var Accept: Boolean);
+var
+ P: TPoint;
+begin
+ Accept := frmFunctionList.DragKind = dkDock;
+ if(Accept)then
+ begin
+ P := ScriptPanel.ClientToScreen(Point(0, 0));
+ if(X <= (ScriptPanel.Width div 2))then
+ Source.DockRect := Rect(P.x, P.y, min(P.x + frmFunctionList.Width, P.x + (ScriptPanel.Width div 2)), P.y + ScriptPanel.Height)
+ else
+ Source.DockRect := Rect(max(P.x + ScriptPanel.Width - frmFunctionList.Width, P.x + (ScriptPanel.Width div 2)), P.y, P.x + ScriptPanel.Width, P.y + ScriptPanel.Height);
+ end;
+end;
+
+procedure TForm1.ScriptPopupPopup(Sender: TObject);
+begin
+ SetEditActions;
+end;
+
+procedure TForm1.SpeedButtonSearchClick(Sender: TObject);
+begin
+ CloseFindPanel;
+end;
+
+procedure TForm1.SplitterFunctionListCanResize(Sender: TObject; var NewSize: Integer;
+ var Accept: Boolean);
+begin
+ if(NewSize > ScriptPanel.Width div 2)then
+ NewSize := ScriptPanel.Width div 2;
+end;
+
+procedure TForm1.TrayPopupPopup(Sender: TObject);
+begin
+ MenuItemHide.enabled:= Form1.Visible;
+ {$ifdef MSWindows}
+ MenuItemShow.Enabled:= not Form1.Visible;
+ if Form1.Visible then
+ if Form1.CanFocus then
+ form1.SetFocus;
+ {$endif}
+end;
+
+procedure TForm1.TT_UpdateClick(Sender: TObject);
+begin
+ SimbaUpdateForm.ShowModal;
+ TT_Update.Visible:=False;
+end;
+
+procedure TForm1.UpdateTimerCheck(Sender: TObject);
+var
+ chk: String;
+ time:integer;
+begin
+
+ chk := LoadSettingDef('Settings/Updater/CheckForUpdates','True');
+
+ if chk <> 'True' then
+ Exit;
+
+ if SimbaUpdateForm.CanUpdate then
+ begin;
+ TT_Update.Visible:=True;
+ formWriteln('A new update of Simba is available!');
+ end;
+
+ time := StrToIntDef(LoadSettingDef('Settings/Updater/CheckEveryXMinutes','30'),30);
+ UpdateTimer.Interval:= time {mins} * 60 {secs} * 1000 {ms};//Every half hour
+end;
+
+procedure TForm1.UpdateMenuButtonClick(Sender: TObject);
+begin
+ SimbaUpdateForm.ShowModal;
+end;
+
+procedure formWriteln( S : String);
+begin
+ writeln('formWriteln: ' + s);
+ DebugCriticalSection.Enter;
+ try
+ {$ifdef MSWindows}
+ //Ha, we cán acces the debugmemo
+ Form1.Memo1.Lines.Add(s);
+ {$else}
+ s := s + MEOL;
+ Form1.DebugStream:= Form1.DebugStream + s;
+ {$endif}
+ finally
+ DebugCriticalSection.Leave;
+ end;
+ //Form1.Memo1.Lines.Add(s);
+end;
+
+//{$ENDIF}
+
+procedure TForm1.RunScript;
+var
+ DbgImgInfo : TDbgImgInfo;
+ fontPath: String;
+ includePath : string;
+ AppPath : string;
+ pluginspath: string;
+ ScriptPath : string;
+ loadFontsOnScriptStart: String;
+
+begin
+ with CurrScript do
+ begin
+ if ScriptState = ss_Paused then
+ begin;
+ ScriptThread.Resume;
+ ScriptState := ss_Running;
+ Exit;
+ end else
+ if ScriptState <> ss_None then
+ begin;
+ Writeln('The script hasn''t stopped yet, so we cannot start a new one.');
+ exit;
+ end;
+ AppPath:= MainDir + DS;
+ includePath:= LoadSettingDef('Settings/Includes/Path', IncludeTrailingPathDelimiter(ExpandFileName(MainDir+ DS + '..' + DS + '..' + ds)) + 'Includes' + DS);
+ fontPath := LoadSettingDef('Settings/Fonts/Path', IncludeTrailingPathDelimiter(ExpandFileName(MainDir+ DS + '..' + DS + '..' + ds)) + 'Fonts' + DS);
+ PluginsPath := LoadSettingDef('Settings/Plugins/Path', ExpandFileName(MainDir + DS + '..' + DS + '..'+ DS + 'Plugins'+ DS));
+ ScriptErrorLine:= -1;
+ CurrentSyncInfo.SyncMethod:= @Self.SafeCallThread;
+ ScriptThread := TMMLPSThread.Create(True,@CurrentSyncInfo,PluginsPath);
+ {$IFNDEF TERMINALWRITELN}
+ ScriptThread.SetDebug(@formWriteln);
+ ScriptThread.DebugMemo := Self.Memo1;
+ {$ENDIF}
+ ScriptThread.SetPSScript(CurrScript.SynEdit.Lines.Text);
+ DbgImgInfo.DispSize := @DebugImgForm.DispSize;
+ DbgImgInfo.ShowForm := @DebugImgForm.ShowDebugImgForm;
+ DbgImgInfo.ToDrawBitmap:= @DebugImgForm.ToDrawBmp;
+ DbgImgInfo.DrawBitmap:= @DebugImgForm.DrawBitmap;
+ DbgImgInfo.GetDebugBitmap:= @DebugImgForm.GetDbgBmp;
+ DbgImgInfo.GetBitmap:= @DebugImgForm.GetDebugImage;
+ ScriptThread.SetDbgImg(DbgImgInfo);
+ ScriptThread.ErrorData:= @ErrorData;
+ ScriptThread.OnError:= @HandleErrorData;
+
+ if ScriptFile <> '' then
+ ScriptPath := ExtractFileDir(ScriptFile);
+
+ if DirectoryExists(PluginsPath) then
+ PluginsGlob.AddAndLoadPath(PluginsPath);
+ if not DirectoryExists(IncludePath) then
+ if FirstRun then
+ Writeln('Warning: The include directory specified in the Settings isn''t valid.');
+ if not DirectoryExists(fontPath) then
+ if FirstRun then
+ Writeln('Warning: The font directory specified in the Settings isn''t valid. Can''t load fonts now');
+ ScriptThread.SetPaths(ScriptPath,AppPath,Includepath,PluginsPath,fontPath);
+
+ if selector.haspicked then ScriptThread.Client.IOManager.SetTarget(Selector.LastPick);
+
+
+ loadFontsOnScriptStart := LoadSettingDef('Settings/Fonts/LoadOnStartUp', 'True');
+ // Copy our current fonts
+ if not assigned(Self.OCR_Fonts) and (lowercase(loadFontsOnScriptStart) = 'true') and DirectoryExists(fontPath) then
+ begin
+ Self.OCR_Fonts := TMOCR.Create(ScriptThread.Client);
+ if DirectoryExists(fontPath) then
+ begin
+ OCR_Fonts.InitTOCR(fontPath);
+ end;{
+ else
+ begin
+ writeln('Warning: The Font directory in the Settings is not valid. Changing to default.');
+ OCR_Fonts.InitTOCR(IncludeTrailingPathDelimiter(ExpandFileName(MainDir +DS + '..' + DS + '..' + ds)) + 'Fonts' + DS);
+ end; }
+
+ ScriptThread.Client.MOCR.SetFonts(OCR_Fonts.GetFonts);
+ end else
+ if assigned(Self.OCR_Fonts) and (lowercase(loadFontsOnScriptStart) = 'true') then
+ ScriptThread.Client.MOCR.SetFonts(OCR_Fonts.GetFonts);
+ ScriptThread.OnTerminate:=@ScriptThreadTerminate;
+ ScriptState:= ss_Running;
+ FirstRun := false;
+ //Lets run it!
+ ScriptThread.Resume;
+ end;
+end;
+
+procedure TForm1.PauseScript;
+begin
+ with CurrScript do
+ begin;
+ if ScriptState = ss_Running then
+ begin;
+ {$ifdef MSWindows}
+ ScriptThread.Suspended:= True;
+ ScriptState:= ss_Paused;
+ {$else}
+ Writeln('Linux users are screwed, no pause button for u!');
+ {$endif}
+ end else if ScriptState = ss_Paused then
+ begin;
+ ScriptThread.Resume;
+ ScriptState := ss_Running;
+ end;
+ end;
+end;
+
+procedure TForm1.StopScript;
+begin
+ with CurrScript do
+ begin;
+ case ScriptState of
+ ss_Stopping:
+ begin //Terminate the thread the tough way.
+ writeln('Terminating the Scriptthread');
+ Writeln('Exit code terminate: ' +inttostr(KillThread(ScriptThread.Handle)));
+ WaitForThreadTerminate(ScriptThread.Handle, 0);
+ ScriptThread.Free;
+ ScriptState := ss_None;
+ end;
+ ss_Running:
+ begin
+ ScriptThread.PSScript.Stop;
+ ScriptState := ss_Stopping;
+ end;
+ ss_Paused:
+ begin
+ ScriptThread.Resume;
+ ScriptThread.PSScript.Stop;
+ ScriptState:= ss_Stopping;
+ end;
+ end;
+ end;
+end;
+
+procedure TForm1.AddTab;
+var
+ Tab : TMufasaTab;
+begin;
+ Tab := TMufasaTab.Create(Self.PageControl1);
+ Tabs.Add(Tab);
+ Tab.TabSheet.ImageIndex:= 8;
+// Tab.TabSheet.OnContextPopup:= @TabPopup;
+ PageControl1.TabIndex:= Tabs.Count - 1;
+ RefreshTab;
+ if tabs.count > 1 then
+ begin;
+ TB_SaveAll.Enabled:= True;
+ MenuItemSaveAll.Enabled:= True;
+ end;
+end;
+
+function TForm1.DeleteTab(TabIndex: integer; CloseLast : boolean; Silent : boolean = false) : boolean;
+var
+ Tab : TMufasaTab;
+ OldIndex : integer;//So that we can switch back, if needed.
+begin
+ if not Silent then
+ begin;
+ OldIndex := PageControl1.TabIndex;
+ if TabIndex = OldIndex then
+ begin;
+ if lowercase(LoadSettingDef('Settings/Tabs/OpenNextOnClose','False')) = 'false' then
+ OldIndex := LastTab //We are closing the 'current' tab, lets go back in history
+ else
+ OldIndex := Min(Tabs.Count - 1,OldIndex + 1);
+ end;
+ PageControl1.TabIndex:= TabIndex;
+ end;
+ //ScriptFrame now is now correct ;-D
+ result := CanExitOrOpen;
+ if not result then
+ exit;
+ Tab := TMufasaTab(Tabs[TabIndex]);
+ if (Tabs.Count = 1) and (not CloseLast) then
+ Tab.Clear
+ else
+ begin;
+ Tab.Free;
+ Tabs.Delete(TabIndex);
+ if not Silent then
+ begin;
+ if OldIndex > TabIndex then
+ PageControl1.TabIndex := OldIndex - 1
+ else if OldIndex < TabIndex then
+ PageControl1.TabIndex := OldIndex;
+ end;
+ end;
+ if tabs.count <= 1 then
+ begin;
+ TB_SaveAll.Enabled:= false;
+ MenuItemSaveAll.Enabled:= false;
+ end;
+ if not silent then
+ RefreshTab;
+end;
+
+procedure TForm1.ClearTab(TabIndex: integer);
+begin
+ TMufasaTab(Tabs[TabIndex]).Clear;
+end;
+
+procedure TForm1.CloseTabs(Exclude: integer = -1; Silent : boolean = false);
+var
+ I : integer;
+begin
+ for i := tabs.count - 1 downto 0 do
+ if i <> exclude then
+ if not DeleteTab(i,false,silent) then
+ exit;
+end;
+
+procedure TForm1.SetEditActions;
+procedure EditActions(Undo,Redo,Cut,Copy,Paste,Delete : boolean);
+begin;
+ ActionUndo.Enabled:= Undo;
+ ActionRedo.Enabled:= Redo;
+ ActionCut.Enabled:= Cut;
+ ActionCopy.Enabled:= Copy;
+ ActionPaste.Enabled:= Paste;
+ ActionDelete.Enabled:= Delete;
+ {$ifdef UpdateEditButtons}
+ TT_Cut.Enabled:= Cut;
+ TT_Paste.Enabled:=Paste;
+ TT_Copy.enabled := Copy;
+ {$endif}
+end;
+
+var
+ S: String;
+ B: Boolean;
+begin
+ if CurrScript.SynEdit.Focused or ScriptPopup.HandleAllocated then
+ begin
+ with CurrScript.SynEdit do
+ begin
+ EditActions(CanUndo,CanRedo,SelText <> '',SelText <> '',CanPaste,SelText <> '');
+// B:= SelText <> '';
+ B := SelAvail;
+ PopupItemFind.Enabled:= B;
+ PopupItemReplace.Enabled:= B;
+ if(B)then
+ begin
+ s := SelText;
+ if(Length(S) > 13)then
+ S:= Format('"%s"', [Copy(S, 1, 10) + '...'])
+ else
+ S:= Format('"%s"', [S]);
+ PopupItemFind.Caption:= 'Find next: ' + S;
+ PopupItemReplace.Caption:= 'Replace: ' + S;
+ end;
+ end
+ end
+ else if Memo1.Focused then
+ with Memo1 do
+ EditActions(CanUndo,False,SelText <>'',SelText <> '',True,SelText <> '')
+ else
+ EditActions(false,false,false,false,false,false);
+end;
+
+procedure TForm1.DoSearch(Next: boolean; HighlightAll : boolean);
+var
+ Res : integer;
+ CurrPos : TPoint;
+ SearchOptions : TSynSearchOptions;
+begin
+ SearchOptions:= [];
+ if CheckBoxMatchCase.Checked then
+ SearchOptions := [ssoMatchCase];
+ if SearchString = '' then
+ begin
+ res := -1;
+ CurrScript.Synedit.SetHighlightSearch('',[]);
+// CurrScript.SynEdit.SelectionMode:=
+// CurrScript.SynEdit.CaretXY := CurrScript.SynEdit.CaretXY;
+ CurrScript.SynEdit.LogicalCaretXY := SearchStart;
+ end
+ else
+ begin
+ Writeln('Searching: ' + SearchString);
+ if next then
+ CurrPos := CurrScript.SynEdit.LogicalCaretXY
+ else
+ CurrPos := SearchStart;
+ Res := CurrScript.SynEdit.SearchReplaceEx(SearchString,'',SearchOptions,CurrPos);
+ if res = 0 then
+ begin
+ res := CurrScript.SynEdit.SearchReplaceEx(SearchString,'',SearchOptions,Point(0,0));
+ if res > 0 then
+ begin;
+ Writeln('End of document reached');
+ SearchStart.x := 0;
+ SearchStart.Y := CurrScript.SynEdit.LogicalCaretXY.y;
+ end;
+ end;
+ end;
+ if res = 0 then
+ begin;
+ LabeledEditSearch.Color := 6711039;
+ LabeledEditSearch.Font.Color:= clWhite;
+ CurrScript.Synedit.SetHighlightSearch('',[]);
+ CurrScript.SynEdit.LogicalCaretXY := SearchStart;
+ end
+ else
+ begin
+ LabeledEditSearch.Color:= clWindow;
+ LabeledEditSearch.Font.Color:= clWindowText;
+ with CurrScript.SynEdit do
+ begin
+ HighlightAllColor.Background:= clYellow;
+ if HighlightAll then
+ SetHighlightSearch(SearchString,[])
+ else
+ SetHighlightSearch('',[]);
+ end;
+ end;
+end;
+
+procedure TForm1.RefreshTab;
+var
+ Tab : TMufasaTab;
+ Script : TScriptFrame;
+ NewTab : integer;
+begin
+ if tabs.Count < 1 then
+ begin;
+ Writeln('Cannot refresh tab, since there are no tabs.');
+ exit;
+ end;
+ NewTab := PageControl1.TabIndex;
+ Tab := TMufasaTab(Tabs[Newtab]);
+ Script := Tab.ScriptFrame;
+ Self.CurrScript := Script;
+ Self.CurrTab := Tab;
+ if Script.ScriptChanged then
+ begin;
+ Tab.TabSheet.Caption:= Script.ScriptName + '*';
+ Self.Caption := Format(WindowTitle,[Script.ScriptName + '*'])
+ end else
+ begin;
+ Tab.TabSheet.Caption:= Script.ScriptName;
+ Self.Caption := Format(WindowTitle,[Script.ScriptName]);
+ end;
+ StatusBar.Panels[Panel_ScriptName].Text:= Script.ScriptName;
+ StatusBar.Panels[Panel_ScriptPath].text:= Script.ScriptFile;
+ SetScriptState(Tab.ScriptFrame.FScriptState);//To set the buttons right
+ if Self.Showing then
+ if Tab.TabSheet.TabIndex = Self.PageControl1.TabIndex then
+ CurrScript.SynEdit.SetFocus;
+ StopCodeCompletion;//To set the highlighting back to normal;
+ frmFunctionList.LoadScriptTree(CurrScript.SynEdit.Text);
+ with CurrScript.SynEdit do
+ begin
+ SetHighlightSearch('',[]);
+ UseIncrementalColor:= false;
+ MarkupByClass[TSynEditMarkupHighlightAllCaret].TempEnable;
+ Invalidate;
+ end;
+ LabeledEditSearch.SelLength:= 0;
+ LabeledEditSearch.Color:= clWindow;
+ LabeledEditSearch.Font.Color:= clWindowText;
+ //Set tha edit buttons right
+ SetEditActions;
+end;
+
+procedure TForm1.RefreshTabSender(sender: PtrInt);
+begin
+ RefreshTab;
+end;
+
+
+procedure TForm1.ActionTabLastExecute(Sender: TObject);
+var
+ CurrIndex : integer;
+begin
+ CurrIndex := PageControl1.TabIndex;
+ if CurrIndex = 0 then
+ CurrIndex := Tabs.count - 1
+ else
+ Dec(CurrIndex);
+ PageControl1.TabIndex:= CurrIndex;
+end;
+
+procedure TForm1.ActionCloseTabExecute(Sender: TObject);
+begin
+ if(PageControl1.PageCount > 1)then
+ Self.DeleteTab(PageControl1.TabIndex,false)
+ else
+ Self.ClearScript; //DeleteTab would take care of this already, but yeah, it's neater this way.
+end;
+
+procedure TForm1.ActionCopyExecute(Sender: TObject);
+begin
+ if CurrScript.SynEdit.Focused or ScriptPopup.HandleAllocated then
+ CurrScript.SynEdit.CopyToClipboard
+ else if Memo1.Focused then
+ Memo1.CopyToClipboard
+ { else
+ Writeln(Sender.ToString); }
+end;
+
+procedure TForm1.ActionCutExecute(Sender: TObject);
+begin
+ if CurrScript.SynEdit.Focused or ScriptPopup.HandleAllocated then
+ CurrScript.SynEdit.CutToClipboard
+ else if Memo1.Focused then
+ Memo1.CutToClipboard;
+end;
+
+procedure TForm1.ActionDeleteExecute(Sender: TObject);
+begin
+ if CurrScript.SynEdit.Focused or ScriptPopup.HandleAllocated then
+ CurrScript.SynEdit.ClearSelection
+ else if Memo1.Focused then
+ Memo1.ClearSelection;
+end;
+
+procedure TForm1.ActionExitExecute(Sender: TObject);
+begin
+ Self.Close;
+end;
+
+procedure TForm1.ActionFindNextExecute(Sender: TObject);
+begin
+ DoSearch(true, false);
+end;
+
+procedure TForm1.ActionFindstartExecute(Sender: TObject);
+begin
+ if frmFunctionList.Focused or frmFunctionList.FunctionList.Focused or frmFunctionList.editSearchList.Focused then
+ begin
+ if frmFunctionList.editSearchList.CanFocus then
+ frmFunctionList.editSearchList.SetFocus;
+ end else
+ begin
+ SearchPanel.Visible:= true;
+ if LabeledEditSearch.CanFocus then
+ LabeledEditSearch.SetFocus;
+ end;
+end;
+
+procedure TForm1.ActionClearDebugExecute(Sender: TObject);
+begin
+ Memo1.Clear;
+end;
+
+procedure TForm1.ActionNewExecute(Sender: TObject);
+begin
+ Self.ClearScript;
+end;
+
+procedure TForm1.ActionNewTabExecute(Sender: TObject);
+begin
+ Self.AddTab;
+end;
+
+procedure TForm1.ActionOpenExecute(Sender: TObject);
+begin
+ Self.OpenScript;
+end;
+
+procedure TForm1.ActionPasteExecute(Sender: TObject);
+begin
+ if CurrScript.SynEdit.Focused or ScriptPopup.HandleAllocated then
+ CurrScript.SynEdit.PasteFromClipboard
+ else if Memo1.Focused then
+ Memo1.PasteFromClipboard;
+end;
+
+procedure TForm1.ActionPauseExecute(Sender: TObject);
+begin
+ Self.PauseScript;
+end;
+
+procedure TForm1.ActionRedoExecute(Sender: TObject);
+begin
+ if CurrScript.SynEdit.Focused or ScriptPopup.HandleAllocated then
+ CurrScript.Redo
+ else if Memo1.Focused then
+ Memo1.Undo; //?
+end;
+
+procedure TForm1.ActionReplaceExecute(Sender: TObject);
+begin
+ if(ScriptPopup.HandleAllocated)then
+ dlgReplace.FindText:= CurrScript.SynEdit.SelText;
+ dlgReplace.Execute;
+end;
+
+procedure TForm1.ActionRunExecute(Sender: TObject);
+begin
+ Self.RunScript;
+end;
+
+procedure TForm1.ActionSaveAllExecute(Sender: TObject);
+var
+ i : integer;
+ OldIndex : integer;
+begin
+ OldIndex := PageControl1.TabIndex;
+ for i := 0 to Tabs.Count - 1 do
+ begin;
+ PageControl1.TabIndex:= i;
+ SaveCurrentScript;
+ end;
+ PageControl1.TabIndex:= oldindex;
+end;
+
+procedure TForm1.ActionSaveAsExecute(Sender: TObject);
+begin
+ Self.SaveCurrentScriptAs;
+end;
+
+procedure TForm1.ActionSaveExecute(Sender: TObject);
+begin
+ Self.SaveCurrentScript;
+end;
+
+procedure TForm1.ActionSelectAllExecute(Sender: TObject);
+begin
+ if CurrScript.SynEdit.Focused or ScriptPopup.HandleAllocated then
+ CurrScript.SynEdit.SelectAll
+ else if Memo1.Focused then
+ Memo1.SelectAll
+ else if LabeledEditSearch.Focused then
+ LabeledEditSearch.SelectAll;
+
+end;
+
+procedure TForm1.ActionStopExecute(Sender: TObject);
+begin
+ Self.StopScript;
+end;
+
+procedure TForm1.ActionTabNextExecute(Sender: TObject);
+var
+ CurrIndex : integer;
+begin
+ CurrIndex := PageControl1.TabIndex;
+ if CurrIndex = Tabs.count - 1 then
+ CurrIndex := 0
+ else
+ Inc(CurrIndex);
+ PageControl1.TabIndex:= CurrIndex;
+end;
+
+procedure TForm1.ActionUndoExecute(Sender: TObject);
+begin
+ if CurrScript.SynEdit.Focused or ScriptPopup.HandleAllocated then
+ CurrScript.Undo
+ else if Memo1.Focused then
+ Memo1.Undo;
+end;
+
+
+
+procedure TForm1.CheckBoxMatchCaseClick(Sender: TObject);
+begin
+ RefreshTab;
+ CurrScript.SynEdit.MarkupByClass[TSynEditMarkupHighlightAllCaret].TempDisable;
+ SearchString := LabeledEditSearch.Text;
+ DoSearch(false, true);
+ CurrScript.SynEdit.UseIncrementalColor:= true;
+ LabeledEditSearch.SetFocus;
+end;
+
+
+
+procedure TForm1.CloseFindPanel;
+begin
+ SearchPanel.Visible:= false;
+ if CurrScript.SynEdit.CanFocus then
+ CurrScript.SynEdit.SetFocus;
+end;
+
+procedure TForm1.StopCodeCompletion;
+begin
+ if frmFunctionList.InCodeCompletion then
+ with CurrScript,frmFunctionList do
+ begin;
+ editSearchList.Color:= clWhite;
+ if FilterTree.Focused then
+ begin;
+ Writeln('This is currently not supported');
+ SynEdit.Lines[CompletionCaret.y - 1] := CompletionStart;
+ SynEdit.LogicalCaretXY:= point(CompletionCaret.x,CompletionCaret.y);
+ SynEdit.SelEnd:= SynEdit.SelStart;
+ end;
+ InCodeCompletion:= false;
+ SynEdit.SelectedColor.Style:= [];
+ SynEdit.SelectedColor.Foreground:= clHighlightText;
+ SynEdit.SelectedColor.Background:= clHighlight;
+ Synedit.MarkupByClass[TSynEditMarkupHighlightAllCaret].TempEnable;
+ end;
+end;
+
+procedure TForm1.editSearchListExit(Sender: TObject);
+begin
+ frmFunctionList.editSearchList.Color := clWhite;
+ StopCodeCompletion;
+end;
+
+procedure TForm1.editSearchListKeyDown(Sender: TObject; var Key: Word;
+ Shift: TShiftState);
+begin
+ if key = vk_up then
+ begin
+ frmFunctionList.Find(True,true);
+ key := 0;
+ end else
+ if key = vk_down then
+ begin
+ frmFunctionList.Find(true);
+ key := 0;
+ end;
+end;
+
+procedure TForm1.editSearchListKeyPress(Sender: TObject; var Key: char);
+var
+ linetext : string;
+begin
+ if key = #13 then//enter
+ begin;
+ key := #0;
+ frmFunctionList.Find(True);
+ end else
+ if frmFunctionList.InCodeCompletion then
+ begin;
+ if key = #27 then//esc -> C'est error!
+ begin
+ key := #0;
+ StopCodeCompletion;
+ CurrScript.SynEdit.Lines[frmFunctionList.CompletionCaret.y - 1] := frmFunctionList.CompletionStart;
+ CurrScript.SynEdit.LogicalCaretXY:= point(frmFunctionList.CompletionCaret.x,frmFunctionList.CompletionCaret.y);
+ CurrScript.SynEdit.SelEnd:= CurrScript.SynEdit.SelStart;
+ CurrScript.SynEdit.SetFocus;
+ end else
+ if key in [' ',',','.','(',')'] then //on on these chars we will insert the function!
+ begin;
+ StopCodeCompletion;
+ linetext := CurrScript.SynEdit.Lines[frmFunctionList.CompletionCaret.y - 1];
+ while (frmFunctionList.CompletionCaret.x <= length(linetext)) and (linetext[frmFunctionList.CompletionCaret.x] in ['a'..'z','A'..'Z','0'..'9','_']) do
+ inc(frmFunctionList.CompletionCaret.x);
+ CurrScript.SynEdit.LogicalCaretXY:= frmFunctionList.CompletionCaret;
+ CurrScript.SynEdit.SelStart:= CurrScript.SynEdit.SelEnd;
+ CurrScript.SynEdit.ExecuteCommand(ecChar,key,nil);
+ CurrScript.SynEdit.SetFocus;
+ key := #0;
+ end;
+ end;
+end;
+
+procedure TForm1.FunctionListChange(Sender: TObject; Node: TTreeNode);
+begin
+ if node = nil then
+ exit;
+ if Node.Level > 0 then
+ StatusBar.Panels[2].Text := PChar(Node.Data);
+ if Node.level = 0 then
+ StatusBar.Panels[2].Text := 'Section: ' + Node.Text;
+end;
+
+procedure TForm1.FunctionListEnter(Sender: TObject);
+begin
+ frmFunctionList.LoadScriptTree(CurrScript.SynEdit.Text);
+end;
+
+procedure TForm1.FunctionListExit(Sender: TObject);
+begin
+// StatusBar.Panels[2].Text:= '';
+end;
+
+procedure TForm1.MenuItemColourHistoryClick(Sender: TObject);
+begin
+ MenuItemColourHistory.Checked := not ColourHistoryForm.Visible;
+ if MenuItemColourHistory.Checked then
+ ColourHistoryForm.Show
+ else
+ ColourHistoryForm.Hide;
+end;
+
+procedure TForm1.dlgReplaceFind(Sender: TObject);
+begin
+ SearchString := dlgReplace.FindText;
+ DoSearch(True, False);
+end;
+
+procedure TForm1.dlgReplaceReplace(Sender: TObject);
+var
+ SOptions: TSynSearchOptions;
+ P: TPoint;
+ Y: Boolean;
+ Btns: TMsgDlgButtons;
+
+ procedure Replace;
+ begin
+ CurrScript.SynEdit.SearchReplaceEx(dlgReplace.FindText, dlgReplace.ReplaceText, SOptions + [ssoReplace], P);
+ end;
+
+begin
+ Y:= False;
+ SOptions:= [];
+ if(frMatchCase in dlgReplace.Options)then SOptions:= [ssoMatchCase];
+ if(frWholeWord in dlgReplace.Options)then SOptions+= [ssoWholeWord];
+ with CurrScript.SynEdit do
+ begin
+ Btns:= [mbYes, mbNo];
+ if(frReplaceAll in dlgReplace.Options)then Btns+= [mbYesToAll];
+ if(frEntireScope in dlgReplace.Options)then P:= Point(0, 0) else P:= CaretXY;
+ while SearchReplaceEx(dlgReplace.FindText, '', SOptions, P) > 0 do
+ begin
+ if(Y)then
+ Replace
+ else case MessageDlg('Replace', Format('Do you want to replace "%s" with "%s"?', [dlgReplace.FindText, dlgReplace.ReplaceText]), mtConfirmation, Btns, 0) of
+ mrYes: Replace;
+ mrYesToAll: begin
+ Replace;
+ Y:= True;
+ end;
+ end;
+ if(not(frReplaceAll in dlgReplace.Options))then exit;
+ P:= CaretXY;
+ end;
+ end;
+end;
+
+procedure TForm1.EditSearchChange(Sender: TObject);
+begin
+ SearchString :=LabeledEditSearch.Text;
+ DoSearch(false, true);
+end;
+
+procedure TForm1.FormClose(Sender: TObject; var CloseAction: TCloseAction);
+var
+ i : integer;
+begin
+ for i := Tabs.Count - 1 downto 0 do
+ if not DeleteTab(i,true) then
+ begin;
+ CloseAction := caNone;
+ exit
+ end;
+end;
+
+procedure TForm1.FormCreate(Sender: TObject);
+begin
+ Randomize;
+ //Show close buttons @ tabs
+ PageControl1.Options:=PageControl1.Options+[nboShowCloseButtons];
+ PageControl1.OnCloseTabClicked:=ActionCloseTab.OnExecute;
+ Tabs := TList.Create;
+ AddTab;//Give it alteast 1 tab ;-).
+ FunctionListShown(True); //Show this function list bitch!
+ Manager := TIOManager.Create; //No need to load plugins for the Global manager
+ Picker := TMColorPicker.Create(Manager);
+ Selector := TMWindowSelector.Create(Manager);
+ MainDir:= ExtractFileDir(Application.ExeName);
+ { For writeln }
+ SetLength(DebugStream, 0);
+ DebugCriticalSection := syncobjs.TCriticalSection.Create;
+ {$ifdef mswindows}
+ DebugTimer.Enabled:= false;
+ {$endif}
+ Application.QueueAsyncCall(@RefreshTabSender,0);
+ {$ifdef mswindows}
+ if FileExists(Application.ExeName+'_old_') then
+ begin
+ Writeln('We still have an out-dated exe file in the dir, lets remove!');
+ Writeln(format('Sucesfully deleted the file? %s',[BoolToStr(DeleteFile(Application.ExeName + '_old_'),true)]));
+ end;
+ {$endif}
+ frmFunctionList.OnEndDock:= @frmFunctionList.FrameEndDock;
+ FirstRun := true;//Our next run is the first run.
+end;
+
+procedure TForm1.FormDestroy(Sender: TObject);
+var
+ i : integer;
+begin
+ for i := Tabs.Count - 1 downto 0 do
+ TMufasaTab(Tabs[i]).Free;
+ Tabs.free;
+ Selector.Free;
+ Picker.Free;
+ Manager.Free;
+ PluginsGlob.Free;
+
+ SetLength(DebugStream, 0);
+ DebugCriticalSection.Free;
+end;
+
+procedure TForm1.FormShortCuts(var Msg: TLMKey; var Handled: Boolean);
+begin
+ SetEditActions;
+ Handled := ActionList.IsShortCut(Msg);
+end;
+
+
+
+procedure TForm1.LabeledEditSearchEnter(Sender: TObject);
+begin
+ SearchStart := CurrScript.SynEdit.LogicalCaretXY;
+ with CurrScript.SynEdit do
+ begin
+ UseIncrementalColor:= true;
+ MarkupByClass[TSynEditMarkupHighlightAllCaret].TempDisable
+ end;
+end;
+
+procedure TForm1.LabeledEditSearchExit(Sender: TObject);
+begin
+ if not CheckBoxMatchCase.MouseEntered then
+ RefreshTab;
+end;
+
+procedure TForm1.LabeledEditSearchKeyDown(Sender: TObject; var Key: Word;
+ Shift: TShiftState);
+begin
+ if (ssCtrl in Shift) and (key = vk_f) then
+ begin;
+ LabeledEditSearch.SelectAll;
+ end else
+ if key = VK_ESCAPE then
+ begin
+ CloseFindPanel;
+ key := 0;
+ end;
+end;
+
+procedure TForm1.LabeledEditSearchKeyPress(Sender: TObject; var Key: char);
+begin
+ if key = #13 then
+ begin;
+ SearchString:= LabeledEditSearch.Text;
+ DoSearch(true, true);
+ key := #0;
+// LabeledEditSearch.SelStart:= Length(LabeledEditSearch.Text);
+ end;
+end;
+
+procedure TForm1.MenuEditClick(Sender: TObject);
+begin
+ SetEditActions;
+end;
+
+procedure TForm1.MenuItemAboutClick(Sender: TObject);
+begin
+ AboutForm.ShowModal;
+end;
+
+procedure TForm1.MenuItemCloseTabsClick(Sender: TObject);
+begin
+ Self.CloseTabs;
+end;
+
+procedure TForm1.MenuItemDebugImageClick(Sender: TObject);
+begin
+ MenuItemDebugImage.Checked := not DebugImgForm.Visible;
+ if MenuItemDebugImage.Checked then
+ DebugImgForm.Show
+ else
+ DebugImgForm.Hide;
+end;
+
+procedure TForm1.MenuItemExportHTMLClick(Sender: TObject);
+var
+ SynExporterHTML : TSynExporterHTML;
+begin;
+ SynExporterHTML := TSynExporterHTML.Create(nil);
+ SynExporterHTML.Highlighter := CurrScript.SynFreePascalSyn1;
+ SynExporterHTML.ExportAsText:= True;
+ with TSaveDialog.Create(nil) do
+ try
+ Filter:= 'HTML Files (*.html;*.htm)|*.html;*.htm|All files(*.*)|*.*';
+ Options:= [ofOverwritePrompt,ofEnableSizing];
+ DefaultExt:= 'html';
+ if Execute then
+ begin
+ if CurrScript.ScriptName <> '' then
+ SynExporterHTML.Title:= 'Simba - ' + CurrScript.ScriptName
+ else
+ SynExporterHTML.Title:= 'Cogat - Untitled';
+ SynExporterHTML.ExportAll(CurrScript.SynEdit.Lines);
+ SynExporterHTML.SaveToFile(FileName);
+ end;
+ finally
+ free;
+ SynExporterHTML.Free;
+ end;
+end;
+
+function GetMethodName( Decl : string; PlusNextChar : boolean) : string;
+var
+ I : integer;
+ ii : integer;
+begin;
+ I := pos(' ',Decl) + 1;
+ for ii := i to Length(decl) do
+ begin;
+ if (Decl[ii] = '(') or (Decl[ii] = ';') then
+ begin;
+ if PlusNextChar then
+ result := result + decl[ii];
+ exit;
+ end;
+ if (Decl[ii] = ' ') or (Decl[ii] = ':') then
+ begin;
+ if PlusNextChar then
+ result := result + ' ';
+ exit;
+ end;
+ result := result + decl[ii];
+ end;
+ //We made it out of the loop.. This is a method without ';' we might wanne add that!
+ if PlusNextChar then
+ result := result + ';';
+end;
+
+procedure TForm1.MenuitemFillFunctionListClick(Sender: TObject);
+var
+ Methods : TExpMethodArr;
+ LastSection : string;
+ Sections : TStringList;
+ i : integer;
+ Index : integer;
+ TempNode : TTreeNode;
+ Temp2Node : TTreeNode;
+ Tree : TTreeView;
+begin
+ if frmFunctionList.FunctionList.Items.Count = 0 then
+ begin;
+ Methods := TMMLPSThread.GetExportedMethods;
+ Tree := frmFunctionList.FunctionList;
+ Tree.Items.Clear;
+ Sections := TStringList.Create;
+ LastSection := '';
+ frmFunctionList.ScriptNode := Tree.Items.Add(nil,'Script');
+ for i := 0 to high(Methods) do
+ begin;
+ if Methods[i].Section <> LastSection then
+ begin;
+ LastSection := Methods[i].Section;
+ Index := Sections.IndexOf(LastSection);
+ if Index <> -1 then
+ TempNode := Tree.Items.Item[index]
+ else
+ begin
+ TempNode := Tree.Items.Add(nil,LastSection);
+ Sections.Add(LastSection);
+ end;
+ end;
+ Temp2Node := Tree.Items.AddChild(Tempnode,GetMethodName(Methods[i].FuncDecl,false));
+ Temp2Node.Data:= strnew(PChar(Methods[i].FuncDecl));
+ end;
+ Sections.free;
+ end;
+ frmFunctionList.LoadScriptTree(CurrScript.SynEdit.Text);
+end;
+
+procedure TForm1.MenuItemHideClick(Sender: TObject);
+begin
+ if Self.Visible = false then
+ MenuItemShowClick(sender)
+ else
+ Self.hide;
+end;
+
+procedure TForm1.MenuItemReportBugClick(Sender: TObject);
+begin
+ //OpenURL('http://old.villavu.com/mantis/bug_report_page.php');
+end;
+
+procedure TForm1.MenuItemShowClick(Sender: TObject);
+begin
+ Self.Show;
+ Self.WindowState := wsNormal;
+end;
+
+procedure TForm1.MenuItemTabCloseClick(Sender: TObject);
+begin
+ DeleteTab(PopupTab,false);
+end;
+
+procedure TForm1.MenuItemTabCloseOthersClick(Sender: TObject);
+begin
+ CloseTabs(PopupTab);
+end;
+
+procedure TForm1.MenuItemFunctionListClick(Sender: TObject);
+begin
+ FunctionListShown(not MenuItemFunctionList.Checked);
+end;
+
+procedure TForm1.MenuViewSettingsClick(Sender: TObject);
+begin
+ SettingsForm.ShowModal;
+end;
+
+procedure TForm1.OnLinePSScript(Sender: TObject);
+begin
+ //Writeln('We just completed a line!!');
+ {$IFDEF ProcessMessages}
+ Application.ProcessMessages; //Don't think that this is neccesary though
+ {$ENDIF}
+end;
+
+
+
+procedure TForm1.ButtonPickClick(Sender: TObject);
+var
+ c, x, y: Integer;
+ cobj: TColourPickerObject;
+begin
+ Picker.Pick(c, x, y);
+ cobj := TColourPickerObject.Create(c, Point(x,y), '');
+
+ if lowercase(LoadSettingDef('Settings/ColourPicker/ShowHistoryOnPick', 'True')) = 'true' then
+ begin
+ ColourHistoryForm.AddColObj(cobj, true);
+ ColourHistoryForm.Show;
+ end;
+ formWriteln('Picked colour: ' + inttostr(c) + ' at (' + inttostr(x) + ', ' + inttostr(y) + ')');
+end;
+
+
+procedure TForm1.ButtonSelectorDown(Sender: TObject; Button: TMouseButton;
+ Shift: TShiftState; X, Y: Integer);
+begin
+ Manager.SetTarget(Selector.Drag);
+ writeln('New window: ' + IntToStr(Selector.LastPick));
+end;
+
+procedure TForm1.NoTray(Sender: TObject);
+begin
+ if Not Form1.IsVisible then
+ Self.MenuItemShowClick(Sender)
+ else
+ Form1.Hide;
+end;
+
+procedure TForm1.PageControl1Change(Sender: TObject);
+begin
+ RefreshTab();
+end;
+
+procedure TForm1.ButtonTrayClick(Sender: TObject);
+begin
+ Form1.Hide;
+end;
+
+procedure TForm1.PageControl1Changing(Sender: TObject; var AllowChange: Boolean
+ );
+begin
+ LastTab:= PageControl1.TabIndex;
+end;
+
+procedure TForm1.PageControl1ContextPopup(Sender: TObject; MousePos: TPoint;
+ var Handled: Boolean);
+begin
+ PopupTab := PageControl1.TabIndexAtClientPos(MousePos);
+ if PopupTab = -1 then
+ begin
+ Writeln('We couldn''t find which tab you clicked on, closing the popup');
+ Handled := true;
+ end;
+end;
+
+procedure TForm1.PageControl1DragDrop(Sender, Source: TObject; X, Y: Integer);
+var
+ NewPos : integer;
+ OldPos : integer;
+begin
+ if sender <> PageControl1 then
+ exit;
+ NewPos := PageControl1.TabIndexAtClientPos(Point(x,y));
+ OldPos := PageControl1.TabIndex;
+ if (NewPos <> OldPos) and (NewPos <> -1) then
+ begin;
+ Tabs.Move(OldPos,NewPos);
+ PageControl1.Pages[OldPos].TabIndex:= NewPos;
+ end;
+end;
+
+procedure TForm1.PageControl1DragOver(Sender, Source: TObject; X, Y: Integer;
+ State: TDragState; var Accept: Boolean);
+var
+ Pos: Integer;
+begin
+ Pos := PageControl1.TabIndexAtClientPos(Point(x,y));
+ Accept := (Pos <> PageControl1.TabIndex) and (Pos <> -1);
+end;
+
+procedure TForm1.PageControl1MouseDown(Sender: TObject; Button: TMouseButton;
+ Shift: TShiftState; X, Y: Integer);
+begin
+ if(Button = mbLeft)then
+ begin
+ {$ifdef linux}
+ PageControl1.TabIndex := PageControl1.TabIndexAtClientPos(Point(x,y));
+ {$endif}
+ PageControl1.BeginDrag(false, 10);
+ end;
+end;
+
+procedure TForm1.PageControl1MouseUp(Sender: TObject; Button: TMouseButton;
+ Shift: TShiftState; X, Y: Integer);
+begin
+ if(Button = mbMiddle) and (not(PageControl1.Dragging))then
+ if(PageControl1.TabIndexAtClientPos(Point(x,y)) <> -1)then
+ DeleteTab(PageControl1.TabIndexAtClientPos(Point(x,y)), False);
+end;
+
+procedure TForm1.PopupItemFindClick(Sender: TObject);
+begin
+ SearchString := CurrScript.SynEdit.SelText;
+ ActionFindNextExecute(ScriptPopup);
+end;
+
+function TForm1.GetScriptState: TScriptState;
+begin
+ result := CurrScript.FScriptState;
+end;
+
+procedure TForm1.SetScriptState(const State: TScriptState);
+begin
+ CurrScript.FScriptState:= State;
+ with Self.StatusBar.panels[Panel_State] do
+ case state of
+ ss_Running : begin Text := 'Running'; TB_Run.Enabled:= False; {$ifdef MSWindows}TB_Pause.Enabled:= True; {$endif}
+ TB_Stop.ImageIndex := Image_Stop; TB_Stop.Enabled:= True;
+ TrayPlay.Checked := True; TrayPlay.Enabled := False; {$ifdef MSWindows}TrayPause.Checked := false; TrayPause.Enabled := True;{$endif}
+ TrayStop.Enabled:= True; TrayStop.Checked:= False;
+ end;
+ ss_Paused : begin Text := 'Paused'; TB_Run.Enabled:= True; {$ifdef MSWindows}TB_Pause.Enabled:= True; {$endif}
+ TB_Stop.ImageIndex := Image_Stop; TB_Stop.Enabled:= True;
+ TrayPlay.Checked := false; TrayPlay.Enabled := True; {$ifdef MSWindows}TrayPause.Checked := True; TrayPause.Enabled := True;{$endif}
+ TrayStop.Enabled:= True; TrayStop.Checked:= False;
+ end;
+ ss_Stopping: begin Text := 'Stopping';TB_Run.Enabled:= False; TB_Pause.Enabled:= False; TB_Stop.Enabled:= True;
+ TB_Stop.ImageIndex := Image_Terminate;
+ TrayPlay.Checked := False; TrayPlay.Enabled := False; {$ifdef MSWindows}TrayPause.Checked := false; TrayPause.Enabled := False;{$endif}
+ TrayStop.Enabled:= True; TrayStop.Checked:= True;
+ end;
+ ss_None : begin Text := 'Done'; TB_Run.Enabled:= True; TB_Pause.Enabled:= False; TB_Stop.Enabled:= False;
+ TB_Stop.ImageIndex := Image_Stop;
+ TrayPlay.Checked := false; TrayPlay.Enabled := True; {$ifdef MSWindows}TrayPause.Checked := false; TrayPause.Enabled := False;{$endif}
+ TrayStop.Enabled:= false; TrayStop.Checked:= False;
+ end;
+ end;
+end;
+
+function TForm1.LoadSettingDef(Key: string; Def: string): string;
+begin
+ result := SettingsForm.Settings.GetSetLoadSaveDefaultKeyValueIfNotExists(Key,def,SimbaSettingsFile);
+end;
+
+procedure TForm1.FunctionListShown(ShowIt: boolean);
+var
+ Node : TTreeNode;
+ tmpNode : TTreeNode;
+ Tree : TTreeView;
+ Analyzer : TScriptAnalyzer;
+ I,ii : integer;
+begin
+ with MenuItemFunctionList, frmFunctionList do
+ begin
+ Checked := ShowIt;
+ if(Checked)then
+ begin
+ if FunctionList.Items.Count = 0 then
+ MenuitemFillFunctionListClick(nil);
+ FrameEndDock(frmFunctionList,frmFunctionList.Parent,0,0);//Set the label correctly
+ if(frmFunctionList.Parent is TPanel)then
+ begin
+ SplitterFunctionList.Show;
+ frmFunctionList.Show;
+ end else frmFunctionList.Parent.Show;
+ if Self.Visible then
+ if editSearchList.CanFocus then
+ editSearchList.SetFocus;
+ //Lets load up this Script tree!
+ frmFunctionList.LoadScriptTree(CurrScript.SynEdit.text);
+ end else begin
+ if(frmFunctionList.Parent is TPanel)then
+ frmFunctionList.Hide
+ else
+ frmFunctionList.Parent.Hide;
+ SplitterFunctionList.Hide;
+ end;
+ end;
+end;
+
+
+procedure TForm1.SafeCallThread;
+begin
+ Writeln('Executing : ' + CurrentSyncInfo.MethodName);
+ mmlpsthread.CurrThread := TMMLPSTHREAD(CurrentSyncInfo.OldThread);
+ with CurrentSyncInfo.PSScript do
+ begin;
+ OnLine:=@OnLinePSScript;
+ CurrentSyncInfo.Res:= Exec.RunProcPVar(CurrentSyncInfo.V,Exec.GetProc(CurrentSyncInfo.MethodName));
+ Online := nil;
+ end;
+ mmlpsthread.CurrThread := nil;
+end;
+
+function TForm1.OpenScript: boolean;
+begin;
+ Result := False;
+ if CanExitOrOpen = false then
+ Exit;
+ with TOpenDialog.Create(nil) do
+ try
+ Filter:= 'Mufasa Files|*.cogat;*.mufa;*.txt|Any files|*.*';
+ if Execute then
+ result := LoadScriptFile(filename);
+ finally
+ Free;
+ end;
+end;
+
+function TForm1.LoadScriptFile(FileName : string): boolean;
+begin
+ if FileExists(FileName) then
+ begin;
+ with CurrScript do
+ begin
+ filename := SetDirSeparators(filename);
+ SynEdit.Lines.LoadFromFile(FileName);
+ StartText := SynEdit.Lines.text;
+ ScriptName:= ExtractFileNameOnly(filename);
+ WriteLn('Script name will be: ' + ScriptName);
+ ScriptFile:= FileName;
+ ScriptChanged := false;
+ RefreshTab();
+ Result := True;
+ end;
+ end;
+end;
+
+function TForm1.SaveCurrentScript: boolean;
+begin
+ with CurrScript do
+ begin
+ Result := (ScriptFile <> '');
+ if Result then
+ begin;
+ ScriptChanged := false;
+ SynEdit.Lines.SaveToFile(ScriptFile);
+ StartText:= SynEdit.Lines.Text;
+ SynEdit.MarkTextAsSaved;
+ Self.Caption:= Format(WindowTitle,[ScriptName]);
+ end
+ else
+ result := SaveCurrentScriptAs;
+ end;
+ RefreshTab;
+end;
+
+function TForm1.SaveCurrentScriptAs: boolean;
+begin
+ with CurrScript do
+ begin;
+ Result := false;
+ with TSaveDialog.Create(nil) do
+ try
+ Filter:= 'Mufasa files|*.cogat;*.mufa;*.pas;*.txt|Any Files|*.*';
+ if Execute then
+ begin;
+ if ExtractFileExt(FileName) = '' then
+ begin;
+ ScriptFile := FileName + '.mufa';
+ end else
+ ScriptFile := FileName;
+ SynEdit.Lines.SaveToFile(ScriptFile);
+ ScriptName:= ExtractFileNameOnly(ScriptFile);
+ Writeln('Saving to: ' + FileName);
+ WriteLn('Script name will be: ' + ScriptName);
+ RefreshTab();
+ Result := True;
+ end;
+ finally
+ Free;
+ end;
+ if result then
+ begin;
+ Writeln('Succesfully saved: ' + ScriptFile);
+ StartText:= SynEdit.Lines.Text;
+ SynEdit.MarkTextAsSaved;
+ ScriptChanged := false;
+ end;
+ end;
+end;
+
+function TForm1.CanExitOrOpen: boolean;
+var
+ I : integer;
+begin;
+ Self.Enabled := False;//We HAVE to answer the popup
+ Result := True;
+ if ScriptState <> ss_None then
+ begin
+ if ScriptState <> ss_Stopping then
+ begin
+ result := False;
+ case MessageDlg('Script is still running', 'Do you want to stop the script?',
+ mtConfirmation, mbYesNoCancel, 0) of
+ mrYes: StopScript;
+ end;
+ end else
+ case MessageDlg('Script is stopping.', 'Do you want to terminate the script?',
+ mtConfirmation, mbYesNoCancel, 0) of
+ mrNo, mrCancel: Result := false;
+ mrYes: StopScript;
+ end;
+ end;
+ if Result and (CurrScript.StartText <> CurrScript.SynEdit.Lines.text) then
+ begin
+ case MessageDlg('Script has been modified.', 'Do you want to save the script?',
+ mtConfirmation, mbYesNoCancel, 0) of
+ mrCancel : Result := False;
+ mrYes : Result := SaveCurrentScript;
+ end;
+ end;
+ Self.Enabled := True;
+ if Self.CanFocus then
+ Self.SetFocus;
+end;
+
+function TForm1.ClearScript: boolean;
+begin
+ if CanExitOrOpen then
+ begin;
+ CurrTab.Clear;
+ RefreshTab();
+ end;
+end;
+
+
+{ TMufasaTab }
+
+procedure TMufasaTab.Clear;
+begin
+ ScriptFrame.Free;
+ ScriptFrame := TScriptFrame.Create(Tabsheet);
+ ScriptFrame.Parent := Tabsheet;
+ ScriptFrame.Align:= alClient;
+end;
+
+constructor TMufasaTab.Create(Page: TPageControl);
+begin
+ inherited Create;
+ PageCtrl := Page;
+ Tabsheet := TTabSheet.Create(Page);
+ Tabsheet.PageControl := Page;
+ ScriptFrame := TScriptFrame.Create(Tabsheet);
+ ScriptFrame.Parent := Tabsheet;
+ ScriptFrame.Align := alClient;
+end;
+
+destructor TMufasaTab.Destroy;
+begin
+ ScriptFrame.Free;
+ TabSheet.Free;
+ inherited Destroy;
+end;
+
+initialization
+ {$I testunit.lrs}
+
+
+end.
+
diff --git a/branches/script-component/Projects/SAMufasaGUI/updateform.lfm b/branches/script-component/Projects/SAMufasaGUI/updateform.lfm
new file mode 100644
index 0000000..149534d
--- /dev/null
+++ b/branches/script-component/Projects/SAMufasaGUI/updateform.lfm
@@ -0,0 +1,70 @@
+object SimbaUpdateForm: TSimbaUpdateForm
+ Left = 507
+ Height = 391
+ Top = 321
+ Width = 467
+ ActiveControl = UpdateButton
+ BorderIcons = [biSystemMenu, biMinimize]
+ Caption = 'Update Simba'
+ ClientHeight = 391
+ ClientWidth = 467
+ OnCreate = FormCreate
+ OnShow = CleanUpdateForm
+ LCLVersion = '0.9.29'
+ object DownloadProgress: TProgressBar
+ Left = 24
+ Height = 28
+ Top = 64
+ Width = 413
+ Anchors = [akTop, akLeft, akRight]
+ Smooth = True
+ TabOrder = 0
+ end
+ object UpdateButton: TButton
+ Left = 24
+ Height = 40
+ Top = 8
+ Width = 413
+ Anchors = [akTop, akLeft, akRight]
+ Caption = 'Update!'
+ OnClick = UpdateButtonClick
+ TabOrder = 1
+ end
+ object OkButton: TButton
+ Left = 362
+ Height = 25
+ Top = 352
+ Width = 75
+ Anchors = [akRight, akBottom]
+ Caption = 'Ok'
+ OnClick = OkButtonClick
+ TabOrder = 2
+ end
+ object CancelButton: TButton
+ Left = 24
+ Height = 25
+ Top = 352
+ Width = 75
+ Anchors = [akLeft, akBottom]
+ Caption = 'Cancel'
+ OnClick = CancelButtonClick
+ TabOrder = 3
+ end
+ object UpdateLog: TMemo
+ Left = 24
+ Height = 207
+ Top = 128
+ Width = 413
+ Anchors = [akTop, akLeft, akRight, akBottom]
+ TabOrder = 4
+ end
+ object DownloadSpeed: TLabel
+ Left = 24
+ Height = 14
+ Top = 104
+ Width = 78
+ Caption = 'DownloadSpeed'
+ ParentColor = False
+ Visible = False
+ end
+end
diff --git a/branches/script-component/Projects/SAMufasaGUI/updateform.lrs b/branches/script-component/Projects/SAMufasaGUI/updateform.lrs
new file mode 100644
index 0000000..570894b
--- /dev/null
+++ b/branches/script-component/Projects/SAMufasaGUI/updateform.lrs
@@ -0,0 +1,24 @@
+{ This is an automatically generated lazarus resource file }
+
+LazarusResources.Add('TSimbaUpdateForm','FORMDATA',[
+ 'TPF0'#16'TSimbaUpdateForm'#15'SimbaUpdateForm'#4'Left'#3#251#1#6'Height'#3
+ +#135#1#3'Top'#3'A'#1#5'Width'#3#211#1#13'ActiveControl'#7#12'UpdateButton'#11
+ +'BorderIcons'#11#12'biSystemMenu'#10'biMinimize'#0#7'Caption'#6#12'Update Si'
+ +'mba'#12'ClientHeight'#3#135#1#11'ClientWidth'#3#211#1#8'OnCreate'#7#10'Form'
+ +'Create'#6'OnShow'#7#15'CleanUpdateForm'#10'LCLVersion'#6#6'0.9.29'#0#12'TPr'
+ +'ogressBar'#16'DownloadProgress'#4'Left'#2#24#6'Height'#2#28#3'Top'#2'@'#5'W'
+ +'idth'#3#157#1#7'Anchors'#11#5'akTop'#6'akLeft'#7'akRight'#0#6'Smooth'#9#8'T'
+ +'abOrder'#2#0#0#0#7'TButton'#12'UpdateButton'#4'Left'#2#24#6'Height'#2'('#3
+ +'Top'#2#8#5'Width'#3#157#1#7'Anchors'#11#5'akTop'#6'akLeft'#7'akRight'#0#7'C'
+ +'aption'#6#7'Update!'#7'OnClick'#7#17'UpdateButtonClick'#8'TabOrder'#2#1#0#0
+ +#7'TButton'#8'OkButton'#4'Left'#3'j'#1#6'Height'#2#25#3'Top'#3'`'#1#5'Width'
+ +#2'K'#7'Anchors'#11#7'akRight'#8'akBottom'#0#7'Caption'#6#2'Ok'#7'OnClick'#7
+ +#13'OkButtonClick'#8'TabOrder'#2#2#0#0#7'TButton'#12'CancelButton'#4'Left'#2
+ +#24#6'Height'#2#25#3'Top'#3'`'#1#5'Width'#2'K'#7'Anchors'#11#6'akLeft'#8'akB'
+ +'ottom'#0#7'Caption'#6#6'Cancel'#7'OnClick'#7#17'CancelButtonClick'#8'TabOrd'
+ +'er'#2#3#0#0#5'TMemo'#9'UpdateLog'#4'Left'#2#24#6'Height'#3#207#0#3'Top'#3
+ +#128#0#5'Width'#3#157#1#7'Anchors'#11#5'akTop'#6'akLeft'#7'akRight'#8'akBott'
+ +'om'#0#8'TabOrder'#2#4#0#0#6'TLabel'#13'DownloadSpeed'#4'Left'#2#24#6'Height'
+ +#2#14#3'Top'#2'h'#5'Width'#2'N'#7'Caption'#6#13'DownloadSpeed'#11'ParentColo'
+ +'r'#8#7'Visible'#8#0#0#0
+]);
diff --git a/branches/script-component/Projects/SAMufasaGUI/updateform.pas b/branches/script-component/Projects/SAMufasaGUI/updateform.pas
new file mode 100644
index 0000000..dbfb050
--- /dev/null
+++ b/branches/script-component/Projects/SAMufasaGUI/updateform.pas
@@ -0,0 +1,241 @@
+unit updateform;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+ Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
+ ComCtrls, StdCtrls, updater;
+
+type
+
+ { TSimbaUpdateForm }
+
+ { TSimbaVersionThread }
+
+ TSimbaVersionThread = class(TThread)
+ public
+ ResultStr : string;
+ InputURL : string;
+ Done : boolean;
+ procedure Execute; override;
+ end;
+ TSimbaUpdateForm = class(TForm)
+ DownloadSpeed: TLabel;
+ UpdateLog: TMemo;
+ UpdateButton: TButton;
+ OkButton: TButton;
+ CancelButton: TButton;
+ DownloadProgress: TProgressBar;
+ procedure CancelButtonClick(Sender: TObject);
+ procedure CleanUpdateForm(Sender: TObject);
+ procedure FormCreate(Sender: TObject);
+ procedure OkButtonClick(Sender: TObject);
+ procedure UpdateButtonClick(Sender: TObject);
+ function CanUpdate: Boolean;
+
+ private
+ { private declarations }
+
+ Updater: TMMLFileDownloader;
+ FStartTime : longword;
+ FCancelling: Boolean;
+ FDone: Boolean;
+ FUpdating : boolean;
+ FOldSpeed : integer;
+ FLastUpdateSpeed : longword;
+ FSimbaVersion: Integer;
+ SimbaVersionThread : TSimbaVersionThread;
+ private
+ function OnUpdateBeat: Boolean;
+ function GetLatestSimbaVersion: Integer;
+ public
+ { public declarations }
+ procedure PerformUpdate;
+ protected
+ FCancelled: Boolean;
+ end;
+
+const
+ DownloadSpeedTextRunning = 'Downloading at %d kB/s';
+ DownloadSpeedTextEnded = 'Downloaded at %d kB/s';
+
+var
+ SimbaUpdateForm: TSimbaUpdateForm;
+
+implementation
+
+uses
+ internets, TestUnit, simbasettings,lclintf;
+
+function TSimbaUpdateForm.CanUpdate: Boolean;
+begin
+ GetLatestSimbaVersion;
+ Writeln(format('Current Simba version: %d',[TestUnit.SimbaVersion]));
+ Writeln('Latest Simba Version: ' + IntToStr(FSimbaVersion));
+ Exit(testunit.SimbaVersion < FSimbaVersion);
+end;
+
+function TSimbaUpdateForm.GetLatestSimbaVersion: Integer;
+
+begin
+ if SimbaVersionThread = nil then//Create thread (only if no-other one is already running)
+ begin
+ SimbaVersionThread := TSimbaVersionThread.Create(true);
+
+ SimbaVersionThread.InputURL := SettingsForm.Settings.GetSetLoadSaveDefaultKeyValueIfNotExists(
+ 'Settings/Updater/RemoteVersionLink',
+ 'http://old.villavu.com/merlijn/Simba'{$IFDEF WINDOWS} +
+ '.exe'{$ENDIF} + '.version',
+ SimbaSettingsFile);
+
+ SimbaVersionThread.Resume;
+ while SimbaVersionThread.Done = false do//Wait till thread is done
+ begin
+ Application.ProcessMessages;
+ Sleep(50);
+ end;
+ FSimbaVersion := StrToIntDef(Trim(SimbaVersionThread.ResultStr), -1);//Read output
+ FreeAndNil(SimbaVersionThread);//Free the thread
+ end else
+ begin
+ //Another thread is already running, lets wait for it! (When it's nil, it means that the result is written!)
+ while SimbaVersionThread = nil do
+ begin;
+ Application.ProcessMessages;
+ Sleep(50);
+ end;
+ end;
+ Exit(FSimbaVersion);
+end;
+
+procedure TSimbaUpdateForm.UpdateButtonClick(Sender: TObject);
+begin
+ if FUpdating then
+ UpdateLog.Lines.Add('Already performing an update!')
+ else
+ Self.PerformUpdate;
+end;
+
+procedure TSimbaUpdateForm.CancelButtonClick(Sender: TObject);
+begin
+ if FCancelled or FDone then
+ begin
+ Self.ModalResult:=mrCancel;
+ Self.Hide;
+ end else
+ begin
+ FCancelling := True;
+ end;
+end;
+
+procedure TSimbaUpdateForm.CleanUpdateForm(Sender: TObject);
+begin
+ Self.DownloadProgress.Position:=0;
+ Self.UpdateLog.Clear;
+ Self.UpdateLog.Lines.Add('---------- Update Session ----------');
+ Self.DownloadSpeed.Visible:= false;
+end;
+
+procedure TSimbaUpdateForm.FormCreate(Sender: TObject);
+begin
+ FDone := True;
+ FUpdating:= false;
+
+end;
+
+procedure TSimbaUpdateForm.OkButtonClick(Sender: TObject);
+begin
+ Self.ModalResult:=mrOK;
+ Self.Hide;
+end;
+
+{ Return true if we have to cancel }
+function TSimbaUpdateForm.OnUpdateBeat: Boolean;
+var
+ Percentage: Integer;
+ NewSpeed : integer;
+begin
+ Application.ProcessMessages;
+
+ Percentage := Updater.GetPercentage();
+ if Percentage <> -1 then
+ DownloadProgress.Position:=Percentage;
+ // Formula for speed (kB/s) -> (Bytes div 1000) / (MSecSinceStart div 1000) = Bytes/ MSecSinceStart
+ NewSpeed :=(Updater.DownloadedSize) div ((GetTickCount-FStartTime));
+ if abs(NewSpeed - FOldSpeed) > 1 then
+ if (GetTickCount - FLastUpdateSpeed) > 1000 then //Only update the speed text every second
+ begin;
+ FOldSpeed:= NewSpeed;
+ DownloadSpeed.Caption:= Format(DownloadSpeedTextRunning,[NewSpeed]);
+ FLastUpdateSpeed:= GetTickCount;
+ end;
+ Result := FCancelling;
+end;
+
+procedure TSimbaUpdateForm.PerformUpdate;
+
+begin
+ FUpdating:= True;
+ Updater := TMMLFileDownloader.Create;
+
+ FDone := False;
+ FCancelling := False;
+ FCancelled := False;
+
+ Updater.FileURL := SettingsForm.Settings.GetSetLoadSaveDefaultKeyValueIfNotExists(
+ 'Settings/Updater/RemoteLink',
+ 'http://old.villavu.com/merlijn/Simba'{$IFDEF WINDOWS} +'.exe'{$ENDIF},
+ SimbaSettingsFile
+ );
+
+ //ApplicationName{$IFDEF WINDOWS} +'.exe'{$ENDIF};
+
+ // Should work on Windows as well
+ Updater.ReplacementFile := ExtractFileName(Application.ExeName);
+ Updater.OnBeat := @Self.OnUpdateBeat;
+ Updater.BasePath := ExtractFilePath(Application.ExeName);
+
+ Self.UpdateLog.Lines.Add('Starting download of ' + Updater.FileURL + ' ...');
+ try
+ Self.OkButton.Enabled := False; // grey out button
+ DownloadSpeed.Visible:= true;
+ DownloadSpeed.Caption:= Format(DownloadSpeedTextRunning,[0]);
+ FStartTime:= GetTickCount - 1;//Be sure that we don't get div 0
+ Updater.DownloadAndSave;
+ DownloadSpeed.Caption := Format(DownloadSpeedTextEnded,[Updater.FileSize div (GetTickCount-FStartTime)]);
+ Self.UpdateLog.Lines.Add('Downloaded to ' + Updater.ReplacementFile + '_ ...');
+ Updater.Replace;
+ Self.UpdateLog.Lines.Add('Renaming ' + Updater.ReplacementFile + ' to ' + Updater.ReplacementFile + '_old_');
+ Self.UpdateLog.Lines.Add('Renaming ' + Updater.ReplacementFile + '_ to ' + Updater.ReplacementFile);
+ Self.UpdateLog.Lines.Add('Deleting ' + Updater.ReplacementFile + '_old_');
+ Updater.Free;
+ Self.UpdateLog.Lines.Add('Done ... ');
+ Self.UpdateLog.Lines.Add('Please restart all currently running Simba binaries.');
+ except
+ FCancelling := False;
+ FCancelled := True;
+ DownloadSpeed.Visible:= false;
+ Self.UpdateLog.Lines.Add('Download stopped at '+inttostr(DownloadProgress.Position)+'%... Simba did not succesfully update.');
+ // more detailed info
+ writeln('EXCEPTION IN UPDATEFORM: We either hit Cancel, or something went wrong with files');
+ end;
+ FDone := True;
+ Self.OkButton.Enabled := True; // un-grey out button
+ FUpdating:= false;
+end;
+
+{ TSimbaVersionThread }
+
+procedure TSimbaVersionThread.Execute;
+begin
+ ResultStr:= GetPage(InputURL);
+ done := true;
+end;
+
+initialization
+ {$I updateform.lrs}
+
+end.
+
diff --git a/branches/script-component/Projects/forking/project1.lpi b/branches/script-component/Projects/forking/project1.lpi
new file mode 100644
index 0000000..f7ffe64
--- /dev/null
+++ b/branches/script-component/Projects/forking/project1.lpi
@@ -0,0 +1,203 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/branches/script-component/Projects/forking/project1.lpr b/branches/script-component/Projects/forking/project1.lpr
new file mode 100644
index 0000000..c034274
--- /dev/null
+++ b/branches/script-component/Projects/forking/project1.lpr
@@ -0,0 +1,121 @@
+program project1;
+
+{$mode objfpc}{$H+}
+
+uses
+ {$IFDEF UNIX}{$IFDEF UseCThreads}
+ cthreads,
+ {$ENDIF}{$ENDIF}
+ Classes, SysUtils, CustApp, Process
+ { you can add units after this };
+
+type
+
+ { TMyApplication }
+
+ TMyApplication = class(TCustomApplication)
+ protected
+ procedure DoRun; override;
+ public
+ constructor Create(TheOwner: TComponent); override;
+ destructor Destroy; override;
+ procedure WriteHelp; virtual;
+ end;
+
+{ TMyApplication }
+
+procedure TMyApplication.DoRun;
+var
+ ErrorMsg: String;
+
+ Processes: array of TProcess;
+ i, c, a:integer;
+
+begin
+
+ // quick check parameters
+ ErrorMsg:=CheckOptions('h','help');
+ if ErrorMsg<>'' then begin
+ ShowException(Exception.Create(ErrorMsg));
+ Terminate;
+ Exit;
+ end;
+
+ // parse parameters
+ if HasOption('h','help') then begin
+ WriteHelp;
+ Terminate;
+ Exit;
+ end;
+
+ a := 5;
+ SetLength(Processes, a);
+ for i := 0 to a - 1 do
+ begin
+ Processes[i] := TProcess.Create(Self);
+ {$WARNING SET THIS PATH}
+ //Processes[i].CommandLine := 'C:/mufasa/Projects/MufasaTests/project1.exe';
+ Processes[i].CommandLine := '/home/merlijn/Programs/mufasa/Projects/MufasaTests/project1';
+ //Processes[i].ApplicationName := 'ForkingTest: ' + inttostr(i);
+ Processes[i].Execute;
+ sleep(100);
+ Writeln('Process ' + inttostr(i) + ', has ID ' + inttostr(Processes[i].ProcessID));
+ end;
+
+ sleep(10000);
+ while true do
+ begin
+ c := 0;
+ for i := 0 to a - 1 do
+ begin
+ if not Processes[i].Running then
+ c := c + 1;
+ end;
+ if c = a then
+ break;
+ sleep(1000);
+ end;
+
+ for i := 0 to a - 1 do
+ begin
+ Processes[i].Free;
+ end;
+ { add
+
+ end;
+ your program here }
+
+ // stop program loop
+ writeln('done');
+ Terminate;
+end;
+
+constructor TMyApplication.Create(TheOwner: TComponent);
+begin
+ inherited Create(TheOwner);
+ StopOnException:=True;
+end;
+
+destructor TMyApplication.Destroy;
+begin
+ inherited Destroy;
+end;
+
+procedure TMyApplication.WriteHelp;
+begin
+ { add your help code here }
+ writeln('Usage: ',ExeName,' -h');
+end;
+
+var
+ Application: TMyApplication;
+
+{$IFDEF WINDOWS}{$R project1.rc}{$ENDIF}
+
+begin
+ Application:=TMyApplication.Create(nil);
+ Application.Title:='My Application';
+ Application.Run;
+ Application.Free;
+end.
+
diff --git a/branches/script-component/README b/branches/script-component/README
new file mode 100644
index 0000000..277e88a
--- /dev/null
+++ b/branches/script-component/README
@@ -0,0 +1,3 @@
+Hello, and welcome to the Mufasa project.
+
+blablabla
diff --git a/branches/script-component/Tests/FPC/oldtest.pas b/branches/script-component/Tests/FPC/oldtest.pas
new file mode 100644
index 0000000..a8bca64
--- /dev/null
+++ b/branches/script-component/Tests/FPC/oldtest.pas
@@ -0,0 +1,220 @@
+{type
+ TMyThread = class(TThread)
+ private
+ protected
+ procedure Execute; override;
+ public
+ Constructor Create(CreateSuspended : boolean);
+ end;
+
+ constructor TMyThread.Create(CreateSuspended : boolean);
+ begin
+ FreeOnTerminate := True;
+ inherited Create(CreateSuspended);
+ end;
+
+procedure TMyThread.Execute;
+
+Const
+ fsFromBeginning = 0; // offset must be pos or 0
+ fsFromCurrent = 1; // offset pos or neg
+ fsFromEnd = 2; // offset only neg or 0
+
+ // put somewhese else
+ {$IFDEF MSWINDOWS}
+ TestPath = 'c:/test';
+ DirectorySeperator = '\';
+ DS = '\';
+ ExeExt = '.exe';
+ {$ENDIF}
+ {$IFDEF LINUX}
+ TestPath = '/tmp/test';
+ DirectorySeperator = '/';
+ DS = '/';
+ ExeExt = '';
+ {$ENDIF}
+Var
+ Client: TClient;
+ w,h, x, y, xx, yy, i,t1,t2:integer;
+ bmp: TBitmap;
+ ReturnData : TRetData;
+ arr: Array Of Integer;
+ LoopY,LoopX : integer;
+
+ s, s2: string;
+ myFile, myFile2: Integer;
+
+
+begin
+ while (not Terminated) do
+ begin
+
+ Writeln('Creating the client');
+ Client := TClient.Create;
+ //Client.MWindow.SetTarget(77594696);
+ Writeln('Getting the dimensions');
+ Client.MWindow.GetDimensions(w, h);
+ t1 := lclintf.gettickcount;
+ for i := 0 to 100 do
+ Client.MFinder.FindColor(x, y, 123456, 0, 0, w, h);
+ t2 := lclintf.gettickcount;
+ writeln(inttostr(round((t2 - t1) / 101)));
+
+ //break;
+
+
+
+ writeln(inttostr(w) + ' , ' + inttostr(h));
+ Writeln('Setting target');
+// Client.MWindow.SetTarget(67232,w_window);
+
+{ SetLength(Arr, 9);
+ for i := 0 to high(arr) do
+ arr[i] := $FFFFFF;
+
+ Client.MWIndow.SetTarget(PRGB32(@Arr[0]), Point(3, 3)); }
+
+// Client.MWindow.ActivateClient;
+
+ Client.MWindow.GetDimensions(w, h);
+ Writeln('Copying BMP');
+ bmp := Client.MWindow.CopyClientToBitmap(0, 0, w, h);
+ Writeln('Saving BMP');
+
+ {$IFDEF WINDOWS}
+ bmp.SaveToFile('c:\test1.bmp');
+ {$ENDIF}
+ {$IFDEF LINUX}
+ bmp.SaveToFile('/tmp/test1.bmp');
+ {$ENDIF}
+
+ writeln('Copied Bitmap');
+
+ Client.MInput.GetMousePos(x, y);
+ writeln(inttostr(x) + ' , ' + inttostr(y));
+
+ Client.MInput.SetMousePos(50, 50);
+ Client.MInput.GetMousePos(x, y);
+ writeln(inttostr(x) + ' , ' + inttostr(y));
+
+ Client.MInput.ClickMouse(60, 60, mouse_Right);
+
+ LoopX:= w div 2;
+ LoopY:= h div 2;
+ bmp.SetSize(Loopx + 1, Loopy + 1);
+ ReturnData := Client.MWindow.ReturnData(0, 0, Loopx + 1, Loopy + 1);
+
+ SetLength(Arr,(Loopy + 1) * (Loopx + 1));
+
+ for yy := 0 to Loopy do
+ begin;
+ for xx := 0 to Loopx do
+ begin
+ { Do comparison here }
+ Arr[yy * (loopx) + xx] :=RGBToColor(ReturnData.Ptr^.B,ReturnData.Ptr^.G,ReturnData.Ptr^.R);
+
+ // .Canvas not thread stable on linux. (use fpImage and fpCanvas)
+ //Bmp.Canvas.Pixels[xx,yy] := RGBToColor(ReturnData.Ptr^.R,ReturnData.Ptr^.G,ReturnData.Ptr^.B);
+
+ inc(ReturnData.Ptr);
+ end;
+ Inc(ReturnData.Ptr,ReturnData.IncPtrWith);
+ end;
+ bmp.Free;
+
+ Client.MWindow.SetTarget(@Arr[0], Point(loopx, loopy));
+ writeln(inttostr(loopx) + ' , ' + inttostr(loopy));
+ Client.MWindow.GetDimensions(W, H);
+ writeln(inttostr(w) + ' , ' + inttostr(h));
+
+ Bmp := Client.MWindow.CopyClientToBitmap(0, 0, loopx, loopy);
+
+
+ {$IFDEF WINDOWS}
+ bmp.SaveToFile('c:\test2.bmp');
+ {$ENDIF}
+ {$IFDEF LINUX}
+ bmp.SaveToFile('/tmp/test2.bmp');
+ {$ENDIF}
+
+ Bmp.free;
+
+// Client.MWIndow.SetTarget(PRGB32(@Arr[0]), Point(Loopx + 1, Loopy + 1));
+ Client.MWindow.FreeReturnData;
+
+ Client.MInput.IsMouseButtonDown(mouse_Right);
+ // Sleep(1000);
+ if Client.MInput.IsMouseButtonDown(mouse_Left) then
+ writeln('Left mouse is down!');
+ if Client.MInput.IsMouseButtonDown(mouse_Right) then
+ writeln('Right mouse is down!');
+ if Client.MInput.IsMouseButtonDown(mouse_Middle) then
+ writeln('Middle mouse is down!');
+
+
+ with Client.MFiles do
+ begin
+ s := ExtractFileDir(Application.ExeName);
+ Writeln('Our current path is: ' + s);
+ If DirectoryExists(s) Then
+ writeln('Directory ' + s + ' exists.');
+
+ If FileExists(s + DirectorySeperator + 'Cogat' + ExeExt) Then
+ writeln('We exist!');
+
+ myFile := CreateFile(TestPath);
+ WriteFileString(myFile, 'wat');
+ WriteFileString(myFile, 'watnumber2');
+ CloseFile(myFile);
+
+ myFile := OpenFile(TestPath, False);
+ ReadFileString(myFile, s2, 2);
+ writeln('s2: ' + s2);
+ CloseFile(myFile);
+
+ myFile := CreateFile(TestPath + '2');
+ WriteFileString(myFile, 'wat222');
+
+ CloseFile(myFile);
+
+ // TestPath now contains; 'watwatnumber2'. We will make it write 'number',
+ // and then 2.
+ myFile := OpenFile(TestPath, False);
+ SetFileCharPointer(myFile, 6, fsFromBeginning);
+ ReadFileString(myFile, s2, 6);
+ writeln('s2: ' + s2);
+ s2 := '';
+
+ SetFileCharPointer(myFile, -1, fsFromEnd);
+ ReadFileString(myFile, s2, 1);
+ writeln('s2: ' + s2);
+ CloseFile(myFile);
+ // myFile2 should be -1.
+ myFile := RewriteFile(TestPath, False);
+ myFile2 := RewriteFile(TestPath, False);
+ writeln(inttostr(myFile) + ' : ' + inttostr(myFile2));
+
+ // myFile2 should be -1.
+ myFile2 := OpenFile(TestPath, False);
+ writeln(inttostr(myFile) + ' : ' + inttostr(myFile2));
+
+ // Now, we will test EndOfFile, and FileSize.
+
+ While Not EndOfFile(myFile) Do
+ Begin
+ ReadFileString(myFile, s2, 1);
+ Writeln(s2);
+ End;
+
+ CloseFile(myFile);
+ writeln('wat');
+
+
+ end;
+ Client.Destroy;
+ writeln('Test completed successfully');
+ break;
+
+ end;
+end;
+ }
diff --git a/branches/script-component/Tests/PS/BmpTest.mufa b/branches/script-component/Tests/PS/BmpTest.mufa
new file mode 100644
index 0000000..e68871f
--- /dev/null
+++ b/branches/script-component/Tests/PS/BmpTest.mufa
@@ -0,0 +1,77 @@
+program new;
+//http://www.hawaiisunshine.org/wp-content/uploads/2008/12/sunshine1.jpg
+var
+ Bmp : integer;
+ x,y : integer;
+ w,h : integer;
+begin
+ Bmp := BitmapFromString(37, 32, 'beNqFl3lwVuUVxp93veu3f1' +
+ 'lI+EKCLCkIAuI6oIBl0ylWweJerSm2atAaUJYgZCMLBAKyTSAh+w4' +
+ 'ERKnUpWoXERSBjtailDVACLS17Tj+13NvpB3tTHvnzOTOzb3vL+c5' +
+ 'azIGaIDMYMwQ3BBSkSkD4J4xCa4gNKQBZTClTS5tMBNQgAAY6C3mG' +
+ 'cN/zP/Wf0o3373oK0mfM8/E1UMMAa0YmZKQ4pvz6DUHzAJM3wwmpH' +
+ '/6t1j/D3f1He/Xyj/HFQgzhIEQEAHiQDIwAEjzbrjrQX2c7yNJwDn' +
+ '/5vh+Tb5l/3Vx77mhdFDLEEMMSPdtMDAGmMAwXWOWxWfb4s6APT4a' +
+ 'S5iBCDgRLT8KnjhcEJEJIgvP/ieOccPgZpDrsO/FIGAUcI8TeMwJP' +
+ 'heOLI/FVkZj5YFAuWEscANTw8lDnEgcMgQeBDd9hQXjQggu6ack+z' +
+ 'b0u5enHpAEZADXA3MDwSWZgwtSB5aG4+VmoBxGOfgqYC2wVNrjIaJ' +
+ 'gQV/nKBdh7rnpMPKUecnGhCI044xdzZ9+5tV40ZXMPenIo/ujumRk' +
+ '5oahA1cHCIEqsCqINZCV3Fpjhsp08CnDHe5RVAw86oeVLOoHN8W/T' +
+ '+YywpWnMPfj2h/d/iTm3xBHAHcHUDT2mi3jrqmISgJVK2yXvFbqjd' +
+ 'ysYGah4S5xQ08b1t1CDZMi4COygKHANcBYYHbmwEUzpg33JUoSgiB' +
+ 'aCWFKP+P75ca/U3j9iOH7pk2pHpRaAmwSaHJ0NbCRnkuxynFXhEN5' +
+ 'SbHHosGpEsN9FzJtjBYYDcwCirPSm267pWbSLQuGDxrXn7rKO57O5' +
+ 'dqyAuGrGeuB/CrjHZmZG6TYANQL3qpEE9g2YJvQa4ReBPYT4IfAFD' +
+ '+sQ/34kl93Glg1etBrk8Z1j8hYb2MpkGfh8RCboL1kiynpWK6fuRa' +
+ 'D5lDcq2mvfMnaQnaj4g0AWSPQDNYIVSusddJ+ial5wA+AicANPnEa' +
+ 'R/61SR3Tx+y+dXBnltGditfT+asJ/Up2rOumYQsTkZFAKqmtXC8Bj' +
+ 'TiDzWFyD6p9KN8C1ADthuwyDWI1gDfB2OQJa20IRMqD4YWWkcNxP/' +
+ 'AghfW6RNvYAV3XxbqGGjvT8Uoy9sWxN4LuKHYPjuy8YcSiRNpNnqr' +
+ 'U+Dwih61AUfRwXt9iYksImy1slqiVvNV0W5TTCN0s3QZt15r2Jq2r' +
+ 'tFxrmRuToo2J+GuDgntTsSMV3ZnYl403RuLd7+H9bH1omLsngpaYU' +
+ '2xbpMa1XgkrB5YFbVLieKnqFyNnm4LYFlI1rrFV6Rqu67nRLO1WaT' +
+ 'UKUcdQyyiOaHB4V2rwjczIwSzzyBB5cKTxu9HGW9epX13L9w/Bmxn' +
+ 'YH8EuEw0C9LctCUTvZeYQIAFGNRL2mx6lK/PTZZuFelc32FY1RL2y' +
+ 'Opxwo9KtpqwXaLVRw9EewtvZgXdGhI7cmPLJGPvoSHZsvHtonLsvC' +
+ '3sHYV9CdATRotDAUc1QpTg5+LwVeFhY06GvB0v4zSrsdzxK0AaFRi' +
+ 'VJxiZltxgu3Wynhxo7Y6gWaIvi9+OtD28N/mFy0rHbQ0dvlp9OtA6' +
+ 'M5m8Nwfujo+9lx7tjssNlDRLbODYxrBMoN8VyQy+Uep7QD7uhmZY9' +
+ '0bFH2TrKvBpp9Ux0SqddOp6MhtFgojMJNQ5aUnFkWuCTWeHDM8zj9' +
+ 'yV/MFUemi4/nGq9c714e4T1wai0NwdGWzij2qlnbCvDyxxrBCoUVi' +
+ 'oUKpGv9S9Md54TfiASnRx0MihNgU6OLq7aBaWlbhSq3VWdcTTFURv' +
+ 'FRzPNM48nfzLH/GyudXS2PnAXfjMDb07EgcmhwxPS96W7LZwKR20H' +
+ 'q4PaygTh1nKUMawkAwo5WwDkcvNR05miJI0Y6khdFu+0dLMWJGmTJ' +
+ 'ZuDaI5jWxgfTTMv5Aw4di+OPyRPPeES6+hs/s4d+O33xcczUt8dG2' +
+ '20vApqFW4DrBrwanAqnyoGaoPFQBFQwHg+RJ60HxHqNmpHAPX2Nhf' +
+ '0IQnYEjCagtgeQEMc799u9s7LOPlj5/ij7OQT+sgckB27j308S5x8' +
+ 'MHHwtkhzCHUSrVJR1dTB2NLf95gn5iqGUoYSqEKmXxLmAsP9Edh4v' +
+ 'yPRHGlwsN0CgVqisi6E1nT8+mbz77mje3KSTzyuLueFT+Sww3Pw5x' +
+ 'zj0wdkz2MpX8yKv56FOk5+oY1zcrAabCPlJEeFRKn0WKXQpbCL4OZ' +
+ 'B/cy0ZgLZ/tRwOSMcsTpSjLYUTvF6fRy/kjvy/FNpPU8Hr7wY+/xJ' +
+ 'fJaDSy+ETj9jnvpp4G9PZu8fhjqNLgcdCnXUacFqhNoo2RrKEIEij' +
+ 'kJPTFkCawXsZxnPsa07GM/yaoFpqbrjRnOAt8RY5yDszMb5nw+8mB' +
+ 'c785w+MR+nntdfzBe9S8PHn8YXubi8IOXAJLc7Dc022ilvJSNWLcR' +
+ 'mkhFYTU5xFAsUS1GidLEw86V+VuMhjQngaV7NKSizM8DbQ6otiXVk' +
+ '4eN73MsvppxZyE++gLP54vM8nF8WOLlAnV9sn1moz82PvzoCHTFeb' +
+ '6DZZNR2SMmtEFvA14Othp+T3MNRFazgaonk8w08aOAmyBRv/hg0ll' +
+ 'ps7Egy25LRORSXnx98eVmkn9Vb5J5cLC4VBk7koe+l0KUl8cNzDKr' +
+ 'EtoifWtRGpIcj1zYzsY68A8o5SgVKhCgSvAByMeO5ms3VfIw/8Q1O' +
+ 'iyQ6w+hON5oHYP8t+HJZRu8yeXY5egr1uQLrQoF9Zom8sFReWGRfX' +
+ 'pixewwaY9gRl5TMdQJ1Smxl7GVgAxhtMpUMFQJlHpEVgxeCLwbLVf' +
+ 'JeybP9BSAgJE3nPenoTAMp+dmjQfLiYhEuluNsiTqzwuwpNM/ms8s' +
+ 'rjCuLw6dz0uoHoD2GPclWm8Opl24nnCAZaavBGsJxD0fmVwEv8nCC' +
+ 'Vo47ucjqX6X8WtiTgdYB+OWN5FriUqE6vxI9FThVzM6V2KeXo6/Yu' +
+ 'LLc+Ud+4uA0pykZXXHsDMtmE9sYtgpsFp6MhFvrV1ylj6sA4TwHl8' +
+ 'J4yg5OBhvo40hPGr67MrF3FP74kPPP0uS+Mpwtw6lSnC7DuTJ1vlh' +
+ 'cKjC+XB7tm5+2ezi6UrArKjqoSA1s12yTn5DrOa/irNLvlmSruYcr' +
+ 'BSuDXMasHCdyo19xUX9VnsSwKxsf3IWvChJ/WWn0VXqgUyTmKpwpw' +
+ 'V8rndML8XXB4D/NjdRT1JJVd1S3GWixZKOjN/gaVknRD1pLpSf8CF' +
+ 'KKghMuXwYecbx1gja0VO6tOvcZ4r0p6FuQ9HVFvHel59qFtR7rdDn' +
+ '61grKmUtLA725CYpsawy7U+2dAfKO1SlUc6//V/lOkWs05ip9SdcJ' +
+ 'bwf2cMxcZATuD8dp3qULkJ60vD0TC/XkZnxVmtJbiIskYDlOFuN8J' +
+ 'etZjd5V6FmGvkVJh+6ym1PQSgtJ3Njh0mTktcIbbV6G+E4Ra4Pma/' +
+ 'xNm4T1vGOqVNp5ZnCashLeWPf+47gnwIv/BWSck+g=');
+ GetClientDimensions(w,h);
+ if FindBitmapToleranceIn(bmp,x,y,0,0,w-1,h-1,25) then
+ MoveMouse(x,y);
+end.
diff --git a/branches/script-component/Tests/PS/ColourTest.mufa b/branches/script-component/Tests/PS/ColourTest.mufa
new file mode 100644
index 0000000..eb396f6
--- /dev/null
+++ b/branches/script-component/Tests/PS/ColourTest.mufa
@@ -0,0 +1,31 @@
+program new;
+var
+ p1, p2: TPointArray;
+ w, h: integer;
+ i, col: integer;
+ bmp: integer;
+
+begin
+ SetColorToleranceSpeed(2);
+ bmp := LoadBitmap('/home/merlijn/Pictures/Mooi/Carina_1_by_Eeitam.png');
+ SetTargetBitmap(bmp);
+ GetClientDimensions(W, H);
+ writeln(inttostr(w) + ' : ' + inttostr(h));
+
+ for i := 0 to 100 do
+ begin
+ col := Random(clWhite);
+ writeln(inttostr(col));
+ FindColorsTolerance(p1, col, 0, 0, W - 1, H - 1, 40);
+ FindColorsToleranceOptimised(p2, col, 0, 0, W - 1, H - 1, 40);
+ writeln(inttostr(length(p1)) + ' : ' + inttostr(length(p2)));
+ if(length(p1) <> length(p2)) then
+ writeln('wat!');
+
+ setlength(p1,0);
+ setlength(p2,0);
+
+ end;
+
+ FreeBitmap(bmp);
+end.
diff --git a/branches/script-component/Tests/PS/DeformedTest.mufa b/branches/script-component/Tests/PS/DeformedTest.mufa
new file mode 100644
index 0000000..0d3ff6d
--- /dev/null
+++ b/branches/script-component/Tests/PS/DeformedTest.mufa
@@ -0,0 +1,21 @@
+program New;
+//Scar manual -> you have to pick x1,y1,x2,y2 yourself. (It's at the first bitmapa
+var
+ Deformed ,x,y: integer;
+ ThaTime : integer;
+ i : integer;
+ acc : extended;
+begin
+ Deformed := BitmapFromString(25, 24, 'beNrN1UEKwCAMBMDtb/oO' +
+ 'r/0//U1pISCiYUnCIpU9eRgihgTg525HD6pnRKZIkKAWEYJmjXI1F' +
+ 'VV2IhQavpzX02M3XHOdEZmSoohj5bmUW3CWMi3rkDf+k1q1AiX/QS' +
+ '21aqRFuRNssP2TQTv6suDmNVFcXi/8Qvf1');
+ //Doing this same code in scar will result in invalid results, since
+ //fast replacedolor didn't work alright, atleast for me.
+ FastReplaceColor(Deformed,clblack,clwhite);
+ FastReplaceColor(deformed,82647,clblack);
+ ThaTime := GetSystemTime;
+ FindDeformedBitmapToleranceIn(Deformed, x, y, 119, 538, 213, 613, 70, 10, True, acc);
+ Writeln(inttostr(GetSystemTime - ThaTime));
+ Writeln(floattostr(acc));
+end.
diff --git a/branches/script-component/Tests/PS/FileTests.mufa b/branches/script-component/Tests/PS/FileTests.mufa
new file mode 100644
index 0000000..5135302
--- /dev/null
+++ b/branches/script-component/Tests/PS/FileTests.mufa
@@ -0,0 +1,90 @@
+program Hoi;
+
+{
+ Description: Test file to test the consistency of
+ the following Functions:
+
+ AppPath, DirectoryExists, FileExists, ExeExt,
+ DirectorySeperator, OpenFile, CreateFile, RewriteFile,
+ WriteFileString, ReadFileString, SetFileCharPointer,
+ FileSize, EndOfFile, FileContents.
+
+ Notes:
+ Needs: GetFiles.
+
+ Bugs:
+ Using ./test as TestPath crashes on Linux.
+ Usage:
+ Run it. Set the TestPath to a different directory if you are on Windows. :)
+}
+
+Const
+ TestPath = './test';
+
+ fsFromBeginning = 0; // offset must be pos or 0
+ fsFromCurrent = 1; // offset pos or neg
+ fsFromEnd = 2; // offset only neg or 0
+
+var
+ s, s2: string;
+ myFile, myFile2: Integer;
+
+begin
+ s := apppath;
+ Writeln('Our current path is: ' + s);
+ { If DirectoryExists(s) Then
+ writeln('Directory ' + s + ' exists.'); }
+
+ { If FileExists(s + DirectorySeperator + 'Cogat' + ExeExt) Then
+ writeln('We exist!'); }
+
+ myFile := CreateFile(TestPath);
+ WriteFileString(myFile, 'wat');
+ WriteFileString(myFile, 'watnumber2');
+ CloseFile(myFile);
+
+ myFile := OpenFile(TestPath, False);
+ ReadFileString(myFile, s2, 2);
+ writeln('s2: ' + s2);
+ CloseFile(myFile);
+
+ myFile := CreateFile(TestPath + '2');
+ WriteFileString(myFile, 'wat222');
+
+ CloseFile(myFile);
+
+ // TestPath now contains; 'watwatnumber2'. We will make it write 'number',
+ // and then 2.
+ myFile := OpenFile(TestPath, False);
+ SetFileCharPointer(myFile, 6, fsFromBeginning);
+ ReadFileString(myFile, s2, 6);
+ writeln('s2: ' + s2);
+ s2 := '';
+
+ SetFileCharPointer(myFile, -1, fsFromEnd);
+ ReadFileString(myFile, s2, 1);
+ writeln('s2: ' + s2);
+ CloseFile(myFile);
+
+ // myFile2 should be -1.
+ myFile := RewriteFile(TestPath, False);
+ myFile2 := RewriteFile(TestPath, False);
+ writeln(inttostr(myFile) + ' : ' + inttostr(myFile2));
+
+ // myFile2 should be -1.
+ myFile2 := OpenFile(TestPath, False);
+ writeln(inttostr(myFile) + ' : ' + inttostr(myFile2));
+
+ // Now, we will test EndOfFile, and FileSize.
+
+ While Not EndOfFile(myFile) Do
+ Begin
+ ReadFileString(myFile, s2, 1);
+ Writeln(s2);
+ End;
+
+ CloseFile(myFile);
+
+ //Writeln(FileContents(TestPath));
+ writeln('wat');
+end.
diff --git a/branches/script-component/Tests/PS/FormTest.mufa b/branches/script-component/Tests/PS/FormTest.mufa
new file mode 100644
index 0000000..f5031a4
--- /dev/null
+++ b/branches/script-component/Tests/PS/FormTest.mufa
@@ -0,0 +1,35 @@
+program new;
+var
+ TempVar : Boolean;
+procedure OnClick(Sender : TObject);
+begin;
+ TempVar := True;
+ Writeln('YOU HAS CLICKED THE BUTTON');
+end;
+function x : Boolean;
+var
+ MyForm : TForm;
+ AButton : TButton;
+begin;
+ TempVar := False;
+ Result := false;
+ MyForm := TForm.Create(nil);
+ MyForm.Width := 250;
+ MyForm.Height := 250;
+ AButton := TButton.Create(MyForm);
+ AButton.Parent := MyForm;
+ Abutton.SetBounds(100,100,100,50);
+ AButton.OnClick := @OnClick;
+ AButton.Caption := 'Test';
+ MyForm.ShowModal;
+ MyForm.Free;
+ Result := TempVar;
+end;
+var
+ v : TVariantArray;
+begin
+ if ThreadSafeCall('x',v) then
+ Writeln('You clicked the button! WinnOr')
+ else
+ Writeln('You did not click the button, fail all the way');
+end.
diff --git a/branches/script-component/Tests/PS/IncludeTest.mufa b/branches/script-component/Tests/PS/IncludeTest.mufa
new file mode 100644
index 0000000..8e9c926
--- /dev/null
+++ b/branches/script-component/Tests/PS/IncludeTest.mufa
@@ -0,0 +1,6 @@
+program new;
+{.include test.mufa}
+begin
+ Writeln(TestStr);
+ Writeln(inttostr(MultiPly(500,-20)));
+end.
diff --git a/branches/script-component/Tests/PS/MaskTest.mufa b/branches/script-component/Tests/PS/MaskTest.mufa
new file mode 100644
index 0000000..79db52e
--- /dev/null
+++ b/branches/script-component/Tests/PS/MaskTest.mufa
@@ -0,0 +1,22 @@
+program new;
+//http://nl.wikipedia.org/wiki/Lily_Allen
+
+var
+ Bmp : integer;
+ Mask : TMask;
+ x,y : integer;
+ i, ii : integer;
+ w,h : integer;
+begin
+ Bmp := BitmapFromString(107, 19, 'beNrtVkEOgCAM8/+fxoOJUYG' +
+ 'uWwZKbE9KtmYrHbBtgiAIgpCOckFiopdtZr/j2HhynBjYjmntJxaW' +
+ '6BwJWC8eH6QU15gz0Zx9vFgX0Iwhs0CASRUW8CFmioB1JFisA5qRI' +
+ 'KvJQNKa5mEcyAhoauI6N8ymAlkxWpdtwgL2bhPXCJc7+E7JLNJsgG' +
+ 'qQgL1jhHwX4VJdBsNZMbN5D//m/ob5XzwDp40wfg/jW9g024hbuPd' +
+ 'ritabVqaAj7zYVyxg9fol4M8FFG7YAfIG00k=');
+ Mask := CreateBitmapMask(Bmp);
+ GetClientDimensions(w,h);
+// if FindBitmapMaskTolerance(Bmp,x,y,0, 0,w-1, h-1,1,5) then
+ if FindMaskTolerance(Mask,x,y,0, 0,w-1, h-1,1,5) then
+ MoveMouse(x,y);
+end.
diff --git a/branches/script-component/Tests/PS/Neopets_old.mufa b/branches/script-component/Tests/PS/Neopets_old.mufa
new file mode 100644
index 0000000..4891a82
--- /dev/null
+++ b/branches/script-component/Tests/PS/Neopets_old.mufa
@@ -0,0 +1,148 @@
+program BankProblems;
+
+// http://www.neopets.com/games/play.phtml?game_id=371
+
+Const
+ KeyDownUpSpeed = 1; // The Higher the "KeyDownUpSpeed", the slower the script is.
+
+Type
+ Door = record
+ X: Integer;
+ Y: Integer;
+ DoorChar: Byte;
+ IsOpen: Boolean;
+ IsMonster: Boolean;
+ WhatMonster: String;
+ End;
+
+Var
+ Doors: Array [0..5] Of Door;
+
+Procedure DeclareStuff;
+
+Var
+ I: Integer;
+Begin
+ For I := 0 To 5 Do
+ Begin
+ Doors[I].X := 45 + I * 96;
+ Doors[I].Y := 210;
+ End;
+
+ Doors[0].DoorChar := 83;
+ Doors[1].DoorChar := 68;
+ Doors[2].DoorChar := 70;
+ Doors[3].DoorChar := 74;
+ Doors[4].DoorChar := 75;
+ Doors[5].DoorChar := 76;
+End;
+
+Function IsBadGuy(DN: Integer): Boolean;
+
+Var
+ TempColor: Array [0..11] Of Integer;
+ I, x, y: Integer;
+ H, S, L: Extended;
+Begin
+ TempColor[0] := GetColor(Doors[DN].X, Doors[DN].Y);
+ TempColor[1] := GetColor(Doors[DN].X, Doors[DN].Y-1);
+ TempColor[2] := GetColor(Doors[DN].X-1, Doors[DN].Y);
+ TempColor[3] := GetColor(Doors[DN].X, Doors[DN].Y+1);
+ TempColor[4] := GetColor(Doors[DN].X+1, Doors[DN].Y);
+ TempColor[5] := GetColor(Doors[DN].X, Doors[DN].Y-2);
+ TempColor[5] := GetColor(Doors[DN].X-2, Doors[DN].Y);
+ TempColor[6] := GetColor(Doors[DN].X+1, Doors[DN].Y+2);
+ TempColor[7] := GetColor(Doors[DN].X+2, Doors[DN].Y);
+ TempColor[8] := GetColor(Doors[DN].X, Doors[DN].Y-3);
+ TempColor[9] := GetColor(Doors[DN].X-3, Doors[DN].Y);
+ TempColor[10] := GetColor(Doors[DN].X+1, Doors[DN].Y+3);
+ TempColor[11] := GetColor(Doors[DN].X+3, Doors[DN].Y);
+
+ For I := 0 To 11 Do
+ Begin
+ If SimilarColors(TempColor[I], 3055, 30) Then // Red Devil
+ Begin
+ Result := True;
+ Doors[DN].WhatMonster := 'Devil';
+ Exit;
+ End;
+ End;
+
+ For I := 0 To 11 Do
+ Begin
+ If SimilarColors(TempColor[I], 12841714, 40) Then // Squirrle
+ Begin
+ ColorToHSL(TempColor[I], H, S, L);
+ If (L > 60) And (L < 95) Then
+ If (H > 5 ) And (H < 30) Then
+ If FindColorTolerance(x, y, 4092580, Doors[DN].X, Doors[DN].Y-1,
+ Doors[DN].X + 20, Doors[DN].Y + 1, 40)
+ Then
+ Begin
+ Result := True;
+ Doors[DN].WhatMonster := 'Squirrle';
+ Exit;
+ End;
+ End;
+ End;
+
+ For I := 0 To 11 Do
+ Begin
+ If SimilarColors(TempColor[I], 28756, 30) Then // Green Monster
+ Begin
+ Result := True;
+ Doors[DN].WhatMonster := 'Green Monster';
+ Exit;
+ End;
+ End;
+
+ For I := 0 To 11 Do
+ Begin
+ If SimilarColors(TempColor[I], 794793, 30) Then // Mysterious Man
+ Begin
+ Result := True;
+ Doors[DN].WhatMonster := 'Mysterious Man';
+ Exit;
+ End;
+ End;
+
+End;
+
+Procedure HandleMonsters;
+
+Var
+ I, iX, iY, Time: Integer;
+
+Begin
+ For I := 0 To 5 Do
+ Begin
+ If IsBadGuy(I) Then
+ Begin
+ KeyDown(Doors[I].DoorChar);
+ Wait(10 * KeyDownUpSpeed);
+ KeyUp(Doors[I].DoorChar);
+ End;
+ End;
+End;
+
+Procedure AddToGold;
+
+Begin
+ If GetColor(388, 25) = 0 Then
+ Begin
+ Wait(100);
+ KeyDown(32);
+ Wait(10 * KeyDownUpSpeed);
+ KeyUp(32);
+ End;
+End;
+
+begin
+ //ClearDebug;
+ DeclareStuff;
+ Repeat
+ AddToGold;
+ HandleMonsters;
+ Wait(10);
+ Until False;
+end.
diff --git a/branches/script-component/Tests/PS/PathTest.mufa b/branches/script-component/Tests/PS/PathTest.mufa
new file mode 100644
index 0000000..415b1b3
--- /dev/null
+++ b/branches/script-component/Tests/PS/PathTest.mufa
@@ -0,0 +1,5 @@
+program new;
+begin
+ Writeln(AppPath);
+ Writeln(ScriptPath);
+end.
diff --git a/branches/script-component/Tests/PS/Several bitmap operations.mufa b/branches/script-component/Tests/PS/Several bitmap operations.mufa
new file mode 100644
index 0000000..5384114
--- /dev/null
+++ b/branches/script-component/Tests/PS/Several bitmap operations.mufa
@@ -0,0 +1,159 @@
+program new;
+const
+ SaveDir = 'C:\';
+var
+ Bmpz : integer;
+ Bmp2 : integer;
+ w,h : integer;
+begin
+ Bmpz := BitmapFromString(166, 73, 'beNq9Xf2PVeURtv+Jv' +
+ 'zeKSYvZaNlc2/S4N22tmtoYE0NsLdYQQoiClpgNQaSUUpRSpFhC/a' +
+ 'yIX0QCVaOtxn/MYWd39rnPM/Pecz/OJm82994958z7vjPvfM+c1ZW' +
+ 'f/+RHOtZWd9vwD/T7eLT7Fz+9z/7G17g+LrYfbdC99ks3mvil2/jF' +
+ 'nxDP8YfbX/8Q/8WB/wro9KM/wQbOKmau42f33W0Dv6aXLTgcCu6Dz' +
+ '6cbreDqYi3+tRttbm8nk9/YwxVcFG07ogORopitNieQjo/y22/jdH' +
+ 'XF1+W/2GSqDcSlxTPxK2IWf8Tf/bE+W7rXL/NpBDbjXzGlWMsD994' +
+ 'V0/av9//4h36N345LCFKfSjb+1bYlZuJoInTE8mPgj3qmcA8JOym+' +
+ 'cN8aBKm3IyycA36mVeMpUyaAvCJWFxfghPHk4i/+nDjODiKwr8tJ9' +
+ '6RappMBnan2EdYdwPXG79Vp8pl3gKBuch+QVXZbn4OQKozjw5Gpxv' +
+ 'Lj7LR5VEp46XEYC1U7cnFRSNXdJBuvzjiNlAD0PBIx0PRo2ElvnIV' +
+ 'YqX2wK20YkTxw7z1KKr5efxohTlGGHM9/jzl3k1JVT73OdvuYrK7E' +
+ 'mcJjiA8h5l8h/Y47fmCD7rVV2MLxmUFIKrDiAJIUoyuJ//sHh07iA' +
+ 'DnG2mgXbmyAQ25PqCGCj4MWk4wHOnRfrKNbBRnugBODajWpyDOx6J' +
+ 'cFxG5LsvtjHXqba5HqNZWZ00FG3NlwiKdOrR879kKAjusd41MB4ZT' +
+ 'wCJNAJ+lmHwh6XB+U01OhQloidpTO3KEo9IrPK08IZQznidgkVkAs' +
+ 'vRPoJAdRhCknVElHaNVrgrYN4jvvXPzyy+sXLpw+ePCZOOmhHaWaD' +
+ 'G0mcuyYACIa9Rn/VwVdNZlNGhjtIgVMgdq9D3d7/GuwZeWcSOcE3f' +
+ 'l2KgiC49FRIu0F7QvcBNyTCnolvGg/U2VeMY57hRA//+/H3377+Xf' +
+ 'ffXn16uX19cP2+z133tlHB8DT5PMhso+FE1fvAx0nEIBQptB+kgqR' +
+ '2hf+wD7Qg7E7n9c9JLUccYpfSbchXDfWTuoiYbzi2+lAiLduffjVV' +
+ '5/Z+PrrG///381vvrl1/vypI0cOOKn31PqQqvGr/+Kma0y1P/SKtF' +
+ 'SDVbQaN0AaS+m8J3RHcSA9JHhqgqH8IuwTrvuvvc3SKzmOS3aIN25' +
+ 'cNaA2jMy++OITG8ZbbALvvXfppZeec2JDo6yN9MAv2dG+XWt77o4l' +
+ '94eOoGMP8bA7OBSyZDlun7UNrW8m6JW2bBhfXbmLbEy1xJEe4mjPC' +
+ 'h3lAunGwTYrBIXINoifffafTz99+/r1d+2DDZvAzZsf4Bxee/WVo0' +
+ 'cPuTwNPKZKqdJe5WSYA/oYLFbaPdTYyX2UOvfmgI4ycbylaSvoCtG' +
+ 'I8bmhI64R47jViPRwfgZEA2fj2rUrNj766N+ffPyW/+JzsAn4HOxK' +
+ 'IzanNxLHhE3yppJvFsXWfNBRSJHninQGPBQdCL5FoJPrQP0D8TWsM' +
+ 'BJqC6499VeoDwcXHhANhA37YMO4x/vvv2HDtAWfQMzBJuBzOHv2Zb' +
+ 'cXnLfn7q8NXk2uP7xsKdDJzEdHRzdpCZJqscS1q+O0Kyy+IIDl7nx' +
+ 'YNx2gm7huQHS6+tcbr16+fO7Klb/beGXXbhs4B5tAzMFneODwkePH' +
+ '/2TDFQn1/boGizo5mttLhK6OtdQ1gadvudDVxVTpS0Rpi0NPfZUUf' +
+ 'kJc+9NMAzRbz8bFi2cuXTrrQG3YBN588x8xB5tAzMGneubM8RMnjj' +
+ 'qxdVtUTa5vFWRDQEcfMvJS1ZqGgI4SLXWhK09bInSV0Rh+cgKLh9i' +
+ 'NxiJsmD5w7tyfbfgcAjQOm8Pbb71uI8jv2UOHTp58yYa7H9EJluqi' +
+ 'vuQhoFO4p+K0A0FXp184xPAIDAS98rc7xh2oDyMSu8XMARunTx+jO' +
+ 'QQ4Jz8byHxiDnv37bN7bYTHm8LWqNcNCj3s4hTjOwBdRQmy1qF3Hu' +
+ '0RhG7/dRqzsb5+2BQAlwg+BxtKYEiBNgefhs3Br7fZGr0dXl8P/kZ' +
+ 'RLeKog0IPdI8zt97Q0FMHMmpNQ0OnUGwosXaBa4N2r1l2NkzV9znY' +
+ 'SLmKE6FRoBOhT9V+2f/c8w7RgaLqqBGTQPpw0MO9iV591G0GhZ4eM' +
+ 'Tz7Q0Mn5QGJzdUGG4cOPfv88/uPHDnw4osHbcQcfBoI2lmQz82gm7' +
+ 'ponxCiA628THHwh4OuerIGZAeFHhDJVAxKGA56GoQlu8wNPeMYBw7' +
+ '84eDBZ2zEHHwaPocgQvtg1GVkdvCFF43O0t1Gnx5yVEqjWjr0Kl8L' +
+ 'GU4Y5kuHHgycdiDNxxgCuqoQGkG2W9yyMwVg3769z/7xKRv79//e5' +
+ 'uDT8DkEEZqssRmmEOPJqCbpVzTTlgg9dR1TbGLbEbfhDlru2impEv' +
+ 'eZYuVB7cuCjjZ4h9HJjQQYNR/sXnfimaTYu/fx3z31xNNPP2lz8Gn' +
+ 'YHGwYUNMQTG0w9fLoiRPpelU51yNGF7ijb0HolE6gpzvNiY2DtiD0' +
+ 'cebKU1YTkfrlQsdMNs18IKU9uI09wcTD9evvmhbx+OOPPPHEb5588' +
+ 'rc2fA5GXSY7TDm8Haw5efKVV19TLqrqGaGbfFCktM8NHcP65N9Io5' +
+ 'ORTbcU6EjGGmkNvdH4iY34TI7lRdautJ3mMqW/2KNu3LhqWoSxjkc' +
+ 'f/aWNxx77tQkRM/HMCjCV0iZm5gESWJpVRYnllM6kccnY9lmh0wKR' +
+ 'e7cx7nyP/H6zQg8nj1r6uNjKXojb/bjNCl19p2H9UYSUQqXE2I2Eb' +
+ 't78wCSF8RPTEIzPGOHdzrU4derU+fMqNOkJGqTT0LPvCbm/5oBOt6' +
+ 'fqGQ7PqKfUGqS3WdeeUhpJzMCIJ0VgGgYZibNCxwRmzLdHesPT3Y3' +
+ 'y42CPvXXrQ9MizMS7fPnctWtXjv3ldAqRTlA7kYZQkIp1l2h9oKf+' +
+ '0tSxpnRVJaL0XztVu9A+B1ePCpRANGluIWEjkNR/5wODaTIPBoUpT' +
+ 'o3UGKs++89LpkWYvXD8r2dOX7igKoqWC6FnqZH3opusGJ8KPTXt0z' +
+ 'QDPEQVaMqPbUNHnoZZTMRh0LUb2lrci7FyrKroAx1v75q55WmeiZY' +
+ 'PhEx5+W9nz7x+MT1Zmp+GG6tFTMptiGBClQqSa0BXNSke8nC355Hx' +
+ 'A9XpJlyTQ2brXKy0oWMOW0U8eITTah3aQPJ4p9ArS7MT0Um+DlKck' +
+ 'C9R5Ut/Hk6qoLpZCAQhOjbK8EXhS1JH48mE1niUPeHhtdU+GCdNng' +
+ '6s4lp1YBLcPqWGVYgVeXg61I6reBqKg6hfIH2JHqhphEo2iEdcL6p' +
+ 'eeCOlYaep11WBoWoUOBz6r9buj+sp+1cTpRqCW8tbSOugu9CZQzdq' +
+ '9qljHOkQVaOHuhH63PrkkNO5rlCGWLv9qNWVdm1gNxnTSRWwqlI1K' +
+ 'q282MqzNBu1qFpnpL+0NS63ZO1z0EBsYJUH3lbVdA406KTEKm4jcW' +
+ '20uaWjXepONNTjoaZAkobsqzyooPPIvyVDTG1D4iHtKtFxpto1hqM' +
+ 'bzUycQ2od49ywiLKBcdITHN1YVY1ZgvHfNvHgw1NrWmM9qTmApwYL' +
+ 'WyiP0Y4eMoo0ESjVMVTPp0ic0uTm07bql1OMt4vO+pfDp7o3kXHVD' +
+ 'aCqQ0n9dQ2FXOuVGuhO3QI53je4JZWfO7r9A1Wya8uFVMdrgE6rBq' +
+ 'I4tJLIOmftMDB3uwNlMunGqozQPdGVpkzYU3zxOIeShviNY94Q7lM' +
+ 'NdtQP0RAj9QmtUdTE1LOtx7mVi7W6knLaiVOwFRmZOrRItiofSOtq' +
+ 'kyK+1U1fZapBYeFzGpuumHn8yzGo/MGGYTxkejcZEdMz1ZPP096Se' +
+ 'kxSspJBMWfc5MYR3jQ0HhxRHLkS1rMOtc6matpUBalOvAYGlQ9oYm' +
+ '3IvoYGFdjvpFTcy4V6FnrQZcT8FeOoFronraF7pPUI0R0l9Hb1tKe' +
+ 'hTNRSGiyLOnVUZYxVMxPtylI1WplaOYX71okKRLen8i69nm40Mpjp' +
+ 'CCjG00YEVKRDJwLVM53zVA+/lu5WTYd6HvCUTpTOUWmsdIxGgLub5' +
+ 'GzjQvHGE03KEpFTpYegOUZtARr0pn1j4smuAFSIJiJUryntiSJdu1' +
+ 'XgcGrRKmMvPDc7VyvNMRJEa0T5i9XxarWRzw0/NwRBVQZL6lk36cf' +
+ 'WoAmFzmPa1amJM9XgLUo/xk4rvR1X1HDRR3yqUrQqNSy2VC82evPl' +
+ 'uPbVqGKgxzYal5E3jEhOufpUjHegf3Yjflr0gdHyzCotQbNQsDdUm' +
+ '4kRb4k+MKm20MiTJ7OlYdapCa/QdaXsZlzdluboT1aFJwwx9Rt4oz' +
+ 'Cs7PBSiLQ/W7rnVVw17bcThqdW8UcvFFTkqFdDugT1SaKWgh4VNdL' +
+ 'TXihpjpOmU2p8x2HhrMw6I9Tg8xU6hVdiK1wJ3+o3ck/KdV2jS/MD' +
+ 'cVZBNgSd1OzKWK5ccIjTShtvdCNpkFyFi4pRV2GRNvSGF6tyOaItH' +
+ 'Dc+tDYibzkWJCr0EKM0W7Tr0T9J14R1lnKkuL7RAwePUlAIAaq6Em' +
+ 'lmi3ZYqrqRbJ7u0a7UzQJF09tGdFpHTy5TLGlvQE+tsKl9tCq3Hkb' +
+ 'E+nRioVCgE4w/BHlXJWsq1bFnFxoNEum5a3QiDWRhUnffPjBbaXtu' +
+ 'iqLTG/NhUmHhe6Ue8p7QSY9Now8N46JSXHtCD19QPCeQbvwKsZ/6u' +
+ 'NSon2nnNa6hXru00SJtTqTX9u9GMs76laW9lVI/z6YqO5mMNFMXGt' +
+ 'KiQ13pad7S9GZdOybKBsZxYAkYCtNKhM269j7xODrXaWV3/24k5Fq' +
+ 'MNstkTWv6dOio2jOhP3SyONIOimgXd/UBn68LDfIQ5O2EdMqWIeXB' +
+ 'xnwdeHRv04586KsJ4lykGwlG4dXQrhLmqbB6kU4sbZeUhryrrjtz9' +
+ '8BRzWSbw4MJoLNacOfbqgsVyChtL9iJBZuIVm4QZTtLgZ6mHERqAd' +
+ 'YXo58Hd3vBTixVP4qGKr6stVNCGmGcxOgSu5F0PXzmWhSzxC405NX' +
+ 'R7isVD18cugaMXGZNuEwhQW650DVomyaWD9GNZDt8LIYhGWsDQU/D' +
+ 'lBjhJTpfLvR2ly2sNByiC00aQQsaGK4bSdWAhbwKA3ViodBP6O3Yh' +
+ 'XXQLjSaP4wN9ofrA9NO8hy6G0kjpBvoHgg6RTAxjukm/86vHcXZzq' +
+ 'xdc/Z2oA8MURpVTw8KHeNumsOzA2tHc4wy7Xdy51VpGboPTDBS8rA' +
+ 'NDT38OZpNFCQ36No1IuM/uum9YzuPPgcDPVw3EordY5tcrHQbFDrl' +
+ 'wpEjaAegN/Jmh4PuvIX81T6H8PAsvRuJpuph50AKvC4XejtHCDmMH' +
+ 'cAdgJ6i25n8ENAb9XeI8WV1IyF/KeUeaHGrq6xL7MQSaa601eFZ1Y' +
+ 'O23D4wtOGVzbL0ne+Z7BeqxVK6kWhRDKGbCiswGriULjSNw4Up7lo' +
+ '5viB0xDJ+Jsc+7bkT4RLX3o1miBMt2I2ky7I605qItBB1QeiNMiKK' +
+ 'yqVVUYtAx0hoO72qiowv3oWm6rmU1sLQwhfvA6MZsFVlBCV0zd0Lh' +
+ 'bIKVYVo1J7E8Z+vC02Fa1xa9YKYyHdyTWa+HjhVonvF7jRiNV8nlr' +
+ 'RYhmIZ8T7T9P0vc3RiqXKoFG5Dc0N6mxV6zx4FE+9mgoowN5QC4zN' +
+ 'BD7iaAtEI2aTJCTP1QtHsxKpUaqIbxlbxo6ag9O+FUlUjpmmQyNJV' +
+ 'l4vY9ExdaG43KNgY6bkeQ1JEo04ZWUR/6A0JUq0O31yjpN7uRlLle' +
+ 'NP7NOnh6TvsNP11KvR2Sc7UKjNtKzHr2isjSys+MAhLMfGwi2+nr2' +
+ '/pk1Ohk/tOMz/7hGW12r3RiSUqpjVhjN615P/VupUgRX29whhex1l' +
+ 'B71n/m7YG1d4jlftxahcafCYx9mpXKfulwlobOuXL+WfNuW0jXfM0' +
+ 'MPtd22/qi+bbZeZpvZKmK5BKk0qQIBgV2VXWgdKb/kvvTbmobqkTv' +
+ '/6L3ihtw9SzFOOb7tYt5Q2Dp7rzrubFc+yzj3imf527htpMSNWOcL' +
+ 'ejGx51C0lFuRbU42O1pCs6sYQzp9FGoErtbltqVfEIdqEhaev8AbO' +
+ 'R22+lRJUS0U32hStvSAPbmuGDo+rwOnIDxRW625Xm2lWyLSMmurRJ' +
+ 'U4LIc4voSVrUGRjfPBRb1VjY7gwba2hrDnrlaFqzlpYcTrTNaa4un' +
+ 'rOdgbznbsxWavQ/ieNJF2DxC0pn/7xJYw+OpoqhqTWnU7Pi1UEUOl' +
+ 'gIHX+Nr7duoP7h1DRsgsNPqrLaZU5zk+IlZZqSN5YCh9QUjWhpN6l' +
+ 'm9FFyQuWIWhU84FUOdspksM4okml9bq4J+EmnE61lUI0J69vEdNUq' +
+ 'Q4lZpZG+tLhS++s2ClLUXE21Aqzg7ia7J6X1renO0Bmvuv8lGs5W3' +
+ 'xXcE6wyaNQKRduHgE6sW/fWSSLdbfWcTFXPsNJ5LO9wTAveUxcxvf' +
+ 'WV6psUv423Syd8dbLrO/HqwPu2RiQSilKMegawti01UJtJ3w4iIe2' +
+ 'ry1KUA7kh/QmPgetGv8Ew37Q1Qa9uRUUfsEZibUP/SZ1saRd9dbv1' +
+ 'gZVSTtuVpMt0PkzqE5VETZWA9ORAYtxORWo4HJuqd6EyhpGdBsanM' +
+ 'pM+fH7qXVRxSZ6WbsS9QJMebtBVLH1PqzZk07pdJOxutBsNn0huof' +
+ '6H6avb2+2V0KYgqUdS1VFABNOoOkm3FI98BHDT0ADJgrLZi5G3j3a' +
+ 'Po+8BCV1cWQ==');
+ SaveBitmap(bmpz,SaveDir + 'original.bmp');
+ GetBitmapSize(bmpz,w,h);
+ SetBitmapName(bmpz,'Invetory Bitmap');
+ Writeln('Bitmap size: ('+inttostr(w) + ',' + inttostr(h) + ')');
+ Bmp2 := CopyBitmap(bmpz);
+ SetBitmapSize(Bmp2,w div 2, h div 2);
+ SaveBitmap(bmp2,SaveDir + 'cut.bmp');
+ StretchBitmapResize(Bmpz,w*2,h*2);
+ SaveBitmap(bmpz,savedir + 'stretched.bmp');
+ FreeBitmap(bmp2);
+ Bmp2 := CopyBitmap(bmpz);
+ StretchBitmapResize(bmp2,w div 2, h div 2);
+ SaveBitmap(bmp2,savedir + 'stretchedSmall.bmp');
+ SaveBitmap(ContrastBitmap(bmpz,50),savedir + 'Contrast.bmp');
+ SaveBitmap(BrightnessBitmap(bmpz,150),savedir + 'Brightness.bmp');
+ SaveBitmap(GreyScaleBitmap(bmpz),savedir + 'GreyScale.bmp');
+ InvertBitmap(bmpz);
+ SaveBitmap(bmpz,savedir + 'inverted.bmp');
+ Invertbitmap(bmpz);//Invert back
+ SaveBitmap(DesaturateBitmap(Bmpz),savedir + 'desaturate.bmp');
+ SaveBitmap(RotateBitmap(Bmpz,0.30*pi),savedir + 'rotated.bmp');
+ SaveBitmap(PosterizeBitmap(Bmpz,75),savedir + 'posterized.bmp');
+end.
diff --git a/branches/script-component/Tests/PS/SimpleBMPLoader.txt b/branches/script-component/Tests/PS/SimpleBMPLoader.txt
new file mode 100644
index 0000000..2867c6b
--- /dev/null
+++ b/branches/script-component/Tests/PS/SimpleBMPLoader.txt
@@ -0,0 +1,142 @@
+program new;
+var
+ Bmpz : integer;
+ w,h : integer;
+begin
+ Bmpz := BitmapFromString(166, 73, 'beNq9Xf2PVeURtv+Jv' +
+ 'zeKSYvZaNlc2/S4N22tmtoYE0NsLdYQQoiClpgNQaSUUpRSpFhC/a' +
+ 'yIX0QCVaOtxn/MYWd39rnPM/Pecz/OJm82994958z7vjPvfM+c1ZW' +
+ 'f/+RHOtZWd9vwD/T7eLT7Fz+9z/7G17g+LrYfbdC99ks3mvil2/jF' +
+ 'nxDP8YfbX/8Q/8WB/wro9KM/wQbOKmau42f33W0Dv6aXLTgcCu6Dz' +
+ '6cbreDqYi3+tRttbm8nk9/YwxVcFG07ogORopitNieQjo/y22/jdH' +
+ 'XF1+W/2GSqDcSlxTPxK2IWf8Tf/bE+W7rXL/NpBDbjXzGlWMsD994' +
+ 'V0/av9//4h36N345LCFKfSjb+1bYlZuJoInTE8mPgj3qmcA8JOym+' +
+ 'cN8aBKm3IyycA36mVeMpUyaAvCJWFxfghPHk4i/+nDjODiKwr8tJ9' +
+ '6RappMBnan2EdYdwPXG79Vp8pl3gKBuch+QVXZbn4OQKozjw5Gpxv' +
+ 'Lj7LR5VEp46XEYC1U7cnFRSNXdJBuvzjiNlAD0PBIx0PRo2ElvnIV' +
+ 'YqX2wK20YkTxw7z1KKr5efxohTlGGHM9/jzl3k1JVT73OdvuYrK7E' +
+ 'mcJjiA8h5l8h/Y47fmCD7rVV2MLxmUFIKrDiAJIUoyuJ//sHh07iA' +
+ 'DnG2mgXbmyAQ25PqCGCj4MWk4wHOnRfrKNbBRnugBODajWpyDOx6J' +
+ 'cFxG5LsvtjHXqba5HqNZWZ00FG3NlwiKdOrR879kKAjusd41MB4ZT' +
+ 'wCJNAJ+lmHwh6XB+U01OhQloidpTO3KEo9IrPK08IZQznidgkVkAs' +
+ 'vRPoJAdRhCknVElHaNVrgrYN4jvvXPzyy+sXLpw+ePCZOOmhHaWaD' +
+ 'G0mcuyYACIa9Rn/VwVdNZlNGhjtIgVMgdq9D3d7/GuwZeWcSOcE3f' +
+ 'l2KgiC49FRIu0F7QvcBNyTCnolvGg/U2VeMY57hRA//+/H3377+Xf' +
+ 'ffXn16uX19cP2+z133tlHB8DT5PMhso+FE1fvAx0nEIBQptB+kgqR' +
+ '2hf+wD7Qg7E7n9c9JLUccYpfSbchXDfWTuoiYbzi2+lAiLduffjVV' +
+ '5/Z+PrrG///381vvrl1/vypI0cOOKn31PqQqvGr/+Kma0y1P/SKtF' +
+ 'SDVbQaN0AaS+m8J3RHcSA9JHhqgqH8IuwTrvuvvc3SKzmOS3aIN25' +
+ 'cNaA2jMy++OITG8ZbbALvvXfppZeec2JDo6yN9MAv2dG+XWt77o4l' +
+ '94eOoGMP8bA7OBSyZDlun7UNrW8m6JW2bBhfXbmLbEy1xJEe4mjPC' +
+ 'h3lAunGwTYrBIXINoifffafTz99+/r1d+2DDZvAzZsf4Bxee/WVo0' +
+ 'cPuTwNPKZKqdJe5WSYA/oYLFbaPdTYyX2UOvfmgI4ycbylaSvoCtG' +
+ 'I8bmhI64R47jViPRwfgZEA2fj2rUrNj766N+ffPyW/+JzsAn4HOxK' +
+ 'IzanNxLHhE3yppJvFsXWfNBRSJHninQGPBQdCL5FoJPrQP0D8TWsM' +
+ 'BJqC6499VeoDwcXHhANhA37YMO4x/vvv2HDtAWfQMzBJuBzOHv2Zb' +
+ 'cXnLfn7q8NXk2uP7xsKdDJzEdHRzdpCZJqscS1q+O0Kyy+IIDl7nx' +
+ 'YNx2gm7huQHS6+tcbr16+fO7Klb/beGXXbhs4B5tAzMFneODwkePH' +
+ '/2TDFQn1/boGizo5mttLhK6OtdQ1gadvudDVxVTpS0Rpi0NPfZUUf' +
+ 'kJc+9NMAzRbz8bFi2cuXTrrQG3YBN588x8xB5tAzMGneubM8RMnjj' +
+ 'qxdVtUTa5vFWRDQEcfMvJS1ZqGgI4SLXWhK09bInSV0Rh+cgKLh9i' +
+ 'NxiJsmD5w7tyfbfgcAjQOm8Pbb71uI8jv2UOHTp58yYa7H9EJluqi' +
+ 'vuQhoFO4p+K0A0FXp184xPAIDAS98rc7xh2oDyMSu8XMARunTx+jO' +
+ 'QQ4Jz8byHxiDnv37bN7bYTHm8LWqNcNCj3s4hTjOwBdRQmy1qF3Hu' +
+ '0RhG7/dRqzsb5+2BQAlwg+BxtKYEiBNgefhs3Br7fZGr0dXl8P/kZ' +
+ 'RLeKog0IPdI8zt97Q0FMHMmpNQ0OnUGwosXaBa4N2r1l2NkzV9znY' +
+ 'SLmKE6FRoBOhT9V+2f/c8w7RgaLqqBGTQPpw0MO9iV591G0GhZ4eM' +
+ 'Tz7Q0Mn5QGJzdUGG4cOPfv88/uPHDnw4osHbcQcfBoI2lmQz82gm7' +
+ 'ponxCiA628THHwh4OuerIGZAeFHhDJVAxKGA56GoQlu8wNPeMYBw7' +
+ '84eDBZ2zEHHwaPocgQvtg1GVkdvCFF43O0t1Gnx5yVEqjWjr0Kl8L' +
+ 'GU4Y5kuHHgycdiDNxxgCuqoQGkG2W9yyMwVg3769z/7xKRv79//e5' +
+ 'uDT8DkEEZqssRmmEOPJqCbpVzTTlgg9dR1TbGLbEbfhDlru2impEv' +
+ 'eZYuVB7cuCjjZ4h9HJjQQYNR/sXnfimaTYu/fx3z31xNNPP2lz8Gn' +
+ 'YHGwYUNMQTG0w9fLoiRPpelU51yNGF7ijb0HolE6gpzvNiY2DtiD0' +
+ 'cebKU1YTkfrlQsdMNs18IKU9uI09wcTD9evvmhbx+OOPPPHEb5588' +
+ 'rc2fA5GXSY7TDm8Haw5efKVV19TLqrqGaGbfFCktM8NHcP65N9Io5' +
+ 'ORTbcU6EjGGmkNvdH4iY34TI7lRdautJ3mMqW/2KNu3LhqWoSxjkc' +
+ 'f/aWNxx77tQkRM/HMCjCV0iZm5gESWJpVRYnllM6kccnY9lmh0wKR' +
+ 'e7cx7nyP/H6zQg8nj1r6uNjKXojb/bjNCl19p2H9UYSUQqXE2I2Eb' +
+ 't78wCSF8RPTEIzPGOHdzrU4derU+fMqNOkJGqTT0LPvCbm/5oBOt6' +
+ 'fqGQ7PqKfUGqS3WdeeUhpJzMCIJ0VgGgYZibNCxwRmzLdHesPT3Y3' +
+ 'y42CPvXXrQ9MizMS7fPnctWtXjv3ldAqRTlA7kYZQkIp1l2h9oKf+' +
+ '0tSxpnRVJaL0XztVu9A+B1ePCpRANGluIWEjkNR/5wODaTIPBoUpT' +
+ 'o3UGKs++89LpkWYvXD8r2dOX7igKoqWC6FnqZH3opusGJ8KPTXt0z' +
+ 'QDPEQVaMqPbUNHnoZZTMRh0LUb2lrci7FyrKroAx1v75q55WmeiZY' +
+ 'PhEx5+W9nz7x+MT1Zmp+GG6tFTMptiGBClQqSa0BXNSke8nC355Hx' +
+ 'A9XpJlyTQ2brXKy0oWMOW0U8eITTah3aQPJ4p9ArS7MT0Um+DlKck' +
+ 'C9R5Ut/Hk6qoLpZCAQhOjbK8EXhS1JH48mE1niUPeHhtdU+GCdNng' +
+ '6s4lp1YBLcPqWGVYgVeXg61I6reBqKg6hfIH2JHqhphEo2iEdcL6p' +
+ 'eeCOlYaep11WBoWoUOBz6r9buj+sp+1cTpRqCW8tbSOugu9CZQzdq' +
+ '9qljHOkQVaOHuhH63PrkkNO5rlCGWLv9qNWVdm1gNxnTSRWwqlI1K' +
+ 'q282MqzNBu1qFpnpL+0NS63ZO1z0EBsYJUH3lbVdA406KTEKm4jcW' +
+ '20uaWjXepONNTjoaZAkobsqzyooPPIvyVDTG1D4iHtKtFxpto1hqM' +
+ 'bzUycQ2od49ywiLKBcdITHN1YVY1ZgvHfNvHgw1NrWmM9qTmApwYL' +
+ 'WyiP0Y4eMoo0ESjVMVTPp0ic0uTm07bql1OMt4vO+pfDp7o3kXHVD' +
+ 'aCqQ0n9dQ2FXOuVGuhO3QI53je4JZWfO7r9A1Wya8uFVMdrgE6rBq' +
+ 'I4tJLIOmftMDB3uwNlMunGqozQPdGVpkzYU3zxOIeShviNY94Q7lM' +
+ 'NdtQP0RAj9QmtUdTE1LOtx7mVi7W6knLaiVOwFRmZOrRItiofSOtq' +
+ 'kyK+1U1fZapBYeFzGpuumHn8yzGo/MGGYTxkejcZEdMz1ZPP096Se' +
+ 'kxSspJBMWfc5MYR3jQ0HhxRHLkS1rMOtc6matpUBalOvAYGlQ9oYm' +
+ '3IvoYGFdjvpFTcy4V6FnrQZcT8FeOoFronraF7pPUI0R0l9Hb1tKe' +
+ 'hTNRSGiyLOnVUZYxVMxPtylI1WplaOYX71okKRLen8i69nm40Mpjp' +
+ 'CCjG00YEVKRDJwLVM53zVA+/lu5WTYd6HvCUTpTOUWmsdIxGgLub5' +
+ 'GzjQvHGE03KEpFTpYegOUZtARr0pn1j4smuAFSIJiJUryntiSJdu1' +
+ 'XgcGrRKmMvPDc7VyvNMRJEa0T5i9XxarWRzw0/NwRBVQZL6lk36cf' +
+ 'WoAmFzmPa1amJM9XgLUo/xk4rvR1X1HDRR3yqUrQqNSy2VC82evPl' +
+ 'uPbVqGKgxzYal5E3jEhOufpUjHegf3Yjflr0gdHyzCotQbNQsDdUm' +
+ '4kRb4k+MKm20MiTJ7OlYdapCa/QdaXsZlzdluboT1aFJwwx9Rt4oz' +
+ 'Cs7PBSiLQ/W7rnVVw17bcThqdW8UcvFFTkqFdDugT1SaKWgh4VNdL' +
+ 'TXihpjpOmU2p8x2HhrMw6I9Tg8xU6hVdiK1wJ3+o3ck/KdV2jS/MD' +
+ 'cVZBNgSd1OzKWK5ccIjTShtvdCNpkFyFi4pRV2GRNvSGF6tyOaItH' +
+ 'Dc+tDYibzkWJCr0EKM0W7Tr0T9J14R1lnKkuL7RAwePUlAIAaq6Em' +
+ 'lmi3ZYqrqRbJ7u0a7UzQJF09tGdFpHTy5TLGlvQE+tsKl9tCq3Hkb' +
+ 'E+nRioVCgE4w/BHlXJWsq1bFnFxoNEum5a3QiDWRhUnffPjBbaXtu' +
+ 'iqLTG/NhUmHhe6Ue8p7QSY9Now8N46JSXHtCD19QPCeQbvwKsZ/6u' +
+ 'NSon2nnNa6hXru00SJtTqTX9u9GMs76laW9lVI/z6YqO5mMNFMXGt' +
+ 'KiQ13pad7S9GZdOybKBsZxYAkYCtNKhM269j7xODrXaWV3/24k5Fq' +
+ 'MNstkTWv6dOio2jOhP3SyONIOimgXd/UBn68LDfIQ5O2EdMqWIeXB' +
+ 'xnwdeHRv04586KsJ4lykGwlG4dXQrhLmqbB6kU4sbZeUhryrrjtz9' +
+ '8BRzWSbw4MJoLNacOfbqgsVyChtL9iJBZuIVm4QZTtLgZ6mHERqAd' +
+ 'YXo58Hd3vBTixVP4qGKr6stVNCGmGcxOgSu5F0PXzmWhSzxC405NX' +
+ 'R7isVD18cugaMXGZNuEwhQW650DVomyaWD9GNZDt8LIYhGWsDQU/D' +
+ 'lBjhJTpfLvR2ly2sNByiC00aQQsaGK4bSdWAhbwKA3ViodBP6O3Yh' +
+ 'XXQLjSaP4wN9ofrA9NO8hy6G0kjpBvoHgg6RTAxjukm/86vHcXZzq' +
+ 'xdc/Z2oA8MURpVTw8KHeNumsOzA2tHc4wy7Xdy51VpGboPTDBS8rA' +
+ 'NDT38OZpNFCQ36No1IuM/uum9YzuPPgcDPVw3EordY5tcrHQbFDrl' +
+ 'wpEjaAegN/Jmh4PuvIX81T6H8PAsvRuJpuph50AKvC4XejtHCDmMH' +
+ 'cAdgJ6i25n8ENAb9XeI8WV1IyF/KeUeaHGrq6xL7MQSaa601eFZ1Y' +
+ 'O23D4wtOGVzbL0ne+Z7BeqxVK6kWhRDKGbCiswGriULjSNw4Up7lo' +
+ '5viB0xDJ+Jsc+7bkT4RLX3o1miBMt2I2ky7I605qItBB1QeiNMiKK' +
+ 'yqVVUYtAx0hoO72qiowv3oWm6rmU1sLQwhfvA6MZsFVlBCV0zd0Lh' +
+ 'bIKVYVo1J7E8Z+vC02Fa1xa9YKYyHdyTWa+HjhVonvF7jRiNV8nlr' +
+ 'RYhmIZ8T7T9P0vc3RiqXKoFG5Dc0N6mxV6zx4FE+9mgoowN5QC4zN' +
+ 'BD7iaAtEI2aTJCTP1QtHsxKpUaqIbxlbxo6ag9O+FUlUjpmmQyNJV' +
+ 'l4vY9ExdaG43KNgY6bkeQ1JEo04ZWUR/6A0JUq0O31yjpN7uRlLle' +
+ 'NP7NOnh6TvsNP11KvR2Sc7UKjNtKzHr2isjSys+MAhLMfGwi2+nr2' +
+ '/pk1Ohk/tOMz/7hGW12r3RiSUqpjVhjN615P/VupUgRX29whhex1l' +
+ 'B71n/m7YG1d4jlftxahcafCYx9mpXKfulwlobOuXL+WfNuW0jXfM0' +
+ 'MPtd22/qi+bbZeZpvZKmK5BKk0qQIBgV2VXWgdKb/kvvTbmobqkTv' +
+ '/6L3ihtw9SzFOOb7tYt5Q2Dp7rzrubFc+yzj3imf527htpMSNWOcL' +
+ 'ejGx51C0lFuRbU42O1pCs6sYQzp9FGoErtbltqVfEIdqEhaev8AbO' +
+ 'R22+lRJUS0U32hStvSAPbmuGDo+rwOnIDxRW625Xm2lWyLSMmurRJ' +
+ 'U4LIc4voSVrUGRjfPBRb1VjY7gwba2hrDnrlaFqzlpYcTrTNaa4un' +
+ 'rOdgbznbsxWavQ/ieNJF2DxC0pn/7xJYw+OpoqhqTWnU7Pi1UEUOl' +
+ 'gIHX+Nr7duoP7h1DRsgsNPqrLaZU5zk+IlZZqSN5YCh9QUjWhpN6l' +
+ 'm9FFyQuWIWhU84FUOdspksM4okml9bq4J+EmnE61lUI0J69vEdNUq' +
+ 'Q4lZpZG+tLhS++s2ClLUXE21Aqzg7ia7J6X1renO0Bmvuv8lGs5W3' +
+ 'xXcE6wyaNQKRduHgE6sW/fWSSLdbfWcTFXPsNJ5LO9wTAveUxcxvf' +
+ 'WV6psUv423Syd8dbLrO/HqwPu2RiQSilKMegawti01UJtJ3w4iIe2' +
+ 'ry1KUA7kh/QmPgetGv8Ew37Q1Qa9uRUUfsEZibUP/SZ1saRd9dbv1' +
+ 'gZVSTtuVpMt0PkzqE5VETZWA9ORAYtxORWo4HJuqd6EyhpGdBsanM' +
+ 'pM+fH7qXVRxSZ6WbsS9QJMebtBVLH1PqzZk07pdJOxutBsNn0huof' +
+ '6H6avb2+2V0KYgqUdS1VFABNOoOkm3FI98BHDT0ADJgrLZi5G3j3a' +
+ 'Po+8BCV1cWQ==');
+ GetBitmapSize(bmpz,w,h);
+ Writeln(inttostr(w) + '-' + inttostr(h));
+ SetBitmapSize(Bmpz,w div 2, h div 2);
+ SaveBitmap(Bmpz,'/tmp/test.bmp');
+ //FreeBitmap(Bmpz);
+ Bmpz := LoadBitmap('/tmp/test.bmp');
+ SetBitmapSize(bmpz,w,h);
+ SaveBitmap(Bmpz,'/tmp/test2.bmp');
+end.
diff --git a/branches/script-component/Tests/PS/Uptext.mufa b/branches/script-component/Tests/PS/Uptext.mufa
new file mode 100644
index 0000000..e612331
--- /dev/null
+++ b/branches/script-component/Tests/PS/Uptext.mufa
@@ -0,0 +1,10 @@
+program new;
+var
+ i,t:integer;
+begin
+ t:=getsystemtime;
+ for i := 0 to 100 do
+ rs_getuptext;
+ writeln(inttostr(round(getsystemtime - t) / 100));
+ writeln(rs_getuptext);
+end.
diff --git a/branches/script-component/Tests/PS/colour conversions.mufa b/branches/script-component/Tests/PS/colour conversions.mufa
new file mode 100644
index 0000000..3b23a11
--- /dev/null
+++ b/branches/script-component/Tests/PS/colour conversions.mufa
@@ -0,0 +1,9 @@
+program new;
+var
+ R,G,B : byte;
+begin
+ ColorToRGB(clwhite,r,g,b);
+ Writeln([r,g,b]);
+ Writeln(RGBToColor(50,150,250));//16422450
+ writeln(XYZToColor(0.5,0.7,0.9));//1513219
+end.
diff --git a/branches/script-component/Tests/PS/colourtest.txt b/branches/script-component/Tests/PS/colourtest.txt
new file mode 100644
index 0000000..4ab67e0
--- /dev/null
+++ b/branches/script-component/Tests/PS/colourtest.txt
@@ -0,0 +1,43 @@
+program new;
+var
+ x,y,w,h,i,j,t,t2:integer;
+begin
+ getclientdimensions(w,h);
+ writeln(inttostr(w) + ', ' + inttostr(h));
+
+ freeze();
+ for i := 0 to 2 do
+ begin
+ setcolortolerancespeed(i);
+ t := getsystemtime;
+ for j := 0 to 100 do
+ findcolortolerance(x, y, 2532562, 0, 0, w -1 , h -1, 1);
+ t2 := getsystemtime;
+ writeln('Time for 101 tries: ' + inttostr(t2 - t) + ' ms.');
+ writeln('That is ' + FloatToStr((t2 - t) / 101) + ' ms each.');
+
+ if findcolortolerance(x, y, 2532562, 0, 0, w-1, h-1, 1) then
+ begin
+ writeln('CTS: ' + inttostr(I) + '; Found the colour at (' + inttostr(x) + ', ' +
+ inttostr(y) + ')');
+ movemouse(x, y);
+ wait(1000);
+ end else
+ writeln('not found');
+ end;
+ unfreeze();
+end.
+
+Compiled succesfully in 7 ms.
+826, 597
+Time for 101 tries: 1143 ms.
+That is 11.316831683168 ms each.
+not found
+Time for 101 tries: 2565 ms.
+That is 25.396039603960 ms each.
+not found
+Time for 101 tries: 3799 ms.
+That is 37.613861386139 ms each.
+not found
+Succesfully executed
+
diff --git a/branches/script-component/Tests/PS/debugimageform.mufa b/branches/script-component/Tests/PS/debugimageform.mufa
new file mode 100644
index 0000000..470f807
--- /dev/null
+++ b/branches/script-component/Tests/PS/debugimageform.mufa
@@ -0,0 +1,21 @@
+program new;
+var
+ Bmp,x,y : integer;
+ DebugBmp : integer;
+begin
+ Bmp := createbItmap(100,100);
+ CopyClientToBitmap(Bmp,0,0,99,99);
+ for x := 0 to 49 do
+ begin;
+ for y := 0 to 49 do
+ begin;
+ fastsetpixel(bmp,x,y,random(clwhite));
+ fastsetpixel(bmp,y,x,random(clwhite));
+ end;
+ x := x + 5;
+ end;
+ DisplayDebugImgWindow(100,100);
+ DrawBitmapDebugImg(bmp);
+ DebugBMP := GetDebugBitmap;
+ SaveBitmap(DebugBmp,ScriptPath + 'debugimage.bmp');
+end.
diff --git a/branches/script-component/Tests/PS/dtmtest.mufa b/branches/script-component/Tests/PS/dtmtest.mufa
new file mode 100644
index 0000000..ccc764d
--- /dev/null
+++ b/branches/script-component/Tests/PS/dtmtest.mufa
@@ -0,0 +1,24 @@
+program new;
+var
+ dtm,x,y, w, h:integer;
+ ppdtm:pdtm;
+begin
+ getclientdimensions(w,h);
+ writeln(inttostr(w) + ',' + inttostr(h));
+ dtm := DTMFromString('78DA63F4606460F0634001E181810C46401A2' +
+ '8C3F01F0818AD31D54064612490B601B28209A87105B2A209A8F1' +
+ '23424D38901540841A2FFC6A00C8100982');
+
+ if finddtm(dtm, x,y, 0, 0, w-1,h-1) then
+ begin
+ writeln('found');
+ movemouse(x,y);
+ end else
+ writeln('not found');
+ if getdtm(dtm, ppdtm) then
+ writeln('yay');
+ printpdtm(tdtmtopdtm(pdtmtotdtm(ppdtm)));
+ dtm := addpdtm(ppdtm);
+ freedtm(dtm);
+ // old dtm is not freed, since it is overridden by addpdtm.
+end.
diff --git a/branches/script-component/Tests/PS/dtmtest2.mufa b/branches/script-component/Tests/PS/dtmtest2.mufa
new file mode 100644
index 0000000..48fbddb
--- /dev/null
+++ b/branches/script-component/Tests/PS/dtmtest2.mufa
@@ -0,0 +1,61 @@
+program new;
+
+const
+ dtm_Rectangle = 0;
+ dtm_Cross = 1;
+ dtm_DiagonalCross = 2;
+ dtm_Circle = 3;
+ dtm_Triangle = 4;
+
+var
+ ppdtm: pdtm;
+ w,h,x,y,dtm,i: integer;
+
+ a: extended;
+
+ p,pp: TPointArray;
+ c,t,asz,ash: TIntegerArray;
+ bp:array of boolean;
+
+begin
+ p := [Point(0,0), Point(1,1), Point(-4, -4)];
+ c := [clWhite, clWhite, clWhite];
+ t := [0, 0, 0];
+ asz := [0, 4, 4];
+ ash := [dtm_Rectangle, dtm_Rectangle, dtm_Rectangle];
+ setlength(ppdtm.p,2);
+ bp:=[false,false,false];
+
+ ppdtm.l := 3;//We have 3 points..
+ ppdtm.p := p;
+ ppdtm.c := c;
+ ppdtm.t := t;
+ ppdtm.asz := asz;
+ ppdtm.ash := ash;
+ ppdtm.bp := bp;
+ ppdtm.n := 'TestDTM';//Our name!
+
+ dtm := AddpDTM(ppdtm);
+
+ getclientdimensions(w,h);
+ writeln(inttostr(w) + ', ' + inttostr(h));
+
+ if FindDTM(dtm, x, y, 0, 0, w-1, h-1) then
+ begin
+ writeln('Found DTM at ' + inttostr(x) + ', ' + inttostr(y));
+ movemouse(x,y);
+ end;
+
+ if FindDTMs(dtm, p, 0, 0, w-1, h-1) then
+ begin
+ writeln('Found ' + inttostr(length(p)) + ' DTM(s). First one at ' +
+ inttostr(p[0].x) + ', ' + inttostr(p[0].y));
+ movemouse(p[0].x,p[0].y);
+ end;
+
+ if FindDTMRotated(dtm, x, y, 0, 0, w-1, h-1, -3.14, 3.14, 0.05, a) then
+ begin
+ writeln('Found DTM at ' + inttostr(x) + ', ' + inttostr(y) + ' Angle: ' + FloatToStr(a));
+ movemouse(x,y);
+ end;
+end.
diff --git a/branches/script-component/Tests/PS/mouse.mufa b/branches/script-component/Tests/PS/mouse.mufa
new file mode 100644
index 0000000..8a77a07
--- /dev/null
+++ b/branches/script-component/Tests/PS/mouse.mufa
@@ -0,0 +1,32 @@
+program Mouse;
+
+{
+This program illustrates the Mufasa Mouse Functions
+}
+
+var
+ w, h, x, y: integer;
+begin
+ getclientdimensions(w,h);
+ writeln(inttostr(w) + ', ' + inttostr(h));
+ MoveMouse(0, 0);
+ getmousepos(x, y);
+ writeln(inttostr(x) + ', ' + inttostr(y));
+ wait(1000);
+ MoveMouse(w, 0);
+ getmousepos(x, y);
+ writeln(inttostr(x) + ', ' + inttostr(y));
+ wait(1000);
+ MoveMouse(0, h);
+ getmousepos(x, y);
+ writeln(inttostr(x) + ', ' + inttostr(y));
+ wait(1000);
+ MoveMouse(w, h);
+ getmousepos(x, y);
+ writeln(inttostr(x) + ', ' + inttostr(y));
+ wait(1000);
+ ClickMouse(0, 0, mouse_Right);
+
+ for x := 0 to 400 do
+ MoveMouse(x, x);
+end.
diff --git a/branches/script-component/Tests/PS/plugintest.txt b/branches/script-component/Tests/PS/plugintest.txt
new file mode 100644
index 0000000..0d82666
--- /dev/null
+++ b/branches/script-component/Tests/PS/plugintest.txt
@@ -0,0 +1,64 @@
+program new;
+{.LoadDLL libsmart}
+function IsKeyDown(C:Char): Boolean;
+begin
+ Result := SmartIsKeyDown(ord(c));
+end;
+
+procedure MoveMouse(x, y: Integer);
+begin
+ SmartMoveMouse(x, y);
+end;
+
+procedure HoldMouse(x, y: Integer; left: Boolean);
+begin
+ SmartHoldMouse(x, y, left);
+end;
+
+procedure ReleaseMouse(x, y: Integer; left: Boolean);
+begin
+ SmartReleaseMouse(x, y, left);
+end;
+
+procedure KeyUp(key: Byte);
+begin
+ If Key = 13 Then
+ Key := 10;
+ SmartReleaseKey(key);
+end;
+
+procedure KeyDown(key: Byte);
+begin
+ If Key = 13 Then
+ Key := 10;
+ SmartHoldKey(key);
+end;
+
+procedure SendKeys(S: String);
+begin
+ SmartSendKeys(S);
+end;
+
+procedure GetMousePos(var x, y: Integer);
+begin
+ SmartGetMousePos(x, y);
+end;
+
+function GetColor(x, y: Integer): Integer;
+begin
+ result:= SmartGetColor(x, y);
+end;
+
+
+var
+ w,h:integer;
+begin
+ SmartSetup('http://world19.runescape.com/', 'plugin.js?param=o0,a1,m0', 765, 503);
+ SetTargetArray(SmartImageArray, 765,503);
+ getclientdimensions(w,h);
+ writeln(inttostr(w) + ' , ' + inttostr(h));
+ if findcolortolerance(w,h,clwhite,0,0,764,502,300) then
+ smartmovemouse(w,h);
+ savescreenshot('/tmp/smart.bmp');
+ //Wait(5000);
+end.
diff --git a/branches/script-component/Tests/PS/stringtest.mufa b/branches/script-component/Tests/PS/stringtest.mufa
new file mode 100644
index 0000000..c3e911a
--- /dev/null
+++ b/branches/script-component/Tests/PS/stringtest.mufa
@@ -0,0 +1,39 @@
+program new;
+type
+ LetsDoThis = record
+ str : string;
+ x,y : integer;
+ end;
+ LetsDoThis2 = record
+ str : string;
+ pt : TPoint;
+ end;
+ Yeah = array of LetsDoThis2;
+ ArrThis = array of yeah;
+
+
+var
+ x : LetsDoThis;
+ y : arrthis;
+ j : TForm;
+ i,ii : integer;
+begin
+ x.str := 'Testmebitch';
+ x.x := 500;
+ x.y := -900;
+ Writeln(x);
+ SetLength(y,2);
+ for i := 0 to high(y) do
+ begin;
+ setlength(y[i],2);
+ for ii := 0 to high(y[i]) do
+ begin;
+ y[i][ii].pt := Point(i*5,-random(9000));
+ y[i][ii].str := format('[%d][%d]=%s',[i,ii,tostr(y[i][ii].pt)]);
+ end;
+ end;
+ Writeln(y);
+ Writeln(TPointArray([Point(5,5),Point(20,1337),point(1,2)]));
+ J := TForm.Create(nil);
+ Writeln(j.canvas);
+end.
diff --git a/branches/script-component/Units/Linux/xinput.pas b/branches/script-component/Units/Linux/xinput.pas
new file mode 100644
index 0000000..9943e54
--- /dev/null
+++ b/branches/script-component/Units/Linux/xinput.pas
@@ -0,0 +1,1014 @@
+ { $Xorg: XInput.h,v 1.4 2001/02/09 02:03:23 xorgcvs Exp $ }
+ {***********************************************************
+
+ Copyright 1989, 1998 The Open Group
+
+ Permission to use, copy, modify, distribute, and sell this software and its
+ documentation for any purpose is hereby granted without fee, provided that
+ the above copyright notice appear in all copies and that both that
+ copyright notice and this permission notice appear in supporting
+ documentation.
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ Except as contained in this notice, the name of The Open Group shall not be
+ used in advertising or otherwise to promote the sale, use or other dealings
+ in this Software without prior written authorization from The Open Group.
+
+ Copyright 1989 by Hewlett-Packard Company, Palo Alto, California.
+
+ All Rights Reserved
+
+ Permission to use, copy, modify, and distribute this software and its
+ documentation for any purpose and without fee is hereby granted,
+ provided that the above copyright notice appear in all copies and that
+ both that copyright notice and this permission notice appear in
+ supporting documentation, and that the name of Hewlett-Packard not be
+ used in advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+ HEWLETT-PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ SOFTWARE.
+
+ ******************************************************* }
+unit xinput;
+
+interface
+
+uses
+ x, xlib, xi, ctypes;
+
+type
+ PXEventClass = ^XEventClass;
+ PpXEventClass = ^PXEventClass;
+
+{$IFDEF FPC}
+{$PACKRECORDS C}
+{$ENDIF}
+
+const
+ _deviceKeyPress = 0;
+ _deviceKeyRelease = 1;
+ _deviceButtonPress = 0;
+ _deviceButtonRelease = 1;
+ _deviceMotionNotify = 0;
+ _deviceFocusIn = 0;
+ _deviceFocusOut = 1;
+ _proximityIn = 0;
+ _proximityOut = 1;
+ _deviceStateNotify = 0;
+ _deviceMappingNotify = 1;
+ _changeDeviceNotify = 2;
+ { Space of 3 between is necessary! Reserved for DeviceKeyStateNotify,
+ DeviceButtonStateNotify, DevicePresenceNotify (essentially unused). This
+ code has to be in sync with FixExtensionEvents() in xserver/Xi/extinit.c }
+ _propertyNotify = 6;
+
+ { We need the declaration for DevicePresence. }
+
+ function _XiGetDevicePresenceNotifyEvent(dpy:pDisplay):cint; cdecl; external;
+
+ {**************************************************************
+ *
+ * DeviceKey events. These events are sent by input devices that
+ * support input class Keys.
+ * The location of the X pointer is reported in the coordinate
+ * fields of the x,y and x_root,y_root fields.
+ *
+ }
+type
+ TXDeviceKeyEvent = record
+ _type : cint; { of event }
+ serial : culong; { # of last request processed }
+ send_event : cbool; { true if from SendEvent request }
+ display : PDisplay; { Display the event was read from }
+ window : TWindow; { "event" window reported relative to }
+ deviceid : TXID;
+ root : TWindow; { root window event occured on }
+ subwindow : TWindow; { child window }
+ time : TTime; { milliseconds }
+ x : cint; { x, y coordinates in event window }
+ y : cint;
+ x_root : cint; { coordinates relative to root }
+ y_root : cint; { coordinates relative to root }
+ state : cuint; { key or button mask }
+ keycode : cuint; { detail }
+ same_screen : cbool; { same screen flag }
+ device_state : cuint; { device key or button mask }
+ axes_count : cuchar;
+ first_axis : cuchar;
+ axis_data : array[0..5] of cint;
+ end;
+
+ TXDeviceKeyPressedEvent = TXDeviceKeyEvent;
+
+ TXDeviceKeyReleasedEvent = TXDeviceKeyEvent;
+ {******************************************************************
+ *
+ * DeviceButton events. These events are sent by extension devices
+ * that support input class Buttons.
+ *
+ }
+
+ TXDeviceButtonEvent = record
+ _type : cint; { of event }
+ serial : culong; { # of last request processed by server }
+ send_event : cbool; { true if from a SendEvent request }
+ display : PDisplay; { Display the event was read from }
+ window : TWindow; { "event" window reported relative to }
+ deviceid : TXID;
+ root : TWindow; { root window that the event occured on }
+ subwindow : TWindow; { child window }
+ time : TTime; { milliseconds }
+ x : cint; { x, y coordinates in event window }
+ y : cint;
+ x_root : cint; { coordinates relative to root }
+ y_root : cint; { coordinates relative to root }
+ state : cuint; { key or button mask }
+ button : cuint; { detail }
+ same_screen : cbool; { same screen flag }
+ device_state : cuint; { device key or button mask }
+ axes_count : cuchar;
+ first_axis : cuchar;
+ axis_data : array[0..5] of cint;
+ end;
+
+ TXDeviceButtonPressedEvent = TXDeviceButtonEvent;
+
+ TXDeviceButtonReleasedEvent = TXDeviceButtonEvent;
+ {******************************************************************
+ *
+ * DeviceMotionNotify event. These events are sent by extension devices
+ * that support input class Valuators.
+ *
+ }
+ TXDeviceMotionEvent = record
+ _type : cint; { of event }
+ serial : culong; { # of last request processed by server }
+ send_event : cbool; { true if from a SendEvent request }
+ display : PDisplay; { Display the event was read from }
+ window : TWindow; { "event" window reported relative to }
+ deviceid : TXID;
+ root : TWindow; { root window that the event occured on }
+ subwindow : TWindow; { child window }
+ time : TTime; { milliseconds }
+ x,y : cint; { x, y coordinates in event window }
+ x_root : cint; { coordinates relative to root }
+ y_root : cint; { coordinates relative to root }
+ state : cuint; { key or button mask }
+ is_hint : char; { detail }
+ same_screen : cbool; { same screen flag }
+ device_state : cuint; { device key or button mask }
+ axes_count : cuchar;
+ first_axis : cuchar;
+ axis_data : array[0..5] of cint;
+ end;
+
+ {******************************************************************
+ *
+ * DeviceFocusChange events. These events are sent when the focus
+ * of an extension device that can be focused is changed.
+ *
+ }
+ TXDeviceFocusChangeEvent = record
+ _type : cint; { of event }
+ serial : culong; { # of last request processed by server }
+ send_event : cbool; { true if from a SendEvent request }
+ display : PDisplay; { Display the event was read from }
+ window : TWindow; { "event" window reported relative to }
+ deviceid : TXID;
+ mode : cint; { NotifyNormal, NotifyGrab, NotifyUngrab }
+ detail : cint;
+ { * NotifyAncestor, NotifyVirtual, NotifyInferior,
+ * NotifyNonLinear,NotifyNonLinearVirtual, NotifyPointer,
+ * NotifyPointerRoot, NotifyDetailNone }
+ time : TTime;
+ end;
+
+ TXDeviceFocusInEvent = TXDeviceFocusChangeEvent;
+
+ TXDeviceFocusOutEvent = TXDeviceFocusChangeEvent;
+ {******************************************************************
+ *
+ * ProximityNotify events. These events are sent by those absolute
+ * positioning devices that are capable of generating proximity information.
+ *
+ }
+
+ TXProximityNotifyEvent = record
+ _type : cint; { ProximityIn or ProximityOut }
+ serial : culong; { # of last request processed by server }
+ send_event : cbool; { true if this came from a SendEvent request }
+ display : PDisplay; { Display the event was read from }
+ window : TWindow;
+ deviceid : TXID;
+ root : TWindow;
+ subwindow : TWindow;
+ time : TTime;
+ x : cint;
+ y : cint;
+ x_root : cint;
+ y_root : cint;
+ state : cuint;
+ same_screen : cbool;
+ device_state : cuint; { device key or button mask }
+ axes_count : cuchar;
+ first_axis : cuchar;
+ axis_data : array[0..5] of cint;
+ end;
+
+ TXProximityInEvent = TXProximityNotifyEvent;
+
+ TXProximityOutEvent = TXProximityNotifyEvent;
+ {******************************************************************
+ *
+ * DeviceStateNotify events are generated on EnterWindow and FocusIn
+ * for those clients who have selected DeviceState.
+ *
+ }
+
+ TXInputClass = record
+ c_class : cuchar;
+ _length : cuchar;
+ end;
+ PXInputClass = ^TXInputClass;
+
+ TXDeviceStateNotifyEvent = record
+ _type : cint;
+ serial : culong; { # of last request processed by server }
+ send_event : cbool; { true if this came from a SendEvent request }
+ display : PDisplay; { Display the event was read from }
+ window : TWindow;
+ deviceid : TXID;
+ time : TTime;
+ num_classes : cint;
+ data : array[0..63] of char;
+ end;
+
+ TXValuatorStatus = record
+ c_class : cuchar;
+ _length : cuchar;
+ num_valuators : cuchar;
+ mode : cuchar;
+ valuators : array[0..5] of cint;
+ end;
+
+ TXKeyStatus = record
+ c_class : cuchar;
+ _length : cuchar;
+ num_keys : cshort;
+ keys : array[0..31] of char;
+ end;
+
+ TXButtonStatus = record
+ c_class : cuchar;
+ _length : cuchar;
+ num_buttons : cshort;
+ buttons : array[0..31] of char;
+ end;
+
+ {******************************************************************
+ *
+ * DeviceMappingNotify event. This event is sent when the key mapping,
+ * modifier mapping, or button mapping of an extension device is changed.
+ *
+ }
+ TXDeviceMappingEvent = record
+ _type : cint;
+ serial : culong; { # of last request processed by server }
+ send_event : cbool; { true if this came from a SendEvent request }
+ display : PDisplay; { Display the event was read from }
+ window : TWindow; { unused }
+ deviceid : TXID;
+ time : TTime;
+ request : cint; { one of MappingModifier, MappingKeyboard, MappingPointer }
+ first_keycode : cint; { first keycode }
+ count : cint; { defines range of change w. first_keycode }
+ end;
+ {******************************************************************
+ *
+ * ChangeDeviceNotify event. This event is sent when an
+ * XChangeKeyboard or XChangePointer request is made.
+ *
+ }
+ TXChangeDeviceNotifyEvent = record
+ _type : cint;
+ serial : culong; { # of last request processed by server }
+ send_event : cbool; { true if this came from a SendEvent request }
+ display : PDisplay; { Display the event was read from }
+ window : TWindow; { unused }
+ deviceid : TXID;
+ time : TTime;
+ request : cint; { NewPointer or NewKeyboard }
+ end;
+
+ {******************************************************************
+ *
+ * DevicePresenceNotify event. This event is sent when the list of
+ * input devices changes, in which case devchange will be false, and
+ * no information about the change will be contained in the event;
+ * the client should use XListInputDevices() to learn what has changed.
+ *
+ * If devchange is true, an attribute that the server believes is
+ * important has changed on a device, and the client should use
+ * XGetDeviceControl to examine the device. If control is non-zero,
+ * then that control has changed meaningfully.
+ }
+
+ TXDevicePresenceNotifyEvent = record
+ _type : cint;
+ serial : culong; { # of last request processed by server }
+ send_event : cbool; { true if this came from a SendEvent request }
+ display : PDisplay; { Display the event was read from }
+ window : TWindow; { unused }
+ time : TTime;
+ devchange : cbool;
+ deviceid : TXID;
+ control : TXID;
+ end;
+
+ {
+ * Notifies the client that a property on a device has changed value. The
+ * client is expected to query the server for updated value of the property.
+ }
+
+ TXDevicePropertyNotifyEvent = record
+ _type : cint;
+ serial : culong; { # of last request processed by server }
+ send_event : cbool; { true if this came from a SendEvent request }
+ display : PDisplay; { Display the event was read from }
+ window : TWindow; { unused }
+ time : TTime;
+ deviceid : TXID; { id of the device that changed }
+ atom : TAtom; { the property that changed }
+ state : cint; { PropertyNewValue or PropertyDeleted }
+ end;
+
+ {******************************************************************
+ *
+ * Control structures for input devices that support input class
+ * Feedback. These are used by the XGetFeedbackControl and
+ * XChangeFeedbackControl functions.
+ *
+ }
+
+ TXFeedbackState = record
+ c_class : TXID;
+ _length : cint;
+ id : TXID;
+ end;
+ PXFeedbackState = ^TXFeedbackState;
+
+ TXKbdFeedbackState = record
+ c_class : TXID;
+ _length : cint;
+ id : TXID;
+ click : cint;
+ percent : cint;
+ pitch : cint;
+ duration : cint;
+ led_mask : cint;
+ global_auto_repeat : cint;
+ auto_repeats : array[0..31] of char;
+ end;
+
+ TXPtrFeedbackState = record
+ c_class : TXID;
+ _length : cint;
+ id : TXID;
+ accelNum : cint;
+ accelDenom : cint;
+ threshold : cint;
+ end;
+
+ TXIntegerFeedbackState = record
+ c_class : TXID;
+ _length : cint;
+ id : TXID;
+ resolution : cint;
+ minVal : cint;
+ maxVal : cint;
+ end;
+
+ TXStringFeedbackState = record
+ c_class : TXID;
+ _length : cint;
+ id : TXID;
+ max_symbols : cint;
+ num_syms_supported : cint;
+ syms_supported : PKeySym;
+ end;
+
+ TXBellFeedbackState = record
+ c_class : TXID;
+ _length : cint;
+ id : TXID;
+ percent : cint;
+ pitch : cint;
+ duration : cint;
+ end;
+
+ TXLedFeedbackState = record
+ c_class : TXID;
+ _length : cint;
+ id : TXID;
+ led_values : cint;
+ led_mask : cint;
+ end;
+
+ TXFeedbackControl = record
+ c_class : TXID;
+ _length : cint;
+ id : TXID;
+ end;
+ PXFeedbackControl = ^TXFeedbackControl;
+
+ TXPtrFeedbackControl = record
+ c_class : TXID;
+ _length : cint;
+ id : TXID;
+ accelNum : cint;
+ accelDenom : cint;
+ threshold : cint;
+ end;
+
+ TXKbdFeedbackControl = record
+ c_class : TXID;
+ _length : cint;
+ id : TXID;
+ click : cint;
+ percent : cint;
+ pitch : cint;
+ duration : cint;
+ led_mask : cint;
+ led_value : cint;
+ key : cint;
+ auto_repeat_mode : cint;
+ end;
+
+ TXStringFeedbackControl = record
+ c_class : TXID;
+ _length : cint;
+ id : TXID;
+ num_keysyms : cint;
+ syms_to_display : PKeySym;
+ end;
+
+ TXIntegerFeedbackControl = record
+ c_class : TXID;
+ _length : cint;
+ id : TXID;
+ int_to_display : cint;
+ end;
+
+ TXBellFeedbackControl = record
+ c_class : TXID;
+ _length : cint;
+ id : TXID;
+ percent : cint;
+ pitch : cint;
+ duration : cint;
+ end;
+
+ TXLedFeedbackControl = record
+ c_class : TXID;
+ _length : cint;
+ id : TXID;
+ led_mask : cint;
+ led_values : cint;
+ end;
+
+ {******************************************************************
+ *
+ * Device control structures.
+ *
+ }
+
+ TXDeviceControl = record
+ control : TXID;
+ _length : cint;
+ end;
+ PXDeviceControl = ^TXDeviceControl;
+
+ TXDeviceResolutionControl = record
+ control : TXID;
+ _length : cint;
+ first_valuator : cint;
+ num_valuators : cint;
+ resolutions : ^cint;
+ end;
+
+ TXDeviceResolutionState = record
+ control : TXID;
+ _length : cint;
+ num_valuators : cint;
+ resolutions : ^cint;
+ min_resolutions : ^cint;
+ max_resolutions : ^cint;
+ end;
+
+ TXDeviceAbsCalibControl = record
+ control : TXID;
+ _length : cint;
+ min_x : cint;
+ max_x : cint;
+ min_y : cint;
+ max_y : cint;
+ flip_x : cint;
+ flip_y : cint;
+ rotation : cint;
+ button_threshold : cint;
+ end;
+ TXDeviceAbsCalibState = TXDeviceAbsCalibControl;
+
+ TXDeviceAbsAreaControl = record
+ control : TXID;
+ _length : cint;
+ offset_x : cint;
+ offset_y : cint;
+ width : cint;
+ height : cint;
+ screen : cint;
+ following : TXID;
+ end;
+ TXDeviceAbsAreaState = TXDeviceAbsAreaControl;
+
+ TXDeviceCoreControl = record
+ control : TXID;
+ _length : cint;
+ status : cint;
+ end;
+
+ TXDeviceCoreState = record
+ control : TXID;
+ _length : cint;
+ status : cint;
+ iscore : cint;
+ end;
+
+ TXDeviceEnableControl = record
+ control : TXID;
+ _length : cint;
+ enable : cint;
+ end;
+ TXDeviceEnableState = TXDeviceEnableControl;
+
+ {******************************************************************
+ *
+ * An array of XDeviceList structures is returned by the
+ * XListInputDevices function. Each entry contains information
+ * about one input device. Among that information is an array of
+ * pointers to structures that describe the characteristics of
+ * the input device.
+ *
+ }
+
+ _XAnyClassinfo = record
+ c_class : TXID;
+ _length : cint;
+ end;
+ TXAnyClassInfo = _XAnyClassinfo;
+ PXAnyClassInfo = ^TXAnyClassInfo;
+
+ _XDeviceInfo = record
+ id : TXID;
+ _type : TAtom;
+ name : ^char;
+ num_classes : cint;
+ use : cint;
+ inputclassinfo : PXAnyClassInfo;
+ end;
+ TXDeviceInfo = _XDeviceInfo;
+ PXDeviceInfo = ^TXDeviceInfo;
+
+ _XKeyInfo = record
+ c_class : TXID;
+ _length : cint;
+ min_keycode : cushort;
+ max_keycode : cushort;
+ num_keys : cushort;
+ end;
+ TXKeyInfo = _XKeyInfo;
+ PXKeyInfo = ^TXKeyInfo;
+
+ _XButtonInfo = record
+ c_class : TXID;
+ _length : cint;
+ num_buttons : cshort;
+ end;
+ TXButtonInfo = _XButtonInfo;
+ PXButtonInfo = ^TXButtonInfo;
+
+ _XAxisInfo = record
+ resolution : cint;
+ min_value : cint;
+ max_value : cint;
+ end;
+ TXAxisInfo = _XAxisInfo;
+ PXAxisInfo = ^TXAxisInfo;
+
+ _XValuatorInfo = record
+ c_class : TXID;
+ _length : cint;
+ num_axes : cuchar;
+ mode : cuchar;
+ motion_buffer : culong;
+ axes : PXAxisInfo;
+ end;
+ TXValuatorInfo = _XValuatorInfo;
+ PXValuatorInfo = ^TXValuatorInfo;
+ {******************************************************************
+ *
+ * An XDevice structure is returned by the XOpenDevice function.
+ * It contains an array of pointers to XInputClassInfo structures.
+ * Each contains information about a class of input supported by the
+ * device, including a pointer to an array of data for each type of event
+ * the device reports.
+ *
+ }
+
+ TXInputClassInfo = record
+ input_class : cuchar;
+ event_type_base : cuchar;
+ end;
+ PXInputClassInfo = ^TXInputClassInfo;
+
+ TXDevice = record
+ device_id : TXID;
+ num_classes : cint;
+ classes : PXInputClassInfo;
+ end;
+ PXDevice = ^TXDevice;
+
+ {******************************************************************
+ *
+ * The following structure is used to return information for the
+ * XGetSelectedExtensionEvents function.
+ *
+ }
+
+ TXEventList = record
+ event_type : XEventClass;
+ device : TXID;
+ end;
+ {******************************************************************
+ *
+ * The following structure is used to return motion history data from
+ * an input device that supports the input class Valuators.
+ * This information is returned by the XGetDeviceMotionEvents function.
+ *
+ }
+
+ TXDeviceTimeCoord = record
+ time : TTime;
+ data : pcint;
+ end;
+ PXDeviceTimeCoord = ^TXDeviceTimeCoord;
+
+ {******************************************************************
+ *
+ * Device state structure.
+ * This is returned by the XQueryDeviceState request.
+ *
+ }
+
+ TXDeviceState = record
+ device_id : TXID;
+ num_classes : cint;
+ data : PXInputClass;
+ end;
+ PXDeviceState = ^TXDeviceState;
+
+ {******************************************************************
+ *
+ * Note that the mode field is a bitfield that reports the Proximity
+ * status of the device as well as the mode. The mode field should
+ * be OR'd with the mask DeviceMode and compared with the values
+ * Absolute and Relative to determine the mode, and should be OR'd
+ * with the mask ProximityState and compared with the values InProximity
+ * and OutOfProximity to determine the proximity state.
+ *
+ }
+
+ TXValuatorState = record
+ c_class : cuchar;
+ _length : cuchar;
+ num_valuators : cuchar;
+ mode : cuchar;
+ valuators : pcint;
+ end;
+
+ TXKeyState = record
+ c_class : cuchar;
+ _length : cuchar;
+ num_keys : cshort;
+ keys : array[0..31] of char;
+ end;
+
+ TXButtonState = record
+ c_class : cuchar;
+ _length : cuchar;
+ num_buttons : cshort;
+ buttons : array[0..31] of char;
+ end;
+
+ {******************************************************************
+ *
+ * Function definitions.
+ *
+ }
+
+ function XChangeKeyboardDevice(display:PDisplay; device:PXDevice):cint;cdecl; external;
+
+ function XChangePointerDevice(display:PDisplay; device:pXDevice; xaxis:cint; yaxis:cint):cint;cdecl; external;
+
+ function XGrabDevice(display:pDisplay; device:pXDevice; grab_window:TWindow; ownerEvents:cbool; event_count:cint;
+ event_list:PXEventClass; this_device_mode:cint; other_devices_mode:cint; time:TTime):cint;cdecl; external;
+
+ function XUngrabDevice(display:pDisplay; device:pXDevice; time:TTime):cint;cdecl; external;
+
+ function XGrabDeviceKey(display:pDisplay; device:pXDevice; key:cuint; modifiers:cuint; modifier_device:pXDevice;
+ grab_window:TWindow; owner_events:cbool; event_count:cuint; event_list:pXEventClass; this_device_mode:cint;
+ other_devices_mode:cint):cint;cdecl; external;
+
+ function XUngrabDeviceKey(display:pDisplay; device:pXDevice; key:cuint; modifiers:cuint; modifier_dev:pXDevice;
+ grab_window:TWindow):cint;cdecl; external;
+
+ function XGrabDeviceButton(display:pDisplay; device:pXDevice; button:cuint; modifier:cuint; modifier_device:pXDevice;
+ grab_window:TWindow; owner_events:cbool; event_count:cuint; event_list:pXEventClass; this_device_mode:cint;
+ other_devices_mode:cint):cint;cdecl; external;
+
+ function XUngrabDeviceButton(display:pDisplay; device:pXDevice; button:cuint; modifiers:cuint; modifier_dev:pXDevice;
+ grab_window:TWindow):cint;cdecl; external;
+
+ function XAllowDeviceEvents(display:pDisplay; device:pXDevice; event_mode:cint; time:TTime):cint;cdecl;external;
+
+ function XGetDeviceFocus(display:pDisplay; device:pXDevice; focus:pWindow; revert_to:pcint; time:pTime):cint;cdecl;external;
+
+ function XSetDeviceFocus(display:pDisplay; device:pXDevice; focus:TWindow; revert_to:cint; time:TTime):cint;cdecl;external;
+
+ function XGetFeedbackControl(display:pDisplay; device:pXDevice; num_feedbacks:pcint): PXFeedbackState;cdecl;external;
+
+ procedure XFreeFeedbackList(list:pXFeedbackState);cdecl;external;
+
+ function XChangeFeedbackControl(display:pDisplay; device:pXDevice; mask:culong; f:pXFeedbackControl):cint;cdecl;external;
+
+ function XDeviceBell(display:pDisplay; device:pXDevice; feedbackclass:TXID; feedbackid:TXID; percent:cint):cint;cdecl;external;
+
+ function XGetDeviceKeyMapping(display:pDisplay; device:pXDevice; first:cuint; keycount:cint; syms_per_code:pcint):PKeySym;cdecl;external;
+
+ function XChangeDeviceKeyMapping(display:pDisplay; device:pXDevice; first:cint; syms_per_code:cint; keysyms:pKeySym;
+ count:cint):cint;cdecl;external;
+
+ function XGetDeviceModifierMapping(display:pDisplay; device:pXDevice):PXModifierKeymap;cdecl;external;
+
+ function XSetDeviceModifierMapping(display:pDisplay; device:pXDevice; modmap:pXModifierKeymap):cint;cdecl;external;
+
+ function XSetDeviceButtonMapping(display:pDisplay; device:pXDevice; map:array of pcuchar; nmap:cint):cint;cdecl;external;
+
+ function XGetDeviceButtonMapping(display:pDisplay; device:pXDevice; map:array of pcuchar; nmap:cuint):cint;cdecl;external;
+
+ function XQueryDeviceState(display:pDisplay; device:pXDevice):PXDeviceState;cdecl;external;
+
+ procedure XFreeDeviceState(list:pXDeviceState);cdecl;external;
+
+(* Const before type ignored *)
+ function XGetExtensionVersion(display:pDisplay; name:pchar):PXExtensionVersion;cdecl;external;
+
+ function XListInputDevices(display:pDisplay; ndevices:pcint):PXDeviceInfo;cdecl;external;
+
+ procedure XFreeDeviceList(list:pXDeviceInfo);cdecl;external;
+
+ function XOpenDevice(display:pDisplay; id:TXID):PXDevice;cdecl;external;
+
+ function XCloseDevice(display:pDisplay; device:pXDevice):cint;cdecl;external;
+
+ function XSetDeviceMode(display:pDisplay; device:pXDevice; mode:cint):cint;cdecl;external;
+
+ function XSetDeviceValuators(display:pDisplay; device:pXDevice; valuators:pcint; first_valuator:cint; num_valuators:cint):cint;cdecl;external;
+
+ function XGetDeviceControl(display:pDisplay; device:pXDevice; control:cint):PXDeviceControl;cdecl;external;
+
+ function XChangeDeviceControl(display:pDisplay; device:pXDevice; control:cint; d:pXDeviceControl):cint;cdecl;external;
+
+ function XSelectExtensionEvent(display:pDisplay; w:TWindow; event_list:pXEventClass; count:cint):cint;cdecl;external;
+
+ function XGetSelectedExtensionEvents(display:pDisplay; w:TWindow; this_client_count:pcint; this_client_list:PpXEventClass; all_clients_count:pcint;
+ all_clients_list:PpXEventClass):cint;cdecl;external;
+
+ function XChangeDeviceDontPropagateList(display:pDisplay; window:TWindow; count:cint; events:pXEventClass; mode:cint):cint;cdecl;external;
+
+ function XGetDeviceDontPropagateList(display:pDisplay; window:TWindow; count:pcint):PXEventClass;cdecl;external;
+
+ function XSendExtensionEvent(display:pDisplay; device:pXDevice; dest:TWindow; prop:cbool; count:cint;
+ list:pXEventClass; event:pXEvent):TStatus;cdecl;external;
+
+ function XGetDeviceMotionEvents(display:pDisplay; device:pXDevice; start:TTime; stop:TTime; nEvents:pcint;
+ mode:pcint; axis_count:pcint):PXDeviceTimeCoord;cdecl;external;
+
+ procedure XFreeDeviceMotionEvents(events:pXDeviceTimeCoord);cdecl;external;
+
+ procedure XFreeDeviceControl(control:pXDeviceControl);cdecl;external;
+
+
+type
+ TXIPropertyInfo = record
+ pending : cbool;
+ range : cbool;
+ immutable : cbool;
+ fromClient : cbool;
+ num_values : cint;
+ values : ^longint;
+ end;
+
+ function XListDeviceProperties(dpy:pDisplay; dev:pXDevice; nprops_return:pcint):PAtom;cdecl;external;
+
+(* Const before type ignored *)
+ procedure XChangeDeviceProperty(dpy:pDisplay; dev:pXDevice; _property:TAtom; _type:TAtom; format:cint;
+ mode:cint; data:pcuchar; nelements:cint);cdecl;external;
+
+ procedure XDeleteDeviceProperty(dpy:pDisplay; dev:pXDevice; _property:TAtom);cdecl;external;
+
+ function XGetDeviceProperty(dpy:pDisplay; dev:pXDevice; _property:TAtom; offset:longint; _length:longint;
+ _delete:cbool; req_type:TAtom; actual_type:pAtom; actual_format:pcint; nitems:pculong;
+ bytes_after:pculong; prop:Ppcuchar):TStatus;cdecl;external;
+ procedure FindTypeAndClass(d: PXDevice; _type, _class, classid: cint; offset: cint); inline;
+ procedure DeviceKeyPress(d: PXDevice; _type, _class: cint); inline;
+ procedure DeviceKeyRelease(d: PXDevice; _type, _class: cint); inline;
+ procedure DeviceButtonPress(d: PXDevice; _type, _class: cint); inline;
+ procedure DeviceButtonRelease(d: PXDevice; _type, _class: cint); inline;
+ procedure DeviceMotionNotify(d: PXDevice; _type, _class: cint); inline;
+ procedure DeviceFocusIn(d: PXDevice; _type, _class: cint); inline;
+ procedure DeviceFocusOut(d: PXDevice; _type, _class: cint); inline;
+ procedure ProximityIn(d: PXDevice; _type, _class: cint); inline;
+ procedure ProximityOut(d: PXDevice; _type, _class: cint); inline;
+ procedure DeviceStateNotify(d: PXDevice; _type, _class: cint); inline;
+ procedure DeviceMappingNotify(d: PXDevice; _type, _class: cint); inline;
+ procedure ChangeDeviceNotify(d: PXDevice; _type, _class: cint); inline;
+ procedure DevicePropertyNotify(d: PXDevice; _type, _class: cint); inline;
+ procedure DevicePointerMotionHint(d: PXDevice; _type, _class: cint); inline;
+ procedure DeviceButton1Motion(d: PXDevice; _type, _class: cint); inline;
+ procedure DeviceButton2Motion(d: PXDevice; _type, _class: cint); inline;
+ procedure DeviceButton3Motion(d: PXDevice; _type, _class: cint); inline;
+ procedure DeviceButton4Motion(d: PXDevice; _type, _class: cint); inline;
+ procedure DeviceButton5Motion(d: PXDevice; _type, _class: cint); inline;
+ procedure DeviceButtonMotion(d: PXDevice; _type, _class: cint); inline;
+ procedure DeviceOwnerGrabButton(d: PXDevice; _type, _class: cint); inline;
+ procedure DeviceButtonPressGrab(d: PXDevice; _type, _class: cint); inline;
+
+implementation
+
+// Most important macro
+procedure FindTypeAndClass(d: PXDevice; _type, _class, classid: cint; offset: cint); inline;
+var
+ _i: integer;
+ _ip: PXInputClassInfo;
+begin
+ _type := 0;
+ _class := 0;
+ _ip := d^.classes;
+ for _i := 0 to d^.num_classes do
+ begin
+ if _ip^.input_class = classid then
+ begin
+ _type := _ip^.event_type_base + offset;
+ _class := d^.device_id shl 8 or _type;
+ end;
+ Inc(_ip);
+ end;
+end;
+
+ {
+ #define FindTypeAndClass(d,type,_class,classid,offset) \
+ int _i; XInputClassInfo *_ip; \
+ type = 0; _class = 0; \
+ for (_i=0, _ip= ((XDevice *) d)->classes; \
+ _i< ((XDevice *) d)->num_classes; \
+ _i++, _ip++) \
+ if (_ip->input_class == classid) \
+ type = _ip->event_type_base + offset; \
+ _class = ((XDevice *) d)->device_id << 8 | type; }
+
+procedure DeviceKeyPress(d: PXDevice; _type, _class: cint); inline;
+begin
+ FindTypeAndClass(d, _type, _class, KeyClass, _deviceKeyPress);
+end;
+
+procedure DeviceKeyRelease(d: PXDevice; _type, _class: cint); inline;
+begin
+ FindTypeAndClass(d, _type, _class, KeyClass, _deviceKeyRelease);
+end;
+
+procedure DeviceButtonPress(d: PXDevice; _type, _class: cint); inline;
+begin
+ FindTypeAndClass(d, _type, _class, ButtonClass, _deviceButtonPress);
+end;
+
+procedure DeviceButtonRelease(d: PXDevice; _type, _class: cint); inline;
+begin
+ FindTypeAndClass(d, _type, _class, ButtonClass, _deviceButtonRelease);
+end;
+
+procedure DeviceMotionNotify(d: PXDevice; _type, _class: cint); inline;
+begin
+ FindTypeAndClass(d, _type, _class, ValuatorClass, _deviceMotionNotify);
+end;
+
+procedure DeviceFocusIn(d: PXDevice; _type, _class: cint); inline;
+begin
+ FindTypeAndClass(d, _type, _class, FocusClass, _deviceFocusIn);
+end;
+
+procedure DeviceFocusOut(d: PXDevice; _type, _class: cint); inline;
+begin
+ FindTypeAndClass(d, _type, _class, FocusClass, _deviceFocusOut);
+end;
+
+procedure ProximityIn(d: PXDevice; _type, _class: cint); inline;
+begin
+ FindTypeAndClass(d, _type, _class, ProximityClass, _proximityIn);
+end;
+
+procedure ProximityOut(d: PXDevice; _type, _class: cint); inline;
+begin
+ FindTypeAndClass(d, _type, _class, ProximityClass, _proximityOut);
+end;
+
+procedure DeviceStateNotify(d: PXDevice; _type, _class: cint); inline;
+begin
+ FindTypeAndClass(d, _type, _class, OtherClass, _deviceStateNotify);
+end;
+
+procedure DeviceMappingNotify(d: PXDevice; _type, _class: cint); inline;
+begin
+ FindTypeAndClass(d, _type, _class, OtherClass, _deviceMappingNotify);
+end;
+
+procedure ChangeDeviceNotify(d: PXDevice; _type, _class: cint); inline;
+begin
+ FindTypeAndClass(d, _type, _class, OtherClass, _changeDeviceNotify);
+end;
+
+procedure DevicePropertyNotify(d: PXDevice; _type, _class: cint); inline;
+begin
+ FindTypeAndClass(d, _type, _class, OtherClass, _propertyNotify);
+end;
+
+procedure DevicePointerMotionHint(d: PXDevice; _type, _class: cint); inline;
+begin
+ _class := d^.device_id shl 8 or _devicePointerMotionHint;
+end;
+
+procedure DeviceButton1Motion(d: PXDevice; _type, _class: cint); inline;
+begin
+ _class := d^.device_id shl 8 or _deviceButton1Motion;
+end;
+
+procedure DeviceButton2Motion(d: PXDevice; _type, _class: cint); inline;
+begin
+ _class := d^.device_id shl 8 or _deviceButton2Motion;
+end;
+
+procedure DeviceButton3Motion(d: PXDevice; _type, _class: cint); inline;
+begin
+ _class := d^.device_id shl 8 or _deviceButton3Motion;
+end;
+
+procedure DeviceButton4Motion(d: PXDevice; _type, _class: cint); inline;
+begin
+ _class := d^.device_id shl 8 or _deviceButton4Motion;
+end;
+
+procedure DeviceButton5Motion(d: PXDevice; _type, _class: cint); inline;
+begin
+ _class := d^.device_id shl 8 or _deviceButton5Motion;
+end;
+
+procedure DeviceButtonMotion(d: PXDevice; _type, _class: cint); inline;
+begin
+ _class := d^.device_id shl 8 or _deviceButtonMotion;
+end;
+
+procedure DeviceOwnerGrabButton(d: PXDevice; _type, _class: cint); inline;
+begin
+ _class := d^.device_id shl 8 or _deviceOwnerGrabButton;
+end;
+procedure DeviceButtonPressGrab(d: PXDevice; _type, _class: cint); inline;
+begin
+ _class := d^.device_id shl 8 or _deviceButtonGrab;
+end;
+
+end.
diff --git a/branches/script-component/Units/Linux/xtest.pas b/branches/script-component/Units/Linux/xtest.pas
new file mode 100644
index 0000000..39e6f1c
--- /dev/null
+++ b/branches/script-component/Units/Linux/xtest.pas
@@ -0,0 +1,132 @@
+unit XTest;
+
+{$mode objfpc}{$H+}
+{$linklib Xtst}
+interface
+
+uses
+ Classes, SysUtils, x, xutil, xlib, ctypes, XKB, xinput;
+
+{ type
+ PXDevice = Pointer; // ^XDevice ? }
+
+const
+ X_XTestGetVersion = 0;
+ X_XTestCompareCursor = 1;
+ X_XTestFakeInput = 2;
+ X_XTestGrabControl = 3;
+ XTestNumberEvents = 0;
+ XTestNumberErrors = 0;
+ XTestMajorVersion = 2;
+ XTestMinorVersion = 2;
+ XTestExtensionName = 'XTEST';
+
+function XTestQueryExtension(dpy:PDisplay; event_basep, error_basep, majorp, minorp:pcint):CBool; cdecl; external;
+function XTestCompareCursorWithWindow(dpy:PDisplay; window:TWindow; cursor: TCursor):CBool; cdecl; external;
+function XTestCompareCurrentCursorWithWindow(dpy:pDisplay; window:TWindow):CBool; cdecl; external;
+function XTestFakeKeyEvent(dpy:PDisplay; keycode: cuint; is_press: CBool; delay: cuint):cint;cdecl; external;
+function XTestFakeButtonEvent(dpy:PDisplay; button: cuint; is_press: CBool; delay: cuint):cint;cdecl; external;
+function XTestFakeMotionEvent(dpy:PDisplay; screen, x,y: cint; delay :cuint):cint;cdecl; external;
+function XTestFakeRelativeMotionEvent(dpy:PDisplay; x,y,delay: cuint):cint;cdecl; external;
+function XTestFakeDeviceKeyEvent(dpy:PDisplay; dev:pXDevice; keycode:cuint; is_press:cbool;
+ axes:pcint; n_axes:cint; delay:cuint):cint;cdecl; external;
+function XTestFakeDeviceButtonEvent(dpy:PDisplay; dev:pXDevice; button:cuint; is_press:cbool; axes:pcint;
+ n_axes:cint; delay:cuint):cint;cdecl; external;
+function XTestFakeProximityEvent(dpy:PDisplay; dev:pXDevice; in_prox:cbool; axes:pcint; n_axes:cint;
+ delay:cuint):cint;cdecl; external;
+function XTestFakeDeviceMotionEvent(dpy:PDisplay; dev:pXDevice;
+ is_relative:cbool; first_axis:cint; axes:pcint; n_axes:cint; delay:cuint):cint;cdecl; external;
+function XTestGrabControl(dpy:PDisplay; impervious:cbool):cint;cdecl; external;
+
+procedure XTestSetGContextOfGC(gc: TGC; gid:TGContext); cdecl; external;
+procedure XTestSetVisualIDOfVisual(visual:PVisual; visualid: TVisualID); cdecl; external;
+function XTestDiscard(dpy:pDisplay):TStatus; cdecl; external;
+
+{ Below is old testing code }
+procedure mouse_move(x,y: integer);
+procedure mouse_click(left:boolean);
+procedure keytest;
+procedure keystest(s:string);
+
+implementation
+
+function thing_to_keycode(D: PDisplay; thing: string): TKeyCode;
+var
+ kc: TKeyCode;
+ ks: TKeySym;
+begin
+ ks := XStringToKeysym(@thing[1]);
+ if(ks = NoSymbol) then
+ begin
+ writeln('Can''t resolve keysym for ' + thing);
+ result := thing_to_keycode(D, 'space');
+ exit;
+ end;
+ kc := XKeysymToKeycode(D, ks);
+ result := kc;
+end;
+
+procedure mouse_move(x,y: integer);
+var
+ d: PDisplay;
+begin
+ d := XOpenDisplay(nil);
+ XTestFakeMotionEvent(d, -1, x, y, CurrentTime);
+ XCloseDisplay(d);
+end;
+
+procedure mouse_click(left:boolean);
+var
+ d: PDisplay;
+begin
+ d := XOpenDisplay(nil);
+ if left then
+ begin
+ XTestFakeButtonEvent(d, Button1, True, CurrentTime);
+ XTestFakeButtonEvent(d, Button1, False, CurrentTime);
+ end
+ else
+ begin
+ XTestFakeButtonEvent(d, Button3, True, CurrentTime);
+ XTestFakeButtonEvent(d, Button3, False, CurrentTime);
+ end;
+ XCloseDisplay(d);
+end;
+
+procedure send_key(D: PDisplay; c: char);
+begin
+ XTestFakeKeyEvent(d, thing_to_keycode(d, c), True, CurrentTime);
+ XTestFakeKeyEvent(d, thing_to_keycode(d, c), False, CurrentTime);
+end;
+
+procedure send_keys(d:pdisplay; s:string);
+var
+ i: integer;
+begin
+ for i := 1 to length(s) do
+ begin
+ send_key(d, s[i]);
+ XFlush(d);
+ end;
+end;
+
+procedure keytest;
+var
+ d:pdisplay;
+begin
+ d := XOpenDisplay(nil);
+ send_key(d, 'a');
+ XCloseDisplay(d);
+end;
+
+procedure keystest(s:string);
+var
+ d:pdisplay;
+begin
+ d := XOpenDisplay(nil);
+ send_keys(d, s);
+ XCloseDisplay(d);
+end;
+
+end.
+
diff --git a/branches/script-component/Units/MMLAddon/PSInc/Wrappers/bitmap.inc b/branches/script-component/Units/MMLAddon/PSInc/Wrappers/bitmap.inc
new file mode 100644
index 0000000..24ef421
--- /dev/null
+++ b/branches/script-component/Units/MMLAddon/PSInc/Wrappers/bitmap.inc
@@ -0,0 +1,284 @@
+{
+ This file is part of the Mufasa Macro Library (MML)
+ Copyright (c) 2009 by Raymond van Venetië and Merlijn Wajer
+
+ MML is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ MML is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with MML. If not, see .
+
+ See the file COPYING, included in this distribution,
+ for details about the copyright.
+
+ Bitmap.inc for the Mufasa Macro Library
+}
+function CreateBitmapString(bmp : integer) : string;
+begin;
+ result := CurrThread.Client.MBitmaps[bmp].ToString;
+end;
+
+function GetMufasaBitmap(bmp : integer): TMufasaBitmap;
+begin;
+ result := CurrThread.Client.MBitmaps[bmp];
+end;
+
+function CreateBitmap(w,h : integer):integer;
+begin
+ result := CurrThread.Client.MBitmaps.CreateBMP(w,h);
+end;
+
+procedure FreeBitmap(Number : integer);
+begin
+ CurrThread.Client.MBitmaps.FreeBMP(Number);
+end;
+
+procedure SaveBitmap(Bmp : integer; path : string);
+begin;
+ CurrThread.Client.MBitmaps[Bmp].SaveToFile(Path);
+end;
+
+function BitmapFromString(Width,height : integer; Data : string) : integer;
+begin;
+ Result := CurrThread.Client.MBitmaps.CreateBMPFromString(Width,Height,Data);
+end;
+
+function LoadBitmap(Path : String) : integer;
+begin;
+ Result := CurrThread.Client.MBitmaps.CreateBMPFromFile(Path);
+end;
+
+procedure SetBitmapSize(Bmp,NewW,NewH : integer);
+begin;
+ if (NewW>=0) and (NewH >=0) then
+ CurrThread.Client.MBitmaps[Bmp].SetSize(NewW,NewH)
+ else
+ raise exception.createfmt('Wrong Width or Height in SetBitmapSize: (%d,%d)',[NewW,NewH]);
+end;
+
+procedure StretchBitmapResize(Bmp,NewW,NewH : integer);
+begin;
+ if (NewW>=0) and (NewH >=0) then
+ CurrThread.Client.MBitmaps[Bmp].StretchResize(NewW,NewH)
+ else
+ raise exception.createfmt('Wrong Width or Height in ScretchResize: (%d,%d)',[NewW,NewH]);
+end;
+
+procedure GetBitmapSize(Bmp : integer; out BmpW,BmpH : integer);
+begin;
+ With CurrThread.Client.MBitmaps[bmp] do
+ begin;
+ BmpW := width;
+ BmpH := Height;
+ end;
+end;
+
+procedure SetBitmapName(Bmp : integer; name : string);
+begin;
+ CurrThread.Client.MBitmaps[Bmp].BmpName:= name;
+end;
+
+function CreateMirroredBitmap(Bmp : integer) : integer;
+begin;
+ Result := CurrThread.Client.MBitmaps.CreateMirroredBitmap(Bmp, MirrorWidth);
+end;
+
+function CreateMirroredBitmapEx(Bmp : integer; MirrorStyle : TBmpMirrorStyle) : integer;
+begin;
+ Result := CurrThread.Client.MBitmaps.CreateMirroredBitmap(Bmp,MirrorStyle);
+end;
+
+function FastGetPixel(bmp,x,y : integer) : LongWord;
+begin;
+ Result := CurrThread.Client.MBitmaps[Bmp].FastGetPixel(x,y);
+end;
+
+function FastGetPixels(bmp : integer; TPA : TPointArray) : TIntegerArray;
+begin;
+ result := CurrThread.Client.MBitmaps[Bmp].FastGetPixels(TPA);
+end;
+
+procedure FastSetPixel(Bmp,x,y : integer; Color : TColor);
+begin
+ CurrThread.Client.MBitmaps[bmp].FastSetPixel(x,y,color);
+end;
+
+procedure FastSetPixels(Bmp : integer; TPA : TPointArray; Colors : TIntegerArray);
+begin;
+ CurrThread.Client.MBitmaps[Bmp].FastSetPixels(TPA,Colors);
+end;
+
+procedure DrawTPABitmap(bitmap : integer; TPA : TPointArray; Color : integer);
+begin
+ CurrThread.Client.MBitmaps[Bitmap].DrawTPA(TPA,Color);
+end;
+procedure DrawATPABitmap(bitmap : integer; ATPA : T2DPointArray);
+begin
+ CurrThread.Client.MBitmaps[bitmap].DrawATPA(ATPA);
+end;
+
+procedure DrawATPABitmapEx(bitmap : integer; ATPA : T2DPointArray; Colors : TIntegerArray);
+begin
+ CurrThread.Client.MBitmaps[bitmap].DrawATPA(ATPA,Colors);
+end;
+
+procedure FastDrawClear(bmp : integer; Color : TColor);
+begin;
+ CurrThread.Client.MBitmaps[bmp].FastDrawClear(Color);
+end;
+
+procedure FastDrawTransparent(x, y: Integer; SourceBitmap, TargetBitmap: Integer);
+begin;
+ CurrThread.Client.MBitmaps[SourceBitmap].FastDrawTransparent(x,y,CurrThread.Client.MBitmaps[TargetBitmap]);
+end;
+
+procedure SetTransparentColor(Bmp : integer; Color : TColor);
+begin
+ CurrThread.Client.MBitmaps[Bmp].SetTransparentColor(Color);
+end;
+
+function GetTransparentColor(Bmp : integer) : TColor;
+begin;
+ Result := CurrThread.Client.MBitmaps[bmp].GetTransparentColor;
+end;
+
+procedure FastReplaceColor(bmp: Integer; OldColor, NewColor: TColor);
+begin
+ CurrThread.Client.MBitmaps[Bmp].FastReplaceColor(OldColor,NewColor);
+end;
+
+procedure ps_CopyClientToBitmap(bmp, xs, ys, xe, ye: Integer);
+begin
+ CurrThread.Client.MBitmaps.GetBMP(bmp).CopyClientToBitmap(CurrThread.Client.IOManager, True, xs, ys, xe, ye);
+end;
+
+function BitmapFromClient(const xs, ys, xe, ye: Integer): Integer;
+begin;
+ result := CurrThread.Client.MBitmaps.CreateBMP(0,0);
+ CurrThread.Client.MBitmaps[result].CopyClientToBitmap(CurrThread.Client.IOManager,True,xs,ys,xe,ye);
+end;
+
+function FindBitmap(Bitmap: integer; out x, y: Integer): Boolean;
+begin;
+ with CurrThread.Client do
+ result := MFinder.FindBitmap( MBitmaps[bitmap],x,y);
+end;
+
+function FindBitmapIn(bitmap: integer; out x, y: Integer; xs, ys, xe, ye: Integer): Boolean;
+begin;
+ with CurrThread.Client do
+ result := MFinder.FindBitmapIn( MBitmaps[bitmap],x,y,xs,ys,xe,ye);
+end;
+
+function FindBitmapToleranceIn(bitmap: integer; out x, y: Integer; xs, ys, xe, ye: Integer; tolerance: Integer): Boolean;
+begin;
+ with CurrThread.Client do
+ result := MFinder.FindBitmapToleranceIn( MBitmaps[bitmap],x,y,xs,ys,xe,ye,tolerance);
+end;
+
+
+function FindBitmapSpiral(bitmap: Integer; var x, y: Integer; xs, ys, xe, ye: Integer): Boolean;
+begin;
+ with CurrThread.Client do
+ result := MFinder.FindBitmapSpiral(Mbitmaps[bitmap],x,y,xs,ys,xe,ye);
+end;
+
+function FindBitmapsSpiralTolerance(bitmap: integer; x, y: Integer; out Points : TPointArray; xs, ys, xe, ye,tolerance: Integer): Boolean;
+begin;
+ with CurrThread.Client do
+ result := MFinder.FindBitmapsSpiralTolerance(MBitmaps[bitmap],x,y,points,xs,ys,xe,ye,tolerance);
+end;
+
+function FindBitmapSpiralTolerance(bitmap: integer; var x, y: Integer; xs, ys, xe, ye,tolerance : integer): Boolean;
+begin;
+ with CurrThread.Client do
+ result := MFinder.FindBitmapSpiralTolerance(MBitmaps[bitmap],x,y,xs,ys,xe,ye,tolerance);
+end;
+
+function RotateBitmap(bitmap: Integer; angle: Extended): Integer;
+begin;
+ with CurrThread.Client.MBitmaps do
+ begin;
+ Result := CreateBMP(0,0);
+ Bmp[Bitmap].RotateBitmap(angle,Bmp[result]);
+ end;
+end;
+
+function Desaturate(Bitmap : integer) : integer;
+begin;
+ with CurrThread.Client.MBitmaps do
+ begin;
+ result := CreateBMP(0,0);
+ Bmp[Bitmap].Desaturate(Bmp[result]);
+ end;
+end;
+procedure InvertBitmap(Bitmap : integer);
+begin;
+ CurrThread.Client.MBitmaps[Bitmap].Invert;
+end;
+function CopyBitmap(Bitmap : integer) : integer;
+begin;
+ result := Currthread.Client.MBitmaps.CopyBMP(bitmap);
+end;
+function GreyScaleBitmap(Bitmap : integer) : integer;
+begin;
+ with CurrThread.Client.MBitmaps do
+ begin;
+ result := CreateBMP(0,0);
+ Bmp[Bitmap].GreyScale(Bmp[result]);
+ end;
+end;
+function BrightnessBitmap(Bitmap,br : integer) : integer;
+begin;
+ with CurrThread.Client.MBitmaps do
+ begin;
+ result := CreateBMP(0,0);
+ Bmp[Bitmap].Brightness(Bmp[result],br);
+ end;
+end;
+function ContrastBitmap(bitmap : integer; co : extended) : integer;
+begin;
+ with CurrThread.Client.MBitmaps do
+ begin;
+ result := CreateBMP(0,0);
+ Bmp[Bitmap].Contrast(Bmp[result],co);
+ end;
+end;
+
+function PosterizeBitmap(Bitmap : integer; po : integer) : integer;
+begin;
+ with CurrThread.Client.MBitmaps do
+ begin
+ result := CreateBMP(0,0);
+ Bmp[bitmap].Posterize(Bmp[result],po);
+ end;
+end;
+function CreateMaskFromBitmap(Bitmap : integer) : TMask;
+begin;
+ result := CurrThread.Client.MBitmaps[Bitmap].CreateTMask;
+end;
+
+function FindMaskTolerance(mask: TMask; out x, y: Integer; xs,ys, xe, ye: Integer; Tolerance, ContourTolerance: Integer): Boolean;
+begin;
+ result := CurrThread.Client.MFinder.FindMaskTolerance(Mask,x,y,xs,ys,xe,ye,tolerance,contourtolerance);
+end;
+function FindBitmapMaskTolerance(mask: Integer; out x, y: Integer; xs, ys, xe, ye: Integer; Tolerance, ContourTolerance: Integer): Boolean;
+begin;
+ psWriteln('Better be using FindMaskTolerance in combination with CreateMaskFromBitmap, more efficient.');
+ with CurrThread.Client do
+ result := MFinder.FindMaskTolerance(MBitmaps[mask].CreateTMask,x,y,xs,ys,xe,ye,tolerance,contourtolerance);
+end;
+
+function FindDeformedBitmapToleranceIn(bitmap: integer; out x,
+ y: Integer; xs, ys, xe, ye: Integer; tolerance: Integer; Range: Integer;
+ AllowPartialAccuracy: Boolean; out accuracy: Extended): Boolean;
+begin;
+ result := CurrThread.Client.MFinder.FindDeformedBitmapToleranceIn(CurrThread.Client.MBitmaps[Bitmap],x,y,xs,ys,xe,ye,tolerance,range,AllowPartialAccuracy,accuracy);
+end;
diff --git a/branches/script-component/Units/MMLAddon/PSInc/Wrappers/colour.inc b/branches/script-component/Units/MMLAddon/PSInc/Wrappers/colour.inc
new file mode 100644
index 0000000..30a3214
--- /dev/null
+++ b/branches/script-component/Units/MMLAddon/PSInc/Wrappers/colour.inc
@@ -0,0 +1,115 @@
+{
+ This file is part of the Mufasa Macro Library (MML)
+ Copyright (c) 2009 by Raymond van Venetië and Merlijn Wajer
+
+ MML is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ MML is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with MML. If not, see .
+
+ See the file COPYING, included in this distribution,
+ for details about the copyright.
+
+ Colour.inc for the Mufasa Macro Library
+}
+
+function GetColor(x,y : integer) : TColor;
+begin;
+ Result := CurrThread.Client.IOManager.GetColor(x,y);
+end;
+
+function GetColors(Coords : TPointArray) : TIntegerArray;
+begin
+ result := CurrThread.Client.MFinder.GetColors(coords);
+end;
+
+function findcolor(out x, y: integer; color, x1, y1, x2, y2: integer): boolean;
+begin
+ Result := CurrThread.Client.MFinder.FindColor(x, y, color, x1, y1, x2, y2);
+end;
+
+function findcolortoleranceOptimised(out x, y: integer; color, x1, y1, x2, y2, tol: integer): boolean;
+begin
+ Result := CurrThread.Client.MFinder.FindColorToleranceOptimised(x, y, color, x1, y1, x2, y2, tol);
+end;
+function findcolortolerance(out x, y: integer; color, x1, y1, x2, y2, tol: integer): boolean;
+begin
+ Result := CurrThread.Client.MFinder.FindColorTolerance(x, y, color, x1, y1, x2, y2, tol);
+end;
+
+function FindColors(out TPA: TPointArray; Color, x1, y1, x2, y2: Integer): Boolean;
+begin
+ Result := CurrThread.Client.MFinder.FindColors(TPA, color, x1, y1, x2, y2);
+end;
+
+procedure SetColorToleranceSpeed(cts: Integer);
+begin
+ CurrThread.Client.MFinder.SetToleranceSpeed(cts);
+end;
+
+function GetToleranceSpeed: Integer;
+begin
+ CurrThread.Client.MFinder.GetToleranceSpeed;
+end;
+
+procedure SetToleranceSpeed2Modifiers(nHue, nSat: Extended);
+begin
+ CurrThread.Client.MFinder.SetToleranceSpeed2Modifiers(nHue, nSat);
+end;
+
+procedure GetToleranceSpeed2Modifiers(out hMod, sMod: Extended);
+begin
+ CurrThread.Client.MFinder.GetToleranceSpeed2Modifiers(hMod, sMod);
+end;
+
+function SimilarColors(Col1,Col2,Tol : integer) : boolean;
+begin;
+ Result := CurrThread.Client.MFinder.SimilarColors(Col1,Col2,Tol);
+end;
+
+function CountColor(Color, xs, ys, xe, ye: Integer): Integer;
+begin;
+ result := CurrThread.Client.MFinder.CountColor(color,xs,ys,xe,ye);
+end;
+function CountColorTolerance(Color, xs, ys, xe, ye, Tolerance: Integer): Integer;
+begin;
+ result := CurrThread.Client.MFinder.CountColorTolerance(color,xs,ys,xe,ye,tolerance);
+end;
+
+function FindColorsToleranceOptimised(out Points: TPointArray; Color, xs, ys, xe, ye, Tolerance: Integer): Boolean;
+begin;
+ result := CurrThread.Client.MFinder.FindColorsToleranceOptimised(points,color,xs,ys,xe,ye,tolerance);
+end;
+function FindColorsTolerance(out Points: TPointArray; Color, xs, ys, xe, ye, Tolerance: Integer): Boolean;
+begin;
+ result := CurrThread.Client.MFinder.FindColorsTolerance(points,color,xs,ys,xe,ye,tolerance);
+end;
+
+function FindColorSpiral(var x, y: Integer; color, xs, ys, xe, ye: Integer): Boolean;
+begin;
+ result := CurrThread.Client.MFinder.FindColorSpiral(x,y,color,xs,ys,xe,ye);
+end;
+
+function FindColorsSpiralTolerance(x, y: Integer; out Points: TPointArray; color, xs, ys, xe, ye: Integer; Tolerance: Integer) : boolean;
+begin;
+ result := CurrThread.Client.MFinder.FindColorsSpiralTolerance(x,y,Points,color,xs,ys,xe,ye,tolerance);
+end;
+
+function FindColoredArea(var x, y: Integer; color, xs, ys, xe, ye: Integer; MinArea: Integer): Boolean;
+begin;
+ result := CurrThread.Client.MFinder.FindColoredArea(x,y,color,xs,ys,xe,ye,minarea);
+end;
+
+function FindColoredAreaTolerance(var x, y: Integer; Color, xs, ys, xe, ye, MinArea, tol: Integer): Boolean;
+begin;
+ result := CurrThread.Client.MFinder.FindColoredAreaTolerance(x,y,color,xs,ys,xe,ye,minarea,tol);
+end;
+
diff --git a/branches/script-component/Units/MMLAddon/PSInc/Wrappers/dtm.inc b/branches/script-component/Units/MMLAddon/PSInc/Wrappers/dtm.inc
new file mode 100644
index 0000000..5e7f77e
--- /dev/null
+++ b/branches/script-component/Units/MMLAddon/PSInc/Wrappers/dtm.inc
@@ -0,0 +1,116 @@
+{
+ This file is part of the Mufasa Macro Library (MML)
+ Copyright (c) 2009 by Raymond van Venetië and Merlijn Wajer
+
+ MML is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ MML is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with MML. If not, see .
+
+ See the file COPYING, included in this distribution,
+ for details about the copyright.
+
+ DTM.inc for the Mufasa Macro Library
+}
+
+function ps_FindDTM(DTM: Integer; out x, y: Integer; x1, y1, x2, y2: Integer): Boolean;
+var
+ temp: pDTM;
+begin
+ if CurrThread.Client.MDTM.GetDTM(DTM, temp) then
+ Result := CurrThread.Client.MFinder.FindDTM(temp, x, y, x1, y1, x2, y2)
+ else
+ begin
+ x := 0;
+ y := 0;
+ Result := False;
+ end;
+end;
+
+function ps_FindDTMs(DTM: Integer; out p: TPointArray; x1, y1, x2, y2: Integer): Boolean;
+var
+ temp: pDTM;
+begin
+ if CurrThread.Client.MDTM.GetDTM(DTM, temp) then
+ Result := CurrThread.Client.MFinder.FindDTMs(temp, p, x1, y1, x2, y2, 0)
+ else
+ begin
+ setlength(p,0);
+ Result := False;
+ end;
+end;
+
+function ps_FindDTMRotated(DTM: Integer; out x, y: Integer; x1, y1, x2, y2:
+ Integer; sAngle, eAngle, aStep: Extended;
+ out aFound: Extended): Boolean;
+var
+ temp: pDTM;
+begin
+ if CurrThread.Client.MDTM.GetDTM(DTM, temp) then
+ Result := CurrThread.Client.MFinder.FindDTMRotated(temp, x, y, x1, y1, x2, y2, sAngle, eAngle, aStep, aFound)
+ else
+ begin
+ x := 0;
+ y := 0;
+ Result := False;
+ end;
+end;
+
+function ps_FindDTMsRotated(DTM: Integer; out Points: TPointArray; x1, y1, x2, y2: Integer; sAngle, eAngle, aStep: Extended; out aFound: T2DExtendedArray): Boolean;
+var
+ temp: pDTM;
+begin
+ if CurrThread.Client.MDTM.GetDTM(DTM, temp) then
+ Result := CurrThread.Client.MFinder.FindDTMsRotated(temp, Points, x1, y1, x2, y2,
+ sAngle, eAngle, aStep, aFound, 0)
+ else
+ Result := False;
+end;
+
+{function ps_FindDTMsRotated(DTM: Integer; out Points: TPointArray; x1,
+ y1, x2, y2: Integer; sAngle, eAngle,
+ aStep: Extended; out aFound: T2DExtendedArray)
+ : Boolean;
+begin
+ Result := CurrThread.Client.MDTM.FindDTMsRotated(DTM, Points, x1, y1, x2, y2,
+ sAngle, eAngle, aStep, aFound);
+end; }
+
+function ps_DTMFromString(DTMString: String): Integer;
+var
+ dtm: pDTM;
+begin
+ With CurrThread.Client.MDTM do
+ begin
+ dtm := StringToDTM(DTMString);
+ Result := AddpDTM(dtm);
+ end;
+end;
+
+procedure ps_FreeDTM(DTM: Integer);
+begin
+ CurrThread.Client.MDTM.FreeDTM(DTM);
+end;
+
+function ps_GetDTM(index: Integer; out dtm: pDTM): Boolean;
+begin
+ Result := CurrThread.Client.MDTM.GetDTM(index, dtm);
+end;
+
+function ps_AddDTM(d: TDTM): Integer;
+begin
+ Result := CurrThread.Client.MDTM.AddDTM(d);
+end;
+
+function ps_AddpDTM(d: pDTM): Integer;
+begin
+ Result := CurrThread.Client.MDTM.AddpDTM(d);
+end;
diff --git a/branches/script-component/Units/MMLAddon/PSInc/Wrappers/file.inc b/branches/script-component/Units/MMLAddon/PSInc/Wrappers/file.inc
new file mode 100644
index 0000000..bc2ad57
--- /dev/null
+++ b/branches/script-component/Units/MMLAddon/PSInc/Wrappers/file.inc
@@ -0,0 +1,70 @@
+{
+ This file is part of the Mufasa Macro Library (MML)
+ Copyright (c) 2009 by Raymond van Venetië and Merlijn Wajer
+
+ MML is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ MML is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with MML. If not, see .
+
+ See the file COPYING, included in this distribution,
+ for details about the copyright.
+
+ File.inc for the Mufasa Macro Library
+}
+
+function ps_CreateFile(Path: string): Integer;
+begin
+ Result := CurrThread.Client.MFiles.CreateFile(Path);
+end;
+
+function ps_OpenFile(Path: string; Shared: Boolean): Integer;
+begin
+ Result := CurrThread.Client.MFiles.OpenFile(Path, Shared);
+end;
+
+function ps_RewriteFile(Path: string; Shared: Boolean): Integer;
+begin
+ Result := CurrThread.Client.MFiles.RewriteFile(Path, Shared);
+end;
+
+procedure ps_CloseFile(FileNum: Integer);
+begin
+ CurrThread.Client.MFiles.CloseFile(FileNum);
+end;
+
+function ps_EndOfFile(FileNum: Integer): Boolean;
+begin
+ Result := CurrThread.Client.MFiles.EndOfFile(FileNum);
+end;
+
+function ps_FileSize(FileNum: Integer): LongInt;
+begin
+ Result := CurrThread.Client.MFiles.FileSizeMuf(FileNum);
+end;
+
+function ps_ReadFileString(FileNum: Integer; out s: string; x: Integer): Boolean;
+begin
+ Result := CurrThread.Client.MFiles.ReadFileString(FileNum, s, x);
+end;
+
+function ps_WriteFileString(FileNum: Integer; s: string): Boolean;
+begin
+ Result := CurrThread.Client.MFiles.WriteFileString(FileNum, s);
+end;
+function ps_SetFileCharPointer(FileNum, cChars, Origin: Integer): Integer;
+begin
+ Result := CurrThread.Client.MFiles.SetFileCharPointer(Filenum, cChars, Origin);
+end;
+function ps_FilePointerPos(FileNum: Integer): Integer;
+begin
+ Result := CurrThread.Client.MFiles.FilePointerPos(FileNum);
+end;
diff --git a/branches/script-component/Units/MMLAddon/PSInc/Wrappers/internets.inc b/branches/script-component/Units/MMLAddon/PSInc/Wrappers/internets.inc
new file mode 100644
index 0000000..6d8af3d
--- /dev/null
+++ b/branches/script-component/Units/MMLAddon/PSInc/Wrappers/internets.inc
@@ -0,0 +1,4 @@
+function ps_GetPage(S: String): String;
+begin
+ result := GetPage(S);
+end;
diff --git a/branches/script-component/Units/MMLAddon/PSInc/Wrappers/keyboard.inc b/branches/script-component/Units/MMLAddon/PSInc/Wrappers/keyboard.inc
new file mode 100644
index 0000000..b6160e6
--- /dev/null
+++ b/branches/script-component/Units/MMLAddon/PSInc/Wrappers/keyboard.inc
@@ -0,0 +1,47 @@
+{
+ This file is part of the Mufasa Macro Library (MML)
+ Copyright (c) 2009 by Raymond van Venetië and Merlijn Wajer
+
+ MML is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ MML is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with MML. If not, see .
+
+ See the file COPYING, included in this distribution,
+ for details about the copyright.
+
+ Keyboard.inc for the Mufasa Macro Library
+}
+
+procedure KeyDown(key: Word);
+begin
+ CurrThread.Client.IOManager.KeyDown(key);
+end;
+
+procedure KeyUp(key: Word);
+begin
+ CurrThread.Client.IOManager.KeyUp(key);
+end;
+
+procedure SendKeys(s: string);
+begin
+ CurrThread.Client.IOManager.SendText(s);
+end;
+
+procedure PressKey(key: Word);
+begin
+ CurrThread.Client.IOManager.PressKey(key);
+end;
+
+function isKeyDown(key: Word): boolean;
+begin
+ Result := CurrThread.Client.IOManager.isKeyDown(key);
+end;
diff --git a/branches/script-component/Units/MMLAddon/PSInc/Wrappers/math.inc b/branches/script-component/Units/MMLAddon/PSInc/Wrappers/math.inc
new file mode 100644
index 0000000..dbe9785
--- /dev/null
+++ b/branches/script-component/Units/MMLAddon/PSInc/Wrappers/math.inc
@@ -0,0 +1,64 @@
+{
+ This file is part of the Mufasa Macro Library (MML)
+ Copyright (c) 2009 by Raymond van Venetië and Merlijn Wajer
+
+ MML is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ MML is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with MML. If not, see .
+
+ See the file COPYING, included in this distribution,
+ for details about the copyright.
+
+ Math.inc for the Mufasa Macro Library
+}
+
+function psSqr( e : extended) : extended;
+begin;
+ result := sqr(e);
+end;
+
+function ps_RandomRange(const aFrom, aTo: Integer): Integer;
+begin
+ Result:=Random(Abs(aFrom-aTo))+Min(aTo,AFrom);
+end;
+
+function Factorial(number: longword): Int64;
+var
+ Loop : longword;
+begin
+ result := 1;
+ for loop := number downto 2 do
+ result := result * loop;
+end;
+
+function BinCoe(a, b: LongInt): Extended;
+begin
+ result := Factorial(a) / (factorial(b) * factorial(a-b));
+end;
+
+function FixD(Degrees : extended) : Extended;
+begin;
+ Result := Degrees;
+ while Result < 0 do
+ Result := Result + 360;
+ while Result > 360 do
+ Result := Result - 360;
+end;
+
+procedure psSwap(var A,B);
+var
+ TempPtr : Pointer;
+begin;
+ TempPtr := pointer(A);
+ pointer(a) := pointer(b);
+ pointer(b) := TempPtr;
+end;
diff --git a/branches/script-component/Units/MMLAddon/PSInc/Wrappers/mouse.inc b/branches/script-component/Units/MMLAddon/PSInc/Wrappers/mouse.inc
new file mode 100644
index 0000000..495b98e
--- /dev/null
+++ b/branches/script-component/Units/MMLAddon/PSInc/Wrappers/mouse.inc
@@ -0,0 +1,61 @@
+{
+ This file is part of the Mufasa Macro Library (MML)
+ Copyright (c) 2009 by Raymond van Venetië and Merlijn Wajer
+
+ MML is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ MML is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with MML. If not, see .
+
+ See the file COPYING, included in this distribution,
+ for details about the copyright.
+
+ Mouse.inc for the Mufasa Macro Library
+}
+
+const
+ ps_mouse_right = 0;
+ ps_mouse_left = 1;
+ ps_mouse_middle = 2;
+procedure MoveMouse(x, y: integer);
+begin
+ CurrThread.Client.IOManager.SetMousePos(X, Y);
+end;
+
+procedure GetMousePos(out x, y: integer);
+begin
+ CurrThread.Client.IOManager.GetMousePos(X, Y);
+end;
+function ConvIntClickType(Int : Integer) : TClickType;inline;
+begin;
+ case int of
+ ps_mouse_right : result := mouse_Right;
+ ps_mouse_left : result := mouse_left;
+ ps_mouse_middle: result := mouse_middle;
+ else
+ raise exception.CreateFMT('Unknown Clicktype (%d) passed.',[int]);
+ end;
+end;
+
+procedure HoldMouse(x, y: integer; clickType: integer);
+begin
+ CurrThread.Client.IOManager.HoldMouse(x, y, ConvIntClickType(clickType));
+end;
+
+procedure ReleaseMouse(x, y: integer; clickType: integer);
+begin
+ CurrThread.Client.IOManager.ReleaseMouse(x, y, ConvIntClickType(clickType));
+end;
+
+procedure ClickMouse(x, y: integer; clickType: integer);
+begin
+ CurrThread.Client.IOManager.ClickMouse(x, y, ConvIntClickType(clickType));
+end;
diff --git a/branches/script-component/Units/MMLAddon/PSInc/Wrappers/ocr.inc b/branches/script-component/Units/MMLAddon/PSInc/Wrappers/ocr.inc
new file mode 100644
index 0000000..d416322
--- /dev/null
+++ b/branches/script-component/Units/MMLAddon/PSInc/Wrappers/ocr.inc
@@ -0,0 +1,25 @@
+function rs_GetUpText: String;
+begin
+ Result := CurrThread.Client.MOCR.GetUpTextAtEx(7, 7, true);
+end;
+
+function BitmapFromText(text, font: String): integer;
+var
+ bmp: TMufasaBitmap;
+begin
+ writeln('BitmapFromText: ' + text + ' ' + font);
+ bmp := CurrThread.Client.MOCR.TextToFontBitmap(text, font);
+ Result := CurrThread.Client.MBitmaps.AddBMP(bmp);
+end;
+
+function MaskFromText(text, font: String): TMask;
+begin
+ Result := CurrThread.Client.MOCR.TextToMask(text,font);
+end;
+
+function TPAFromText(text, font: String): TPointArray;
+var
+ w,h : integer;
+begin
+ Result := CurrThread.Client.MOCR.TextToFontTPA(text, font, w, h);
+end;
diff --git a/branches/script-component/Units/MMLAddon/PSInc/Wrappers/other.inc b/branches/script-component/Units/MMLAddon/PSInc/Wrappers/other.inc
new file mode 100644
index 0000000..117220e
--- /dev/null
+++ b/branches/script-component/Units/MMLAddon/PSInc/Wrappers/other.inc
@@ -0,0 +1,129 @@
+{
+ This file is part of the Mufasa Macro Library (MML)
+ Copyright (c) 2009 by Raymond van Venetië and Merlijn Wajer
+
+ MML is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ MML is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with MML. If not, see .
+
+ See the file COPYING, included in this distribution,
+ for details about the copyright.
+
+ Other.inc for the Mufasa Macro Library
+}
+
+procedure psWait(t: Integer);
+{$ifdef MSWINDOWS}
+begin
+ Sleep(t);
+end;
+{$else}
+var
+ EndTime : DWord;
+begin
+ if t > 50 then
+ begin;
+ EndTime := GetTickCount + t;
+ while (CurrThread.PSScript.Exec.Status = isRunning) and (GetTickCount < EndTime) do
+ Sleep(16);
+ end else
+ begin
+ sleep(t);
+ end;
+end;
+{$endif}
+
+procedure ClearDebug;
+begin
+ if Assigned(CurrThread.DebugMemo) then
+ CurrThread.Synchronize(@CurrThread.DebugMemo.Clear);
+end;
+
+procedure SaveScreenshot(FileName: string);
+var
+ w,h : integer;
+ bmp: TMufasaBitmap;
+begin;
+ CurrThread.Client.IOManager.GetDimensions(w,h);
+ bmp := TMufasaBitmap.Create;
+ bmp.CopyClientToBitmap(CurrThread.Client.IOManager,True,0,0,w-1,h-1);
+ bmp.SaveToFile(FileName);
+ bmp.Free;
+end;
+
+function MinE(a, b: Extended): Extended;
+begin;
+ result := min(a,b);
+end;
+
+function IntToBox(x1,y1,x2,y2 : integer) : TBox;
+begin;
+ result.x1 := x1;
+ result.y1 := y1;
+ result.x2 := x2;
+ result.y2 := y2;
+end;
+
+function IntInBox(x, y: Integer; Box: TBox): Boolean;
+begin;
+ result := (((x >= Box.x1) and(x <= Box.x2)) and ((y >= box.y1) and (y <= box.y2)));
+end;
+
+function Distance(x1, y1, x2, y2: Integer): Integer;
+begin;
+ Result := Round(Sqrt(Sqr(x2-x1) + Sqr(y2-y1)));
+end;
+
+procedure DisplayDebugImgWindow(w,h : integer);
+begin;
+ CurrThread.DebugImg.DispSize^ := Classes.Point(w,h);
+ CurrThread.Synchronize( CurrThread.DebugImg.ShowForm);
+end;
+
+procedure DrawBitmapDebugImg(bmp : integer);
+begin;
+ CurrThread.DebugImg.ToDrawBitmap^ := CurrThread.Client.MBitmaps[bmp];
+ CurrThread.Synchronize(CurrThread.DebugImg.DrawBitmap);
+end;
+
+function GetDebugBitmap : integer;
+begin;
+ result := CurrThread.Client.MBitmaps.CreateBMP(0,0);
+ CurrThread.DebugImg.GetDebugBitmap^ := CurrThread.Client.MBitmaps[result];
+ CurrThread.Synchronize(CurrThread.DebugImg.GetBitmap);
+end;
+
+procedure TerminateScript;
+begin;
+ CurrThread.PSScript.Stop;
+end;
+function GetTimeRunning: LongWord;
+begin;
+ result := GetTickCount - CurrThread.StartTime;
+end;
+
+procedure ConvertTime(Time : integer; var h,m,s : integer);
+var
+ x : integer;
+begin;
+ x := time;
+ h := x div(1000 * 60 * 60);
+ x := x mod (1000 * 60 * 60);
+ m := x div (1000 * 60);
+ x := x mod (1000 * 60);
+ s := x div (1000);
+end;
+
+procedure HakunaMatata;
+begin;
+ OpenWebPage('http://www.youtube.com/v/ejEVczA8PLU&hl=en&fs=1&autoplay=1');
+end;
diff --git a/branches/script-component/Units/MMLAddon/PSInc/Wrappers/strings.inc b/branches/script-component/Units/MMLAddon/PSInc/Wrappers/strings.inc
new file mode 100644
index 0000000..d33bfc5
--- /dev/null
+++ b/branches/script-component/Units/MMLAddon/PSInc/Wrappers/strings.inc
@@ -0,0 +1,26 @@
+function psFormat(const fmt : string;const args : array of const) : string;
+begin;
+ Result := Format(fmt,Args);
+end;
+
+function Capitalize(str : string) : string;
+var
+ i , l : integer;
+ cap : boolean;
+begin;
+ result := str;
+ l := length(str);
+ cap := true;
+ for i := 1 to l do
+ if cap and (str[i] in ['a'..'z'] + ['A'..'Z']) then
+ begin;
+ result[i] := UpperCase(str[i])[1];
+ cap := false;
+ end else if not (str[i] in ['a'..'z'] + ['A'..'Z']) then
+ cap := true;
+end;
+
+function psBoolToStr(bool : boolean) : string;
+begin;
+ result := BoolToStr(bool,true);
+end;
diff --git a/branches/script-component/Units/MMLAddon/PSInc/Wrappers/window.inc b/branches/script-component/Units/MMLAddon/PSInc/Wrappers/window.inc
new file mode 100644
index 0000000..94cef68
--- /dev/null
+++ b/branches/script-component/Units/MMLAddon/PSInc/Wrappers/window.inc
@@ -0,0 +1,64 @@
+{
+ This file is part of the Mufasa Macro Library (MML)
+ Copyright (c) 2009 by Raymond van Venetië and Merlijn Wajer
+
+ MML is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ MML is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with MML. If not, see .
+
+ See the file COPYING, included in this distribution,
+ for details about the copyright.
+
+ window.inc for the Mufasa Macro Library
+}
+
+procedure SetDesktopAsClient;
+begin;
+ CurrThread.Client.IOManager.SetDesktop;
+end;
+
+procedure SetTargetArray(P: Integer; w, h: integer);
+begin
+ CurrThread.Client.IOManager.SetTarget(PRGB32(P), classes.point(w,h));
+end;
+
+procedure SetTargetBitmap(bitmap: Integer);
+begin;
+ CurrThread.Client.IOManager.SetTarget(CurrThread.Client.MBitmaps[Bitmap]);
+end;
+
+procedure GetClientDimensions(out w, h: integer);
+begin
+ CurrThread.Client.IOManager.GetDimensions(w, h);
+end;
+
+function Freeze: boolean;
+begin
+ CurrThread.Client.IOManager.SetFrozen(true);
+ result := true; //dunno what the result is supposed to mean
+end;
+
+function Unfreeze: boolean;
+begin
+ CurrThread.Client.IOManager.SetFrozen(false);
+ result := true; //dunno what the result is supposed to mean
+end;
+
+procedure ActivateClient;
+begin
+ CurrThread.Client.IOManager.ActivateClient;
+end;
+
+function IsTargetValid: boolean;
+begin
+ result:= CurrThread.Client.IOManager.TargetValid;
+end;
diff --git a/branches/script-component/Units/MMLAddon/PSInc/pscompile.inc b/branches/script-component/Units/MMLAddon/PSInc/pscompile.inc
new file mode 100644
index 0000000..00fffa8
--- /dev/null
+++ b/branches/script-component/Units/MMLAddon/PSInc/pscompile.inc
@@ -0,0 +1,53 @@
+{
+ This file is part of the Mufasa Macro Library (MML)
+ Copyright (c) 2009 by Raymond van Venetië and Merlijn Wajer
+
+ MML is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ MML is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with MML. If not, see .
+
+ See the file COPYING, included in this distribution,
+ for details about the copyright.
+
+ PSCompile.inc for the Mufasa Macro Library
+}
+
+Sender.Comp.AddConstantN('AppPath','string').SetString(CurrThread.AppPath);
+Sender.Comp.AddConstantN('ScriptPath','string').SetString(CurrThread.ScriptPath);
+Sender.Comp.AddConstantN('IncludePath','string').SetString(CurrThread.IncludePath);
+Sender.Comp.AddConstantN('PluginPath','string').SetString(CurrThread.PluginPath);
+Sender.Comp.AddConstantN('FontPath','string').SetString(CurrThread.FontPath);
+Sender.Comp.AddTypeS('TIntegerArray', 'Array of LongInt');
+Sender.Comp.AddTypeS('TExtendedArray','Array of extended');
+Sender.Comp.AddTypeS('TBoolArray', 'Array of Boolean');
+Sender.Comp.AddTypes('TBox', 'record X1,Y1,X2,Y2 : Integer; end;');
+Sender.Comp.AddTypeS('TPointArray','Array of TPoint');
+Sender.Comp.AddTypeS('T2DPointArray','Array of Array of TPoint');
+Sender.Comp.AddTypeS('TPointArrayArray','Array of Array of TPoint');
+Sender.Comp.AddTypeS('TBmpMirrorStyle','(MirrorWidth,MirrorHeight,MirrorLine)');
+Sender.Comp.AddTypeS('TMask','record White, Black : TPointArray; WhiteHi,BlackHi : integer; W,H : integer;end;');
+Sender.Comp.addtypeS('PPoint','record R,T : extended; end;');
+
+Sender.Comp.AddTypes('TDTMPointDef', 'record x, y, Color, Tolerance, AreaSize, AreaShape: integer; end;');
+Sender.Comp.AddTypes('TDTMPointDefArray', 'Array Of TDTMPointDef;');
+Sender.Comp.AddTypes('TDTM','record MainPoint: TDTMPointDef; SubPoints: TDTMPointDefArray; end;');
+Sender.Comp.AddTypeS('pDTM','record l: Integer;p: TPointArray;c, t, asz, ash: TIntegerArray; bp: Array Of Boolean; n: String; end;');
+
+Sender.Comp.AddTypeS('T2DExtendedArray', 'array of array of extended;');
+Sender.Comp.AddTypeS('TStringArray','Array of string;');
+Sender.Comp.AddTypeS('TMousePress', '(mouse_Down, mouse_Up);');
+Sender.Comp.AddTypeS('Pointer', 'Integer');
+
+
+Sender.Comp.AddConstantN('mouse_Right','integer').SetInt(ps_mouse_right); //0
+Sender.Comp.AddConstantN('mouse_Left','integer').SetInt(ps_mouse_left);//1
+Sender.Comp.AddConstantN('mouse_Middle','integer').SetInt(ps_mouse_middle);//2
diff --git a/branches/script-component/Units/MMLAddon/PSInc/psdefines.inc b/branches/script-component/Units/MMLAddon/PSInc/psdefines.inc
new file mode 100644
index 0000000..455fe56
--- /dev/null
+++ b/branches/script-component/Units/MMLAddon/PSInc/psdefines.inc
@@ -0,0 +1,38 @@
+{
+ This file is part of the Mufasa Macro Library (MML)
+ Copyright (c) 2009 by Raymond van Venetië and Merlijn Wajer
+
+ MML is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ MML is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with MML. If not, see .
+
+ See the file COPYING, included in this distribution,
+ for details about the copyright.
+
+ PSDefines.inc for the Mufasa Macro Library
+}
+
+{$IFDEF CPU386 }
+PSScript.Defines.Add('CPU386');
+{$ENDIF }
+PSScript.Defines.Add('MUFASA');
+PSScript.Defines.Add('COGAT');
+PSScript.Defines.Add('SIMBA');
+PSScript.Defines.Add('RAYMONDPOWNS');
+{$IFDEF MSWINDOWS }
+PSScript.Defines.Add('MSWINDOWS');
+PSScript.Defines.Add('WIN32');
+PSScript.Defines.Add('WINDOWS');
+{$ENDIF }
+{$IFDEF LINUX }
+PSScript.Defines.Add('LINUX');
+{$ENDIF }
diff --git a/branches/script-component/Units/MMLAddon/PSInc/psexportedmethods.inc b/branches/script-component/Units/MMLAddon/PSInc/psexportedmethods.inc
new file mode 100644
index 0000000..0c0e489
--- /dev/null
+++ b/branches/script-component/Units/MMLAddon/PSInc/psexportedmethods.inc
@@ -0,0 +1,288 @@
+{
+ This file is part of the Mufasa Macro Library (MML)
+ Copyright (c) 2009 by Raymond van Venetië and Merlijn Wajer
+
+ MML is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ MML is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with MML. If not, see .
+
+ See the file COPYING, included in this distribution,
+ for details about the copyright.
+
+ psexportedmethods.inc for the Mufasa Macro Library
+}
+
+AddFunction(@ThreadSafeCall,'function ThreadSafeCall(ProcName: string; var V: TVariantArray): Variant;');
+AddFunction(nil,'procedure Writeln(x);'); //We use special function for this
+
+{ DTM }
+SetCurrSection('DTM');
+AddFunction(@PrintpDTM, 'Procedure PrintpDTM(tDTM : pDTM);');
+AddFunction(@ps_GetDTM ,'function GetDTM(index: Integer; out dtm: pDTM): Boolean;');
+AddFunction(@pDTMToTDTM, 'Function pDTMToTDTM(DTM: pDTM): TDTM;');
+AddFunction(@tDTMTopDTM, 'Function tDTMTopDTM(DTM: TDTM): pDTM;');
+AddFunction(@ps_DTMFromString, 'function DTMFromString(DTMString: String): Integer;');
+AddFunction(@ps_FreeDTM, 'procedure FreeDTM(DTM: Integer);');
+AddFunction(@ps_FindDTM, 'function FindDTM(DTM: Integer; out x, y: Integer; x1, y1, x2, y2: Integer): Boolean;');
+AddFunction(@ps_FindDTMs, 'function FindDTMs(DTM: Integer; out p: TPointArray; x1, y1, x2, y2: Integer): Boolean;');
+AddFunction(@ps_FindDTMRotated, 'function FindDTMRotated(DTM: Integer; out x, y: Integer; x1, y1, x2, y2: Integer; sAngle, eAngle, aStep: Extended; out aFound: Extended): Boolean;');
+AddFunction(@ps_FindDTMsRotated, 'function FindDTMsRotated(DTM: Integer; out Points: TPointArray; x1, y1, x2, y2: Integer; sAngle, eAngle, aStep: Extended; out aFound: T2DExtendedArray) : Boolean;');
+AddFunction(@ps_addDTM, 'function AddDTM(d: TDTM): Integer;');
+AddFunction(@ps_addpDTM, 'function AddpDTM(d: pDTM): Integer;');
+
+{maths}
+SetCurrSection('Math');
+AddFunction(nil,'function Round(e:extended) : integer');
+AddFunction(@ceil,'function ceil(e : extended) : integer');
+AddFunction(@power,'function pow(base,exponent : extended) : extended');
+AddFunction(@max,'function Max(a, b: Integer): Integer;');
+AddFunction(@min,'function Min(a, b: Integer): Integer;');
+AddFunction(@minE,'function MinE(a, b: extended): Extended;');
+AddFunction(@IntToBox,'function IntToBox(x1,y1,x2,y2 : integer) : TBox;');
+AddFunction(@IntInBox,'function IntInBox(x, y: Integer; Box: TBox): Boolean;');
+AddFunction(@pssqr,'function Sqr(e : extended) : extended;');
+AddFunction(@classes.point,'function Point(x,y:integer) : TPoint;');
+AddFunction(@Distance,'function Distance(x1,y1,x2,y2 : integer) : integer;');
+AddFunction(@hypot,'function Hypot(X, Y: Extended): Extended;');
+AddFunction(@ps_RandomRange,'function RandomRange(aFrom,aTo: Integer): Integer;');
+AddFunction(@BinCoe,'function BinCoe(a, b: LongInt): Extended;');
+AddFunction(@FixD,'function FixD(Degrees : extended) : Extended;');
+AddFunction(@InRange,'function InRange(value,min,max : integer) : boolean;');
+
+{window}
+SetCurrSection('Window');
+AddFunction(@Freeze, 'function Freeze: boolean;');
+AddFunction(@Unfreeze, 'function Unfreeze: boolean;');
+AddFunction(@GetClientDimensions, 'procedure GetClientDimensions(var w, h:integer);');
+AddFunction(@SetTargetBitmap,'procedure SetTargetBitmap(Bitmap : integer);');
+AddFunction(@SetDesktopAsClient,'procedure SetDesktopAsClient');
+AddFunction(@SetTargetArray, 'procedure SetTargetArray(P: Integer; w, h: integer);');
+AddFunction(@ActivateClient, 'procedure ActivateClient;');
+AddFunction(@IsTargetValid, 'function IsTargetValid: boolean;');
+
+{files}
+SetCurrSection('Files');
+AddFunction(@ps_CreateFile, 'function CreateFile(Path: string): Integer;');
+AddFunction(@ps_OpenFile, 'function OpenFile(Path: string; Shared: Boolean): Integer;');
+AddFunction(@ps_RewriteFile, 'function RewriteFile(Path: string; Shared: Boolean): Integer;');
+AddFunction(@ps_CloseFile, 'procedure CloseFile(FileNum: Integer);');
+AddFunction(@ps_EndOfFile, 'function EndOfFile(FileNum: Integer): Boolean;');
+AddFunction(@ps_FileSize, 'function FileSize(FileNum: Integer): LongInt;');
+AddFunction(@ps_ReadFileString, 'function ReadFileString(FileNum: Integer; out s: string; x: Integer): Boolean;');
+AddFunction(@ps_WriteFileString, 'function WriteFileString(FileNum: Integer; s: string): Boolean;');
+AddFunction(@ps_SetFileCharPointer, 'Function SetFileCharPointer(FileNum, cChars, Origin: Integer): Integer;');
+AddFunction(@ps_FilePointerPos, 'function FilePointerPos(FileNum: Integer): Integer;');
+
+{other}
+SetCurrSection('Other');
+AddFunction(@SaveScreenshot,'procedure SaveScreenshot(FileName: string);');
+AddFunction(@psWait, 'procedure wait(t: integer);');
+AddFunction(@psWait, 'procedure Sleep(t: integer);');
+AddFunction(@GetTickCount, 'function GetSystemTime: LongWord;');
+AddFunction(@GetTickCount, 'function GetTickCount: LongWord;');
+AddFunction(@GetTimeRunning,'function GetTimeRunning: LongWord;');
+AddFunction(@ConvertTime,'procedure ConvertTime(Time: integer; var h, m, s: integer);');
+AddFunction(@HakunaMatata,'procedure HakunaMatata;');
+AddFunction(@TerminateScript,'procedure TerminateScript;');
+AddFunction(@DisplayDebugImgWindow,'procedure DisplayDebugImgWindow(w, h: integer);');
+AddFunction(@DrawBitmapDebugImg,'procedure DrawBitmapDebugImg(bmp: integer);');
+AddFunction(@GetDebugBitmap,'function GetDebugBitmap: integer;');
+AddFunction(@Random,'function Random(Int: integer): integer;');
+AddFunction(@NewThreadCall,'function NewThreadCall(procname : string) : cardinal');
+AddFunction(@ClearDebug,'procedure ClearDebug;');
+
+
+
+{string}
+SetCurrSection('String');
+AddFunction(@Capitalize,'function Capitalize(str : string) : string;');
+AddFunction(@psFormat,'function Format(const fmt : string;const args : array of const) : string;');
+AddFunction(nil,'function ToStr(x) : string;');
+AddFunction(@IntToStr, 'function IntToStr(value: Integer): String;');
+AddFunction(@FloatToStr, 'function FloatToStr(value: Extended): String;');
+AddFunction(@psBoolToStr, 'function BoolToStr(value: Boolean): String;');
+AddFunction(@StrToInt, 'function StrToInt(value: String): Integer;');
+AddFunction(@StrToIntDef, 'function StrToIntDef(value: String; default: Integer): Integer;');
+AddFunction(@StrToFloat, 'function StrToFloat(value: String): Extended;');
+AddFunction(@StrToFloatDef, 'function StrToFloatDef(value: String; default: Extended): Extended;');
+AddFunction(@StrToBool, 'function StrToBool(value: String): Boolean;');
+AddFunction(@StrToBoolDef, 'function StrToBoolDef(value: String; default: Boolean): Boolean;');
+
+{web}
+SetCurrSection('Web');
+AddFunction(@OpenWebPage,'procedure OpenWebPage(url : string);');
+AddFunction(@ps_GetPage,'function GetPage(url : string): string;');
+
+
+{ Color Conversions and Speed }
+SetCurrSection('Color Convert');
+AddFunction(@Colour_Conv.ColorToRGB, 'procedure ColorToRGB(Color: integer; out r, g, b: Byte);');
+AddFunction(@Colour_conv.RGBToColor, 'function RGBtoColor(r, g, b: Byte): TColor;');
+AddFunction(@Colour_conv.ColorToHSL, 'procedure ColorToHSL(Color: Integer; out h, s, l: Extended);');
+AddFunction(@Colour_conv.HSLToColor, 'function HSLToColor(H, S, L: Extended): TColor;');
+AddFunction(@Colour_conv.ColorToXYZ, 'procedure ColorToXYZ(Color: Integer; out x, y, z: Extended);');
+AddFunction(@Colour_conv.XYZToColor, 'function XYZToColor(X, Y, Z: Extended): TColor;');
+AddFunction(@Colour_conv.RGBToHSL, 'procedure RGBToHSL(R, G, B: Byte; out h, s, l: Extended);');
+AddFunction(@Colour_conv.HSLToRGB, 'procedure HSLtoRGB(H, S, L: extended; out R, G ,B: Byte);');
+AddFunction(@Colour_conv.RGBToXYZ, 'procedure RGBToXYZ(R, G, B: Byte;out x, y ,z: Extended);');
+AddFunction(@Colour_conv.XYZToRGB, 'procedure XYZToRGB(X, Y, Z: Extended; out R, G, B: Byte);');
+
+{ Color Finding }
+SetCurrSection('Color');
+AddFunction(@SetColorToleranceSpeed, 'procedure SetColorToleranceSpeed(cts: integer);');
+AddFunction(@GetToleranceSpeed, 'function GetToleranceSpeed: Integer;');
+AddFunction(@SetToleranceSpeed2Modifiers, 'procedure SetToleranceSpeed2Modifiers(nHue, nSat: Extended);');
+AddFunction(@GetToleranceSpeed2Modifiers, 'procedure GetToleranceSpeed2Modifiers(out hMod, sMod: Extended);');
+AddFunction(@GetColor,'function GetColor(x, y: Integer): Integer;');
+AddFunction(@GetColors,'function GetColors(Coords : TPointArray) : TIntegerArray;');
+AddFunction(@FindColor, 'function FindColor(out x, y: integer; color, x1, y1, x2, y2: integer): boolean;');
+AddFunction(@findcolortoleranceOptimised, 'function FindColorToleranceOptimised(out x, y: integer; color, x1, y1, x2, y2, tol: integer): boolean;');
+AddFunction(@FindColorTolerance, 'function FindColorTolerance(out x, y: integer; color, x1, y1, x2, y2, tol: integer): boolean;');
+AddFunction(@FindColors, 'function FindColors(out TPA: TPointArray; color, x1, y1, x2, y2: integer): boolean;');
+AddFunction(@SimilarColors,'function SimilarColors(Col1, Col2, Tolerance: integer): boolean');
+AddFunction(@CountColor,'function CountColor(Color, xs, ys, xe, ye: Integer): Integer;');
+AddFunction(@CountColorTolerance,'function CountColorTolerance(Color, xs, ys, xe, ye, Tolerance: Integer): Integer;');
+AddFunction(@FindColorsToleranceOptimised,'function FindColorsToleranceOptimised(out Points: TPointArray; Color, xs, ys, xe, ye, Tolerance: Integer): Boolean;');
+AddFunction(@FindColorsTolerance,'function FindColorsTolerance(out Points: TPointArray; Color, xs, ys, xe, ye, Tolerance: Integer): Boolean;');
+AddFunction(@FindColorSpiral,'function FindColorSpiral(var x, y: Integer; color, xs, ys, xe, ye: Integer): Boolean;');
+AddFunction(@FindColorsSpiralTolerance,'function FindColorsSpiralTolerance(x, y: Integer; out Points: TPointArray; color, xs, ys, xe, ye: Integer; Tolerance: Integer) : boolean;');
+AddFunction(@FindColoredArea, 'function FindColoredArea(var x, y: Integer; color, xs, ys, xe, ye, MinArea: Integer): Boolean');
+AddFunction(@FindColoredAreaTolerance, 'function FindColoredAreaTolerance(var x, y : Integer; color, xs, ys, xe, ye, MinArea, Tolerance : Integer): Boolean');
+
+{Mouse etc.}
+SetCurrSection('Mouse');
+AddFunction(@MoveMouse, 'procedure MoveMouse(x, y: integer);');
+AddFunction(@GetMousePos, 'procedure GetMousePos(out x, y: integer);');
+AddFunction(@HoldMouse, 'procedure HoldMouse(x, y: integer; clickType: integer);');
+AddFunction(@ReleaseMouse, 'procedure ReleaseMouse(x, y: integer; clickType: integer);');
+AddFunction(@ClickMouse, 'procedure ClickMouse(x, y: integer; clickType: integer);');
+
+
+{Keyboard}
+SetCurrSection('Keyboard');
+AddFunction(@KeyDown, 'procedure KeyDown(key: Word);');
+AddFunction(@KeyUp, 'procedure KeyUp(key: Word);');
+AddFunction(@PressKey, 'procedure PressKey(key: Word);');
+AddFunction(@SendKeys, 'procedure SendKeys(s: string);');
+AddFunction(@isKeyDown, 'function IsKeyDown(key: Word): Boolean;');
+
+{ OCR}
+SetCurrSection('OCR');
+AddFunction(@rs_GetUpText, 'function rs_GetUpText: string;');
+AddFunction(@BitmapFromText, 'function BitmapFromText(text, font: String): integer;');
+AddFunction(@TPAFromText, 'function TPAFromText(text, font: String): TPointArray;');
+AddFunction(@MaskFromText, 'function MaskFromText(text, font: String): TMask;');
+
+{Bitmaps}
+SetCurrSection('Bitmaps');
+AddFunction(@CreateBitmapString,'function CreateBitmapString(bmp : integer) : string;');
+AddFunction(@GetMufasaBitmap,'function GetMufasaBitmap(bmp : integer) : TMufasaBitmap;');
+AddFunction(@CreateBitmap,'function CreateBitmap(w,h :integer) : integer;');
+AddFunction(@FreeBitmap,'procedure FreeBitmap(Bmp : integer);');
+AddFunction(@SaveBitmap,'procedure SaveBitmap(Bmp : integer; path : string);');
+AddFunction(@BitmapFromString,'function BitmapFromString(Width,Height : integer; Data : string): integer;');
+AddFunction(@LoadBitmap,'function LoadBitmap(Path : string) : integer;');
+AddFunction(@SetBitmapSize,'procedure SetBitmapSize(Bmp,NewW,NewH : integer);');
+AddFunction(@GetBitmapSize,'procedure GetBitmapSize(Bmp : integer; out BmpW,BmpH : integer);');
+AddFunction(@StretchBitmapResize,'procedure StretchBitmapResize(Bmp,NewW,NewH : integer);');
+AddFunction(@CreateMirroredBitmap,'function CreateMirroredBitmap(Bmp : integer) : integer;');
+AddFunction(@CreateMirroredBitmapEx,'function CreateMirroredBitmapEx(Bmp : integer; MirrorStyle : TBmpMirrorStyle) : integer;');
+AddFunction(@FastSetPixel,'procedure FastSetPixel(bmp,x,y : integer; Color : TColor);');
+AddFunction(@FastSetPixels,'procedure FastSetPixels(bmp : integer; TPA : TPointArray; Colors : TIntegerArray);');
+AddFunction(@FastGetPixel,'function FastGetPixel(bmp, x,y : integer) : TColor;');
+AddFunction(@FastGetPixels,'function FastGetPixels(Bmp : integer; TPA : TPointArray) : TIntegerArray;');
+AddFunction(@FastDrawClear,'procedure FastDrawClear(bmp : integer; Color : TColor)');
+AddFunction(@FastDrawTransparent,'procedure FastDrawTransparent(x, y: Integer; SourceBitmap, TargetBitmap: Integer);');
+AddFunction(@SetTransparentColor,'procedure SetTransparentColor(bmp : integer; Color : TColor);');
+AddFunction(@GetTransparentColor,'function GetTransparentColor(bmp: integer) : TColor;');
+AddFunction(@FastReplaceColor,'procedure FastReplaceColor(Bmp : integer; OldColor,NewColor : TColor);');
+AddFunction(@ps_CopyClientToBitmap, 'procedure CopyClientToBitmap(bmp, xs, ys, xe, ye: Integer);');
+AddFunction(@BitmapFromClient,'function BitmapFromClient(const xs, ys, xe, ye: Integer): Integer;');
+AddFunction(@SetBitmapName, 'procedure SetBitmapName(Bmp : integer; name : string);');
+AddFunction(@FindBitmap,'function FindBitmap(bitmap: integer; out x, y: Integer): Boolean;');
+AddFunction(@FindBitmapIn,'function FindBitmapIn(bitmap: integer; out x, y: Integer; xs, ys, xe, ye: Integer): Boolean;');
+AddFunction(@FindBitmapToleranceIn,'function FindBitmapToleranceIn(bitmap: integer; out x, y: Integer; xs, ys, xe, ye: Integer; tolerance: Integer): Boolean;');
+AddFunction(@FindBitmapSpiral,'function FindBitmapSpiral(bitmap: Integer; var x, y: Integer; xs, ys, xe, ye: Integer): Boolean;');
+AddFunction(@FindBitmapsSpiralTolerance,'function FindBitmapsSpiralTolerance(bitmap: integer; x, y: Integer; out Points : TPointArray; xs, ys, xe, ye,tolerance: Integer): Boolean;');
+AddFunction(@FindBitmapSpiralTolerance,'function FindBitmapSpiralTolerance(bitmap: integer; var x, y: Integer; xs, ys, xe, ye,tolerance : integer): Boolean;');
+AddFunction(@RotateBitmap,'function RotateBitmap(bitmap: Integer; angle: Extended): Integer;');
+AddFunction(@Desaturate,'function DesaturateBitmap(Bitmap : integer) : integer;');
+AddFunction(@InvertBitmap,'procedure InvertBitmap(Bitmap : integer);');
+AddFunction(@CopyBitmap,'function CopyBitmap(Bitmap: integer) : integer)');
+AddFunction(@GreyScaleBitmap,'function GreyScaleBitmap(bitmap : integer) : integer');
+AddFunction(@BrightnessBitmap,'function BrightnessBitmap(Bitmap,br : integer) : integer;');
+AddFunction(@ContrastBitmap,'function ContrastBitmap(bitmap : integer; co : extended) : integer;');
+AddFunction(@PosterizeBitmap,'function PosterizeBitmap(Bitmap : integer; po : integer) : integer;');
+AddFunction(@CreateMaskFromBitmap,'function CreateMaskFromBitmap(Bitmap : integer) : TMask;');
+AddFunction(@FindMaskTolerance,'function FindMaskTolerance(mask: TMask; out x, y: Integer; xs,ys, xe, ye: Integer; Tolerance, ContourTolerance: Integer): Boolean;');
+AddFunction(@FindBitmapMaskTolerance,'function FindBitmapMaskTolerance(mask: Integer; out x, y: Integer; xs, ys, xe, ye: Integer; Tolerance, ContourTolerance: Integer): Boolean;');
+AddFunction(@FindDeformedBitmapToleranceIn,'function FindDeformedBitmapToleranceIn(bitmap: integer; out x,y: Integer; xs, ys, xe, ye: Integer; tolerance: Integer; Range: Integer; AllowPartialAccuracy: Boolean; out accuracy: Extended): Boolean;');
+AddFunction(@DrawTPABitmap,'procedure DrawTPABitmap(bitmap: integer; TPA: TPointArray; Color: integer);');
+AddFunction(@DrawATPABitmap,'procedure DrawATPABitmap(bitmap: integer; ATPA: T2DPointArray);');
+AddFunction(@DrawATPABitmapEx,'procedure DrawATPABitmapEx(bitmap: integer; ATPA: T2DPointArray; Colors: TIntegerArray);');
+
+{tpa}
+SetCurrSection('TPA');
+AddFunction(@tSwap,'procedure tSwap(var a, b: TPoint);');
+AddFunction(@tpaSwap,'procedure tpaSwap(var a, b: TPointArray);');
+AddFunction(@SwapE,'procedure SwapE(var a, b: Extended);');
+AddFunction(@RAaSTPAEx,'procedure RAaSTPAEx(var a: TPointArray; const w, h: Integer);');
+AddFunction(@RAaSTPA,'procedure RAaSTPA(var a: TPointArray; const Dist: Integer);');
+AddFunction(@NearbyPointInArrayEx,'function NearbyPointInArrayEx(const P: TPoint; w, h:Integer; a: TPointArray): Boolean;');
+AddFunction(@NearbyPointInArray,'function NearbyPointInArray(const P: TPoint; Dist:Integer; a: TPointArray): Boolean;');
+AddFunction(@ReArrangeandShortenArrayEx,'function ReArrangeandShortenArrayEx(a: TPointArray; w, h: Integer): TPointArray;');
+AddFunction(@ReArrangeandShortenArray,'function ReArrangeandShortenArray(a: TPointArray; Dist: Integer): TPointArray;');
+AddFunction(@TPAtoATPAEx,'function TPAtoATPAEx(TPA: TPointArray; w, h: Integer): T2DPointArray;');
+AddFunction(@TPAtoATPA,'function TPAtoATPA(TPA: TPointArray; Dist: Integer): T2DPointArray;');
+AddFunction(@QuickTPASort,'procedure QuickTPASort(var A: TIntegerArray; var B: TPointArray; iLo, iHi: Integer; SortUp: Boolean);');
+AddFunction(@QuickATPASort,'procedure QuickATPASort(var A: TIntegerArray; var B: T2DPointArray; iLo, iHi: Integer; SortUp: Boolean);');
+AddFunction(@SortTPAFrom,'procedure SortTPAFrom(var a: TPointArray; const From: TPoint);');
+AddFunction(@SortATPAFrom,'procedure SortATPAFrom(var a: T2DPointArray; const From: TPoint);');
+AddFunction(@SortATPAFromFirstPoint,'procedure SortATPAFromFirstPoint(var a: T2DPointArray; const From: TPoint);');
+AddFunction(@InvertTPA,'procedure InvertTPA(var a: TPointArray);');
+AddFunction(@InvertATPA,'procedure InvertATPA(var a: T2DPointArray);');
+AddFunction(@MiddleTPAEx,'function MiddleTPAEx(TPA: TPointArray; var x, y: Integer): Boolean;');
+AddFunction(@MiddleTPA,'function MiddleTPA(tpa: TPointArray): TPoint;');
+AddFunction(@SortATPASize,'procedure SortATPASize(var a: T2DPointArray; const BigFirst: Boolean);');
+AddFunction(@SortATPAFromSize,'procedure SortATPAFromSize(var a: T2DPointArray; const Size: Integer; CloseFirst: Boolean);');
+AddFunction(@CombineTPA,'function CombineTPA(Ar1, Ar2: TPointArray): TPointArray;');
+AddFunction(@CombineIntArray,'function CombineIntArray(Ar1, Ar2: TIntegerArray): TIntegerArray;');
+AddFunction(@InIntArrayEx,'function InIntArrayEx(a: TIntegerArray; var Where: Integer; const Number: Integer): Boolean;');
+AddFunction(@InIntArray,'function InIntArray(a: TIntegerArray; Number: Integer): Boolean;');
+AddFunction(@ClearSameIntegers,'procedure ClearSameIntegers(var a: TIntegerArray);');
+AddFunction(@ClearSameIntegersAndTPA,'procedure ClearSameIntegersAndTPA(var a: TIntegerArray; var p: TPointArray);');
+AddFunction(@SplitTPAEx,'function SplitTPAEx(arr: TPointArray; w, h: Integer): T2DPointArray;');
+AddFunction(@SplitTPA,'function SplitTPA(arr: TPointArray; Dist: Integer): T2DPointArray;');
+AddFunction(@FilterPointsPie,'procedure FilterPointsPie(var Points: TPointArray; const SD, ED, MinR, MaxR: Extended; Mx, My: Integer);');
+AddFunction(@RemoveDistTPointArray,'function RemoveDistTPointArray(x, y, dist: Integer; ThePoints: TPointArray; RemoveHigher: Boolean): TPointArray;');
+AddFunction(@GetATPABounds,'function GetATPABounds(ATPA: T2DPointArray): TBox;');
+AddFunction(@GetTPABounds,'function GetTPABounds(TPA: TPointArray): TBox;');
+AddFunction(@FindTPAinTPA,'function FindTPAinTPA(SearchTPA, TotalTPA: TPointArray; var Matches: TPointArray): Boolean;');
+AddFunction(@FindTextTPAinTPA,'function FindTextTPAinTPA(Height : integer; SearchTPA, TotalTPA: TPointArray; var Matches: TPointArray): Boolean;');
+AddFunction(@FindGapsTPA,'function FindGapsTPA(TPA: TPointArray; MinPixels: Integer): T2DPointArray;');
+AddFunction(@SortCircleWise,'procedure SortCircleWise(var tpa: TPointArray; const cx, cy, StartDegree: Integer; SortUp, ClockWise: Boolean);');
+AddFunction(@LinearSort,'procedure LinearSort(var tpa: TPointArray; cx, cy, sd: Integer; SortUp: Boolean);');
+AddFunction(@MergeATPA,'Function MergeATPA(ATPA : T2DPointArray) : TPointArray;');
+AddFunction(@TPAFromBox,'function TPAFromBox(const Box : TBox) : TPointArray;');
+AddFunction(@RotatePoints,'Function RotatePoints(Const P: TPointArray; A, cx, cy: Extended): TPointArray ;');
+AddFunction(@RotatePoint,'Function RotatePoint(Const p: TPoint; angle, mx, my: Extended): TPoint; inline;');
+AddFunction(@FindTPAEdges,'function FindTPAEdges(p: TPointArray): TPointArray;');
+AddFunction(@PointInTPA,'function PointInTPA(p: TPoint; arP: TPointArray): Boolean;');
+AddFunction(@ClearTPAFromTPA,'function ClearTPAFromTPA(arP, ClearPoints: TPointArray): TPointArray;');
+AddFunction(@ClearDoubleTPA,'procedure ClearDoubleTPA(var TPA: TPointArray);');
+AddFunction(@ReturnPointsNotInTPA,'Function ReturnPointsNotInTPA(Const TotalTPA: TPointArray; const Box: TBox): TPointArray;');
+AddFunction(@TPACountSort,'Procedure TPACountSort(Var TPA: TPointArray;const max: TPoint;Const SortOnX : Boolean);');
+AddFunction(@TPACountSortBase,'Procedure TPACountSortBase(Var TPA: TPointArray;const maxx, base: TPoint; const SortOnX : Boolean);');
+AddFunction(@InvertTIA,'procedure InvertTIA(var tI: TIntegerArray);');
+AddFunction(@SumIntegerArray,'function SumIntegerArray(Ints : TIntegerArray): Integer;');
+AddFunction(@AverageTIA,'function AverageTIA(tI: TIntegerArray): Integer;');
+AddFunction(@AverageExtended,'function AverageExtended(tE: TExtendedArray): Extended;');
diff --git a/branches/script-component/Units/MMLAddon/colourpicker.pas b/branches/script-component/Units/MMLAddon/colourpicker.pas
new file mode 100644
index 0000000..b46fdb2
--- /dev/null
+++ b/branches/script-component/Units/MMLAddon/colourpicker.pas
@@ -0,0 +1,294 @@
+{
+ This file is part of the Mufasa Macro Library (MML)
+ Copyright (c) 2009 by Raymond van Venetië and Merlijn Wajer
+
+ MML is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ MML is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with MML. If not, see .
+
+ See the file COPYING, included in this distribution,
+ for details about the copyright.
+
+ Colourpicker for the Mufasa Macro Library
+}
+
+unit colourpicker;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+ Classes, SysUtils, LCLIntf,LCLType,InterfaceBase,Forms,Controls,ExtCtrls,
+ Graphics,
+ {$IFDEF MSWINDOWS} os_windows, {$ENDIF}
+ {$IFDEF LINUX} os_linux, {$ENDIF}
+ MufasaTypes, colourhistory,bitmaps
+
+ {$IFNDEF PICKER_CLIENT}
+ {$IFDEF LINUX}
+ ,x
+ {$ENDIF}
+ {$ENDIF}
+ ;
+
+
+type
+ TPickEvent = procedure (Sender: TObject; Color, X, Y: Integer);
+
+ TMColorPicker = class(TObject)
+ constructor Create(manager: TIOManager);
+ destructor Destroy; override;
+
+ procedure Pick(Out C, X, Y: Integer);
+
+ procedure ImageMainMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
+ procedure ImageInfoMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
+ Procedure ColorPickUp(Sender: TObject; Button: TMouseButton;Shift: TShiftState; X, Y: Integer);
+ public
+ manager: TIOManager;
+
+ { Form components }
+ ScreenForm, InfoForm : TForm;
+ ImageMain, ImageInfo: TImage;
+ Text : string;
+ FPickEvent : TPickEvent;
+
+ { Some temp vars }
+ oldx, oldy, Color, colorx, colory: Integer;
+// targetleft,targettop : integer;
+
+ TheChangedEvent,TheChangingEvent : TNotifyEvent;
+
+ { Handles }
+ InfoHandle, ImageHandle : HDC;
+ public
+ property OnPick: TPickEvent read FPickEvent write FPickEvent;
+ end;
+
+
+implementation
+
+constructor TMColorPicker.Create(manager: TIOManager);
+
+begin
+ inherited Create;
+
+ self.manager := manager;
+end;
+
+destructor TMColorPicker.Destroy;
+begin
+
+ inherited Destroy;
+end;
+
+var
+ closed: Boolean;
+
+procedure TMColorPicker.Pick(Out C, X, Y: Integer);
+var
+ w, h: integer;
+ SS : TShiftState;
+ p : TPoint;
+
+ bmp: TMufasaBitmap;
+ Desktop : TIOManager;
+
+
+begin
+ { Disable both of the color pick buttons }
+ w := 0;
+ h := 0;
+ { If the target window isn't valid (closed etc), make the destkop the new window}
+ if not Self.Manager.TargetValid then
+ self.Manager.SetDesktop;
+
+ {Desktop is needed for the whole picture}
+ Desktop := TIOManager.Create;
+ Desktop.SetDesktop;
+ Desktop.GetDimensions(w, h);
+
+ Application.MainForm.Enabled := False;
+ ColourHistoryForm.Enabled := False;
+
+ { Create a form that will hold the client image and a form that will show cursor and color data }
+ ScreenForm := TForm.Create(Application.MainForm);
+ InfoForm := TForm.Create(ScreenForm);
+
+ { Initialize the form that will hold the client image }
+ ScreenForm.Caption := 'SimbaColourPicker';
+ { Set the form's dimensions to match that of the screen }
+ ScreenForm.Width := w;
+ ScreenForm.Height := h;
+ ScreenForm.Top := 0;
+ ScreenForm.left := 0;
+ ScreenForm.WindowState := wsmaximized;
+ ScreenForm.BorderStyle:= bsNone;
+ ScreenForm.FormStyle := fsStayOnTop;
+
+ { Initialize the form that will hold the cursor and color info }
+ InfoForm.Width := 173;
+ InfoForm.Height := 33;
+ InfoForm.BorderStyle := bsNone;
+ InfoForm.FormStyle := fsStayOnTop;
+ InfoForm.Left := Mouse.CursorPos.X + 5;
+ InfoForm.Top := Mouse.CursorPos.Y - 15;
+
+ { Initialize the image that will hold the cursor and color info }
+ ImageInfo := TImage.Create(InfoForm);
+ ImageInfo.Parent := InfoForm;
+ ImageInfo.Left := 0;
+ ImageInfo.Top := 0;
+ ImageInfo.Width := 173;
+ ImageInfo.Height := 33;
+ ImageInfo.Cursor := crCross;
+ ImageInfo.OnMouseMove := @ImageInfoMouseMove;
+ ImageInfo.Canvas.Brush.Color := 14811135;
+ ImageInfo.Canvas.Rectangle(0, 0, 173, 33);
+ ImageInfo.Canvas.Rectangle(114, 3, 140, 29);
+ ImageInfo.Canvas.Rectangle(142, 3, 168, 29);
+ ImageInfo.Canvas.Pen.Style := psClear;
+
+ { Initialize the image that will hold the client image }
+ ImageMain := TImage.Create(ScreenForm);
+ ImageMain.Parent := ScreenForm;
+ ImageMain.left := 0;
+ ImageMain.top := 0;
+ ImageMain.width := ScreenForm.Width;
+ ImageMain.Height := ScreenForm.Height;
+ ImageMain.Cursor:= crCross;
+ ImageMain.OnMouseUp:= @ColorPickUp;
+ ImageMain.OnMouseMove:=@ImageMainMouseMove;
+
+ { Copy the client to ImageMain }
+ bmp:=TMufasaBitmap.Create;
+ bmp.CopyClientToBitmap(Desktop, true, 0, 0, w-1, h-1);
+ ImageMain.Picture.Bitmap.Free;
+ ImageMain.Picture.Bitmap := bmp.ToTBitmap;
+ bmp.Free;
+
+ { Set up handles and events }
+ ImageHandle:= ImageMain.Canvas.Handle;
+ InfoHandle:= ImageInfo.Canvas.Handle;
+ TheChangedEvent := ImageMain.Canvas.OnChange;
+ TheChangingEvent := ImageMain.Canvas.OnChanging;
+ { Show the forms }
+ ScreenForm.Show;
+ InfoForm.Show;
+
+ { Display the data on the info form }
+ p := ImageMain.ScreenToClient(Mouse.CursorPos);
+ ImageMainMouseMove(nil, SS, p.x, p.y);
+
+ closed := False;
+
+ { Wait while the forms are still open }
+ while not Closed do
+ begin
+ sleep(1);
+ Application.ProcessMessages;
+ end;
+
+ // add x to history here.
+ c := Color;
+ x := Colorx;
+ y := Colory;
+
+ { Free forms and images }
+ ImageMain.Free;
+ ImageInfo.Free;
+ InfoForm.Free;
+ ScreenForm.Free;
+
+ Desktop.free;
+
+ { Re-enable the color pick buttons }
+ Application.MainForm.Enabled := True;
+ ColourHistoryForm.Enabled := True;
+end;
+
+procedure TMColorPicker.ImageMainMouseMove(Sender: TObject; Shift: TShiftState; X,
+ Y: Integer);
+var
+ TempPoint : TPoint;
+ R : TRect;
+ px, py : Integer;
+ MouseX, MouseY: Integer;
+begin
+ { Move the info form }
+ manager.GetMousePos(MouseX, MouseY);
+ InfoForm.Left := Mouse.CursorPos.X + 5;
+ InfoForm.Top := Mouse.CursorPos.Y - 15;
+
+ TempPoint := Point(x, y);
+
+ { If a form cannot be fully set to 0,0 }
+ TempPoint.X := TempPoint.X - ScreenForm.Left;
+ TempPoint.Y := TempPoint.Y - ScreenForm.Top;
+
+ { Get the pixel that the cursor is currently on }
+ Color := WidgetSet.DCGetPixel(ImageHandle, X, Y);
+
+ { Draw the current pixel to the right color box }
+ ImageInfo.Canvas.Brush.Color := Color;
+ ImageInfo.Canvas.Rectangle(143, 4, 168, 29);
+
+ { Draw the cursor and color info }
+ SetBkColor(InfoHandle, 14811135);
+ Text := Format('Pos: %d, %d', [MouseX, MouseY]);
+ R := Rect(5, 6, 114, 18);
+ ExtTextOut(InfoHandle, 5, 3, ETO_OPAQUE, @R, pchar(text), length(text), nil);
+ Text := Format('Color: %d', [Color]);
+ R := Rect(5, 18, 114, 28);
+ ExtTextOut(InfoHandle, 5, 15, ETO_OPAQUE, @R, pchar(text), length(text), nil);
+
+ { Draw the left, slightly zoomed out, color box }
+ for px := -1 to 1 do
+ for py := -1 to 1 do
+ begin
+ ImageInfo.Canvas.Brush.Color := WidgetSet.DCGetPixel(ImageHandle, x + px, y + py);
+ ImageInfo.Canvas.Rectangle((px + 1) * 8 + 115, (py + 1) * 8 + 4, (px + 1) * 8 + 124, (py + 1) * 8 + 13);
+ end;
+
+ Oldx := TempPoint.x;
+ Oldy := TempPoint.y;
+end;
+
+procedure TMColorPicker.ImageInfoMouseMove(Sender: TObject; Shift: TShiftState; X,
+ Y: Integer);
+begin
+ { Move the info form }
+ InfoForm.Top := Mouse.CursorPos.Y - 15;
+ InfoForm.Left := Mouse.CursorPos.X + 5;
+end;
+
+procedure TMColorPicker.ColorPickUp(Sender: TObject; Button: TMouseButton;
+ Shift: TShiftState; X, Y: Integer);
+begin;
+ { Set the coordinates and color that the user cliked on }
+ Color:= WidgetSet.DCGetPixel(ImageMain.Canvas.Handle,x,y);
+ Manager.GetMousePos(ColorX, ColorY);
+
+ if OnPick <> nil then
+ Onpick(Sender,Color,Colorx,Colory);
+
+ { Close the forms }
+ InfoForm.Close;
+ ScreenForm.Close;
+
+ { Tell Pick() that we are done }
+ closed := True;
+end;
+
+end.
+
diff --git a/branches/script-component/Units/MMLAddon/internets.pas b/branches/script-component/Units/MMLAddon/internets.pas
new file mode 100644
index 0000000..c94732d
--- /dev/null
+++ b/branches/script-component/Units/MMLAddon/internets.pas
@@ -0,0 +1,28 @@
+unit internets;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+ Classes, SysUtils;
+
+function GetPage(URL: String): String;
+
+implementation
+uses
+ httpsend;
+
+{ OTHER }
+function GetPage(URL: String): String;
+var
+ s: TStringList;
+begin
+ s:=TStringList.Create;
+ HttpGetText(URL, s);
+ result := String(s.GetText);
+ s.Free;
+end;
+
+end.
+
diff --git a/branches/script-component/Units/MMLAddon/mmlpsthread.pas b/branches/script-component/Units/MMLAddon/mmlpsthread.pas
new file mode 100644
index 0000000..969bfca
--- /dev/null
+++ b/branches/script-component/Units/MMLAddon/mmlpsthread.pas
@@ -0,0 +1,620 @@
+{
+ This file is part of the Mufasa Macro Library (MML)
+ Copyright (c) 2009 by Raymond van Venetië and Merlijn Wajer
+
+ MML is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ MML is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with MML. If not, see .
+
+ See the file COPYING, included in this distribution,
+ for details about the copyright.
+
+ MMLPSThread for the Mufasa Macro Library
+}
+
+unit mmlpsthread;
+
+{$Define PS_USESSUPPORT}
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+ Classes, SysUtils, client, uPSComponent,uPSCompiler,
+ uPSRuntime,stdCtrls, uPSPreProcessor,MufasaTypes, web,
+ bitmaps, plugins;
+
+var
+ PluginsGlob: TMPlugins;
+
+type
+ { TMMLPSThread }
+ TSyncInfo = record
+ V : MufasaTypes.TVariantArray;
+ MethodName : string;
+ Res : Variant;
+ SyncMethod : procedure of object;
+ OldThread : TThread;
+ PSScript : TPSScript;
+ end;
+
+ TWritelnProc = procedure(s: string);
+ TDbgImgInfo = record
+ DispSize : ^TPoint;
+ ShowForm : procedure of object;
+ ToDrawBitmap : ^TMufasaBitmap;
+ DrawBitmap : procedure of object;
+ GetDebugBitmap : ^TMufasaBitmap;
+ GetBitmap : procedure of object;
+ end;
+ PSyncInfo = ^TSyncInfo;
+ TErrorType = (errRuntime,errCompile);
+ TOnError = procedure of object;
+ TErrorData = record
+ Line,Position : integer;
+ Error : string;
+ ErrType : TErrorType;
+ Module : string;
+ IncludePath : string;
+ end;
+ PErrorData = ^TErrorData;
+ TExpMethod = record
+ Section : string;
+ FuncDecl : string;
+ FuncPtr : Pointer;
+ end;
+ TExpMethodArr = array of TExpMethod;
+
+ TMMLPSThread = class(TThread)
+ procedure OnProcessDirective(Sender: TPSPreProcessor;
+ Parser: TPSPascalPreProcessorParser; const Active: Boolean;
+ const DirectiveName, DirectiveParam: string; var Continue: Boolean);
+ function PSScriptFindUnknownFile(Sender: TObject;
+ const OrginFileName: string; var FileName, Output: string
+ ): Boolean;
+ procedure PSScriptProcessUnknowDirective(Sender: TPSPreProcessor;
+ Parser: TPSPascalPreProcessorParser; const Active: Boolean;
+ const DirectiveName, DirectiveParam: string; var Continue: Boolean);
+ private
+ ScriptPath, AppPath, IncludePath, PluginPath, FontPath: string;
+ procedure HandleError(ErrorAtLine,ErrorPosition : integer; ErrorStr : string; ErrorType : TErrorType; ErrorModule : string);
+ protected
+ //DebugTo : TMemo;
+ DebugTo: TWritelnProc;
+ DebugImg : TDbgImgInfo;
+ PluginsToload : Array of integer;
+ FOnError : TOnError;
+ procedure OnCompile(Sender: TPSScript);
+ function RequireFile(Sender: TObject; const OriginFileName: String;
+ var FileName, OutPut: string): Boolean;
+ procedure OnCompImport(Sender: TObject; x: TPSPascalCompiler);
+ procedure OnExecImport(Sender: TObject; se: TPSExec; x: TPSRuntimeClassImporter);
+ procedure OutputMessages;
+ procedure OnThreadTerminate(Sender: TObject);
+ procedure Execute; override;
+ public
+ ExportedMethods : TExpMethodArr;
+ PSScript : TPSScript; // Moved to public, as we can't kill it otherwise.
+ Client : TClient;
+ StartTime : LongWord;
+ DebugMemo : TMemo;
+ SyncInfo : PSyncInfo; //We need this for callthreadsafe
+ ErrorData : PErrorData; //We need this for thread-safety etc
+ property OnError : TOnError read FOnError write FOnError;
+ procedure LoadMethods;
+ class function GetExportedMethods : TExpMethodArr;
+ procedure SetPSScript(Script : string);
+ procedure SetDebug( writelnProc : TWritelnProc );
+ procedure SetDbgImg( DebugImageInfo : TDbgImgInfo);
+ procedure SetPaths(ScriptP,AppP,IncludeP,PluginP,FontP : string);
+ constructor Create(CreateSuspended: Boolean; TheSyncInfo : PSyncInfo; plugin_dir: string);
+ destructor Destroy; override;
+ end;
+threadvar
+ CurrThread : TMMLPSThread;
+implementation
+uses
+ colour_conv,dtmutil,
+ {$ifdef mswindows}windows,{$endif}
+ uPSC_std, uPSC_controls,uPSC_classes,uPSC_graphics,uPSC_stdctrls,uPSC_forms,
+ uPSC_extctrls, //Compile-libs
+ uPSUtils,
+ fontloader,
+ uPSR_std, uPSR_controls,uPSR_classes,uPSR_graphics,uPSR_stdctrls,uPSR_forms,
+ uPSR_extctrls, //Runtime-libs
+ Graphics, //For Graphics types
+ math, //Maths!
+ internets, // internets
+ strutils,
+ tpa, //Tpa stuff
+ forms,//Forms
+ lclintf; // for GetTickCount and others.
+
+
+{Some General PS Functions here}
+procedure psWriteln(str : string);
+begin
+ if Assigned(CurrThread.DebugTo) then
+ CurrThread.DebugTo(str)
+ else
+ writeln(str);
+end;
+
+function MakeString(data : TPSVariantIFC) : string;
+begin;
+ if data.aType.basetype in [btString,btChar] then
+ result := PSGetAnsiString(Data.Dta,data.aType)
+ else if data.aType.ExportName = 'BOOLEAN' then
+ result := BoolToStr(PSGetInt(Data.Dta,data.aType) <> 0,true)
+ else
+ result := PSVariantToString(data,'');
+end;
+
+function writeln_(Caller: TPSExec; p: TPSExternalProcRec; Global, Stack: TPSStack): Boolean;
+var
+ arr: TPSVariantIFC;
+begin
+ Result:=true;
+ psWriteln(makeString(NewTPSVariantIFC(Stack[Stack.Count-1],false)));
+end;
+
+function swap_(Caller: TPSExec; p: TPSExternalProcRec; Global, Stack: TPSStack): Boolean;
+var
+ Param1,Param2: TPSVariantIFC;
+ tempCopy : pointer;
+begin
+ Result:=true;
+ Param1 := NewTPSVariantIFC(Stack[Stack.count-1],true);
+ Param2 := NewTPSVariantIFC(Stack[Stack.count-2],true);
+ if Param1.aType.BaseType <> Param2.aType.BaseType then
+ exit(false)
+ else
+ begin
+ Param1.aType.CalcSize;
+ param2.aType.CalcSize;
+ if Param1.aType.RealSize <> Param2.aType.RealSize then
+ exit(false);
+ GetMem(tempcopy,Param1.aType.RealSize);
+ Move(Param1.Dta^,tempCopy^,param1.atype.realsize);
+ Move(Param2.Dta^,Param1.Dta^,param1.atype.realsize);
+ Move(tempCopy^,Param2.Dta^,param1.atype.realsize);
+ Freemem(tempcopy);
+ end;
+end;
+
+function ToStr_(Caller: TPSExec; p: TPSExternalProcRec; Global, Stack: TPSStack): Boolean;
+var
+ data: TPSVariantIFC;
+begin
+ result := true;
+ Stack.SetAnsiString(-1, MakeString(NewTPSVariantIFC(Stack[Stack.Count-2],false)));
+end;
+
+function NewThreadCall(Procname : string) : Cardinal;
+begin;
+ result := CurrThread.PSScript.Exec.GetVar(Procname);
+end;
+
+function ThreadSafeCall(ProcName: string; var V: TVariantArray): Variant;
+begin;
+ CurrThread.SyncInfo^.MethodName:= ProcName;
+ CurrThread.SyncInfo^.V:= V;
+ CurrThread.SyncInfo^.PSScript := CurrThread.PSScript;
+ CurrThread.SyncInfo^.OldThread := CurrThread;
+ CurrThread.Synchronize(CurrThread.SyncInfo^.SyncMethod);
+ Result := CurrThread.SyncInfo^.Res;
+{ Writeln('We have a length of: ' + inttostr(length(v)));
+ Try
+ Result := CurrThread.PSScript.Exec.RunProcPVar(v,CurrThread.PSScript.Exec.GetProc(Procname));
+ Except
+ Writeln('We has some errors :-(');
+ end;}
+end;
+
+
+{
+ Note to Raymond: For PascalScript, Create it on the .Create,
+ Execute it on the .Execute, and don't forget to Destroy it on .Destroy.
+
+ Furthermore, all the wrappers can be in the unit "implementation" section.
+ Better still to create an .inc for it, otherwise this unit will become huge.
+ (You can even split up the .inc's in stuff like color, bitmap, etc. )
+
+ Also, don't add PS to this unit, but make a seperate unit for it.
+ Unit "MMLPSThread", perhaps?
+
+ See the TestUnit for use of this thread, it's pretty straightforward.
+
+ It may also be wise to turn the "Importing of wrappers" into an include as
+ well, it will really make the unit more straightforward to use and read.
+}
+
+
+constructor TMMLPSThread.Create(CreateSuspended : boolean; TheSyncInfo : PSyncInfo; plugin_dir: string);
+begin
+ SyncInfo:= TheSyncInfo;
+ SetLength(PluginsToLoad,0);
+ Client := TClient.Create(plugin_dir);
+ PSScript := TPSScript.Create(nil);
+ PSScript.UsePreProcessor:= True;
+ PSScript.OnNeedFile := @RequireFile;
+ PSScript.OnProcessDirective:=@OnProcessDirective;
+ PSScript.OnProcessUnknowDirective:=@PSScriptProcessUnknowDirective;
+ PSScript.OnCompile:= @OnCompile;
+ PSScript.OnCompImport:= @OnCompImport;
+ PSScript.OnExecImport:= @OnExecImport;
+ PSScript.OnFindUnknownFile:=@PSScriptFindUnknownFile;
+ OnError:= nil;
+ // Set some defines
+ {$I PSInc/psdefines.inc}
+ // Load the methods we're going to export
+ Self.LoadMethods;
+
+ FreeOnTerminate := True;
+ Self.OnTerminate := @Self.OnThreadTerminate;
+
+ inherited Create(CreateSuspended);
+end;
+
+procedure TMMLPSThread.OnThreadTerminate(Sender: TObject);
+begin
+// Writeln('Terminating the thread');
+end;
+
+destructor TMMLPSThread.Destroy;
+begin
+ SetLength(PluginsToLoad,0);
+ Client.Free;
+ PSScript.Free;
+ inherited;
+end;
+
+// include PS wrappers
+{$I PSInc/Wrappers/other.inc}
+{$I PSInc/Wrappers/bitmap.inc}
+{$I PSInc/Wrappers/window.inc}
+
+{$I PSInc/Wrappers/strings.inc}
+
+{$I PSInc/Wrappers/colour.inc}
+{$I PSInc/Wrappers/math.inc}
+{$I PSInc/Wrappers/mouse.inc}
+{$I PSInc/Wrappers/file.inc}
+
+{$I PSInc/Wrappers/keyboard.inc}
+{$I PSInc/Wrappers/dtm.inc}
+{$I PSInc/Wrappers/ocr.inc}
+{$I PSInc/Wrappers/internets.inc}
+
+procedure TMMLPSThread.OnProcessDirective(Sender: TPSPreProcessor;
+ Parser: TPSPascalPreProcessorParser; const Active: Boolean;
+ const DirectiveName, DirectiveParam: string; var Continue: Boolean);
+begin
+end;
+
+function TMMLPSThread.PSScriptFindUnknownFile(Sender: TObject;
+ const OrginFileName: string; var FileName, Output: string): Boolean;
+begin
+ Writeln(OrginFileName + '-' + Output + '-' + FileName);
+end;
+
+procedure TMMLPSThread.PSScriptProcessUnknowDirective(Sender: TPSPreProcessor;
+ Parser: TPSPascalPreProcessorParser; const Active: Boolean;
+ const DirectiveName, DirectiveParam: string; var Continue: Boolean);
+var
+ TempNum : integer;
+ I: integer;
+begin
+ if DirectiveName= 'LOADDLL' then
+ if DirectiveParam <> '' then
+ begin;
+ TempNum := PluginsGlob.LoadPlugin(DirectiveParam);
+ if TempNum < 0 then
+ psWriteln(Format('Your DLL %s has not been found',[DirectiveParam]))
+ else
+ begin;
+ for i := High(PluginsToLoad) downto 0 do
+ if PluginsToLoad[i] = TempNum then
+ Exit;
+ SetLength(PluginsToLoad,Length(PluginsToLoad)+1);
+ PluginsToLoad[High(PluginsToLoad)] := TempNum;
+ end;
+ end;
+ Continue:= True;
+end;
+
+procedure TMMLPSThread.HandleError(ErrorAtLine, ErrorPosition: integer;
+ ErrorStr: string; ErrorType: TErrorType; ErrorModule : string);
+begin
+ if FOnError = nil then
+ exit;
+ ErrorData^.Line:= ErrorAtLine;
+ ErrorData^.Position:= ErrorPosition;
+ ErrorData^.Error:= ErrorStr;
+ ErrorData^.ErrType:= ErrorType;
+ ErrorData^.Module:= ErrorModule;
+ ErrorData^.IncludePath:= IncludePath;
+ CurrThread.Synchronize(FOnError);
+end;
+
+
+
+procedure TMMLPSThread.OnCompile(Sender: TPSScript);
+var
+ i,ii : integer;
+ Fonts : TMFonts;
+begin
+ {$I PSInc/pscompile.inc}
+ Fonts := Client.MOCR.GetFonts;
+ for i := fonts.count - 1 downto 0 do
+ PSScript.Comp.AddConstantN(Fonts[i].Name,'string').SetString(Fonts[i].Name);
+
+ for i := high(PluginsToLoad) downto 0 do
+ for ii := 0 to PluginsGlob.MPlugins[PluginsToLoad[i]].MethodLen - 1 do
+ PSScript.AddFunctionEx(PluginsGlob.MPlugins[PluginsToLoad[i]].Methods[ii].FuncPtr,
+ PluginsGlob.MPlugins[PluginsToLoad[i]].Methods[ii].FuncStr, cdStdCall);
+
+ for i := 0 to high(VirtualKeys) do
+ PSScript.Comp.AddConstantN(Format('VK_%S',[VirtualKeys[i].Str]),'Byte').SetInt(VirtualKeys[i].Key);
+ // Here we add all the Consts/Types to the engine.
+
+ //Export all the methods
+ for i := 0 to high(ExportedMethods) do
+ if ExportedMethods[i].FuncPtr <> nil then
+ PSScript.AddFunction(ExportedMethods[i].FuncPtr,ExportedMethods[i].FuncDecl);
+end;
+
+function TMMLPSThread.RequireFile(Sender: TObject;
+ const OriginFileName: String; var FileName, OutPut: string): Boolean;
+var
+ path: string;
+ f: TFileStream;
+begin
+ if FileExists(FileName) then
+ Path := FileName
+ else
+ Path := IncludePath + Filename;
+ if not FileExists(Path) then
+ begin;
+ psWriteln(Path + ' doesn''t exist');
+ Result := false;
+ Exit;
+ end;
+ try
+ F := TFileStream.Create(Path, fmOpenRead or fmShareDenyWrite);
+ except
+ Result := false;
+ exit;
+ end;
+ try
+ SetLength(Output, f.Size);
+ f.Read(Output[1], Length(Output));
+ finally
+ f.Free;
+ end;
+ Result := True;
+end;
+
+procedure SIRegister_Mufasa(cl: TPSPascalCompiler);
+
+begin;
+ with cl.AddClassN(cl.FindClass('TObject'),'TMufasaBitmap') do
+ begin;
+ RegisterMethod('constructor create');
+ RegisterMethod('procedure Free');
+ RegisterMethod('function SaveToFile(const FileName : string) :boolean;');
+ RegisterMethod('procedure LoadFromFile(const FileName : string);');
+ RegisterProperty('Index','Integer',iptR);
+ end;
+end;
+
+function CreateMufasaBitmap : TMufasaBitmap;
+begin;
+ result := TMufasaBitmap.Create;
+ CurrThread.Client.MBitmaps.AddBMP(result);
+end;
+
+procedure FreeMufasaBitmap(Self : TMufasaBitmap);
+begin;
+ CurrThread.Client.MBitmaps.FreeBMP(Self.Index);
+end;
+
+procedure MufasaBitmapIndex(self : TMufasaBitmap; var Index : integer);
+begin;
+ Index := self.Index;
+end;
+
+procedure RIRegister_Mufasa(cl: TPSRuntimeClassImporter);
+begin;
+ with cl.Add(TMufasaBitmap) do
+ begin
+ RegisterConstructor(@CreateMufasaBitmap,'CREATE');
+ RegisterMethod(@FreeMufasaBitmap,'FREE');
+ RegisterMethod(@TMufasaBitmap.SaveToFile, 'SAVETOFILE');
+ RegisterMethod(@TMufasaBitmap.LoadFromFile, 'LOADFROMFILE');
+ RegisterPropertyHelper(@MufasaBitmapIndex,nil,'INDEX');
+ end;
+end;
+
+procedure TMMLPSThread.OnCompImport(Sender: TObject; x: TPSPascalCompiler);
+begin
+ SIRegister_Std(x);
+ SIRegister_Controls(x);
+ SIRegister_Classes(x, true);
+ SIRegister_Graphics(x, true);
+ SIRegister_stdctrls(x);
+ SIRegister_Forms(x);
+ SIRegister_ExtCtrls(x);
+ SIRegister_Mufasa(x);
+ with x.AddFunction('procedure writeln;').decl do
+ with AddParam do
+ begin
+ OrgName:= 'x';
+ Mode:= pmIn;
+ end;
+ with x.AddFunction('function ToStr:string').decl do
+ with addparam do
+ begin
+ OrgName:= 'x';
+ Mode:= pmIn;
+ end;
+ with x.AddFunction('procedure swap;').decl do
+ begin
+ with addparam do
+ begin
+ OrgName:= 'x';
+ Mode:= pmInOut;
+ end;
+ with addparam do
+ begin
+ OrgName:= 'y';
+ Mode:= pmInOut;
+ end;
+ end;
+end;
+
+procedure TMMLPSThread.OnExecImport(Sender: TObject; se: TPSExec;
+ x: TPSRuntimeClassImporter);
+begin
+ RIRegister_Std(x);
+ RIRegister_Classes(x, True);
+ RIRegister_Controls(x);
+ RIRegister_Graphics(x, True);
+ RIRegister_stdctrls(x);
+ RIRegister_Forms(x);
+ RIRegister_ExtCtrls(x);
+ RIRegister_Mufasa(x);
+ se.RegisterFunctionName('WRITELN',@Writeln_,nil,nil);
+ se.RegisterFunctionName('TOSTR',@ToStr_,nil,nil);
+ se.RegisterFunctionName('SWAP',@swap_,nil,nil);
+end;
+
+procedure TMMLPSThread.OutputMessages;
+var
+ l: Longint;
+ b: Boolean;
+begin
+ b := False;
+ for l := 0 to PSScript.CompilerMessageCount - 1 do
+ begin
+ if (not b) and (PSScript.CompilerMessages[l] is TIFPSPascalCompilerError) then
+ begin
+ b := True;
+ if OnError <> nil then
+ with PSScript.CompilerMessages[l] do
+ HandleError(Row, Pos, MessageToString,errCompile, ModuleName)
+ else
+ psWriteln(PSScript.CompilerErrorToStr(l) + ' at line ' + inttostr(PSScript.CompilerMessages[l].Row));
+ end else
+ psWriteln(PSScript.CompilerErrorToStr(l) + ' at line ' + inttostr(PSScript.CompilerMessages[l].Row));
+
+ end;
+end;
+
+procedure TMMLPSThread.Execute;
+begin
+ CurrThread := Self;
+ Starttime := lclintf.GetTickCount;
+
+ try
+ if PSScript.Compile then
+ begin
+ OutputMessages;
+ psWriteln('Compiled succesfully in ' + IntToStr(GetTickCount - Starttime) + ' ms.');
+// if not (ScriptState = SCompiling) then
+ if not PSScript.Execute then
+ HandleError(PSScript.ExecErrorRow,PSScript.ExecErrorPosition,PSScript.ExecErrorToString,
+ errRuntime, PSScript.ExecErrorFileName)
+ else
+ psWriteln('Succesfully executed');
+ end else
+ begin
+ OutputMessages;
+ psWriteln('Compiling failed');
+ end;
+ except
+ on E : Exception do
+ psWriteln('ERROR IN PSSCRIPT: ' + e.message);
+ end;
+end;
+
+procedure TMMLPSThread.LoadMethods;
+begin
+ ExportedMethods:= GetExportedMethods;
+end;
+
+class function TMMLPSThread.GetExportedMethods: TExpMethodArr;
+var
+ c : integer;
+ CurrSection : string;
+
+ procedure SetCurrSection(str : string);
+ begin;
+ CurrSection := Str;
+ end;
+
+ procedure AddFunction( Ptr : Pointer; DeclStr : String);
+ begin;
+ // SetLength(ExportedMethods,c+1);
+ if c >= 300 then
+ raise exception.create('PSThread.LoadMethods: Exported more than 300 functions');
+ Result[c].FuncDecl:= DeclStr;
+ Result[c].FuncPtr:= Ptr;
+ Result[c].Section:= CurrSection;
+ inc(c);
+ end;
+
+begin
+ c := 0;
+ CurrSection := 'Other';
+ SetLength(Result,300);
+
+ {$i PSInc/psexportedmethods.inc}
+
+ SetLength(Result,c);
+
+end;
+
+procedure TMMLPSThread.SetPSScript(Script: string);
+begin
+ PSScript.Script.Text:= Script;
+end;
+
+procedure TMMLPSThread.SetDebug(writelnProc: TWritelnProc);
+begin
+ DebugTo := writelnProc;
+end;
+
+procedure TMMLPSThread.SetDbgImg(DebugImageInfo: TDbgImgInfo);
+begin
+ DebugImg := DebugImageInfo;
+end;
+
+procedure TMMLPSThread.SetPaths(ScriptP, AppP,IncludeP,PluginP,FontP: string);
+begin
+ AppPath:= AppP;
+ ScriptPath:= ScriptP;
+ IncludePath:= IncludeP;
+ PluginPath:= PluginP;
+ FontPath:= FontP;
+
+end;
+
+
+initialization
+ PluginsGlob := TMPlugins.Create;
+finalization
+ //PluginsGlob.Free;
+ //Its a nice idea, but it will segfault... the program is closing anyway.
+end.
+
+
diff --git a/branches/script-component/Units/MMLAddon/newinternets.pas b/branches/script-component/Units/MMLAddon/newinternets.pas
new file mode 100644
index 0000000..320613c
--- /dev/null
+++ b/branches/script-component/Units/MMLAddon/newinternets.pas
@@ -0,0 +1,305 @@
+unit newinternets;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+ Classes, SysUtils;
+
+type
+ {
+ Record to hold the information of a $_POST variable and value.
+ }
+ TPostVariable = record
+ variable, value: String;
+ end;
+
+ {
+ Store the internet connection information
+ }
+ TInternetConnection = class(TObject)
+ protected
+ //url of the connection
+ ConnURL: String;
+ //contains post paramaters and vars
+ PostVars: TList;
+ private
+ function createPostVariable(variable, value: String): TPostVariable;
+ public
+ constructor Create(URL: String);
+ destructor Destroy; override;
+
+ //$_POST variable functions for PHP transmission
+ procedure AddPostVariable(theVar, theValue: String);
+ procedure DelPostVariable(theVar: String);
+ procedure ReplacePostVariable(searchVar, replaceVar, value: String);
+ function PostHTTP(out dataStream: TStream): Boolean;
+ end;
+
+ TMufasaInternet = class(TObject)
+ protected
+ // TList storing all of the connection infos
+ ConnList : TList;
+
+ public
+ function ConnectionOpen(URL: String): Integer;
+ function ConnectionClose(ConnInd: Integer): Boolean;
+ destructor Destroy; override;
+
+ //$_POST variable functions for PHP
+ procedure AddPostVariable(connInd: Integer; theVar, theValue: String);
+ procedure DelPostVariable(connInd: Integer; theVar: String);
+ procedure ReplacePostVariable(connInd: Integer; searchVar, replaceVar, value: String);
+ function PostHTTP(connInd: Integer; out dataStream: TStream): Boolean;
+ end;
+
+function GetPage(URL: String): String;
+
+implementation
+uses
+ httpsend, synacode;
+
+
+function replace(sStr, rStr, iStr: String): String;
+var
+ ind: Integer;
+begin
+ ind := Pos(sStr, iStr);
+ while (ind <> 0) do
+ begin
+ Delete(iStr, ind, Length(sStr));
+ Insert(rStr, iStr, ind);
+ end;
+end;
+
+{ TInternetConnection }
+
+procedure TInternetConnection.Create(URL: String);
+begin
+ inherited;
+ Self.ConnURL := EncodeURL(URL);
+ Self.PostVars.Create;
+end;
+
+procedure TInternetConnection.Destroy; overload;
+begin
+ inherited;
+ // ADD CLOSING OF CONNECTION
+
+ // Clear it up
+ PostVars.Clear;
+end;
+
+procedure TInternetConnect.AddPostVariable(theVar, theValue: String);
+var
+ currentIndex: Integer;
+begin
+ theVar := EncodeURLElement(theVar);
+ theValue := EncodeURLElement(theValue);
+ Self.PostVars.Add(createPostVariable(theVar, theValue));
+ { with Self do
+ begin
+
+
+ if (FreeSpotsHigh = -1) then
+ begin
+ setLength(PostVars, PostVarsHigh + 2);
+ inc(PostVarsHigh);
+ currentIndex := PostVarsHigh;
+ end else
+ begin
+ currentIndex := PostFreeSpots[FreeSpotsHigh];
+ dec(FreeSpotsHigh);
+ end;
+ PostVars[currentIndex].variable := theVar;
+ PostVars[currentIndex].value := theValue;
+
+ end; }
+end;
+
+procedure TInternetConnection.DelPostVariable(theVar: String);
+var
+ i: Integer;
+ tempPostVar: TPostVariable;
+begin
+ for i := (Self.PostVars.Count - 1) downto 0 do
+ begin
+ if (theVar = Self.PostVars.Items[i].variable) then
+ begin
+ tempPostVar := PostVars.Items[i];
+ Self.PostVars.Remove(tempPostVar);
+ break;
+ end;
+ end;
+end;
+
+procedure TInternetConnection.ReplacePostVariable(searchVar, replaceVar, theValue: String);
+var
+ i: Integer;
+ tempPostVar: TPostVariable;
+begin
+ with Self do
+ begin
+ for i := (PostVars.Count - 1) downto 0 do
+ begin
+ tempPostVar := PostVars.Items[i];
+ if (searchVar = tempPostVar.variable) then
+ begin
+ tempPostVar.variable := replaceVar;
+ tempPostVar.value := theValue;
+ break;
+ end;
+ end;
+ end;
+end;
+
+function TInternetConnection.PostHTTP(out dataStream: TStream): Boolean;
+var
+ // holds the vars when they are placed together
+ URLData: String;
+ tempPostVar: TPostVariable;
+begin
+ try
+ with Self do
+ begin
+ //ADD Connection stuffs
+
+ for i := (PostVars.Count - 1) downto 0 do
+ begin
+ tempPostVar := PostVars.Items[i];
+ if (tempPostVar.variable <> '') then
+ begin
+ URLData := URLData + format('%d=%d+', [tempPostVar.variable,
+ tempPostVar.value]);
+ end;
+ end;
+ Delete(URLData, Length(URLData) - 1, 1);
+
+ {I DONT KNOW (TStream), this should work since we don't reuse it after.}
+ dataStream := TStream.Create;
+ HttpPostURL(ConnURL, URLData, dataStream);
+
+ // Lets remove all Post Variable data so fresh start next time.
+ PostVars.Clear;
+ end;
+ except
+ raise Exception.createFMT('TInternetConnection.PostHTTP: Something went wrong, could not complete. URL: %d', URLData);
+ exit(false);
+ end;
+ result := true;
+end;
+
+{ TMufasaInternet }
+
+{
+ Allocate space in the ConnArray, then open the connection.
+}
+function TMufasaInternet.ConnectionOpen(URL: String): Integer;
+var
+ currentIndex: Integer;
+begin
+ try
+ Result := Self.ConnList.Add(TInternetConnection.Create(URL));
+ except
+ raise Exception.createFMT('TInternetArray.ConnectionClose: Could not close connection %d URL: %d',
+ [theInd, ConnURL]);
+ end;
+end;
+
+{
+ Close the connection, add the index to the FreeSpots.
+}
+function TMufasaInternet.ConnectionClose(theInd: Integer): Boolean;
+var
+ tempConn: TInternetConnection;
+begin
+ try
+ tempConn := Self.ConnList.Items[theInd];
+ Self.ConnList.Remove(tempConn);
+ tempConn.Destroy;
+ {
+ with Self do
+ begin
+ ConnArray[theInd].Destroy;
+ if (FreeSpotsHigh = FreeSpotsLen) then
+ begin
+ FreeSpotsLen := FreeSpotsLen + 1;
+ setLength(FreeSpots, FreeSpotsLen);
+ end;
+ FreeSpots[FreeSpotsHigh] := theInd;
+ end; }
+ except
+ raise Exception.createFMT('TInternetArray.ConnectionClose: Could not close connection %d URL: %d',
+ [theInd, ConnList.Items[theInd].ConnURL]);
+ exit(false);
+ end;
+ result := True;
+end;
+
+{
+ Wrapper for the TInternetConnection.PostVariableAdd procedure which accepts
+ a connection index.
+}
+procedure TMufasaInternet.PostVariableAdd(connInd: Integer; theVar, theValue: String);
+begin
+ try
+ ConnList.Items[commInd].PostVariableAdd(theVar, theValue);
+ except
+ raise Exception.createFMT('TInternetArray.PostVariableAdd: %d is not in the ConnArray',
+ [connInd]);
+ end;
+end;
+
+{
+ Wrapper for the TInternetConnection.PostVariableDel procedure which accepts
+ a connection index.
+}
+procedure TMufasaInternet.PostVariableDel(connInd: Integer; theVar: String);
+begin
+ try
+ ConnList.Items[commInd].PostVariableAdd(theVar);
+ except
+ raise Exception.createFMT('TInternetArray.PostVariableDel: %d is not in the ConnArray',
+ [connInd]);
+ end;
+end;
+
+{
+ Wrapper for the TInternetConnection.PostVariableReplace procedure which accepts
+ a connection index.
+}
+procedure TMufasaInternet.PostVariableReplace(connInd: Integer; searchVar, replaceVar, value: String);
+begin
+ try
+ ConnList.Items[commInd].PostVariableAdd(searchVar, replaceVar, value);
+ except
+ raise Exception.createFMT('TInternetArray.PostVariableReplace: %d is not in the ConnArray',
+ [connInd]);
+ end;
+end;
+
+function TMufasaInternet.PostHTTP(connInd: Integer; out dataStream: TStream): Boolean;
+begin
+ try
+ result := ConnList.Items[commInd].PostHTTP(dataStream);
+ except
+ raise Exception.createFMT('TInternetArray.PostHTTP: %d is not in the ConnArray',
+ [connInd]);
+ end;
+end;
+
+{ OTHER }
+function GetPage(URL: String): String;
+var
+ s: TStringList;
+begin
+ s:=TStringList.Create;
+ HttpGetText(URL, s);
+ result := String(s.GetText);
+ s.Free;
+end;
+
+end.
+
+
diff --git a/branches/script-component/Units/MMLAddon/plugins.pas b/branches/script-component/Units/MMLAddon/plugins.pas
new file mode 100644
index 0000000..c8bd112
--- /dev/null
+++ b/branches/script-component/Units/MMLAddon/plugins.pas
@@ -0,0 +1,105 @@
+{
+ This file is part of the Mufasa Macro Library (MML)
+ Copyright (c) 2009 by Raymond van Venetië and Merlijn Wajer
+
+ MML is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ MML is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with MML. If not, see .
+
+ See the file COPYING, included in this distribution,
+ for details about the copyright.
+
+ Plugins Class for the Mufasa Macro Library
+}
+
+unit plugins;
+
+{
+ Problems with SMART; you cannot free the plugin when smart is open..
+ Therefore, loading & free-ing plugins per script run is not an option.
+ Assigning a TMPlugin per Tab might be a do-able solution, but will still cope with the SMART Problems..
+ So the question is: Plugins Per Tab,Per Run or Global?
+}
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+ Classes, SysUtils, dynlibs, libloader;
+
+type
+ TMPluginMethod = record
+ FuncPtr : pointer;
+ FuncStr : string;
+ end;
+
+ TMPlugin = record
+ Methods : Array of TMPluginMethod;
+ MethodLen : integer;
+ end;
+ TMPluginArray = array of TMPlugin;
+
+
+
+ { TMPlugins }
+
+ TMPlugins = class (TGenericLoader)
+ private
+ Plugins : TMPluginArray;
+ NumPlugins : integer;
+ protected
+ function InitPlugin(plugin: TLibHandle): boolean; override;
+ public
+ property MPlugins : TMPluginArray read Plugins;
+ property Count : integer read NumPlugins;
+ end;
+
+implementation
+
+uses
+ MufasaTypes,FileUtil;
+
+{ TMPlugins }
+
+function TMPlugins.InitPlugin(plugin: TLibHandle): boolean;
+var
+ pntrArrc : function : integer; stdcall;
+ GetFuncInfo : function (x: Integer; var ProcAddr: Pointer; var ProcDef: PChar) : Integer; stdcall;
+ GetTypeCount : function : Integer; stdcall;
+ GetTypeInfo : function (x: Integer; var sType, sTypeDef: string): Integer; stdcall;
+ PD : PChar;
+ pntr : Pointer;
+ arrc, ii : integer;
+begin
+ Pointer(pntrArrc) := GetProcAddress(plugin, PChar('GetFunctionCount'));
+ if @pntrArrc = nil then begin result:= false; exit; end;
+ Pointer(GetFuncInfo) := GetProcAddress(plugin, PChar('GetFunctionInfo'));
+ if @GetFuncInfo = nil then begin result:= false; exit; end;
+ arrc := pntrArrc();
+ SetLength(Plugins,NumPlugins+1);
+ Plugins[NumPlugins].MethodLen := Arrc;
+ SetLength(Plugins[NumPlugins].Methods, ArrC);
+ pd := StrAlloc(255);
+ for ii := 0 to ArrC-1 do
+ begin;
+ if (GetFuncInfo(ii, pntr, pd) < 0) then
+ Continue;
+ Plugins[NumPlugins].Methods[ii].FuncPtr := pntr;
+ Plugins[NumPlugins].Methods[ii].FuncStr := pd;
+ end;
+ StrDispose(pd);
+ inc(NumPlugins);
+ result:= true;
+end;
+
+end.
+
diff --git a/branches/script-component/Units/MMLAddon/settings.pas b/branches/script-component/Units/MMLAddon/settings.pas
new file mode 100644
index 0000000..368851a
--- /dev/null
+++ b/branches/script-component/Units/MMLAddon/settings.pas
@@ -0,0 +1,619 @@
+{
+ This file is part of the Mufasa Macro Library (MML)
+ Copyright (c) 2009 by Raymond van Venetië and Merlijn Wajer
+
+ MML is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ MML is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with MML. If not, see .
+
+ See the file COPYING, included in this distribution,
+ for details about the copyright.
+
+ Settings class for Mufasa Macro Library
+}
+
+unit settings;
+
+{$mode objfpc}{$M+}
+
+interface
+
+uses
+ Classes, SysUtils, ComCtrls, xmlread, xmlwrite, DOM;
+
+
+
+type
+ // remove later
+ TStringArray = Array Of String;
+
+ TSettingData = class(TObject)
+ public
+ Val: String;
+
+ constructor Create;
+ destructor Destroy; override;
+
+ end;
+
+ {
+ TMMLSettings; class to manage settings with XML.
+ Features:
+ - Loading and Saving to XML.
+ - Showing the settings as a tree.
+ - Changing, Creating settings. (No Deleting yet.)
+ - Bad naming conventions.
+ Bugs:
+ - Don't use '/' as a *name* for a node. It WILL fuck up.
+ It is no problem in values, but in NAMES for nodes, it will
+ simply not work.
+ - Poor naming.
+ }
+
+ TMMLSettings = class(TObject)
+
+ public
+ constructor Create(aNodes: TTreeNodes);
+ destructor Destroy; override;
+
+ private
+ Nodes: TTreeNodes;
+ function KeyNameToKeys(KeyName: String): TStringArray;
+ function WalkToNode(KeyName: String): TTreeNode;
+
+ procedure InternalLoadFromXML(XMLDoc: TXMLDocument);
+ procedure WriteXMLData(n: TTreeNode;
+ XMLNode: TDOMNode; XMLDoc: TXMLDocument;
+ var XMLChild: TDOMNode; var C: Integer);
+ procedure WalkTree(Node: TTreeNode; XMLNode: TDOMNode; XMLDoc: TXMLDocument;
+ var C: Integer);
+
+ public
+ function GetNodePath(Node: TTreeNode): String;
+ function ListKeys(KeyName: String): TStringArray;
+ function KeyExists(KeyName: String): Boolean;
+ function IsKey(KeyName: String): Boolean;
+ function IsDirectory(KeyName: String): Boolean;
+ procedure SetKeyValue(KeyName: String; KeyValue: String);
+ function CreateKey(KeyName: String; CreatePath: Boolean = False): Boolean;
+ function GetKeyValue(KeyName: String): String;
+
+ // Horrible name
+ function GetSetDefaultKeyValue(KeyName, defVal: String): String;
+ private
+ // /facepalm
+ function GetSetLoadSaveDefaultKeyValue(KeyName, defVal, fileName: String): String;
+ public
+ // AAAAAAAAAAAHG??
+ function GetSetLoadSaveDefaultKeyValueIfNotExists(KeyName, defVal, fileName: String): String;
+
+ public
+ procedure LoadFromXML(fileName: String);
+ procedure SaveToXML(fileName: String);
+
+ end;
+
+implementation
+uses
+ strutils;
+
+constructor TSettingData.Create;
+begin
+ inherited;
+ Val := '';
+end;
+
+destructor TSettingData.Destroy;
+begin
+ Val := '';
+ inherited;
+end;
+
+
+constructor TMMLSettings.Create(aNodes: TTreeNodes);
+begin
+ Self.Nodes := aNodes;
+end;
+
+destructor TMMLSettings.Destroy;
+var
+ i : integer;
+begin
+ for i := 0 to Nodes.Count - 1 do
+ if Nodes[i].data <> nil then
+ TSettingData(Nodes[i].Data).Free;
+ Nodes := nil;
+
+ inherited;
+end;
+
+procedure TMMLSettings.InternalLoadFromXML(XMLDoc: TXMLDocument);
+var
+ iNode: TDOMNode;
+
+ procedure ProcessNode(Node: TDOMNode; TreeNode: TTreeNode);
+ var
+ cNode: TDOMNode;
+ s: string;
+ d: TSettingData;
+
+ begin
+ if Node = nil then Exit; // Stops if reached a leaf
+
+ // Adds a node to the tree
+ s := Node.NodeName;
+
+ TreeNode := Nodes.AddChild(TreeNode, s);
+ if (Node.NodeType = 3) then
+ begin
+ d := TSettingData.Create;
+ D.Val := Node.NodeValue;
+ TreeNode.Data := D;
+
+ TreeNode.Text := Node.NodeValue;
+ end;
+ // Goes to the child node
+ cNode := Node.FirstChild;
+
+ // Processes all child nodes
+ while cNode <> nil do
+ begin
+ ProcessNode(cNode, TreeNode);
+ cNode := cNode.NextSibling;
+ end;
+ end;
+
+begin
+ iNode := XMLDoc.DocumentElement;
+ while iNode <> nil do
+ begin
+ ProcessNode(iNode, nil); // Recursive
+ iNode := iNode.NextSibling;
+ end;
+end;
+
+function TMMLSettings.KeyNameToKeys(KeyName: String): TStringArray;
+ // yay for SRL!
+ function srl_Explode(str, del: string): TStringArray;
+ var
+ i, l, dL: Integer;
+ begin
+ i := 0;
+ l := -1;
+ SetLength(Result, 0);
+ if (str = '') then
+ Exit;
+ dL := Length(del) - 1;
+ repeat
+ Inc(l);
+ SetLength(Result, l + 1);
+ i := Pos(del, str);
+ if i <= 0 then
+ Break;
+ Result[l] := Copy(str, 1, i - 1);
+ Delete(str, 1, i + dL);
+ until false;
+ Result[l] := Copy(str, 1, Length(str));
+ end;
+begin
+ Result := srl_Explode(KeyName, '/');
+end;
+
+function TMMLSettings.WalkToNode(KeyName: String): TTreeNode;
+var
+ N: TTreeNode;
+ i: Integer;
+ S: TStringArray;
+begin
+ Result := nil;
+
+ if KeyName[length(KeyName)]='/' then setlength(KeyName,length(KeyName)-1);
+ S := KeyNameToKeys(KeyName);
+
+ if not assigned(s) then
+ Exit(nil);
+
+ N := Nodes.GetFirstNode;
+ i := 0;
+
+ while N <> nil do
+ begin
+ if N.Text = s[i] then
+ begin
+ inc(i);
+ if i = length(s) then
+ break;
+ N := N.GetFirstChild;
+ end else
+ N := N.GetNextSibling;
+ end;
+
+ Result := N;
+end;
+
+{
+ Return the "path" of the given Node.
+ The node should be in Nodes. (TreeView.Items)
+}
+
+function TMMLSettings.GetNodePath(Node: TTreeNode): String;
+var
+ N: TTreeNode;
+ s: TStringArray;
+ i: Integer;
+begin
+ if Node = nil then
+ Exit('');
+
+ N := Node;
+ setlength(s, 0);
+ while N <> nil do
+ begin
+ setlength(s,length(s) + 1);
+ s[high(s)] := N.Text;
+ N := N.Parent;
+ end;
+
+ result := '';
+ for i := high(s) downto 0 do
+ result := result + s[i] + '/';
+ if length(result) > 1 then
+ setlength(result,length(result)-1);
+end;
+
+{
+ Equivalent to 'ls' or 'dir'. It lists the keys in a certain key (directory)
+}
+
+function TMMLSettings.ListKeys(KeyName: String): TStringArray;
+var
+ N: TTreeNode;
+ i: Integer;
+ S: TStringArray;
+begin
+ SetLength(Result, 0);
+ N := WalkToNode(KeyName);
+ if N <> nil then
+ N := N.GetFirstChild;
+
+ while N <> nil do
+ begin
+ setlength(result,length(result)+1);
+ result[high(result)] := N.Text;
+ N := N.GetNextSibling;
+ end;
+end;
+
+{
+ Return wether the given key exists or not
+}
+
+function TMMLSettings.KeyExists(KeyName: String): Boolean;
+
+begin
+ Result := WalkToNode(KeyName) <> nil;
+end;
+
+{
+ Return wether the given key is a key. (again, bad naming)
+ What I mean is, a 'key' only has a 'Value', which a 'directory key' has other
+ keys (or none) as childs.
+}
+
+function TMMLSettings.IsKey(KeyName: String): Boolean;
+var
+ N: TTreeNode;
+
+begin
+ N := WalkToNode(KeyName);
+ if N = nil then
+ Exit(False);
+
+ n := N.GetFirstChild;
+ while n <> nil do
+ begin
+ if n.HasChildren then
+ exit(false);
+ n := N.GetNextSibling;
+ end;
+ exit(true);
+end;
+
+{
+ Perhaps this should just do Exit(not IsKey(KeyName))
+}
+
+function TMMLSettings.IsDirectory(KeyName: String): Boolean;
+var
+ N: TTreeNode;
+begin
+ N := WalkToNode(KeyName);
+ if N <> nil then
+ Exit(N.HasChildren);
+ Exit(False);
+end;
+
+{
+ Get the value of a Key. (String)
+}
+
+function TMMLSettings.GetKeyValue(KeyName: String): String;
+var
+ N: TTreeNode;
+begin
+ if not KeyExists(KeyName) then
+ Exit('');
+ N := WalkToNode(KeyName);
+ if N <> nil then
+ N := N.GetFirstChild;
+ while N <> nil do
+ begin
+ if assigned(n.Data) then
+ begin
+ Exit(TSettingData(n.Data).Val);
+ end;
+ N := N.GetNextSibling;
+ end;
+ Exit('');
+end;
+
+{
+ If the key exists - return the value.
+ If it does not exist, create the key - with a possible path, set it to
+ defVal and return defVal.
+}
+
+function TMMLSettings.GetSetDefaultKeyValue(KeyName, defVal: String): String;
+var
+ Res: String;
+begin
+ if not IsKey(KeyName) then
+ begin
+ CreateKey(KeyName, True);
+ SetKeyValue(KeyName, defVal);
+ exit(defVal);
+ end;
+ Res := GetKeyValue(KeyName);
+ if Res = '' then
+ begin
+ SetKeyValue(KeyName, defVal);
+ exit(defVal);
+ end;
+ Exit(Res);
+end;
+
+{
+ Clear the entire tree. Load from fileName. call GetSetDefaultKeyValue.
+}
+
+function TMMLSettings.GetSetLoadSaveDefaultKeyValue(KeyName, defVal, fileName: String): String;
+begin
+ Nodes.Clear;
+ LoadFromXML(fileName);
+ Result := GetSetDefaultKeyValue(KeyName, defVal);
+ SaveToXML(fileName);
+end;
+
+{
+ If Key exists, call getSetDefaultKeyValue, else call GetSetLoadSaveDefaultKeyValue
+}
+function TMMLSettings.GetSetLoadSaveDefaultKeyValueIfNotExists(KeyName, defVal, fileName: String): String;
+begin
+ if KeyExists(KeyName) then
+ Exit(GetSetDefaultKeyValue(KeyName, defVal))
+ else
+ Exit(GetSetLoadSaveDefaultKeyValue(KeyName, defVal, fileName));
+end;
+
+{
+ Create the given key. If CreatePath = true, then create every key that is
+ required to create the key. (Say KeyName = 'a/b/c/d/e' and only key a exists,
+ and CreatePath = True, then b,c,d and e are all created.
+}
+
+function TMMLSettings.CreateKey(KeyName: String; CreatePath: Boolean = False): Boolean;
+var
+ N, newN, nParent: TTreeNode;
+ Path: TStringArray;
+ NewPath: String;
+ i: Integer;
+
+begin
+ if KeyExists(KeyName) then
+ begin
+ Exit(False);
+ end;
+ NewPath := '';
+ N := nil;
+ nParent := Nodes.GetFirstNode;
+
+ Path := KeyNameToKeys(KeyName);
+ if length(path) < 2 then
+ begin
+ writeln('Path too short!');
+ exit(false);
+ end;
+
+ if path[0] <> nParent.Text then
+ begin
+ writeln('First key doesn''t match. First key should always match');
+ exit(false);
+ end;
+ for i := 0 to length(Path) - 2 do
+ begin
+ if Path[i] = '' then
+ begin
+ writeln('Invalid Key Path / Name');
+ exit(false);
+ end;
+ NewPath := NewPath + Path[i] + '/';
+ N := WalkToNode(NewPath);
+
+ if (N = nil) and (not CreatePath) then
+ exit(false);
+
+ if (N = nil) and CreatePath then
+ begin
+ newN := TTreeNode.Create(Nodes);
+ newN.Text := Path[i];
+ if (nParent = nil) then
+ begin
+ writeln('This shouldn''t happen...');
+ newN.MoveTo(Nodes.GetFirstNode, naAddChild);
+ nParent := newN;
+ end
+ else
+ begin
+ newN.MoveTo(nParent, naAddChild);
+ nParent := newN;
+ end;
+ end;
+
+ if N <> nil then
+ nParent := N;
+ end;
+
+ if nParent = nil then
+ exit(false);
+
+ newN := TTreeNode.Create(Nodes);
+ newN.Text := Path[High(Path)];
+ newN.MoveTo(nParent, naAddChild);
+end;
+
+{
+ Set the value of a key.
+}
+
+procedure TMMLSettings.SetKeyValue(KeyName: String; KeyValue: String);
+var
+ N, NN: TTreeNode;
+begin
+ if not KeyExists(KeyName) then
+ begin
+ writeln('SetKeyValue - Key does not exist');
+ Exit;
+ end;
+ if not IsKey(KeyName) then
+ begin
+ writeln('SetKeyValue - IsKey returned false');
+ Exit;
+ end;
+ N := WalkToNode(KeyName);
+
+ if not N.HasChildren then
+ begin
+ NN := TTreeNode.Create(Nodes);
+ NN.Text := KeyValue;
+ NN.MoveTo(N, naAddChild);
+ end;
+
+ if n <> nil then
+ N := N.GetFirstChild;
+ while N <> nil do
+ begin
+ if Assigned(N.Data) then
+ TSettingData(N.Data).Free;
+ N.Data := TSettingData.Create;
+ TSettingData(N.Data).Val := KeyValue;
+ writeln('Setting ' + KeyName + ' to ' + KeyValue);
+ N := N.GetNextSibling;
+ end;
+end;
+
+
+{ load from xml }
+procedure TMMLSettings.LoadFromXML(fileName: String);
+var
+ Doc: TXMLDocument;
+begin
+ Nodes.Clear;
+ if not fileExists(fileName) then
+ begin
+ writeln('KANKER');
+ // create file.
+ SaveToXML(fileName);
+ end;
+ ReadXMLFile(Doc, fileName);
+ InternalLoadFromXML(Doc);
+ Doc.Free;
+end;
+
+procedure TMMLSettings.WriteXMLData(n: TTreeNode;
+ XMLNode: TDOMNode; XMLDoc: TXMLDocument;
+ var XMLChild: TDOMNode; var C: Integer);
+
+var
+ DDataNode, DataNode: TDOMNode;
+
+begin
+ if assigned(n.data) and (n.HasChildren) then
+ writeln('Has data and children! Please close simba and remove settings.xml. if problem persists, please report your settings.xml');
+ if assigned(n.Data) then
+ begin
+ XMLChild := XMLDoc.CreateTextNode(TSettingData(N.Data).Val);
+ end else
+ begin
+ XMLChild := XMLDoc.CreateElement(n.Text);
+ end;
+ Inc(C);
+ XMLNode.AppendChild(XMLChild);
+end;
+
+procedure TMMLSettings.WalkTree(Node: TTreeNode; XMLNode: TDOMNode; XMLDoc: TXMLDocument;
+ var C: Integer);
+var
+ N: TTreeNode;
+ XMLChild: TDOMNode;
+
+begin
+ N := Node.GetFirstChild;
+
+ while assigned(n) do
+ begin
+ WriteXMLData(n, XMLNode, XMLDoc, XMLChild, C);
+
+ WalkTree(n, XMLChild, XMLDoc, C);
+ n := n.GetNextSibling;
+ end;
+end;
+
+{ save to xml }
+
+procedure TMMLSettings.SaveToXML(fileName: String);
+var
+ XMLDoc: TXMLDocument;
+ RootNode: TDOMNode;
+ C: Integer;
+begin
+ XMLDoc := TXMLDocument.Create;
+
+ RootNode := XMLDoc.CreateElement('Settings');
+ XMLDoc.AppendChild(RootNode);
+
+ RootNode := XMLDoc.DocumentElement;
+
+ C := 0;
+ if Nodes.GetFirstNode <> nil then
+ WalkTree(Nodes.GetFirstNode, RootNode, XMLDoc, C);
+ try
+ WriteXMLFile(XMLDoc, fileName);
+ except
+ Writeln('Failed to write ' + fileName);
+ end;
+
+
+ XMLDoc.Free;
+end;
+
+end.
+
diff --git a/branches/script-component/Units/MMLAddon/updater.pas b/branches/script-component/Units/MMLAddon/updater.pas
new file mode 100644
index 0000000..07d0028
--- /dev/null
+++ b/branches/script-component/Units/MMLAddon/updater.pas
@@ -0,0 +1,251 @@
+unit updater;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+ Classes, SysUtils, httpsend,blcksock
+ {$IFDEF LINUX}
+ ,BaseUnix
+ {$ENDIF};
+
+type
+ { TMMLUpdateThread = class(TThread)
+ procedure Execute; override;
+ constructor Create(CreateSuspended: Boolean);
+ destructor Destroy; override;
+ end; }
+ TMemory = pointer;
+ TMMLFunctionBoolean = function: boolean of object;
+
+
+ TMMLFileDownloader = class(TObject)
+ private
+ FFileURL: String;
+ FBasePath: String;
+ FReplacementFile: String;
+ FTotal: Integer;
+ HTTPSend: THTTPSend;
+ FFileSize: Integer;
+ FDownloaded: Boolean;
+ FOnChange: TMMLFunctionBoolean;
+ FOnBeat: TMMLFunctionBoolean;
+ private
+ procedure SetBasePath(s: string);
+
+ public
+ constructor Create;
+ destructor Destroy; override;
+
+ { Download and Save the file }
+ function DownloadAndSave: Boolean;
+
+ { Replace the new file with the one we downloaded }
+ function Replace: Boolean;
+
+ { Where do we get the file from? }
+ property FileURL: String read FFileURL write FFileURL;
+
+ { The file to write to. Note that downloading downloads to this
+ file with a '_' added to the end of the FileName;
+ Replace; is called to replace the old file with the downloaded
+ one }
+ property ReplacementFile: String read FReplacementFile write FReplacementFile;
+
+ { Return true if we have downloaded the file completely }
+ property Downloaded: Boolean read FDownloaded;
+
+ property BasePath: String read FBasePath write SetBasePath;
+
+ { If either of these events return "True", an exception is thrown
+ and the download is cancelled. This way we can easily `cancel'
+ a download. }
+ property OnChange: TMMLFunctionBoolean read FOnChange write FOnChange;
+
+ { Called every 50ms }
+ property OnBeat: TMMLFunctionBoolean read FOnBeat write FOnBeat;
+
+ property DownloadedSize : Integer read FTotal;
+ property FileSize : integer read FFileSize;
+ function GetPercentage: Integer;
+ private
+ procedure TryToGetFileSize;
+
+ procedure OnMonitor(Sender: TObject; Writing: Boolean;
+ const Buffer: TMemory; Len: Integer);
+ procedure OnStatus(Sender: TObject; Reason: THookSocketReason;
+ const Value: String);
+ procedure OnHeartBeat(Sender: TObject);
+ end;
+
+
+
+
+
+
+implementation
+uses
+ strings;
+
+procedure TMMLFileDownloader.SetBasePath(s: string);
+begin
+ if s[length(s) - 1] <> DirectorySeparator then
+ s := s + DirectorySeparator;
+ FBasePath:=s;
+end;
+
+procedure TMMLFileDownloader.TryToGetFileSize;
+var
+ i,p:integer;
+begin
+ if assigned(HTTPSend.Headers) then
+ for i := 0 to HTTPSend.headers.count - 1 do
+ begin
+ p := Pos('Content-Length: ', HTTPSend.headers.strings[i]);
+ if p <> 0 then
+ FFileSize := StrToInt(Copy(HTTPSend.headers.strings[i],
+ p+length('Content-Length: '),length( HTTPSend.headers.strings[i]) - p) );
+ end;
+end;
+
+procedure TMMLFileDownloader.OnStatus(Sender: TObject; Reason: THookSocketReason;
+ const Value: String);
+begin
+ if FFileSize = 0 then
+ TryToGetFileSize;
+ if Assigned(FOnChange) then
+ if FOnChange() then
+ raise Exception.Create('OnChange event called for a quit');
+end;
+
+procedure TMMLFileDownloader.OnHeartBeat(Sender: TObject);
+begin
+ if Assigned(FOnBeat) then
+ if FOnBeat() then
+ raise Exception.Create('OnBeat event called for a quit');
+end;
+
+procedure TMMLFileDownloader.OnMonitor(Sender: TObject; Writing: Boolean;
+ const Buffer: TMemory; Len: Integer);
+
+var
+ i,p:integer;
+begin
+ if writing then exit;
+ Inc(FTotal, len);
+
+ if FFileSize = 0 then
+ TryToGetFileSize;
+ if Assigned(FOnChange) then
+ if FOnChange() then
+ raise Exception.Create('OnChange event called for a quit');
+end;
+
+function TMMLFileDownloader.GetPercentage: Integer;
+begin
+ if FFileSize <> 0 then
+ Exit( Round( (FTotal / FFileSize) * 100.0) )
+ else
+ Exit(-1);
+end;
+
+function TMMLFileDownloader.DownloadAndSave: Boolean;
+
+var
+ response: TStream;
+ i:integer;
+ f: TFileStream;
+
+begin
+ Result := False;
+ HTTPSend := THTTPSend.Create;
+ HTTPSend.Sock.OnMonitor:=@Self.OnMonitor;
+ HTTPSend.Sock.OnStatus:=@Self.OnStatus;
+ HTTPSend.Sock.OnHeartbeat:=@Self.OnHeartBeat;
+ HTTPSend.Sock.HeartbeatRate:=50;
+
+ if FReplacementFile = '' then
+ raise Exception.Create('ReplacementFile not set');
+ if FileURL = '' then
+ raise Exception.Create('FileURL not set');
+
+ Response := TFileStream.Create(FBasePath + FReplacementFile + '_', fmCreate);
+ try
+ Result := HTTPSend.HTTPMethod('GET', FileURL);
+
+ if Result then
+ begin
+ Response.Seek(0, soFromBeginning);
+ Response.CopyFrom(HTTPSend.Document, 0);
+ end;
+ FDownloaded := True;
+ except
+ writeln('DownloadAndSave: Exception Occured');
+ Result := False;
+ end;
+ HTTPSend.Free;
+ Response.Free;
+ if not result then
+ Raise Exception.Create('Throwing it so we can catch it later');
+end;
+
+function TMMLFileDownloader.Replace: Boolean;
+begin
+ { Change to messages + Exit(False) instead of exceptions? }
+ if not Downloaded then
+ begin
+ writeln('Nothing downloaded');
+ exit(False);
+ // raise Exception.Create('Nothing downloaded');
+ end;
+ if FReplacementFile = '' then
+ begin
+ writeln('ReplacementFile not se');
+ exit(False);
+ //raise Exception.Create('ReplacementFile not set');
+ end;
+ if not FileExists(FBasePath + FReplacementFile) then
+ begin
+ writeln('ReplacementFile not found');
+ exit(False);
+ //raise Exception.Create('ReplacementFile not found');
+ end;
+ if not FileExists(FBasePath + FReplacementFile+ '_') then
+ begin
+ writeln('ReplacementFile + _ not found');
+ exit(False);
+ //raise Exception.Create('ReplacementFile + _ not found');
+ end;
+ RenameFile(FBasePath + FReplacementFile, FBasePath + FReplacementFile+'_old_');
+ RenameFile(FBasePath + FReplacementFile +'_', FBasePath + FReplacementFile);
+ DeleteFile(FBasePath + FReplacementFile+'_old_');
+ {$IFDEF LINUX}
+ fpchmod(FBasePath + FReplacementFile, S_IRUSR or S_IWUSR or S_IXUSR or S_IRGRP
+ or S_IXGRP or S_IROTH or S_IXOTH);
+ {$ENDIF}
+
+end;
+
+constructor TMMLFileDownloader.Create;
+begin
+ inherited Create;
+ FTotal := 0;
+ FFileSize := 0;
+ FDownloaded := False;
+ FReplacementFile:='';
+ FFileURL := '';
+ FBasePath:= '';
+ FOnChange := nil;
+ FOnBeat := nil;
+end;
+
+
+destructor TMMLFileDownloader.Destroy;
+begin
+
+ inherited;
+end;
+
+end.
+
diff --git a/branches/script-component/Units/MMLAddon/windowselector.pas b/branches/script-component/Units/MMLAddon/windowselector.pas
new file mode 100644
index 0000000..bfd629b
--- /dev/null
+++ b/branches/script-component/Units/MMLAddon/windowselector.pas
@@ -0,0 +1,210 @@
+{
+ This file is part of the Mufasa Macro Library (MML)
+ Copyright (c) 2009 by Raymond van Venetië and Merlijn Wajer
+
+ MML is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ MML is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with MML. If not, see .
+
+ See the file COPYING, included in this distribution,
+ for details about the copyright.
+
+ WindowSelector for the Mufasa Macro Library
+}
+
+unit windowselector;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+ Classes, SysUtils,
+ ctypes,
+ {$IFDEF MSWINDOWS} os_windows, {$ENDIF}
+ {$IFDEF LINUX} os_linux, {$ENDIF}
+ controls,
+ graphics,
+ forms,
+ {$IFNDEF MSWINDOWS}x, xlib,xatom
+ {$ELSE}
+ windows
+ {$ENDIF}
+
+ ;
+
+type
+ TMWindowSelector = class(TObject)
+ constructor Create(manager: TIOManager);
+ destructor Destroy; override;
+
+ function Drag: TNativeWindow;
+
+
+ public
+ LastPick: TNativeWindow;
+ haspicked: boolean;
+ manager: TIOManager;
+
+ end;
+
+
+implementation
+
+
+constructor TMWindowSelector.Create(manager: TIOManager);
+begin
+ inherited create;
+ haspicked:= false;
+ self.manager := manager;
+
+end;
+
+
+destructor TMWindowSelector.Destroy;
+begin
+
+ inherited;
+end;
+
+{$IFDEF LINUX}
+function TMWindowSelector.Drag: TNativeWindow;
+var
+ Tempwindow : x.TWindow;
+ root : x.TWindow;
+ subwindow : x.TWindow;
+ x_root, y_root : cint;
+ xmask : cuint;
+ x, y : cint;
+ Old_Handler : TXErrorHandler;
+
+ window_opacity: TAtom;
+ opacity_75: culong;
+ opacity_100: culong;
+
+begin
+ Old_Handler := XSetErrorHandler(@MufasaXErrorHandler);
+
+ Result := 0;
+
+ window_opacity:=XInternAtom(manager.display,PChar('_NET_WM_WINDOW_OPACITY'), False);
+ opacity_75 := cuint($ffffffff * 0.75);
+ opacity_100 := cuint($ffffffff);
+
+ repeat
+ // get pointer pos + current window we are at.
+ XQueryPointer(manager.display, manager.desktop, @root,
+ @Tempwindow, @x_root, @y_root,
+ @x, @y, @xmask);
+ subwindow:= Tempwindow;
+
+ while subwindow <> 0 do
+ begin
+ Tempwindow := subwindow;
+ XQueryPointer(manager.display, Tempwindow, @root,
+ @subwindow, @x_root, @y_root,
+ @x, @y, @xmask);
+ end;
+
+
+
+ if Result <> Tempwindow then
+ begin
+ writeln('Making ' + inttostr(tempwindow) + ' transparent');
+ XChangeProperty(manager.display, tempwindow, window_opacity, XA_CARDINAL, 32, PropModeReplace, @opacity_75, 1);
+
+ writeln('Resetting ' + inttostr(Result));
+ if result <> 0 then
+ XChangeProperty(manager.display, Result, window_opacity, XA_CARDINAL, 32, PropModeReplace, @opacity_100, 1);
+ WriteLn('Changing Window from: ' + Inttostr(result) +' to: ' + IntToStr(Tempwindow));
+ // XChangeProperty(Window.XDisplay, tempwindow, window_opacity, XA_CARDINAL, 32, PropModeReplace, @opacity_50, 1);
+
+ Result := Tempwindow;
+ LastPick:= TempWindow;
+ haspicked:= true;
+ end;
+ XFlush(manager.display);
+ Sleep(16);
+
+ //if we are selecting for a long time, we must still process other messages
+ Application.ProcessMessages;
+
+ until (xmask and Button1Mask) = 0;
+
+ XChangeProperty(manager.display, Result, window_opacity, XA_CARDINAL, 32, PropModeReplace, @opacity_100, 1);
+ XFlush(manager.display);
+
+ XSetErrorHandler(Old_handler);
+end;
+
+{$ELSE}
+
+function TMWindowSelector.Drag: TNativeWindow;
+var
+ TargetRect: TRect;
+ DC: HDC;
+ OldPen, Pen: hPen;
+ OldBrush : hBrush;
+ BrushHandle : THandle;
+ Cursor : TCursor;
+ TempHandle : Hwnd;
+ Handle : Hwnd;
+begin;
+ Pen := CreatePen(PS_SOLID, GetSystemMetrics(SM_CXBORDER)*5, clred);
+ BrushHandle := GetStockObject(Null_Brush);
+ Cursor:= Screen.Cursor;
+ Screen.Cursor:= crCross;
+ TempHandle := GetDesktopWindow;
+ while GetAsyncKeyState(VK_LBUTTON) <> 0 do
+ begin;
+ Handle:= WindowFromPoint(Mouse.CursorPos);
+ if Handle <> TempHandle then
+ begin;
+ if TempHandle <> 0 then
+ begin;
+ Invalidaterect(temphandle, nil, true);
+ UpdateWindow(temphandle);
+ {$IFDEF MSWINDOWS}
+ RedrawWindow(TempHandle, nil, 0, RDW_Frame or RDW_Invalidate or RDW_Updatenow or RDW_Allchildren);
+ {$ENDIF}
+ end;
+ if Handle <> 0 then
+ begin;
+ GetWindowRect(Handle, TargetRect);
+ DC := Windows.GetWindowDC(Handle);
+ OldPen := SelectObject(DC, Pen);
+ OldBrush := SelectObject(DC, BrushHandle);
+ Rectangle(DC, 0, 0, TargetRect.Right - TargetRect.Left, TargetRect.Bottom - TargetRect.Top);
+ SelectObject(DC, OldBrush);
+ SelectObject(DC, OldPen);
+ ReleaseDC(Handle, DC);
+ end;
+ TempHandle := Handle;
+ end;
+ Application.ProcessMessages;
+ Sleep(64);
+ end;
+ Result := TempHandle;
+ LastPick:= TempHandle;
+ haspicked:= true;
+ Screen.Cursor:= cursor;
+ Invalidaterect(temphandle, nil, true);
+ UpdateWindow(temphandle);
+ RedrawWindow(TempHandle, nil, 0, RDW_Frame or RDW_Invalidate or RDW_Updatenow or RDW_Allchildren);
+ DeleteObject(Pen);
+end;
+{$ENDIF}
+
+
+
+end.
+
diff --git a/branches/script-component/Units/MMLCore/bitmaps.pas b/branches/script-component/Units/MMLCore/bitmaps.pas
new file mode 100644
index 0000000..39ebc2a
--- /dev/null
+++ b/branches/script-component/Units/MMLCore/bitmaps.pas
@@ -0,0 +1,1214 @@
+{
+ This file is part of the Mufasa Macro Library (MML)
+ Copyright (c) 2009 by Raymond van Venetië and Merlijn Wajer
+
+ MML is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ MML is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with MML. If not, see .
+
+ See the file COPYING, included in this distribution,
+ for details about the copyright.
+
+ Bitmaps class for the Mufasa Macro Library
+}
+
+unit bitmaps;
+
+{$mode objfpc}{$H+}
+
+interface
+uses
+ Classes, SysUtils, FPImage,IntfGraphics,graphtype,MufasaTypes,graphics;
+
+type
+
+ { TMufasaBitmap }
+ TMufasaBitmap = class(TObject)
+ private
+ w,h : integer;
+ TransparentColor : TRGB32;
+ TransparentSet : boolean;
+ FIndex : integer;
+ public
+ OnDestroy : procedure(Bitmap : TMufasaBitmap) of object;
+ FakeData : array of TRGB32;
+ FData : PRGB32;
+ BmpName : string; //Optional?
+ property Index : integer read FIndex write FIndex;
+ procedure SetSize(AWidth,AHeight : integer);
+ procedure StretchResize(AWidth,AHeight : integer);
+ property Width : Integer read w;
+ property Height : Integer read h;
+ procedure ValidatePoint(x,y : integer);
+ function SaveToFile(const FileName : string) :boolean;
+ procedure LoadFromFile(const FileName : string);
+ procedure FastSetPixel(x,y : integer; Color : TColor);
+ procedure FastSetPixels(TPA : TPointArray; Colors : TIntegerArray);
+ procedure DrawATPA(ATPA : T2DPointArray; Colors : TIntegerArray);overload;
+ procedure DrawATPA(ATPA : T2DPointArray);overload;
+ procedure DrawTPA(TPA : TPointArray; Color : TColor);
+ function CreateTPA(SearchCol : TColor) : TPointArray;
+ function FastGetPixel(x,y : integer) : TColor;
+ function FastGetPixels(TPA : TPointArray) : TIntegerArray;
+ Procedure SetTransparentColor(Col : TColor);
+ Function GetTransparentColor : TColor;
+ property TransparentColorSet : boolean read TransparentSet;
+ procedure FastDrawClear(Color : TColor);
+ procedure FastDrawTransparent(x, y: Integer; TargetBitmap: TMufasaBitmap);
+ procedure FastReplaceColor(OldColor, NewColor: TColor);
+ procedure CopyClientToBitmap(MWindow : TObject;Resize : boolean; xs, ys, xe, ye: Integer);overload;
+ procedure CopyClientToBitmap(MWindow : TObject;Resize : boolean;x,y : integer; xs, ys, xe, ye: Integer);overload;
+ procedure RotateBitmap(angle: Extended;TargetBitmap : TMufasaBitmap );
+ procedure Desaturate;overload;
+ procedure Desaturate(TargetBitmap : TMufasaBitmap); overload;
+ procedure GreyScale(TargetBitmap : TMufasaBitmap);overload;
+ procedure GreyScale;
+ procedure Brightness(br: integer);overload;
+ procedure Brightness(TargetBitmap : TMufasaBitmap; br : integer); overload;
+ procedure Contrast(co: Extended);overload;
+ procedure Contrast(TargetBitmap : TMufasaBitmap; co : Extended);overload;
+ procedure Invert;
+ procedure Posterize(TargetBitmap : TMufasaBitmap; Po : integer);overload;
+ procedure Posterize(Po : integer);overload;
+ function Copy: TMufasaBitmap;
+ function ToTBitmap: TBitmap;
+ function ToString : string;
+ procedure LoadFromTBitmap(bmp: TBitmap);
+ procedure LoadFromRawImage(RawImage: TRawImage);
+ function CreateTMask : TMask;
+ constructor Create;
+ destructor Destroy;override;
+ end;
+
+ TMufasaBmpArray = Array of TMufasaBitmap;
+ { TMBitmaps }
+ TMBitmaps = class(TObject)
+ protected
+ Client : TObject;
+ FreeSpots : Array of integer;
+ BmpArray : TMufasaBmpArray;
+ BmpsCurr,BmpsHigh,FreeSpotsHigh,FreeSpotsLen : integer;
+ function GetNewIndex : integer;
+ public
+ function GetBMP(Index : integer) : TMufasaBitmap;
+ property Bmp[Index : integer]: TMufasaBitmap read GetBMP; default;
+ function CreateBMP(w, h: integer): Integer;
+ function AddBMP(_bmp: TMufasaBitmap): Integer;
+ function CopyBMP( Bitmap : integer) : Integer;
+ function CreateMirroredBitmap(bitmap: Integer; MirrorStyle : TBmpMirrorStyle): Integer;
+ function CreateBMPFromFile(const Path : string) : integer;
+ function CreateBMPFromString(width,height : integer; Data : string) : integer;overload;
+ function CreateBMPFromString(BmpName : string; width,height : integer; Data : string) : integer;overload;
+ procedure FreeBMP( Number : integer);
+ constructor Create(Owner : TObject);
+ destructor Destroy;override;
+ end;
+
+ Procedure ArrDataToRawImage(Ptr: PRGB32; Size: TPoint; out RawImage: TRawImage);
+
+implementation
+
+uses
+ paszlib,DCPbase64,math,
+ colour_conv,IOManager,mufasatypesutil,tpa;
+
+// Needs more fixing. We need to either copy the memory ourself, or somehow
+// find a TRawImage feature to skip X bytes after X bytes read. (Most likely a
+// feature)
+Procedure ArrDataToRawImage(Ptr: PRGB32; Size: TPoint; out RawImage: TRawImage);
+Begin
+ RawImage.Init; { Calls raw.Description.Init as well }
+
+ RawImage.Description.PaletteColorCount:=0;
+ RawImage.Description.MaskBitsPerPixel:=0;
+ RawImage.Description.Width := Size.X;
+ RawImage.Description.Height:= Size.Y;
+
+ RawImage.Description.Format := ricfRGBA;
+ RawImage.Description.ByteOrder := riboLSBFirst;
+ RawImage.Description.BitOrder:= riboBitsInOrder; // should be fine
+ RawImage.Description.Depth:=24;
+ RawImage.Description.BitsPerPixel:=32;
+ RawImage.Description.LineOrder:=riloTopToBottom;
+ RawImage.Description.LineEnd := rileDWordBoundary;
+
+ RawImage.Description.RedPrec := 8;
+ RawImage.Description.GreenPrec:= 8;
+ RawImage.Description.BluePrec:= 8;
+ RawImage.Description.AlphaPrec:=0;
+
+
+ RawImage.Description.RedShift:=16;
+ RawImage.Description.GreenShift:=8;
+ RawImage.Description.BlueShift:=0;
+
+ RawImage.DataSize := RawImage.Description.Width * RawImage.Description.Height
+ * (RawImage.Description.bitsperpixel shr 3);
+ RawImage.Data := PByte(Ptr);
+End;
+
+function Min(a,b:integer) : integer;
+begin
+ if a < b then
+ result := a
+ else
+ result := b;
+end;
+
+{ TMBitmaps }
+
+function TMBitmaps.GetNewIndex: integer;
+begin
+ if BmpsCurr < BmpsHigh then
+ begin;
+ inc(BmpsCurr);
+ Result := BmpsCurr;
+ end else if (FreeSpotsHigh > -1) then
+ begin;
+ Result := FreeSpots[FreeSpotsHigh];
+ dec(FreeSpotsHigh);
+ end else
+ begin;
+ SetLength(BmpArray, BmpsHigh + 6);
+ BmpsHigh := BmpsHigh + 5;
+ inc(BmpsCurr);
+ Result := BmpsCurr;
+ end;
+end;
+
+function TMBitmaps.GetBMP(Index: integer): TMufasaBitmap;
+begin
+ Result := nil;
+ if (Index >= 0) and (Index <= BmpsCurr) then
+ if BmpArray[Index] <> nil then
+ Result := BmpArray[Index];
+ if Result = nil then
+ raise Exception.CreateFmt('The bitmap[%d] does not exist',[Index]);
+end;
+
+function TMBitmaps.CreateBMP(w,h : integer): Integer;
+begin
+ result := GetNewIndex;
+ BmpArray[Result] := TMufasaBitmap.Create;
+ BmpArray[Result].SetSize(w,h);
+ BmpArray[Result].Index:= Result;
+end;
+
+function TMBitmaps.AddBMP(_bmp: TMufasaBitmap): Integer;
+begin
+ Result := GetNewIndex;
+ BmpArray[Result] := _bmp;
+end;
+
+function TMBitmaps.CopyBMP(Bitmap: integer): Integer;
+var
+ InputBMP : TMufasaBitmap;
+ OutputBMP : TMUfasaBitmap;
+begin
+ InputBMP := GetBMP(Bitmap);
+ Result := CreateBMP(InputBmp.w,InputBMP.h);
+ OutputBMP := GetBMP(Result);
+ Move(InputBMP.FData[0],OutPutBMP.FData[0],InputBMP.w * InputBMP.h * SizeOf(TRGB32));
+end;
+
+function TMBitmaps.CreateMirroredBitmap(bitmap: Integer;
+ MirrorStyle: TBmpMirrorStyle): Integer;
+var
+ w,h : integer;
+ y,x : integer;
+ Source,Dest : PRGB32;
+begin
+ Source := Bmp[Bitmap].FData;
+ w := BmpArray[Bitmap].Width;
+ h := BmpArray[Bitmap].Height;
+ if MirrorStyle = MirrorLine then
+ Result := CreateBMP(h,w)
+ else
+ Result := CreateBMP(w,h);
+ Dest := BmpArray[Result].FData;
+ case MirrorStyle of
+ MirrorWidth : for y := (h-1) downto 0 do
+ for x := (w-1) downto 0 do
+ Dest[y*w+x] := Source[y*w+w-1-x];
+ MirrorHeight : for y := (h-1) downto 0 do
+ Move(Source[y*w],Dest[(h-1 - y) * w],w*SizeOf(TRGB32));
+ MirrorLine : for y := (h-1) downto 0 do
+ for x := (w-1) downto 0 do
+ Dest[x*h+y] := Source[y*w+x];
+
+ end;
+//Can be optmized, this is just proof of concept
+end;
+
+function TMBitmaps.CreateBMPFromFile(const Path: string): integer;
+begin
+ Result := CreateBMP(0,0);
+ BmpArray[result].LoadFromFile(Path);
+end;
+
+function HexToInt(HexNum: string): LongInt;inline;
+begin
+ Result:=StrToInt('$' + HexNum);
+end;
+
+function TMBitmaps.CreateBMPFromString(width, height: integer; Data: string): integer;
+var
+ I,II: LongWord;
+ DestLen : LongWord;
+ Dest,Source : string;
+ DestPoint, Point : PByte;
+ MufRaw : PRGB24;
+ MufDest : PRGB32;
+
+
+begin
+ Result := CreateBMP(width,height);
+ if (Data <> '') and (Length(Data) <> 6) then
+ begin;
+ Point := Pointer(BmpArray[Result].FData);
+ if (Data[1] = 'b') or (Data[1] = 'm') then
+ begin;
+ Source := Base64DecodeStr(Copy(Data,2,Length(Data) - 1));
+ Destlen := Width * Height * 3;
+ Setlength(Dest,DestLen);
+ if uncompress(PChar(Dest),Destlen,pchar(Source), Length(Source)) = Z_OK then
+ begin;
+ if data[1] = 'm' then //Our encrypted bitmap! Winnor.
+ begin
+ MufRaw:= @Dest[1];
+ MufDest:= PRGB32(Point);
+ for i := width * height - 1 downto 0 do
+ begin
+ MufDest[i].R:= MufRaw[i].R;
+ MufDest[i].G := MufRaw[i].G;
+ MufDest[i].B := MufRaw[i].B;
+ end;
+ end else
+ if Data[1] = 'b'then
+ begin
+ DestPoint := @Dest[1];
+ i := 0;
+ ii := 2;
+ Dec(DestLen);
+ if DestLen > 2 then
+ begin;
+ while (ii < DestLen) do
+ Begin;
+ Point[i]:= DestPoint[ii+2];
+ Point[i+1]:= DestPoint[ii+1];
+ Point[i+2]:= DestPoint[ii];
+ ii := ii + 3;
+ i := i + 4;
+ end;
+ Point[i] := DestPoint[1];
+ Point[i+1] := DestPoint[0];
+ Point[i+2] := DestPoint[ii];
+ end else if (Width = 1) and (Height =1 ) then
+ begin;
+ Point[0] := DestPoint[1];
+ Point[1] := DestPoint[0];
+ Point[2] := DestPoint[2];
+ end;
+ end;
+ end;
+ end else if Data[1] = 'z' then
+ begin;
+ Destlen := Width * Height * 3 *2;
+ Setlength(Dest,DestLen);
+ ii := (Length(Data) - 1) div 2;
+ SetLength(Source,ii);
+ for i := 1 to ii do
+ Source[i] := Chr(HexToInt(Data[i * 2] + Data[i * 2+1]));
+ if uncompress(PChar(Dest),Destlen,pchar(Source), ii) = Z_OK then
+ begin;
+ ii := 1;
+ i := 0;
+ while (II < DestLen) do
+ begin;
+ Point[i+2]:= HexToInt(Dest[ii] + Dest[ii + 1]);
+ Point[i+1]:= HexToInt(Dest[ii+2] + Dest[ii + 3]);
+ Point[i]:= HexToInt(Dest[ii+4] + Dest[ii + 5]);
+ ii := ii + 6;
+ i := i + 4;
+ end;
+ end;
+ end else if LongWord(Length(Data)) = LongWord((Width * Height * 3 * 2)) then
+ begin;
+ ii := 1;
+ i := 0;
+ Destlen := Width * Height * 3 * 2;
+ while (II < DestLen) do
+ begin;
+ Point[i+2]:= HexToInt(Data[ii] + Data[ii + 1]);
+ Point[i+1]:= HexToInt(Data[ii+2] + Data[ii + 3]);
+ Point[i]:= HexToInt(Data[ii+4] + Data[ii + 5]);
+ ii := ii + 6;
+ i := i + 4;
+ end;
+ end;
+ end else
+ begin;
+ if Length(data) = 6 then
+ BmpArray[Result].FastDrawClear(HexToInt(Data));
+// else
+// FastDrawClear(Result,clBlack);
+ end;
+end;
+
+function TMBitmaps.CreateBMPFromString(BmpName: string; width, height: integer;
+ Data: string): integer;
+begin
+ Result := Self.CreateBMPFromString(width,height,data);
+ Bmp[Result].BmpName:= BmpName;
+
+end;
+
+procedure TMBitmaps.FreeBMP(Number: integer);
+var
+ ToDestroy : TMufasaBitmap;
+begin
+ ToDestroy := GetBMP(Number);
+ if Number = BmpsCurr then
+ Dec(BmpsCurr)
+ else
+ begin;
+ inc(FreeSpotsHigh);
+ if FreeSpotsHigh = FreeSpotsLen then
+ begin;
+ inc(FreeSpotsLen);
+ SetLength(FreeSpots, FreeSpotsLen);
+ end;
+ FreeSpots[FreeSpotsHigh] := Number;
+ end;
+ //Just for testing purposes
+ if ToDestroy.BmpName = '' then
+ Writeln(Format('BMP[%d] has been freed.',[number]))
+ else
+ Writeln(Format('BMP[%s] has been freed.',[ToDestroy.BmpName]));
+ FreeAndNil(ToDestroy);
+end;
+
+function TMufasaBitmap.SaveToFile(const FileName: string): boolean;
+var
+ rawImage : TRawImage;
+ Bmp : TLazIntfImage;
+begin
+ ArrDataToRawImage(FData,Point(w,h),RawImage);
+ result := true;
+// Bmp := Graphics.TBitmap.Create;
+ try
+ Bmp := TLazIntfImage.Create(RawImage,false);
+ Bmp.SaveToFile(FileName);
+ Bmp.Free;
+ except
+ result := false;
+ end;
+end;
+
+procedure TMufasaBitmap.LoadFromFile(const FileName: string);
+var
+ LazIntf : TLazIntfImage;
+ RawImageDesc : TRawImageDescription;
+begin
+ if FileExists(FileName) then
+ begin;
+ LazIntf := TLazIntfImage.Create(0,0);
+ RawImageDesc.Init_BPP32_B8G8R8_BIO_TTB(LazIntf.Width,LazIntf.Height);
+ LazIntf.DataDescription := RawImageDesc;
+ LazIntf.LoadFromFile(FileName);
+ if Assigned(FData) then
+ Freemem(FData);
+ Self.W := LazIntf.Width;
+ Self.H := LazIntf.Height;
+ FData := GetMem(Self.W*Self.H*SizeOf(TRGB32));
+ Move(LazIntf.PixelData[0],FData[0],w*h*sizeOf(TRGB32));
+ LazIntf.Free;
+ end;
+end;
+
+function RGBToBGR(Color : TColor) : TRGB32; inline;
+begin;
+ Result.R := Color and $ff;
+ Result.G := Color shr 8 and $ff;
+ Result.B := Color shr 16 and $ff;
+end;
+
+function TMufasaBitmap.Copy: TMufasaBitmap;
+begin
+ Result := TMufasaBitmap.Create;
+ Result.SetSize(self.Width, self.Height);
+ Move(self.FData[0], Result.FData[0],self.w * self.h * SizeOf(TRGB32));
+end;
+
+function TMufasaBitmap.ToTBitmap: TBitmap;
+
+var
+ tr:TRawImage;
+
+begin
+ Result := TBitmap.Create;
+ ArrDataToRawImage(Self.Fdata, point(self.width,self.height), tr);
+ Result.LoadFromRawImage(tr, false);
+end;
+
+function TMufasaBitmap.ToString: string;
+var
+ i : integer;
+ DestLen : longword;
+ DataStr : string;
+ CorrectData : PRGB24;
+begin
+ SetLength(DataStr,w*h*3);
+ CorrectData:= PRGB24(@DataStr[1]);
+ for i := w*h - 1 downto 0 do
+ begin
+ CorrectData[i].R := FData[i].R;
+ CorrectData[i].G := FData[i].G;
+ CorrectData[i].B := FData[i].B;
+ end;
+ DestLen := BufferLen;
+ if compress(Pchar(BufferString),destlen,PChar(DataStr),w*h*3) = Z_OK then
+ begin;
+ SetLength(DataStr,DestLen);
+ move(bufferstring[0],dataStr[1],DestLen);
+ result := 'm' + Base64EncodeStr(datastr);
+ SetLength(datastr,0);
+ end;
+end;
+
+procedure TMufasaBitmap.LoadFromRawImage(RawImage: TRawImage);
+
+var
+ x,y: integer;
+ _24_old_p: PByte;
+ rs,gs,bs:byte;
+ data: PRGB32;
+
+
+begin
+ // clear data
+ Self.SetSize(0,0);
+
+ if (RawImage.Description.BitsPerPixel <> 24) and (RawImage.Description.BitsPerPixel <> 32) then
+ raise Exception.CreateFMT('TMufasaBitmap.LoadFromRawImage - BitsPerPixel is %d', [RawImage.Description.BitsPerPixel]);
+
+ {writeln('Bits per pixel: ' + Inttostr(RawImage.Description.BitsPerPixel)); }
+ if RawImage.Description.LineOrder <> riloTopToBottom then
+ raise Exception.Create('TMufasaBitmap.LoadFromRawImage - LineOrder is not riloTopToBottom');
+
+ { writeln(format('LineOrder: theirs: %d, ours: %d', [RawImage.Description.LineOrder, riloTopToBottom])); }
+
+
+ // Todo, add support for other alignments.
+ { if RawImage.Description.LineEnd <> rileDWordBoundary then
+ raise Exception.Create('TMufasaBitmap.LoadFromRawImage - LineEnd is not rileDWordBoundary'); }
+
+ //writeln(format('LineEnd: t', [RawImage.Description.LineEnd]));
+
+ if RawImage.Description.Format<>ricfRGBA then
+ raise Exception.Create('TMufasaBitmap.LoadFromRawImage - Format is not ricfRGBA');
+
+ // Set w,h and alloc mem.
+ Self.SetSize(RawImage.Description.Width, RawImage.Description.Height);
+
+ {writeln(format('Image size: %d, %d', [w,h])); }
+ rs := RawImage.Description.RedShift shr 3;
+ gs := RawImage.Description.GreenShift shr 3;
+ bs := RawImage.Description.BlueShift shr 3;
+ { writeln(format('Shifts(R,G,B): %d, %d, %d', [rs,gs,bs]));
+ writeln(format('Bits per line %d, expected: %d',
+ [RawImage.Description.BitsPerLine, RawImage.Description.BitsPerPixel * self.w]));
+ }
+
+
+ if RawImage.Description.BitsPerPixel = 32 then
+ Move(RawImage.Data[0], Self.FData[0], self.w * self.h * SizeOf(TRGB32))
+ else
+ begin
+ //FillChar(Self.FData[0], self.w * self.h * SizeOf(TRGB32), 0);
+ data := self.FData;
+
+ _24_old_p := RawImage.Data;
+ for y := 0 to self.h -1 do
+ begin
+ for x := 0 to self.w -1 do
+ begin
+ // b is the first byte in the record.
+ data^.b := _24_old_p[bs];
+ data^.g := _24_old_p[gs];
+ data^.r := _24_old_p[rs];
+ data^.a := 0;
+
+ inc(_24_old_p, 3);
+ inc(data);
+ end;
+
+ case RawImage.Description.LineEnd of
+ rileTight, rileByteBoundary: ; // do nothing
+ rileWordBoundary:
+ while (_24_old_p - RawImage.Data) mod 2 <> 0 do
+ inc(_24_old_p);
+ rileDWordBoundary:
+ while (_24_old_p - RawImage.Data) mod 4 <> 0 do
+ inc(_24_old_p);
+ rileQWordBoundary:
+ while (_24_old_p - RawImage.Data) mod 4 <> 0 do
+ inc(_24_old_p);
+ rileDQWordBoundary:
+ while (_24_old_p - RawImage.Data) mod 8 <> 0 do
+ inc(_24_old_p);
+ end;
+ end;
+ end;
+end;
+
+procedure TMufasaBitmap.LoadFromTBitmap(bmp: TBitmap);
+
+begin
+ bmp.BeginUpdate();
+ LoadFromRawImage(bmp.RawImage);
+ bmp.EndUpdate();
+end;
+
+procedure TMufasaBitmap.FastSetPixel(x, y: integer; Color: TColor);
+begin
+ ValidatePoint(x,y);
+ FData[y*w+x] := RGBToBGR(Color);
+end;
+
+procedure TMufasaBitmap.FastSetPixels(TPA: TPointArray; Colors: TIntegerArray);
+var
+ i,len : integer;
+begin
+ len := High(TPA);
+ if Len <> High(colors) then
+ Raise Exception.CreateFMT('TPA/Colors Length differ',[]);
+ for i := 0 to len do
+ begin;
+ ValidatePoint(TPA[i].x,TPA[i].y);
+ FData[TPA[i].y * w + TPA[i].x] := RGBToBGR(Colors[i]);
+ end;
+end;
+
+procedure TMufasaBitmap.DrawATPA(ATPA: T2DPointArray; Colors: TIntegerArray);
+var
+ lenTPA,lenATPA : integer;
+ i,ii : integer;
+ Color : TRGB32;
+begin
+ lenATPA := High(ATPA);
+ if LenATPA <> High(colors) then
+ Raise Exception.CreateFMT('TPA/Colors Length differ -> %d : %d',[LenATPA + 1,High(Colors) + 1]);
+ for i := 0 to lenATPA do
+ begin;
+ lenTPA := High(ATPA[i]);
+ Color := RGBToBGR(Colors[i]);
+ for ii := 0 to lenTPA do
+ begin;
+ ValidatePoint(ATPA[i][ii].x,ATPA[i][ii].y);
+ FData[ATPA[i][ii].y * w + ATPA[i][ii].x] := Color;
+ end;
+ end;
+end;
+
+
+procedure TMufasaBitmap.DrawATPA(ATPA: T2DPointArray);
+var
+ Colors : TIntegerArray;
+ i,len : integer;
+begin
+ len := high(ATPA);
+ SetLength(colors,len+1);
+ for i := 0 to len do
+ Colors[i] := Random(clwhite);
+ DrawATPA(ATPA,Colors);
+end;
+
+procedure TMufasaBitmap.DrawTPA(TPA: TPointArray; Color: TColor);
+begin
+ DrawATPA(ConvArr([TPA]),ConvArr([Color]));
+end;
+
+function TMufasaBitmap.CreateTPA(SearchCol: TColor): TPointArray;
+var
+ x,y,L,I : Integer;
+ StartPtr : PRGB32;
+ Search : TRGB32;
+begin
+ SetLength(Result,self.Width * Self.Height);
+ L := 0;
+ Search := RGBToBGR(SearchCol);
+ StartPtr := Self.FData;
+ For y := 0 to Self.h - 1 do
+ For x := 0 to self.w - 1 do
+ if LongWord(StartPtr^) = LongWord(SearchCol) then
+ begin;
+ L := L + 1;
+ Result[L].x := x;
+ Result[L].y := y;
+ end;
+ SetLength(Result,L + 1);
+end;
+
+
+
+
+function TMufasaBitmap.FastGetPixel(x, y: integer): TColor;
+begin
+ ValidatePoint(x,y);
+ Result := BGRToRGB(FData[y*w+x]);
+end;
+
+function TMufasaBitmap.FastGetPixels(TPA: TPointArray): TIntegerArray;
+var
+ i,len : integer;
+begin
+ len := high(TPA);
+ SetLength(result,len+1);
+ for i := 0 to len do
+ begin;
+ ValidatePoint(TPA[i].x,TPA[i].y);
+ Result[i] := BGRToRGB(FData[TPA[i].y*w + TPA[i].x]);
+ end;
+end;
+
+procedure TMufasaBitmap.SetTransparentColor(Col: TColor);
+begin
+ TransparentColor:= RGBToBGR(Col);
+ TransparentSet:= True;
+end;
+
+function TMufasaBitmap.GetTransparentColor: TColor;
+begin
+ if TransparentSet then
+ Result := BGRToRGB(TransparentColor)
+ else
+ raise Exception.CreateFmt('Transparent color for Bitmap[%d] isn''t set',[index]);
+end;
+
+procedure TMufasaBitmap.FastDrawClear(Color: TColor);
+var
+ i : integer;
+ Rec : TRGB32;
+begin
+ Rec := RGBToBGR(Color);
+ if h > 0 then
+ begin;
+ for i := (w-1) downto 0 do
+ FData[i] := Rec;
+ for i := (h-1) downto 1 do
+ Move(FData[0],FData[i*w],w*SizeOf(TRGB32));
+ end;
+end;
+
+procedure TMufasaBitmap.FastDrawTransparent(x, y: Integer;
+ TargetBitmap: TMufasaBitmap);
+var
+ MinW,MinH,TargetW,TargetH : Integer;
+ loopx,loopy : integer;
+begin
+ ValidatePoint(x,y);
+ TargetW := TargetBitmap.Width;
+ TargetH := TargetBitmap.height;
+ MinW := Min(w-1,TargetW-x-1);
+ MinH := Min(h-1,TargetH-y-1);
+ if TransparentSet then
+ begin;
+ for loopy := 0 to MinH do
+ for loopx := 0 to MinW do
+ if LongWord(FData[loopy * w + loopx]) <> LongWord(TransparentColor) then
+ TargetBitmap.FData[(loopy + y) * TargetW + loopx + x] := FData[Loopy * w + loopx];
+
+ end
+ else
+ for loopy := 0 to MinH do
+ Move(FData[loopy*w],TargetBitmap.FData[(loopy+y) * TargetW + x],(MinW+1) * SizeOf(TRGB32));
+
+end;
+
+procedure TMufasaBitmap.FastReplaceColor(OldColor, NewColor: TColor);
+var
+ OldCol,NewCol : TRGB32;
+ i : integer;
+begin
+ OldCol := RGBToBGR(OldColor);
+ NewCol := RGBToBGR(NewColor);
+ for i := w*h-1 downto 0 do
+ if LongWord(FData[i]) = LongWord(OldCol) then
+ FData[i] := NewCol;
+end;
+
+procedure TMufasaBitmap.CopyClientToBitmap(MWindow : TObject;Resize : boolean; xs, ys, xe, ye: Integer);
+var
+ y : integer;
+ wi,hi : integer;
+ PtrRet : TRetData;
+begin
+ if Resize then
+ Self.SetSize(xe-xs+1,ye-ys+1);
+
+ wi := Min(xe-xs + 1,Self.w);
+ hi := Min(ye-ys + 1,Self.h);
+
+ PtrRet := TIOManager_Abstract(MWindow).ReturnData(xs,ys,wi,hi);
+
+ for y := 0 to (hi-1) do
+ Move(PtrRet.Ptr[y * (wi + PtrRet.IncPtrWith)], FData[y * self.w],wi * SizeOf(TRGB32));
+ TIOManager_Abstract(MWindow).FreeReturnData;
+end;
+
+procedure TMufasaBitmap.CopyClientToBitmap(MWindow: TObject; Resize: boolean;
+ x, y: integer; xs, ys, xe, ye: Integer);
+var
+ yy : integer;
+ wi,hi : integer;
+ PtrRet : TRetData;
+begin
+ if Resize then
+ Self.SetSize(xe-xs+1 + x,ye-ys+1 + y);
+
+ wi := Min(xe-xs + 1 + x,Self.w);
+ hi := Min(ye-ys + 1 + y,Self.h);
+ PtrRet := TIOManager_Abstract(MWindow).ReturnData(xs,ys,wi - x,hi - y);
+
+ for yy := 0 to (hi-1 - y) do
+ Move(PtrRet.Ptr[yy * (wi - x + PtrRet.IncPtrWith)], FData[(yy + y) * self.w + x],wi * SizeOf(TRGB32));
+ TIOManager_Abstract(MWindow).FreeReturnData;
+end;
+
+
+function RotatePointEdited(p: TPoint; angle, mx, my: Extended): TPoint;
+
+begin
+ Result.X := Ceil(mx + cos(angle) * (p.x - mx) - sin(angle) * (p.y - my));
+ Result.Y := Ceil(my + sin(angle) * (p.x - mx) + cos(angle) * (p.y- my));
+end;
+
+//Scar rotates unit circle-wise.. Oh, scar doesnt update the bounds, so kinda crops ur image.
+procedure TMufasaBitmap.RotateBitmap(angle: Extended;TargetBitmap : TMufasaBitmap );
+var
+ NewW,NewH : integer;
+ CosAngle,SinAngle : extended;
+ MinX,MinY,MaxX,MaxY : integer;
+ i : integer;
+ x,y : integer;
+ OldX,OldY : integer;
+ MiddlePoint : TPoint;
+ NewCorners : array[1..4] of TPoint; //(xs,ye);(xe,ye);(xe,ys);(xs,ys)
+begin
+ MiddlePoint := Point((w-1) div 2,(h-1) div 2);
+ CosAngle := Cos(Angle);
+ SinAngle := Sin(Angle);
+ MinX := MaxInt;
+ MinY := MaxInt;
+ MaxX := 0;
+ MaxY := 0;
+ NewCorners[1]:= RotatePointEdited(Point(0,h-1),angle,middlepoint.x,middlepoint.y);
+ NewCorners[2]:= RotatePointEdited(Point(w-1,h-1),angle,middlepoint.x,middlepoint.y);
+ NewCorners[3]:= RotatePointEdited(Point(w-1,0),angle,middlepoint.x,middlepoint.y);
+ NewCorners[4]:= RotatePointEdited(Point(0,0),angle,middlepoint.x,middlepoint.y);
+ for i := 1 to 4 do
+ begin;
+ if NewCorners[i].x > MaxX then
+ MaxX := NewCorners[i].x;
+ if NewCorners[i].Y > MaxY then
+ MaxY := NewCorners[i].y;
+ if NewCorners[i].x < MinX then
+ MinX := NewCorners[i].x;
+ if NewCorners[i].y < MinY then
+ MinY := NewCorners[i].y;
+ end;
+ Writeln(Format('Min: (%d,%d) Max : (%d,%d)',[MinX,MinY,MaxX,MaxY]));
+ NewW := MaxX - MinX+1;
+ NewH := MaxY - MinY+1;
+ Writeln(format('New bounds: %d,%d',[NewW,NewH]));
+ TargetBitmap.SetSize(NewW,NewH);
+ for y := NewH - 1 downto 0 do
+ for x := NewW - 1 downto 0 do
+ begin;
+ Oldx := Round(MiddlePoint.x + CosAngle * (x + MinX-MiddlePoint.x) - SinAngle * (y + MinY - MiddlePoint.y));
+ Oldy := Round(MiddlePoint.y + SinAngle * (x + MinX-MiddlePoint.x) + CosAngle * (y + MinY-MiddlePoint.y));
+ if not ((Oldx <0) or (Oldx >= w) or (Oldy < 0) or (Oldy >= h)) then
+ TargetBitmap.FData[ y * NewW + x] := Self.FData[OldY * W + OldX];
+ end;
+end;
+
+procedure TMufasaBitmap.Desaturate;
+var
+ I : integer;
+ He,Se,Le : extended;
+ Ptr : PRGB32;
+begin
+ Ptr := FData;
+ for i := (h*w-1) downto 0 do
+ begin;
+ RGBToHSL(Ptr^.R,Ptr^.G,Ptr^.B,He,Se,Le);
+ HSLtoRGB(He,0.0,Le,Ptr^.R,Ptr^.G,Ptr^.B);
+ inc(ptr);
+ end;
+end;
+
+procedure TMufasaBitmap.Desaturate(TargetBitmap: TMufasaBitmap);
+var
+ I : integer;
+ He,Se,Le : extended;
+ PtrOld,PtrNew : PRGB32;
+begin
+ TargetBitmap.SetSize(w,h);
+ PtrOld := Self.FData;
+ PtrNew := TargetBitmap.FData;
+ for i := (h*w-1) downto 0 do
+ begin;
+ RGBToHSL(PtrOld^.R,PtrOld^.G,PtrOld^.B,He,Se,Le);
+ HSLtoRGB(He,0.0,Le,PtrNew^.R,PtrNew^.G,PtrNew^.B);
+ inc(ptrOld);
+ inc(PtrNew);
+ end;
+end;
+
+procedure TMufasaBitmap.GreyScale(TargetBitmap: TMufasaBitmap);
+var
+ I : integer;
+ Lum : byte;
+ PtrOld,PtrNew : PRGB32;
+begin
+ TargetBitmap.SetSize(w,h);
+ PtrOld := Self.FData;
+ PtrNew := TargetBitmap.FData;
+ for i := (h*w-1) downto 0 do
+ begin;
+ Lum := Round(PtrOld^.r * 0.3 + PtrOld^.g * 0.59 + PtrOld^.b * 0.11);
+ PtrNew^.r := Lum;
+ PtrNew^.g := Lum;
+ PtrNew^.b := Lum;
+ inc(ptrOld);
+ inc(PtrNew);
+ end;
+end;
+
+procedure TMufasaBitmap.GreyScale;
+var
+ I : integer;
+ Lum : Byte;
+ Ptr: PRGB32;
+begin
+ Ptr := Self.FData;
+ for i := (h*w-1) downto 0 do
+ begin;
+ Lum := Round(Ptr^.r * 0.3 + Ptr^.g * 0.59 + Ptr^.b * 0.11);
+ Ptr^.r := Lum;
+ Ptr^.g := Lum;
+ Ptr^.b := Lum;
+ inc(ptr);
+ end;
+end;
+
+function BrightnessAdjust(Col: byte; br : integer): byte;inline;
+var
+ temp : integer;
+begin;
+ Temp := Col + Br;
+ if temp < 0 then
+ temp := 0
+ else if temp > 255 then
+ temp := 255;
+ result := temp;
+end;
+procedure TMufasaBitmap.Brightness(br: integer);
+var
+ I : integer;
+ Ptr: PRGB32;
+begin
+ Ptr := Self.FData;
+ for i := (h*w-1) downto 0 do
+ begin;
+ Ptr^.r := BrightnessAdjust(Ptr^.r,br);
+ Ptr^.g := BrightnessAdjust(Ptr^.g,br);
+ Ptr^.b := BrightnessAdjust(Ptr^.b,br);
+ inc(ptr);
+ end;
+end;
+
+procedure TMufasaBitmap.Brightness(TargetBitmap: TMufasaBitmap; br: integer);
+var
+ I : integer;
+ PtrOld,PtrNew : PRGB32;
+begin
+ TargetBitmap.SetSize(w,h);
+ PtrOld := Self.FData;
+ PtrNew := TargetBitmap.FData;
+ for i := (h*w-1) downto 0 do
+ begin;
+ PtrNew^.r := BrightnessAdjust(PtrOld^.r,br);
+ PtrNew^.g := BrightnessAdjust(PtrOld^.g,br);
+ PtrNew^.b := BrightnessAdjust(PtrOld^.b,br);
+ inc(ptrOld);
+ inc(PtrNew);
+ end;
+end;
+
+const
+ Grey = 128;
+function ContrastAdjust(Col: byte; co : extended): byte;inline;
+var
+ temp : integer;
+begin;
+ Temp := floor((col - Grey) * co) + grey;
+ if temp < 0 then
+ temp := 0
+ else if temp > 255 then
+ temp := 255;
+ result := temp;
+end;
+
+procedure TMufasaBitmap.Contrast(co: Extended);
+var
+ I : integer;
+ Ptr: PRGB32;
+begin
+ Ptr := Self.FData;
+ for i := (h*w-1) downto 0 do
+ begin;
+ Ptr^.r := ContrastAdjust(Ptr^.r,co);
+ Ptr^.g := ContrastAdjust(Ptr^.g,co);
+ Ptr^.b := ContrastAdjust(Ptr^.b,co);
+ inc(ptr);
+ end;
+end;
+
+procedure TMufasaBitmap.Contrast(TargetBitmap: TMufasaBitmap; co: Extended);
+var
+ I : integer;
+ PtrOld,PtrNew : PRGB32;
+begin
+ TargetBitmap.SetSize(w,h);
+ PtrOld := Self.FData;
+ PtrNew := TargetBitmap.FData;
+ for i := (h*w-1) downto 0 do
+ begin;
+ PtrNew^.r := ContrastAdjust(PtrOld^.r,co);
+ PtrNew^.g := ContrastAdjust(PtrOld^.g,co);
+ PtrNew^.b := ContrastAdjust(PtrOld^.b,co);
+ inc(ptrOld);
+ inc(PtrNew);
+ end;
+end;
+
+procedure TMufasaBitmap.Invert;
+var
+ i : integer;
+begin
+ for i := (h*w-1) downto 0 do
+ begin;
+ Self.FData[i].r := not Self.FData[i].r;
+ Self.FData[i].g := not Self.FData[i].g;
+ Self.Fdata[i].b := not Self.FData[i].b;
+ end;
+end;
+
+procedure TMufasaBitmap.Posterize(TargetBitmap: TMufasaBitmap; Po: integer);
+var
+ I : integer;
+ PtrOld,PtrNew : PRGB32;
+begin
+ if not InRange(Po,1,255) then
+ Raise exception.CreateFmt('Posterize Po(%d) out of range[1,255]',[Po]);
+ TargetBitmap.SetSize(w,h);
+ PtrOld := Self.FData;
+ PtrNew := TargetBitmap.FData;
+ for i := (h*w-1) downto 0 do
+ begin;
+ PtrNew^.r := min(Round(PtrOld^.r / po) * Po, 255);
+ PtrNew^.g := min(Round(PtrOld^.g / po) * Po, 255);
+ PtrNew^.b := min(Round(PtrOld^.b / po) * Po, 255);
+ inc(ptrOld);
+ inc(PtrNew);
+ end;
+end;
+
+procedure TMufasaBitmap.Posterize(Po: integer);
+var
+ I : integer;
+ Ptr: PRGB32;
+ {a:integer; }
+begin
+ if not InRange(Po,1,255) then
+ Raise exception.CreateFmt('Posterize Po(%d) out of range[1,255]',[Po]);
+ Ptr := Self.FData;
+ for i := (h*w-1) downto 0 do
+ begin;
+ { a := round(ptr^.r / po);
+ a := a * po;
+ ptr^.r := min(a,255);
+ a := round(ptr^.g / po);
+ a := a * po;
+ ptr^.g := min(a,255);
+ a := round(ptr^.b / po);
+ a := a * po;
+ ptr^.b := min(a,255); }
+ ptr^.r := min(Round(ptr^.r / po) * Po, 255);
+ ptr^.g := min(Round(ptr^.g / po) * Po, 255);
+ ptr^.b := min(Round(ptr^.b / po) * Po, 255);
+ inc(ptr);
+ end;
+end;
+
+function TMufasaBitmap.CreateTMask: TMask;
+var
+ x,y : integer;
+ dX,dY : integer;
+begin
+ Result.BlackHi:= -1;
+ Result.WhiteHi:= -1;
+ Result.W := Self.Width;
+ Result.H := Self.Height;
+ SetLength(result.Black,w*h);
+ SetLength(result.White,w*h);
+ dX := w-1;
+ dY := h-1;
+ for y := 0 to dY do
+ for x := 0 to dX do
+ //Check for non-white/black pixels? Not for now atleast.
+ if FData[y*w+x].r = 255 then
+ begin;
+ inc(Result.WhiteHi);
+ Result.White[Result.WhiteHi].x := x;
+ Result.White[Result.WhiteHi].y := y;
+ end else
+ begin;
+ inc(Result.BlackHi);
+ Result.Black[Result.BlackHi].x := x;
+ Result.Black[Result.BlackHi].y := y;
+ end;
+ SetLength(result.Black,Result.BlackHi+1);
+ SetLength(result.White,Result.WhiteHi+1);
+end;
+
+
+
+constructor TMBitmaps.Create(Owner: TObject);
+begin
+ inherited Create;
+ SetLength(BmpArray,50);
+ SetLength(FreeSpots, 50);
+ FreeSpotsLen := 50;
+ BmpsHigh := 49;
+ BmpsCurr := -1;
+ FreeSpotsHigh := -1;
+ Self.Client := Owner;
+end;
+
+destructor TMBitmaps.Destroy;
+var
+ I : integer;
+begin
+ for i := 0 to BmpsCurr do
+ if BmpArray[i] <> nil then
+ begin;
+ if BmpArray[i].BmpName = '' then
+ Writeln(Format('BMP[%d] has not been freed in the script, freeing it now.',[i]))
+ else
+ Writeln(Format('BMP[%s] has not been freed in the script, freeing it now.',[BmpArray[i].BmpName]));
+ FreeAndNil(BmpArray[i]);
+ end;
+ SetLength(BmpArray,0);
+ SetLength(FreeSpots,0);
+ inherited Destroy;
+end;
+
+
+{ TMufasaBitmap }
+procedure TMufasaBitmap.SetSize(Awidth, Aheight: integer);
+var
+ NewData : PRGB32;
+ i,minw,minh : integer;
+begin
+ if (AWidth <> w) or (AHeight <> h) then
+ begin;
+ if AWidth*AHeight <> 0 then
+ begin;
+ NewData := GetMem(AWidth * AHeight * SizeOf(TRGB32));
+ FillDWord(NewData[0],AWidth*AHeight,0);
+ end
+ else
+ NewData := nil;
+ if Assigned(FData) and Assigned(NewData) and (w*H <> 0) then
+ begin;
+ minw := Min(AWidth,w);
+ minh := Min(AHeight,h);
+ for i := 0 to minh - 1 do
+ Move(FData[i*w],Newdata[i*AWidth],minw * SizeOf(TRGB32));
+ end;
+ if Assigned(FData) then
+ FreeMem(FData);
+ FData := NewData;
+ w := AWidth;
+ h := AHeight;
+ end;
+end;
+
+procedure TMufasaBitmap.StretchResize(AWidth, AHeight: integer);
+var
+ NewData : PRGB32;
+ x,y : integer;
+begin
+ if (AWidth <> w) or (AHeight <> h) then
+ begin;
+ if AWidth*AHeight <> 0 then
+ begin;
+ NewData := GetMem(AWidth * AHeight * SizeOf(TRGB32));
+ FillDWord(NewData[0],AWidth*AHeight,0);
+ end
+ else
+ NewData := nil;
+ if Assigned(FData) and Assigned(NewData) and (w*H <> 0) then
+ begin;
+ for y := 0 to AHeight - 1 do
+ for x := 0 to AWidth -1 do
+ NewData[y*AWidth + x] := FData[((y * h)div aheight) * W+ (x * W) div awidth];
+ end;
+ if Assigned(FData) then
+ FreeMem(FData);
+ FData := NewData;
+ w := AWidth;
+ h := AHeight;
+ end;
+end;
+
+procedure TMufasaBitmap.ValidatePoint(x, y: integer);
+begin
+ if (x <0) or (x >= w) or (y < 0) or (y >= h) then
+ raise Exception.CreateFmt('You are accessing an invalid point, (%d,%d) at bitmap[%d]',[x,y,index]);
+end;
+
+constructor TMufasaBitmap.Create;
+begin
+ inherited Create;
+ BmpName:= '';
+ TransparentSet:= False;
+ setSize(0,0);
+ {FData:= nil;
+ w := 0;
+ h := 0; }
+end;
+
+destructor TMufasaBitmap.Destroy;
+begin
+ if Assigned(OnDestroy) then
+ OnDestroy(Self);
+ if Assigned(FData) then
+ Freemem(FData);
+ inherited Destroy;
+end;
+
+end.
+
diff --git a/branches/script-component/Units/MMLCore/client.pas b/branches/script-component/Units/MMLCore/client.pas
new file mode 100644
index 0000000..4da6aaa
--- /dev/null
+++ b/branches/script-component/Units/MMLCore/client.pas
@@ -0,0 +1,85 @@
+{
+ This file is part of the Mufasa Macro Library (MML)
+ Copyright (c) 2009 by Raymond van Venetië and Merlijn Wajer
+
+ MML is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ MML is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with MML. If not, see .
+
+ See the file COPYING, included in this distribution,
+ for details about the copyright.
+
+ Client class for the Mufasa Macro Library
+}
+
+
+unit Client;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+ Classes, SysUtils, MufasaTypes,
+ IOManager, Files, Finder, Bitmaps, dtm, ocr,
+ {$IFDEF MSWINDOWS} os_windows {$ENDIF}
+ {$IFDEF LINUX} os_linux {$ENDIF};
+
+{
+TClient is a full-blown instance of the MML.
+It binds all the components together.
+}
+
+ type
+ TClient = class(TObject)
+ constructor Create(plugin_dir: string);
+ destructor Destroy; override;
+
+ public
+ IOManager: TIOManager;
+ MFiles: TMFiles;
+ MFinder: TMFinder;
+ MBitmaps : TMBitmaps;
+ MDTM: TMDTM;
+ MOCR: TMOCR;
+
+ end;
+
+implementation
+
+// Possibly pass arguments to a default window.
+constructor TClient.Create(plugin_dir: string);
+begin
+ inherited Create;
+
+ IOManager:= TIOManager.Create(plugin_dir);
+ MFiles := TMFiles.Create;
+ MFinder := TMFinder.Create(Self);
+ MBitmaps := TMBitmaps.Create(self);
+ MDTM := TMDTM.Create(self);
+ MOCR := TMOCR.Create(self);
+end;
+
+destructor TClient.Destroy;
+begin
+ MOCR.Free;
+ MDTM.Free;
+ MBitmaps.Free;
+ MFinder.Free;
+ MFiles.Free;
+ IOManager.Free;
+
+ inherited;
+end;
+
+end.
+
diff --git a/branches/script-component/Units/MMLCore/colour_conv.pas b/branches/script-component/Units/MMLCore/colour_conv.pas
new file mode 100644
index 0000000..dea8709
--- /dev/null
+++ b/branches/script-component/Units/MMLCore/colour_conv.pas
@@ -0,0 +1,338 @@
+{
+ This file is part of the Mufasa Macro Library (MML)
+ Copyright (c) 2009 by Raymond van Venetië and Merlijn Wajer
+
+ MML is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ MML is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with MML. If not, see .
+
+ See the file COPYING, included in this distribution,
+ for details about the copyright.
+
+ Colour Conversion Utilities for the Mufasa Macro Library
+}
+
+unit colour_conv;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+ Classes, SysUtils,
+ Graphics, mufasatypes,
+ Math;
+
+
+Function RGBtoColor(r,g,b : byte) : TColor; overload; inline;
+Function RGBtoColor(r,g,b : integer) : TColor; overload; inline;
+Procedure ColorToRGB(Color : integer;out r,g,b : byte); overload; inline;
+Procedure ColorToRGB(Color : integer;out r,g,b : integer); overload; inline;
+Procedure RGBToXYZ(R,G,B : byte;out x,y,z : Extended); inline;
+Procedure XYZToRGB(X,Y,Z : Extended;out R,G,B: byte); inline;
+Procedure RGBToHSL(RR,GG,BB : byte;out H,S,L : Extended); inline;
+Procedure RGBToHSLNonFixed(RR,GG,BB : byte;out H,S,L : Extended); inline;
+Procedure HSLtoRGB(H,S,L : extended;out R,G,B : Byte); inline;
+Procedure ColorToHSL(Col: Integer; out h, s, l: Extended); inline;
+procedure ColorToXYZ(color: Integer; out X, Y, Z: Extended); inline;
+function XYZToColor(X, Y, Z: Extended): TColor; inline;
+function HSLToColor(H, S, L: Extended): TColor; inline;
+function BGRToRGB(BGR : TRGB32) : TColor;inline;
+
+
+
+implementation
+
+Const
+ OneDivThree = 1/3.0;
+ TwoDivThree = 2 / 3.0;
+ OneDivTwoPointFour = 1 / 2.4;
+function BGRToRGB(BGR : TRGB32) : TColor;inline;
+begin;
+ Result := BGR.R or BGR.g shl 8 or BGR.b shl 16;
+end;
+
+Function RGBtoColor(r,g,b : byte): TColor; overload; inline;
+begin;
+ Result := R or g shl 8 or b shl 16;
+end;
+
+{/\
+ Translates the given Red (R), Green (G) and Blue (B) components to a TColor.
+ R, G and B are integers.
+/\}
+
+Function RGBtoColor(r,g,b : integer): TColor; overload; inline;
+begin;
+ Result := R or g shl 8 or b shl 16;
+end;
+
+{/\
+ Translates the given win-32 color in the Red (R), Green (G) and Blue (B)
+ components. R, G and B are bytes.
+/\}
+
+Procedure ColorToRGB(Color : integer;out r,g,b : byte); overload; inline;
+begin
+ R := Color and $ff;
+ G := Color shr 8 and $ff;
+ B := Color shr 16 and $ff;
+end;
+
+{/\
+ Translates the given win-32 color in the Red (R), Green (G) and Blue (B)
+ components. R, G and B are integers.
+/\}
+
+Procedure ColorToRGB(Color : integer;out r,g,b : integer); overload; inline;
+begin
+ R := Color and $ff;
+ G := Color shr 8 and $ff;
+ B := Color shr 16 and $ff;
+end;
+
+{/\
+ Translates the given Red (R), Green (G) and Blue (B) components to
+ X, Y and Z components.
+/\}
+
+Procedure RGBToXYZ(R,G,B : byte;out x,y,z : Extended); inline;
+var
+ Red,Green,Blue : Extended;
+begin;
+ Red := R / 255;
+ Green := G / 255;
+ Blue := B / 255;
+ if Red > 0.04045 then
+ Red := Power( ( Red + 0.055 ) / 1.055 , 2.4) * 100
+ else
+ Red := Red / 7.73994;
+ if Green > 0.04045 then
+ Green := Power( ( Green + 0.055 ) / 1.055 , 2.4) * 100
+ else
+ Green := Green / 7.73994;
+ if Blue > 0.04045 then
+ Blue := Power( ( Blue + 0.055 ) / 1.055 , 2.4) * 100
+ else
+ Blue := Blue / 7.73994;
+ X := Red * 0.4124 + Green * 0.3576 + Blue * 0.1805;
+ Y := Red * 0.2126 + Green * 0.7152 + Blue * 0.0722;
+ Z := Red * 0.0193 + Green * 0.1192 + Blue * 0.9505;
+end;
+
+{/\
+ Translates the given X, Y and Z components to
+ Red (R), Green (G) and Blue (B) components.
+/\}
+
+Procedure XYZToRGB(X,Y,Z : Extended;out R,G,B: byte); inline;
+var
+ TempR,TempG,TempB,Tempx,tempy,tempz : Extended;
+begin;
+ Tempx := X / 100;
+ tempy := Y / 100;
+ tempz := Z / 100;
+ TempR := Tempx * 3.2406 + tempy * -1.5372 + tempz * -0.4986;
+ TempG := Tempx * -0.9689 + tempy * 1.8758 + tempz * 0.0415;
+ TempB := Tempx * 0.0557 + tempy * -0.2040 + tempz * 1.0570;
+ if TempR > 0.0031308 then
+ TempR := 1.055 * ( Power(TempR, (OneDivTwoPointFour)) ) - 0.055
+ else
+ TempR := 12.92 * TempR;
+ if TempG > 0.0031308 then
+ TempG := 1.055 * ( Power(TempG, ( OneDivTwoPointFour)) ) - 0.055
+ else
+ TempG := 12.92 * TempG;
+ if TempB > 0.0031308 then
+ TempB := 1.055 * ( Power(TempB , ( OneDivTwoPointFour )) ) - 0.055
+ else
+ TempB := 12.92 * TempB;
+ R := Round(TempR * 255);
+ G := Round(TempG * 255);
+ B := Round(TempB * 255);
+end;
+
+{/\
+ Translates the given Red (R), Green (G) and Blue (B) components to
+ H (Hue), S (Saturation) and L (Luminance) components.
+/\}
+
+Procedure RGBToHSL(RR,GG,BB : byte;out H,S,L : Extended); inline;
+var
+ R, G, B, D, Cmax, Cmin: Extended;
+begin
+ R := RR / 255;
+ G := GG / 255;
+ B := BB / 255;
+ CMin := R;
+ if G < Cmin then Cmin := G;
+ if B < Cmin then Cmin := B;
+ CMax := R;
+ if G > Cmax then Cmax := G;
+ if B > Cmax then Cmax := B;
+ L := 0.5 * (Cmax + Cmin);
+ if Cmax = Cmin then
+ begin
+ H := 0;
+ S := 0;
+ end else
+ begin;
+ D := Cmax - Cmin;
+ if L < 0.5 then
+ S := D / (Cmax + Cmin)
+ else
+ S := D / (2 - Cmax - Cmin);
+ if R = Cmax then
+ H := (G - B) / D
+ else
+ if G = Cmax then
+ H := 2 + (B - R) / D
+ else
+ H := 4 + (R - G) / D;
+ H := H / 6;
+ if H < 0 then
+ H := H + 1;
+ end;
+ H := H * 100;
+ S := S * 100;
+ L := L * 100;
+end;
+
+{/\
+ Translates the given Red (R), Green (G) and Blue (B) components to
+ H (Hue), S (Saturation) and L (Luminance) components.
+ This function does not multiply it by 100.
+/\}
+
+Procedure RGBToHSLNonFixed(RR,GG,BB : byte;out H,S,L : Extended); inline;
+var
+ R, G, B, D, Cmax, Cmin: Extended;
+begin
+ R := RR / 255;
+ G := GG / 255;
+ B := BB / 255;
+ CMin := R;
+ if G < Cmin then Cmin := G;
+ if B < Cmin then Cmin := B;
+ CMax := R;
+ if G > Cmax then Cmax := G;
+ if B > Cmax then Cmax := B;
+ L := 0.5 * (Cmax + Cmin);
+ if Cmax = Cmin then
+ begin
+ H := 0;
+ S := 0;
+ end else
+ begin;
+ D := Cmax - Cmin;
+ if L < 0.5 then
+ S := D / (Cmax + Cmin)
+ else
+ S := D / (2 - Cmax - Cmin);
+ if R = Cmax then
+ H := (G - B) / D
+ else
+ if G = Cmax then
+ H := 2 + (B - R) / D
+ else
+ H := 4 + (R - G) / D;
+ H := H / 6;
+ if H < 0 then
+ H := H + 1;
+ end;
+end;
+
+{/\
+ Translates the given H (Hue), S (Saturation) and L (Luminance) components to
+ Red (R), Green (G) and Blue (B) components.
+/\}
+
+procedure HSLtoRGB(H, S, L: extended; out R, G, B: Byte); inline;
+var
+ Temp,Temp2 : Extended;
+//begin
+
+Function Hue2RGB(TempHue : Extended) : integer;
+begin;
+ if TempHue < 0 then
+ TempHue := TempHue + 1
+ else if TempHue > 1 then
+ TempHue := TempHue - 1;
+ if ( ( 6 * TempHue ) < 1 ) then
+ Result :=Round(255 * (( Temp + ( Temp2 - Temp ) * 6 * TempHue )))
+ else if ( ( 2 * TempHue ) < 1 ) then
+ Result :=Round(255 * Temp2)
+ else if ( ( 3 * TempHue ) < 2 ) then
+ Result :=Round(255 * (Temp + ( Temp2 - Temp ) * ( ( TwoDivThree ) - TempHue ) * 6))
+ else
+ Result :=Round(255 * Temp);
+end;
+
+begin;
+ H := H / 100;
+ S := S / 100;
+ L := L / 100;
+ if s = 0 then
+ begin;
+ R := Byte(Round(L * 255));
+ G := R;
+ B := R;
+ end else
+ begin;
+ if (L < 0.5) then
+ Temp2 := L * ( 1 + S )
+ else
+ Temp2 := (L + S) - ( S * L);
+ Temp := 2 * L - Temp2;
+ R := Hue2RGB( H + ( OneDivThree ) );
+ G := Hue2RGB( H );
+ B := Hue2RGB( H - ( OneDivThree ) );
+ end;
+end;
+
+{/\
+ Split the Given Color col in H, S, L components.
+/\}
+
+Procedure ColorToHSL(Col: Integer; out h, s, l: Extended); inline;
+Var
+ R, G, B: byte;
+Begin
+ ColorToRGB(Col, R, G, B);
+ RGBToHSL(R, G, B, H, S, L);
+End;
+
+procedure ColorToXYZ(color: Integer; out X, Y, Z: Extended); inline;
+var
+ R, G, B: byte;
+begin
+ ColorToRGB(Color, R, G, B);
+ RGBToXYZ(R, G, B, X, Y, Z);
+end;
+
+function HSLToColor(H, S, L: Extended): TColor; inline;
+var
+ r, g, b: byte;
+begin
+ HSLToRGB(H, S, L, r, g, b);
+ Result := RGBToColor(r, g, b);
+end;
+
+function XYZToColor(X, Y, Z: Extended): TColor; inline;
+var
+ r, g, b: byte;
+begin
+ XYZToRGB(X, Y, Z, r, g, b);
+ Result := RGBToColor(r, g, b);
+end;
+
+end.
diff --git a/branches/script-component/Units/MMLCore/dtm.pas b/branches/script-component/Units/MMLCore/dtm.pas
new file mode 100644
index 0000000..23ff406
--- /dev/null
+++ b/branches/script-component/Units/MMLCore/dtm.pas
@@ -0,0 +1,441 @@
+{
+ This file is part of the Mufasa Macro Library (MML)
+ Copyright (c) 2009 by Raymond van Venetië and Merlijn Wajer
+
+ MML is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ MML is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with MML. If not, see .
+
+ See the file COPYING, included in this distribution,
+ for details about the copyright.
+
+ DTM class for the Mufasa Macro Library
+}
+
+unit dtm;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+ Classes, SysUtils, MufasaTypes;
+
+type
+ TMDTM = class(TObject)
+
+ private
+
+
+ public
+ function AddDTM(d: TDTM): Integer;
+ function AddpDTM(d: pDTM): Integer;
+ function GetDTM(index: Integer; out dtm: pDTM): Boolean;
+ procedure FreeDTM(DTM: Integer);
+ function StringToDTM(S: String): pDTM;
+ function SetDTMName(DTM: Integer; S: String): boolean;
+
+
+ { function FindDTM(DTM: Integer; out x, y: Integer; x1, y1, x2,
+ y2: Integer): Boolean;
+ function FindDTMs(DTM: Integer; out Points: TPointArray; x1, y1, x2,
+ y2: Integer): Boolean;
+ function FindDTMRotated(DTM: Integer; out x, y: Integer; x1, y1, x2,
+ y2: Integer; sAngle, eAngle, aStep: Extended;
+ out aFound: Extended): Boolean;
+ function FindDTMsRotated(DTM: Integer; out Points: TPointArray; x1,
+ y1, x2, y2: Integer; sAngle, eAngle,
+ aStep: Extended; out aFound: T2DExtendedArray)
+ : Boolean;
+ function pFindDTM(DTM: pDTM; out x, y: Integer; x1, y1, x2, y2:
+ Integer): Boolean;
+ function pFindDTMRotated(DTM: pDTM; out x, y: Integer; x1, y1, x2,
+ y2: Integer; sAngle, eAngle, aStep: Extended;
+ out aFound: Extended): Boolean;
+ function pFindDTMsRotated(DTM: pDTM; out Points: TPointArray; x1,
+ y1, x2, y2: Integer; sAngle, eAngle,
+ aStep: Extended; out aFound: T2DExtendedArray)
+ : Boolean;
+ }
+ constructor Create(Owner: TObject);
+ destructor Destroy; override;
+ private
+ Client: TObject;
+ DTMList: Array Of pDTM;
+ FreeSpots: Array Of Integer;
+ end;
+
+implementation
+uses
+ Client, dtmutil, paszlib,
+ graphics, // for TColor
+ math // for max
+ ;
+
+
+
+
+constructor TMDTM.Create(Owner: TObject);
+begin
+ inherited Create;
+ Self.Client := Owner;
+
+ SetLength(DTMList, 0);
+ SetLength(FreeSpots, 0);
+end;
+
+{$DEFINE DTM_DEBUG}
+destructor TMDTM.Destroy;
+
+var
+ i, j: integer;
+ b:boolean;
+begin
+ for i := 0 to high(DTMList) do
+ begin
+ b := false;
+ for j := 0 to high(freespots) do
+ if i = freespots[j] then
+ begin
+ b := true;
+ break;
+ end;
+ if not b then
+ begin;
+ if DTMList[i].n <> '' then
+ Writeln(Format('DTM [%s] was not freed',[DTMList[i].n]))
+ else
+ writeln(Format('DTM [%d] was not freed',[i]));
+ end;
+ end;
+ SetLength(DTMList, 0);
+ SetLength(FreeSpots, 0);
+
+ inherited Destroy;
+end;
+
+Function AreaShape(Color, Tolerance, Size, Shape: Integer; P: TPoint) : Boolean; inline;
+
+Begin
+
+End;
+
+// Rotates the given point (p) by A (in radians) around the point defined by cx, cy.
+
+function RotatePoint(p: TPoint; angle, mx, my: Extended): TPoint; inline;
+
+begin
+ Result.X := Round(mx + cos(angle) * (p.x - mx) - sin(angle) * (p.y - my));
+ Result.Y := Round(my + sin(angle) * (p.x - mx) + cos(angle) * (p.y- my));
+end;
+
+function HexToInt(HexNum: string): LongInt;inline;
+begin
+ Result:=StrToInt('$' + HexNum);
+end;
+
+function TMDTM.StringToDTM(S: String): pDTM;
+var
+ b: PBufferByteArray;
+ Source : String;
+ DestLen : longword;
+ i,ii,c : integer;
+begin
+ SetLength(Result.p,0);
+ SetLength(Result.c,0);
+ SetLength(Result.t,0);
+ SetLength(Result.asz,0);
+ SetLength(Result.ash,0);
+ ii := Length(S);
+ if (ii = 0) or (ii mod 2 <> 0) then
+ Exit;
+ ii := ii div 2;
+ SetLength(Source,ii);
+ for i := 1 to ii do
+ Source[i] := Chr(HexToInt(S[i * 2 - 1] + S[i * 2]));
+ DestLen := BufferLen;
+ if uncompress(Bufferstring,Destlen,pchar(Source), ii) = Z_OK then
+ begin;
+ if (Destlen mod 36) > 0 then
+ begin;
+ Writeln('Invalid DTM');
+ Exit;
+ end;
+ DestLen := DestLen div 36;
+ SetLength(Result.p,DestLen);
+ SetLength(Result.c,DestLen);
+ SetLength(Result.t,DestLen);
+ SetLength(Result.asz,DestLen);
+ SetLength(Result.ash,DestLen);
+ SetLength(Result.bp,DestLen);
+ b := PBufferByteArray(BufferString);
+ for i := 0 to DestLen - 1 do
+ begin;
+ c := i * 36;
+ Result.p[i].x := PInteger(@b^[c+1])^;
+ Result.p[i].y := PInteger(@b^[c+5])^;
+ Result.asz[i] := PInteger(@b^[c+12])^;
+ Result.ash[i] := PInteger(@b^[c+16])^;
+ Result.c[i] := PInteger(@b^[c+20])^;
+ Result.t[i] := PInteger(@b^[c+24])^;
+ Result.bp[i] := False;
+ end;
+ end;
+ result.l := length(result.p);
+end;
+
+function TMDTM.AddDTM(d: TDTM): Integer;
+
+begin
+ if Length(FreeSpots) > 0 then
+ begin
+ DTMList[FreeSpots[High(FreeSpots)]] := TDTMTopDTM(d);
+ Result := FreeSpots[High(FreeSpots)];
+ SetLength(FreeSpots, High(FreeSpots));
+ end
+ else
+ begin
+ SetLength(DTMList, Length(DTMList) + 1);
+ DTMList[High(DTMList)] := TDTMTopDTM(d);
+ Result := High(DTMList);
+ end;
+end;
+
+{/\
+ Adds the given pDTM to the DTM Array, and returns it's index.
+/\}
+
+function TMDTM.AddpDTM(d: pDTM): Integer;
+
+begin
+ if Length(FreeSpots) > 0 then
+ begin
+ DTMList[FreeSpots[High(FreeSpots)]] := d;
+ Result := FreeSpots[High(FreeSpots)];
+ SetLength(FreeSpots, High(FreeSpots));
+ end
+ Else
+ begin
+ SetLength(DTMList, Length(DTMList) + 1);
+ DTMList[High(DTMList)] := d;
+ Result := High(DTMList);
+ end;
+end;
+
+{/\
+ Returns the DTM (pDTM type) in the variable dtm at the given index.
+ Returns true is succesfull, false if the dtm does not exist.
+/\}
+
+function TMDTM.GetDTM(index: Integer; out dtm: pDTM): Boolean;
+begin
+ Result := True;
+ try
+ dtm := DTMList[index];
+ except
+ begin
+ raise Exception.CreateFmt('The given DTM Index ([%d]) is invalid.',
+ [index]);
+ //WriteLn('DTM Index ' + IntToStr(index) + ' does not exist');
+ Result := False;
+ end;
+ end
+end;
+
+function TMDTM.SetDTMName(DTM: Integer; s: string): boolean;
+var
+ dtm_: pDTM;
+begin
+ if(GetDTM(dtm, dtm_)) then
+ begin
+ dtm_.n := s;
+ Exit(True);
+ end;
+ raise Exception.CreateFMT('SetDTMName: The given DTM %d does not exist.', [DTM]);
+ Exit(False);
+end;
+
+{/\
+ Unloads the DTM at the given index from the DTM Array.
+ Notes:
+ Will keep track of not used index, so it is very memory efficient.
+/\}
+
+Procedure TMDTM.FreeDTM(DTM: Integer);
+begin
+ try
+ SetLength(DTMList[DTM].p, 0);
+ SetLength(DTMList[DTM].c, 0);
+ SetLength(DTMList[DTM].t, 0);
+ SetLength(DTMList[DTM].asz, 0);
+ SetLength(DTMList[DTM].ash, 0);
+ DTMList[DTM].l := 0;
+ except
+ raise Exception.CreateFmt('Invalid DTM passed to FreeDTM', []);
+ //WriteLn('Invalid DTM');
+ end;
+ SetLength(FreeSpots, Length(FreeSpots) + 1);
+ FreeSpots[High(FreeSpots)] := DTM;
+end;
+
+
+{
+ Tries to find the given DTM (index). If found will put the point the dtm has
+ been found at in x, y and result to true.
+}
+{function TMDTM.FindDTM(DTM: Integer; out x, y: Integer; x1, y1, x2, y2: Integer): Boolean;
+var
+ temp: pDTM;
+begin
+ if GetDTM(DTM, temp) then
+ Result := pFindDTM(temp, x, y, x1, y1, x2, y2)
+ else
+ begin
+ x := 0;
+ y := 0;
+ Result := False;
+ end;
+end; }
+
+{
+ Tries to find the given pDTM. If found will put the point the dtm has
+ been found at in x, y and result to true.
+}
+
+{function TMDTM.pFindDTM(DTM: pDTM; out x, y: Integer; x1, y1, x2, y2: Integer): Boolean;
+
+
+begin
+
+end; }
+
+{/\
+ Tries to find the given DTM (index). Will return true if it has found one or more
+ DTM's. All the occurances are stored in the Points (TPointArray)
+/\}
+
+{function TMDTM.FindDTMs(DTM: Integer; out Points: TPointArray; x1, y1, x2, y2: Integer): Boolean;
+Var
+ temp: pDTM;
+Begin
+ If GetDTM(DTM, temp) Then
+ Result := pFindDTMs(temp, Points, x1, y1, x2, y2)
+ Else
+ Begin
+ SetLength(Points, 0);
+ Result := False;
+ End;
+End; }
+
+{/\
+ Tries to find the given pDTM. Will return true if it has found one or more
+ DTM's. All the occurances are stored in the Points (TPointArray)
+/\}
+
+
+
+{wat}
+// Then, first find all occurances of all colours on the given client.
+// Each point has a colour, and we call them C_0...C_n.
+// MP denotes the points of the main point colour on the client.
+// P_i denotes the points on the client for C_i
+// O_i denotes the point offset, and possible area shape and size.
+// B_i denotes a boolean representation of P_i for C_i, for C_1...C_n.
+// B_0 and O_0 are the merry exception here, as we don't need them for C_0,
+// which we will show later.
+
+// I hope it is clear how this will be respresented in computer data
+// structures.
+
+// Now, we iterate for i in range(1, n),
+ // We use MP_i, and iterate for j in range(0, dtm_points),
+ // Calculate the B_j indices (with MP_i and O_j) for each j, and
+ // see if B_j is not true, go on with MP_i + 1.
+ // Possible using areasize/shape.
+
+ // else, if B_j is true, continue with this inner loop.
+ // If B_{0...dtm_points} were all true, the point is valid.
+
+{/\
+ Tries to find the given DTM (index). If found will put the point the dtm has
+ been found at in x, y and result to true.
+ Will rotate the DTM starting at sAngle, increasing by aStep until eAngle has been reached, or when the DTM has been found.
+ Returns all Angles in an Extended array.
+/\}
+
+{Function TMDTM.FindDTMRotated(DTM: Integer; out x, y: Integer; x1, y1, x2, y2: Integer; sAngle, eAngle, aStep: Extended; out aFound: Extended): Boolean;
+Var
+ temp: pDTM;
+Begin
+ If GetDTM(DTM, temp) Then
+ Result := pFindDTMRotated(temp, x, y, x1, y1, x2, y2, sAngle, eAngle, aStep, aFound)
+ Else
+ Begin
+ x := 0;
+ y := 0;
+ aFound := 0.0;
+ Result := False;
+ End;
+End; }
+
+{/\
+ Tries to find the given pDTM. If found will put the point the dtm has
+ been found at in x, y and result to true.
+ Will rotate the DTM starting at sAngle, increasing by aStep until eAngle has been reached, or when the DTM has been found.
+ Returns all Angles in an Extended array.
+/\}
+
+{Function TMDTM.pFindDTMRotated(DTM: pDTM; out x, y: Integer; x1, y1, x2, y2: Integer; sAngle, eAngle, aStep: Extended; out aFound: Extended): Boolean;
+
+Begin
+
+End; }
+
+{/\
+ Tries to find the given DTM (index). Will return true if it has found one or more
+ DTM's. All the occurances are stored in the Points (TPointArray)
+ Will rotate the DTM starting at sAngle, increasing by aStep until eAngle has been reached.
+ Does not stop rotating when one occurance of a DTM has been found.
+ Returns all Angles in a Two Dimensional Extended array.
+/\}
+
+{Function TMDTM.FindDTMsRotated(DTM: Integer; out Points: TPointArray; x1, y1, x2, y2: Integer; sAngle, eAngle, aStep: Extended; out aFound: T2DExtendedArray): Boolean;
+Var
+ temp: pDTM;
+Begin
+ If GetDTM(DTM, temp) Then
+ Result := pFindDTMsRotated(temp, Points, x1, y1, x2, y2, sAngle, eAngle, aStep, aFound)
+ Else
+ Begin
+ SetLength(Points, 0);
+ SetLength(aFound, 0);
+ Result := False;
+ End;
+End; }
+
+{/\
+ Tries to find the given pDTM. Will return true if it has found one or more
+ DTM's. All the occurances are stored in the Points (TPointArray)
+ Will rotate the DTM starting at sAngle, increasing by aStep until eAngle has been reached.
+ Does not stop rotating when one occurance of a DTM has been found.
+ Returns all Angles in a Two Dimensional Extended array.
+/\}
+
+{Function TMDTM.pFindDTMsRotated(DTM: pDTM; out Points: TPointArray; x1, y1, x2, y2: Integer; sAngle, eAngle, aStep: Extended; out aFound: T2DExtendedArray): Boolean;
+
+Begin
+ // Don't forget to pre calculate the rotated points at the start.
+ // Saves a lot of rotatepoint() calls.
+End; }
+
+end.
+
diff --git a/branches/script-component/Units/MMLCore/dtmutil.pas b/branches/script-component/Units/MMLCore/dtmutil.pas
new file mode 100644
index 0000000..f84ea8c
--- /dev/null
+++ b/branches/script-component/Units/MMLCore/dtmutil.pas
@@ -0,0 +1,270 @@
+{
+ This file is part of the Mufasa Macro Library (MML)
+ Copyright (c) 2009 by Raymond van Venetië and Merlijn Wajer
+
+ MML is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ MML is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with MML. If not, see .
+
+ See the file COPYING, included in this distribution,
+ for details about the copyright.
+
+ DTM Utilities for the Mufasa Macro Library
+}
+
+unit dtmutil;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+ Classes, SysUtils, MufasaTypes;
+
+
+Function pDTMToTDTM(Const DTM: pDTM): TDTM;
+Function tDTMTopDTM(Const DTM: TDTM): pDTM;
+Procedure PrintpDTM(aDTM : pDTM);
+
+procedure initdtm(out d: pdtm; len: integer);
+function ValidMainPointBox(var dtm: pDTM; const x1, y1, x2, y2: Integer): TBox;
+function ValidMainPointBoxRotated(var dtm: pDTM; const x1, y1, x2, y2: Integer): TBox;
+function DTMConsistent(var dtm: pdtm): boolean;
+procedure NormalizeDTM(var dtm: pdtm);
+
+const
+ dtm_Rectangle = 0;
+ dtm_Cross = 1;
+ dtm_DiagonalCross = 2;
+ dtm_Circle = 3;
+ dtm_Triangle = 4;
+
+implementation
+uses math;
+
+// macro
+procedure initdtm(out d: pdtm; len: integer);
+var
+ i: integer;
+begin
+ d.l := len;
+ d.n := '';
+ setlength(d.p, len);
+ setlength(d.c, len);
+ setlength(d.t, len);
+ setlength(d.ash, len);
+ setlength(d.asz, len);
+ setlength(d.bp, len);
+
+ FillChar(d.p[0], SizeOf(TPoint) * len, 0);
+ FillChar(d.c[0], SizeOf(Integer) * len, 0);
+ FillChar(d.t[0], SizeOf(Integer) * len, 0);
+ FillChar(d.ash[0], SizeOf(Integer) * len, 0);
+
+ // Better set it to 1, than fill with 0.
+ FillChar(d.asz[0], SizeOf(Integer) * len, 0);
+
+ //FillChar(d.gp[0], SizeOf(Boolean) * len, 0);
+ for i := 0 to len - 1 do
+ d.bp[i] := False;
+end;
+
+Procedure PrintpDTM(aDTM : pDTM);
+var
+ i : integer;
+begin;
+ i := 0;
+ if adtm.n <> '' then
+ writeln('Name: ' + aDTM.n);
+ WriteLn('MainPoint ' + inttostr(aDTM.p[i].x) + ', ' + inttostr(aDTM.p[i].y) + ' col: ' + inttostr(aDTM.c[i]) + ', tol: ' + inttostr(aDTM.t[i]) + '; ashape ' + inttostr(aDTM.ash[i]) + ' asize ' + inttostr(aDTM.asz[i])+ ', Bad Point: ' + BoolToStr(aDTM.bp[i]));
+ for I := 1 to High(aDTM.p) do
+ WriteLn('SubPoint['+IntToStr(I) + '] ' + inttostr(aDTM.p[i].x) + ', ' + inttostr(aDTM.p[i].y) + ' col: ' + inttostr(aDTM.c[i]) + ', tol: ' + inttostr(aDTM.t[i]) + '; ashape ' + inttostr(aDTM.ash[i]) + ' asize ' + inttostr(aDTM.asz[i]) + ', Bad Point: ' + BoolToStr(aDTM.bp[i]));
+end;
+
+Function pDTMToTDTM(Const DTM: pDTM): TDTM;
+
+Var
+ Temp: TDTMPointDef;
+ I: Integer;
+
+Begin
+ For I := 0 To 0 Do
+ Begin
+ Temp.X := DTM.p[i].x;
+ Temp.Y := DTM.p[i].y;
+ Temp.AreaSize := DTM.asz[i];
+ Temp.AreaShape := DTM.ash[i];
+ Temp.Color := DTM.c[i];
+ Temp.Tolerance := DTM.t[i];
+ End;
+ Result.MainPoint := Temp;
+ SetLength(Result.SubPoints, Length(DTM.p) - 1);
+
+ For I := 1 To DTM.l-1 Do
+ Begin
+ Temp.X := 0; Temp.Y := 0; Temp.AreaSize := 0; Temp.AreaShape := 0; Temp.Color := 0; Temp.Tolerance := 0;
+ Temp.X := DTM.p[i].x;
+ Temp.Y := DTM.p[i].y;
+ Temp.AreaSize := DTM.asz[i];
+ Temp.AreaShape := DTM.ash[i];
+ Temp.Color := DTM.c[i];
+ Temp.Tolerance := DTM.t[i];
+ Result.SubPoints[I - 1] := Temp;
+ End;
+End;
+
+{/\
+ Converts a TDTM to a pDTM.
+/\}
+
+Function tDTMTopDTM(Const DTM: TDTM): pDTM;
+
+Var
+ //Temp: TDTMPointDef;
+ I: Integer;
+
+Begin
+ SetLength(Result.p, Length(DTM.SubPoints) + 1);
+ SetLength(Result.c, Length(DTM.SubPoints) + 1);
+ SetLength(Result.t, Length(DTM.SubPoints) + 1);
+ SetLength(Result.asz, Length(DTM.SubPoints) + 1);
+ SetLength(Result.ash, Length(DTM.SubPoints) + 1);
+ SetLength(Result.bp, Length(DTM.SubPoints) + 1);
+
+ Result.p[0].x := DTM.MainPoint.x;
+ Result.p[0].y := DTM.MainPoint.y;
+ Result.c[0] := DTM.MainPoint.Color;
+ Result.t[0] := DTM.MainPoint.Tolerance;
+ Result.asz[0] := DTM.MainPoint.AreaSize;
+ Result.ash[0] := DTM.MainPoint.AreaShape;
+
+ For I := 1 To Length(DTM.SubPoints) Do // High + 1 = Length
+ Begin
+ Result.p[I].x := DTM.SubPoints[I - 1].x;
+ Result.p[I].y := DTM.SubPoints[I - 1].y;
+ Result.c[I] := DTM.SubPoints[I - 1].Color;
+ Result.t[I] := DTM.SubPoints[I - 1].Tolerance;
+ Result.asz[I] := DTM.SubPoints[I - 1].AreaSize;
+ Result.ash[I] := DTM.SubPoints[I - 1].AreaShape;
+ End;
+
+ Result.l := length(Result.p);
+ setlength(result.bp, result.l);
+ for i := 0 to result.l -1 do
+ result.bp[i] := false;
+End;
+
+{ TODO: Check if bounds are correct? }
+function DTMConsistent(var dtm: pdtm): boolean;
+var
+ i: integer;
+begin
+ if dtm.l = 0 then
+ Exit(False);
+ if dtm.l <> length(dtm.p) then
+ Exit(False);
+ if dtm.l <> length(dtm.c) then
+ Exit(False);
+ if dtm.l <> length(dtm.t) then
+ Exit(False);
+ if dtm.l <> length(dtm.asz) then
+ Exit(False);
+ if dtm.l <> length(dtm.ash) then
+ Exit(False);
+ if dtm.l <> length(dtm.bp) then
+ Exit(False);
+ for i := 0 to dtm.l-1 do
+ if dtm.asz[i] < 0 then
+ Exit(False);
+ for i := 0 to dtm.l-1 do
+ if dtm.c[i] < 0 then
+ Exit(False);
+ for i := 0 to dtm.l-1 do
+ if dtm.t[i] < 0 then
+ Exit(False);
+ for i := 0 to dtm.l-1 do
+ if dtm.ash[i] < 0 then
+ Exit(False);
+ Exit(True);
+end;
+
+procedure NormalizeDTM(var dtm: pdtm);
+var
+ i:integer;
+begin
+ for i := 0 to dtm.l do
+ dtm.p[i] := dtm.p[i] - dtm.p[0];
+end;
+
+Function ValidMainPointBox(var dtm: pDTM; const x1, y1, x2, y2: Integer): TBox;
+
+var
+ i: Integer;
+ b: TBox;
+
+begin
+ // writeln(format('%d, %d', [0,0]));
+ for i := 1 to high(dtm.c) do
+ begin
+ dtm.p[i] := dtm.p[i] - dtm.p[0];
+ // writeln(format('%d, %d', [dtm.p[i].x, dtm.p[i].y]));
+ end;
+ dtm.p[0] := dtm.p[0] - dtm.p[0];
+
+
+ FillChar(b, SizeOf(TBox), 0);
+ for i := 0 to high(dtm.c) do
+ begin
+ b.x1 := min(b.x1, dtm.p[i].x - dtm.asz[i]);
+ b.y1 := min(b.y1, dtm.p[i].y - dtm.asz[i]);
+ b.x2 := max(b.x2, dtm.p[i].x + dtm.asz[i]);
+ b.y2 := max(b.y2, dtm.p[i].y + dtm.asz[i]);
+ end;
+
+ //FillChar(Result, SizeOf(TBox), 0);
+ //writeln(Format('DTM Bounding Box: %d, %d : %d, %d', [b.x1, b.y1,b.x2,b.y2]));
+ Result.x1 := x1 - b.x1;
+ Result.y1 := y1 - b.y1;
+ Result.x2 := x2 - b.x2;
+ Result.y2 := y2 - b.y2;
+end;
+
+Function ValidMainPointBoxRotated(var dtm: pDTM; const x1, y1, x2, y2: Integer): TBox;
+
+var
+ i, d: Integer;
+
+begin
+ for i := 1 to high(dtm.c) do
+ begin
+ dtm.p[i] := dtm.p[i] - dtm.p[0];
+ end;
+ dtm.p[0] := dtm.p[0] - dtm.p[0];
+
+
+ for i := 0 to high(dtm.c) do
+ begin
+ d := max(dtm.p[i].x - dtm.asz[i], d);
+ d := max(dtm.p[i].x + dtm.asz[i], d);
+ d := max(dtm.p[i].y - dtm.asz[i], d);
+ d := max(dtm.p[i].y + dtm.asz[i], d);
+ end;
+
+ Result.x1 := d;
+ Result.y1 := d;
+ Result.x2 := d;
+ Result.y2 := d;
+end;
+
+
+end.
+
diff --git a/branches/script-component/Units/MMLCore/files.pas b/branches/script-component/Units/MMLCore/files.pas
new file mode 100644
index 0000000..5056feb
--- /dev/null
+++ b/branches/script-component/Units/MMLCore/files.pas
@@ -0,0 +1,511 @@
+{
+ This file is part of the Mufasa Macro Library (MML)
+ Copyright (c) 2009 by Raymond van Venetië and Merlijn Wajer
+
+ MML is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ MML is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with MML. If not, see .
+
+ See the file COPYING, included in this distribution,
+ for details about the copyright.
+
+ Files Class for the Mufasa Macro Library
+}
+
+unit files;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+ Classes, SysUtils, MufasaTypes;
+
+type
+ TMufasaFile = record
+ Path: String;
+ FS: TFileStream;
+ BytesRead, Mode: Integer;
+ end;
+
+ TMufasaFilesArray = Array Of TMufasaFile;
+
+ TMFiles = class(TObject)
+ constructor Create;
+ destructor Destroy; override;
+ public
+ function CreateFile(Path: string): Integer;
+ function OpenFile(Path: string; Shared: Boolean): Integer;
+ function RewriteFile(Path: string; Shared: Boolean): Integer;
+ procedure CloseFile(FileNum: Integer);
+ function EndOfFile(FileNum: Integer): Boolean;
+ function FileSizeMuf(FileNum: Integer): LongInt;
+ function ReadFileString(FileNum: Integer; out s: string; x: Integer): Boolean;
+ function WriteFileString(FileNum: Integer; s: string): Boolean;
+ Function SetFileCharPointer(FileNum, cChars, Origin: Integer): Integer;
+ function FilePointerPos(FileNum: Integer): Integer;
+ protected
+ MFiles: TMufasaFilesArray;
+ FreeSpots: Array Of Integer;
+ private
+ procedure FreeFileList;
+ function AddFileToManagedList(Path: string; FS: TFileStream; Mode: Integer): Integer;
+
+ end;
+
+ // We don't need one per object. :-)
+ function GetFiles(Path, Ext: string): TStringArray;
+ function GetDirectories(Path: string): TstringArray;
+
+implementation
+uses
+ {$IFDEF MSWINDOWS}Windows,{$ENDIF} IniFiles;
+
+{ GetFiles in independant of the TMFiles class }
+
+function GetFiles(Path, Ext: string): TstringArray;
+var
+ SearchRec : TSearchRec;
+ c : integer;
+begin
+ c := 0;
+ if FindFirst(Path + '*.' + ext, faAnyFile, SearchRec) = 0 then
+ begin
+ repeat
+ inc(c);
+ SetLength(Result,c);
+ Result[c-1] := SearchRec.Name;
+ until FindNext(SearchRec) <> 0;
+ SysUtils.FindClose(SearchRec);
+ end;
+end;
+
+function GetDirectories(Path: string): TstringArray;
+var
+ SearchRec : TSearchRec;
+ c : integer;
+begin
+ c := 0;
+ if FindFirst(Path + '*', faDirectory, SearchRec) = 0 then
+ begin
+ repeat
+ if SearchRec.Name[1] = '.' then
+ continue;
+ inc(c);
+ SetLength(Result,c);
+ Result[c-1] := SearchRec.Name;
+ until FindNext(SearchRec) <> 0;
+ SysUtils.FindClose(SearchRec);
+ end;
+end;
+
+constructor TMFiles.Create;
+begin
+ inherited Create;
+ SetLength(Self.MFiles, 0);
+ SetLength(Self.FreeSpots, 0);
+end;
+
+procedure TMFiles.FreeFileList;
+var
+ I : integer;
+begin;
+ For I := 0 To High(MFiles) Do
+ If MFiles[i].FS <> nil Then
+ Begin
+ WriteLn('You forgot to free a file... (Path = ' + MFiles[i].Path + ')');
+ Try
+ MFiles[I].FS.Free;
+ Except
+ WriteLn('FreeFileList - Exception when freeing');
+ End;
+ End;
+ SetLength(MFiles, 0);
+ SetLength(FreeSpots, 0);
+end;
+
+destructor TMFiles.Destroy;
+begin
+ FreeFileList;
+ inherited;
+end;
+
+Function TMFiles.AddFileToManagedList(Path: String; FS: TFileStream; Mode: Integer): Integer;
+Var
+ tFile: TMufasaFile;
+Begin
+ tFile.Path := Path;
+ tFile.FS := FS;
+ tFile.Mode := Mode;
+ tFile.BytesRead := 0;
+
+ If Length(FreeSpots) > 0 Then
+ Begin
+ //WriteLn('There is a free spot: ' + IntToStr(FreeSpots[High(FreeSpots)]));
+ MFiles[FreeSpots[High(FreeSpots)]] := tFile;
+ Result := FreeSpots[High(FreeSpots)];
+ SetLength(FreeSpots, High(FreeSpots));
+ End Else
+ Begin
+ // Increase by * 2.
+ //WriteLn('No Free Spot. Increasing the size');
+ SetLength(MFiles, Length(MFiles) + 1);
+ //Writeln('Length of Files: ' + IntToStr(Length(Files)));
+ MFiles[High(MFiles)] := tFile;
+ Result := High(MFiles);
+ End;
+End;
+
+Function TMFiles.SetFileCharPointer(FileNum, cChars, Origin: Integer): Integer;
+Begin
+ If(FileNum < 0) or (FileNum >= Length(MFiles)) Then
+ Begin
+ WriteLn('Invalid File Num');
+ Result := -1;
+ Exit;
+ End;
+
+ {If Files[FileNum].Handle = -1 Then
+ Begin
+ WriteLn('SetFileCharPointer: Invalid Internal Handle');
+ Result := -1;
+ Exit;
+ End;}
+
+ case Origin of
+ fsFromBeginning:
+ If(cChars < 0) Then
+ Begin
+ Writeln('fsFromBeginning takes no negative cChars.');
+ Result := -1;
+ Exit;
+ End;
+ fsFromCurrent:
+ ;
+ fsFromEnd:
+ If(cChars > 0) Then
+ Begin
+ Writeln('fsFromEnd takes no positive cChars.');
+ Result := -1;
+ Exit;
+ End;
+ else
+ Begin
+ WriteLn('Invalid Origin: ' + IntToStr(Origin));
+ Result := -1;
+ Exit;
+ End;
+ End;
+
+ Try
+ Result := MFiles[FileNum].FS.Seek(cChars, Origin);
+ Except
+ WriteLn('SetFileCharPointer - Exception Occured.');
+ End;
+ //Result := FileSeek(Files[FileNum].Handle, cChars, Origin);
+End;
+
+{/\
+ Creates a file for reading/writing.
+ Returns the handle (index) to the File Array.
+ Returns -1 if unsuccesfull.
+/\}
+
+function TMFiles.CreateFile(Path: string): Integer;
+
+Var
+ FS: TFileStream;
+
+begin
+ Try
+ FS := TFileStream.Create(Path, fmCreate);
+ Except
+ Result := -1;
+ WriteLn('CreateFile - Exception. Could not create file. Returning -1');
+ Exit;
+ End;
+
+ Result := AddFileToManagedList(Path, FS, fmCreate);
+end;
+
+{/\
+ Opens a file for reading.
+ Returns the handle (index) to the File Array.
+ Returns -1 if unsuccesfull.
+/\}
+
+function TMFiles.OpenFile(Path: string; Shared: Boolean): Integer;
+
+Var
+ FS: TFileStream;
+ fMode: Integer;
+
+begin
+ If Shared Then
+ fMode := fmOpenRead or fmShareDenyNone
+ Else
+ fMode := fmOpenRead or fmShareExclusive;
+
+ Try
+ FS := TFileStream.Create(Path, fMode)
+ Except
+ Result := -1;
+ WriteLn('OpenFile - Exception. Could not create file. Returning -1');
+ Exit;
+ End;
+
+ Result := AddFileToManagedList(Path, FS, fMode);
+
+ {Result := FileOpen(Path, fmOpenRead);
+ If Result <> -1 Then
+ Begin
+ //WriteLn('File was successfully opened');
+ Result := AddFileToManagedList(Path, Result, fmOpenRead);
+ {If Result <> -1 Then
+ WriteLn('File was successfully added: ' + IntToStr(Result));}
+ End Else
+ Begin
+ WriteLn('Could not open file. Returning -1');
+ End; }
+end;
+
+{/\
+ Opens a file for writing.
+ Returns the handle (index) to the File Array.
+ Returns -1 if unsuccesfull.
+/\}
+
+function TMFiles.RewriteFile(Path: string; Shared: Boolean): Integer;
+
+Var
+ FS: TFileStream;
+ fMode: Integer;
+begin
+ If Shared Then
+ fMode := fmOpenReadWrite or fmShareDenyNone or fmCreate
+ Else
+ fMode := fmOpenReadWrite or fmShareDenyWrite or fmShareDenyRead or fmCreate;
+
+ Try
+ FS := TFileStream.Create(Path, fMode);
+ Except
+ Result := -1;
+ WriteLn('ReWriteFile - Exception. Could not create file. Returning -1');
+ Exit;
+ End;
+
+ Result := AddFileToManagedList(Path, FS, fMode);
+
+ {Result := FileOpen(Path, fmOpenReadWrite);
+ If Result <> -1 Then
+ Begin
+ //WriteLn('File was successfully opened.');
+ Result := AddFileToManagedList(Path, Result, fmOpenReadWrite);
+ {If Result <> -1 Then
+ WriteLn('File was successfully added: ' + IntToStr(Result)); }
+ End Else
+ Begin
+ WriteLn('Could not open file. Returning -1');
+ End; }
+end;
+
+{/\
+ Free's the given File at the given index.
+/\}
+procedure TMFiles.CloseFile(FileNum: Integer);
+
+begin
+ //Writeln('Length of Files: ' + IntToStr(Length(Files)));
+ If (FileNum >= Length(MFiles)) or (FileNum < 0) Then
+ Begin
+ WriteLn('CloseFile. Invalid FileNum: ' + IntToStr(FileNum));
+ Exit;
+ End;
+
+ Try
+ MFiles[FileNum].FS.Free;
+ Except
+ WriteLn('CloseFile, exception when freeing the file...');
+ Exit;
+ End;
+
+ MFiles[FileNum].FS := nil;
+ SetLength(FreeSpots, Length(FreeSpots) + 1);
+ FreeSpots[High(FreeSpots)] := FileNum;
+
+ {If Files[FileNum].Handle = -1 Then
+ Begin
+ WriteLn('CloseFile: Invalid Internal Handle');
+ Exit;
+ End;
+ FileClose(Files[FileNum].Handle); }
+
+end;
+
+{/\
+ Returns true if the BytesRead of the given FileNum (Index) has been reached.
+ Also returns true if the FileNum is not valid.
+/\}
+
+function TMFiles.EndOfFile(FileNum: Integer): Boolean;
+begin
+ If(FileNum < 0) or (FileNum >= Length(MFiles)) Then
+ Begin
+ WriteLn('Invalid File Num');
+ Result := True;
+ Exit;
+ End;
+ If MFiles[FileNum].FS = nil Then
+ Begin
+ WriteLn('EndOfFile: Invalid Internal Handle');
+ Result := True;
+ Exit;
+ End;
+
+ Result := FilePointerPos(FileNum) >= FileSizeMuf(FileNum);
+end;
+
+{/\
+ Returns the FileSize of the given index (FileNum)
+/\}
+
+function TMFiles.FileSizeMuf(FileNum: Integer): LongInt;
+Var
+ tempPos: Integer;
+begin
+
+ If(FileNum < 0) or (FileNum >= Length(MFiles)) Then
+ Begin
+ WriteLn('Invalid File Num');
+ Result := -1;
+ Exit;
+ End;
+
+ If MFiles[FileNum].FS = nil Then
+ Begin
+ WriteLn('FileSize: Invalid Internal Handle');
+ Result := -1;
+ Exit;
+ End;
+
+ Result := MFiles[FileNum].FS.Size;
+
+ {
+ If Files[FileNum].Handle = -1 Then
+ Begin
+ WriteLn('FileSize: Invalid Internal Handle');
+ Result := -1;
+ Exit;
+ End;
+ // Get our current position.
+ tempPos := FileSeek(Files[FileNum].Handle, 0, fsFromCurrent);
+
+ // End of the file.
+ Result := FileSeek(Files[FileNum].Handle, 0, fsFromEnd);
+
+ // Reset the position.
+ FileSeek(Files[FileNum].Handle, tempPos, fsFromBeginning); }
+end;
+
+function TMFiles.FilePointerPos(FileNum: Integer): Integer;
+begin
+ If(FileNum < 0) or (FileNum >= Length(MFiles)) Then
+ Begin
+ WriteLn('Invalid File Num');
+ Result := -1;
+ Exit;
+ End;
+ If MFiles[FileNum].FS = nil Then
+ Begin
+ WriteLn('FileSize: Invalid Internal Handle');
+ Result := -1;
+ Exit;
+ End;
+
+ try
+ Result := MFiles[FileNum].FS.Seek(0, fsFromCurrent);
+ Except
+ WriteLn('Exception in FilePointerPos');
+ End;
+ //Result := FileSeek(Files[FileNum].FS, 0, fsFromCurrent);
+end;
+
+{/\
+ Reads x numbers of characters from a file, and stores it into s.
+/\}
+
+function TMFiles.ReadFileString(FileNum: Integer; out s: string; x: Integer): Boolean;
+
+begin
+ If(FileNum < 0) or (FileNum >= Length(MFiles)) Then
+ Begin
+ WriteLn('Invalid File Num');
+ Result := False;
+ Exit;
+ End;
+ If MFiles[FileNum].FS = nil Then
+ Begin
+ WriteLn('ReadFileString: Invalid Internal Handle');
+ Exit;
+ End;
+
+ SetLength(S, 0);
+ SetLength(S, X);
+ MFiles[FileNum].FS.Read(S[1], x);
+
+ {Files[FileNum].BytesRead := Files[FileNum].BytesRead + X;
+ FileRead(Files[FileNum].Handle, S[1], X);
+ SetLength(S, X); }
+end;
+
+{/\
+ Writes s in the given File.
+/\}
+
+function TMFiles.WriteFileString(FileNum: Integer; s: string): Boolean;
+var
+ BytesRead : DWord;
+begin
+ If(FileNum < 0) or (FileNum >= Length(MFiles)) Then
+ Begin
+ WriteLn('Invalid File Num');
+ Result := False;
+ Exit;
+ End;
+ If(MFiles[FileNum].FS = nil) Then
+ Begin
+ WriteLn('WriteFileString: Invalid Internal Handle');
+ Result := False;
+ Exit;
+ End;
+
+ {If((Files[FileNum].Mode and fmOpenWrite) = 0) Then
+ Begin
+ WriteLn('This file may not write');
+ Exit;
+ End; }
+
+ try
+ Result := MFiles[FileNum].FS.Write(S[1], Length(S)) <> 1;
+ except
+ WriteLn('Exception - WriteFileString.');
+ Result := False;
+ end;
+
+ {If(FileWrite(Files[FileNum].Handle, S[1], Length(S)) <> -1) Then
+ Result := True
+ Else
+ Result := False; }
+end;
+
+end.
+
diff --git a/branches/script-component/Units/MMLCore/finder.pas b/branches/script-component/Units/MMLCore/finder.pas
new file mode 100644
index 0000000..0334c23
--- /dev/null
+++ b/branches/script-component/Units/MMLCore/finder.pas
@@ -0,0 +1,2027 @@
+{
+ This file is part of the Mufasa Macro Library (MML)
+ Copyright (c) 2009 by Raymond van Venetië and Merlijn Wajer
+
+ MML is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ MML is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with MML. If not, see .
+
+ See the file COPYING, included in this distribution,
+ for details about the copyright.
+
+ Finder class for the Mufasa Macro Library
+}
+
+unit finder;
+
+{$mode objfpc}{$H+}
+
+interface
+
+{$define CheckAllBackground}//Undefine this to only check the first white point against the background (in masks).
+uses
+ Classes, SysUtils,bitmaps, MufasaTypes; // Types
+
+{ TMFinder Class }
+
+{
+ Should be 100% independant, as all platform dependant code is in the
+ Window and Input classes.
+
+ Let's try not to use any OS-specific defines here? ;)
+}
+
+type
+ TMFinder = class(TObject)
+ constructor Create(aClient: TObject);
+ destructor Destroy; override;
+ private
+
+
+ Procedure UpdateCachedValues(NewWidth,NewHeight : integer);
+ procedure DefaultOperations(var xs,ys,xe,ye : integer);
+ //Loads the Spiral into ClientTPA (Will not cause problems)
+ procedure LoadSpiralPath(startX, startY, x1, y1, x2, y2: Integer);
+ public
+ function FindColorsToleranceOptimised(out Points: TPointArray; Color,
+ xs, ys, xe, ye, Tol: Integer): Boolean;
+ function FindColorToleranceOptimised(out x, y: Integer; Color, xs, ys,
+ xe, ye, tol: Integer): Boolean;
+ function CountColorTolerance(Color, xs, ys, xe, ye, Tolerance: Integer): Integer;
+ function CountColor(Color, xs, ys, xe, ye: Integer): Integer;
+ function SimilarColors(Color1,Color2,Tolerance : Integer) : boolean;
+ // Possibly turn x, y into a TPoint var.
+ function FindColor(out x, y: Integer; Color, xs, ys, xe, ye: Integer): Boolean;
+ function FindColorSpiral(var x, y: Integer; color, xs, ys, xe, ye: Integer): Boolean;
+ function FindColorTolerance(out x, y: Integer; Color, xs, ys, xe, ye, tol: Integer): Boolean;
+ function FindColorsTolerance(out Points: TPointArray; Color, xs, ys, xe, ye, Tol: Integer): Boolean;
+ function FindColorsSpiralTolerance(x, y: Integer; out Points: TPointArray; color, xs, ys, xe, ye: Integer; Tolerance: Integer) : boolean;
+ function FindColors(out TPA: TPointArray; Color, xs, ys, xe, ye: Integer): Boolean;
+ function FindColoredArea(var x, y: Integer; color, xs, ys, xe, ye: Integer; MinArea: Integer): Boolean;
+ function FindColoredAreaTolerance(var x, y: Integer; color, xs, ys, xe, ye: Integer; MinArea, tol: Integer): Boolean;
+ //Mask
+ function FindMaskTolerance(mask: TMask; out x, y: Integer; xs, ys, xe, ye: Integer; Tolerance, ContourTolerance: Integer): Boolean;
+ procedure CheckMask(Mask : TMask);
+ //Bitmap functions
+ function FindBitmap(bitmap: TMufasaBitmap; out x, y: Integer): Boolean;
+ function FindBitmapIn(bitmap: TMufasaBitmap; out x, y: Integer; xs, ys, xe, ye: Integer): Boolean;
+ function FindBitmapToleranceIn(bitmap: TMufasaBitmap; out x, y: Integer; xs, ys, xe, ye: Integer; tolerance: Integer): Boolean;
+ function FindBitmapSpiral(bitmap: TMufasaBitmap; var x, y: Integer; xs, ys, xe, ye: Integer): Boolean;
+ function FindBitmapSpiralTolerance(bitmap: TMufasaBitmap; var x, y: Integer; xs, ys, xe, ye,tolerance : integer): Boolean;
+ function FindBitmapsSpiralTolerance(bitmap: TMufasaBitmap; x, y: Integer; out Points : TPointArray; xs, ys, xe, ye,tolerance: Integer): Boolean;
+ function FindDeformedBitmapToleranceIn(bitmap: TMufasaBitmap; out x, y: Integer; xs, ys, xe, ye: Integer; tolerance: Integer; Range: Integer; AllowPartialAccuracy: Boolean; var accuracy: Extended): Boolean;
+
+ function FindDTM(DTM: pDTM; out x, y: Integer; x1, y1, x2, y2: Integer): Boolean;
+ function FindDTMs(DTM: pDTM; out Points: TPointArray; x1, y1, x2, y2, maxToFind: Integer): Boolean;
+ function FindDTMRotated(DTM: pDTM; out x, y: Integer; x1, y1, x2, y2: Integer; sAngle, eAngle, aStep: Extended; out aFound: Extended): Boolean;
+ function FindDTMsRotated(DTM: pDTM; out Points: TPointArray; x1, y1, x2, y2: Integer; sAngle, eAngle, aStep: Extended; out aFound: T2DExtendedArray; maxToFind: Integer): Boolean;
+ //Donno
+ function GetColors(Coords: TPointArray): TIntegerArray;
+ // tol speeds
+ procedure SetToleranceSpeed(nCTS: Integer);
+ function GetToleranceSpeed: Integer;
+ procedure SetToleranceSpeed2Modifiers(nHue, nSat: Extended);
+ procedure GetToleranceSpeed2Modifiers(out hMod, sMod: Extended);
+ protected
+ Client: TObject;
+ Percentage : array[0..255] of Extended; //We store all the possible RGB / 255 divisions.
+ CachedWidth, CachedHeight : integer;
+ ClientTPA : TPointArray;
+ hueMod, satMod: Extended;
+ CTS: Integer;
+ end;
+
+implementation
+uses
+ colour_conv,// For RGBToColor, etc.
+ Client, // For the Client Casts.
+ math, //min/max
+ tpa, //TPABounds
+ dtmutil
+ ;
+type
+ TPRGB32Array = array of PRGB32;
+
+procedure TMFinder.LoadSpiralPath(startX, startY, x1, y1, x2, y2: Integer);
+var
+ i,c,Ring : integer;
+ CurrBox : TBox;
+begin;
+ i := 0;
+ Ring := 1;
+ c := 0;
+ CurrBox.x1 := Startx-1;
+ CurrBox.y1 := Starty-1;
+ CurrBox.x2 := Startx+1;
+ CurrBox.y2 := Starty+1;
+ if (startx >= x1) and (startx <= x2) and (starty >= y1) and (starty <= y2) then
+ begin;
+ ClientTPA[c] := Point(Startx, StartY);
+ inc(c);
+ end;
+ Repeat
+ if (CurrBox.x2 >= x1) and (CurrBox.x1 <= x2) and (Currbox.y1 >= y1) and (Currbox.y1 <= y2) then
+ for i := CurrBox.x1 + 1 to CurrBox.x2 do
+ if (I >= x1) and ( I <= x2) then
+ begin;
+ ClientTPA[c] := Point(i,CurrBox.y1);
+ inc(c);
+ end;
+ if (CurrBox.x2 >= x1) and (CurrBox.x2 <= x2) and (Currbox.y2 >= y1) and (Currbox.y1 <= y2) then
+ for i := CurrBox.y1 + 1 to CurrBox.y2 do
+ if (I >= y1) and ( I <= y2) then
+ begin;
+ ClientTPA[c] := Point(Currbox.x2, I);
+ inc(c);
+ end;
+ if (CurrBox.x2 >= x1) and (CurrBox.x1 <= x2) and (Currbox.y2 >= y1) and (Currbox.y2 <= y2) then
+ for i := CurrBox.x2 - 1 downto CurrBox.x1 do
+ if (I >= x1) and ( I <= x2) then
+ begin;
+ ClientTPA[c] := Point(i,CurrBox.y2);
+ inc(c);
+ end;
+ if (CurrBox.x1 >= x1) and (CurrBox.x1 <= x2) and (Currbox.y2 >= y1) and (Currbox.y1 <= y2) then
+ for i := CurrBox.y2 - 1 downto CurrBox.y1 do
+ if (I >= y1) and ( I <= y2) then
+ begin;
+ ClientTPA[c] := Point(Currbox.x1, I);
+ inc(c);
+ end;
+ inc(ring);
+ CurrBox.x1 := Startx-ring;
+ CurrBox.y1 := Starty-Ring;
+ CurrBox.x2 := Startx+Ring;
+ CurrBox.y2 := Starty+Ring;
+ until (Currbox.x1 < x1) and (Currbox.x2 > x2) and (currbox.y1 < y1) and (currbox.y2 > y2);
+end;
+
+function CalculateRowPtrs(ReturnData : TRetData; RowCount : integer) : TPRGB32Array;overload;
+var
+ I : integer;
+begin;
+ setlength(result,RowCount);
+ for i := 0 to RowCount - 1 do
+ result[i] := ReturnData.Ptr + ReturnData.RowLen * i;
+end;
+
+function CalculateRowPtrs(Bitmap : TMufasaBitmap) : TPRGB32Array;overload;
+var
+ I : integer;
+begin;
+ setlength(result,Bitmap.Height);
+ for i := 0 to Bitmap.Height - 1 do
+ result[i] := Bitmap.FData + Bitmap.Width * i;
+end;
+//SkipCoords[y][x] = False/True; True means its "transparent" and therefore not needed to be checked.
+procedure CalculateBitmapSkipCoords(Bitmap : TMufasaBitmap; out SkipCoords : T2DBoolArray);
+var
+ x,y : integer;
+ R,G,B : byte;
+ Ptr : PRGB32;
+begin;
+ r := 0;
+ g := 0;
+ b := 0;
+ if Bitmap.TransparentColorSet then
+ ColorToRGB(Bitmap.GetTransparentColor,r,g,b);
+ Ptr := Bitmap.FData;
+ SetLength(SkipCoords,Bitmap.Height,Bitmap.Width);
+ for y := 0 to Bitmap.Height - 1 do
+ for x := 0 to Bitmap.Width - 1 do
+ begin;
+ if (Ptr^.r = r) and (Ptr^.g = g) and (Ptr^.b = b) then
+ SkipCoords[y][x] := True
+ else
+ SkipCoords[y][x] := false;
+ inc(ptr);
+ end;
+end;
+//Points left holds the amount of points that are "left" to be checked (Including the point itself.. So for example Pointsleft[0][0] would hold the total amount of pixels that are to be checked.
+procedure CalculateBitmapSkipCoordsEx(Bitmap : TMufasaBitmap; out SkipCoords : T2DBoolArray;out TotalPoints : integer; out PointsLeft : T2DIntArray);
+var
+ x,y : integer;
+ R,G,B : byte;
+ Ptr : PRGB32;
+ TotalC : integer;
+begin;
+ r := 0;
+ g := 0;
+ b := 0;
+ TotalC := 0;
+ if Bitmap.TransparentColorSet then
+ ColorToRGB(Bitmap.GetTransparentColor,r,g,b);
+ Ptr := Bitmap.FData;
+ SetLength(SkipCoords,Bitmap.Height,Bitmap.Width);
+ SetLength(PointsLeft,Bitmap.Height,Bitmap.Width);
+ for y := 0 to Bitmap.Height - 1 do
+ for x := 0 to Bitmap.Width - 1 do
+ begin;
+ if (Ptr^.r = r) and (Ptr^.g = g) and (Ptr^.b = b) then
+ SkipCoords[y][x] := True
+ else
+ begin;
+ SkipCoords[y][x] := false;
+ inc(TotalC);
+ end;
+ inc(ptr);
+ end;
+ TotalPoints:= TotalC;
+ for y := 0 to Bitmap.Height - 1 do
+ for x := 0 to Bitmap.Width - 1 do
+ begin;
+ PointsLeft[y][x] := TotalC;
+ if not SkipCoords[y][x] then
+ Dec(TotalC);
+ end;
+end;
+
+constructor TMFinder.Create(aClient: TObject);
+var
+ I : integer;
+
+begin
+ inherited Create;
+
+ Self.Client := aClient;
+ Self.CTS := 1;
+ Self.hueMod := 0.2;
+ Self.satMod := 0.2;
+ for i := 0 to 255 do
+ Percentage[i] := i / 255;
+
+end;
+
+destructor TMFinder.Destroy;
+begin
+
+ inherited;
+end;
+
+procedure TMFinder.SetToleranceSpeed(nCTS: Integer);
+begin
+ if (nCTS < 0) or (nCTS > 2) then
+ raise Exception.CreateFmt('The given CTS ([%d]) is invalid.',[nCTS]);
+ Self.CTS := nCTS;
+end;
+
+function TMFinder.GetToleranceSpeed: Integer;
+begin
+ Result := Self.CTS;
+end;
+
+procedure TMFinder.SetToleranceSpeed2Modifiers(nHue, nSat: Extended);
+begin
+ Self.hueMod := nHue;
+ Self.satMod := nSat;
+end;
+
+procedure TMFinder.GetToleranceSpeed2Modifiers(out hMod, sMod: Extended);
+begin
+ hMod := Self.hueMod;
+ sMod := Self.satMod;
+end;
+
+function TMFinder.SimilarColors(Color1, Color2,Tolerance: Integer) : boolean;
+var
+ R1,G1,B1,R2,G2,B2 : Byte;
+ H1,S1,L1,H2,S2,L2 : extended;
+begin
+ Result := False;
+ ColorToRGB(Color1,R1,G1,B1);
+ ColorToRGB(Color2,R2,G2,B2);
+ if Color1 = Color2 then
+ Result := true
+ else
+ case CTS of
+ 0: Result := ((Abs(R1-R2) <= Tolerance) and (Abs(G1-G2) <= Tolerance) and (Abs(B1-B2) <= Tolerance));
+ 1: Result := (Sqrt(sqr(R1-R2) + sqr(G1-G2) + sqr(B1-B2)) <= Tolerance);
+ 2: begin
+ RGBToHSL(R1,g1,b1,H1,S1,L1);
+ RGBToHSL(R2,g2,b2,H2,S2,L2);
+ Result := ((abs(H1 - H2) <= (hueMod * Tolerance)) and (abs(S2-S1) <= (satMod * Tolerance)) and (abs(L1-L2) <= Tolerance));
+ end;
+ end;
+end;
+
+
+function ColorSame(var CTS,Tolerance : Integer; var R1,G1,B1,R2,G2,B2 : byte; var H1,S1,L1,huemod,satmod : extended) : boolean; inline;
+var
+ H2,S2,L2 : extended;
+begin
+ Result := False;
+ case CTS of
+ 0: Result := ((Abs(R1-R2) <= Tolerance) and (Abs(G1-G2) <= Tolerance) and (Abs(B1-B2) <= Tolerance));
+ 1: Result := (Sqrt(sqr(R1-R2) + sqr(G1-G2) + sqr(B1-B2)) <= Tolerance);
+ 2: begin
+ RGBToHSL(R2,g2,b2,H2,S2,L2);
+ Result := ((abs(H1 - H2) <= (hueMod * Tolerance)) and (abs(S2-S1) <= (satMod * Tolerance)) and (abs(L1-L2) <= Tolerance));
+ end;
+ end;
+end;
+
+procedure TMFinder.UpdateCachedValues(NewWidth, NewHeight: integer);
+begin
+ CachedWidth := NewWidth;
+ CachedHeight := NewHeight;
+ SetLength(ClientTPA,NewWidth * NewHeight);
+end;
+
+procedure TMFinder.DefaultOperations(var xs, ys, xe, ye: integer);
+var
+ w,h : integer;
+begin
+ if xs > xe then
+ raise Exception.CreateFMT('Finder function: Xs > xe (%d,%d)',[xs,xe]);
+ if ys > ye then
+ raise Exception.CreateFMT('Finder function: Ys > ye (%d,%d)',[ys,ye]);
+ if xs < 0 then
+ // xs := 0;
+ raise Exception.createFMT('Any Find Function, you did not pass a ' +
+ 'correct xs: %d.', [xs]);
+ if ys < 0 then
+// ys := 0;
+ raise Exception.createFMT('Any Find Function, you did not pass a ' +
+ 'correct ys: %d.', [ys]);
+
+ TClient(Self.Client).IOManager.GetDimensions(w,h);
+ if (w <> CachedWidth) or (h <> CachedHeight) then
+ UpdateCachedValues(w,h);
+ if xe >= w then
+// xe := w-1;
+ raise Exception.createFMT('Any Find Function, you did not pass a ' +
+ 'correct xe: %d.', [xe]);
+ if ye >= h then
+// ye := h-1;
+ raise Exception.createFMT('Any Find Function, you did not pass a ' +
+ 'correct ye: %d.', [ye]);
+end;
+
+function TMFinder.CountColorTolerance(Color, xs, ys, xe, ye, Tolerance: Integer): Integer;
+var
+ PtrData: TRetData;
+ Ptr: PRGB32;
+ PtrInc: Integer;
+ clR, clG, clB : byte;
+ dX, dY, xx, yy: Integer;
+ h,s,l,hmod,smod : extended;
+ Ccts : integer;
+begin
+ Result := 0;
+ DefaultOperations(xs, ys, xe, ye);
+ dX := xe - xs;
+ dY := ye - ys;
+ ColorToRGB(Color, clR, clG, clB);
+ PtrData := TClient(Client).IOManager.ReturnData(xs, ys, dX + 1, dY + 1);
+ Ptr := PtrData.Ptr;
+ PtrInc := PtrData.IncPtrWith;
+ CCts := Self.CTS;
+ result := 0;
+ if cts = 2 then
+ begin;
+ RGBToHSL(clR,clG,clB,h,s,l);
+ hmod := Self.hueMod;
+ smod := Self.satMod;
+ end;
+ for yy := ys to ye do
+ begin;
+ for xx := xs to xe do
+ begin;
+ if ColorSame(CCts,Tolerance,clR,clG,clB,Ptr^.r,Ptr^.g,Ptr^.b,H,S,L,hmod,smod) then
+ inc(result);
+ Inc(Ptr);
+ end;
+ Inc(Ptr, PtrInc)
+ end;
+ TClient(Client).IOManager.FreeReturnData;
+end;
+
+function TMFinder.CountColor(Color, xs, ys, xe, ye: Integer): Integer;
+var
+ PtrData: TRetData;
+ Ptr: PRGB32;
+ PtrInc: Integer;
+ dX, dY, clR, clG, clB, xx, yy: Integer;
+
+begin
+ Result := 0;
+ // checks for valid xs,ys,xe,ye? (may involve GetDimensions)
+ DefaultOperations(xs,ys,xe,ye);
+
+ // calculate delta x and y
+ dX := xe - xs;
+ dY := ye - ys;
+
+ //next, convert the color to r,g,b
+ ColorToRGB(Color, clR, clG, clB);
+
+ PtrData := TClient(Client).IOManager.ReturnData(xs, ys, dX + 1, dY + 1);
+
+ // Do we want to "cache" these vars?
+ // We will, for now. Easier to type.
+ Ptr := PtrData.Ptr;
+ PtrInc := PtrData.IncPtrWith;
+
+ for yy := ys to ye do
+ begin;
+ for xx := xs to xe do
+ begin;
+ // Colour comparison here. Possibly with tolerance? ;)
+ if (Ptr^.R = clR) and (Ptr^.G = clG) and (Ptr^.B = clB) then
+ inc(result);
+ Inc(Ptr);
+ end;
+ Inc(Ptr, PtrInc)
+ end;
+
+ TClient(Client).IOManager.FreeReturnData;
+end;
+
+function TMFinder.FindColor(out x, y: Integer; Color, xs, ys, xe, ye: Integer): Boolean;
+var
+ PtrData: TRetData;
+ Ptr: PRGB32;
+ PtrInc: Integer;
+ dX, dY, clR, clG, clB, xx, yy: Integer;
+
+begin
+ Result := false;
+ // checks for valid xs,ys,xe,ye? (may involve GetDimensions)
+ DefaultOperations(xs,ys,xe,ye);
+
+ // calculate delta x and y
+ dX := xe - xs;
+ dY := ye - ys;
+
+ //next, convert the color to r,g,b
+ ColorToRGB(Color, clR, clG, clB);
+
+ PtrData := TClient(Client).IOManager.ReturnData(xs, ys, dX + 1, dY + 1);
+
+ // Do we want to "cache" these vars?
+ // We will, for now. Easier to type.
+ Ptr := PtrData.Ptr;
+ PtrInc := PtrData.IncPtrWith;
+
+ for yy := ys to ye do
+ begin;
+ for xx := xs to xe do
+ begin;
+ // Colour comparison here. Possibly with tolerance? ;)
+ if (Ptr^.R = clR) and (Ptr^.G = clG) and (Ptr^.B = clB) then
+ begin
+ Result := True;
+ x := xx;
+ y := yy;
+
+ TClient(Client).IOManager.FreeReturnData;
+ Exit;
+ end;
+ Inc(Ptr);
+ end;
+ Inc(Ptr, PtrInc)
+ end;
+
+ TClient(Client).IOManager.FreeReturnData;
+end;
+
+function TMFinder.FindColorSpiral(var x, y: Integer; color, xs, ys, xe,
+ ye: Integer): Boolean;
+var
+ PtrData: TRetData;
+ RowData : TPRGB32Array;
+ dX, dY, clR, clG, clB, i,HiSpiral: Integer;
+
+begin
+ Result := false;
+ // checks for valid xs,ys,xe,ye? (may involve GetDimensions)
+ DefaultOperations(xs,ys,xe,ye);
+
+ // calculate delta x and y
+ dX := xe - xs;
+ dY := ye - ys;
+
+ //next, convert the color to r,g,b
+ ColorToRGB(Color, clR, clG, clB);
+
+ PtrData := TClient(Client).IOManager.ReturnData(xs, ys, dX + 1, dY + 1);
+ //Load rowdata
+ RowData:= CalculateRowPtrs(ptrdata,dy+1);
+ //Load the spiral path
+ LoadSpiralPath(x-xs,y-ys,0,0,dx,dy);
+
+
+ HiSpiral := (dy+1) * (dx + 1) -1;
+ for i := 0 to HiSpiral do
+ if (RowData[ClientTPA[i].y][ClientTPA[i].x].R = clR) and (RowData[ClientTPA[i].y][ClientTPA[i].x].G = clG)
+ and (RowData[ClientTPA[i].y][ClientTPA[i].x].B = clB) then
+ begin
+ Result := True;
+ x := ClientTPA[i].x + xs;
+ y := ClientTPA[i].y + ys;
+ TClient(Client).IOManager.FreeReturnData;
+ Exit;
+ end;
+
+ TClient(Client).IOManager.FreeReturnData;
+end;
+
+function TMFinder.FindColoredArea(var x, y: Integer; Color, xs, ys, xe, ye, MinArea: Integer): Boolean;
+var
+ PtrData: TRetData;
+ Ptr, Before: PRGB32;
+ PtrInc: Integer;
+ dX, dY, clR, clG, clB, xx, yy, fx, fy, Count : Integer;
+ NotFound : Boolean;
+
+begin
+ Result := false;
+ Count := 0;
+ // checks for valid xs,ys,xe,ye? (may involve GetDimensions)
+ DefaultOperations(xs,ys,xe,ye);
+
+ // calculate delta x and y
+ dX := xe - xs;
+ dY := ye - ys;
+
+ //next, convert the color to r,g,b
+ ColorToRGB(Color, clR, clG, clB);
+
+ PtrData := TClient(Client).IOManager.ReturnData(xs, ys, dX + 1, dY + 1);
+
+ // Do we want to "cache" these vars?
+ // We will, for now. Easier to type.
+ Ptr := PtrData.Ptr;
+ PtrInc := PtrData.IncPtrWith;
+
+ for yy := ys to ye do
+ begin;
+ for xx := xs to xe do
+ begin;
+ NotFound := False;
+ // Colour comparison here. Possibly with tolerance? ;)
+ if (Ptr^.R = clR) and (Ptr^.G = clG) and (Ptr^.B = clB) then
+ begin
+ Before := Ptr;
+ for fy := yy to ye do
+ begin
+ for fx := xx to xe do
+ begin
+ Inc(Ptr);
+ if not ((Ptr^.R = clR) and (Ptr^.G = clG) and (Ptr^.B = clB)) then
+ begin
+ NotFound := True;
+ Break;
+ end;
+ Inc(Count);
+ if Count >= MinArea then
+ Begin
+ Result := True;
+ x := xx;
+ y := yy;
+ TClient(Client).IOManager.FreeReturnData;
+ Exit;
+ end;
+ end;
+
+ if NotFound then
+ begin
+ Ptr := Before;
+ Break;
+ end;
+ Inc(Ptr, PtrInc);
+ end;
+ end;
+ Inc(Ptr);
+ end;
+ Inc(Ptr, PtrInc);
+ end;
+
+ TClient(Client).IOManager.FreeReturnData;
+end;
+
+
+function TMFinder.FindColorToleranceOptimised(out x, y: Integer; Color, xs, ys, xe, ye, tol: Integer): Boolean;
+var
+ PtrData: TRetData;
+ Ptr: PRGB32;
+ PtrInc: Integer;
+ dX, dY, clR, clG, clB, xx, yy: Integer;
+ H1, S1, L1, H2, S2, L2: Extended;
+ R,G,B : extended; //percentage R,G,B.. (Needed for HSL).
+ D : Extended; //CMax - Cmin
+ HueTol,SatTol, LumTol : extended;
+ CMax, CMin : extended;
+ label Hit;
+
+begin
+ Result := false;
+ // checks for valid xs,ys,xe,ye? (may involve GetDimensions)
+ DefaultOperations(xs,ys,xe,ye);
+
+ // calculate delta x and y
+ dX := xe - xs;
+ dY := ye - ys;
+ //next, convert the color to r,g,b
+ ColorToRGB(Color, clR, clG, clB);
+ if Cts = 2 then
+ RGBToHSLNonFixed(clR,clG,clB,H1,S1,L1);
+
+ PtrData := TClient(Client).IOManager.ReturnData(xs, ys, dX + 1, dY + 1);
+
+ // Do we want to "cache" these vars?
+ // We will, for now. Easier to type.
+ Ptr := PtrData.Ptr;
+ PtrInc := PtrData.IncPtrWith;
+
+ case CTS of
+ 0:
+ for yy := ys to ye do
+ begin
+ for xx := xs to xe do
+ begin
+ if ((abs(clB-Ptr^.B) <= Tol) and (abs(clG-Ptr^.G) <= Tol) and (Abs(clR-Ptr^.R) <= Tol)) then
+ goto Hit;
+ inc(Ptr);
+ end;
+ Inc(Ptr, PtrInc);
+ end;
+
+ 1:
+ begin
+ Tol := Sqr(Tol);
+
+ for yy := ys to ye do
+ begin
+ for xx := xs to xe do
+ begin
+ if (sqr(clB - Ptr^.B) + sqr(clG - Ptr^.G) + sqr(clR-Ptr^.R)) <= Tol then
+ goto Hit;
+ inc(ptr);
+ end;
+ Inc(Ptr, PtrInc);
+ end;
+
+ end;
+ 2:
+ begin
+ //Since we don't make (real) percentages of the HSL-values we need to change the tolerance..
+ HueTol := hueMod * Tol / 100;
+ SatTol := satMod * Tol / 100;
+ LumTol := Tol / 100;
+ for yy := ys to ye do
+ begin
+ for xx := xs to xe do
+ begin
+ R := Percentage[Ptr^.r];
+ G := Percentage[Ptr^.g];
+ B := Percentage[Ptr^.b];
+ //We increase the Ptr already, since we do Continue in loops..
+ inc(Ptr);
+ CMin := R;
+ CMax := R;
+ if G < Cmin then CMin := G;
+ if B < Cmin then CMin := B;
+ if G > Cmax then CMax := G;
+ if B > Cmax then CMax := B;
+ L2 := 0.5 * (Cmax + Cmin);
+ //The L-value is already calculated, lets see if the current point meats the requirements!
+ if Abs(L2-L1) > LumTol then //if not (Abs(L2 - L1) <= LumTol) then
+ Continue;
+ if Cmax = Cmin then
+ begin
+ //S and H are both zero, lets check if we need found a point!
+ if (H1 <= HueTol) and (S1 <= SatTol) then
+ goto Hit
+ else
+ Continue;
+ end;
+ D := Cmax - Cmin;
+ if L2 < 0.5 then
+ S2 := D / (Cmax + Cmin)
+ else
+ S2 := D / (2 - Cmax - Cmin);
+ //We've Calculated the S. Lets see if we need to continue.
+ if Abs(S2 - S1) > SatTol then //if not (abs(S1 - S2) <= SatXTol) then
+ Continue;
+ if R = Cmax then
+ H2 := (G - B) / D
+ else
+ if G = Cmax then
+ H2 := 2 + (B - R) / D
+ else
+ H2 := 4 + (R - G) / D;
+ H2 := H2 / 6;
+ if H2 < 0 then
+ H2 := H2 + 1;
+ //Finally lets test H2
+ if Abs(H2 - H1) <= HueTol then
+ goto hit;
+ end;
+ Inc(Ptr, PtrInc);
+ end;
+ end;
+ end;
+ Result := False;
+ TClient(Client).IOManager.FreeReturnData;
+ Exit;
+
+ Hit:
+ Result := True;
+ x := xx;
+ y := yy;
+ TClient(Client).IOManager.FreeReturnData;
+end;
+
+function TMFinder.FindColorTolerance(out x, y: Integer; Color, xs, ys, xe, ye, tol: Integer): Boolean;
+var
+ PtrData: TRetData;
+ Ptr: PRGB32;
+ PtrInc: Integer;
+ dX, dY, clR, clG, clB, xx, yy: Integer;
+ H1, S1, L1, H2, S2, L2: Extended;
+ R,G,B : extended; //percentage R,G,B.. (Needed for HSL).
+ D : Extended; //CMax - Cmin
+ HueXTol, SatXTol: Extended;
+ CMax, CMin : extended;
+ label Hit;
+
+begin
+ Result := false;
+ // checks for valid xs,ys,xe,ye? (may involve GetDimensions)
+ DefaultOperations(xs,ys,xe,ye);
+
+ // calculate delta x and y
+ dX := xe - xs;
+ dY := ye - ys;
+ //next, convert the color to r,g,b
+ ColorToRGB(Color, clR, clG, clB);
+ if Cts = 2 then
+ RGBToHSL(clR,clG,clB,H1,S1,L1);
+
+ PtrData := TClient(Client).IOManager.ReturnData(xs, ys, dX + 1, dY + 1);
+
+ // Do we want to "cache" these vars?
+ // We will, for now. Easier to type.
+ Ptr := PtrData.Ptr;
+ PtrInc := PtrData.IncPtrWith;
+
+ case CTS of
+ 0:
+ for yy := ys to ye do
+ begin
+ for xx := xs to xe do
+ begin
+ if ((abs(clB-Ptr^.B) <= Tol) and (abs(clG-Ptr^.G) <= Tol) and (Abs(clR-Ptr^.R) <= Tol)) then
+ goto Hit;
+ inc(Ptr);
+ end;
+ Inc(Ptr, PtrInc);
+ end;
+
+ 1:
+ begin
+ Tol := Sqr(Tol);
+
+ for yy := ys to ye do
+ begin
+ for xx := xs to xe do
+ begin
+ if (sqr(clB - Ptr^.B) + sqr(clG - Ptr^.G) + sqr(clR-Ptr^.R)) <= Tol then
+ goto Hit;
+ inc(ptr);
+ end;
+ Inc(Ptr, PtrInc);
+ end;
+
+ end;
+ 2:
+ { Can be optimized a lot... RGBToHSL isn't really inline, }
+ begin
+ HueXTol := hueMod * Tol;
+ SatXTol := satMod * Tol;
+ for yy := ys to ye do
+ begin
+ for xx := xs to xe do
+ begin
+ RGBToHSL(Ptr^.R,Ptr^.G,Ptr^.B,H2,S2,L2);
+ if ((abs(H1 - H2) <= HueXTol) and (abs(S1 - S2) <= SatXTol) and (abs(L1 - L2) <= Tol)) then
+ goto Hit;
+ inc(Ptr);
+ end;
+ Inc(Ptr, PtrInc);
+ end;
+ end;
+ end;
+ Result := False;
+ TClient(Client).IOManager.FreeReturnData;
+ Exit;
+
+ Hit:
+ Result := True;
+ x := xx;
+ y := yy;
+ TClient(Client).IOManager.FreeReturnData;
+end;
+
+function TMFinder.FindColoredAreaTolerance(var x, y: Integer; Color, xs, ys, xe, ye, MinArea, tol: Integer): Boolean;
+var
+ PtrData: TRetData;
+ Ptr, Before: PRGB32;
+ PtrInc: Integer;
+ dX, dY, xx, yy, fx, fy, Count: Integer;
+ clR, clG, clB : Byte;
+ H1, S1, L1: Extended;
+ NotFound : Boolean;
+ label Hit;
+
+begin
+ Result := false;
+ // checks for valid xs,ys,xe,ye? (may involve GetDimensions)
+ DefaultOperations(xs,ys,xe,ye);
+
+ // calculate delta x and y
+ dX := xe - xs;
+ dY := ye - ys;
+ //next, convert the color to r,g,b
+ ColorToRGB(Color, clR, clG, clB);
+ if Cts = 2 then
+ RGBToHSL(clR,clG,clB,H1,S1,L1);
+ PtrData := TClient(Client).IOManager.ReturnData(xs, ys, dX + 1, dY + 1);
+
+ // Do we want to "cache" these vars?
+ // We will, for now. Easier to type.
+ Ptr := PtrData.Ptr;
+ PtrInc := PtrData.IncPtrWith;
+
+ for yy := ys to ye do
+ begin;
+ for xx := xs to xe do
+ begin;
+ NotFound := False;
+ // Colour comparison here.
+ if ColorSame(CTS, Tol, Ptr^.R, Ptr^.G, Ptr^.B, clR, clG, clB, H1, S1, L1, huemod, satmod) then
+ begin
+ Before := Ptr;
+ for fy := yy to ye do
+ begin
+ for fx := xx to xe do
+ begin
+ Inc(Ptr);
+ if not ColorSame(CTS, Tol, Ptr^.R, Ptr^.G, Ptr^.B, clR, clG, clB, H1, S1, L1, huemod, satmod) then
+ begin
+ NotFound := True;
+ Break;
+ end;
+ Inc(Count);
+ if Count >= MinArea then
+ goto Hit;
+ end;
+
+ if NotFound then
+ begin
+ Ptr := Before;
+ Break;
+ end;
+ Inc(Ptr, PtrInc);
+ end;
+ end;
+ Inc(Ptr);
+ end;
+ Inc(Ptr, PtrInc);
+ end;
+
+ Result := False;
+ TClient(Client).IOManager.FreeReturnData;
+ Exit;
+
+ Hit:
+ Result := True;
+ x := xx;
+ y := yy;
+ TClient(Client).IOManager.FreeReturnData;
+end;
+
+function TMFinder.FindColorsTolerance(out Points: TPointArray; Color, xs, ys,
+ xe, ye, Tol: Integer): Boolean;
+var
+ PtrData: TRetData;
+ Ptr: PRGB32;
+ PtrInc,C: Integer;
+ dX, dY, clR, clG, clB, xx, yy: Integer;
+ H1, S1, L1, H2, S2, L2, hueXTol, satXTol,LumTol,R,G,B,D,Cmin,Cmax: Extended;
+label
+ hit;
+begin
+ Result := false;
+ DefaultOperations(xs,ys,xe,ye);
+
+ dX := xe - xs;
+ dY := ye - ys;
+ //next, convert the color to r,g,b
+ ColorToRGB(Color, clR, clG, clB);
+ if CTS = 2 then
+ ColorToHSL(color,H1,S1,L1);
+
+ PtrData := TClient(Client).IOManager.ReturnData(xs, ys, dX + 1, dY + 1);
+
+ // Do we want to "cache" these vars?
+ // We will, for now. Easier to type.
+ Ptr := PtrData.Ptr;
+ PtrInc := PtrData.IncPtrWith;
+ c := 0;
+ case CTS of
+ 0:
+ for yy := ys to ye do
+ begin
+ for xx := xs to xe do
+ begin
+ if ((abs(clB-Ptr^.B) <= Tol) and (abs(clG-Ptr^.G) <= Tol) and (Abs(clR-Ptr^.R) <= Tol)) then
+ begin;
+ ClientTPA[c].x := xx;
+ ClientTPA[c].y := yy;
+ inc(c);
+ end;
+ inc(Ptr);
+ end;
+ Inc(Ptr, PtrInc);
+ end;
+
+ 1:
+ for yy := ys to ye do
+ begin
+ for xx := xs to xe do
+ begin
+ if (Sqrt(sqr(clR-Ptr^.R) + sqr(clG - Ptr^.G) + sqr(clB - Ptr^.B)) <= Tol) then
+ begin;
+ ClientTPA[c].x := xx;
+ ClientTPA[c].y := yy;
+ inc(c);
+ end;
+ inc(ptr);
+ end;
+ Inc(Ptr, PtrInc);
+ end;
+
+ 2:
+ begin
+ HueXTol := hueMod * Tol;
+ SatXTol := satMod * Tol;
+ for yy := ys to ye do
+ begin
+ for xx := xs to xe do
+ begin
+ RGBToHSL(Ptr^.R,Ptr^.G,Ptr^.B,H2,S2,L2);
+ if ((abs(H1 - H2) <= HueXTol) and (abs(S1 - S2) <= SatXTol) and (abs(L1 - L2) <= Tol)) then
+ begin;
+ ClientTPA[c].x := xx;
+ ClientTPA[c].y := yy;
+ Inc(c);
+ end;
+ Inc(Ptr)
+ end;
+ Inc(Ptr, PtrInc);
+ end;
+ end;
+ end;
+ SetLength(Points, C);
+ Move(ClientTPA[0], Points[0], C * SizeOf(TPoint));
+ Result := C > 0;
+ TClient(Client).IOManager.FreeReturnData;
+end;
+function TMFinder.FindColorsToleranceOptimised(out Points: TPointArray; Color, xs, ys,
+ xe, ye, Tol: Integer): Boolean;
+var
+ PtrData: TRetData;
+ Ptr: PRGB32;
+ PtrInc,C: Integer;
+ dX, dY, clR, clG, clB, xx, yy: Integer;
+ H1, S1, L1, H2, S2, L2, hueTol, satTol,LumTol,R,G,B,D,Cmin,Cmax: Extended;
+label
+ hit;
+begin
+ Result := false;
+ DefaultOperations(xs,ys,xe,ye);
+
+ dX := xe - xs;
+ dY := ye - ys;
+ //next, convert the color to r,g,b
+ ColorToRGB(Color, clR, clG, clB);
+ if CTS = 2 then
+ RGBToHSLNonFixed(clR,clG,clB,H1,S1,L1);
+
+ PtrData := TClient(Client).IOManager.ReturnData(xs, ys, dX + 1, dY + 1);
+
+ // Do we want to "cache" these vars?
+ // We will, for now. Easier to type.
+ Ptr := PtrData.Ptr;
+ PtrInc := PtrData.IncPtrWith;
+ c := 0;
+ case CTS of
+ 0:
+ for yy := ys to ye do
+ begin
+ for xx := xs to xe do
+ begin
+ if ((abs(clB-Ptr^.B) <= Tol) and (abs(clG-Ptr^.G) <= Tol) and (Abs(clR-Ptr^.R) <= Tol)) then
+ begin;
+ ClientTPA[c].x := xx;
+ ClientTPA[c].y := yy;
+ inc(c);
+ end;
+ inc(Ptr);
+ end;
+ Inc(Ptr, PtrInc);
+ end;
+
+ 1:
+ for yy := ys to ye do
+ begin
+ for xx := xs to xe do
+ begin
+ if (Sqrt(sqr(clR-Ptr^.R) + sqr(clG - Ptr^.G) + sqr(clB - Ptr^.B)) <= Tol) then
+ begin;
+ ClientTPA[c].x := xx;
+ ClientTPA[c].y := yy;
+ inc(c);
+ end;
+ inc(ptr);
+ end;
+ Inc(Ptr, PtrInc);
+ end;
+
+ 2:
+ begin
+ HueTol := hueMod * Tol / 100;
+ SatTol := satMod * Tol / 100;
+ LumTol := Tol / 100;
+ for yy := ys to ye do
+ begin
+ for xx := xs to xe do
+ begin
+ R := Percentage[Ptr^.r];
+ G := Percentage[Ptr^.g];
+ B := Percentage[Ptr^.b];
+ //We increase the Ptr already, since we use Continue;
+ inc(Ptr);
+ CMin := R;
+ CMax := R;
+ if G < Cmin then CMin := G;
+ if B < Cmin then CMin := B;
+ if G > Cmax then CMax := G;
+ if B > Cmax then CMax := B;
+ L2 := 0.5 * (Cmax + Cmin);
+ //The L-value is already calculated, lets see if the current point meats the requirements!
+ if Abs(L2-L1) > LumTol then //if not (Abs(L2 - L1) <= LumTol) then
+ Continue;
+ if Cmax = Cmin then
+ begin
+ //S and H are both zero, lets check if we need found a point!
+ if (H1 <= HueTol) and (S1 <= SatTol) then
+ goto Hit
+ else
+ Continue;
+ end;
+ D := Cmax - Cmin;
+ if L2 < 0.5 then
+ S2 := D / (Cmax + Cmin)
+ else
+ S2 := D / (2 - Cmax - Cmin);
+ { We've Calculated the S. Lets see if we need to continue. }
+ if Abs(S2 - S1) > SatTol then //if not (abs(S1 - S2) <= SatXTol) then
+ Continue;
+ if R = Cmax then
+ H2 := (G - B) / D
+ else
+ if G = Cmax then
+ H2 := 2 + (B - R) / D
+ else
+ H2 := 4 + (R - G) / D;
+ H2 := H2 / 6;
+ if H2 < 0 then
+ H2 := H2 + 1;
+ //Finally lets test H2
+ if Abs(H2 - H1) > HueTol then
+ continue;
+ hit:
+ ClientTPA[c].x := xx;
+ ClientTPA[c].y := yy;
+ Inc(c);
+ end;
+ Inc(Ptr, PtrInc);
+ end;
+ end;
+ end;
+ SetLength(Points, C);
+ Move(ClientTPA[0], Points[0], C * SizeOf(TPoint));
+ Result := C > 0;
+ TClient(Client).IOManager.FreeReturnData;
+end;
+
+function TMFinder.FindColorsSpiralTolerance(x, y: Integer;
+ out Points: TPointArray; color, xs, ys, xe, ye: Integer; Tolerance: Integer
+ ): boolean;
+var
+ PtrData: TRetData;
+ c : integer;
+ RowData : TPRGB32Array;
+ dX, dY, clR, clG, clB, i,SpiralHi: Integer;
+ H1, S1, L1, H2, S2, L2, HueXTol, SatXTol: Extended;
+begin
+ Result := false;
+ DefaultOperations(xs,ys,xe,ye);
+
+ dX := xe - xs;
+ dY := ye - ys;
+ //next, convert the color to r,g,b
+ ColorToRGB(Color, clR, clG, clB);
+ ColorToHSL(Color, H1, S1, L1);
+
+ PtrData := TClient(Client).IOManager.ReturnData(xs, ys, dX + 1, dY + 1);
+
+ c := 0;
+
+ //Load rowdata
+ RowData:= CalculateRowPtrs(ptrdata,dy+1);
+ //Load the spiral path
+ LoadSpiralPath(x-xs,y-ys,0,0,dx,dy);
+ SpiralHi := (dx + 1) * (dy + 1) - 1;
+ case CTS of
+ 0:
+ for i := 0 to SpiralHi do
+ if ((abs(clB-RowData[ClientTPA[i].y][ClientTPA[i].x].B) <= Tolerance) and
+ (abs(clG-RowData[ClientTPA[i].y][ClientTPA[i].x].G) <= Tolerance) and
+ (Abs(clR-RowData[ClientTPA[i].y][ClientTPA[i].x].R) <= Tolerance)) then
+ begin;
+ ClientTPA[c].x := ClientTPA[i].x + xs;
+ ClientTPA[c].y := ClientTPA[i].y + ys;
+ inc(c);
+ end;
+
+
+ 1:
+ for i := 0 to SpiralHi do
+ if (Sqrt(sqr(clR - RowData[ClientTPA[i].y][ClientTPA[i].x].R) +
+ sqr(clG - RowData[ClientTPA[i].y][ClientTPA[i].x].G) +
+ sqr(clB - RowData[ClientTPA[i].y][ClientTPA[i].x].B)) <= Tolerance) then
+ begin;
+ ClientTPA[c].x := ClientTPA[i].x + xs;
+ ClientTPA[c].y := ClientTPA[i].y + ys;
+ inc(c);
+ end;
+
+ 2:
+ begin;
+ HueXTol := hueMod * Tolerance;
+ SatXTol := satMod * Tolerance;
+ for i := 0 to SpiralHi do
+ begin;
+ RGBToHSL(RowData[ClientTPA[i].y][ClientTPA[i].x].R,
+ RowData[ClientTPA[i].y][ClientTPA[i].x].G,
+ RowData[ClientTPA[i].y][ClientTPA[i].x].B,
+ H2,S2,L2);
+ if ((abs(H1 - H2) <= (HueXTol)) and (abs(S1 - S2) <= (satXTol)) and (abs(L1 - L2) <= Tolerance)) then
+ begin;
+ ClientTPA[c].x := ClientTPA[i].x + xs;
+ ClientTPA[c].y := ClientTPA[i].y + ys;
+ inc(c);
+ end;
+ end;
+ end;
+ end;
+ SetLength(Points, C);
+ Move(ClientTPA[0], Points[0], C * SizeOf(TPoint));
+ Result := C > 0;
+ TClient(Client).IOManager.FreeReturnData;
+end;
+
+function TMFinder.FindColors(out TPA: TPointArray; Color, xs, ys, xe, ye: Integer): Boolean;
+var
+ PtrData: TRetData;
+ Ptr: PRGB32;
+ PtrInc: Integer;
+ dX, dY, clR, clG, clB, xx, yy, i: Integer;
+
+begin
+ Result := false;
+ DefaultOperations(xs,ys,xe,ye);
+
+ dX := xe - xs;
+ dY := ye - ys;
+
+ I := 0;
+
+ ColorToRGB(Color, clR, clG, clB);
+
+ PtrData := TClient(Client).IOManager.ReturnData(xs, ys, dX + 1, dY + 1);
+
+ Ptr := PtrData.Ptr;
+ PtrInc := PtrData.IncPtrWith;
+
+ for yy := ys to ye do
+ begin;
+ for xx := xs to xe do
+ begin;
+ if (Ptr^.R = clR) and (Ptr^.G = clG) and (Ptr^.B = clB) then
+ begin
+ Self.ClientTPA[I].x := xx;
+ Self.ClientTPA[i].y := yy;
+ Inc(I);
+ end;
+ Inc(Ptr);
+ end;
+ Inc(Ptr, PtrInc);
+ end;
+
+ SetLength(TPA, I);
+
+ Move(ClientTPA[0], TPA[0], i * SizeOf(TPoint));
+
+ Result := I > 0;
+
+ TClient(Client).IOManager.FreeReturnData;
+end;
+
+ { Only works with CTS 1 for now.. Since Colorsame doesn't return a boolean :-( }
+//We do not check whether every white pixel is in tol range with every other white pixel..
+
+function TMFinder.FindMaskTolerance(mask: TMask; out x, y: Integer; xs,
+ ys, xe, ye: Integer; Tolerance, ContourTolerance: Integer): Boolean;
+var
+ MainRowdata : TPRGB32Array;
+ PtrData : TRetData;
+ MaskW,MaskH : integer;
+ CheckerWhite,CheckerBlack,CurrWhite,CurrBlack: TRGB32;
+ i,ii : integer;
+ dX, dY, xx, yy: Integer;
+label NotFoundMask;
+ { Don't know if the compiler has any speed-troubles with goto jumping in nested for loops. }
+
+begin
+ Result := false;
+ // checks for valid xs,ys,xe,ye? (may involve GetDimensions)
+ DefaultOperations(xs,ys,xe,ye);
+ //Check the mask.
+ CheckMask(Mask);
+ // calculate delta x and y
+ dX := xe - xs;
+ dY := ye - ys;
+
+ PtrData := TClient(Client).IOManager.ReturnData(xs, ys, dX + 1, dY + 1);
+ //Caculate the row ptrs
+ MainRowdata:= CalculateRowPtrs(PtrData,dy+1);
+
+ //Get the 'fixed' mask size
+ MaskW := Mask.W;
+ MaskH := Mask.H;
+ //Heck our mask cannot be outside the search area
+ dX := dX - MaskW;
+ dY := dY - MaskH;
+ for yy := 0 to dY do
+ for xx := 0 to dX do
+ begin;
+ CheckerWhite := MainRowdata[yy + mask.White[0].y][xx + mask.white[0].x];
+ CheckerBlack := MainRowdata[yy + mask.Black[0].y][xx + mask.Black[0].x];
+ //Just check two 'random' points against eachother, might be a time saver in some circumstances.
+ if (Sqrt(sqr(CheckerWhite.r-CheckerBlack.r) + sqr(CheckerWhite.G-CheckerBlack.G) + sqr(CheckerWhite.b-CheckerBlack.B))
+ <= ContourTolerance) then //The Tol between the white and black is lower than the minimum difference, so continue with looking!
+ continue;
+ for i := 0 to mask.WhiteHi do
+ begin;
+ CurrWhite := MainRowdata[yy + mask.White[i].y][xx + mask.white[i].x];
+ if (Sqrt(sqr(CheckerWhite.r-CurrWhite.r) + sqr(CheckerWhite.G-CurrWhite.G) + sqr(CheckerWhite.b-CurrWhite.B))
+ > Tolerance) then //The white checkpoint n' this point aren't in the same tol range -> goto nomatch;
+ goto NotFoundMask;
+ {$ifdef CheckAllBackground}
+ for ii := 0 to mask.BlackHi do
+ begin
+ CurrBlack := MainRowdata[yy + mask.Black[ii].y][xx + mask.Black[ii].x];
+ if (Sqrt(sqr(CurrWhite.r-CurrBlack.r) + sqr(CurrWhite.G-CurrBlack.G) + sqr(CurrWhite.b-CurrBlack.B))
+ <= ContourTolerance) then //The Tol between the white and black is lower than the minimum difference -> goto nomatch;
+ goto NotFoundMask;
+ end;
+ {$endif}
+ end;
+ {$ifndef CheckAllBackground}
+ for ii := 0 to mask.BlackHi do
+ begin
+ CurrBlack := MainRowdata[yy + mask.Black[ii].y][xx + mask.Black[ii].x];
+ if (Sqrt(sqr(CheckerWhite.r-CurrBlack.r) + sqr(CheckerWhite.G-CurrBlack.G) + sqr(CheckerWhite.b-CurrBlack.B))
+ <= ContourTolerance) then //The Tol between the white and black is lower than the minimum difference -> goto nomatch;
+ goto NotFoundMask;
+ end;
+ {$endif}
+ //We have found the mask appearntly, otherwise we would have jumped! Gna Gna.
+ x := xx + xs;
+ y := yy + ys;
+ TClient(Client).IOManager.FreeReturnData;
+ Exit(true);
+ //Bah not found the mask, lets do nothing and continue!
+ NotFoundMask:
+ end;
+ TClient(Client).IOManager.FreeReturnData;
+end;
+
+procedure TMFinder.CheckMask(Mask: TMask);
+begin
+ if (Mask.W < 1) or (Mask.H < 1) or (Mask.WhiteHi < 0) or (Mask.BlackHi < 0) then
+ raise exception.CreateFMT('Mask is invalid. Width/Height: (%d,%d). WhiteHi/BlackHi: (%d,%d)',[Mask.W,Mask.H,Mask.WhiteHi,Mask.BlackHi]);
+end;
+
+function TMFinder.FindBitmap(bitmap: TMufasaBitmap; out x, y: Integer): Boolean;
+var
+ w,h : integer;
+begin
+ TClient(Client).IOManager.GetDimensions(w,h);
+ result := Self.FindBitmapIn(bitmap,x,y,0,0,w-1,h-1);
+end;
+
+function TMFinder.FindBitmapIn(bitmap: TMufasaBitmap; out x, y: Integer; xs,
+ ys, xe, ye: Integer): Boolean;
+var
+ MainRowdata : TPRGB32Array;
+ BmpRowData : TPRGB32Array;
+ PtrData : TRetData;
+ BmpW,BmpH : integer;
+ xBmp,yBmp : integer;
+ tmpY : integer;
+ dX, dY, xx, yy: Integer;
+ SkipCoords : T2DBoolArray;
+label NotFoundBmp;
+ { Don't know if the compiler has any speed-troubles with goto jumping in nested for loops. }
+
+begin
+ Result := false;
+ // checks for valid xs,ys,xe,ye? (may involve GetDimensions)
+ DefaultOperations(xs,ys,xe,ye);
+
+ // calculate delta x and y
+ dX := xe - xs;
+ dY := ye - ys;
+
+ PtrData := TClient(Client).IOManager.ReturnData(xs, ys, dX + 1, dY + 1);
+ //Caculate the row ptrs
+ MainRowdata:= CalculateRowPtrs(PtrData,dy+1);
+ BmpRowData:= CalculateRowPtrs(bitmap);
+ //Get the 'fixed' bmp size
+ BmpW := bitmap.Width - 1;
+ BmpH := bitmap.Height - 1;
+ //Heck our bitmap cannot be outside the search area
+ dX := dX - bmpW;
+ dY := dY - bmpH;
+ //Get the "skip coords".
+ CalculateBitmapSkipCoords(Bitmap,SkipCoords);
+ for yy := 0 to dY do
+ for xx := 0 to dX do
+ begin;
+ for yBmp:= 0 to BmpH do
+ begin;
+ tmpY := yBmp + yy;
+ for xBmp := 0 to BmpW do
+ if not SkipCoords[yBmp][xBmp] then
+ if (BmpRowData[yBmp][xBmp].R <> MainRowdata[tmpY][xBmp + xx].R) or
+ (BmpRowData[yBmp][xBmp].G <> MainRowdata[tmpY][xBmp + xx].G) or
+ (BmpRowData[yBmp][xBmp].B <> MainRowdata[tmpY][xBmp + xx].B) then
+ goto NotFoundBmp;
+
+ end;
+ //We did find the Bmp, otherwise we would be at the part below
+ TClient(Client).IOManager.FreeReturnData;
+ x := xx + xs;
+ y := yy + ys;
+ result := true;
+ exit;
+ NotFoundBmp:
+ end;
+ TClient(Client).IOManager.FreeReturnData;
+end;
+
+function TMFinder.FindBitmapToleranceIn(bitmap: TMufasaBitmap; out x, y: Integer; xs,
+ ys, xe, ye: Integer; tolerance: Integer): Boolean;
+var
+ MainRowdata : TPRGB32Array;
+ BmpRowData : TPRGB32Array;
+ PtrData : TRetData;
+ BmpW,BmpH : integer;
+ xBmp,yBmp : integer;
+ tmpY : integer;
+ dX, dY, xx, yy: Integer;
+ CCTS : integer;
+ H,S,L,HMod,SMod : extended;
+ SkipCoords : T2DBoolArray;
+label NotFoundBmp;
+ { Don't know if the compiler has any speed-troubles with goto jumping in nested for loops. }
+
+begin
+ Result := false;
+ // checks for valid xs,ys,xe,ye? (may involve GetDimensions)
+ DefaultOperations(xs,ys,xe,ye);
+
+ // calculate delta x and y
+ dX := xe - xs;
+ dY := ye - ys;
+
+ PtrData := TClient(Client).IOManager.ReturnData(xs, ys, dX + 1, dY + 1);
+ //Caculate the row ptrs
+ MainRowdata:= CalculateRowPtrs(PtrData,dy+1);
+ BmpRowData:= CalculateRowPtrs(bitmap);
+ //Get the 'fixed' bmp size
+ BmpW := bitmap.Width - 1;
+ BmpH := bitmap.Height - 1;
+ //Heck our bitmap cannot be outside the search area
+ dX := dX - bmpW;
+ dY := dY - bmpH;
+ //Compiler hints
+ HMod := 0;SMod := 0;H := 0.0;S := 0.0; L := 0.0;
+ CCTS := Self.CTS;
+ //We wont want HSL comparison with BMPs, right? Not for now atleast.
+ if CCTS > 1 then
+ CCTS := 1;
+ //Get the "skip coords".
+ CalculateBitmapSkipCoords(Bitmap,SkipCoords);
+ for yy := 0 to dY do
+ for xx := 0 to dX do
+ begin;
+ for yBmp:= 0 to BmpH do
+ begin;
+ tmpY := yBmp + yy;
+ for xBmp := 0 to BmpW do
+ if not SkipCoords[yBmp][xBmp] then
+ if not ColorSame(CCTS,tolerance,
+ BmpRowData[yBmp][xBmp].R,BmpRowData[yBmp][xBmp].G,BmpRowData[yBmp][xBmp].B,
+ MainRowdata[tmpY][xBmp + xx].R,MainRowdata[tmpY][xBmp + xx].G,MainRowdata[tmpY][xBmp + xx].B,
+ H,S,L,HMod,SMod) then
+ goto NotFoundBmp;
+
+ end;
+ //We did find the Bmp, otherwise we would be at the part below
+ TClient(Client).IOManager.FreeReturnData;
+ x := xx + xs;
+ y := yy + ys;
+ result := true;
+ exit;
+ NotFoundBmp:
+ end;
+ TClient(Client).IOManager.FreeReturnData;
+end;
+
+function TMFinder.FindBitmapSpiral(bitmap: TMufasaBitmap; var x, y: Integer;
+ xs, ys, xe, ye: Integer): Boolean;
+var
+ MainRowdata : TPRGB32Array;
+ BmpRowData : TPRGB32Array;
+ PtrData : TRetData;
+ BmpW,BmpH : integer;
+ xBmp,yBmp : integer;
+ tmpY : integer;
+ dX, dY, i,HiSpiral: Integer;
+ SkipCoords : T2DBoolArray;
+label NotFoundBmp;
+ { Don't know if the compiler has any speed-troubles with goto jumping in nested for loops }
+
+begin
+ Result := false;
+ // checks for valid xs,ys,xe,ye? (may involve GetDimensions)
+ DefaultOperations(xs,ys,xe,ye);
+
+ // calculate delta x and y
+ dX := xe - xs;
+ dY := ye - ys;
+
+ PtrData := TClient(Client).IOManager.ReturnData(xs, ys, dX + 1, dY + 1);
+ //Caculate the row ptrs
+ MainRowdata:= CalculateRowPtrs(PtrData,dy+1);
+ BmpRowData:= CalculateRowPtrs(bitmap);
+ //Get the 'fixed' bmp size
+ BmpW := bitmap.Width - 1;
+ BmpH := bitmap.Height - 1;
+ //Heck, our bitmap cannot be outside the search area
+ dX := dX - bmpW;
+ dY := dY - bmpH;
+ //Load the spiral into memory
+ LoadSpiralPath(x-xs,y-ys,0,0,dX,dY);
+ HiSpiral := (dx+1) * (dy+1) - 1;
+ //Get the "skip coords".
+ CalculateBitmapSkipCoords(Bitmap,SkipCoords);
+ for i := 0 to HiSpiral do
+ begin;
+ for yBmp:= 0 to BmpH do
+ begin;
+ tmpY := yBmp + ClientTPA[i].y;
+ for xBmp := 0 to BmpW do
+ if not SkipCoords[yBmp][xBmp] then
+ if (BmpRowData[yBmp][xBmp].R <> MainRowdata[tmpY][xBmp + ClientTPA[i].x].R) or
+ (BmpRowData[yBmp][xBmp].G <> MainRowdata[tmpY][xBmp + ClientTPA[i].x].G) or
+ (BmpRowData[yBmp][xBmp].B <> MainRowdata[tmpY][xBmp + ClientTPA[i].x].B) then
+ goto NotFoundBmp;
+
+ end;
+ //We did find the Bmp, otherwise we would be at the part below
+ TClient(Client).IOManager.FreeReturnData;
+ x := ClientTPA[i].x + xs;
+ y := ClientTPA[i].y + ys;
+ result := true;
+ exit;
+ NotFoundBmp:
+ end;
+ TClient(Client).IOManager.FreeReturnData;
+end;
+
+function TMFinder.FindBitmapSpiralTolerance(bitmap: TMufasaBitmap; var x,
+ y: Integer; xs, ys, xe, ye, tolerance: integer): Boolean;
+var
+ MainRowdata : TPRGB32Array;
+ BmpRowData : TPRGB32Array;
+ PtrData : TRetData;
+ BmpW,BmpH : integer;
+ xBmp,yBmp : integer;
+ tmpY : integer;
+ dX, dY, i,HiSpiral: Integer;
+ CCTS : integer;
+ H,S,L,HMod,SMod : extended;
+ SkipCoords : T2DBoolArray;
+label NotFoundBmp;
+ { Don't know if the compiler has any speed-troubles with goto jumping in nested for loops. }
+
+begin
+ Result := false;
+ // checks for valid xs,ys,xe,ye? (may involve GetDimensions)
+ DefaultOperations(xs,ys,xe,ye);
+
+ // calculate delta x and y
+ dX := xe - xs;
+ dY := ye - ys;
+
+ PtrData := TClient(Client).IOManager.ReturnData(xs, ys, dX + 1, dY + 1);
+ //Caculate the row ptrs
+ MainRowdata:= CalculateRowPtrs(PtrData,dy+1);
+ BmpRowData:= CalculateRowPtrs(bitmap);
+ //Get the 'fixed' bmp size
+ BmpW := bitmap.Width - 1;
+ BmpH := bitmap.Height - 1;
+ //Heck, our bitmap cannot be outside the search area
+ dX := dX - bmpW;
+ dY := dY - bmpH;
+ //Load the spiral into memory
+ LoadSpiralPath(x-xs,y-ys,0,0,dX,dY);
+ HiSpiral := (dx+1) * (dy+1) - 1;
+ //Compiler hints
+ HMod := 0;SMod := 0;H := 0.0;S := 0.0; L := 0.0;
+ //NO HSL.
+ CCTS := Self.CTS;
+ if CCTS > 1 then
+ CCTS := 1;
+ //Get the "skip coords".
+ CalculateBitmapSkipCoords(Bitmap,SkipCoords);
+ for i := 0 to HiSpiral do
+ begin;
+ for yBmp:= 0 to BmpH do
+ begin;
+ tmpY := yBmp + ClientTPA[i].y;
+ for xBmp := 0 to BmpW do
+ if not SkipCoords[yBmp][xBmp] then
+ if not ColorSame(CCTS,tolerance,
+ BmpRowData[yBmp][xBmp].R,BmpRowData[yBmp][xBmp].G,BmpRowData[yBmp][xBmp].B,
+ MainRowdata[tmpY][xBmp + ClientTPA[i].x].R,MainRowdata[tmpY][xBmp + ClientTPA[i].x].G,
+ MainRowdata[tmpY][xBmp + ClientTPA[i].x].B,
+ H,S,L,HMod,SMod) then
+ goto NotFoundBmp;
+
+ end;
+ //We did find the Bmp, otherwise we would be at the part below
+ x := ClientTPA[i].x + xs;
+ y := ClientTPA[i].y + ys;
+ result := true;
+ exit;
+ NotFoundBmp:
+ end;
+ TClient(Client).IOManager.FreeReturnData;
+end;
+
+function TMFinder.FindBitmapsSpiralTolerance(bitmap: TMufasaBitmap; x,
+ y: Integer; out Points: TPointArray; xs, ys, xe, ye,tolerance: Integer): Boolean;
+var
+ MainRowdata : TPRGB32Array;
+ BmpRowData : TPRGB32Array;
+ PtrData : TRetData;
+ BmpW,BmpH : integer;
+ xBmp,yBmp : integer;
+ tmpY : integer;
+ dX, dY, i,HiSpiral: Integer;
+ FoundC : integer;
+ CCTS : integer;
+ H,S,L,HMod,SMod : extended;
+ SkipCoords : T2DBoolArray;
+label NotFoundBmp;
+ { Don't know if the compiler has any speed-troubles with goto jumping in nested for loops. }
+
+begin
+ Result := false;
+ // checks for valid xs,ys,xe,ye? (may involve GetDimensions)
+ DefaultOperations(xs,ys,xe,ye);
+
+ // calculate delta x and y
+ dX := xe - xs;
+ dY := ye - ys;
+
+ PtrData := TClient(Client).IOManager.ReturnData(xs, ys, dX + 1, dY + 1);
+ //Caculate the row ptrs
+ MainRowdata:= CalculateRowPtrs(PtrData,dy+1);
+ BmpRowData:= CalculateRowPtrs(bitmap);
+ //Get the 'fixed' bmp size
+ BmpW := bitmap.Width - 1;
+ BmpH := bitmap.Height - 1;
+ //Heck, our bitmap cannot be outside the search area
+ dX := dX - bmpW;
+ dY := dY - bmpH;
+ //Load the spiral into memory
+ LoadSpiralPath(x-xs,y-ys,0,0,dX,dY);
+ HiSpiral := (dx+1) * (dy+1) - 1;
+ //Compiler hints
+ HMod := 0;SMod := 0;H := 0.0;S := 0.0; L := 0.0;
+ //NO HSL.
+ CCTS := Self.CTS;
+ if CCTS > 1 then
+ CCTS := 1;
+ FoundC := 0;
+ //Get the "skip coords".
+ CalculateBitmapSkipCoords(Bitmap,SkipCoords);
+ for i := 0 to HiSpiral do
+ begin;
+ for yBmp:= 0 to BmpH do
+ begin;
+ tmpY := yBmp + ClientTPA[i].y;
+ for xBmp := 0 to BmpW do
+ if not SkipCoords[yBmp][xBmp] then
+ if not ColorSame(CCTS,tolerance,
+ BmpRowData[yBmp][xBmp].R,BmpRowData[yBmp][xBmp].G,BmpRowData[yBmp][xBmp].B,
+ MainRowdata[tmpY][xBmp + ClientTPA[i].x].R,MainRowdata[tmpY][xBmp + ClientTPA[i].x].G,
+ MainRowdata[tmpY][xBmp + ClientTPA[i].x].B,
+ H,S,L,HMod,SMod) then
+ goto NotFoundBmp;
+
+ end;
+ //We did find the Bmp, otherwise we would be at the part below
+ ClientTPA[FoundC].x := ClientTPA[i].x + xs;
+ ClientTPA[FoundC].y := ClientTPA[i].y + ys;
+ inc(FoundC);
+ NotFoundBmp:
+ end;
+ if FoundC > 0 then
+ begin;
+ result := true;
+ SetLength(Points,FoundC);
+ Move(ClientTPA[0], Points[0], FoundC * SizeOf(TPoint));
+ end;
+ TClient(Client).IOManager.FreeReturnData;
+end;
+
+function TMFinder.FindDeformedBitmapToleranceIn(bitmap: TMufasaBitmap; out x,
+ y: Integer; xs, ys, xe, ye: Integer; tolerance: Integer; Range: Integer;
+ AllowPartialAccuracy: Boolean; var accuracy: Extended): Boolean;
+var
+ MainRowdata : TPRGB32Array;
+ BmpRowData : TPRGB32Array;
+ PtrData : TRetData;
+ BmpW,BmpH : integer;
+ xBmp,yBmp : integer;
+ dX, dY, xx, yy: Integer;
+ SearchdX,SearchdY : integer;
+ GoodCount : integer;//Save the amount of pixels who have found a correspondening pixel
+ BestCount : integer;//The best amount of pixels till now..
+ BestPT : TPoint; //The point where it found the most pixels.
+ RangeX,RangeY : Integer;
+ yStart,yEnd,xStart,xEnd : integer;
+ TotalC : integer;
+ SkipCoords : T2DBoolArray;
+ PointsLeft : T2DIntArray;
+label FoundBMPPoint, Madness;
+ { Don't know if the compiler has any speed-troubles with goto jumping in nested for loops. }
+
+begin
+ Result := false;
+ // checks for valid xs,ys,xe,ye? (may involve GetDimensions)
+ DefaultOperations(xs,ys,xe,ye);
+
+ // calculate delta x and y
+ dX := xe - xs;
+ dY := ye - ys;
+ SearchDx := dX;
+ SearchDy := dY;
+ PtrData := TClient(Client).IOManager.ReturnData(xs, ys, dX + 1, dY + 1);
+ //Caculate the row ptrs
+ MainRowdata:= CalculateRowPtrs(PtrData,dy+1);
+ BmpRowData:= CalculateRowPtrs(bitmap);
+ //Get the 'fixed' bmp size
+ BmpW := bitmap.Width - 1;
+ BmpH := bitmap.Height - 1;
+ //Heck our bitmap cannot be outside the search area
+ dX := dX - bmpW;
+ dY := dY - bmpH;
+ //Reset the accuracy :-)
+ Accuracy := 0;
+ BestCount := -1;
+ BestPT := Point(-1,-1);
+ //Get the "skip coords". and PointsLeft (so we can calc whether we should stop searching or not ;-).
+ CalculateBitmapSkipCoordsEx(Bitmap,SkipCoords,TotalC,PointsLeft);
+
+ for yy := 0 to dY do
+ for xx := 0 to dX do
+ begin;
+ GoodCount := 0;
+ for yBmp:= 0 to BmpH do
+ begin;
+ for xBmp := 0 to BmpW do
+ begin;
+ //We do not have to check this point, win win win <--- triple win <-- JACKPOT!
+ if SkipCoords[yBmp][xBmp] then
+ Continue;
+ //Calculate points of the BMP left against Goodcount (if it cannot possibly get more points skip this x,y?
+ if bestCount > (GoodCount + PointsLeft[yBmp][xBmp]) then
+ goto Madness;
+ //The point on the bitmap + the the coordinate we are on at the "screen" minus the range.
+ yStart := max(yBmp + yy-Range,0);
+ yEnd := Min(yBmp + yy+range,SearchdY);
+ for RangeY := yStart to yEnd do
+ begin;
+ xStart := max(xx-Range + xBmp,0);
+ xEnd := Min(xx+range + xBmp,SearchdX);
+ for RangeX := xStart to xEnd do
+ begin;
+ if Sqrt(sqr(BmpRowData[yBmp][xBmp].R - MainRowdata[RangeY][RangeX].R) + sqr(BmpRowData[yBmp][xBmp].G - MainRowdata[RangeY][RangeX].G)
+ +sqr(BmpRowData[yBmp][xBmp].B - MainRowdata[RangeY][RangeX].B)) <= tolerance then
+ goto FoundBMPPoint;
+ end;
+ end;
+ //We did not find a good point so were continueing!
+ Continue;
+ FoundBMPPoint:
+ //We found a pooint woot!
+ inc(GoodCount);
+ end;
+ end;
+ //If we jumped to Madness it means we did not have enuf points left to beat tha fu-king score.
+ Madness:
+ if GoodCount > BestCount then //This x,y has the best Acc so far!
+ begin;
+ BestCount := GoodCount;
+ BestPT := Point(xx+xs,yy+ys);
+ if GoodCount = TotalC then
+ begin;
+ TClient(Client).IOManager.FreeReturnData;
+ x := BestPT.x;
+ y := BestPT.y;
+ accuracy:= 1;
+ Exit(true);
+ end;
+ end;
+ end;
+ TClient(Client).IOManager.FreeReturnData;
+ if BestCount = 0 then
+ Exit;
+ accuracy := BestCount / TotalC;
+ if (accuracy = 1) or AllowPartialAccuracy then
+ begin
+ x := BestPT.x;
+ y := BestPT.y;
+ Exit(true);
+ end;
+end;
+
+function TMFinder.FindDTM(DTM: pDTM; out x, y: Integer; x1, y1, x2, y2: Integer): Boolean;
+
+var
+ P: TPointArray;
+begin
+ Self.FindDTMs(DTM, P, x1, y1, x2, y2, 1);
+ if(Length(p) > 0) then
+ begin
+ x := p[0].x;
+ y := p[0].y;
+ Exit(True);
+ end;
+ Exit(False);
+end;
+
+function TMFinder.FindDTMs(DTM: pDTM; out Points: TPointArray; x1, y1, x2, y2, maxToFind: Integer): Boolean;
+var
+ // Colours of DTMs
+ C: Array of Integer;
+
+ // Bitwise
+ b: Array of Array of Integer;
+
+ // bounds
+ W, H: integer;
+ MA: TBox;
+
+ // for loops, etc
+ xx, yy: integer;
+ i, xxx,yyy: Integer;
+
+ // for comparisons.
+ rgbs: array of TRGB32;
+
+ //clientdata
+ cd: TPRGB32Array;
+
+ PtrData: TRetData;
+
+ // point count
+ pc: Integer = 0;
+
+ goodPoints: Array of Boolean;
+
+ label theEnd;
+ label AnotherLoopEnd;
+
+
+
+begin
+ if not DTMConsistent(dtm) then
+ begin
+ raise Exception.CreateFmt('FindDTMs: DTM is not consistent.', []);
+ Exit;
+ end;
+
+ // Get the area we should search in for the Main Point.
+ //writeln(Format('%d, %d, %d, %d', [x1,y1,x2,y2]));
+ MA := ValidMainPointBox(DTM, x1, y1, x2, y2);
+ //writeln(Format('%d, %d, %d, %d', [MA.x1,MA.y1,MA.x2,MA.y2]));
+
+ DefaultOperations(MA.x1, MA.y1, MA.x2, MA.y2);
+
+ setlength(goodPoints, dtm.l);
+ for i := 0 to dtm.l - 1 do
+ goodPoints[i] := not dtm.bp[i];
+
+ // Init data structure B.
+ W := x2 - x1;
+ H := y2 - y1;
+ setlength(b, (W + 1) * 2);
+ for i := 0 to W do
+ begin
+ setlength(b[i], (H + 1) * 2);
+ { does setlength init already? if it doesn't, do we want to init here?
+ or do we want to init in the loop, as we loop over every b anyway? }
+
+ // init
+ FillChar(b[i][0], SizeOf(Integer) * H * 2, 0);
+ end;
+
+ // C = DTM.C
+ C := DTM.c;
+
+ // Retreive Client Data.
+ PtrData := TClient(Client).IOManager.ReturnData(x1, y1, W + 1, H + 1);
+
+ cd := CalculateRowPtrs(PtrData, h + 1);
+ //writeln(format('w,h: %d, %d', [w,h]));
+
+ // pre calc rgb values for dtms
+ SetLength(rgbs, dtm.l);
+ for i := 0 to dtm.l - 1 do
+ ColorToRGB(dtm.c[i], rgbs[i].r, rgbs[i].g, rgbs[i].b);
+
+ for yy := MA.y1 to MA.y2 do
+ for xx := MA.x1 to MA.x2 do
+ begin
+ // Checking main point now; store that we have checked it.
+ // (Main point is point 1)
+ b[xx][yy] := B[xx][yy] or 1;
+
+ // if Sqrt(sqr(rgbs[0].r - cd[yy][xx].R) + sqr(rgbs[0].g - cd[yy][xx].G) + sqr(rgbs[0].b - cd[yy][xx].B)) > dtm.t[0] then
+ if not SimilarColors(dtm.c[0], RGBToColor(cd[yy][xx].R, cd[yy][xx].G, cd[yy][xx].B), dtm.t[0]) then
+ goto AnotherLoopEnd;
+
+ // Mainpoint match. (If it did not match, we would be at AnotherLoopEnd)
+ b[xx][yy+1] := B[xx][yy+1] or 1;
+
+
+ for i := 1 to dtm.l - 1 do
+ begin //change to use other areashapes too.
+ for xxx := xx - dtm.asz[i] + dtm.p[i].x to xx + dtm.asz[i] + dtm.p[i].x do
+ for yyy := yy - dtm.asz[i] + dtm.p[i].y to yy + dtm.asz[i]+ dtm.p[i].y do
+ begin
+ // If we have matched this point
+ if b[xxx][yyy+1] and (1 shl i) = 0 then
+ begin
+ // Checking point i now. (Store that we matched it)
+ b[xxx][yyy]:=b[xxx][yyy] or (1 shl i);
+
+ // if Sqrt(sqr(rgbs[i].r - cd[yyy][xxx].R) + sqr(rgbs[i].g - cd[yyy][xxx].G) + sqr(rgbs[i].b - cd[yyy][xxx].B)) <= dtm.t[i] then
+ if SimilarColors(dtm.c[i], RGBToColor(cd[yyy][xxx].R, cd[yyy][xxx].G, cd[yyy][xxx].B), dtm.t[i]) then
+ b[xxx][yyy+1] := B[xxx][yyy+1] or (1 shl i)
+ else
+ goto AnotherLoopEnd;
+ end;
+
+ if (b[xxx][yyy+1] and (1 shl i) = 0) and goodPoints[i] then
+ goto AnotherLoopEnd;
+ end;
+ end;
+ //writeln(Format('Found point: (%d, %d)', [xx,yy]));
+ ClientTPA[pc] := Point(xx, yy);
+ Inc(pc);
+ if(pc = maxToFind) then
+ goto theEnd;
+ AnotherLoopEnd:
+ //writeln(format('b[%d][%d]: %d' ,[xx,yy,b[xx][yy]]));
+ end;
+
+ TheEnd:
+ TClient(Client).IOManager.FreeReturnData;
+
+ SetLength(Points, pc);
+ if pc > 0 then
+ Move(ClientTPA[0], Points[0], pc * SizeOf(TPoint));
+end;
+
+function TMFinder.FindDTMRotated(DTM: pDTM; out x, y: Integer; x1, y1, x2, y2: Integer; sAngle, eAngle, aStep: Extended; out aFound: Extended): Boolean;
+
+begin
+ raise Exception.CreateFmt('Not done yet!', []);
+end;
+
+function TMFinder.FindDTMsRotated(DTM: pDTM; out Points: TPointArray; x1, y1, x2, y2: Integer; sAngle, eAngle, aStep: Extended; out aFound: T2DExtendedArray; maxToFind: Integer): Boolean;
+var
+ // Colours of DTMs
+ C: Array of Integer;
+
+ // Bitwise
+ b: Array of Array of Integer;
+
+ // bounds
+ W, H: integer;
+ MA: TBox;
+
+ // for loops, etc
+ xx, yy: integer;
+ i, xxx,yyy: Integer;
+
+ // for comparisons.
+ rgbs: array of TRGB32;
+
+ //clientdata
+ cd: TPRGB32Array;
+
+ PtrData: TRetData;
+
+ // point count
+ pc: Integer = 0;
+
+ goodPoints: Array of Boolean;
+
+ label theEnd;
+ label AnotherLoopEnd;
+
+
+
+begin
+ if not DTMConsistent(dtm) then
+ begin
+ raise Exception.CreateFmt('FindDTMs: DTM is not consistent.', []);
+ Exit;
+ end;
+
+ // Get the area we should search in for the Main Point.
+ //writeln(Format('%d, %d, %d, %d', [x1,y1,x2,y2]));
+ MA := ValidMainPointBoxRotated(DTM, x1, y1, x2, y2);
+ //writeln(Format('%d, %d, %d, %d', [MA.x1,MA.y1,MA.x2,MA.y2]));
+
+ DefaultOperations(MA.x1, MA.y1, MA.x2, MA.y2);
+
+ { Don't forget to pre calculate the rotated points at the start.
+ Saves a lot of rotatepoint() calls. }
+ raise Exception.CreateFmt('Not done yet!', []);
+end;
+
+function TMFinder.GetColors(Coords: TPointArray): TIntegerArray;
+var
+ Box : TBox;
+ Len, I,w,h : integer;
+ PtrRet : TRetData;
+ Ptr : PRGB32;
+begin
+ len := high(Coords);
+ setlength(result,len+1);
+ box := GetTPABounds(coords);
+ w := 0;
+ h := 0;
+ DefaultOperations(w,h,box.x2,box.y2);
+ TClient(Self.Client).IOManager.GetDimensions(w,h);
+ PtrRet := TClient(Client).IOManager.ReturnData(0,0,Box.x2 + 1,box.y2+ 1);//Otherwise lotsashit.
+ ptr := PtrRet.Ptr;
+ for i := 0 to len do
+ Result[i] := BGRToRGB(Ptr[Coords[i].y*w + Coords[i].x]);
+end;
+end.
diff --git a/branches/script-component/Units/MMLCore/fontloader.pas b/branches/script-component/Units/MMLCore/fontloader.pas
new file mode 100644
index 0000000..d3943c0
--- /dev/null
+++ b/branches/script-component/Units/MMLCore/fontloader.pas
@@ -0,0 +1,241 @@
+{
+ This file is part of the Mufasa Macro Library (MML)
+ Copyright (c) 2009 by Raymond van Venetië and Merlijn Wajer
+
+ MML is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ MML is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with MML. If not, see .
+
+ See the file COPYING, included in this distribution,
+ for details about the copyright.
+
+ Fonts class for the Mufasa Macro Library
+}
+
+unit fontloader;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+ Classes, SysUtils,
+ ocrutil; // contains the actual `loading'
+
+{
+ We will not give any access to actual indices.
+}
+
+type
+ TMFont = class(TObject)
+ constructor Create;
+ destructor Destroy; override;
+
+ function Copy: TMFont;
+ public
+ Name: String;
+ Data: TOcrData;
+ end;
+
+
+type
+
+ { TMFonts }
+
+ TMFonts = class(TObject)
+ private
+ function GetFontIndex(Name: String): Integer;
+ function GetFontByIndex(Index : integer): TMfont;
+ private
+ Fonts: TList;
+ Path: String;
+ public
+ constructor Create;
+ destructor Destroy; override;
+
+ function GetFont(Name: String): TOcrData;
+ function FreeFont(Name: String): boolean;
+ function LoadFont(Name: String; Shadow: Boolean): boolean;
+ procedure SetPath(aPath: String);
+ function GetPath: String;
+ function Copy: TMFonts;
+ function Count : integer;
+ property Font[Index : integer]: TMfont read GetFontByIndex; default;
+ end;
+
+implementation
+
+uses
+ files, MufasaTypes;
+
+
+constructor TMFont.Create;
+begin
+ inherited;
+
+ Name:='';
+end;
+
+destructor TMFont.Destroy;
+begin
+ Name:='';
+
+ inherited;
+end;
+
+function TMFont.Copy: TMFont;
+var
+ i, l, ll:integer;
+begin
+ Result := TMFont.Create;
+ Result.Name := Self.Name;
+ Move(Self.Data.ascii[0], Result.Data.ascii[0], length(Self.Data.ascii) * SizeOf(TocrGlyphMetric));
+ l := Length(Self.Data.Pos);
+ SetLength(Result.Data.pos, l);
+ for i := 0 to l - 1 do
+ begin
+ ll := length(Self.Data.Pos[i]);
+ setlength(Result.Data.Pos[i], ll);
+ Move(Self.Data.Pos[i][0], Result.Data.Pos[i][0], ll*SizeOf(Integer));
+ end;
+
+ SetLength(Result.Data.pos_adj, length(Self.Data.pos_adj));
+ Move(Self.Data.pos_adj[0], Result.Data.pos_adj[0], length(Self.Data.pos_adj) * SizeOf(real));
+
+ l := Length(Self.Data.neg);
+ SetLength(Result.Data.neg, l);
+ for i := 0 to l - 1 do
+ begin
+ ll := length(Self.Data.neg[i]);
+ setlength(Result.Data.neg[i], ll);
+ Move(Self.Data.neg[i][0], Result.Data.neg[i][0], ll*SizeOf(Integer));
+ end;
+
+ SetLength(Result.Data.neg_adj, length(Self.Data.neg_adj));
+ Move(Self.Data.neg_adj[0], Result.Data.neg_adj[0], length(Self.Data.neg_adj) * SizeOf(real));
+
+ SetLength(Result.Data.map, length(Self.Data.map));
+ Move(Self.Data.map[0], Result.Data.map[0], length(Self.Data.map) * SizeOf(char));
+
+ Result.Data.Width := Self.Data.Width;
+ Result.Data.Height := Self.Data.Height;
+ Result.Data.inputs := Self.Data.inputs;
+ Result.Data.outputs := Self.Data.outputs;
+end;
+
+function TMFonts.GetFontByIndex(Index : integer): TMfont;
+begin
+ result := TMfont(Fonts.Items[index]);
+end;
+
+constructor TMFonts.Create;
+
+begin
+ inherited;
+
+ Fonts := TList.Create;
+end;
+
+destructor TMFonts.Destroy;
+var
+ i:integer;
+begin
+ for i := 0 to Fonts.Count - 1 do
+ TMFont(Fonts.Items[i]).Free;
+ Fonts.Free;
+
+ inherited;
+end;
+
+procedure TMFonts.SetPath(aPath: String);
+begin
+ Path := aPath;
+end;
+
+function TMFonts.GetPath: String;
+begin
+ Exit(Path);
+end;
+
+function TMFonts.GetFontIndex(Name: String): Integer;
+var
+ i: integer;
+begin
+ for i := 0 to Fonts.Count - 1 do
+ begin
+ if Name = TMFont(Fonts.Items[i]).Name then
+ Exit(i);
+ end;
+ raise Exception.Create('Font [' + Name + '] not found.');
+ Exit(-1);
+end;
+
+function TMFonts.GetFont(Name: String): TOcrData;
+var
+ i: integer;
+begin
+ i := GetFontIndex(Name);
+ Exit(TMFont(Fonts.Items[i]).Data);
+end;
+
+function TMFonts.FreeFont(Name: String): boolean;
+var
+ i: integer;
+begin
+ i := GetFontIndex(Name);
+ TMFont(Fonts.Items[i]).Free;
+ Fonts.Delete(i);
+end;
+
+function TMFonts.LoadFont(Name: String; Shadow: Boolean): boolean;
+var
+ f: TMFont;
+ ocrdata: TOcrData;
+
+begin
+ if not DirectoryExists(Path + Name) then
+ begin
+ raise Exception.Create('LoadFont: Directory ' + Path + Name + ' does not exists.');
+ Exit(False);
+ end;
+
+ ocrdata := InitOCR(Path + Name + DS, Shadow);
+
+ f:=TMFont.Create;
+ f.Name := Name;
+ if Shadow then
+ F.Name := F.Name + '_s';
+ f.Data := ocrdata;
+ Fonts.Add(f);
+ {$IFDEF FONTDEBUG}
+ writeln('Loaded Font ' + f.Name);
+ {$ENDIF}
+end;
+
+function TMFonts.Copy: TMFonts;
+
+var
+ i:integer;
+begin
+ Result := TMFonts.Create;
+ Result.Path := Self.GetPath();
+ for i := 0 to Self.Fonts.Count -1 do
+ Result.Fonts.Add(TMFont(Self.Fonts.Items[i]).Copy());
+end;
+
+function TMFonts.Count: integer;
+begin
+ result := Fonts.Count;
+end;
+
+end.
+
diff --git a/branches/script-component/Units/MMLCore/iomanager.pas b/branches/script-component/Units/MMLCore/iomanager.pas
new file mode 100644
index 0000000..e6ca520
--- /dev/null
+++ b/branches/script-component/Units/MMLCore/iomanager.pas
@@ -0,0 +1,644 @@
+{
+ This file is part of the Mufasa Macro Library (MML)
+ Copyright (c) 2009 by Raymond van Venetië and Merlijn Wajer
+
+ MML is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ MML is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with MML. If not, see .
+
+ See the file COPYING, included in this distribution,
+ for details about the copyright.
+
+ Input/Output manager for Mufasa Macro Library
+}
+
+{$mode objfpc}{$H+}
+unit IOManager;
+
+interface
+
+ uses
+ Classes, SysUtils, mufasatypes, graphics, LCLType, bitmaps, LCLIntf, libloader, dynlibs;
+
+ type
+
+ { This is the base class for the target functionality. If it provides a target, it extends this.
+ | Some methods in heregratuitous provide default functionality as a convinence. Only override as nessessary }
+ TTarget = class(TObject)
+ public
+
+ { ONLY override some of the following methods if the target provides image functions, defaults
+ | to raise exceptions. GetColor provides default functionality using ReturData of width 1.
+ | FreeReturnData provides default of doing nothing. }
+ procedure GetTargetDimensions(var w, h: integer); virtual;
+ function GetColor(x,y : integer) : TColor; virtual;
+ function ReturnData(xs, ys, width, height: Integer): TRetData; virtual;
+ procedure FreeReturnData; virtual;
+ procedure ActivateClient; virtual;
+ function TargetValid: boolean; virtual;
+
+ { ONLY override the following methods if the target provides mouse functions, defaults to
+ | raise exceptions }
+ procedure GetMousePosition(var x,y: integer); virtual;
+ procedure MoveMouse(x,y: integer); virtual;
+ procedure HoldMouse(x,y: integer; button: TClickType); virtual;
+ procedure ReleaseMouse(x,y: integer; button: TClickType); virtual;
+
+ { ONLY override the following methods if the target provides key functions, defaults to
+ | raise exceptions }
+ procedure SendString(str: string); virtual;
+ procedure HoldKey(key: integer); virtual;
+ procedure ReleaseKey(key: integer); virtual;
+ function IsKeyHeld(key: integer): boolean; virtual;
+ end;
+
+ { Implements a target that is a raw pixel array, e.g. stuff from a bitmap or a frozen state.
+ | Currently this uses the pointer as-is, but it might be needed to make a local copy... }
+ TRawTarget = class(TTarget)
+ public
+ constructor Create(rgb: prgb32; w,h: integer; CopyData : boolean = false);
+ destructor Destroy; override;
+
+ procedure GetTargetDimensions(var w, h: integer); override;
+ function ReturnData(xs, ys, width, height: Integer): TRetData; override;
+
+ private
+ rgb: prgb32;
+ freedata : boolean;
+ w,h: integer;
+ end;
+
+ { Implements a target that is a Window in the operating system. This class is abstract, i.e.,
+ | the actual os-specific Implementation of TWindow is in one of the os units. }
+ TWindow_Abstract = class(TTarget)
+ public
+ procedure GetTargetDimensions(var w, h: integer); override; abstract;
+ function ReturnData(xs, ys, width, height: Integer): TRetData; override; abstract;
+
+ function TargetValid: boolean; override; abstract;
+ procedure ActivateClient; override; abstract;
+ procedure GetMousePosition(var x,y: integer); override; abstract;
+ procedure MoveMouse(x,y: integer); override; abstract;
+ procedure HoldMouse(x,y: integer; button: TClickType); override; abstract;
+ procedure ReleaseMouse(x,y: integer; button: TClickType); override; abstract;
+
+ procedure SendString(str: string); override; abstract;
+ procedure HoldKey(key: integer); override; abstract;
+ procedure ReleaseKey(key: integer); override; abstract;
+ function IsKeyHeld(key: integer): boolean; override; abstract;
+ end;
+
+ { Contains the pointers to a non-internal target implementation using the EIOS specification.
+ | N.B. this *is* the specification that I will finalize the speficication as... Once this is
+ | finalized that is. Trust me, its >9000 times easier to use a buffer across the language
+ | barrier. And the internal target implementation of EIOS will make that verry efficient. }
+ TEIOS_Client = record
+ RequestTarget: function(initdata: pointer): pointer; stdcall;
+ ReleaseTarget: procedure(target: pointer); stdcall;
+
+ GetTargetDimensions: procedure(target: pointer; var w, h: integer); stdcall;
+ GetImageBuffer: function(target: pointer): prgb32; stdcall;
+ UpdateImageBuffer: procedure(target: pointer); stdcall;
+ UpdateImageBufferBounds: procedure(target: pointer; sx,sy,ex,ey: integer); stdcall;
+
+ GetMousePosition: procedure(target: pointer; var x,y: integer); stdcall;
+ MoveMouse: procedure(target: pointer; x,y: integer); stdcall;
+ HoldMouse: procedure(target: pointer; x,y: integer; left: boolean); stdcall;
+ ReleaseMouse: procedure(target: pointer; x,y: integer; left: boolean); stdcall;
+
+ SendString: procedure(target: pointer; str: PChar); stdcall;
+ HoldKey: procedure(target: pointer; key: integer); stdcall;
+ ReleaseKey: procedure(target: pointer; key: integer); stdcall;
+ IsKeyHeld: function(target: pointer; key: integer): boolean; stdcall;
+ end;
+
+ { Implements a EIOS target. This is, for all intensive purposes, a TRawTarget with added
+ | key and mouse methods, as well as the capability to request a buffer update. N.B. that
+ | some EIOS implementors can and will update the buffer on their own. In that case, the
+ | UpdateImageBuffer call is just a call to an empty method, OR does not exist. In the case
+ | of an EIOS client not needing a method defined, it will not be exported and will be set
+ | to NIL here. I think. Will get back to that. }
+ TEIOS_Target = class(TTarget)
+ public
+ constructor Create(client: TEIOS_Client; initval: pointer);
+ destructor Destroy; override;
+
+ procedure GetTargetDimensions(var w, h: integer); override;
+ function ReturnData(xs, ys, width, height: Integer): TRetData; override;
+
+ procedure GetMousePosition(var x,y: integer); override;
+ procedure MoveMouse(x,y: integer); override;
+ procedure HoldMouse(x,y: integer; button: TClickType); override;
+ procedure ReleaseMouse(x,y: integer; button: TClickType); override;
+
+ procedure SendString(str: string); override;
+ procedure HoldKey(key: integer); override;
+ procedure ReleaseKey(key: integer); override;
+ function IsKeyHeld(key: integer): boolean; override;
+
+ private
+ client: TEIOS_Client;
+ target: pointer;
+ buffer: prgb32;
+ width,height: integer;
+ end;
+
+ { EIOS Clients will give an exported name, have a loaded library associated, and have
+ | a TEIOS_Client with the method pointers set. }
+ type TEIOS_LoadedPlugin = record
+ name: string;
+ client: TEIOS_Client;
+ end;
+
+ { This is just a class that loads EIOS clients (like SMART) and sets them up to be used
+ | as targets. I hope to have a method like...
+ | function SetTarget(eios_name: pchar; init_args: variant): integer;
+ | where the init_args variant will be implied to be anything that can be cast to a pointer
+ | in the binary side after it gets out of PascalScript. So, the only thing to setup SMART
+ | would be the single call....
+ | SetTarget('SMART',SmartSetupRecord);
+ | Sexy, right? ;}
+ TEIOS_Controller = class(TGenericLoader)
+ public
+ constructor Create();
+ destructor Destroy; override;
+
+ function ClientExists(name: string): boolean;
+ function GetClient(name: string): TEIOS_Client;
+
+ protected
+ function InitPlugin(plugin: TLibHandle): boolean; override;
+ private
+ plugs: array of TEIOS_LoadedPlugin;
+ function FindClient(name:string): integer;
+ end;
+
+ { This class specifies the object that will go in the ThreadVar to give the script access
+ | to targets. This class is abstract, i.e., the actual os-specific Implementation of
+ | TIOManager is in one of the os units.
+ | I assume you Simba people know what the methods you made do, and I'm mantaining
+ | Name -> Function compatibility from the TWindow and TMInput classes (e.g. key, image,
+ | and window functions). I decided to split targeting into input/output == image/keymouse,
+ | since they sometimes are treated as seperate entities. }
+ TIOManager_Abstract = class(TObject)
+ public
+ constructor Create;
+ constructor Create(plugin_dir: string);
+ destructor Destroy; override;
+
+ procedure SetDesktop; virtual; abstract;
+ function SetTarget(ArrPtr: PRGB32; Size: TPoint): integer; overload;
+ function SetTarget(bmp : TMufasaBitmap) : integer; overload;
+ function SetTarget(name: string; initargs: pointer): integer; overload;
+ function TargetValid: Boolean;
+
+ function GetColor(x,y : integer) : TColor;
+ function ReturnData(xs, ys, width, height: Integer): TRetData;
+ procedure FreeReturnData;
+
+ procedure GetDimensions(var W, H: Integer);
+ procedure ActivateClient;
+
+ function IsFrozen: boolean;
+ procedure SetFrozen(makefrozen: boolean);
+
+ procedure GetMousePos(var X, Y: Integer);
+ procedure SetMousePos(X, Y: Integer);
+ procedure HoldMouse(x,y : integer; button: TClickType);
+ procedure ReleaseMouse(x,y : integer; button: TClickType);
+ procedure ClickMouse(X, Y: Integer; button: TClickType);
+
+ procedure KeyUp(key: Word);
+ procedure KeyDown(key: Word);
+ procedure PressKey(key: Word);
+ procedure SendText(text: string);
+ function isKeyDown(key: Word): Boolean;
+
+ protected
+ keymouse: TTarget;
+ image: TTarget;
+ frozen: TTarget;
+ freezebuffer: prgb32;
+ bothsame: boolean;
+
+ procedure SetImageTarget(target: TTarget);
+ procedure SetKeyMouseTarget(target: TTarget);
+ procedure SetBothTargets(target: TTarget);
+ procedure NativeInit; virtual; abstract;
+ procedure NativeFree; virtual; abstract;
+ end;
+
+implementation
+
+ uses FileUtil,
+ {$IFDEF MSWINDOWS} os_windows {$ENDIF}
+ {$IFDEF LINUX} os_linux {$ENDIF};
+
+ var eios_controller: TEIOS_Controller;
+
+//***implementation*** TIOManager
+
+constructor TIOManager_Abstract.Create(plugin_dir: string);
+begin
+ inherited Create;
+ eios_controller.AddAndLoadPath(plugin_dir);
+ keymouse:= nil;
+ image:= nil;
+ frozen:= nil;
+ NativeInit;
+ SetDesktop;
+{
+ self.create;
+ eios_controller.AddAndLoadPath(plugin_dir);
+}
+end;
+
+constructor TIOManager_Abstract.Create;
+begin
+ inherited Create;
+ keymouse:= nil;
+ image:= nil;
+ frozen:= nil;
+ NativeInit;
+ SetDesktop;
+end;
+
+destructor TIOManager_Abstract.Destroy;
+begin
+ if bothsame then keymouse.Destroy() else
+ begin
+ keymouse.Free();
+ image.Free();
+ end;
+ if IsFrozen then frozen.Destroy();
+end;
+
+procedure TIOManager_Abstract.SetImageTarget(target: TTarget);
+begin
+ if IsFrozen then
+ raise Exception.Create('You cannot set a target when Frozen');
+ if not(bothsame) then image.Free();
+ image:= target;
+ bothsame:= false;
+end;
+procedure TIOManager_Abstract.SetKeyMouseTarget(target: TTarget);
+begin
+ if not(bothsame) then keymouse.Free();
+ keymouse:= target;
+ bothsame:= false;
+end;
+procedure TIOManager_Abstract.SetBothTargets(target: TTarget);
+begin
+ if IsFrozen then
+ raise Exception.Create('You cannot set a target when Frozen');
+ if bothsame then image.Destroy() else
+ begin
+ image.Free();
+ keymouse.Free();
+ end;
+ image:= target;
+ keymouse:= target;
+ bothsame:= true;
+end;
+
+procedure TIOManager_Abstract.SetFrozen(makefrozen: boolean);
+var
+ w,h: integer;
+ buffer: TRetData;
+begin
+ if (makefrozen) and (IsFrozen) then
+ raise Exception.Create('The window is already frozen.');
+ //BenLand100 edit: I say we leave this exception out. POLS
+ //if not(isfrozen) and (frozen = nil) then
+ // raise Exception.Create('The window is not frozen.');
+ if makefrozen then //No need for the Frozen = nil check, already done above with the exception.
+ begin
+ frozen:= image;
+ frozen.GetTargetDimensions(w,h);
+ buffer:= frozen.ReturnData(0,0,w,h);
+ image:= TRawTarget.Create(buffer.Ptr,w,h,true);
+ frozen.FreeReturnData;
+ end else
+ begin
+ image.Free();
+ image:= frozen;
+ frozen:= nil;
+ end;
+end;
+
+function TIOManager_Abstract.IsFrozen: boolean;
+begin
+ result:= frozen <> nil;
+end;
+
+function TIOManager_Abstract.GetColor(x,y : integer) : TColor; begin result:= image.GetColor(x,y); end;
+function TIOManager_Abstract.ReturnData(xs,ys,width,height: integer): TRetData; begin result:= image.ReturnData(xs,ys,width,height); end;
+procedure TIOManager_Abstract.FreeReturnData; begin image.freeReturnData(); end;
+
+function TIOManager_Abstract.SetTarget(ArrPtr: PRGB32; Size: TPoint): integer; begin SetImageTarget(TRawTarget.Create(ArrPtr,Size.X,Size.Y)); end;
+function TIOManager_Abstract.SetTarget(bmp : TMufasaBitmap) : integer; begin SetImageTarget(TRawTarget.Create(bmp.FData,bmp.width,bmp.height)); end;
+function TIOManager_Abstract.SetTarget(name: string; initargs: pointer): integer;
+var
+ client: TEIOS_Client;
+begin
+ if not eios_controller.ClientExists(name) then raise Exception.Create('EIOS Client by specified name does not exist');
+ client:= eios_controller.GetClient(name);
+ SetBothTargets(TEIOS_Target.Create(client, initargs));
+end;
+
+function TIOManager_Abstract.TargetValid: Boolean;
+begin
+ result:= false;
+ if (keymouse <> nil) and (image <> nil) then
+ result := (keymouse.TargetValid and image.TargetValid);
+end;
+
+procedure TIOManager_Abstract.GetDimensions(var W, H: Integer); begin image.GetTargetDimensions(w,h) end;
+procedure TIOManager_Abstract.ActivateClient;
+begin
+ keymouse.ActivateClient();
+ {not sure if image needs activation or not, if its a native window keymouse == image so it should be good.}
+end;
+
+procedure TIOManager_Abstract.GetMousePos(var X, Y: Integer); begin keymouse.GetMousePosition(x,y) end;
+procedure TIOManager_Abstract.SetMousePos(X, Y: Integer); begin keymouse.MoveMouse(x,y); end;
+procedure TIOManager_Abstract.HoldMouse(x,y : integer; button: TClickType); begin keymouse.ReleaseMouse(x,y,button); end;
+procedure TIOManager_Abstract.ReleaseMouse(x,y : integer; button: TClickType); begin keymouse.ReleaseMouse(x,y,button); end;
+procedure TIOManager_Abstract.ClickMouse(X, Y: Integer; button: TClickType);
+begin
+ HoldMouse(x,y,button);
+ //BenLand100 note: probably should wait here
+ ReleaseMouse(x,y,button);
+end;
+
+procedure TIOManager_Abstract.KeyUp(key: Word); begin keymouse.ReleaseKey(key) end;
+procedure TIOManager_Abstract.KeyDown(key: Word); begin keymouse.HoldKey(key) end;
+procedure TIOManager_Abstract.PressKey(key: Word); begin keyup(key); keydown(key); end;
+procedure TIOManager_Abstract.SendText(text: string); begin keymouse.SendString(text); end;
+function TIOManager_Abstract.isKeyDown(key: Word): Boolean; begin result:= keymouse.IsKeyHeld(key); end;
+
+//***implementation*** TTarget
+
+procedure TTarget.GetTargetDimensions(var w, h: integer); begin raise Exception.Create('GetTargetDimensions not avaliable for this target'); end;
+function TTarget.GetColor(x,y : integer) : TColor;
+begin
+ with ReturnData(x,y,1,1) do
+ Result := RGBToColor(Ptr[0].r,Ptr[0].g,Ptr[0].b);
+ FreeReturnData;
+end;
+function TTarget.ReturnData(xs, ys, width, height: Integer): TRetData; begin raise Exception.Create('ReturnData not avaliable for this target'); end;
+procedure TTarget.FreeReturnData; begin {do nothing by default} end;
+procedure TTarget.ActivateClient; begin raise Exception.Create('ActivateClient not avaliable for this target'); end;
+function TTarget.TargetValid: boolean; begin result:= true; end;
+
+procedure TTarget.GetMousePosition(var x,y: integer); begin raise Exception.Create('GetMousePosition not avaliable for this target'); end;
+procedure TTarget.MoveMouse(x,y: integer); begin raise Exception.Create('MoveMouse not avaliable for this target'); end;
+procedure TTarget.HoldMouse(x,y: integer; button: TClickType); begin raise Exception.Create('HoldMouse not avaliable for this target'); end;
+procedure TTarget.ReleaseMouse(x,y: integer; button: TClickType); begin raise Exception.Create('ReleaseMouse not avaliable for this target'); end;
+
+procedure TTarget.SendString(str: string); begin raise Exception.Create('SendString not avaliable for this target'); end;
+procedure TTarget.HoldKey(key: integer); begin raise Exception.Create('HoldKey not avaliable for this target'); end;
+procedure TTarget.ReleaseKey(key: integer); begin raise Exception.Create('ReleaseKey not avaliable for this target'); end;
+function TTarget.IsKeyHeld(key: integer): boolean; begin raise Exception.Create('IsKeyHeld not avaliable for this target'); end;
+
+//***implementation*** TEIOS_Target
+
+constructor TEIOS_Target.Create(client: TEIOS_Client; initval: pointer); begin
+ inherited Create;
+ self.client:= client;
+ if Pointer(client.RequestTarget) <> nil then
+ self.target:= client.RequestTarget(initval);
+ if Pointer(client.GetImageBuffer) <> nil then
+ self.buffer:= client.GetImageBuffer(target)
+ else
+ self.buffer:= nil;
+ GetTargetDimensions(self.width,self.height);
+end;
+
+destructor TEIOS_Target.Destroy; begin
+ client.ReleaseTarget(self.target);
+ inherited Destroy;
+end;
+
+procedure TEIOS_Target.GetTargetDimensions(var w, h: integer);
+begin
+ if Pointer(client.GetTargetDimensions) <> nil then
+ client.GetTargetDimensions(target,w,h)
+ else
+ inherited GetTargetDimensions(w,h);
+end;
+function TEIOS_Target.ReturnData(xs, ys, width, height: Integer): TRetData;
+begin
+ if Pointer(client.UpdateImageBufferBounds) <> nil then
+ client.UpdateImageBufferBounds(target,xs,ys,xs+width,ys+height)
+ else if Pointer(client.UpdateImageBuffer) <> nil then
+ client.UpdateImageBuffer(target)
+ else begin
+ {no update command exported}
+ end;
+ result.Ptr := buffer;
+ result.RowLen:= self.width;
+ result.IncPtrWith:= result.RowLen - width;
+ Inc(result.Ptr, ys * result.RowLen + xs);
+end;
+
+procedure TEIOS_Target.GetMousePosition(var x,y: integer);
+begin
+ if Pointer(client.GetMousePosition) <> nil then
+ client.GetMousePosition(target,x,y)
+ else
+ inherited GetMousePosition(x,y);
+end;
+procedure TEIOS_Target.MoveMouse(x,y: integer);
+begin
+ if Pointer(client.MoveMouse) <> nil then
+ client.MoveMouse(target,x,y)
+ else
+ inherited MoveMouse(x,y);
+end;
+procedure TEIOS_Target.HoldMouse(x,y: integer; button: TClickType);
+begin
+ if Pointer(client.HoldMouse) <> nil then
+ begin
+ case button of
+ mouse_Left: client.HoldMouse(target,x,y,true);
+ mouse_Middle: raise Exception.Create('EIOS does not implement the middle mouse button.');
+ mouse_Right: client.HoldMouse(target,x,y,false);
+ end;
+ end else
+ inherited HoldMouse(x,y,button);
+end;
+procedure TEIOS_Target.ReleaseMouse(x,y: integer; button: TClickType);
+begin
+ if Pointer(client.ReleaseMouse) <> nil then
+ begin
+ case button of
+ mouse_Left: client.ReleaseMouse(target,x,y,true);
+ mouse_Middle: raise Exception.Create('EIOS does not implement the middle mouse button.');
+ mouse_Right: client.ReleaseMouse(target,x,y,false);
+ end;
+ end else
+ inherited ReleaseMouse(x,y,button);
+end;
+
+procedure TEIOS_Target.SendString(str: string);
+begin
+ if Pointer(client.SendString) <> nil then
+ client.SendString(target,PChar(str))
+ else
+ inherited SendString(str);
+end;
+procedure TEIOS_Target.HoldKey(key: integer);
+begin
+ if Pointer(client.HoldKey) <> nil then
+ client.HoldKey(target,key)
+ else
+ inherited HoldKey(key);
+end;
+procedure TEIOS_Target.ReleaseKey(key: integer);
+begin
+ if Pointer(client.ReleaseKey) <> nil then
+ client.ReleaseKey(target,key)
+ else
+ inherited ReleaseKey(key);
+end;
+function TEIOS_Target.IsKeyHeld(key: integer): boolean;
+begin
+ if Pointer(client.IsKeyHeld) <> nil then
+ result:= client.IsKeyHeld(target,key)
+ else
+ result:= inherited IsKeyHeld(key);
+end;
+
+//***implementation*** TRawTarget
+
+constructor TRawTarget.Create(rgb: prgb32; w,h: integer; CopyData : boolean = false);
+begin
+ inherited Create;
+ self.w:= w;
+ self.h:= h;
+ self.freedata:= copydata;
+ if CopyData then
+ begin
+ GetMem(self.rgb,w*h*sizeof(TRGB32));
+ Move(rgb[0],self.rgb[0],w*h*sizeof(TRGB32));
+ end else
+ self.rgb:= rgb;
+end;
+
+destructor TRawTarget.Destroy;
+begin
+ if freedata then
+ Freemem(self.rgb,w*h*sizeof(TRGB32));
+ inherited Destroy;
+end;
+
+procedure TRawTarget.GetTargetDimensions(var w, h: integer);
+begin
+ w:= self.w;
+ h:= self.h;
+end;
+
+function TRawTarget.ReturnData(xs, ys, width, height: Integer): TRetData;
+begin
+ result.Ptr := rgb;
+ result.RowLen:= self.w;
+ result.IncPtrWith:= result.RowLen - width;
+ Inc(result.Ptr, ys * result.RowLen + xs);
+end;
+
+//***implementation*** TEIOS_Controller
+
+constructor TEIOS_Controller.Create();
+begin
+ inherited Create;
+end;
+
+destructor TEIOS_Controller.Destroy;
+var
+ i: integer;
+begin
+ SetLength(plugs,0);
+ inherited Destroy;
+end;
+
+function TEIOS_Controller.InitPlugin(plugin: TLibHandle): boolean;
+var
+ GetName: procedure(name: pchar); stdcall;
+ buffer: pchar;
+ idx: integer;
+begin
+ Pointer(GetName) := GetProcAddress(plugin, PChar('EIOS_GetName'));
+ if Pointer(GetName) = nil then begin result:= false; exit; end;
+ idx:= Length(plugs);
+ SetLength(plugs,idx+1);
+ buffer:= stralloc(255);
+ GetName(buffer);
+ plugs[idx].name:= buffer;
+ strdispose(buffer);
+ {link in all eios methods that *might* exist}
+ with plugs[idx].client do
+ begin
+ Pointer(RequestTarget):= GetProcAddress(plugin, PChar('EIOS_RequestTarget'));
+ Pointer(ReleaseTarget):= GetProcAddress(plugin, PChar('EIOS_ReleaseTarget'));
+
+ Pointer(GetTargetDimensions):= GetProcAddress(plugin, PChar('EIOS_GetTargetDimensions'));
+ Pointer(GetImageBuffer):= GetProcAddress(plugin, PChar('EIOS_GetImageBuffer'));
+ Pointer(UpdateImageBuffer):= GetProcAddress(plugin, PChar('EIOS_UpdateImageBuffer'));
+ Pointer(UpdateImageBufferBounds):= GetProcAddress(plugin, PChar('EIOS_UpdateImageBufferBounds'));
+
+ Pointer(GetMousePosition):= GetProcAddress(plugin, PChar('EIOS_GetMousePosition'));
+ Pointer(MoveMouse):= GetProcAddress(plugin, PChar('EIOS_MoveMouse'));
+ Pointer(HoldMouse):= GetProcAddress(plugin, PChar('EIOS_HoldMouse'));
+ Pointer(ReleaseMouse):= GetProcAddress(plugin, PChar('EIOS_ReleaseMouse'));
+
+ Pointer(SendString):= GetProcAddress(plugin, PChar('EIOS_SendString'));
+ Pointer(HoldKey):= GetProcAddress(plugin, PChar('EIOS_HoldKey'));
+ Pointer(ReleaseKey):= GetProcAddress(plugin, PChar('EIOS_ReleaseKey'));
+ Pointer(IsKeyHeld):= GetProcAddress(plugin, PChar('EIOS_IsKeyHeld'));
+ end;
+ {done linking in methods}
+ result:= true;
+end;
+
+function TEIOS_Controller.FindClient(name: string): integer;
+var
+ i: integer;
+begin
+ for i:= 0 to length(plugs) - 1 do
+ if plugs[i].name = name then
+ begin
+ result:= i;
+ exit;
+ end;
+ result:= -1;
+end;
+
+function TEIOS_Controller.ClientExists(name: string): boolean;
+begin
+ result:= FindClient(name) >= 0;
+end;
+
+function TEIOS_Controller.GetClient(name: string): TEIOS_Client;
+var
+ i: integer;
+begin
+ i:= FindClient(name);
+ if i >= 0 then
+ result:= plugs[i].client
+end;
+
+initialization
+ eios_controller:= TEIOS_Controller.Create;
+finalization
+ eios_controller.Free;
+end.
diff --git a/branches/script-component/Units/MMLCore/libloader.pas b/branches/script-component/Units/MMLCore/libloader.pas
new file mode 100644
index 0000000..0867139
--- /dev/null
+++ b/branches/script-component/Units/MMLCore/libloader.pas
@@ -0,0 +1,162 @@
+unit libloader;
+
+{$mode objfpc}
+
+interface
+
+ uses
+ Classes, SysUtils, dynlibs;
+ type
+ TGenericLib = record
+ filename: string;
+ handle: TLibHandle;
+ end;
+ TGenericLibArray = array of TGenericLib;
+
+ TGenericLoader = class(TObject)
+ private
+ PluginLen : integer;
+ Loaded: TGenericLibArray;
+ PluginDirs : TStringList;
+ procedure FreePlugins;
+ procedure LoadPluginsDir(DirIndex : integer);
+ protected
+ function InitPlugin(plugin: TLibHandle): boolean; virtual; abstract;
+ public
+ constructor Create;
+ destructor Destroy; override;
+ procedure ValidateDirs;
+ procedure AddAndLoadPath(path: string);
+ function LoadPlugin(PluginName : string) : integer;
+ end;
+
+implementation
+
+ uses
+ MufasaTypes,FileUtil;
+
+ procedure TGenericLoader.AddAndLoadPath(path: string);
+ var
+ idx: integer;
+ begin
+ if PluginDirs.Find(path,idx) then
+ LoadPluginsDir(idx)
+ else begin
+ writeln('Loading Path: ' + path);
+ PluginDirs.Add(path);
+ LoadPluginsDir(PluginDirs.Count-1);
+ end;
+ end;
+
+ procedure TGenericLoader.FreePlugins;
+ var
+ I : integer;
+ begin
+ for i := 0 to PluginLen - 1 do
+ begin;
+ if (Loaded[i].handle > 0) then
+ try
+ Writeln(inttostr(I));
+ FreeLibrary(Loaded[i].handle);
+ except
+ end;
+ end;
+ SetLength(Loaded,0);
+ PluginLen:= 0;
+ end;
+
+ procedure TGenericLoader.ValidateDirs;
+ var
+ i : integer;
+ TempStr : string;
+ begin
+ for i := 0 to PluginDirs.Count - 1 do
+ begin;
+ if DirectoryExists(PluginDirs.Strings[i]) = false then
+ raise Exception.createFMT('Directory(%s) does not exist',[PluginDirs[i]]);
+ TempStr := PluginDirs.Strings[i];
+ if (TempStr[Length(TempStr)] <> DS) then
+ begin;
+ if (TempStr[Length(TempStr)] = '\') or (TempStr[Length(TempStr)] = '/') then
+ TempStr[Length(TempStr)] := DS
+ else
+ TempStr := TempStr + DS;
+ PluginDirs.Strings[i] := TempStr;
+ end;
+ end;
+ end;
+
+ procedure TGenericLoader.LoadPluginsDir(DirIndex: integer);
+ var
+ PlugExt: String = {$IFDEF LINUX}'*.so';{$ELSE}'*.dll';{$ENDIF}
+ FileSearcher : TSearchRec;
+ begin
+ if (DirIndex < 0) or (DirIndex >= PluginDirs.Count) then
+ Exit;
+ if FindFirst(PluginDirs.Strings[DirIndex] + PlugExt, faAnyFile, FileSearcher) <> 0 then
+ begin;
+ FindClose(FileSearcher);
+ Exit;
+ end;
+ repeat
+ LoadPlugin(FileSearcher.Name);
+ until FindNext(FileSearcher) <> 0;
+ FindClose(FileSearcher);
+ end;
+
+
+ function TGenericLoader.LoadPlugin(PluginName: string): Integer;
+ var
+ i, ii : integer;
+ Status : LongInt;
+ PlugExt: String = {$IFDEF LINUX}'.so';{$ELSE}'.dll';{$ENDIF}
+ begin
+ ii := -1;
+ result := -1;
+ if PluginDirs.Count = 0 then
+ Exit;
+ ValidateDirs;
+ PluginName := ExtractFileNameWithoutExt(PluginName);
+ for i := 0 to PluginDirs.Count - 1 do
+ if FileExists(PluginDirs.Strings[i] + Pluginname + PlugExt) then
+ begin;
+ if ii <> -1 then
+ Raise Exception.CreateFmt('Plugin(%s) has been found multiple times',[PluginName]);
+ ii := i;
+ end;
+ if ii = -1 then
+ raise Exception.CreateFMT('Plugins(%s) has not been found',[PluginName]);
+ for i := 0 to PluginLen - 1 do
+ if Loaded[i].filename = (PluginDirs.Strings[ii] + PluginName + PlugExt) then
+ Exit(i);
+ SetLength(Loaded,PluginLen + 1);
+ Writeln(Format('Loading plugin %s at %s',[PluginName,PluginDirs.Strings[ii]]));
+ Loaded[PluginLen].filename:= PluginDirs.Strings[ii] + Pluginname + PlugExt;
+ Loaded[PluginLen].handle:= LoadLibrary(Loaded[PluginLen].filename);
+ if Loaded[PluginLen].handle = 0 then
+ Raise Exception.CreateFMT('Error loading plugin %s',[Loaded[PluginLen].filename]);
+ if InitPlugin(Loaded[PluginLen].handle) then
+ inc(PluginLen)
+ else
+ FreeLibrary(Loaded[PluginLen].handle);
+ Result := PluginLen;
+ end;
+
+
+ constructor TGenericLoader.Create;
+ begin
+ inherited Create;
+ PluginLen := 0;
+ PluginDirs := TStringList.Create;
+ PluginDirs.CaseSensitive:= {$IFDEF LINUX}true{$ELSE}false{$ENDIF};
+ end;
+
+ destructor TGenericLoader.Destroy;
+ begin
+ FreePlugins;
+ PluginDirs.Free;
+ inherited Destroy;
+ end;
+
+end.
+
diff --git a/branches/script-component/Units/MMLCore/mmath.pas b/branches/script-component/Units/MMLCore/mmath.pas
new file mode 100644
index 0000000..941eea5
--- /dev/null
+++ b/branches/script-component/Units/MMLCore/mmath.pas
@@ -0,0 +1,71 @@
+{
+ This file is part of the Mufasa Macro Library (MML)
+ Copyright (c) 2009 by Raymond van Venetië and Merlijn Wajer
+
+ MML is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ MML is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with MML. If not, see .
+
+ See the file COPYING, included in this distribution,
+ for details about the copyright.
+
+ Mufasa Math Unit for the Mufasa Macro Library
+}
+
+unit mmath;
+// mufasa math
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+ Classes, SysUtils,MufasaTypes;
+
+function RotatePoints(P: TPointArray; A, cx, cy: Extended): TPointArray;
+function RotatePoint(p: TPoint; angle, mx, my: Extended): TPoint;
+
+
+implementation
+
+{/\
+ Rotates the given points (P) by A (in radians) around the point defined by cx, cy.
+/\}
+
+function RotatePoints(P: TPointArray; A, cx, cy: Extended): TPointArray;
+
+var
+ I, L: Integer;
+
+begin
+ L := High(P);
+ SetLength(Result, L + 1);
+ for I := 0 to L do
+ begin
+ Result[I].X := Round(cx + cos(A) * (p[i].x - cx) - sin(A) * (p[i].y - cy));
+ Result[I].Y := Round(cy + sin(A) * (p[i].x - cx) + cos(A) * (p[i].y - cy));
+ end;
+end;
+
+{/\
+ Rotates the given point (p) by A (in radians) around the point defined by cx, cy.
+/\}
+
+function RotatePoint(p: TPoint; angle, mx, my: Extended): TPoint;
+
+begin
+ Result.X := Round(mx + cos(angle) * (p.x - mx) - sin(angle) * (p.y - my));
+ Result.Y := Round(my + sin(angle) * (p.x - mx) + cos(angle) * (p.y- my));
+end;
+
+end.
+
diff --git a/branches/script-component/Units/MMLCore/mufasatypes.pas b/branches/script-component/Units/MMLCore/mufasatypes.pas
new file mode 100644
index 0000000..fc75228
--- /dev/null
+++ b/branches/script-component/Units/MMLCore/mufasatypes.pas
@@ -0,0 +1,331 @@
+{
+ This file is part of the Mufasa Macro Library (MML)
+ Copyright (c) 2009 by Raymond van Venetië and Merlijn Wajer
+
+ MML is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ MML is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with MML. If not, see .
+
+ See the file COPYING, included in this distribution,
+ for details about the copyright.
+
+ Type declarations for the Mufasa Macro Library
+}
+
+unit MufasaTypes;
+
+{$mode objfpc}{$H+}
+
+interface
+
+
+uses
+ Classes, SysUtils;
+const
+ DS = DirectorySeparator;
+ MEOL = {$ifdef MSWINDOWS}#13+{$endif}#10;
+
+{ Overloaded Operators}
+
+{ TPoint add }
+operator + (PT1,PT2 : TPoint) : TPoint;
+
+{ TPoint sub }
+operator - (PT1,PT2 : TPoint) : TPoint;
+
+type
+ TRGB24 = packed record
+ B, G, R : byte;
+ end;
+ PRGB24 = ^TRGB24;
+ TRGB32 = packed record
+ B, G, R, A: Byte;
+ end;
+ PRGB32 = ^TRGB32;
+
+ TRetData = record
+ Ptr : PRGB32;
+ IncPtrWith : integer;
+ RowLen : integer;
+ end;
+ TBmpMirrorStyle = (MirrorWidth,MirrorHeight,MirrorLine); //LineMirror is in line x=y;
+ TTargetWindowMode = (w_BMP, w_Window, w_HDC, w_ArrayPtr, w_XWindow);
+ TClickType = (mouse_Left, mouse_Right, mouse_Middle);
+ TMousePress = (mouse_Down, mouse_Up);
+
+ TStringArray = array of String;
+ TPointArray = array of TPoint;
+ T2DPointArray = array of TPointArray;
+ TVariantArray = Array of Variant;
+ TIntegerArray = Array of Integer;
+ T2DIntArray = array of TIntegerArray;
+ T2DIntegerArray = T2DIntArray;
+ TBoolArray = array of boolean;
+ T2DBoolArray = Array of TBoolArray;
+ TExtendedArray = Array of Extended;
+ T2DExtendedArray = Array of Array of Extended;
+ { Mask Types }
+ TMask = record
+ White, Black : TPointArray;
+ WhiteHi,BlackHi : integer;
+ W,H : integer;
+ end;
+
+ { DTM Types }
+ {
+ Possibly add .name too?
+ Then one could give DTM names, which would be easy for debugging.
+ }
+ TBox = record
+ x1, y1, x2, y2: Integer;
+ end;
+
+ { TODO: add cts per colour/tolerance? }
+
+ // TODO DTM-Not points. Not very hard really.
+
+ { not points -
+ add seperate tpa or boolean array for every point that is to be matched ?
+ }
+
+ pDTM = record
+ l: Integer;
+ p: TPointArray;
+ c, t, asz, ash: TIntegerArray;
+ bp: Array Of Boolean;
+ n: String; // DOEN
+ end;
+
+ { Other DTM Types }
+
+ TDTMPointDef = record
+ x, y, Color, Tolerance, AreaSize, AreaShape: integer;
+ end;
+
+ TDTMPointDefArray = Array Of TDTMPointDef;
+
+ TDTM = record
+ MainPoint: TDTMPointDef;
+ SubPoints: TDTMPointDefArray;
+ end;
+
+type
+ VirtualKeyInfo = record
+ Str : string;
+ Key : byte;
+ end;
+type
+ TBufferByteArray = Array[0..524287] of Byte;
+ PBufferByteArray = ^TBufferByteArray;
+
+var
+ BufferString : PChar;
+ BufferLen : LongWord;
+ VirtualKeys : array[0..173] of VirtualKeyInfo = (
+ (str :'UNKNOWN'; key : 0),
+ (str :'LBUTTON'; key : 1),
+ (str :'RBUTTON'; key : 2),
+ (str :'CANCEL'; key : 3),
+ (str :'MBUTTON'; key : 4),
+ (str :'XBUTTON1'; key : 5),
+ (str :'XBUTTON2'; key : 6),
+ (str :'BACK'; key : 8),
+ (str :'TAB'; key : 9),
+ (str :'CLEAR'; key : 12),
+ (str :'RETURN'; key : 13),
+ (str :'SHIFT'; key : 16),
+ (str :'CONTROL'; key : 17),
+ (str :'MENU'; key : 18),
+ (str :'PAUSE'; key : 19),
+ (str :'CAPITAL'; key : 20),
+ (str :'KANA'; key : 21),
+ (str :'HANGUL'; key : 21),
+ (str :'JUNJA'; key : 23),
+ (str :'FINAL'; key : 24),
+ (str :'HANJA'; key : 25),
+ (str :'KANJI'; key : 25),
+ (str :'ESCAPE'; key : 27),
+ (str :'CONVERT'; key : 28),
+ (str :'NONCONVERT'; key : 29),
+ (str :'ACCEPT'; key : 30),
+ (str :'MODECHANGE'; key : 31),
+ (str :'SPACE'; key : 32),
+ (str :'PRIOR'; key : 33),
+ (str :'NEXT'; key : 34),
+ (str :'END'; key : 35),
+ (str :'HOME'; key : 36),
+ (str :'LEFT'; key : 37),
+ (str :'UP'; key : 38),
+ (str :'RIGHT'; key : 39),
+ (str :'DOWN'; key : 40),
+ (str :'SELECT'; key : 41),
+ (str :'PRINT'; key : 42),
+ (str :'EXECUTE'; key : 43),
+ (str :'SNAPSHOT'; key : 44),
+ (str :'INSERT'; key : 45),
+ (str :'DELETE'; key : 46),
+ (str :'HELP'; key : 47),
+ (str :'0'; key : $30),
+ (str :'1'; key : $31),
+ (str :'2'; key : $32),
+ (str :'3'; key : $33),
+ (str :'4'; key : $34),
+ (str :'5'; key : $35),
+ (str :'6'; key : $36),
+ (str :'7'; key : $37),
+ (str :'8'; key : $38),
+ (str :'9'; key : $39),
+ (str :'A'; key : $41),
+ (str :'B'; key : $42),
+ (str :'C'; key : $43),
+ (str :'D'; key : $44),
+ (str :'E'; key : $45),
+ (str :'F'; key : $46),
+ (str :'G'; key : $47),
+ (str :'H'; key : $48),
+ (str :'I'; key : $49),
+ (str :'J'; key : $4A),
+ (str :'K'; key : $4B),
+ (str :'L'; key : $4C),
+ (str :'M'; key : $4D),
+ (str :'N'; key : $4E),
+ (str :'O'; key : $4F),
+ (str :'P'; key : $50),
+ (str :'Q'; key : $51),
+ (str :'R'; key : $52),
+ (str :'S'; key : $53),
+ (str :'T'; key : $54),
+ (str :'U'; key : $55),
+ (str :'V'; key : $56),
+ (str :'W'; key : $57),
+ (str :'X'; key : $58),
+ (str :'Y'; key : $59),
+ (str :'Z'; key : $5A),
+ (str :'LWIN'; key : $5B),
+ (str :'RWIN'; key : $5C),
+ (str :'APPS'; key : $5D),
+ (str :'SLEEP'; key : $5F),
+ (str :'NUMPAD0'; key : 96),
+ (str :'NUMPAD1'; key : 97),
+ (str :'NUMPAD2'; key : 98),
+ (str :'NUMPAD3'; key : 99),
+ (str :'NUMPAD4'; key : 100),
+ (str :'NUMPAD5'; key : 101),
+ (str :'NUMPAD6'; key : 102),
+ (str :'NUMPAD7'; key : 103),
+ (str :'NUMPAD8'; key : 104),
+ (str :'NUMPAD9'; key : 105),
+ (str :'MULTIPLY'; key : 106),
+ (str :'ADD'; key : 107),
+ (str :'SEPARATOR'; key : 108),
+ (str :'SUBTRACT'; key : 109),
+ (str :'DECIMAL'; key : 110),
+ (str :'DIVIDE'; key : 111),
+ (str :'F1'; key : 112),
+ (str :'F2'; key : 113),
+ (str :'F3'; key : 114),
+ (str :'F4'; key : 115),
+ (str :'F5'; key : 116),
+ (str :'F6'; key : 117),
+ (str :'F7'; key : 118),
+ (str :'F8'; key : 119),
+ (str :'F9'; key : 120),
+ (str :'F10'; key : 121),
+ (str :'F11'; key : 122),
+ (str :'F12'; key : 123),
+ (str :'F13'; key : 124),
+ (str :'F14'; key : 125),
+ (str :'F15'; key : 126),
+ (str :'F16'; key : 127),
+ (str :'F17'; key : 128),
+ (str :'F18'; key : 129),
+ (str :'F19'; key : 130),
+ (str :'F20'; key : 131),
+ (str :'F21'; key : 132),
+ (str :'F22'; key : 133),
+ (str :'F23'; key : 134),
+ (str :'F24'; key : 135),
+ (str :'NUMLOCK'; key : $90),
+ (str :'SCROLL'; key : $91),
+ (str :'LSHIFT'; key : $A0),
+ (str :'RSHIFT'; key : $A1),
+ (str :'LCONTROL'; key : $A2),
+ (str :'RCONTROL'; key : $A3),
+ (str :'LMENU'; key : $A4),
+ (str :'RMENU'; key : $A5),
+ (str :'BROWSER_BACK'; key : $A6),
+ (str :'BROWSER_FORWARD'; key : $A7),
+ (str :'BROWSER_REFRESH'; key : $A8),
+ (str :'BROWSER_STOP'; key : $A9),
+ (str :'BROWSER_SEARCH'; key : $AA),
+ (str :'BROWSER_FAVORITES'; key : $AB),
+ (str :'BROWSER_HOME'; key : $AC),
+ (str :'VOLUME_MUTE'; key : $AD),
+ (str :'VOLUME_DOWN'; key : $AE),
+ (str :'VOLUME_UP'; key : $AF),
+ (str :'MEDIA_NEXT_TRACK'; key : $B0),
+ (str :'MEDIA_PREV_TRACK'; key : $B1),
+ (str :'MEDIA_STOP'; key : $B2),
+ (str :'MEDIA_PLAY_PAUSE'; key : $B3),
+ (str :'LAUNCH_MAIL'; key : $B4),
+ (str :'LAUNCH_MEDIA_SELECT'; key : $B5),
+ (str :'LAUNCH_APP1'; key : $B6),
+ (str :'LAUNCH_APP2'; key : $B7),
+ (str :'OEM_1'; key : $BA),
+ (str :'OEM_PLUS'; key : $BB),
+ (str :'OEM_COMMA'; key : $BC),
+ (str :'OEM_MINUS'; key : $BD),
+ (str :'OEM_PERIOD'; key : $BE),
+ (str :'OEM_2'; key : $BF),
+ (str :'OEM_3'; key : $C0),
+ (str :'OEM_4'; key : $DB),
+ (str :'OEM_5'; key : $DC),
+ (str :'OEM_6'; key : $DD),
+ (str :'OEM_7'; key : $DE),
+ (str :'OEM_8'; key : $DF),
+ (str :'OEM_102'; key : $E2),
+ (str :'PROCESSKEY'; key : $E7),
+ (str :'ATTN'; key : $F6),
+ (str :'CRSEL'; key : $F7),
+ (str :'EXSEL'; key : $F8),
+ (str :'EREOF'; key : $F9),
+ (str :'PLAY'; key : $FA),
+ (str :'ZOOM'; key : $FB),
+ (str :'NONAME'; key : $FC),
+ (str :'PA1'; key : $FD),
+ (str :'OEM_CLEAR'; key : $FE),
+
+ (str :'HIGHESTVALUE'; key : $FE),
+ (str :'UNDEFINED'; key : $FF)
+ );
+
+
+implementation
+operator+(PT1, PT2: TPoint): TPoint;
+begin
+ Result.x := PT1.x + PT2.x;
+ Result.y := Pt1.y + PT2.y;
+end;
+operator-(PT1, PT2: TPoint): TPoint;
+begin
+ Result.x := PT1.x - PT2.x;
+ Result.y := Pt1.y - PT2.y;
+end;
+
+initialization
+ BufferString := StrAlloc(524288);
+ BufferLen := 524288;
+finalization
+ StrDispose(bufferstring);
+
+end.
+
diff --git a/branches/script-component/Units/MMLCore/mufasatypesutil.pas b/branches/script-component/Units/MMLCore/mufasatypesutil.pas
new file mode 100644
index 0000000..b3c2290
--- /dev/null
+++ b/branches/script-component/Units/MMLCore/mufasatypesutil.pas
@@ -0,0 +1,63 @@
+unit mufasatypesutil;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+ Classes, SysUtils,mufasatypes;
+
+function ConvArr(Arr: array of TPoint): TPointArray; overload;
+function ConvArr(Arr: array of TPointArray): T2DPointArray; overload;
+function ConvArr(Arr: array of Integer): TIntegerArray; overload;
+
+function ConvTPAArr(Arr: array of TPoint): TPointArray; overload;
+
+
+implementation
+
+function ConvArr(Arr: array of TPoint): TPointArray; overload;
+var
+ Len : Integer;
+begin;
+ Len := Length(Arr);
+ SetLength(Result, Len);
+ Move(Arr[Low(Arr)], Result[0], Len*SizeOf(TPoint));
+end;
+
+function ConvTPAArr(Arr: array of TPoint): TPointArray; overload;
+var
+ Len : Integer;
+begin;
+ Len := Length(Arr);
+ SetLength(Result, Len);
+ Move(Arr[Low(Arr)], Result[0], Len*SizeOf(TPoint));
+end;
+
+
+function ConvArr(Arr: array of TPointArray): T2DPointArray; overload;
+var
+ Len,Len2 : Integer;
+ i : integer;
+begin;
+ Len := Length(Arr);
+ SetLength(Result, Len);
+ for i := Len - 1 downto 0 do
+ begin
+ Len2 := Length(Arr[i]);
+ SetLength(result[i],len2);
+ Move(Arr[i][0],Result[i][0],Len2*SizeOf(TPoint));
+ end;
+end;
+
+function ConvArr(Arr: array of Integer): TIntegerArray; overload;
+var
+ Len : Integer;
+begin;
+ Len := Length(Arr);
+ SetLength(Result, Len);
+ Move(Arr[Low(Arr)], Result[0], Len*SizeOf(Integer));
+end;
+
+end.
+
diff --git a/branches/script-component/Units/MMLCore/ocr.pas b/branches/script-component/Units/MMLCore/ocr.pas
new file mode 100644
index 0000000..661a5a5
--- /dev/null
+++ b/branches/script-component/Units/MMLCore/ocr.pas
@@ -0,0 +1,810 @@
+{
+ This file is part of the Mufasa Macro Library (MML)
+ Copyright (c) 2009 by Raymond van Venetië and Merlijn Wajer
+
+ MML is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ MML is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with MML. If not, see .
+
+ See the file COPYING, included in this distribution,
+ for details about the copyright.
+
+ OCR class for the Mufasa Macro Library
+}
+
+unit ocr;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+ Classes, SysUtils, MufasaTypes, bitmaps, math, ocrutil, fontloader,
+ {Begin To-Remove units. Replace ReadBmp with TMufasaBitmap stuff later.}
+ graphtype, intfgraphics,graphics;
+ {End To-Remove unit}
+
+ type
+
+ { TMOCR }
+
+ TMOCR = class(TObject)
+ constructor Create(Owner: TObject);
+ destructor Destroy; override;
+ function InitTOCR(path: string): boolean;
+ function GetFonts:TMFonts;
+ procedure SetFonts(NewFonts: TMFonts);
+
+ function getTextPointsIn(sx, sy, w, h: Integer; shadow: boolean;
+ var _chars, _shadows: T2DPointArray): Boolean;
+ function GetUpTextAtEx(atX, atY: integer; shadow: boolean): string;
+ function GetUpTextAt(atX, atY: integer; shadow: boolean): string;
+
+ procedure FilterUpTextByColour(bmp: TMufasaBitmap; w,h: integer);
+ procedure FilterUpTextByCharacteristics(bmp: TMufasaBitmap; w,h: integer);
+ procedure FilterShadowBitmap(bmp: TMufasaBitmap);
+ procedure FilterCharsBitmap(bmp: TMufasaBitmap);
+
+ function GetTextAt(atX, atY, font, minspacing, maxspacing, color, len: integer): string;
+ function TextToFontTPA(Text, font: String; var w, h: integer): TPointArray;
+ function TextToFontBitmap(Text, font: String): TMufasaBitmap;
+ function TextToMask(Text, font: String): TMask;
+
+
+ {$IFDEF OCRDEBUG}
+ procedure DebugToBmp(bmp: TMufasaBitmap; hmod,h: integer);
+ {$ENDIF}
+ private
+ Client: TObject;
+ Fonts: TMFonts;
+ {$IFDEF OCRDEBUG}
+ public
+ debugbmp: TMufasaBitmap;
+ {$ENDIF}
+
+ end;
+ {$IFDEF OCRDEBUG}
+ {$IFDEF LINUX}
+ const OCRDebugPath = '/tmp/';
+ {$ELSE}
+ const OCRDebugPath = '';
+ {$ENDIF}
+ {$ENDIF}
+implementation
+
+uses
+ colour_conv, client, files, tpa, mufasatypesutil;
+
+const
+ { Very rough limits for R, G, B }
+ ocr_Limit_High = 190;
+ ocr_Limit_Med = 130;
+ ocr_Limit_Low = 65;
+
+
+ { `base' Colours of the Uptext }
+
+ { White }
+ ocr_White = 16777215;
+
+ { Level < Your Level }
+ ocr_Green = 65280;
+
+ { Level > Your Level }
+ ocr_Red = 255;
+
+ { Interact or Level = Your Level }
+ ocr_Yellow = 65535;
+
+ { Object }
+ ocr_Blue = 16776960;
+
+ { Item }
+ ocr_ItemC = 16744447;
+
+ { Shadow }
+ ocr_Purple = 8388736;
+
+
+{ Constructor }
+constructor TMOCR.Create(Owner: TObject);
+
+var
+ files: TStringArray;
+
+begin
+ inherited Create;
+ Self.Client := Owner;
+ Self.Fonts := TMFonts.Create;
+end;
+
+{ Destructor }
+destructor TMOCR.Destroy;
+
+begin
+
+ Self.Fonts.Free;
+ inherited Destroy;
+end;
+
+{
+ InitTOCR loads all fonts in path
+ We don't do this in the constructor because we may not yet have the path.
+}
+function TMOCR.InitTOCR(path: string): boolean;
+var
+ dirs: array of string;
+ i: longint;
+ dir: string;
+begin
+ // We're going to load all fonts now
+ Fonts.SetPath(path);
+ dirs := GetDirectories(path);
+
+ for i := 0 to high(dirs) do
+ begin
+ Fonts.LoadFont(dirs[i], false);
+ {$IFDEF FONTDEBUG}
+ writeln('Loading ' + dirs[i]);
+ {$ENDIF}
+ end;
+ If DirectoryExists(path + 'UpChars') then
+ Fonts.LoadFont('UpChars', true); // shadow
+end;
+
+{ Get the current pointer to our list of Fonts }
+function TMOCR.GetFonts:TMFonts;
+begin
+ Exit(Self.Fonts);
+end;
+
+{ Set new Fonts. We set it to a Copy of NewFonts }
+procedure TMOCR.SetFonts(NewFonts: TMFonts);
+begin
+ Self.Fonts := NewFonts.Copy();
+end;
+
+{
+ Filter UpText by a very rough colour comparison / range check.
+ We first convert the colour to RGB, and if it falls into the following
+ defined ranges, it may be part of the uptext. Also get the possible
+ shadows.
+
+ We have large ranges because we rather have extra (fake) pixels than less
+ uptext pixels... This because we can filter most of the noise out easily.
+
+ Non optimised. We can make it use direct data instead of fastgetpixel and
+ fastsetpixel, but speed isn't really an issue. The entire algorithm is still
+ fast enough.
+}
+
+procedure TMOCR.FilterUpTextByColour(bmp: TMufasaBitmap; w,h: integer);
+var
+ x, y,r, g, b: Integer;
+begin
+ // We're going to filter the bitmap solely on colours first.
+ // If we found one, we set it to it's `normal' colour.
+ for y := 0 to bmp.Height - 1 do
+ for x := 0 to bmp.Width - 1 do
+ begin
+ colortorgb(bmp.fastgetpixel(x,y),r,g,b);
+ // the abs(g-b) < 15 seems to help heaps when taking out crap points
+ if (r > ocr_Limit_High) and (g > ocr_Limit_High) and (b > ocr_Limit_High)
+ // 50 or 55. 55 seems to be better.
+ and (abs(r-g) + abs(r-b) + abs(g-b) < 55) then
+ // TODO: make 55 a var, and make it so that it can be set
+ begin
+ bmp.fastsetpixel(x,y,ocr_White);
+ continue;
+ end;
+ if (r < ocr_Limit_Low) and (g > ocr_Limit_High) and (b > ocr_Limit_High) then
+ begin
+ bmp.fastsetpixel(x,y,ocr_Blue);
+ continue;
+ end;
+ if (r < ocr_Limit_Low) and (g > ocr_Limit_High) and (b < ocr_Limit_Low) then
+ begin
+ bmp.fastsetpixel(x,y,ocr_Green);
+ continue;
+ end;
+
+ // false results with fire
+ if(r > ocr_Limit_High) and (g > 100) and (g < ocr_Limit_High) and (b > 40) and (b < 127) then
+ begin
+ bmp.fastsetpixel(x,y,ocr_ItemC);
+ continue;
+ end;
+ if(r > ocr_Limit_High) and (g > ocr_Limit_High) and (b < ocr_Limit_Low) then
+ begin
+ bmp.fastsetpixel(x,y,ocr_Yellow);
+ continue;
+ end;
+ // better use g < 40 than ocr_Limit_Low imo
+ if (r > ocr_Limit_High) and (g < ocr_Limit_Low) and (b < ocr_Limit_Low) then
+ begin
+ bmp.fastsetpixel(x,y,ocr_Red);
+ continue;
+ end;
+ if (r > ocr_Limit_High) and (g > ocr_Limit_Low) and (b < ocr_Limit_Low) then
+ begin
+ bmp.fastsetpixel(x,y,ocr_Red);
+ continue;
+ end;
+ if (r > ocr_Limit_Med) and (r < (ocr_Limit_High + 10)) and (g > ocr_Limit_Low - 10) and
+ (b < 20) then
+ begin
+ bmp.fastsetpixel(x,y,ocr_Green);
+ continue;
+ end;
+ //shadow
+ if (r < ocr_Limit_Low) and (g < ocr_Limit_Low) and (b < ocr_Limit_Low) then
+ begin
+ bmp.FastSetPixel(x,y, ocr_Purple);
+ continue;
+ end;
+
+ bmp.fastsetpixel(x,y,0);
+ end;
+
+
+ // make outline black for shadow characteristics filter
+ // first and last horiz line = 0
+ for x := 0 to bmp.width -1 do
+ bmp.fastsetpixel(x,0,0);
+ for x := 0 to bmp.width -1 do
+ bmp.fastsetpixel(x,bmp.height-1,0);
+ // same for vertical lines
+ for y := 0 to bmp.Height -1 do
+ bmp.fastsetpixel(0, y, 0);
+ for y := 0 to bmp.Height -1 do
+ bmp.fastsetpixel(bmp.Width-1, y, 0);
+end;
+
+
+{
+ This filter assumes the previous colour filter has been applied first.
+ I like to call this the `characteristics' filter because we really only filter
+ on characteristics.
+
+ For the uptext, a few things apply...
+ First of all:
+
+ *** Remove False Shadow ***
+ if shadow[x,y] then not shadow[x-1,y-1]
+ If there is a shadow at x,y then there should not be a shadow at x-1, y-1; if
+ there is one, then shadow[x, y] is not a shadow.
+
+ (One could also say, if shadow[x,y] and shadow[x+1,y+1] then shadow[x+1,y+1]
+ is no shadow; because it essentially means the same. However, a smart mind
+ will soon see that this algorithm will be a *lot* more efficient if we
+ start at the right bottom, instead of the left top. Which means we should
+ work with x-1 and y-1, rather than x+1,y+1
+ Yeah.... My comments are vague.
+ )
+
+ *** UpText chars identity 1 and 2 ***
+ if UpTextChar[x,y] then (UpTextChar[x+1,y+1] or shadow[x+1,y+1])
+ If this is not true, then UpTextChar[x,y] cannot be part of uptext - it
+ has no shadow, and it doesn't have a `friend' (at x+1,y+1) either.
+ We don't need to do this from the right bottom to left top.
+
+}
+procedure TMOCR.FilterUpTextByCharacteristics(bmp: TMufasaBitmap; w,h: integer);
+var
+ x,y: Integer;
+begin
+ // Filter 2
+ // This performs a `simple' filter.
+ // What we are doing here is simple checking that if Colour[x,y] is part
+ // of the uptext, then so must Colour[x+1,y+1], or Colour[x+1,y+1] is a shadow.
+ // if it is neither, we can safely remove it.
+ for y := 0 to bmp.Height - 2 do
+ for x := 0 to bmp.Width - 2 do
+ begin
+ if bmp.fastgetpixel(x,y) = clPurple then
+ continue;
+ if bmp.fastgetpixel(x,y) = clBlack then
+ continue;
+ if (bmp.fastgetpixel(x,y) <> bmp.fastgetpixel(x+1,y+1)) and (bmp.fastgetpixel(x+1,y+1) <> clpurple) then
+ bmp.fastsetpixel(x,y,{clAqua}0);
+ end;
+
+ // Remove false shadow
+ for y := bmp.Height - 1 downto 1 do
+ for x := bmp.Width - 1 downto 1 do
+ begin
+ if bmp.fastgetpixel(x,y) <> clPurple then
+ continue;
+ if bmp.fastgetpixel(x,y) = bmp.fastgetpixel(x-1,y-1) then
+ begin
+ bmp.fastsetpixel(x,y,clSilver);
+ continue;
+ end;
+ if bmp.fastgetpixel(x-1,y-1) = 0 then
+ bmp.fastsetpixel(x,y,clSilver);
+ end;
+
+ // Now we do another filter, with uptext chars identity 1 and 2.
+ for y := bmp.Height - 2 downto 0 do
+ for x := bmp.Width - 2 downto 0 do
+ begin
+ if bmp.fastgetpixel(x,y) = clPurple then
+ continue;
+ if bmp.fastgetpixel(x,y) = clBlack then
+ continue;
+
+ // identity 1
+ if (bmp.fastgetpixel(x,y) = bmp.fastgetpixel(x+1,y+1) ) then
+ continue;
+
+ // identity 2
+ if bmp.fastgetpixel(x+1,y+1) <> clPurple then
+ begin
+ bmp.fastsetpixel(x,y,clOlive);
+ continue;
+ end;
+
+ // If we make it to here, it means the pixel is part of the uptext.
+ end;
+end;
+
+{$IFDEF OCRDEBUG}
+{ Write to our debugbmp }
+procedure TMOCR.DebugToBmp(bmp: TMufasaBitmap; hmod, h: integer);
+var
+ x,y: integer;
+begin
+ for y := 0 to bmp.height - 1 do
+ for x := 0 to bmp.width - 1 do
+ debugbmp.fastsetpixel(x,y + hmod *h,bmp.fastgetpixel(x,y));
+end;
+{$ENDIF}
+
+{
+ Return the shadows of the points in charpoint on bitmap shadowsbmp.
+
+ Pseudo:
+ if shadow[charpoint[i].x+1, charpoint[i].y+1] then addtoResult;
+}
+function getshadows(shadowsbmp:TMufasaBitmap; charpoint: tpointarray): tpointarray;
+var
+ i,c:integer;
+begin
+ setlength(result,length(charpoint));
+ c:=0;
+ for i := 0 to high(charpoint) do
+ begin
+ if shadowsbmp.fastgetpixel(charpoint[i].x+1,charpoint[i].y+1) = clPurple then
+ begin
+ result[c]:=point(charpoint[i].x+1, charpoint[i].y+1);
+ inc(c);
+ end;
+ end;
+ setlength(result,c);
+end;
+
+{ Remove anything but the shadows on the bitmap (Shadow = clPurple, remember?) }
+procedure TMOCR.FilterShadowBitmap(bmp: TMufasaBitmap);
+var
+ x,y:integer;
+begin
+ for y := 0 to bmp.Height - 1 do
+ for x := 0 to bmp.Width - 1 do
+ begin
+ if bmp.fastgetpixel(x,y) <> clPurple then
+ begin
+ bmp.FastSetPixel(x,y,0);
+ continue;
+ end;
+ end;
+end;
+
+{
+ Remove all but uptext colours clWhite,clGreen, etc.
+ See constants above.
+
+ This assumes that the bitmap only consists of colour 0, and the other
+ constants founds above the functionss
+}
+procedure TMOCR.FilterCharsBitmap(bmp: TMufasaBitmap);
+var
+ x,y: integer;
+begin
+ begin
+ for y := 0 to bmp.Height - 1 do
+ for x := 0 to bmp.Width - 1 do
+ begin
+ if bmp.fastgetpixel(x,y) = clPurple then
+ begin
+ bmp.FastSetPixel(x,y,0);
+ continue;
+ end;
+ if bmp.fastgetpixel(x,y) = clOlive then
+ begin
+ bmp.FastSetPixel(x,y,0);
+ continue;
+ end;
+ if bmp.fastgetpixel(x,y) = clSilver then
+ begin
+ bmp.FastSetPixel(x,y,0);
+ continue;
+ end;
+ end;
+ end;
+end;
+
+
+{
+ This uses the two filters, and performs a split on the bitmap.
+ A split per character, that is. So we can more easily identify it.
+
+ TODO:
+ *
+ Remove more noise after we have split, it should be possible to identify
+ noise; weird positions or boxes compared to the rest, etc.
+ *
+ Split each colours seperately, and combine only later, after removing noise.
+
+}
+function TMOCR.getTextPointsIn(sx, sy, w, h: Integer; shadow: boolean;
+ var _chars, _shadows: T2DPointArray): Boolean;
+var
+ bmp, shadowsbmp, charsbmp: TMufasaBitmap;
+ x,y: integer;
+ r,g,b: integer;
+ n: TNormArray;
+ {$IFDEF OCRDEBUG}
+ dx,dy: integer;
+ {$ENDIF}
+ shadows: T2DPointArray;
+ helpershadow: TPointArray;
+ chars: TPointArray;
+ charscount: integer;
+ chars_2d, chars_2d_b, finalchars: T2DPointArray;
+ pc: integer;
+ bb: Tbox;
+
+begin
+ bmp := TMufasaBitmap.Create;
+ { Increase to create a black horizonal line at the top and at the bottom }
+ { This so the crappy algo can do it's work correctly. }
+ bmp.SetSize(w + 2, h + 2);
+
+ // Copy the client to out working bitmap.
+ bmp.CopyClientToBitmap(TClient(Client).IOManager, False, 1{0},1, sx, sy, sx + w - 1, sy + h - 1);
+
+ {$IFDEF OCRSAVEBITMAP}
+ bmp.SaveToFile(OCRDebugPath + 'ocrinit.bmp');
+ {$ENDIF}
+
+ {$IFDEF OCRDEBUG}
+ debugbmp := TMufasaBitmap.Create;
+ debugbmp.SetSize(w + 2, (h + 2) * 7);
+ {$ENDIF}
+ {$IFDEF OCRDEBUG}
+ DebugToBmp(bmp,0,h);
+ {$ENDIF}
+
+ // Filter 1
+ FilterUpTextByColour(bmp,w,h);
+ {$IFDEF OCRSAVEBITMAP}
+ bmp.SaveToFile(OCRDebugPath + 'ocrcol.bmp');
+ {$ENDIF}
+
+ {$IFDEF OCRDEBUG}
+ DebugToBmp(bmp,1,h);
+ {$ENDIF}
+
+ // Filter 2
+ FilterUpTextByCharacteristics(bmp,w,h);
+
+ {$IFDEF OCRSAVEBITMAP}
+ bmp.SaveToFile(OCRDebugPath + 'ocrdebug.bmp');
+ {$ENDIF}
+ {$IFDEF OCRDEBUG}
+ DebugToBmp(bmp,2,h);
+ {$ENDIF}
+
+ // create a bitmap with only the shadows on it
+ shadowsbmp := bmp.copy;
+ FilterShadowBitmap(shadowsbmp);
+ {$IFDEF OCRDEBUG}
+ DebugToBmp(shadowsbmp,3,h);
+ {$ENDIF}
+
+ // create a bitmap with only the chars on it
+ charsbmp := bmp.copy;
+ FilterCharsBitmap(charsbmp);
+ {$IFDEF OCRDEBUG}
+ DebugToBmp(charsbmp,4,h);
+ {$ENDIF}
+
+ // this gets the chars from the bitmap.
+
+ // TODO:
+ // We should make a different TPA
+ // for each colour, rather than put them all in one. Noise can be a of a
+ // differnet colour.
+ setlength(chars, charsbmp.height * charsbmp.width);
+ charscount:=0;
+ for y := 0 to charsbmp.height - 1 do
+ for x := 0 to charsbmp.width - 1 do
+ begin
+ if charsbmp.fastgetpixel(x,y) > 0 then
+ begin
+ chars[charscount]:=point(x,y);
+ inc(charscount);
+ end;
+ end;
+ setlength(chars,charscount);
+
+ // split chars
+ chars_2d := SplitTPAEx(chars,1,charsbmp.height);
+ SortATPAFrom(chars_2d, point(0,0));
+ for x := 0 to high(chars_2d) do
+ begin
+ pc := random(clWhite);
+ for y := 0 to high(chars_2d[x]) do
+ charsbmp.FastSetPixel(chars_2d[x][y].x, chars_2d[x][y].y, pc);
+ end;
+ {$IFDEF OCRDEBUG}
+ DebugToBmp(charsbmp,5,h);
+ {$ENDIF}
+
+ for y := 0 to high(chars_2d) do
+ begin
+ bb:=gettpabounds(chars_2d[y]);
+ if (bb.x2 - bb.x1 > 10) or (length(chars_2d[y]) > 70) then
+ begin // more than one char
+ {$IFDEF OCRDEBUG}
+ if length(chars_2d[y]) > 70 then
+ writeln('more than one char at y: ' + inttostr(y));
+ if (bb.x2 - bb.x1 > 10) then
+ writeln('too wide at y: ' + inttostr(y));
+ {$ENDIF}
+ helpershadow:=getshadows(shadowsbmp,chars_2d[y]);
+ chars_2d_b := splittpaex(helpershadow,2,shadowsbmp.height);
+ //writeln('chars_2d_b length: ' + inttostr(length(chars_2d_b)));
+ shadowsbmp.DrawATPA(chars_2d_b);
+ for x := 0 to high(chars_2d_b) do
+ begin
+ setlength(shadows,length(shadows)+1);
+ shadows[high(shadows)] := ConvTPAArr(chars_2d_b[x]);
+ end;
+ end else
+ if length(chars_2d[y]) < 70 then
+ begin
+ setlength(shadows,length(shadows)+1);
+ shadows[high(shadows)] := getshadows(shadowsbmp, chars_2d[y]);
+ end;
+ end;
+
+ // sort, split messes with the order of chars
+ SortATPAFromFirstPoint(chars_2d, point(0,0));
+ for y := 0 to high(chars_2d) do
+ begin
+ if length(chars_2d[y]) > 70 then
+ continue;
+ setlength(finalchars,length(finalchars)+1);
+ finalchars[high(finalchars)] := chars_2d[y];
+ end;
+
+ SortATPAFromFirstPoint(shadows, point(0,0));
+ for x := 0 to high(shadows) do
+ begin
+ pc:=0;
+ pc := random(clWhite);
+ //pc := rgbtocolor(integer(round((x+1)*255/length(shadows))), round((x+1)*255/length(shadows)), round((x+1)*255/length(shadows)));
+ for y := 0 to high(shadows[x]) do
+ shadowsbmp.FastSetPixel(shadows[x][y].x, shadows[x][y].y, pc);
+ end;
+ {$IFDEF OCRDEBUG}
+ DebugToBmp(shadowsbmp,6,h);
+ {$ENDIF}
+
+ _chars := finalchars;
+ _shadows := shadows;
+
+ bmp.Free;
+ charsbmp.Free;
+ shadowsbmp.Free;
+end;
+
+{
+ GetUpTextAtEx combines/uses the functions above.
+
+ It will identify each character, and also keep track of the previous
+ chars' final `x' bounds. If the difference between the .x2 of the previous
+ character and the .x1 of the current character is bigger than 5, then there
+ was a space between them. (Add ' ' to result)
+}
+
+function TMOCR.GetUpTextAtEx(atX, atY: integer; shadow: boolean): string;
+var
+ n:Tnormarray;
+ ww, hh,i,j: integer;
+ font: TocrData;
+ chars, shadows, thachars: T2DPointArray;
+ t:Tpointarray;
+ b,lb:tbox;
+ lbset: boolean;
+
+begin
+ result:='';
+ ww := 400;
+ hh := 20;
+
+ getTextPointsIn(atX, atY, ww, hh, shadow, chars, shadows);
+
+ // Get font data for analysis.
+
+ if shadow then
+ begin
+ font := Fonts.GetFont('UpChars_s');
+ thachars := shadows;
+ {$IFDEF OCRDEBUG}
+ writeln('using shadows');
+ {$ENDIF}
+ end
+ else
+ begin
+ font := Fonts.GetFont('UpChars');
+ thachars := chars;
+ {$IFDEF OCRDEBUG}
+ writeln('not using shadows');
+ {$ENDIF}
+ end;
+
+ lbset:=false;
+ setlength(n, (font.width+1) * (font.height+1));
+ for j := 0 to high(thachars) do
+ begin
+ for i := 0 to high(n) do
+ n[i] := 0;
+
+ t:= thachars[j];
+ b:=gettpabounds(t);
+ if not lbset then
+ begin
+ lb:=b;
+ lbset:=true;
+ end else
+ begin
+ // spacing
+ if b.x1 - lb.x2 > 5 then
+ result:=result+' ';
+ lb:=b;
+ end;
+ for i := 0 to high(t) do
+ t[i] := t[i] - point(b.x1,b.y1);
+
+ for i := 0 to high(thachars[j]) do
+ begin
+ n[(thachars[j][i].x) + ((thachars[j][i].y) * font.width)] := 1;
+ end;
+ result := result + GuessGlyph(n, font);
+ end;
+end;
+
+function TMOCR.GetUpTextAt(atX, atY: integer; shadow: boolean): string;
+
+begin
+ if shadow then
+ result := GetUpTextAtEx(atX, atY, true)
+ else
+ result := GetUpTextAtEx(atX, atY, false);
+end;
+
+function TMOCR.GetTextAt(atX, atY, font, minspacing, maxspacing, color, len: integer): string;
+
+begin
+
+end;
+
+function TMOCR.TextToFontTPA(Text, font: String; var w, h: integer): TPointArray;
+
+var
+ fontD: TOcrData;
+ c, i, x, y, off: Integer;
+ d: TocrGlyphMetric;
+ an: integer;
+
+begin
+ fontD := Fonts.GetFont(font);
+ c := 0;
+ off := 0;
+ setlength(result, 0);
+
+ for i := 1 to length(text) do
+ begin
+ writeln(text[i]);
+ an := Ord(text[i]);
+ if not InRange(an, 0, 255) then
+ begin
+ writeln('WARNING: Invalid character passed to TextToFontTPA');
+ continue;
+ end;
+ d := fontD.ascii[an];
+ {writeln(format('xoff, yoff: %d, %d', [d.xoff, d.yoff]));
+ writeln(format('bmp w,h: %d, %d', [d.width, d.height]));
+ writeln(format('font w,h: %d, %d', [fontD.width, fontD.height])); }
+ setlength(result, c+d.width*d.height);
+ for y := 0 to fontD.height - 1 do
+ for x := 0 to fontD.width - 1 do
+ begin
+ if fontD.pos[fontD.ascii[an].index][x + y * fontD.width] = 1 then
+ // if fontD.pos[an][x + y * fontD.width] = 1 then
+ begin
+ result[c] := Point(x + off +d.xoff, y+d.yoff);
+ inc(c);
+ end;
+ end;
+ setlength(result, c);
+ off := off + d.width;
+ end;
+ w := off;
+ h := d.height;
+ { writeln('C: ' + inttostr(c)); }
+end;
+
+function TMOCR.TextToFontBitmap(Text, font: String): TMufasaBitmap;
+var
+ TPA: TPointArray;
+ w,h: integer;
+ bmp: TMufasaBitmap;
+begin
+ TPA := TextToFontTPA(text, font, w, h);
+ bmp := TMufasaBitmap.Create;
+ writeln(format('b: %d, %d', [w, h]));
+ bmp.SetSize(w, h);
+ bmp.DrawTPA(TPA, clWhite);
+ result := bmp;
+end;
+
+function TMOCR.TextToMask(Text, font: String): TMask;
+var
+ TPA: TPointArray;
+ w,h: integer;
+ i,x,y : integer;
+ dx,dy : integer;
+ c : integer;
+ bmp: TMufasaBitmap;
+ Pixels : array of array of boolean; //White = true
+begin
+ TPA := TextToFontTPA(text, font, w, h);
+ Result.w := w;
+ Result.h := h;
+ Result.WhiteHi:= High(TPA);//High(WhitePixels)
+ Result.BlackHi:= w*h - Length(TPA) - 1;//High(BlackPixels) = Length(blackPixels) - 1 = (TotalLength - LenWhitePixels) - 1
+ SetLength(Pixels,w,h);
+ SetLength(result.White,Result.WhiteHi + 1);
+ SetLength(result.Black,Result.BlackHi + 1);
+ for i := Result.WhiteHi downto 0 do
+ begin
+ Result.White[i] := TPA[i];
+ Pixels[TPA[i].x][TPA[i].y] := true;
+ end;
+ c := 0;
+ dx := w-1;
+ dy := h-1;
+ for y := 0 to dY do
+ for x := 0 to dX do
+ if not Pixels[x][y] then
+ begin
+ result.Black[c].x :=x;
+ result.black[c].y := y;
+ inc(c);
+ end;
+end;
+
+end.
+
diff --git a/branches/script-component/Units/MMLCore/ocrutil.pas b/branches/script-component/Units/MMLCore/ocrutil.pas
new file mode 100644
index 0000000..a568e6c
--- /dev/null
+++ b/branches/script-component/Units/MMLCore/ocrutil.pas
@@ -0,0 +1,623 @@
+unit ocrutil;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+ Classes, SysUtils, MufasaTypes;
+
+type
+ TNormArray = array of integer;
+ TocrGlyphMask = record
+ ascii: char;
+ width,height: integer;
+ l,r,t,b: integer;
+ mask: TNormArray;
+ end;
+ TocrGlyphMaskArray = array of TocrGlyphMask;
+ TocrGlyphMetric = record
+ xoff,yoff: integer;
+ width,height: integer;
+ index: integer; //stores the internal TocrData index for this char
+ end;
+ TocrData = record
+ ascii: array[0..255] of TocrGlyphMetric;
+ pos: array of array of integer;
+ pos_adj: array of real;
+ neg: array of array of integer;
+ neg_adj: array of real;
+ map: array of char;
+ width,height: integer;
+ inputs,outputs: integer;
+ end;
+
+ TocrDataArray = array of TocrData;
+
+ { We already have PRGB32 -> To be removed later }
+ type
+ tRGB = packed record
+ B, G, R, A: Byte;
+ end;
+ tRGBArray = array of tRGB;
+
+ {Begin To be removed}
+ Tbmp = record
+ data: array of tRGB;
+ width,height: integer;
+ end;
+ {End To be removed}
+
+
+ tLab = record
+ L,a,b: real;
+ end;
+
+ procedure findBounds(glyphs: TocrGlyphMaskArray; out width,height: integer);
+ function LoadGlyphMasks(path: string; shadow: boolean): TocrGlyphMaskArray;
+ function InitOCR(path: string; shadow: boolean): TocrData;
+ function GuessGlyph(glyph: TNormArray; ocrdata: TocrData): char;
+ function PointsToNorm(points: TpointArray; out w,h: integer): TNormArray;
+ function ImageToNorm(src: tRGBArray; w,h: integer): TNormArray;
+ function ocrDetect(txt: TNormArray; w,h: integer; var ocrdata: TocrData): string;
+ function ExtractText(colors: PRGB32;{colors: tRGBArray;} w,h: integer): TNormArray;
+ function MakeTPAString(str: string): TpointArray;
+
+implementation
+uses
+ bitmaps, math,
+ {Begin To-Remove units. Replace ReadBmp with TMufasaBitmap stuff later.}
+ graphtype, intfgraphics,graphics;
+ {End To-Remove unit}
+
+function ReadBMP(path: string): Tbmp;
+var
+ LazIntf : TLazIntfImage;
+ RawImageDesc : TRawImageDescription;
+ data: array of tRGB;
+begin
+ if FileExists(path) then
+ begin;
+ LazIntf := TLazIntfImage.Create(0,0);
+ RawImageDesc.Init_BPP32_B8G8R8_BIO_TTB(LazIntf.Width,LazIntf.Height);
+ LazIntf.DataDescription := RawImageDesc;
+ LazIntf.LoadFromFile(path);
+ Result.width := LazIntf.Width;
+ Result.height := LazIntf.Height;
+ SetLength(data,LazIntf.Width*LazIntf.Height);
+ Move(LazIntf.PixelData[0],data[0],LazIntf.Width*LazIntf.Height*sizeOf(tRGB));
+ Result.data:= data;
+ LazIntf.Free;
+ end;
+end;
+
+
+
+
+{initalizes the remaining fields from a TocrGlyphMask and finds the global bounds}
+procedure findBounds(glyphs: TocrGlyphMaskArray; out width,height: integer);
+var
+ i,x,y,c,w,h: integer;
+ l,r,t,b: integer;
+ dat: TNormArray;
+begin
+ width:= 0;
+ height:= 0;
+ for c:= 0 to length(glyphs) - 1 do
+ begin
+ dat:= glyphs[c].mask;
+ w:= glyphs[c].width;
+ h:= glyphs[c].height;
+ l:= w;
+ r:= 0;
+ t:= h;
+ b:= 0;
+ for i:= 0 to w*h-1 do
+ begin
+ if dat[i] = 1 then
+ begin
+ x:= i mod w;
+ y:= i div w;
+ if x > r then r:= x;
+ if x < l then l:= x;
+ if y > b then b:= y;
+ if y < t then t:= y;
+ end;
+ end;
+ if l = w then l:= 0;
+ if t = h then t:= 0;
+ glyphs[c].r:= r;
+ glyphs[c].l:= l;
+ glyphs[c].b:= b;
+ glyphs[c].t:= t;
+ if (r - l + 1) > width then width:= r - l + 1;
+ if (b - t + 1) > height then height:= b - t + 1;
+ end;
+end;
+
+{Use whatever you want if you don't like this}
+function GetFiles(Path, Ext: string): TstringArray;
+var
+ SearchRec : TSearchRec;
+ c : integer;
+begin
+ c := 0;
+ if FindFirst(Path + '*.' + ext, faAnyFile, SearchRec) = 0 then
+ begin
+ repeat
+ inc(c);
+ SetLength(Result,c);
+ Result[c-1] := SearchRec.Name;
+ until FindNext(SearchRec) <> 0;
+ SysUtils.FindClose(SearchRec);
+ end;
+end;
+
+{This Loads the actual data from the .bmp, but does not init all fields}
+function LoadGlyphMasks(path: string; shadow: boolean): TocrGlyphMaskArray;
+var
+ strs: array of string;
+ bmp: array of Tbmp; {-> TMufasaBitmap, and why use an array? }
+ len,size,i,j: integer;
+ color: tRGB;
+ shadow_i: byte;
+begin
+ strs:= GetFiles(path,'bmp');
+ len:= length(strs);
+ SetLength(result,len);
+ SetLength(bmp,len);
+ if shadow then
+ shadow_i := 0
+ else
+ shadow_i := 255;
+ for i:= 0 to len-1 do
+ begin
+ bmp[i]:= ReadBmp(path + strs[i]);
+ size:= bmp[i].width*bmp[i].height;
+ SetLength(result[i].mask,size);
+ for j:= 0 to size-1 do
+ begin
+ color:= bmp[i].data[j];
+ { if (color.r = 255) and (color.g = 255 and not shadow_i) and
+ (color.b = 255 and not shadow_i) then}
+ if (color.r = 255) and (color.g = shadow_i) and (color.b = shadow_i) then
+ result[i].mask[j]:= 1
+ else
+ result[i].mask[j]:= 0;
+ end;
+ result[i].width:= bmp[i].width;
+ result[i].height:= bmp[i].height;
+ SetLength(strs[i],Length(strs[i])-4);
+ result[i].ascii:= chr(strtoint(strs[i]));
+ end;
+end;
+
+{Fully initalizes a TocrData structure, this is LoadFont or whatever, call it first}
+function InitOCR(path: string; shadow: boolean): TocrData;
+var
+ masks: TocrGlyphMaskArray;
+ t,b,l,r,w,h,mw: integer;
+ x,y: integer;
+ c,i,len,size: integer;
+ pos: integer;
+ ascii: char;
+begin
+ masks:= LoadGlyphMasks(path, shadow);
+ w:= 0;
+ h:= 0;
+ findBounds(masks,w,h);
+ len:= Length(masks);
+ result.width:= w;
+ result.height:= h;
+ size:= w * h;
+ SetLength(result.pos,len,size);
+ SetLength(result.pos_adj,len);
+ SetLength(result.neg,len,size);
+ SetLength(result.neg_adj,len);
+ SetLength(result.map,len);
+ for i:= 0 to len - 1 do
+ begin
+ ascii:= masks[i].ascii;
+ pos:= 0;
+ l:= masks[i].l;
+ r:= masks[i].r;
+ b:= masks[i].b;
+ t:= masks[i].t;
+ mw:= masks[i].width;
+ for y:= t to b do
+ begin
+ for x:= l to r do
+ begin
+ c:= (x-l) + (y-t)*w;
+ if masks[i].mask[x+y*mw] <> 0 then
+ begin
+ result.pos[i][c]:= 1;
+ inc(pos);
+ end else
+ result.pos[i][c] := 0;
+ end;
+ end;
+ for c:= 0 to size-1 do
+ result.neg[i][c]:= 1 - result.pos[i][c];
+ if pos = 0 then result.neg_adj[i]:= 1 else result.neg_adj[i]:= 1 / pos;
+ if pos = 0 then result.pos_adj[i]:= 0 else result.pos_adj[i]:= 1 / pos;
+ result.map[i]:= ascii;
+ result.ascii[ord(ascii)].index:= i;
+ result.ascii[ord(ascii)].xoff:= masks[i].l;
+ result.ascii[ord(ascii)].yoff:= masks[i].t;
+ result.ascii[ord(ascii)].width:= masks[i].width;
+ result.ascii[ord(ascii)].height:= masks[i].height;
+ end;
+ result.inputs:= size;
+ result.outputs:= len;
+end;
+
+{guesses a glyph stored in glyph (which is an 1-0 image of the size specified by width and height in ocrdata}
+function GuessGlyph(glyph: TNormArray; ocrdata: TocrData): char;
+var
+ i,c,inputs,outputs,val: integer;
+ pos_weights: array of real;
+ neg_weights: array of real;
+ max, weight: real;
+begin
+ SetLength(pos_weights,ocrdata.outputs);
+ SetLength(neg_weights,ocrdata.outputs);
+ inputs:= ocrdata.inputs - 1;
+ outputs:= ocrdata.outputs - 1;
+ for i:= 0 to inputs do
+ begin
+ val:= glyph[i];
+ for c:= 0 to outputs do
+ begin
+ pos_weights[c]:= pos_weights[c] + ocrdata.pos[c][i] * val;
+ neg_weights[c]:= neg_weights[c] + ocrdata.neg[c][i] * val;
+ end
+ end;
+ max:= 0;
+ for i:= 0 to outputs do
+ begin
+ weight:= pos_weights[i] * ocrdata.pos_adj[i] - neg_weights[i] * ocrdata.neg_adj[i];
+ if (weight > max) then
+ begin
+ max:= weight;
+ result:= ocrdata.map[i];
+ end;
+ end;
+end;
+
+{converts a TPA into a 1-0 image of the smallest possible size}
+function PointsToNorm(points: TpointArray; out w,h: integer): TNormArray;
+var
+ l,r,t,b: integer;
+ i,len,size: integer;
+ norm: TNormArray;
+begin
+ len:= length(points);
+ l:= points[0].x;
+ r:= points[0].x;
+ t:= points[0].y;
+ b:= points[0].y;
+ for i:= 1 to len-1 do
+ begin
+ if points[i].x < l then l:= points[i].x;
+ if points[i].x > r then r:= points[i].x;
+ if points[i].y < t then t:= points[i].y;
+ if points[i].y > b then b:= points[i].y;
+ end;
+ w:= r - l + 1;
+ h:= b - t + 1;
+ size:= w * h;
+ SetLength(norm,size);
+ for i:= 0 to len-1 do
+ norm[(points[i].x - l) + (points[i].y - t) * w]:= 1;
+ result:= norm;
+end;
+
+function ImageToNorm(src: tRGBArray; w,h: integer): TNormArray;
+var
+ norm: TNormArray;
+ i: integer;
+begin
+ SetLength(norm,w*h);
+ for i:= 0 to w*h-1 do
+ if (src[i].r = 255) and (src[i].g = 255) and (src[i].b = 255) then
+ norm[i]:= 1 else norm[i]:= 0;
+ result:= norm;
+end;
+
+{takes a mask of only one line of text, a TocrData, and returns the string in it}
+function ocrDetect(txt: TNormArray; w,h: integer; var ocrdata: TocrData): string;
+var
+ l,r,t,b,x,y,xx,yy: integer;
+ upper,left,last,spaces: integer;
+ glyph: TNormArray;
+ empty: boolean;
+ ascii: char;
+begin
+ result:= '';
+ l:= -1;
+ r:= -1;
+ upper:= -9001; //large negative
+ left:= -9001; //large negative
+ x:= 0;
+ while x < w do
+ begin
+ empty:= true;
+ for y:= 0 to h-1 do
+ begin
+ if txt[x+y*w] = 1 then
+ begin
+ empty:= false;
+ break;
+ end;
+ end;
+ if (l = -1) and (not empty) then
+ begin
+ l:= x
+ end else if (l <> -1) then
+ begin
+ if empty then
+ r:= x - 1
+ else if x = w-1 then
+ r:= x;
+ end;
+ if (r <> -1) and (l <> -1) then
+ begin
+ t:= -1;
+ b:= -1;
+ SetLength(glyph,0);
+ SetLength(glyph,ocrdata.width*ocrdata.height);
+ for yy:= 0 to h-1 do
+ begin
+ for xx:= l to r do
+ if txt[xx+yy*w] = 1 then begin t:= yy; break; end;
+ if t <> -1 then break;
+ end;
+ for yy:= h-1 downto 0 do
+ begin
+ for xx:= l to r do
+ if txt[xx+yy*w] = 1 then begin b:= yy; break; end;
+ if b <> -1 then break;
+ end;
+ if b - t + 1 > ocrdata.height then b:= b - (b-t+1-ocrdata.height);
+ if r - l + 1 > ocrdata.width then r:= r - (r-l+1-ocrdata.width);
+ for yy:= t to b do
+ for xx:= l to r do
+ glyph[(xx-l) + (yy-t)*ocrdata.width]:= txt[xx+yy*w];
+
+ ascii:= GuessGlyph(glyph,ocrdata);
+ if (upper = -9001) or (left = -9001) then
+ begin
+ upper:= t - ocrdata.ascii[ord(ascii)].yoff;
+ left:= l - ocrdata.ascii[ord(ascii)].xoff + ocrdata.ascii[ord(ascii)].width;
+ x:= left;
+ end else
+ begin
+ last:= left;
+ left:= l - ocrdata.ascii[ord(ascii)].xoff;
+ if last <> left then
+ begin
+ for spaces:= 1 to (left - last) div ocrdata.ascii[32].width do
+ result:= result + ' ';
+ end;
+ left:= left + ocrdata.ascii[ord(ascii)].width;
+ x:= left;
+ end;
+
+ result:= result + ascii;
+
+ l:= -1;
+ r:= -1;
+
+ end;
+ inc(x);
+ end;
+end;
+
+function AvgColors(color1:tRGB; weight1: integer; color2: tRGB; weight2: integer): tRGB;
+begin
+ result.r:= (color1.r * weight1 + color2.r * weight2) div (weight1 + weight2);
+ result.g:= (color1.g * weight1 + color2.g * weight2) div (weight1 + weight2);
+ result.b:= (color1.b * weight1 + color2.b * weight2) div (weight1 + weight2);
+end;
+
+procedure RGBtoXYZ(color: tRGB; out X, Y, Z: real); inline;
+var
+ nr,ng,nb: real;
+begin
+ nr:= color.r / 255.0;
+ ng:= color.g / 255.0;
+ nb:= color.b / 255.0;
+ if nr <= 0.04045 then nr:= nr / 12.92 else nr:= power((nr + 0.055)/1.055,2.4);
+ if ng <= 0.04045 then ng:= ng / 12.92 else ng:= power((ng + 0.055)/1.055,2.4);
+ if nb <= 0.04045 then nr:= nb / 12.92 else nb:= power((nb + 0.055)/1.055,2.4);
+ X:= 0.4124*nr + 0.3576*ng + 0.1805*nb;
+ Y:= 0.2126*nr + 0.7152*ng + 0.0722*nb;
+ Z:= 0.0193*nr + 0.1192*ng + 0.9505*nb;
+end;
+
+function labmod(i: real): real; inline;
+begin
+ if i > power(0.206896552,3) then
+ result:= power(i,0.333333333)
+ else
+ result:= 7.787037037*i + 0.137931034;
+end;
+
+function ColortoLab(c: tRGB): tLab; inline;
+var
+ X,Y,Z,sum,Xn,Yn,Zn: real;
+begin
+ RGBtoXYZ(c,X,Y,Z);
+ sum:= X + Y + Z;
+ if(sum = 0) then
+ begin
+ result.l := 0.0;
+ result.a := 0.0;
+ result.b := 0.0;
+ end;
+ Xn:= X / sum;
+ Yn:= Y / sum;
+ Zn:= Z / sum;
+ result.L:= 116.0*labmod(y/yn) - 16.0;
+ result.a:= 500.0*(labmod(x/xn)-labmod(y/yn));
+ result.b:= 500.0*(labmod(y/yn)-labmod(z/zn));
+end;
+
+function colorDistSqr(a,b:tRGB): integer; inline;
+begin
+ result:= (a.r-b.r)*(a.r-b.r)+(a.b-b.b)*(a.b-b.b)+(a.g-b.g)*(a.g-b.g);
+end;
+
+function ExtractText(colors: PRGB32;{colors: tRGBArray;} w,h: integer): TNormArray;
+const
+ GradientMax = 2.0;
+ white: tRGB = ( b: $FF; g: $FF; r: $FF; a: $00 );
+ cyan: tRGB = ( b: $FF; g: $FF; r: $00; a: $00 );
+ yellow: tRGB = ( b: $00; g: $EF; r: $FF; a: $00 );
+ red: tRGB = ( b: $00; g: $00; r: $FF; a: $00 );
+ green: tRGB = ( b: $00; g: $FF; r: $00; a: $00 );
+var
+ up, left: boolean;
+ len,numblobs,thisblob,lastblob,i,j,used: integer;
+ blobbed,blobcount,stack: array of integer;
+ labs: array of tLab;
+ a,b: tLab;
+ blobcolor: tRGBArray;
+ newcolors: array of integer;
+ c: tRGB;
+ norm: TNormArray;
+begin
+ len:= w*h;
+ SetLength(blobbed,len);
+ SetLength(blobcount,len);
+ SetLength(blobcolor,len);
+ SetLength(stack,len);
+ SetLength(labs,len);
+ for i:= 0 to len-1 do
+ labs[i]:= ColorToLab(tRGB(colors[i]));
+ numblobs:= 0;
+ for i:= 0 to len-1 do
+ begin
+ a:= labs[i];
+ if i >= w then
+ begin
+ b:= labs[i-w];
+ up:= abs(a.L-b.L)+abs(a.a-b.a)+abs(a.b-b.b) <= GradientMax;
+ end else
+ up:= false;
+ if i mod w <> 0 then
+ begin
+ b:= labs[i-1];
+ left:= abs(a.L-b.L)+abs(a.a-b.a)+abs(a.b-b.b) <= GradientMax;
+ end else
+ left:= false;
+ if left and up then
+ begin
+ thisblob:= blobbed[i-w];
+ blobbed[i]:= thisblob;
+ blobcolor[thisblob]:= AvgColors(blobcolor[thisblob],blobcount[thisblob],tRGB(colors[i]),1);
+ blobcount[thisblob]:= blobcount[thisblob] + 1;
+ lastblob:= blobbed[i-1];
+ if lastblob <> thisblob then
+ begin
+ used:= 1;
+ stack[0]:= i-1;
+ while used > 0 do
+ begin
+ used:= used - 1;
+ j:= stack[used];
+ if blobbed[j] = lastblob then
+ begin
+ blobbed[j]:= thisblob;
+ if j >= w then if blobbed[j-w] = lastblob then begin stack[used]:= j-w; used:= used + 1; end;
+ if j mod w <> 0 then if blobbed[j-1] = lastblob then begin stack[used]:= j-1; used:= used + 1; end;
+ if (j+1) mod w <> 0 then if blobbed[j+1] = lastblob then begin stack[used]:= j+1; used:= used + 1; end;
+ if j < w*h-w then if blobbed[j+w] = lastblob then begin stack[used]:= j+w; used:= used + 1; end;
+ end;
+ end;
+ blobcolor[thisblob]:= AvgColors(blobcolor[thisblob],blobcount[thisblob],blobcolor[lastblob],blobcount[lastblob]);
+ blobcount[thisblob]:= blobcount[thisblob] + blobcount[lastblob];
+ blobcount[lastblob]:= 0;
+ end;
+ end else if left then
+ begin
+ thisblob:= blobbed[i-1];
+ blobbed[i]:= thisblob;
+ blobcolor[thisblob]:= AvgColors(blobcolor[thisblob],blobcount[thisblob],tRGB(colors[i]),1);
+ blobcount[thisblob]:= blobcount[thisblob] + 1;
+ end else if up then
+ begin
+ thisblob:= blobbed[i-w];
+ blobbed[i]:= thisblob;
+ blobcolor[thisblob]:= AvgColors(blobcolor[thisblob],blobcount[thisblob],tRGB(colors[i]),1);
+ blobcount[thisblob]:= blobcount[thisblob] + 1;
+ end else
+ begin
+ blobbed[i]:= numblobs;
+ blobcount[numblobs]:= 1;
+ blobcolor[numblobs]:= tRGB(colors[i]);
+ numblobs:= numblobs + 1;
+ end;
+ end;
+ SetLength(blobcount,numblobs);
+ SetLength(blobcolor,numblobs);
+ //Done blobfinding, extract char masks
+ SetLength(newcolors,numblobs);
+ for i:= 0 to numblobs-1 do
+ begin
+ j:= blobcount[i];
+ if j > 0 then
+ begin
+ c:= blobcolor[i];
+ if (j > 50) or (j < 2) then
+ newcolors[i]:= 0
+ else if colorDistSqr(white,c) <= 10000 then
+ newcolors[i]:= 1
+ else if colorDistSqr(cyan,c) <= 10000 then
+ newcolors[i]:= 1
+ else if colorDistSqr(yellow,c) <= 10000 then
+ newcolors[i]:= 1
+ else if colorDistSqr(red,c) <= 10000 then
+ newcolors[i]:= 1
+ else if colorDistSqr(green,c) <= 10000 then
+ newcolors[i]:= 1
+ else
+ newcolors[i]:= 0;
+ end;
+ end;
+ SetLength(norm,len);
+ for i:= 0 to len-1 do
+ norm[i]:= newcolors[blobbed[i]];
+ result:= norm;
+end;
+
+function MakeTPAString(str: string): TpointArray;
+var
+ i,j,c,off: integer;
+ bmp: array of Tbmp;
+begin
+ raise Exception.Create('MakeTPAString sucks ass, don''t use it.');
+ c:= 0;
+ off:= 0;
+ SetLength(bmp,length(str));
+ for i:= 0 to length(str)-1 do
+ begin
+ bmp[i]:= ReadBmp('/home/merlijn/Programs/mufasa/Fonts/StatChars/' + inttostr(ord(str[i+1])) + '.bmp');
+ SetLength(result,c+bmp[i].width*bmp[i].height);
+ for j:= 0 to bmp[i].width*bmp[i].height - 1 do
+ begin
+ if bmp[i].data[j].g = 255 then
+ begin
+ result[c].x:= j mod bmp[i].width + off;
+ result[c].y:= j div bmp[i].width;
+ inc(c);
+ end;
+ end;
+ off:= off + bmp[i].width;
+ SetLength(result,c);
+ end;
+end;
+
+end.
+
diff --git a/branches/script-component/Units/MMLCore/os_linux.pas b/branches/script-component/Units/MMLCore/os_linux.pas
new file mode 100644
index 0000000..19c23f0
--- /dev/null
+++ b/branches/script-component/Units/MMLCore/os_linux.pas
@@ -0,0 +1,372 @@
+{
+ This file is part of the Mufasa Macro Library (MML)
+ Copyright (c) 2009 by Raymond van Venetië and Merlijn Wajer
+
+ MML is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ MML is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with MML. If not, see .
+
+ See the file COPYING, included in this distribution,
+ for details about the copyright.
+
+ Linux OS specific implemetation for Mufasa Macro Library
+}
+{$mode objfpc}{$H+}
+unit os_linux;
+
+interface
+
+ uses
+ Classes, SysUtils, mufasatypes, xlib, x, xutil, IOManager, XKeyInput, ctypes, xtest, keysym;
+
+ type
+
+ TNativeWindow = x.TWindow;
+
+ TKeyInput = class(TXKeyInput)
+ public
+ procedure Down(Key: Word);
+ procedure Up(Key: Word);
+ end;
+
+ TWindow = class(TWindow_Abstract)
+ public
+ constructor Create(display: PDisplay; screennum: integer; window: x.TWindow);
+ destructor Destroy; override;
+ procedure GetTargetDimensions(var w, h: integer); override;
+ function ReturnData(xs, ys, width, height: Integer): TRetData; override;
+ procedure FreeReturnData; override;
+
+ function TargetValid: boolean; override;
+ procedure ActivateClient; override;
+ procedure GetMousePosition(var x,y: integer); override;
+ procedure MoveMouse(x,y: integer); override;
+ procedure HoldMouse(x,y: integer; button: TClickType); override;
+ procedure ReleaseMouse(x,y: integer; button: TClickType); override;
+
+ procedure SendString(str: string); override;
+ procedure HoldKey(key: integer); override;
+ procedure ReleaseKey(key: integer); override;
+ function IsKeyHeld(key: integer): boolean; override;
+ private
+ display: PDisplay;
+ screennum: integer;
+ window: x.TWindow;
+ buffer: PXImage;
+ dirty: Boolean; //true if image loaded
+ keyinput: TKeyInput;
+ end;
+
+ TIOManager = class(TIOManager_Abstract)
+ public
+ constructor Create;
+ constructor Create(plugin_dir: string);
+ function SetTarget(target: TNativeWindow): integer; overload;
+ procedure SetDesktop; override;
+ private
+ procedure NativeInit; override;
+ procedure NativeFree; override;
+ public
+ display: PDisplay;
+ screennum: integer;
+ desktop: x.TWindow;
+ end;
+
+ function MufasaXErrorHandler(para1:PDisplay; para2:PXErrorEvent):cint; cdecl;
+
+implementation
+
+ uses GraphType, interfacebase, lcltype;
+
+ // Too global.
+ function MufasaXErrorHandler(para1:PDisplay; para2:PXErrorEvent):cint;cdecl;
+ begin;
+ result := 0;
+ Writeln('X Error: ');
+ writeln('Error code: ' + inttostr(para2^.error_code));
+ writeln('Display: ' + inttostr(LongWord(para2^.display)));
+ writeln('Minor code: ' + inttostr(para2^.minor_code));
+ writeln('Request code: ' + inttostr(para2^.request_code));
+ writeln('Resource ID: ' + inttostr(para2^.resourceid));
+ writeln('Serial: ' + inttostr(para2^.serial));
+ writeln('Type: ' + inttostr(para2^._type));
+ end;
+
+//***implementation*** TKeyInput
+
+ procedure TKeyInput.Down(Key: Word);
+ begin
+ DoDown(Key);
+ end;
+
+ procedure TKeyInput.Up(Key: Word);
+ begin
+ DoUp(Key);
+ end;
+
+//***implementation*** TWindow
+
+ constructor TWindow.Create(display: PDisplay; screennum: integer; window: x.TWindow);
+ begin
+ inherited Create;
+ self.display:= display;
+ self.screennum:= screennum;
+ self.window:= window;
+ self.dirty:= false;
+ self.keyinput:= TKeyInput.Create
+ end;
+
+ destructor TWindow.Destroy;
+ begin
+ FreeReturnData;
+ keyinput.Free;
+ inherited Destroy;
+ end;
+
+ procedure TWindow.GetTargetDimensions(var w, h: integer);
+ var
+ Old_Handler: TXErrorHandler;
+ Attrib: TXWindowAttributes;
+ newx, newy: integer;
+ childwindow: x.TWindow;
+ begin
+ Old_Handler := XSetErrorHandler(@MufasaXErrorHandler);
+ if XGetWindowAttributes(display, window, @Attrib) <> 0 Then
+ begin
+ { I don't think we need this XTranslateCoordinates... :D }
+ XTranslateCoordinates(display, window, RootWindow(display, screennum), 0,0, @newx, @newy, @childwindow);
+ W := Attrib.Width;
+ H := Attrib.Height;
+ end else
+ begin
+ { TODO: Raise Exception because the Window does not exist? }
+ W := -1;
+ H := -1;
+ end;
+ XSetErrorHandler(Old_Handler);
+ end;
+
+ function TWindow.TargetValid: boolean;
+ var
+ old_handler: TXErrorHandler;
+ Attrib: TXWindowAttributes;
+ begin
+ old_handler := XSetErrorHandler(@MufasaXErrorHandler);
+ //This was in the repos, but it doesn't seem to work...
+ //Maybe I missed something?
+ result:= XGetWindowAttributes(display, window, @Attrib) <> 0;
+ XSetErrorHandler(old_handler);
+ end;
+
+ procedure TWindow.ActivateClient;
+ var
+ Old_Handler: TXErrorHandler;
+ begin
+ Old_Handler := XSetErrorHandler(@MufasaXErrorHandler);
+ { TODO: Check if Window is valid? }
+ XSetInputFocus(display,window,RevertToParent,CurrentTime);
+ XFlush(display);
+ XSetErrorHandler(Old_Handler);
+ end;
+
+ function TWindow.ReturnData(xs, ys, width, height: Integer): TRetData;
+ var
+ Old_Handler: TXErrorHandler;
+ w,h: integer;
+ begin
+ GetTargetDimensions(w,h);
+ if (xs < 0) or (xs + width > w) or (ys < 0) or (ys + height > h) then
+ raise Exception.CreateFMT('TMWindow.ReturnData: The parameters passed are wrong; xs,ys %d,%d width,height %d,%d',[xs,ys,width,height]);
+ if dirty then
+ raise Exception.CreateFmt('ReturnData was called again without freeing'+
+ ' the previously used data. Do not forget to'+
+ ' call FreeReturnData', []);
+ Old_Handler := XSetErrorHandler(@MufasaXErrorHandler);
+ buffer := XGetImage(display, window, xs, ys, width, height, AllPlanes, ZPixmap);
+ if buffer = nil then
+ begin
+ Writeln('ReturnData: XGetImage Error. Dumping data now:');
+ Writeln('xs, ys, width, height: ' + inttostr(xs) + ', ' + inttostr(ys) +
+ ', ' + inttostr(width) + ', ' + inttostr(height));
+ Result.Ptr := nil;
+ Result.IncPtrWith := 0;
+ XSetErrorHandler(Old_Handler);
+ raise Exception.CreateFMT('TMWindow.ReturnData: ReturnData: XGetImage Error', []);
+ exit;
+ end;
+ Result.Ptr := PRGB32(buffer^.data);
+ Result.IncPtrWith := 0;
+ Result.RowLen := width;
+ dirty:= true;
+ XSetErrorHandler(Old_Handler);
+ end;
+
+ procedure TWindow.FreeReturnData;
+ begin
+ if dirty then
+ begin
+ if (buffer <> nil) then
+ XDestroyImage(buffer);
+ buffer:= nil;
+ dirty:= false;
+ end;
+ end;
+
+ procedure TWindow.GetMousePosition(var x,y: integer);
+ var
+ b:integer;
+ root, child: twindow;
+ xmask: Cardinal;
+ Old_Handler: TXErrorHandler;
+ begin
+ Old_Handler := XSetErrorHandler(@MufasaXErrorHandler);
+ XQueryPointer(display,window,@root,@child,@b,@b,@x,@y,@xmask);
+ XSetErrorHandler(Old_Handler);
+ end;
+ procedure TWindow.MoveMouse(x,y: integer);
+ var
+ Old_Handler: TXErrorHandler;
+ w,h: integer;
+ begin
+ GetTargetDimensions(w, h);
+ if (x < 0) or (y < 0) or (x > w) or (y > h) then
+ raise Exception.CreateFmt('SetMousePos: X, Y (%d, %d) is not valid (0,0,%d,%d)', [x, y, w, h]);
+ Old_Handler := XSetErrorHandler(@MufasaXErrorHandler);
+ XWarpPointer(display, 0, window, 0, 0, 0, 0, X, Y);
+ XFlush(display);
+ XSetErrorHandler(Old_Handler);
+ end;
+ procedure TWindow.HoldMouse(x,y: integer; button: TClickType);
+ var
+ ButtonP: cuint;
+ _isPress: cbool;
+ Old_Handler: TXErrorHandler;
+ begin
+ Old_Handler := XSetErrorHandler(@MufasaXErrorHandler);
+ _isPress := cbool(1);
+ case button of
+ mouse_Left: ButtonP:= Button1;
+ mouse_Middle: ButtonP:= Button2;
+ mouse_Right: ButtonP:= Button3;
+ end;
+ XTestFakeButtonEvent(display, ButtonP, _isPress, CurrentTime);
+ XSetErrorHandler(Old_Handler);
+ end;
+ procedure TWindow.ReleaseMouse(x,y: integer; button: TClickType);
+ var
+ ButtonP: cuint;
+ _isPress: cbool;
+ Old_Handler: TXErrorHandler;
+ begin
+ Old_Handler := XSetErrorHandler(@MufasaXErrorHandler);
+ _isPress := cbool(0);
+ case button of
+ mouse_Left: ButtonP:= Button1;
+ mouse_Middle: ButtonP:= Button2;
+ mouse_Right: ButtonP:= Button3;
+ end;
+ XTestFakeButtonEvent(display, ButtonP, _isPress, CurrentTime);
+ XSetErrorHandler(Old_Handler);
+ end;
+
+ function GetSimpleKeyCode(c: char): word;
+ begin
+ case C of
+ '0'..'9' :Result := VK_0 + Ord(C) - Ord('0');
+ 'a'..'z' :Result := VK_A + Ord(C) - Ord('a');
+ 'A'..'Z' :Result := VK_A + Ord(C) - Ord('A');
+ ' ' : result := VK_SPACE;
+ else
+ Raise Exception.CreateFMT('GetSimpleKeyCode - char (%s) is not in A..z',[c]);
+ end
+ end;
+
+ procedure TWindow.SendString(str: string);
+ var
+ i: integer;
+ key: byte;
+ HoldShift : boolean;
+ begin
+ HoldShift := false;
+ for i := 1 to length(str) do
+ begin
+ if((str[i] >= 'A') and (str[i] <= 'Z')) then
+ begin
+ HoldKey(VK_SHIFT);
+ HoldShift:= True;
+ str[i] := lowerCase(str[i]);
+ end else
+ if HoldShift then
+ begin
+ HoldShift:= false;
+ ReleaseKey(VK_SHIFT);
+ end;
+ key:= GetSimpleKeyCode(str[i]);
+ HoldKey(key);
+ //BenLand100: You should probably wait here...
+ ReleaseKey(key);
+ end;
+ if HoldShift then
+ ReleaseKey(VK_SHIFT);
+ end;
+ procedure TWindow.HoldKey(key: integer);
+ begin
+ keyinput.Down(key);
+ end;
+ procedure TWindow.ReleaseKey(key: integer);
+ begin
+ keyinput.Up(key);
+ end;
+ function TWindow.IsKeyHeld(key: integer): boolean;
+ begin
+ raise Exception.CreateFmt('IsKeyDown isn''t implemented yet on Linux', []);
+ end;
+
+//***implementation*** IOManager
+
+ constructor TIOManager.Create;
+ begin
+ inherited Create;
+ end;
+
+ constructor TIOManager.Create(plugin_dir: string);
+ begin
+ inherited Create(plugin_dir);
+ end;
+
+ procedure TIOManager.NativeInit;
+ begin
+ display := XOpenDisplay(nil);
+ if display = nil then
+ begin
+ // throw Exception
+ end;
+ screennum:= DefaultScreen(display);
+ desktop:= RootWindow(display,screennum)
+ end;
+
+ procedure TIOManager.NativeFree;
+ begin
+ XCloseDisplay(display);
+ end;
+
+ procedure TIOManager.SetDesktop;
+ begin
+ SetBothTargets(TWindow.Create(display, screennum, desktop));
+ end;
+
+ function TIOManager.SetTarget(target: x.TWindow): integer;
+ begin
+ SetBothTargets(TWindow.Create(display, screennum, target))
+ end;
+
+end.
diff --git a/branches/script-component/Units/MMLCore/os_windows.pas b/branches/script-component/Units/MMLCore/os_windows.pas
new file mode 100644
index 0000000..79e4d17
--- /dev/null
+++ b/branches/script-component/Units/MMLCore/os_windows.pas
@@ -0,0 +1,346 @@
+{
+ This file is part of the Mufasa Macro Library (MML)
+ Copyright (c) 2009 by Raymond van Venetië and Merlijn Wajer
+
+ MML is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ MML is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with MML. If not, see .
+
+ See the file COPYING, included in this distribution,
+ for details about the copyright.
+
+ Windows OS specific implementation for Mufasa Macro Library
+}
+
+{$mode objfpc}{$H+}
+unit os_windows;
+
+interface
+
+ uses
+ Classes, SysUtils, mufasatypes, windows, graphics, LCLType, bitmaps, LCLIntf, IOManager, WinKeyInput;
+
+ type
+
+ TNativeWindow = Hwnd;
+
+ TKeyInput = class(TWinKeyInput)
+ public
+ procedure Down(Key: Word);
+ procedure Up(Key: Word);
+ end;
+
+ TWindow = class(TWindow_Abstract)
+ public
+ constructor Create(target: Hwnd);
+ destructor Destroy; override;
+ procedure GetTargetDimensions(var w, h: integer); override;
+ function ReturnData(xs, ys, width, height: Integer): TRetData; override;
+ function GetColor(x,y : integer) : TColor; override;
+
+ function TargetValid: boolean; override;
+ procedure ActivateClient; override;
+ procedure GetMousePosition(var x,y: integer); override;
+ procedure MoveMouse(x,y: integer); override;
+ procedure HoldMouse(x,y: integer; button: TClickType); override;
+ procedure ReleaseMouse(x,y: integer; button: TClickType); override;
+
+ procedure SendString(str: string); override;
+ procedure HoldKey(key: integer); override;
+ procedure ReleaseKey(key: integer); override;
+ function IsKeyHeld(key: integer): boolean; override;
+ private
+ handle: Hwnd;
+ dc: HDC;
+ buffer: TBitmap;
+ buffer_raw: prgb32;
+ width,height: integer;
+ keyinput: TKeyInput;
+ procedure ValidateBuffer(w,h:integer);
+ end;
+
+ TIOManager = class(TIOManager_Abstract)
+ public
+ constructor Create;
+ constructor Create(plugin_dir: string);
+ function SetTarget(target: Hwnd): integer; overload;
+ procedure SetDesktop; override;
+ protected
+ DesktopHWND : Hwnd;
+ procedure NativeInit; override;
+ procedure NativeFree; override;
+ end;
+
+implementation
+
+ uses GraphType, interfacebase;
+
+ type
+ PMouseInput = ^TMouseInput;
+ tagMOUSEINPUT = packed record
+ dx: Longint;
+ dy: Longint;
+ mouseData: DWORD;
+ dwFlags: DWORD;
+ time: DWORD;
+ dwExtraInfo: DWORD;
+ end;
+ TMouseInput = tagMOUSEINPUT;
+
+ PKeybdInput = ^TKeybdInput;
+ tagKEYBDINPUT = packed record
+ wVk: WORD;
+ wScan: WORD;
+ dwFlags: DWORD;
+ time: DWORD;
+ dwExtraInfo: DWORD;
+ end;
+ TKeybdInput = tagKEYBDINPUT;
+
+ PHardwareInput = ^THardwareInput;
+ tagHARDWAREINPUT = packed record
+ uMsg: DWORD;
+ wParamL: WORD;
+ wParamH: WORD;
+ end;
+ THardwareInput = tagHARDWAREINPUT;
+ PInput = ^TInput;
+ tagINPUT = packed record
+ Itype: DWORD;
+ case Integer of
+ 0: (mi: TMouseInput);
+ 1: (ki: TKeybdInput);
+ 2: (hi: THardwareInput);
+ end;
+ TInput = tagINPUT;
+
+ const
+ INPUT_MOUSE = 0;
+ INPUT_KEYBOARD = 1;
+ INPUT_HARDWARE = 2;
+
+ function SendInput(cInputs: UINT; var pInputs: TInput; cbSize: Integer): UINT; stdcall; external user32 name 'SendInput';
+
+//***implementation*** TKeyInput
+
+ procedure TKeyInput.Down(Key: Word);
+ begin
+ DoDown(Key);
+ end;
+
+ procedure TKeyInput.Up(Key: Word);
+ begin
+ DoUp(Key);
+ end;
+
+//***implementation*** TWindow
+
+ constructor TWindow.Create(target: Hwnd); begin
+ inherited Create;
+ self.handle:= target;
+ self.dc:= GetWindowDC(target);
+ self.buffer:= TBitmap.Create;
+ self.buffer.PixelFormat:= pf32bit;
+ keyinput:= TKeyInput.Create;
+ end;
+
+ destructor TWindow.Destroy; begin
+ ReleaseDC(handle,dc);
+ buffer.Free;
+ keyinput.Free;
+ inherited Destroy;
+ end;
+
+ function TWindow.TargetValid: boolean;
+ begin
+ result:= IsWindow(handle);
+ end;
+
+ procedure TWindow.ActivateClient;
+ begin
+ SetForegroundWindow(handle);
+ end;
+
+ procedure TWindow.GetTargetDimensions(var w, h: integer);
+ var
+ Rect : TRect;
+ begin
+ GetWindowRect(handle, Rect);
+ w:= Rect.Right - Rect.Left;
+ h:= Rect.Bottom - Rect.Top;
+ end;
+
+ function TWindow.GetColor(x,y : integer) : TColor;
+ begin
+ result:= GetPixel(self.dc,x,y)
+ end;
+
+ procedure TWindow.ValidateBuffer(w,h:integer);
+ var
+ BmpInfo : Windows.TBitmap;
+ begin
+ if (w <> self.width) or (height <> self.height) then
+ begin
+ buffer.SetSize(w,h);
+ self.width:= w;
+ self.height:= h;
+ GetObject(buffer.Handle, SizeOf(BmpInfo), @BmpInfo);
+ self.buffer_raw := BmpInfo.bmBits;
+ end;
+ end;
+
+ function TWindow.ReturnData(xs, ys, width, height: Integer): TRetData;
+ var
+ temp: PRGB32;
+ w,h : integer;
+ begin
+ GetTargetDimensions(w,h);
+ ValidateBuffer(w,h);
+ if (xs < 0) or (xs + width > w) or (ys < 0) or (ys + height > h) then
+ raise Exception.CreateFMT('TMWindow.ReturnData: The parameters passed are wrong; xs,ys %d,%d width,height %d,%d',[xs,ys,width,height]);
+ BitBlt(self.buffer.Canvas.Handle,0,0, width, height, self.dc, xs,ys, SRCCOPY);
+ Result.Ptr:= self.buffer_raw;
+ Result.IncPtrWith:= w - width;
+ Result.RowLen:= w;
+ end;
+
+ procedure TWindow.GetMousePosition(var x,y: integer);
+ var
+ MousePoint : TPoint;
+ Rect : TRect;
+ begin
+ Windows.GetCursorPos(MousePoint);
+ GetWindowRect(handle,Rect);
+ x := MousePoint.x - Rect.Left;
+ y := MousePoint.y - Rect.Top;
+ end;
+ procedure TWindow.MoveMouse(x,y: integer);
+ var
+ rect : TRect;
+ w,h: integer;
+ begin
+ GetWindowRect(handle, Rect);
+ x := x + rect.left;
+ y := y + rect.top;
+ if (x<0) or (y<0) then
+ writeln('Negative coords, what now?');
+ Windows.SetCursorPos(x, y);
+ end;
+ procedure TWindow.HoldMouse(x,y: integer; button: TClickType);
+ var
+ Input : TInput;
+ Rect : TRect;
+ begin
+ GetWindowRect(handle, Rect);
+ Input.Itype:= INPUT_MOUSE;
+ FillChar(Input,Sizeof(Input),0);
+ Input.mi.dx:= x + Rect.left;
+ Input.mi.dy:= y + Rect.Top;
+ case button of
+ Mouse_Left: Input.mi.dwFlags:= MOUSEEVENTF_ABSOLUTE or MOUSEEVENTF_LEFTDOWN;
+ Mouse_Middle: Input.mi.dwFlags:= MOUSEEVENTF_ABSOLUTE or MOUSEEVENTF_MIDDLEDOWN;
+ Mouse_Right: Input.mi.dwFlags:= MOUSEEVENTF_ABSOLUTE or MOUSEEVENTF_RIGHTDOWN;
+ end;
+ SendInput(1,Input, sizeof(Input));
+ end;
+ procedure TWindow.ReleaseMouse(x,y: integer; button: TClickType);
+ var
+ Input : TInput;
+ Rect : TRect;
+ begin
+ GetWindowRect(handle, Rect);
+ Input.Itype:= INPUT_MOUSE;
+ FillChar(Input,Sizeof(Input),0);
+ Input.mi.dx:= x + Rect.left;
+ Input.mi.dy:= y + Rect.Top;
+ case button of
+ Mouse_Left: Input.mi.dwFlags:= MOUSEEVENTF_ABSOLUTE or MOUSEEVENTF_LEFTUP;
+ Mouse_Middle: Input.mi.dwFlags:= MOUSEEVENTF_ABSOLUTE or MOUSEEVENTF_MIDDLEUP;
+ Mouse_Right: Input.mi.dwFlags:= MOUSEEVENTF_ABSOLUTE or MOUSEEVENTF_RIGHTUP;
+ end;
+ SendInput(1,Input, sizeof(Input));
+ end;
+
+ procedure TWindow.SendString(str: string);
+ var
+ i: integer;
+ key: byte;
+ HoldShift : boolean;
+ begin
+ HoldShift := false;
+ for i := 1 to length(str) do
+ begin
+ if((str[i] >= 'A') and (str[i] <= 'Z')) then
+ begin
+ HoldKey(VK_SHIFT);
+ HoldShift:= True;
+ str[i] := lowerCase(str[i]);
+ end else
+ if HoldShift then
+ begin
+ HoldShift:= false;
+ ReleaseKey(VK_SHIFT);
+ end;
+ key:= VkKeyScan(str[i]) and $FF;
+ HoldKey(key);
+ //BenLand100 note: probably should wait here
+ ReleaseKey(key);
+ end;
+ if HoldShift then
+ ReleaseKey(VK_SHIFT);
+ end;
+ procedure TWindow.HoldKey(key: integer);
+ begin
+ keyinput.Down(key);
+ end;
+ procedure TWindow.ReleaseKey(key: integer);
+ begin
+ keyinput.Up(key);
+ end;
+ function TWindow.IsKeyHeld(key: integer): boolean;
+ begin
+ raise Exception.CreateFmt('IsKeyHeld isn''t implemented yet on Windows', []);
+ end;
+
+
+//***implementation*** IOManager
+
+ constructor TIOManager.Create;
+ begin
+ inherited Create;
+ end;
+
+ constructor TIOManager.Create(plugin_dir: string);
+ begin
+ inherited Create(plugin_dir);
+ end;
+
+ procedure TIOManager.NativeInit;
+ begin
+ self.DesktopHWND:= GetDesktopWindow;
+ end;
+
+ procedure TIOManager.NativeFree;
+ begin
+ end;
+
+ procedure TIOManager.SetDesktop;
+ begin
+ SetBothTargets(TWindow.Create(DesktopHWND));
+ end;
+
+ function TIOManager.SetTarget(target: Hwnd): integer;
+ begin
+ SetBothTargets(TWindow.Create(target));
+ end;
+
+end.
diff --git a/branches/script-component/Units/MMLCore/tpa.pas b/branches/script-component/Units/MMLCore/tpa.pas
new file mode 100644
index 0000000..395d29e
--- /dev/null
+++ b/branches/script-component/Units/MMLCore/tpa.pas
@@ -0,0 +1,1711 @@
+{
+ This file is part of the Mufasa Macro Library (MML)
+ Copyright (c) 2009 by Raymond van Venetië and Merlijn Wajer
+
+ MML is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ MML is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with MML. If not, see .
+
+ See the file COPYING, included in this distribution,
+ for details about the copyright.
+
+ TPA functions for the Mufasa Macro Library
+}
+unit tpa;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+ Classes, SysUtils, mufasatypes;
+
+function FastTPASort(TPA: TPointArray; Dists: TIntegerArray; maxDist: Integer; CloseFirst: Boolean): TPointArray;
+
+//Start Wizzyplugin
+procedure tSwap(var a, b: TPoint);
+procedure tpaSwap(var a, b: TPointArray);
+procedure SwapE(var a, b: Extended);
+procedure RAaSTPAEx(var a: TPointArray; const w, h: Integer);
+procedure RAaSTPA(var a: TPointArray; const Dist: Integer);
+function NearbyPointInArrayEx(const P: TPoint; w, h:Integer; a: TPointArray): Boolean;
+function NearbyPointInArray(const P: TPoint; Dist:Integer; a: TPointArray): Boolean;
+function ReArrangeandShortenArrayEx(a: TPointArray; w, h: Integer): TPointArray;
+function ReArrangeandShortenArray(a: TPointArray; Dist: Integer): TPointArray;
+function TPAtoATPAEx(TPA: TPointArray; w, h: Integer): T2DPointArray;
+function TPAtoATPA(TPA: TPointArray; Dist: Integer): T2DPointArray;
+procedure QuickTPASort(var A: TIntegerArray; var B: TPointArray; iLo, iHi: Integer; SortUp: Boolean);
+procedure QuickATPASort(var A: TIntegerArray; var B: T2DPointArray; iLo, iHi: Integer; SortUp: Boolean);
+procedure SortTPAFrom(var a: TPointArray; const From: TPoint);
+procedure SortATPAFrom(var a: T2DPointArray; const From: TPoint);
+procedure SortATPAFromFirstPoint(var a: T2DPointArray; const From: TPoint);
+procedure InvertTPA(var a: TPointArray);
+procedure InvertATPA(var a: T2DPointArray);
+function MiddleTPAEx(TPA: TPointArray; var x, y: Integer): Boolean;
+function MiddleTPA(tpa: TPointArray): TPoint;
+procedure SortATPASize(var a: T2DPointArray; const BigFirst: Boolean);
+procedure SortATPAFromSize(var a: T2DPointArray; const Size: Integer; CloseFirst: Boolean);
+function CombineTPA(Ar1, Ar2: TPointArray): TPointArray;
+function CombineIntArray(Ar1, Ar2: TIntegerArray): TIntegerArray;
+function InIntArrayEx(a: TIntegerArray; var Where: Integer; const Number: Integer): Boolean;
+function InIntArray(a: TIntegerArray; Number: Integer): Boolean;
+procedure ClearSameIntegers(var a: TIntegerArray);
+procedure ClearSameIntegersAndTPA(var a: TIntegerArray; var p: TPointArray);
+function SplitTPAEx(arr: TPointArray; w, h: Integer): T2DPointArray;
+function SplitTPA(arr: TPointArray; Dist: Integer): T2DPointArray;
+procedure FilterPointsPie(var Points: TPointArray; const SD, ED, MinR, MaxR: Extended; Mx, My: Integer);
+function RemoveDistTPointArray(x, y, dist: Integer; ThePoints: TPointArray; RemoveHigher: Boolean): TPointArray;
+function GetATPABounds(ATPA: T2DPointArray): TBox;
+function GetTPABounds(TPA: TPointArray): TBox;
+function FindTPAinTPA(SearchTPA, TotalTPA: TPointArray; var Matches: TPointArray): Boolean;
+function FindTextTPAinTPA(Height : integer; SearchTPA, TotalTPA: TPointArray; var Matches: TPointArray): Boolean;
+function FindGapsTPA(TPA: TPointArray; MinPixels: Integer): T2DPointArray;
+procedure SortCircleWise(var tpa: TPointArray; const cx, cy, StartDegree: Integer; SortUp, ClockWise: Boolean);
+procedure LinearSort(var tpa: TPointArray; cx, cy, sd: Integer; SortUp: Boolean);
+Function MergeATPA(ATPA : T2DPointArray) : TPointArray;
+function TPAFromBox(const Box : TBox) : TPointArray;
+Function RotatePoints(Const P: TPointArray; A, cx, cy: Extended): TPointArray ;
+Function RotatePoint(Const p: TPoint; angle, mx, my: Extended): TPoint; inline;
+function FindTPAEdges(p: TPointArray): TPointArray;
+function PointInTPA(p: TPoint; arP: TPointArray): Boolean;
+function ClearTPAFromTPA(arP, ClearPoints: TPointArray): TPointArray;
+procedure ClearDoubleTPA(var TPA: TPointArray);
+Function ReturnPointsNotInTPA(Const TotalTPA: TPointArray; const Box: TBox): TPointArray;
+Procedure TPACountSort(Var TPA: TPointArray;const max: TPoint;Const SortOnX : Boolean);
+Procedure TPACountSortBase(Var TPA: TPointArray;const maxx, base: TPoint; const SortOnX : Boolean);
+procedure InvertTIA(var tI: TIntegerArray);
+function SumIntegerArray(Ints : TIntegerArray): Integer;
+function AverageTIA(tI: TIntegerArray): Integer;
+function AverageExtended(tE: TExtendedArray): Extended;
+
+implementation
+
+uses
+ math;
+
+
+
+
+{/\
+ Very Fast TPA Sort, uses an adepted CountSort algorithm.
+/\}
+
+Function FastTPASort(TPA: TPointArray; Dists: TIntegerArray; maxDist: Integer; CloseFirst: Boolean): TPointArray;
+
+{
+ If you want to understand this algorithm, it might be helpful to read about
+ CountSort. This algorithm is quite similar to CountSort.
+}
+
+Var
+ Oc, D: TIntegerArray;
+ I, H, J: Integer;
+ ind: array of array of integer;
+
+Begin
+ SetLength(Oc, maxDist + 1); // Oc stores the occurances of each distance.
+ H := High(Dists); // The amount of values in the given Array of Points...
+ // We store it instead of calling High(Dists) each time.
+
+ // Get the occurance of each distance, and store it in Oc.
+ // We need the occurances of each distance, so we can later on set the 2d Array
+ // to it's proper length.
+ For I := 0 To H Do
+ Oc[Dists[I]] := Oc[Dists[I]] + 1;
+
+ // What we are basically going to do now is the following:
+ // Sort the points by their distances using countsort.
+ // But because (-2, -2) and (2, 2) have the same distance from (0, 0), we also
+ // store the index in the array 'TPA', which contains the actual points.
+ // This way we can retreive the actuals points.
+
+ // D nothing but a counter. It contains the amount of points (indices) stored
+ // for EACH distance, so it's length is equal to the amount of Distances.
+ // ind is the array that has as first index the Distance. The second depth of
+ // the array is the index which is used to retreive the original point.
+
+ SetLength(D, maxDist + 1);
+ SetLength(ind, maxDist + 1);
+ For I := 0 To maxDist Do // set the ind length of each ind[distance] to Oc[distance]
+ SetLength(ind[i], Oc[i] + 1);
+ For I := 0 To H Do // Performs the actual index sorting
+ Begin
+ // put an index (of Dists AND TPA) into a distance array.
+ ind[Dists[I]][D[Dists[I]]] := I;
+ // inc by one, so we won't override previous indexes.
+ D[Dists[i]] := D[Dists[i]] + 1;
+ End;
+
+ // Here we are back to the CountSort style of writing back.
+ // Now we are going to write back to the Result.
+ // The Result's length is obviously of the same length as 'TPA'.
+ SetLength(Result, H + 1);
+ H := 0;
+
+ // CloseFirst just means: Start writing from dist 0 to maxDist, or
+ // start writing from maxDist to dist 0. The first one places the closest points
+ // at the start of the result. The higher the index, the more far away the point.
+ // Not Closefirst means put the most far away point in Result first.
+ If CloseFirst Then
+ Begin
+ For I := 0 To maxDist Do // Put back to result
+ For J := 0 To oC[I] - 1 Do
+ Begin
+ Result[H] := TPA[ind[I][J]];
+ H := H + 1;
+ End;
+ End
+ Else
+ For I := maxDist Downto 0 Do // Put back to result
+ For J := 0 To oC[I] - 1 Do
+ Begin
+ Result[H] := TPA[ind[I][J]];
+ H := H + 1;
+ End;
+ // Voila!
+End;
+
+const
+ flnC=545947;
+ fsqrtA:single=0.5;
+
+{$ASMMODE INTEL}
+function fsqrt(x: Single): Single;
+begin
+ asm
+ sub dword ptr x, ($3F800000-flnC)
+ fild dword ptr x
+ fmul fsqrtA
+ fistp dword ptr x
+ add dword ptr x,($3F800000-flnC)
+ fld x
+ end;
+end;
+
+procedure tSwap(var a, b: TPoint);
+var
+ c: TPoint;
+begin
+ c := a;
+ a := b;
+ b := c;
+end;
+
+procedure tpaSwap(var a, b: TPointArray);
+var
+ c: TPointArray;
+begin
+ c := a;
+ a := b;
+ b := c;
+end;
+
+procedure SwapE(var a, b: Extended);
+var
+ c: extended;
+begin
+ c := a;
+ a := b;
+ b := c;
+end;
+
+{/\
+ Leaves one point per box with side lengths W and H to the TPA.
+/\}
+
+procedure RAaSTPAEx(var a: TPointArray; const w, h: Integer);
+var
+ i, c, NoTP, l: Integer;
+ t: TPoint;
+begin
+ NoTP := 0;
+ l := High(a);
+ for i := 0 to l do
+ begin
+ for c := 0 to NoTP - 1 do
+ if (Abs(a[i].x - a[c].x) <= w) and (Abs(a[i].y - a[c].y) <= h) then
+ Break;
+ if (c >= NoTP) then
+ begin
+ t := a[i];
+ a[i] := a[NoTP];
+ a[NoTP] := t;
+ Inc(NoTP);
+ end;
+ end;
+ SetLength(a, NoTP);
+end;
+
+{/\
+ Leaves one point per box with the side length Dist.
+/\}
+
+procedure RAaSTPA(var a: TPointArray; const Dist: Integer);
+var
+ i, c, NoTP, l: Integer;
+ t: TPoint;
+begin
+ NoTP := 0;
+ l := High(a);
+ for i := 0 to l do
+ begin
+ for c := 0 to NoTP - 1 do
+ if (Round(fSqrt(Sqr(a[i].x - a[c].x) + Sqr(a[i].y - a[c].y))) <= Dist) then
+ Break;
+ if (c >= NoTP) then
+ begin
+ t := a[i];
+ a[i] := a[NoTP];
+ a[NoTP] := t;
+ Inc(NoTP);
+ end;
+ end;
+ SetLength(a, NoTP);
+end;
+
+{/\
+ Returns true if the point P is near a point in the TPA a with the max X and Y distances W and H.
+/\}
+
+function NearbyPointInArrayEx(const P: TPoint; w, h:Integer; a: TPointArray): Boolean;
+var
+ i, l: Integer;
+begin
+ Result := False;
+ l := High(a);
+ for i := 0 to l do
+ if (Abs(P.x - a[i].x) <= w) and (Abs(P.y - a[i].y) <= h) then
+ begin
+ Result := True;
+ Exit;
+ end;
+end;
+
+{/\
+ Returns true if the point P is near a point in the TPA a with the max distance Dist.
+/\}
+
+function NearbyPointInArray(const P: TPoint; Dist:Integer; a: TPointArray): Boolean;
+var
+ i, l: Integer;
+begin
+ Result := False;
+ l := High(a);
+ for i := 0 to l do
+ if (Round(fSqrt(Sqr(P.x - a[i].x) + Sqr(P.y - a[i].y))) <= Dist) then
+ begin
+ Result := True;
+ Exit;
+ end;
+end;
+
+{/\
+ Results the TPointArray a with one point per box with side lengths W and H left.
+/\}
+
+function ReArrangeandShortenArrayEx(a: TPointArray; w, h: Integer): TPointArray;
+var
+ i, t, c, l: Integer;
+begin
+ l := High(a);
+ c := 0;
+ SetLength(Result, l + 1);
+ for i := 0 to l do
+ begin
+ for t := 0 to c -1 do
+ if (Abs(Result[t].x - a[i].x) <= w) and (Abs(Result[t].y - a[i].y) <= h) then
+ Break;
+ if (t >= c) then
+ begin
+ Result[c] := a[i];
+ Inc(c);
+ end;
+ end;
+ SetLength(Result, c);
+end;
+
+{/\
+ Results the TPointArray a with one point per box with side length Dist left.
+/\}
+
+function ReArrangeandShortenArray(a: TPointArray; Dist: Integer): TPointArray;
+var
+ i, t, c, l: Integer;
+begin
+ l := High(a);
+ c := 0;
+ SetLength(Result, l + 1);
+ for i := 0 to l do
+ begin
+ for t := 0 to c -1 do
+ if (Round(fSqrt(Sqr(Result[t].x - a[i].x) + Sqr(Result[t].y - a[i].y))) <= Dist) then
+ Break;
+ if (t >= c) then
+ begin
+ Result[c] := a[i];
+ Inc(c);
+ end;
+ end;
+ SetLength(Result, c);
+end;
+
+{/\
+ Splits the TPA to boxes with sidelengths W and H and results them as a T2DPointArray.
+/\}
+
+function TPAtoATPAEx(TPA: TPointArray; w, h: Integer): T2DPointArray;
+var
+ a, b, c, l: LongInt;
+begin
+ SetLength(Result, 0);
+ l := High(TPA);
+ c := 0;
+ for a := 0 to l do
+ begin
+ for b := 0 to c -1 do
+ if (Abs(TPA[a].X - Result[b][0].X) <= w) and (Abs(TPA[a].Y - Result[b][0].Y) <= h) then
+ Break;
+ if (b < c) then
+ begin
+ SetLength(Result[b], Length(Result[b]) + 1);
+ Result[b][High(Result[b])] := TPA[a];
+ end else
+ begin
+ SetLength(Result, c + 1);
+ SetLength(Result[c], 1);
+ Result[c][0] := TPA[a];
+ Inc(c);
+ end;
+ end;
+end;
+
+{/\
+ Splits the TPA to boxes with sidelength Dist and results them as a T2DPointArray.
+/\}
+
+function TPAtoATPA(TPA: TPointArray; Dist: Integer): T2DPointArray;
+var
+ a, b, c, l: LongInt;
+begin
+ SetLength(Result, 0);
+ l := High(tpa);
+ c := 0;
+ for a := 0 to l do
+ begin
+ for b := 0 to c -1 do
+ if (Round(fSqrt(Sqr(TPA[a].X - Result[b][0].X) + Sqr(TPA[a].Y - Result[b][0].Y))) <= Dist) then
+ Break;
+ if (b < c) then
+ begin
+ SetLength(Result[b], Length(Result[b]) + 1);
+ Result[b][High(Result[b])] := TPA[a];
+ end else
+ begin
+ SetLength(Result, c + 1);
+ SetLength(Result[c], 1);
+ Result[c][0] := TPA[a];
+ Inc(c);
+ end;
+ end;
+end;
+
+{/\
+ Sorts the given TPointArray.
+/\}
+
+procedure QuickTPASort(var A: TIntegerArray; var B: TPointArray; iLo, iHi: Integer; SortUp: Boolean);
+var
+ Lo, Hi, Mid, T: Integer;
+ TP: TPoint;
+begin
+ if (Length(A) <> Length(B)) then Exit;
+ Lo := iLo;
+ Hi := iHi;
+ Mid := A[(Lo + Hi) shr 1];
+ repeat
+ if SortUp then
+ begin
+ while (A[Lo] < Mid) do Inc(Lo);
+ while (A[Hi] > Mid) do Dec(Hi);
+ end else
+ begin
+ while (A[Lo] > Mid) do Inc(Lo);
+ while (A[Hi] < Mid) do Dec(Hi);
+ end;
+ if (Lo <= Hi) then
+ begin
+ T := A[Lo];
+ A[Lo] := A[Hi];
+ A[Hi] := T;
+ TP := B[Lo];
+ B[Lo] := B[Hi];
+ B[Hi] := TP;
+ Inc(Lo);
+ Dec(Hi);
+ end;
+ until Lo > Hi;
+ if (Hi > iLo) then QuickTPASort(A, B, iLo, Hi, SortUp);
+ if (Lo < iHi) then QuickTPASort(A, B, Lo, iHi, SortUp);
+end;
+
+{/\
+ Sorts the given T2DPointArray.
+/\}
+
+procedure QuickATPASort(var A: TIntegerArray; var B: T2DPointArray; iLo, iHi: Integer; SortUp: Boolean);
+var
+ Lo, Hi, Mid, T: Integer;
+ TP: TPointArray;
+begin
+ if (Length(A) <> Length(B)) then Exit;
+ Lo := iLo;
+ Hi := iHi;
+ Mid := A[(Lo + Hi) shr 1];
+ repeat
+ if SortUp then
+ begin
+ while (A[Lo] < Mid) do Inc(Lo);
+ while (A[Hi] > Mid) do Dec(Hi);
+ end else
+ begin
+ while (A[Lo] > Mid) do Inc(Lo);
+ while (A[Hi] < Mid) do Dec(Hi);
+ end;
+ if (Lo <= Hi) then
+ begin
+ T := A[Lo];
+ A[Lo] := A[Hi];
+ A[Hi] := T;
+ TP := B[Lo];
+ B[Lo] := B[Hi];
+ B[Hi] := TP;
+ Inc(Lo);
+ Dec(Hi);
+ end;
+ until Lo > Hi;
+ if (Hi > iLo) then QuickATPASort(A, B, iLo, Hi, SortUp);
+ if (Lo < iHi) then QuickATPASort(A, B, Lo, iHi, SortUp);
+end;
+
+{/\
+ Sorts the TPointArray a from the point From.
+ Closest one to the point is [0], second closest is [1] etc.
+/\}
+
+procedure SortTPAFrom(var a: TPointArray; const From: TPoint);
+var
+ i, l: Integer;
+ DistArr: TIntegerArray;
+begin
+ l := High(a);
+ if (l < 0) then Exit;
+ SetLength(DistArr, l + 1);
+ for i := 0 to l do
+ DistArr[i] := Round(Sqr(From.x - a[i].x) + Sqr(From.y - a[i].y));
+ QuickTPASort(DistArr, a, 0, l, True);
+end;
+
+{/\
+ Sorts the T2DPointArray a from the point From.
+/\}
+
+procedure SortATPAFrom(var a: T2DPointArray; const From: TPoint);
+var
+ i, l: Integer;
+begin
+ l := High(a);
+ if (l < 0) then Exit;
+ for i := 0 to l do
+ SortTPAFrom(a[i], From);
+end;
+
+{/\
+ Sorts the T2DPointArray a from the point From.
+/\}
+
+procedure SortATPAFromFirstPoint(var a: T2DPointArray; const From: TPoint);
+var
+ i, l: Integer;
+ DistArr: TIntegerArray;
+begin
+ l := High(a);
+ if (l < 0) then Exit;
+ SetLength(DistArr, l + 1);
+ for i := 0 to l do
+ DistArr[i] := Round(Sqr(From.x - a[i][0].x) + Sqr(From.y - a[i][0].y));
+ QuickATPASort(DistArr, a, 0, l, True);
+end;
+
+{/\
+ Inverts / Reverses the TPointArray a.
+/\}
+
+procedure InvertTPA(var a: TPointArray);
+var
+ i, l: Integer;
+ b: tpointarray;
+begin
+ l := High(a);
+ if (l < 0) then Exit;
+ b := Copy(a);
+ for i := l downto 0 Do
+ a[l - i] := b[i];
+end;
+
+{/\
+ Inverts / Reverts the T2DPointArray a.
+/\}
+
+procedure InvertATPA(var a: T2DPointArray);
+var
+ i, l: Integer;
+ b: T2DPointArray;
+begin
+ l := High(a);
+ if (l < 0) then Exit;
+ b := Copy(a);
+ for i := l downto 0 do
+ a[l - i] := b[i];
+end;
+
+{/\
+ Stores the coordinates of the middle of the TPointArray a to X and Y.
+/\}
+
+function MiddleTPAEx(TPA: TPointArray; var x, y: Integer): Boolean;
+var
+ i, l: Integer;
+begin
+ Result := False;
+ l := High(tpa);
+ if (l < 0) then Exit;
+ x := 0;
+ y := 0;
+ for i := 0 to l do
+ begin
+ x := x + tpa[i].x;
+ y := y + tpa[i].y;
+ end;
+ x := x div (l + 1);
+ y := y div (l + 1);
+ Result := True;
+end;
+
+{/\
+ Returns the middle of the TPointArray tpa.
+/\}
+
+function MiddleTPA(tpa: TPointArray): TPoint;
+var
+ i, l: Integer;
+begin
+ l := High(tpa);
+ if (l < 0) then Exit;
+ Result.x := 0;
+ Result.y := 0;
+ for i := 0 to l do
+ begin
+ Result.x := Result.x + tpa[i].x;
+ Result.y := Result.y + tpa[i].y;
+ end;
+ Result.x := Result.x div (l + 1);
+ Result.y := Result.y div (l + 1);
+end;
+
+{/\
+ Sorts the T2DPointArray a from either largest or smallest, by the amount of points in the TPAs.
+/\}
+
+procedure SortATPASize(var a: T2DPointArray; const BigFirst: Boolean);
+var
+ i, l: Integer;
+ SizeArr: TIntegerArray;
+begin
+ l := High(a);
+ if (l < 0) then Exit;
+ SetLength(SizeArr, l + 1);
+ for i := 0 to l do
+ SizeArr[i] := Length(a[i]);
+ QuickATPASort(SizeArr, a, 0, l, not BigFirst);
+end;
+
+{/\
+ Combines the TPointArrays Ar1 and Ar2, and results the combination.
+/\}
+
+procedure SortATPAFromSize(var a: T2DPointArray; const Size: Integer; CloseFirst: Boolean);
+var
+ i, l: Integer;
+ SizeArr: TIntegerArray;
+begin
+ l := High(a);
+ if (l < 0) then Exit;
+ SetLength(SizeArr, l + 1);
+ for i := 0 to l do
+ SizeArr[i] := Abs(Length(a[i]) - Size);
+ QuickATPASort(SizeArr, a, 0, l, CloseFirst);
+end;
+
+{/\
+ Combines the TPointArrays Ar1 and Ar2, and results the combination.
+/\}
+
+function CombineTPA(Ar1, Ar2: TPointArray): TPointArray;
+var
+ i, l1, l2: Integer;
+begin
+ Result := Copy(Ar1);
+ l1 := Length(Result);
+ l2 := Length(Ar2);
+ SetLength(Result, l1 + l2);
+ for i := 0 to l2 -1 do
+ Result[i + l1] := Ar2[i];
+end;
+
+{/\
+ Combines the TIntegerArrays Ar1 and Ar2, and results the combination.
+/\}
+
+function CombineIntArray(Ar1, Ar2: TIntegerArray): TIntegerArray;
+var
+ i, l1, l2: Integer;
+begin
+ Result := Copy(Ar1);
+ l1 := Length(Result);
+ l2 := Length(Ar2);
+ SetLength(Result, l1 + l2);
+ for i := 0 to l2 -1 do
+ Result[i + l1] := Ar2[i];
+end;
+
+{/\
+ Returns true if the integer Number was found in the integer array a, and stores the index to Where.
+/\}
+
+function InIntArrayEx(a: TIntegerArray; var Where: Integer; const Number: Integer): Boolean;
+var
+ i, l: Integer;
+begin
+ Result := False;
+ l := High(a);
+ for i := 0 to l do
+ if (a[i] = Number) then
+ begin
+ Where := i;
+ Result := True;
+ Exit;
+ end;
+end;
+
+{/\
+ Returns true if the integer Number was found in the integer array a.
+/\}
+
+function InIntArray(a: TIntegerArray; Number: Integer): Boolean;
+var
+ i, l: Integer;
+begin
+ Result := False;
+ l := High(a);
+ for i := 0 to l do
+ if (a[i] = Number) then
+ begin
+ Result := True;
+ Exit;
+ end;
+end;
+
+{/\
+ Clears the duplicates in the integer array a.
+/\}
+
+procedure ClearSameIntegers(var a: TIntegerArray);
+var
+ i, t, c, l: Integer;
+ b: TIntegerArray;
+begin
+ b := Copy(a);
+ l := High(b);
+ c := 0;
+ for i := 0 to l do
+ begin
+ for t := 0 to c -1 do
+ if (b[i] = a[t]) then
+ Break;
+ if (t >= c) then
+ begin
+ a[c] := b[i];
+ Inc(c);
+ end;
+ end;
+ SetLength(a, c);
+end;
+
+{/\
+ Clears the duplicates in the integer array a and the TPointArray p.
+/\}
+
+procedure ClearSameIntegersAndTPA(var a: TIntegerArray; var p: TPointArray);
+var
+ i, t, c, l: Integer;
+ b: TIntegerArray;
+begin
+ b := Copy(a);
+ l := High(b);
+ c := 0;
+ for i := 0 to l do
+ begin
+ for t := 0 to c -1 do
+ if (b[i] = a[t]) then
+ Break;
+ if (t >= c) then
+ begin
+ SetLength(a, c +1);
+ a[c] := b[i];
+ p[c] := p[i];
+ Inc(c);
+ end;
+ end;
+ SetLength(p, c);
+ SetLength(a, c);
+end;
+
+{/\
+ Splits the points with max X and Y distances W and H to their own TPointArrays.
+/\}
+
+function SplitTPAEx(arr: TPointArray; w, h: Integer): T2DPointArray;
+var
+ t1, t2, c, ec, tc, l: Integer;
+ tpa: TPointArray;
+begin
+ tpa := Copy(arr);
+ l := High(tpa);
+ if (l < 0) then Exit;
+ SetLength(Result, l + 1);
+ c := 0;
+ ec := 0;
+ while ((l - ec) >= 0) do
+ begin
+ SetLength(Result[c], 1);
+ Result[c][0] := tpa[0];
+ tpa[0] := tpa[l - ec];
+ Inc(ec);
+ tc := 1;
+ t1 := 0;
+ while (t1 < tc) do
+ begin
+ t2 := 0;
+ while (t2 <= (l - ec)) do
+ begin
+ if (Abs(Result[c][t1].x - tpa[t2].x) <= w) and (Abs(Result[c][t1].y - tpa[t2].y) <= h) then
+ begin
+ SetLength(Result[c], tc +1);
+ Result[c][tc] := tpa[t2];
+ tpa[t2] := tpa[l - ec];
+ Inc(ec);
+ Inc(tc);
+ Dec(t2);
+ end;
+ Inc(t2);
+ end;
+ Inc(t1);
+ end;
+ Inc(c);
+ end;
+ SetLength(Result, c);
+end;
+
+{/\
+ Splits the points with max distance Dist to their own TPointArrays.
+ Dist 1 puts the points that are next to eachother to their own arrays.
+/\}
+
+function SplitTPA(arr: TPointArray; Dist: Integer): T2DPointArray;
+var
+ t1, t2, c, ec, tc, l: Integer;
+ tpa: TPointArray;
+begin
+ tpa := Copy(arr);
+ l := High(tpa);
+ if (l < 0) then Exit;
+ SetLength(Result, l + 1);
+ c := 0;
+ ec := 0;
+ while ((l - ec) >= 0) do
+ begin
+ SetLength(Result[c], 1);
+ Result[c][0] := tpa[0];
+ tpa[0] := tpa[l - ec];
+ Inc(ec);
+ tc := 1;
+ t1 := 0;
+ while (t1 < tc) do
+ begin
+ t2 := 0;
+ while (t2 <= (l - ec)) do
+ begin
+ if (Round(fSqrt(Sqr(Result[c][t1].x - tpa[t2].x) + Sqr(Result[c][t1].y - tpa[t2].y))) <= Dist) then
+ begin
+ SetLength(Result[c], tc +1);
+ Result[c][tc] := tpa[t2];
+ tpa[t2] := tpa[l - ec];
+ Inc(ec);
+ Inc(tc);
+ Dec(t2);
+ end;
+ Inc(t2);
+ end;
+ Inc(t1);
+ end;
+ Inc(c);
+ end;
+ SetLength(Result, c);
+end;
+
+{/\
+ Removes the points in the TPointArray Points that are not within the degrees
+ \\ SD (StartDegree) and ED (EndDegree) and the distances MinR (MinRadius) and
+ \\ MaxR (MaxRadius) from the origin (Mx, My).
+/\}
+
+procedure FilterPointsPie(var Points: TPointArray; const SD, ED, MinR, MaxR: Extended; Mx, My: Integer);
+const
+ i180Pi = 57.29577951;
+var
+ G: TPointArray;
+ I, L, T: Integer;
+ D, StartD, EndD: Extended;
+ cWise: Boolean;
+begin
+ T := High(Points);
+ if (T < 0) then Exit;
+ SetLength(G, T + 1);
+ L := 0;
+ StartD := SD;
+ EndD := ED;
+ cWise := StartD > EndD;
+ while StartD > 360.0 do
+ StartD := StartD - 360.0;
+ while EndD > 360.0 do
+ EndD := EndD - 360.0;
+ while StartD < 0.0 do
+ StartD := StartD + 360.0;
+ while EndD < 0.0 do
+ EndD := EndD + 360.0;
+ if StartD > EndD then
+ SwapE(StartD, EndD);
+ for I := 0 to T do
+ begin
+ D := fSqrt(Sqr(Points[I].X - Mx) + Sqr(Points[I].Y - My));
+ if( D <= MinR) or (D >= MaxR) then
+ Continue;
+ D := (ArcTan2(Points[I].Y - My, Points[I].X - Mx) * i180Pi) + 90;
+ if D < 0.0 then
+ D := D + 360.0;
+ if (not ((StartD <= D) and (EndD >= D))) xor CWise then
+ Continue;
+ G[L] := Points[I];
+ Inc(L);
+ end;
+ SetLength(G, L);
+ Points := G;
+end;
+
+{/\
+ Removes the points that are inside or outside the distance Dist from the point (x, y) from the TPointArray ThePoints.
+/\}
+
+function RemoveDistTPointArray(x, y, dist: Integer; ThePoints: TPointArray; RemoveHigher: Boolean): TPointArray;
+var
+ I, L, LL: integer;
+begin;
+ L := 0;
+ LL := Length(ThePoints) -1;
+ SetLength(Result, LL + 1);
+ if RemoveHigher then
+ begin;
+ for I := 0 to LL do
+ if not (Round(fSqrt(sqr(ThePoints[i].x - x)+sqr(ThePoints[i].y - y))) > Dist) then
+ begin;
+ Result[L] := ThePoints[i];
+ L := L + 1;
+ end;
+ end else
+ begin;
+ for I := 0 to LL do
+ if not (Round(fSqrt(sqr(ThePoints[i].x - x)+sqr(ThePoints[i].y - y))) < Dist) then
+ begin;
+ Result[L] := ThePoints[i];
+ L := L + 1;
+ end;
+ end;
+ SetLength(Result,L);
+end;
+
+{/\
+ Returns the boundaries of the ATPA as a TBox.
+/\}
+
+function GetATPABounds(ATPA: T2DPointArray): TBox;
+var
+ I,II,L2,L : Integer;
+begin;
+ L := High(ATPA);
+ if (l < 0) then Exit;
+ For I := 0 to L do
+ if Length(ATPA[I]) > 0 then
+ begin;
+ Result.x1 := ATPA[I][0].x;
+ Result.y1 := ATPA[I][0].y;
+ Result.x2 := ATPA[I][0].x;
+ Result.y2 := ATPA[I][0].y;
+ end;
+ for I := 0 to L do
+ begin;
+ L2 := High(ATPA[I]);
+ for II := 0 to L2 do
+ begin;
+ if ATPA[i][II].x > Result.x2 then
+ Result.x2 := ATPA[i][II].x
+ else if ATPA[i][II].x < Result.x1 then
+ Result.x1 := ATPA[i][II].x;
+ if ATPA[i][II].y > Result.y2 then
+ Result.y2 := ATPA[i][II].y
+ else if ATPA[i][II].y < Result.y1 then
+ Result.y1 := ATPA[i][II].y;
+ end;
+ end;
+end;
+
+{/\
+ Returns the boundaries of the TPA as a TBox.
+/\}
+
+function GetTPABounds(TPA: TPointArray): TBox;
+var
+ I,L : Integer;
+begin;
+ L := High(TPA);
+ if (l < 0) then Exit;
+ Result.x1 := TPA[0].x;
+ Result.y1 := TPA[0].y;
+ Result.x2 := TPA[0].x;
+ Result.y2 := TPA[0].y;
+ for I:= 1 to L do
+ begin;
+ if TPA[i].x > Result.x2 then
+ Result.x2 := TPA[i].x
+ else if TPA[i].x < Result.x1 then
+ Result.x1 := TPA[i].x;
+ if TPA[i].y > Result.y2 then
+ Result.y2 := TPA[i].y
+ else if TPA[i].y < Result.y1 then
+ Result.y1 := TPA[i].y;
+ end;
+end;
+
+{/\
+ Looks for the TPA SearchTPA in the TPA TotalTPA and returns the matched points
+ \\ to the TPA Matches. Returns true if there were atleast one match(es).
+/\}
+
+function FindTPAinTPA(SearchTPA, TotalTPA: TPointArray; var Matches: TPointArray): Boolean;
+var
+ Len, I,II,LenSearch,xOff,yOff : integer;
+ tx,ty,MatchCount : integer;
+ Screen : Array of Array of Boolean;
+ ScreenBox,SearchBox : TBox;
+begin;
+ Result := False;
+ Len := High(TotalTPA);
+ LenSearch := High(SearchTPA);
+ if LenSearch < 0 then Exit;
+ if Len < LenSearch then Exit;
+ MatchCount := 0;
+ ScreenBox := GetTPABounds(TotalTPA);
+ SearchBox := GetTPABounds(SearchTPA);
+ try
+ SetLength(Screen,ScreenBox.x2 + 1,ScreenBox.y2 + 1);
+ except
+ Exit;
+ end;
+ if (SearchBox.x1 > 0) or (SearchBox.y1 > 0) then
+ begin;
+ for I := 0 to LenSearch do
+ begin;
+ SearchTPA[I].x := SearchTPA[I].x - SearchBox.x1;
+ SearchTPA[I].y := SearchTPA[I].y - SearchBox.y1;
+ end;
+ SearchBox.x2 := SearchBox.x2 - SearchBox.x1;
+ SearchBox.y2 := SearchBox.y2 - SearchBox.y1;
+ SearchBox.x1 := 0;
+ SearchBox.y1 := 0;
+ end;
+ xOff := SearchBox.x2;
+ yOff := SearchBox.y2;
+ for I := 0 to LenSearch do
+ begin;
+ if (SearchTPA[I].x = 0) and (SearchTPA[I].y < yOff) then
+ yOff := SearchTPA[I].y;
+ if (SearchTPA[I].y = 0) and (SearchTPA[I].x < xOff) then
+ xOff := SearchTPA[I].x;
+ end;
+ for I := 0 to Len do
+ Screen[TotalTPA[I].x][TotalTPA[I].y] := True;
+ for I := 0 to Len do
+ begin;
+ tx := TotalTPA[I].x - xOff;
+ ty := TotalTPA[I].y;// - yOff;
+ if tx > 0 then
+ if ty > 0 then
+ if ((SearchBox.x2 + tx) <= ScreenBox.x2) and ((SearchBox.y2 + ty) <= ScreenBox.y2) then
+ begin;
+ For II := 0 to LenSearch do
+ if Screen[tx + SearchTPA[II].x ][ty + SearchTPA[II].y] = False then
+ Break;
+ if II > LenSearch then
+ begin;
+ MatchCount := MatchCount + 1;
+ SetLength(Matches,MatchCount);
+ Matches[MatchCount - 1].x := TotalTPA[I].x;
+ Matches[MatchCount - 1].y := TotalTPA[I].y;
+ end;
+ end;
+ end;
+ if (MatchCount > 0) then
+ Result := True;
+end;
+
+{/\
+ Read the description of FindTPAinTPA. Additional Height parameter.
+/\}
+
+function FindTextTPAinTPA(Height : integer; SearchTPA, TotalTPA: TPointArray; var Matches: TPointArray): Boolean;
+var
+ Len, I,II,LenSearch,LenTPA,xOff,yOff,x,y: integer;
+ tx,ty,MatchCount : integer;
+ Screen : Array of Array of Boolean;
+ ScreenBox,SearchBox : TBox;
+ InversedTPA : TPointArray;
+begin;
+ Result := False;
+ Len := High(TotalTPA);
+ LenSearch := High(SearchTPA);
+ if LenSearch < 0 then Exit;
+ if Len < LenSearch then Exit;
+ MatchCount := 0;
+ xOff := -5;
+ yOff := 0;
+ ScreenBox := GetTPABounds(TotalTPA);
+ SearchBox := GetTPABounds(SearchTPA);
+ if height > SearchBox.y2 then
+ Screenbox.y2 := Screenbox.y2 + (height - SearchBox.y2);
+ SearchBox.y2 := Height;
+ SetLength(Screen, SearchBox.x2 + 1,Searchbox.y2 + 1);
+ SetLength(InversedTPA,(SearchBox.x2 + 1) * (Searchbox.y2 + 1));
+ for I := 0 to LenSearch do
+ Screen[ SearchTPA[I].x,SearchTPA[I].y] := True;
+ LenTPA := -1;
+ for y := 0 to SearchBox.y2 do
+ for x := 0 to SearchBox.x2 do
+ if Screen[X][Y] = False then
+ begin;
+ LenTPA := LenTPA + 1;
+ InversedTPA[LenTPA].x := x;
+ InversedTPA[LenTPA].y := y;
+ end;
+ for x := 0 to SearchBox.x2 do
+ begin;
+ for y := 0 to SearchBox.y2 do
+ if Screen[x][y] = True then
+ begin;
+ xOff := x;
+ yOff := y;
+ Break;
+ end;
+ if xOff >= 0 then
+ Break;
+ end;
+ try
+ SetLength(Screen,0);
+ SetLength(Screen,ScreenBox.x2 + 1,ScreenBox.y2 + 1);
+ except
+ Exit;
+ end;
+ for I := 0 to Len do
+ Screen[TotalTPA[I].x][TotalTPA[I].y] := True;
+ for I := 0 to Len do
+ begin;
+ tx := TotalTPA[I].x - xOff;
+ ty := TotalTPA[I].y - yOff;
+ if tx > 0 then
+ if ty > 0 then
+ if ((SearchBox.x2 + tx) <= ScreenBox.x2) and ((SearchBox.y2 + ty) <= ScreenBox.y2) then
+ begin;
+ For II := 0 to LenSearch do
+ if Screen[tx + SearchTPA[II].x ][ty + SearchTPA[II].y] = False then
+ Break;
+ if (II > LenSearch) then
+ begin;
+ For II := 0 to LenTPA do
+ if Screen[tx + InversedTPA[II].x ][ty + InversedTPA[II].y] = True then
+ Break;
+ if (II > LenTPA) then
+ begin;
+ MatchCount := MatchCount + 1;
+ SetLength(Matches,MatchCount);
+ Matches[MatchCount - 1].x := TotalTPA[I].x;
+ Matches[MatchCount - 1].y := TotalTPA[I].y;
+ end;
+ end;
+ end;
+ end;
+ if (MatchCount > 0) then
+ Result := True;
+end;
+
+{/\
+ Finds the possible gaps in the TPointArray TPA and results the gaps as a T2DPointArray.
+ \\ Considers as a gap if the gap length is >= MinPixels.
+ \\ Only horizontal, sorry folks.
+/\}
+
+function FindGapsTPA(TPA: TPointArray; MinPixels: Integer): T2DPointArray;
+var
+ Len,TotalLen,LenRes,I,II,III : integer;
+ Screen : Array of Array of Boolean;
+ Height,Width : Integer;
+ Box : TBox;
+begin;
+ Len := High(TPA);
+ if Len < 0 then exit;
+ Box := GetTPABounds(TPA);
+ Height := Box.y2 - Box.y1;
+ Width := Box.x2 - Box.x1;
+ LenRes := 0;
+ III := 0;
+ try
+ SetLength(Screen,Width + 1,Height + 1);
+ except
+ Exit;
+ end;
+ For I := 0 to Len do
+ Screen[TPA[I].x - Box.x1][TPA[I].y - Box.y1] := True;
+ SetLength(result,1);
+ SetLength(Result[0],Len+1);
+ TotalLen := 0;
+ for I := 0 to Width do
+ begin;
+ for II := 0 to Height do
+ if Screen[I][II]=True then
+ begin;
+ Result[TotalLen][LenRes].x := I + Box.x1;
+ Result[TotalLen][LenRes].y := II + Box.y1;
+ LenRes := LenRes + 1;
+ III := I;
+ end;
+ if LenRes = 0 then
+ III := I
+ else
+ if (I - III) > MinPixels then
+ begin;
+ III := I;
+ SetLength(Result[TotalLen],LenRes);
+ LenRes := 0;
+ TotalLen := TotalLen + 1;
+ SetLength(Result,TotalLen + 1);
+ SetLength(Result[TotalLen],Len + 1);
+ end;
+ end;
+ SetLength(Result[TotalLen],LenRes);
+end;
+
+
+
+{/\
+ Sorts all points in tpa by distance from degree (Deg) and distance from mx and my.
+ \\ Sortup will return closest distance to mx and my first.
+ \\ Distance will be sorted first (RadialWalk style).
+/\}
+
+procedure SortCircleWise(var tpa: TPointArray; const cx, cy, StartDegree: Integer; SortUp, ClockWise: Boolean);
+const
+ i180Pi = 57.29577951;
+var
+ i, l, td, sd: Integer;
+ Dist, Deg: TIntegerArray;
+begin
+ l := Length(tpa);
+ if (l = 0) then Exit;
+ sd := StartDegree;
+ while (sd > 360) do
+ sd := (sd - 360);
+ sd := (360 - sd);
+ SetLength(Dist, l);
+ SetLength(Deg, l);
+ for i := 0 to l -1 do
+ Dist[i] := Round(Hypot(tpa[i].x - cx, tpa[i].y - cy));
+ QuickTPASort(Dist, tpa, 0, l -1, SortUp);
+ if (l = 1) then Exit;
+ for i := 0 to l -1 do
+ begin
+ td := Round(ArcTan2(tpa[i].y - cy, tpa[i].x - cx) * i180Pi) + 90;
+ if (td < 0) then
+ td := td + 360;
+ if ClockWise then
+ Deg[i] := Round(sd + td) mod 360
+ else
+ Deg[i] := 360 - Round(sd + td) mod 360;
+ end;
+ i := 1;
+ td := 0;
+ Dec(l);
+ while (i < l) do
+ begin
+ while (i < l) and (Abs(Dist[td] - Dist[i]) <= 1) do Inc(i);
+ QuickTPASort(Deg, tpa, td, i, False);
+ Inc(i);
+ td := i;
+ end;
+ if (td < l) then
+ QuickTPASort(Deg, tpa, td, l, False);
+end;
+
+{/\
+ Sorts all points in tpa by distance from degree (Deg) and distance from mx and my.
+ \\ Sortup will return closest distance to mx and my first.
+ \\ Degree will be sorted first (LinearWalk style).
+/\}
+
+procedure LinearSort(var tpa: TPointArray; cx, cy, sd: Integer; SortUp: Boolean);
+const
+ i180Pi = 57.29577951;
+var
+ i, l, td: Integer;
+ Dist, Deg: TIntegerArray;
+begin
+ l := Length(tpa);
+ if (l = 0) then Exit;
+ while (sd > 360) do
+ sd := (sd - 360);
+ SetLength(Dist, l);
+ SetLength(Deg, l);
+ for i := 0 to l -1 do
+ begin
+ td := Round(ArcTan2(tpa[i].y - cy, tpa[i].x - cx) * i180Pi) + 90;
+ if (td < 0) then
+ td := td + 360;
+ Deg[i] := Min(Abs(sd - td), Min(Abs(sd - (td + 360)), Abs((sd + 360) - td)))
+ end;
+ QuickTPASort(Deg, tpa, 0, l -1, True);
+ if (l = 1) then Exit;
+ for i := 0 to l -1 do
+ Dist[i] := Round(Hypot(tpa[i].x - cx, tpa[i].y - cy));
+ i := 1;
+ td := 0;
+ Dec(l);
+ while (i < l) do
+ begin
+ while (i < l) and (Abs(Deg[td] - Deg[i]) <= 3) do Inc(i);
+ QuickTPASort(Dist, tpa, td, i, SortUp);
+ Inc(i);
+ td := i;
+ end;
+ if (td < l) then
+ QuickTPASort(Dist, tpa, td, l, SortUp);
+end;
+
+{/\
+ Merges the TPointArrays of the T2DPointArray ATPA in to one TPA.
+/\}
+
+Function MergeATPA(ATPA: T2DPointArray): TPointArray;
+var
+ I, II, Len, TempL, CurrentL: integer;
+begin;
+ Len := High(ATPA);
+ if Len < 0 then
+ begin
+ SetLength(Result, 0);
+ Exit;
+ end;
+ CurrentL := 0;
+ For I:= 0 to Len do
+ begin;
+ TempL := High(ATPA[I]);
+ if TempL < 0 then
+ Continue;
+ TempL := Templ + CurrentL + 1;
+ Setlength(Result, TempL+1);
+ For II := CurrentL to TempL do
+ Result[II] := ATPA[I][II - CurrentL];
+ CurrentL := TempL;
+ end;
+ SetLength(Result,CurrentL);
+end;
+
+
+{/\
+ Returns a TPointArray of a the full given Box.
+/\}
+
+function TPAFromBox(const Box : TBox) : TPointArray;
+var
+ x, y: integer;
+ l : integer;
+begin;
+ SetLength(Result, (Box.x2 - Box.x1 + 1) * (Box.y2 - Box.y1 + 1));
+ l := 0;
+ For x := box.x1 to Box.x2 do
+ for y := box.y1 to box.y2 do
+ begin;
+ Result[l].x := x;
+ Result[l].y := y;
+ inc(l);
+ end;
+end;
+
+{/\
+ Rotate the given TPA with A radians.
+/\}
+
+Function RotatePoints(Const P: TPointArray; A, cx, cy: Extended): TPointArray ;
+
+Var
+ I, L: Integer;
+
+Begin
+ L := High(P);
+ SetLength(Result, L + 1);
+ For I := 0 To L Do
+ Begin
+ Result[I].X := Trunc(cx + cos(A) * (p[i].x - cx) - sin(A) * (p[i].y - cy));
+ Result[I].Y := Trunc(cy + sin(A) * (p[i].x - cx) + cos(A) * (p[i].y - cy));
+ End;
+ // I recon it's faster than Point().
+End;
+
+{/\
+ Rotate the given Point with A radians.
+/\}
+
+Function RotatePoint(Const p: TPoint; angle, mx, my: Extended): TPoint;
+
+Begin
+ Result.X := Trunc(mx + cos(angle) * (p.x - mx) - sin(angle) * (p.y - my));
+ Result.Y := Trunc(my + sin(angle) * (p.x - mx) + cos(angle) * (p.y- my));
+End;
+
+{/\
+ Returns the edges of the given TPA.
+/\}
+
+function FindTPAEdges(p: TPointArray): TPointArray;
+var
+ b: array of array of Boolean;
+ i, x, y, l, c: Integer;
+ Box: TBox;
+begin
+ SetLength(Result, 0);
+ l := Length(p);
+ if (l = 0) then Exit;
+ Box := GetTPABounds(p);
+ x := (Box.x2 - Box.x1) + 3;
+ y := (Box.y2 - Box.y1) + 3;
+ SetLength(b, x);
+ for i := 0 to x -1 do
+ SetLength(b[i], y);
+ for i := 0 to l -1 do
+ b[p[i].x +1 - Box.x1][p[i].y +1 - Box.y1] := True;
+ SetLength(Result, l);
+ c := 0;
+ for i := 0 to l -1 do
+ begin
+ x := -1;
+ while (x <= 1) do
+ begin
+ for y := -1 to 1 do
+ try
+ if not b[p[i].x + 1 + x - Box.x1][p[i].y + 1 + y - Box.y1] then
+ begin
+ Result[c] := p[i];
+ Inc(c);
+ x := 2;
+ Break;
+ end;
+ except end;
+ Inc(x);
+ end;
+ end;
+ SetLength(Result, c);
+end;
+
+{/\
+ Results true if a point is in a TPointArray.
+ Notes: In actuallys means IN the array, not in the box shaped by the array.
+/\}
+
+function PointInTPA(p: TPoint; arP: TPointArray): Boolean;
+var
+ i, l: Integer;
+begin
+ l := High(arP);
+ if l < 0 then
+ begin
+ Result := False;
+ Exit;
+ end;
+ Result := True;
+ for i := 0 to l do
+ if (arP[i].x = p.x) and (arP[i].y = p.y) then
+ Exit;
+ Result := False;
+end;
+
+{/\
+ Removes the given ClearPoints from arP.
+/\}
+
+function ClearTPAFromTPA(arP, ClearPoints: TPointArray): TPointArray;
+var
+ i, j, l, l2: Integer;
+begin
+ l := High(arP);
+ l2 := High(ClearPoints);
+ for i := 0 to l do
+ begin
+ for j := 0 to l2 do
+ if (arP[i].x = ClearPoints[j].x) and (arP[i].y = ClearPoints[j].y) then
+ Break;
+
+ if (j = l2 + 1) then
+ begin
+ SetLength(Result, Length(Result) + 1);
+ Result[High(Result)] := arP[i];
+ end;
+ end;
+end;
+
+{/\
+ Removes all the doubles point from a TPA.
+/\}
+
+procedure ClearDoubleTPA(var TPA: TPointArray);
+var
+ I, II, L: Integer;
+ Swappie: TPoint;
+begin
+ L := High(TPA);
+ for I := 0 To L Do
+ for II := I + 1 To L Do
+ if ((TPA[I].X = TPA[II].X) And (TPA[I].Y = TPA[II].Y)) then
+ begin
+ Swappie := TPA[L];
+ TPA[L] := TPA[II];
+ TPA[II] := Swappie;
+ L := L - 1;
+ end;
+ SetLength(TPA, L + 1);
+end;
+
+{/\
+ Uses Box to define an area around TotalTPA.
+ Every point that is not in TotalTPA, but is in Box, is added to the Result.
+ \\ This can be very handy if you want for example, can get all the colors of the background, but not of the actual object.
+ \\ If you pass this all the colors of the background, it will returns the points of the object.
+/\}
+
+Function ReturnPointsNotInTPA(Const TotalTPA: TPointArray; const Box: TBox): TPointArray;
+var
+ x, y, w, h, i, l: integer;
+ B: Array of Array of Boolean;
+begin;
+ w := Box.x2 - Box.x1;
+ h := Box.y2 - Box.y1;
+ if (w = 0) and (h = 0) then
+ Exit;
+ SetLength(b, w + 1, h + 1);
+ l := High(TotalTPA);
+ x := 0;
+ for i := 0 to l do
+ if ((TotalTPA[i].x >= Box.x1) and (TotalTPA[i].x <= Box.x2) and
+ (TotalTPA[i].y >= Box.y1) and (TotalTPA[i].y <= Box.y2)) then
+ begin;
+ Inc(x);
+ B[TotalTPA[i].x-Box.x1][TotalTPA[i].y-Box.y1] := True;
+ end;
+ if x = 0 then
+ Exit;
+ SetLength(result,(w + 1) * (h + 1) - x);
+ i := 0;
+ for x := 0 to w do
+ for y := 0 to h do
+ if not B[x][y] then
+ try
+ Result[i].x := x + Box.x1;
+ Result[i].y := y + Box.y1;
+ Inc(i);
+ except end;
+ SetLength(b, 0);
+ SetLength(Result, i);
+end;
+
+{/\
+ Sorts a TPointArray by either X or Y. You have to define the max Point as well.
+/\}
+
+Procedure TPACountSort(Var TPA: TPointArray;const max: TPoint;Const SortOnX : Boolean);
+Var
+ c: Array Of Array Of Integer;
+ I, II, III, hTPA, cc: Integer;
+Begin
+ hTPA := High(TPA);
+ if hTPA < 1 then
+ Exit;
+ SetLength(c, max.X + 1,max.Y + 1);
+ For I := 0 To hTPA Do
+ c[TPA[I].x][TPA[I].y] := c[TPA[i].x][TPA[i].y] + 1;
+
+ cc := 0;
+ if SortOnX then
+ begin
+ For I := 0 To max.X Do
+ For II := 0 To max.Y Do
+ Begin
+ For III := 0 To c[I][II] - 1 Do
+ Begin
+ TPA[cc].x := I;
+ TPA[cc].y := II;
+ cc := cc + 1;
+ End;
+ End;
+ end else
+ begin;
+ For II := 0 To max.Y Do
+ For I := 0 To max.X Do
+ Begin
+ For III := 0 To c[I][II] - 1 Do
+ Begin
+ TPA[cc].x := I;
+ TPA[cc].y := II;
+ cc := cc + 1;
+ End;
+ End;
+ end;
+End;
+
+
+{/\
+ Sorts a TPointArray by either X or Y. Allows one to pass a Base.
+/\}
+
+Procedure TPACountSortBase(Var TPA: TPointArray;const maxx, base: TPoint; const SortOnX : Boolean);
+Var
+ c: Array Of Array Of Integer;
+ I, II, III, hTPA, cc: Integer;
+ Max : TPoint;
+Begin
+ hTPA := High(TPA);
+ if hTPA < 1 then
+ Exit;
+ max.X := maxx.X - base.X;
+ max.Y := maxx.Y - base.Y;
+ SetLength(c, max.X + 1,max.Y + 1);
+ hTPA := High(TPA);
+ For I := 0 To hTPA Do
+ c[TPA[I].x - base.X][TPA[I].y - base.Y] := c[TPA[i].x- base.X][TPA[i].y- base.Y] + 1;
+
+ cc := 0;
+ if SortOnX then
+ begin
+ For I := 0 To max.X Do
+ For II := 0 To max.Y Do
+ Begin
+ For III := 0 To c[I][II] - 1 Do
+ Begin
+ TPA[cc].x := I + base.X;
+ TPA[cc].y := II + base.Y;
+ cc := cc + 1;
+ End;
+ End;
+ end else
+ begin;
+ For II := 0 To max.Y Do
+ For I := 0 To max.X Do
+ Begin
+ For III := 0 To c[I][II] - 1 Do
+ Begin
+ TPA[cc].x := I + base.X;
+ TPA[cc].y := II + base.Y;
+ cc := cc + 1;
+ End;
+ End;
+ end;
+End;
+
+{/\
+ Returns the sum of all integers in the array
+/\}
+function SumIntegerArray(Ints : TIntegerArray): Integer;
+var
+ I, H: Integer;
+begin
+ Result := 0;
+ H := High(Ints);
+ for I := 0 to H do
+ Result := Result + Ints[I];
+end;
+
+{/\
+ Inverts the IntegerArray, last becomes first etc..
+/\}
+procedure InvertTIA(var tI: TIntegerArray);
+var
+ Temp: TIntegerArray;
+ i, h: Integer;
+begin
+ h := High(tI);
+ Temp := tI;
+ for i := 0 to h do
+ tI[i] := Temp[h - i];
+end;
+
+{/\
+ Results the Average of an IntegerArray
+/\}
+
+function AverageTIA(tI: TIntegerArray): Integer;
+begin
+ try Result := (SumIntegerArray(tI) div Length(tI)); except Result := 0; end;
+end;
+
+{/\
+ Results the Average of an ExtendedArray
+/\}
+function AverageExtended(tE: TExtendedArray): Extended;
+var
+ i, h: Integer;
+begin
+ Result := 1;
+ try
+ h := High(tE);
+ for i := 0 to h do
+ Result := (Result * tE[i]);
+ Result := Power(Result, 1/(h + 1));
+ except
+ Result := 0.0;
+ end;
+end;
+
+end.
+
diff --git a/branches/script-component/Units/MMLCore/web.pas b/branches/script-component/Units/MMLCore/web.pas
new file mode 100644
index 0000000..b40936f
--- /dev/null
+++ b/branches/script-component/Units/MMLCore/web.pas
@@ -0,0 +1,42 @@
+unit web;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+ Classes, SysUtils,LazHelpHTML,UTF8Process;
+
+procedure OpenWebPage(URL: string);
+
+implementation
+
+
+procedure OpenWebPage(URL: string);
+var
+ v: THTMLBrowserHelpViewer;
+ BrowserPath, BrowserParams: string;
+ p: LongInt;
+ BrowserProcess: TProcessUTF8;
+begin
+ v:=THTMLBrowserHelpViewer.Create(nil);
+ try
+ v.FindDefaultBrowser(BrowserPath,BrowserParams);
+ p:=System.Pos('%s', BrowserParams);
+ System.Delete(BrowserParams,p,2);
+ System.Insert(URL,BrowserParams,p);
+
+ // start browser
+ BrowserProcess:=TProcessUTF8.Create(nil);
+ try
+ BrowserProcess.CommandLine:=BrowserPath+' '+BrowserParams;
+ BrowserProcess.Execute;
+ finally
+ BrowserProcess.Free;
+ end;
+ finally
+ v.Free;
+ end;
+end;
+end.
+
diff --git a/branches/script-component/Units/Misc/dcpbase64.pas b/branches/script-component/Units/Misc/dcpbase64.pas
new file mode 100644
index 0000000..5a2472d
--- /dev/null
+++ b/branches/script-component/Units/Misc/dcpbase64.pas
@@ -0,0 +1,140 @@
+{******************************************************************************}
+{* DCPcrypt v2.0 written by David Barton (crypto@cityinthesky.co.uk) **********}
+{******************************************************************************}
+{* A Base64 encoding/decoding unit ********************************************}
+{******************************************************************************}
+{* Copyright (c) 1999-2002 David Barton *}
+{* Permission is hereby granted, free of charge, to any person obtaining a *}
+{* copy of this software and associated documentation files (the "Software"), *}
+{* to deal in the Software without restriction, including without limitation *}
+{* the rights to use, copy, modify, merge, publish, distribute, sublicense, *}
+{* and/or sell copies of the Software, and to permit persons to whom the *}
+{* Software is furnished to do so, subject to the following conditions: *}
+{* *}
+{* The above copyright notice and this permission notice shall be included in *}
+{* all copies or substantial portions of the Software. *}
+{* *}
+{* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *}
+{* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *}
+{* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *}
+{* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *}
+{* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *}
+{* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *}
+{* DEALINGS IN THE SOFTWARE. *}
+{******************************************************************************}
+unit DCPbase64;
+
+{$mode delphi}
+interface
+uses
+ Sysutils;
+
+function Base64EncodeStr(const Value: string): string;
+ { Encode a string into Base64 format }
+function Base64DecodeStr(const Value: string): string;
+ { Decode a Base64 format string }
+function Base64Encode(pInput: pointer; pOutput: pointer; Size: longint): longint;
+ { Encode a lump of raw data (output is (4/3) times bigger than input) }
+function Base64Decode(pInput: pointer; pOutput: pointer; Size: longint): longint;
+ { Decode a lump of raw data }
+
+
+{******************************************************************************}
+{******************************************************************************}
+implementation
+
+
+const
+ B64: array[0..63] of byte= (65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,
+ 81,82,83,84,85,86,87,88,89,90,97,98,99,100,101,102,103,104,105,106,107,108,
+ 109,110,111,112,113,114,115,116,117,118,119,120,121,122,48,49,50,51,52,53,
+ 54,55,56,57,43,47);
+
+function Base64Encode(pInput: pointer; pOutput: pointer; Size: longint): longint;
+var
+ i, iptr, optr: integer;
+ Input, Output: PByteArray;
+begin
+ Input:= PByteArray(pInput); Output:= PByteArray(pOutput);
+ iptr:= 0; optr:= 0;
+ for i:= 1 to (Size div 3) do
+ begin
+ Output^[optr+0]:= B64[Input^[iptr] shr 2];
+ Output^[optr+1]:= B64[((Input^[iptr] and 3) shl 4) + (Input^[iptr+1] shr 4)];
+ Output^[optr+2]:= B64[((Input^[iptr+1] and 15) shl 2) + (Input^[iptr+2] shr 6)];
+ Output^[optr+3]:= B64[Input^[iptr+2] and 63];
+ Inc(optr,4); Inc(iptr,3);
+ end;
+ case (Size mod 3) of
+ 1: begin
+ Output^[optr+0]:= B64[Input^[iptr] shr 2];
+ Output^[optr+1]:= B64[(Input^[iptr] and 3) shl 4];
+ Output^[optr+2]:= byte('=');
+ Output^[optr+3]:= byte('=');
+ end;
+ 2: begin
+ Output^[optr+0]:= B64[Input^[iptr] shr 2];
+ Output^[optr+1]:= B64[((Input^[iptr] and 3) shl 4) + (Input^[iptr+1] shr 4)];
+ Output^[optr+2]:= B64[(Input^[iptr+1] and 15) shl 2];
+ Output^[optr+3]:= byte('=');
+ end;
+ end;
+ Result:= ((Size+2) div 3) * 4;
+end;
+
+function Base64EncodeStr(const Value: string): string;
+begin
+ SetLength(Result,((Length(Value)+2) div 3) * 4);
+ Base64Encode(@Value[1],@Result[1],Length(Value));
+end;
+
+function Base64Decode(pInput: pointer; pOutput: pointer; Size: longint): longint;
+var
+ i, j, iptr, optr: integer;
+ Temp: array[0..3] of byte;
+ Input, Output: PByteArray;
+begin
+ Input:= PByteArray(pInput); Output:= PByteArray(pOutput);
+ iptr:= 0; optr:= 0;
+ Result:= 0;
+ for i:= 1 to (Size div 4) do
+ begin
+ for j:= 0 to 3 do
+ begin
+ case Input^[iptr] of
+ 65..90 : Temp[j]:= Input^[iptr] - Ord('A');
+ 97..122: Temp[j]:= Input^[iptr] - Ord('a') + 26;
+ 48..57 : Temp[j]:= Input^[iptr] - Ord('0') + 52;
+ 43 : Temp[j]:= 62;
+ 47 : Temp[j]:= 63;
+ 61 : Temp[j]:= $FF;
+ end;
+ Inc(iptr);
+ end;
+ Output^[optr]:= (Temp[0] shl 2) or (Temp[1] shr 4);
+ Result:= optr+1;
+ if (Temp[2]<> $FF) and (Temp[3]= $FF) then
+ begin
+ Output^[optr+1]:= (Temp[1] shl 4) or (Temp[2] shr 2);
+ Result:= optr+2;
+ Inc(optr)
+ end
+ else if (Temp[2]<> $FF) then
+ begin
+ Output^[optr+1]:= (Temp[1] shl 4) or (Temp[2] shr 2);
+ Output^[optr+2]:= (Temp[2] shl 6) or Temp[3];
+ Result:= optr+3;
+ Inc(optr,2);
+ end;
+ Inc(optr);
+ end;
+end;
+
+function Base64DecodeStr(const Value: string): string;
+begin
+ SetLength(Result,(Length(Value) div 4) * 3);
+ SetLength(Result,Base64Decode(@Value[1],@Result[1],Length(Value)));
+end;
+
+
+end.
diff --git a/branches/script-component/Units/Misc/mPasLex.pas b/branches/script-component/Units/Misc/mPasLex.pas
new file mode 100644
index 0000000..e9977d9
--- /dev/null
+++ b/branches/script-component/Units/Misc/mPasLex.pas
@@ -0,0 +1,1614 @@
+{+--------------------------------------------------------------------------+
+ | Class: TmwPasLex
+ | Created: 07.98 - 10.98
+ | Author: Martin Waldenburg
+ | Description: A very fast Pascal tokenizer.
+ | Version: 1.32
+ | Copyright (c) 1998, 1999 Martin Waldenburg
+ | All rights reserved.
+ |
+ | LICENCE CONDITIONS
+ |
+ | USE OF THE ENCLOSED SOFTWARE
+ | INDICATES YOUR ASSENT TO THE
+ | FOLLOWING LICENCE CONDITIONS.
+ |
+ |
+ |
+ | These Licence Conditions are exlusively
+ | governed by the Law and Rules of the
+ | Federal Republic of Germany.
+ |
+ | Redistribution and use in source and binary form, with or without
+ | modification, are permitted provided that the following conditions
+ | are met:
+ |
+ | 1. Redistributions of source code must retain the above copyright
+ | notice, this list of conditions and the following disclaimer.
+ | If the source is modified, the complete original and unmodified
+ | source code has to distributed with the modified version.
+ |
+ | 2. Redistributions in binary form must reproduce the above
+ | copyright notice, these licence conditions and the disclaimer
+ | found at the end of this licence agreement in the documentation
+ | and/or other materials provided with the distribution.
+ |
+ | 3. Software using this code must contain a visible line of credit.
+ |
+ | 4. If my code is used in a "for profit" product, you have to donate
+ | to a registered charity in an amount that you feel is fair.
+ | You may use it in as many of your products as you like.
+ | Proof of this donation must be provided to the author of
+ | this software.
+ |
+ | 5. If you for some reasons don't want to give public credit to the
+ | author, you have to donate three times the price of your software
+ | product, or any other product including this component in any way,
+ | but no more than $500 US and not less than $200 US, or the
+ | equivalent thereof in other currency, to a registered charity.
+ | You have to do this for every of your products, which uses this
+ | code separately.
+ | Proof of this donations must be provided to the author of
+ | this software.
+ |
+ |
+ | DISCLAIMER:
+ |
+ | THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS'.
+ |
+ | ALL EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ | PARTICULAR PURPOSE ARE DISCLAIMED.
+ |
+ | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ | OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ |
+ | Martin.Waldenburg@T-Online.de
+ +--------------------------------------------------------------------------+}
+
+{25/03/2003 Olivier GUILBAUD update for lazarus project}
+
+unit mPasLex;
+{$mode objfpc}{$H+}{$M+}
+interface
+
+uses
+ SysUtils;
+
+var
+ Identifiers: array[#0..#255]of ByteBool;
+ mHashTable: array[#0..#255]of Integer;
+
+type
+ TTokenKind=(tkAbsolute, tkAbstract, tkAddressOp, tkAnd, tkAnsiComment,
+ tkArray, tkAs, tkAt, tkAsciiChar, tkAsm, tkAssembler, tkAssign, tkAutomated,
+ tkBegin, tkBadString, tkBorComment, tkCase, tkCdecl, tkClass, tkColon,
+ tkComma, tkCompDirect, tkConst, tkConstructor, tkCRLF, tkCRLFCo, tkDefault,
+ tkDestructor, tkDispid, tkDispinterface, tkDiv, tkDo, tkDoubleAddressOp,
+ tkDotDot, tkDownto, tkDynamic, tkElse, tkEnd, tkEqual, tkError, tkExcept,
+ tkExport, tkExports, tkExternal, tkFar, tkFile, tkFinalization, tkFinally,
+ tkFloat, tkFor, tkForward, tkFunction, tkGoto, tkGreater, tkGreaterEqual,
+ tkIdentifier, tkIf, tkImplementation, tkImplements, tkIn, tkInclude, tkIndex,
+ tkInherited, tkInitialization, tkInline, tkInteger, tkInterface, tkIs,
+ tkKeyString, tkLabel, tkLibrary, tkLower, tkLowerEqual, tkMessage, tkMinus,
+ tkMod, tkName, tkNear, tkNil, tkNodefault, tkNone, tkNot, tkNotEqual, tkNull,
+ tkNumber, tkObject, tkOf, tkOn, tkOr, tkOut, tkOverload, tkOverride,
+ tkPacked, tkPascal, tkPlus, tkPoint, tkPointerSymbol, tkPrivate, tkProcedure,
+ tkProgram, tkProperty, tkProtected, tkPublic, tkPublished, tkRaise, tkRead,
+ tkReadonly, tkRecord, tkRegister, tkReintroduce, tkRepeat, tkResident,
+ tkResourcestring, tkRoundClose, tkRoundOpen, tkSafecall, tkSemiColon, tkSet,
+ tkShl, tkShr, tkSlash, tkSlashesComment, tkSquareClose, tkSquareOpen,
+ tkSpace, tkStar, tkStdcall, tkStored, tkString, tkStringresource, tkSymbol,
+ tkThen, tkThreadvar, tkTo, tkTry, tkType, tkUnit, tkUnknown, tkUntil, tkUses,
+ tkVar, tkVirtual, tkWhile, tkWith, tkWrite, tkWriteonly, tkXor);
+
+ TCommentState=(csAnsi, csBor, csNo);
+
+ TmwPasLex=class(TObject)
+ private
+ fComment: TCommentState;
+ fOrigin: PChar;
+ fProcTable: array[#0..#255]of procedure of Object;
+ Run: Longint;
+ Temp: PChar;
+ FRoundCount: Integer;
+ FSquareCount: Integer;
+ fStringLen: Integer;
+ fToIdent: PChar;
+ fIdentFuncTable: array[0..191]of function: TTokenKind of Object;
+ fTokenPos: Integer;
+ fLineNumber: Integer;
+ FTokenID: TTokenKind;
+ fLastIdentPos: Integer;
+ fLastNoSpace: TTokenKind;
+ fLastNoSpacePos: Integer;
+ fLinePos: Integer;
+ fIsInterface: Boolean;
+ fIsClass: Boolean;
+ function KeyHash(ToHash: PChar): Integer;
+ function KeyComp(const aKey: string): Boolean;
+ function Func15: TTokenKind;
+ function Func19: TTokenKind;
+ function Func20: TTokenKind;
+ function Func21: TTokenKind;
+ function Func23: TTokenKind;
+ function Func25: TTokenKind;
+ function Func27: TTokenKind;
+ function Func28: TTokenKind;
+ function Func29: TTokenKind;
+ function Func32: TTokenKind;
+ function Func33: TTokenKind;
+ function Func35: TTokenKind;
+ function Func37: TTokenKind;
+ function Func38: TTokenKind;
+ function Func39: TTokenKind;
+ function Func40: TTokenKind;
+ function Func41: TTokenKind;
+ function Func44: TTokenKind;
+ function Func45: TTokenKind;
+ function Func47: TTokenKind;
+ function Func49: TTokenKind;
+ function Func52: TTokenKind;
+ function Func54: TTokenKind;
+ function Func55: TTokenKind;
+ function Func56: TTokenKind;
+ function Func57: TTokenKind;
+ function Func59: TTokenKind;
+ function Func60: TTokenKind;
+ function Func61: TTokenKind;
+ function Func63: TTokenKind;
+ function Func64: TTokenKind;
+ function Func65: TTokenKind;
+ function Func66: TTokenKind;
+ function Func69: TTokenKind;
+ function Func71: TTokenKind;
+ function Func73: TTokenKind;
+ function Func75: TTokenKind;
+ function Func76: TTokenKind;
+ function Func79: TTokenKind;
+ function Func81: TTokenKind;
+ function Func84: TTokenKind;
+ function Func85: TTokenKind;
+ function Func87: TTokenKind;
+ function Func88: TTokenKind;
+ function Func91: TTokenKind;
+ function Func92: TTokenKind;
+ function Func94: TTokenKind;
+ function Func95: TTokenKind;
+ function Func96: TTokenKind;
+ function Func97: TTokenKind;
+ function Func98: TTokenKind;
+ function Func99: TTokenKind;
+ function Func100: TTokenKind;
+ function Func101: TTokenKind;
+ function Func102: TTokenKind;
+ function Func103: TTokenKind;
+ function Func105: TTokenKind;
+ function Func106: TTokenKind;
+ function Func117: TTokenKind;
+ function Func126: TTokenKind;
+ function Func129: TTokenKind;
+ function Func132: TTokenKind;
+ function Func133: TTokenKind;
+ function Func136: TTokenKind;
+ function Func141: TTokenKind;
+ function Func143: TTokenKind;
+ function Func166: TTokenKind;
+ function Func168: TTokenKind;
+ function Func191: TTokenKind;
+ function AltFunc: TTokenKind;
+ procedure InitIdent;
+ function IdentKind(MayBe: PChar): TTokenKind;
+ procedure SetOrigin(NewValue: PChar);
+ procedure SetRunPos(Value: Integer);
+ procedure MakeMethodTables;
+ procedure AddressOpProc;
+ procedure AsciiCharProc;
+ procedure AnsiProc;
+ procedure BorProc;
+ procedure BraceCloseProc;
+ procedure BraceOpenProc;
+ procedure ColonProc;
+ procedure CommaProc;
+ procedure CRProc;
+ procedure EqualProc;
+ procedure GreaterProc;
+ procedure IdentProc;
+ procedure IntegerProc;
+ procedure LFProc;
+ procedure LowerProc;
+ procedure MinusProc;
+ procedure NullProc;
+ procedure NumberProc;
+ procedure PlusProc;
+ procedure PointerSymbolProc;
+ procedure PointProc;
+ procedure RoundCloseProc;
+ procedure RoundOpenProc;
+ procedure SemiColonProc;
+ procedure SlashProc;
+ procedure SpaceProc;
+ procedure SquareCloseProc;
+ procedure SquareOpenProc;
+ procedure StarProc;
+ procedure StringProc;
+ procedure SymbolProc;
+ procedure UnknownProc;
+ function GetToken: string;
+ function InSymbols(aChar: Char): Boolean;
+ protected
+ public
+ constructor Create;
+ destructor Destroy; override;
+ function CharAhead(Count: Integer): Char;
+ procedure Next;
+ procedure NextID(ID: TTokenKind);
+ procedure NextNoJunk;
+ procedure NextClass;
+ property IsClass: Boolean read fIsClass;
+ property IsInterface: Boolean read fIsInterface;
+ property LastIdentPos: Integer read fLastIdentPos;
+ property LastNoSpace: TTokenKind read fLastNoSpace;
+ property LastNoSpacePos: Integer read fLastNoSpacePos;
+ property LineNumber: Integer read fLineNumber;
+ property LinePos: Integer read fLinePos;
+ property Origin: PChar read fOrigin write SetOrigin;
+ property RunPos: Integer read Run write SetRunPos;
+ property TokenPos: Integer read fTokenPos;
+ property Token: string read GetToken;
+ property TokenID: TTokenKind read FTokenID;
+ published
+ end;
+
+var
+ mwPasLex: TmwPasLex;
+
+implementation
+
+procedure MakeIdentTable;
+var
+ I, J: Char;
+begin
+ for I:=#0 to #255 do
+ begin
+ Case I of
+ '_', '0'..'9', 'a'..'z', 'A'..'Z': Identifiers[I]:=True;
+ else Identifiers[I]:=False;
+ end;
+ J:=UpperCase(I)[1];
+ Case I of
+ 'a'..'z', 'A'..'Z', '_': mHashTable[I]:=Ord(J)-64;
+ else mHashTable[Char(I)]:=0;
+ end;
+ end;
+end;
+
+procedure TmwPasLex.InitIdent;
+var
+ I: Integer;
+begin
+ for I:=0 to 191 do
+ Case I of
+ 15: fIdentFuncTable[I]:={$IFDEF FPC}@{$ENDIF}Func15;
+ 19: fIdentFuncTable[I]:={$IFDEF FPC}@{$ENDIF}Func19;
+ 20: fIdentFuncTable[I]:={$IFDEF FPC}@{$ENDIF}Func20;
+ 21: fIdentFuncTable[I]:={$IFDEF FPC}@{$ENDIF}Func21;
+ 23: fIdentFuncTable[I]:={$IFDEF FPC}@{$ENDIF}Func23;
+ 25: fIdentFuncTable[I]:={$IFDEF FPC}@{$ENDIF}Func25;
+ 27: fIdentFuncTable[I]:={$IFDEF FPC}@{$ENDIF}Func27;
+ 28: fIdentFuncTable[I]:={$IFDEF FPC}@{$ENDIF}Func28;
+ 29: fIdentFuncTable[I]:={$IFDEF FPC}@{$ENDIF}Func29;
+ 32: fIdentFuncTable[I]:={$IFDEF FPC}@{$ENDIF}Func32;
+ 33: fIdentFuncTable[I]:={$IFDEF FPC}@{$ENDIF}Func33;
+ 35: fIdentFuncTable[I]:={$IFDEF FPC}@{$ENDIF}Func35;
+ 37: fIdentFuncTable[I]:={$IFDEF FPC}@{$ENDIF}Func37;
+ 38: fIdentFuncTable[I]:={$IFDEF FPC}@{$ENDIF}Func38;
+ 39: fIdentFuncTable[I]:={$IFDEF FPC}@{$ENDIF}Func39;
+ 40: fIdentFuncTable[I]:={$IFDEF FPC}@{$ENDIF}Func40;
+ 41: fIdentFuncTable[I]:={$IFDEF FPC}@{$ENDIF}Func41;
+ 44: fIdentFuncTable[I]:={$IFDEF FPC}@{$ENDIF}Func44;
+ 45: fIdentFuncTable[I]:={$IFDEF FPC}@{$ENDIF}Func45;
+ 47: fIdentFuncTable[I]:={$IFDEF FPC}@{$ENDIF}Func47;
+ 49: fIdentFuncTable[I]:={$IFDEF FPC}@{$ENDIF}Func49;
+ 52: fIdentFuncTable[I]:={$IFDEF FPC}@{$ENDIF}Func52;
+ 54: fIdentFuncTable[I]:={$IFDEF FPC}@{$ENDIF}Func54;
+ 55: fIdentFuncTable[I]:={$IFDEF FPC}@{$ENDIF}Func55;
+ 56: fIdentFuncTable[I]:={$IFDEF FPC}@{$ENDIF}Func56;
+ 57: fIdentFuncTable[I]:={$IFDEF FPC}@{$ENDIF}Func57;
+ 59: fIdentFuncTable[I]:={$IFDEF FPC}@{$ENDIF}Func59;
+ 60: fIdentFuncTable[I]:={$IFDEF FPC}@{$ENDIF}Func60;
+ 61: fIdentFuncTable[I]:={$IFDEF FPC}@{$ENDIF}Func61;
+ 63: fIdentFuncTable[I]:={$IFDEF FPC}@{$ENDIF}Func63;
+ 64: fIdentFuncTable[I]:={$IFDEF FPC}@{$ENDIF}Func64;
+ 65: fIdentFuncTable[I]:={$IFDEF FPC}@{$ENDIF}Func65;
+ 66: fIdentFuncTable[I]:={$IFDEF FPC}@{$ENDIF}Func66;
+ 69: fIdentFuncTable[I]:={$IFDEF FPC}@{$ENDIF}Func69;
+ 71: fIdentFuncTable[I]:={$IFDEF FPC}@{$ENDIF}Func71;
+ 73: fIdentFuncTable[I]:={$IFDEF FPC}@{$ENDIF}Func73;
+ 75: fIdentFuncTable[I]:={$IFDEF FPC}@{$ENDIF}Func75;
+ 76: fIdentFuncTable[I]:={$IFDEF FPC}@{$ENDIF}Func76;
+ 79: fIdentFuncTable[I]:={$IFDEF FPC}@{$ENDIF}Func79;
+ 81: fIdentFuncTable[I]:={$IFDEF FPC}@{$ENDIF}Func81;
+ 84: fIdentFuncTable[I]:={$IFDEF FPC}@{$ENDIF}Func84;
+ 85: fIdentFuncTable[I]:={$IFDEF FPC}@{$ENDIF}Func85;
+ 87: fIdentFuncTable[I]:={$IFDEF FPC}@{$ENDIF}Func87;
+ 88: fIdentFuncTable[I]:={$IFDEF FPC}@{$ENDIF}Func88;
+ 91: fIdentFuncTable[I]:={$IFDEF FPC}@{$ENDIF}Func91;
+ 92: fIdentFuncTable[I]:={$IFDEF FPC}@{$ENDIF}Func92;
+ 94: fIdentFuncTable[I]:={$IFDEF FPC}@{$ENDIF}Func94;
+ 95: fIdentFuncTable[I]:={$IFDEF FPC}@{$ENDIF}Func95;
+ 96: fIdentFuncTable[I]:={$IFDEF FPC}@{$ENDIF}Func96;
+ 97: fIdentFuncTable[I]:={$IFDEF FPC}@{$ENDIF}Func97;
+ 98: fIdentFuncTable[I]:={$IFDEF FPC}@{$ENDIF}Func98;
+ 99: fIdentFuncTable[I]:={$IFDEF FPC}@{$ENDIF}Func99;
+ 100: fIdentFuncTable[I]:={$IFDEF FPC}@{$ENDIF}Func100;
+ 101: fIdentFuncTable[I]:={$IFDEF FPC}@{$ENDIF}Func101;
+ 102: fIdentFuncTable[I]:={$IFDEF FPC}@{$ENDIF}Func102;
+ 103: fIdentFuncTable[I]:={$IFDEF FPC}@{$ENDIF}Func103;
+ 105: fIdentFuncTable[I]:={$IFDEF FPC}@{$ENDIF}Func105;
+ 106: fIdentFuncTable[I]:={$IFDEF FPC}@{$ENDIF}Func106;
+ 117: fIdentFuncTable[I]:={$IFDEF FPC}@{$ENDIF}Func117;
+ 126: fIdentFuncTable[I]:={$IFDEF FPC}@{$ENDIF}Func126;
+ 129: fIdentFuncTable[I]:={$IFDEF FPC}@{$ENDIF}Func129;
+ 132: fIdentFuncTable[I]:={$IFDEF FPC}@{$ENDIF}Func132;
+ 133: fIdentFuncTable[I]:={$IFDEF FPC}@{$ENDIF}Func133;
+ 136: fIdentFuncTable[I]:={$IFDEF FPC}@{$ENDIF}Func136;
+ 141: fIdentFuncTable[I]:={$IFDEF FPC}@{$ENDIF}Func141;
+ 143: fIdentFuncTable[I]:={$IFDEF FPC}@{$ENDIF}Func143;
+ 166: fIdentFuncTable[I]:={$IFDEF FPC}@{$ENDIF}Func166;
+ 168: fIdentFuncTable[I]:={$IFDEF FPC}@{$ENDIF}Func168;
+ 191: fIdentFuncTable[I]:={$IFDEF FPC}@{$ENDIF}Func191;
+ else fIdentFuncTable[I]:={$IFDEF FPC}@{$ENDIF}AltFunc;
+ end;
+end;
+
+function TmwPasLex.KeyHash(ToHash: PChar): Integer;
+begin
+ Result:=0;
+ while ToHash^in ['a'..'z', 'A'..'Z']do
+ begin
+ Inc(Result, mHashTable[ToHash^]);
+ Inc(ToHash);
+ end;
+ if ToHash^in ['_', '0'..'9']then Inc(ToHash);
+ fStringLen:=ToHash-fToIdent;
+end; { KeyHash }
+
+function TmwPasLex.KeyComp(const aKey: string): Boolean;
+var
+ I: Integer;
+begin
+ Temp:=fToIdent;
+ if Length(aKey)=fStringLen then
+ begin
+ Result:=True;
+ for i:=1 to fStringLen do
+ begin
+ if mHashTable[Temp^]<>mHashTable[aKey[i]]then
+ begin
+ Result:=False;
+ Break;
+ end;
+ Inc(Temp);
+ end;
+ end else Result:=False;
+end; { KeyComp }
+
+function TmwPasLex.Func15: TTokenKind;
+begin
+ if KeyComp('If')then Result:=tkIf else Result:=tkIdentifier;
+end;
+
+function TmwPasLex.Func19: TTokenKind;
+begin
+ if KeyComp('Do')then Result:=tkDo else
+ if KeyComp('And')then Result:=tkAnd else Result:=tkIdentifier;
+end;
+
+function TmwPasLex.Func20: TTokenKind;
+begin
+ if KeyComp('As')then Result:=tkAs else Result:=tkIdentifier;
+end;
+
+function TmwPasLex.Func21: TTokenKind;
+begin
+ if KeyComp('Of')then Result:=tkOf else
+ if KeyComp('At')then Result:=tkAt else Result:=tkIdentifier;
+end;
+
+function TmwPasLex.Func23: TTokenKind;
+begin
+ if KeyComp('End')then Result:=tkEnd else
+ if KeyComp('In')then Result:=tkIn else Result:=tkIdentifier;
+end;
+
+function TmwPasLex.Func25: TTokenKind;
+begin
+ if KeyComp('Far')then Result:=tkFar else Result:=tkIdentifier;
+end;
+
+function TmwPasLex.Func27: TTokenKind;
+begin
+ if KeyComp('Cdecl')then Result:=tkCdecl else Result:=tkIdentifier;
+end;
+
+function TmwPasLex.Func28: TTokenKind;
+begin
+ if KeyComp('Read')then
+ begin
+ if inSymbols(CharAhead(fStringLen))then Result:=tkIdentifier else
+ Result:=tkRead
+ end else
+ if KeyComp('Case')then Result:=tkCase else
+ if KeyComp('Is')then Result:=tkIs else Result:=tkIdentifier;
+end;
+
+function TmwPasLex.Func29: TTokenKind;
+begin
+ if KeyComp('On')then Result:=tkOn else Result:=tkIdentifier;
+end;
+
+function TmwPasLex.Func32: TTokenKind;
+begin
+ if KeyComp('File')then Result:=tkFile else
+ if KeyComp('Label')then Result:=tkLabel else
+ if KeyComp('Mod')then Result:=tkMod else Result:=tkIdentifier;
+end;
+
+function TmwPasLex.Func33: TTokenKind;
+begin
+ if KeyComp('Or')then Result:=tkOr else
+ if KeyComp('Name')then
+ begin
+ if inSymbols(CharAhead(fStringLen))then Result:=tkIdentifier else
+ Result:=tkName
+ end else
+ if KeyComp('Asm')then Result:=tkAsm else Result:=tkIdentifier;
+end;
+
+function TmwPasLex.Func35: TTokenKind;
+begin
+ if KeyComp('To')then Result:=tkTo else
+ if KeyComp('Nil')then Result:=tkNil else
+ if KeyComp('Div')then Result:=tkDiv else Result:=tkIdentifier;
+end;
+
+function TmwPasLex.Func37: TTokenKind;
+begin
+ if KeyComp('Begin')then Result:=tkBegin else Result:=tkIdentifier;
+end;
+
+function TmwPasLex.Func38: TTokenKind;
+begin
+ if KeyComp('Near')then Result:=tkNear else Result:=tkIdentifier;
+end;
+
+function TmwPasLex.Func39: TTokenKind;
+begin
+ if KeyComp('For')then Result:=tkFor else
+ if KeyComp('Shl')then Result:=tkShl else Result:=tkIdentifier;
+end;
+
+function TmwPasLex.Func40: TTokenKind;
+begin
+ if KeyComp('Packed')then Result:=tkPacked else Result:=tkIdentifier;
+end;
+
+function TmwPasLex.Func41: TTokenKind;
+begin
+ if KeyComp('Else')then Result:=tkElse else
+ if KeyComp('Var')then Result:=tkVar else Result:=tkIdentifier;
+end;
+
+function TmwPasLex.Func44: TTokenKind;
+begin
+ if KeyComp('Set')then Result:=tkSet else Result:=tkIdentifier;
+end;
+
+function TmwPasLex.Func45: TTokenKind;
+begin
+ if KeyComp('Shr')then Result:=tkShr else Result:=tkIdentifier;
+end;
+
+function TmwPasLex.Func47: TTokenKind;
+begin
+ if KeyComp('Then')then Result:=tkThen else Result:=tkIdentifier;
+end;
+
+function TmwPasLex.Func49: TTokenKind;
+begin
+ if KeyComp('Not')then Result:=tkNot else Result:=tkIdentifier;
+end;
+
+function TmwPasLex.Func52: TTokenKind;
+begin
+ if KeyComp('Raise')then Result:=tkRaise else
+ if KeyComp('Pascal')then Result:=tkPascal else Result:=tkIdentifier;
+end;
+
+function TmwPasLex.Func54: TTokenKind;
+begin
+ if KeyComp('Class')then
+ begin
+ Result:=tkClass;
+ if fLastNoSpace=tkEqual then
+ begin
+ fIsClass:=True;
+ if Identifiers[CharAhead(fStringLen)]then fIsClass:=False;
+ end else fIsClass:=False;
+ end else Result:=tkIdentifier;
+end;
+
+function TmwPasLex.Func55: TTokenKind;
+begin
+ if KeyComp('Object')then Result:=tkObject else Result:=tkIdentifier;
+end;
+
+function TmwPasLex.Func56: TTokenKind;
+begin
+ if KeyComp('Index')then
+ begin
+ if inSymbols(CharAhead(fStringLen))then Result:=tkIdentifier else
+ Result:=tkIndex
+ end else
+ if KeyComp('Out')then Result:=tkOut else Result:=tkIdentifier;
+end;
+
+function TmwPasLex.Func57: TTokenKind;
+begin
+ if KeyComp('While')then Result:=tkWhile else
+ if KeyComp('Goto')then Result:=tkGoto else
+ if KeyComp('Xor')then Result:=tkXor else Result:=tkIdentifier;
+end;
+
+function TmwPasLex.Func59: TTokenKind;
+begin
+ if KeyComp('Safecall')then Result:=tkSafecall else Result:=tkIdentifier;
+end;
+
+function TmwPasLex.Func60: TTokenKind;
+begin
+ if KeyComp('With')then Result:=tkWith else Result:=tkIdentifier;
+end;
+
+function TmwPasLex.Func61: TTokenKind;
+begin
+ if KeyComp('Dispid')then Result:=tkDispid else Result:=tkIdentifier;
+end;
+
+function TmwPasLex.Func63: TTokenKind;
+begin
+ if KeyComp('Public')then
+ begin
+ if inSymbols(CharAhead(fStringLen))then Result:=tkIdentifier else
+ Result:=tkPublic
+ end else
+ if KeyComp('Record')then Result:=tkRecord else
+ if KeyComp('Try')then Result:=tkTry else
+ if KeyComp('Array')then Result:=tkArray else
+ if KeyComp('Inline')then Result:=tkInline else Result:=tkIdentifier;
+end;
+
+function TmwPasLex.Func64: TTokenKind;
+begin
+ if KeyComp('Uses')then Result:=tkUses else
+ if KeyComp('Unit')then Result:=tkUnit else Result:=tkIdentifier;
+end;
+
+function TmwPasLex.Func65: TTokenKind;
+begin
+ if KeyComp('Repeat')then Result:=tkRepeat else Result:=tkIdentifier;
+end;
+
+function TmwPasLex.Func66: TTokenKind;
+begin
+ if KeyComp('Type')then Result:=tkType else Result:=tkIdentifier;
+end;
+
+function TmwPasLex.Func69: TTokenKind;
+begin
+ if KeyComp('Dynamic')then Result:=tkDynamic else
+ if KeyComp('Default')then Result:=tkDefault else
+ if KeyComp('Message')then Result:=tkMessage else Result:=tkIdentifier;
+end;
+
+function TmwPasLex.Func71: TTokenKind;
+begin
+ if KeyComp('Stdcall')then Result:=tkStdcall else
+ if KeyComp('Const')then Result:=tkConst else Result:=tkIdentifier;
+end;
+
+function TmwPasLex.Func73: TTokenKind;
+begin
+ if KeyComp('Except')then Result:=tkExcept else Result:=tkIdentifier;
+end;
+
+function TmwPasLex.Func75: TTokenKind;
+begin
+ if KeyComp('Write')then
+ begin
+ if inSymbols(CharAhead(fStringLen))then Result:=tkIdentifier else
+ Result:=tkWrite
+ end else Result:=tkIdentifier;
+end;
+
+function TmwPasLex.Func76: TTokenKind;
+begin
+ if KeyComp('Until')then Result:=tkUntil else Result:=tkIdentifier;
+end;
+
+function TmwPasLex.Func79: TTokenKind;
+begin
+ if KeyComp('Finally')then Result:=tkFinally else Result:=tkIdentifier;
+end;
+
+function TmwPasLex.Func81: TTokenKind;
+begin
+ if KeyComp('Interface')then
+ begin
+ Result:=tkInterface;
+ if fLastNoSpace=tkEqual then
+ fIsInterface:=True else fIsInterface:=False;
+ end else
+ if KeyComp('Stored')then Result:=tkStored else Result:=tkIdentifier;
+end;
+
+function TmwPasLex.Func84: TTokenKind;
+begin
+ if KeyComp('Abstract')then Result:=tkAbstract else Result:=tkIdentifier;
+end;
+
+function TmwPasLex.Func85: TTokenKind;
+begin
+ if KeyComp('Library')then Result:=tkLibrary else
+ if KeyComp('Forward')then Result:=tkForward else Result:=tkIdentifier;
+end;
+
+function TmwPasLex.Func87: TTokenKind;
+begin
+ if KeyComp('String')then Result:=tkString else Result:=tkIdentifier;
+end;
+
+function TmwPasLex.Func88: TTokenKind;
+begin
+ if KeyComp('Program')then Result:=tkProgram else Result:=tkIdentifier;
+end;
+
+function TmwPasLex.Func91: TTokenKind;
+begin
+ if KeyComp('Private')then
+ begin
+ if inSymbols(CharAhead(fStringLen))then Result:=tkIdentifier else
+ Result:=tkPrivate
+ end else
+ if KeyComp('Downto')then Result:=tkDownto else Result:=tkIdentifier;
+end;
+
+function TmwPasLex.Func92: TTokenKind;
+begin
+ if KeyComp('overload') then
+ Result:=tkOverload
+ else
+ if KeyComp('Inherited') then
+ Result:=tkInherited
+ else
+ Result:=tkIdentifier;
+end;
+
+function TmwPasLex.Func94: TTokenKind;
+begin
+ if KeyComp('Resident')then Result:=tkResident else
+ if KeyComp('Readonly')then Result:=tkReadonly else
+ if KeyComp('Assembler')then Result:=tkAssembler else Result:=tkIdentifier;
+end;
+
+function TmwPasLex.Func95: TTokenKind;
+begin
+ if KeyComp('Absolute')then Result:=tkAbsolute else Result:=tkIdentifier;
+end;
+
+function TmwPasLex.Func96: TTokenKind;
+begin
+ if KeyComp('Published')then
+ begin
+ if inSymbols(CharAhead(fStringLen))then Result:=tkIdentifier else
+ Result:=tkPublished
+ end else
+ if KeyComp('Override')then Result:=tkOverride else Result:=tkIdentifier;
+end;
+
+function TmwPasLex.Func97: TTokenKind;
+begin
+ if KeyComp('Threadvar')then Result:=tkThreadvar else Result:=tkIdentifier;
+end;
+
+function TmwPasLex.Func98: TTokenKind;
+begin
+ if KeyComp('Export')then Result:=tkExport else
+ if KeyComp('Nodefault')then Result:=tkNodefault else Result:=tkIdentifier;
+end;
+
+function TmwPasLex.Func99: TTokenKind;
+begin
+ if KeyComp('External')then Result:=tkExternal else Result:=tkIdentifier;
+end;
+
+function TmwPasLex.Func100: TTokenKind;
+begin
+ if KeyComp('Automated')then
+ begin
+ if inSymbols(CharAhead(fStringLen))then Result:=tkIdentifier else
+ Result:=tkAutomated
+ end else Result:=tkIdentifier;
+end;
+
+function TmwPasLex.Func101: TTokenKind;
+begin
+ if KeyComp('Register')then Result:=tkRegister else Result:=tkIdentifier;
+end;
+
+function TmwPasLex.Func102: TTokenKind;
+begin
+ if KeyComp('Function')then Result:=tkFunction else Result:=tkIdentifier;
+end;
+
+function TmwPasLex.Func103: TTokenKind;
+begin
+ if KeyComp('Virtual')then Result:=tkVirtual else Result:=tkIdentifier;
+end;
+
+function TmwPasLex.Func105: TTokenKind;
+begin
+ if KeyComp('Procedure')then Result:=tkProcedure else Result:=tkIdentifier;
+end;
+
+function TmwPasLex.Func106: TTokenKind;
+begin
+ if KeyComp('Protected')then
+ begin
+ if inSymbols(CharAhead(fStringLen))then Result:=tkIdentifier else
+ Result:=tkProtected
+ end else Result:=tkIdentifier;
+end;
+
+function TmwPasLex.Func117: TTokenKind;
+begin
+ if KeyComp('Exports')then Result:=tkExports else Result:=tkIdentifier;
+end;
+
+function TmwPasLex.Func126: TTokenKind;
+begin
+ if KeyComp('Implements') then
+ Result:=tkImplements
+ else
+ Result:=tkIdentifier;
+end;
+
+function TmwPasLex.Func129: TTokenKind;
+begin
+ if KeyComp('Dispinterface')then Result:=tkDispinterface else Result:=tkIdentifier;
+end;
+
+function TmwPasLex.Func132: TTokenKind;
+begin
+ if KeyComp('Reintroduce') then
+ Result:=tkReintroduce
+ else
+ Result:=tkIdentifier;
+end;
+
+function TmwPasLex.Func133: TTokenKind;
+begin
+ if KeyComp('Property')then Result:=tkProperty else Result:=tkIdentifier;
+end;
+
+function TmwPasLex.Func136: TTokenKind;
+begin
+ if KeyComp('Finalization')then Result:=tkFinalization else Result:=tkIdentifier;
+end;
+
+function TmwPasLex.Func141: TTokenKind;
+begin
+ if KeyComp('Writeonly')then Result:=tkWriteonly else Result:=tkIdentifier;
+end;
+
+function TmwPasLex.Func143: TTokenKind;
+begin
+ if KeyComp('Destructor')then Result:=tkDestructor else Result:=tkIdentifier;
+end;
+
+function TmwPasLex.Func166: TTokenKind;
+begin
+ if KeyComp('Constructor')then Result:=tkConstructor else
+ if KeyComp('Implementation')then Result:=tkImplementation else Result:=tkIdentifier;
+end;
+
+function TmwPasLex.Func168: TTokenKind;
+begin
+ if KeyComp('Initialization')then Result:=tkInitialization else Result:=tkIdentifier;
+end;
+
+function TmwPasLex.Func191: TTokenKind;
+begin
+ if KeyComp('Resourcestring')then Result:=tkResourcestring else
+ if KeyComp('Stringresource')then Result:=tkStringresource else Result:=tkIdentifier;
+end;
+
+function TmwPasLex.AltFunc: TTokenKind;
+begin
+ Result:=tkIdentifier
+end;
+
+function TmwPasLex.IdentKind(MayBe: PChar): TTokenKind;
+var
+ HashKey: Integer;
+begin
+ fToIdent:=MayBe;
+ HashKey:=KeyHash(MayBe);
+ if HashKey<192 then
+ Result:=fIdentFuncTable[HashKey]()
+ else
+ Result:=tkIdentifier;
+end;
+
+procedure TmwPasLex.MakeMethodTables;
+var
+ I: Char;
+begin
+ for I:=#0 to #255 do
+ case I of
+ #0: fProcTable[I]:={$IFDEF FPC}@{$ENDIF}NullProc;
+ #10: fProcTable[I]:={$IFDEF FPC}@{$ENDIF}LFProc;
+ #13: fProcTable[I]:={$IFDEF FPC}@{$ENDIF}CRProc;
+ #1..#9, #11, #12, #14..#32:
+ fProcTable[I]:={$IFDEF FPC}@{$ENDIF}SpaceProc;
+ '#': fProcTable[I]:={$IFDEF FPC}@{$ENDIF}AsciiCharProc;
+ '$': fProcTable[I]:={$IFDEF FPC}@{$ENDIF}IntegerProc;
+ #39: fProcTable[I]:={$IFDEF FPC}@{$ENDIF}StringProc;
+ '0'..'9': fProcTable[I]:={$IFDEF FPC}@{$ENDIF}NumberProc;
+ 'A'..'Z', 'a'..'z', '_':
+ fProcTable[I]:={$IFDEF FPC}@{$ENDIF}IdentProc;
+ '{': fProcTable[I]:={$IFDEF FPC}@{$ENDIF}BraceOpenProc;
+ '}': fProcTable[I]:={$IFDEF FPC}@{$ENDIF}BraceCloseProc;
+ '!', '"', '%', '&', '('..'/', ':'..'@', '['..'^', '`', '~':
+ begin
+ case I of
+ '(': fProcTable[I]:={$IFDEF FPC}@{$ENDIF}RoundOpenProc;
+ ')': fProcTable[I]:={$IFDEF FPC}@{$ENDIF}RoundCloseProc;
+ '*': fProcTable[I]:={$IFDEF FPC}@{$ENDIF}StarProc;
+ '+': fProcTable[I]:={$IFDEF FPC}@{$ENDIF}PlusProc;
+ ',': fProcTable[I]:={$IFDEF FPC}@{$ENDIF}CommaProc;
+ '-': fProcTable[I]:={$IFDEF FPC}@{$ENDIF}MinusProc;
+ '.': fProcTable[I]:={$IFDEF FPC}@{$ENDIF}PointProc;
+ '/': fProcTable[I]:={$IFDEF FPC}@{$ENDIF}SlashProc;
+ ':': fProcTable[I]:={$IFDEF FPC}@{$ENDIF}ColonProc;
+ ';': fProcTable[I]:={$IFDEF FPC}@{$ENDIF}SemiColonProc;
+ '<': fProcTable[I]:={$IFDEF FPC}@{$ENDIF}LowerProc;
+ '=': fProcTable[I]:={$IFDEF FPC}@{$ENDIF}EqualProc;
+ '>': fProcTable[I]:={$IFDEF FPC}@{$ENDIF}GreaterProc;
+ '@': fProcTable[I]:={$IFDEF FPC}@{$ENDIF}AddressOpProc;
+ '[': fProcTable[I]:={$IFDEF FPC}@{$ENDIF}SquareOpenProc;
+ ']': fProcTable[I]:={$IFDEF FPC}@{$ENDIF}SquareCloseProc;
+ '^': fProcTable[I]:={$IFDEF FPC}@{$ENDIF}PointerSymbolProc;
+ else fProcTable[I]:={$IFDEF FPC}@{$ENDIF}SymbolProc;
+ end;
+ end;
+ else fProcTable[I]:={$IFDEF FPC}@{$ENDIF}UnknownProc;
+ end;
+end;
+
+constructor TmwPasLex.Create;
+begin
+ inherited Create;
+ InitIdent;
+ MakeMethodTables;
+end; { Create }
+
+destructor TmwPasLex.Destroy;
+begin
+ inherited Destroy;
+end; { Destroy }
+
+procedure TmwPasLex.SetOrigin(NewValue: PChar);
+begin
+ fOrigin:=NewValue;
+ fComment:=csNo;
+ fLineNumber:=0;
+ fLinePos:=0;
+ Run:=0;
+ Next;
+end; { SetOrigin }
+
+procedure TmwPasLex.SetRunPos(Value: Integer);
+begin
+ Run:=Value;
+ Next;
+end;
+
+procedure TmwPasLex.AddressOpProc;
+begin
+ Case FOrigin[Run+1]of
+ '@':
+ begin
+ fTokenID:=tkDoubleAddressOp;
+ Inc(Run, 2);
+ end;
+ else
+ begin
+ fTokenID:=tkAddressOp;
+ Inc(Run);
+ end;
+ end;
+end;
+
+procedure TmwPasLex.AsciiCharProc;
+begin
+ fTokenID:=tkAsciiChar;
+ Inc(Run);
+ while FOrigin[Run]in ['0'..'9']do Inc(Run);
+end;
+
+procedure TmwPasLex.BraceCloseProc;
+begin
+ Inc(Run);
+ fTokenId:=tkError;
+end;
+
+procedure TmwPasLex.BorProc;
+begin
+ fTokenID:=tkBorComment;
+ case FOrigin[Run]of
+ #0:
+ begin
+ NullProc;
+ Exit;
+ end;
+
+ #10:
+ begin
+ LFProc;
+ Exit;
+ end;
+
+ #13:
+ begin
+ CRProc;
+ Exit;
+ end;
+ end;
+
+ while FOrigin[Run]<>#0 do
+ case FOrigin[Run]of
+ '}':
+ begin
+ fComment:=csNo;
+ Inc(Run);
+ Break;
+ end;
+ #10: Break;
+
+ #13: Break;
+ else Inc(Run);
+ end;
+end;
+
+procedure TmwPasLex.BraceOpenProc;
+var
+ i: Integer;
+ s: string;
+begin
+ Case FOrigin[Run+1]of
+ '$': fTokenID:=tkCompDirect;
+ '.':
+ begin
+ fComment := csBor;
+ i := 1;
+ while (FOrigin[Run + 1 + i] <> #0) and (i <= 8) do
+ begin
+ s := s + FOrigin[Run + 1 + i];
+ Inc(i);
+ end;
+ if (AnsiCompareText(s, 'include ') = 0) then
+ begin
+ //Inc(Run, 8);
+ fTokenID := tkInclude;
+ end;
+ end
+ else
+ begin
+ fTokenID:=tkBorComment;
+ fComment:=csBor;
+ end;
+ end;
+ Inc(Run);
+ while FOrigin[Run]<>#0 do
+ case FOrigin[Run]of
+ '}':
+ begin
+ fComment:=csNo;
+ Inc(Run);
+ Break;
+ end;
+ #10: Break;
+
+ #13: Break;
+ else Inc(Run);
+ end;
+end;
+
+procedure TmwPasLex.ColonProc;
+begin
+ Case FOrigin[Run+1]of
+ '=':
+ begin
+ Inc(Run, 2);
+ fTokenID:=tkAssign;
+ end;
+ else
+ begin
+ Inc(Run);
+ fTokenID:=tkColon;
+ end;
+ end;
+end;
+
+procedure TmwPasLex.CommaProc;
+begin
+ Inc(Run);
+ fTokenID:=tkComma;
+end;
+
+procedure TmwPasLex.CRProc;
+begin
+ Case fComment of
+ csBor: fTokenID:=tkCRLFCo;
+ csAnsi: fTokenID:=tkCRLFCo;
+ else fTokenID:=tkCRLF;
+ end;
+
+ Case FOrigin[Run+1]of
+ #10: Inc(Run, 2);
+ else Inc(Run);
+ end;
+ Inc(fLineNumber);
+ fLinePos:=Run;
+end;
+
+procedure TmwPasLex.EqualProc;
+begin
+ Inc(Run);
+ fTokenID:=tkEqual;
+end;
+
+procedure TmwPasLex.GreaterProc;
+begin
+ Case FOrigin[Run+1]of
+ '=':
+ begin
+ Inc(Run, 2);
+ fTokenID:=tkGreaterEqual;
+ end;
+ else
+ begin
+ Inc(Run);
+ fTokenID:=tkGreater;
+ end;
+ end;
+end;
+
+function TmwPasLex.InSymbols(aChar: Char): Boolean;
+begin
+ if aChar in ['#', '$', '&', #39, '(', ')', '*', '+', ',', '–', '.', '/', ':',
+ ';', '<', '=', '>', '@', '[', ']', '^']then Result:=True else Result:=False;
+end;
+
+function TmwPasLex.CharAhead(Count: Integer): Char;
+begin
+ Temp:=fOrigin+Run+Count;
+ while Temp^in [#1..#9, #11, #12, #14..#32]do Inc(Temp);
+ Result:=Temp^;
+end;
+
+Function TokeToString(Toke : TTokenKind) : string;
+begin;
+ case toke of
+ tkAbsolute: result := 'tkAbsolute';
+ tkAbstract: result := 'tkAbstract';
+ tkAddressOp: result := 'tkAddressOp';
+ tkAnd: result := 'tkAnd';
+ tkAnsiComment: result := 'tkAnsiComment';
+ tkArray: result := 'tkArray';
+ tkAs: result := 'tkAs';
+ tkAt: result := 'tkAt';
+ tkAsciiChar: result := 'tkAsciiChar';
+ tkAsm: result := 'tkAsm';
+ tkAssembler: result := 'tkAssembler';
+ tkAssign: result := 'tkAssign';
+ tkAutomated: result := 'tkAutomated';
+ tkBegin: result := 'tkBegin';
+ tkBadString: result := 'tkBadString';
+ tkBorComment: result := 'tkBorComment';
+ tkCase: result := 'tkCase';
+ tkCdecl: result := 'tkCdecl';
+ tkClass: result := 'tkClass';
+ tkColon: result := 'tkColon';
+ tkComma: result := 'tkComma';
+ tkCompDirect: result := 'tkCompDirect';
+ tkConst: result := 'tkConst';
+ tkConstructor: result := 'tkConstructor';
+ tkCRLF: result := 'tkCRLF';
+ tkCRLFCo: result := 'tkCRLFCo';
+ tkDefault: result := 'tkDefault';
+ tkDestructor: result := 'tkDestructor';
+ tkDispid: result := 'tkDispid';
+ tkDispinterface: result := 'tkDispinterface';
+ tkDiv: result := 'tkDiv';
+ tkDo: result := 'tkDo';
+ tkDoubleAddressOp: result := 'tkDoubleAddressOp';
+ tkDotDot: result := 'tkDotDot';
+ tkDownto: result := 'tkDownto';
+ tkDynamic: result := 'tkDynamic';
+ tkElse: result := 'tkElse';
+ tkEnd: result := 'tkEnd';
+ tkEqual: result := 'tkEqual';
+ tkError: result := 'tkError';
+ tkExcept: result := 'tkExcept';
+ tkExport: result := 'tkExport';
+ tkExports: result := 'tkExports';
+ tkExternal: result := 'tkExternal';
+ tkFar: result := 'tkFar';
+ tkFile: result := 'tkFile';
+ tkFinalization: result := 'tkFinalization';
+ tkFinally: result := 'tkFinally';
+ tkFloat: result := 'tkFloat';
+ tkFor: result := 'tkFor';
+ tkForward: result := 'tkForward';
+ tkFunction: result := 'tkFunction';
+ tkGoto: result := 'tkGoto';
+ tkGreater: result := 'tkGreater';
+ tkGreaterEqual: result := 'tkGreaterEqual';
+ tkIdentifier: result := 'tkIdentifier';
+ tkIf: result := 'tkIf';
+ tkImplementation: result := 'tkImplementation';
+ tkImplements: result := 'tkImplements';
+ tkIn: result := 'tkIn';
+ tkINCLUDE: result := 'tkINCLUDE';
+ tkIndex: result := 'tkIndex';
+ tkInherited: result := 'tkInherited';
+ tkInitialization: result := 'tkInitialization';
+ tkInline: result := 'tkInline';
+ tkInteger: result := 'tkInteger';
+ tkInterface: result := 'tkInterface';
+ tkIs: result := 'tkIs';
+ tkKeyString: result := 'tkKeyString';
+ tkLabel: result := 'tkLabel';
+ tkLibrary: result := 'tkLibrary';
+ tkLower: result := 'tkLower';
+ tkLowerEqual: result := 'tkLowerEqual';
+ tkMessage: result := 'tkMessage';
+ tkMinus: result := 'tkMinus';
+ tkMod: result := 'tkMod';
+ tkName: result := 'tkName';
+ tkNear: result := 'tkNear';
+ tkNil: result := 'tkNil';
+ tkNodefault: result := 'tkNodefault';
+ tkNone: result := 'tkNone';
+ tkNot: result := 'tkNot';
+ tkNotEqual: result := 'tkNotEqual';
+ tkNull: result := 'tkNull';
+ tkNumber: result := 'tkNumber';
+ tkObject: result := 'tkObject';
+ tkOf: result := 'tkOf';
+ tkOn: result := 'tkOn';
+ tkOr: result := 'tkOr';
+ tkOut: result := 'tkOut';
+ tkOverload: result := 'tkOverload';
+ tkOverride: result := 'tkOverride';
+ tkPacked: result := 'tkPacked';
+ tkPascal: result := 'tkPascal';
+ tkPlus: result := 'tkPlus';
+ tkPoint: result := 'tkPoint';
+ tkPointerSymbol: result := 'tkPointerSymbol';
+ tkPrivate: result := 'tkPrivate';
+ tkProcedure: result := 'tkProcedure';
+ tkProgram: result := 'tkProgram';
+ tkProperty: result := 'tkProperty';
+ tkProtected: result := 'tkProtected';
+ tkPublic: result := 'tkPublic';
+ tkPublished: result := 'tkPublished';
+ tkRaise: result := 'tkRaise';
+ tkRead: result := 'tkRead';
+ tkReadonly: result := 'tkReadonly';
+ tkRecord: result := 'tkRecord';
+ tkRegister: result := 'tkRegister';
+ tkReintroduce: result := 'tkReintroduce';
+ tkRepeat: result := 'tkRepeat';
+ tkResident: result := 'tkResident';
+ tkResourcestring: result := 'tkResourcestring';
+ tkRoundClose: result := 'tkRoundClose';
+ tkRoundOpen: result := 'tkRoundOpen';
+ tkSafecall: result := 'tkSafecall';
+ tkSemiColon: result := 'tkSemiColon';
+ tkSet: result := 'tkSet';
+ tkShl: result := 'tkShl';
+ tkShr: result := 'tkShr';
+ tkSlash: result := 'tkSlash';
+ tkSlashesComment: result := 'tkSlashesComment';
+ tkSquareClose: result := 'tkSquareClose';
+ tkSquareOpen: result := 'tkSquareOpen';
+ tkSpace: result := 'tkSpace';
+ tkStar: result := 'tkStar';
+ tkStdcall: result := 'tkStdcall';
+ tkStored: result := 'tkStored';
+ tkString: result := 'tkString';
+ tkStringresource: result := 'tkStringresource';
+ tkSymbol: result := 'tkSymbol';
+ tkThen: result := 'tkThen';
+ tkThreadvar: result := 'tkThreadvar';
+ tkTo: result := 'tkTo';
+ tkTry: result := 'tkTry';
+ tkType: result := 'tkType';
+ tkUnit: result := 'tkUnit';
+ tkUnknown: result := 'tkUnknown';
+ tkUntil: result := 'tkUntil';
+ tkUses: result := 'tkUses';
+ tkVar: result := 'tkVar';
+ tkVirtual: result := 'tkVirtual';
+ tkWhile: result := 'tkWhile';
+ tkWith: result := 'tkWith';
+ tkWrite: result := 'tkWrite';
+ tkWriteonly: result := 'tkWriteonly';
+ tkXor: Result := 'tkXor';
+ end;
+end;
+
+procedure TmwPasLex.IdentProc;
+begin
+ fTokenID:=IdentKind((fOrigin+Run));
+ Inc(Run, fStringLen);
+ while Identifiers[fOrigin[Run]]do Inc(Run);
+end;
+
+procedure TmwPasLex.IntegerProc;
+begin
+ Inc(Run);
+ fTokenID:=tkInteger;
+ while FOrigin[Run]in ['0'..'9', 'A'..'F', 'a'..'f']do Inc(Run);
+end;
+
+procedure TmwPasLex.LFProc;
+begin
+ Case fComment of
+ csBor: fTokenID:=tkCRLFCo;
+ csAnsi: fTokenID:=tkCRLFCo;
+ else fTokenID:=tkCRLF;
+ end;
+ Inc(Run);
+ Inc(fLineNumber);
+ fLinePos:=Run;
+end;
+
+procedure TmwPasLex.LowerProc;
+begin
+ case FOrigin[Run+1]of
+ '=':
+ begin
+ Inc(Run, 2);
+ fTokenID:=tkLowerEqual;
+ end;
+ '>':
+ begin
+ Inc(Run, 2);
+ fTokenID:=tkNotEqual;
+ end
+ else
+ begin
+ Inc(Run);
+ fTokenID:=tkLower;
+ end;
+ end;
+end;
+
+procedure TmwPasLex.MinusProc;
+begin
+ Inc(Run);
+ fTokenID:=tkMinus;
+end;
+
+procedure TmwPasLex.NullProc;
+begin
+ fTokenID:=tkNull;
+end;
+
+procedure TmwPasLex.NumberProc;
+begin
+ Inc(Run);
+ fTokenID:=tkNumber;
+ while FOrigin[Run]in ['0'..'9', '.', 'e', 'E']do
+ begin
+ case FOrigin[Run]of
+ '.':
+ if FOrigin[Run+1]='.' then Break else fTokenID:=tkFloat
+ end;
+ Inc(Run);
+ end;
+end;
+
+procedure TmwPasLex.PlusProc;
+begin
+ Inc(Run);
+ fTokenID:=tkPlus;
+end;
+
+procedure TmwPasLex.PointerSymbolProc;
+begin
+ Inc(Run);
+ fTokenID:=tkPointerSymbol;
+end;
+
+procedure TmwPasLex.PointProc;
+begin
+ case FOrigin[Run+1]of
+ '.':
+ begin
+ Inc(Run, 2);
+ fTokenID:=tkDotDot;
+ end;
+ ')':
+ begin
+ Inc(Run, 2);
+ fTokenID:=tkSquareClose;
+ Dec(FSquareCount);
+ end;
+ else
+ begin
+ Inc(Run);
+ fTokenID:=tkPoint;
+ end;
+ end;
+end;
+
+procedure TmwPasLex.RoundCloseProc;
+begin
+ Inc(Run);
+ fTokenID:=tkRoundClose;
+ Dec(FRoundCount);
+end;
+
+procedure TmwPasLex.AnsiProc;
+begin
+ fTokenID:=tkAnsiComment;
+ case FOrigin[Run]of
+ #0:
+ begin
+ NullProc;
+ Exit;
+ end;
+
+ #10:
+ begin
+ LFProc;
+ Exit;
+ end;
+
+ #13:
+ begin
+ CRProc;
+ Exit;
+ end;
+ end;
+
+ while fOrigin[Run]<>#0 do
+ case fOrigin[Run]of
+ '*':
+ if fOrigin[Run+1]=')' then
+ begin
+ fComment:=csNo;
+ Inc(Run, 2);
+ Break;
+ end else Inc(Run);
+ #10: Break;
+
+ #13: Break;
+ else Inc(Run);
+ end;
+end;
+
+procedure TmwPasLex.RoundOpenProc;
+begin
+ Inc(Run);
+ case fOrigin[Run]of
+ '*':
+ begin
+ fTokenID:=tkAnsiComment;
+ if FOrigin[Run+1]='$' then fTokenID:=tkCompDirect else fComment:=csAnsi;
+ Inc(Run);
+ while fOrigin[Run]<>#0 do
+ case fOrigin[Run]of
+ '*':
+ if fOrigin[Run+1]=')' then
+ begin
+ fComment:=csNo;
+ Inc(Run, 2);
+ Break;
+ end else Inc(Run);
+ #10: Break;
+ #13: Break;
+ else Inc(Run);
+ end;
+ end;
+ '.':
+ begin
+ Inc(Run);
+ fTokenID:=tkSquareOpen;
+ Inc(FSquareCount);
+ end;
+ else
+ begin
+ FTokenID:=tkRoundOpen;
+ Inc(FRoundCount);
+ end;
+ end;
+end;
+
+procedure TmwPasLex.SemiColonProc;
+begin
+ Inc(Run);
+ fTokenID:=tkSemiColon;
+end;
+
+procedure TmwPasLex.SlashProc;
+begin
+ case FOrigin[Run+1]of
+ '/':
+ begin
+ Inc(Run, 2);
+ fTokenID:=tkSlashesComment;
+ while FOrigin[Run]<>#0 do
+ begin
+ case FOrigin[Run]of
+ #10, #13: Break;
+ end;
+ Inc(Run);
+ end;
+ end;
+ else
+ begin
+ Inc(Run);
+ fTokenID:=tkSlash;
+ end;
+ end;
+end;
+
+procedure TmwPasLex.SpaceProc;
+begin
+ Inc(Run);
+ fTokenID:=tkSpace;
+ while FOrigin[Run]in [#1..#9, #11, #12, #14..#32]do Inc(Run);
+end;
+
+procedure TmwPasLex.SquareCloseProc;
+begin
+ Inc(Run);
+ fTokenID:=tkSquareClose;
+ Dec(FSquareCount);
+end;
+
+procedure TmwPasLex.SquareOpenProc;
+begin
+ Inc(Run);
+ fTokenID:=tkSquareOpen;
+ Inc(FSquareCount);
+end;
+
+procedure TmwPasLex.StarProc;
+begin
+ Inc(Run);
+ fTokenID:=tkStar;
+end;
+
+procedure TmwPasLex.StringProc;
+begin
+ fTokenID:=tkString;
+ if(FOrigin[Run+1]=#39)and(FOrigin[Run+2]=#39)then Inc(Run, 2);
+ repeat
+ case FOrigin[Run]of
+ #0, #10, #13: Break;
+ end;
+ Inc(Run);
+ until FOrigin[Run]=#39;
+ if FOrigin[Run]<>#0 then Inc(Run);
+end;
+
+procedure TmwPasLex.SymbolProc;
+begin
+ Inc(Run);
+ fTokenID:=tkSymbol;
+end;
+
+procedure TmwPasLex.UnknownProc;
+begin
+ Inc(Run);
+ fTokenID:=tkUnknown;
+end;
+
+procedure TmwPasLex.Next;
+begin
+ Case fTokenID of
+ tkIdentifier:
+ begin
+ fLastIdentPos:=fTokenPos;
+ fLastNoSpace:=fTokenID;
+ fLastNoSpacePos:=fTokenPos;
+ end;
+ tkSpace: ;
+ else
+ begin
+ fLastNoSpace:=fTokenID;
+ fLastNoSpacePos:=fTokenPos;
+ end;
+ end;
+ fTokenPos:=Run;
+ Case fComment of
+ csNo: fProcTable[fOrigin[Run]];
+ else
+ Case fComment of
+ csBor: BorProc;
+ csAnsi: AnsiProc;
+ end;
+ end;
+end;
+
+function TmwPasLex.GetToken: string;
+var
+ Len: Longint;
+begin
+ Result := '';
+ Len:=Run-fTokenPos;
+ SetString(Result, (FOrigin+fTokenPos), Len);
+end;
+
+procedure TmwPasLex.NextID(ID: TTokenKind);
+begin
+ repeat
+ Case fTokenID of
+ tkNull: Break;
+ else Next;
+ end;
+ until fTokenID=ID;
+end;
+
+procedure TmwPasLex.NextNoJunk;
+begin
+ repeat
+ Next;
+ until not(fTokenID in [tkSlashesComment, tkAnsiComment, tkBorComment, tkCRLF, tkCRLFCo, tkSpace]);
+end;
+
+procedure TmwPasLex.NextClass;
+begin
+ if fTokenID<>tkNull then next;
+ repeat
+ Case fTokenID of
+ tkNull: Break;
+ else Next;
+ end;
+ until(fTokenID=tkClass)and(IsClass);
+end;
+
+initialization
+ MakeIdentTable;
+
+end.
+
+
+
+
+
+
diff --git a/branches/script-component/Units/PascalScript/PascalScript.inc b/branches/script-component/Units/PascalScript/PascalScript.inc
new file mode 100644
index 0000000..7f684a7
--- /dev/null
+++ b/branches/script-component/Units/PascalScript/PascalScript.inc
@@ -0,0 +1,66 @@
+{----------------------------------------------------------------------------}
+{ RemObjects Pascal Script }
+{ }
+{ compiler: Delphi 2 and up, Kylix 3 and up }
+{ platform: Win32, Linux }
+{ }
+{ (c)opyright RemObjects Software. all rights reserved. }
+{ }
+{----------------------------------------------------------------------------}
+
+
+{$INCLUDE eDefines.inc}
+
+{$IFDEF FPC}{$MODE DELPHI}{$H+}{$ENDIF}
+
+{$IFDEF VER125}{C4}{$B-}{$X+}{$T-}{$H+}{$ENDIF}
+{$IFDEF VER110}{C3}{$B-}{$X+}{$T-}{$H+}{$ENDIF}
+{$IFDEF VER93}{C1}{$B-}{$X+}{$T-}{$H+}{$ENDIF}
+
+{$IFDEF DELPHI4UP}
+ {$DEFINE PS_HAVEVARIANT}
+ {$DEFINE PS_DYNARRAY}
+{$ENDIF}
+
+{$IFNDEF FPC}
+ {$B-}{$X+}{$T-}{$H+}
+{$ELSE}
+ {$R-}{$Q-}
+{$ENDIF}
+
+{$IFNDEF FPC}
+{$IFNDEF DELPHI4UP}
+{$IFNDEF LINUX}
+ {$DEFINE PS_NOINT64}
+{$ENDIF}
+{$ENDIF}
+
+{$IFDEF DELPHI2}
+ {$DEFINE PS_NOINT64}
+ {$DEFINE PS_NOWIDESTRING}
+ {$B-}{$X+}{$T-}{$H+}
+{$ENDIF}
+
+{$IFDEF LINUX}{KYLIX}{$DEFINE CLX}{$DEFINE DELPHI3UP}{$DEFINE DELPHI6UP}{$ENDIF}
+{$ENDIF}
+{$R-}{$Q-}
+
+
+{
+Defines:
+ PS_NOSMARTLIST - Don't use the smart list option
+ PS_NOIDISPATCH
+ PS_NOWIDESTRING
+ PS_NOINT64
+ PS_DELPHIDIV
+}
+
+{$UNDEF DEBUG}
+
+{$IFDEF CLX}
+{$DEFINE PS_NOIDISPATCH} // not implemented
+{$ENDIF}
+
+{$IFDEF FPC}
+ {$I PascalScriptFPC.inc}
+{$ENDIF}
diff --git a/branches/script-component/Units/PascalScript/PascalScriptFPC.inc b/branches/script-component/Units/PascalScript/PascalScriptFPC.inc
new file mode 100644
index 0000000..f73780a
--- /dev/null
+++ b/branches/script-component/Units/PascalScript/PascalScriptFPC.inc
@@ -0,0 +1,18 @@
+
+ {$DEFINE PS_HAVEVARIANT}
+ {$DEFINE PS_DYNARRAY}
+ {$DEFINE PS_NOIDISPATCH}
+ {.$if (fpc_version=2) and (fpc_release>=3) and (fpc_patch>=1)}
+ {$if (fpc_version=2) and ((fpc_release=2) and (fpc_patch>=4)) or (fpc_release>2)}
+ {$UNDEF FPC_OLD_FIX}
+ {$DEFINE PS_STACKALIGN}
+ {$UNDEF PS_FPCSTRINGWORKAROUND}
+ {$DEFINE PS_RESBEFOREPARAMETERS}
+ {$DEFINE x64_string_result_as_varparameter}
+ {FreePascal 2.3.1 and above has much Delphi compatibility bugs fixed}
+ {$else}
+ {$DEFINE FPC_OLD_FIX}
+ {$DEFINE PS_FPCSTRINGWORKAROUND}
+ {$ifend}
+ {$DEFINE DELPHI3UP}
+ {$DEFINE DELPHI6UP}
diff --git a/branches/script-component/Units/PascalScript/PascalScript_Core_Ext_Reg.pas b/branches/script-component/Units/PascalScript/PascalScript_Core_Ext_Reg.pas
new file mode 100644
index 0000000..baedd90
--- /dev/null
+++ b/branches/script-component/Units/PascalScript/PascalScript_Core_Ext_Reg.pas
@@ -0,0 +1,30 @@
+unit PascalScript_Core_Ext_Reg;
+
+{----------------------------------------------------------------------------}
+{ RemObjects Pascal Script }
+{ }
+{ compiler: Delphi 2 and up, Kylix 3 and up }
+{ platform: Win32, Linux }
+{ }
+{ (c)opyright RemObjects Software. all rights reserved. }
+{ }
+{----------------------------------------------------------------------------}
+
+{$I PascalScript.inc}
+
+interface
+
+procedure Register;
+
+implementation
+
+uses
+ Classes,
+ uPSComponentExt;
+
+procedure Register;
+begin
+ RegisterComponents('RemObjects Pascal Script',[TPSScriptExtension]);
+end;
+
+end.
diff --git a/branches/script-component/Units/PascalScript/PascalScript_Core_Reg.pas b/branches/script-component/Units/PascalScript/PascalScript_Core_Reg.pas
new file mode 100644
index 0000000..b21d770
--- /dev/null
+++ b/branches/script-component/Units/PascalScript/PascalScript_Core_Reg.pas
@@ -0,0 +1,65 @@
+unit PascalScript_Core_Reg;
+
+{----------------------------------------------------------------------------
+/ RemObjects Pascal Script
+/
+/ compiler: Delphi 2 and up, Kylix 3 and up
+/ platform: Win32, Linux
+/
+/ (c)opyright RemObjects Software. all rights reserved.
+/
+----------------------------------------------------------------------------}
+
+{$I PascalScript.inc}
+
+interface
+
+{$IFNDEF FPC}
+{$R PascalScript_Core_Glyphs.res}
+{$ENDIF}
+
+procedure Register;
+
+implementation
+
+uses
+ Classes,
+ {$IFDEF FPC}
+ LResources,
+ {$ENDIF}
+ uPSComponent,
+ uPSDebugger,
+ uPSComponent_Default,
+ {$IFNDEF FPC}
+ uPSComponent_COM,
+ {$ENDIF}
+ uPSComponent_DB,
+ uPSComponent_Forms,
+ uPSComponent_Controls,
+ uPSComponent_StdCtrls;
+
+procedure Register;
+begin
+ RegisterComponents('Pascal Script', [TPSScript,
+ TPSScriptDebugger,
+ TPSDllPlugin,
+ TPSImport_Classes,
+ TPSImport_DateUtils,
+ {$IFNDEF FPC}
+ TPSImport_ComObj,
+ {$ENDIF}
+ TPSImport_DB,
+ TPSImport_Forms,
+ TPSImport_Controls,
+ TPSImport_StdCtrls,
+ TPSCustumPlugin]);
+end;
+
+
+{$IFDEF FPC}
+ initialization;
+ {$i pascalscript.lrs}
+{$ENDIF}
+
+
+end.
diff --git a/branches/script-component/Units/PascalScript/PascalScript_Core_Reg_noDB.pas b/branches/script-component/Units/PascalScript/PascalScript_Core_Reg_noDB.pas
new file mode 100644
index 0000000..277952f
--- /dev/null
+++ b/branches/script-component/Units/PascalScript/PascalScript_Core_Reg_noDB.pas
@@ -0,0 +1,48 @@
+unit PascalScript_Core_Reg_noDB;
+
+{----------------------------------------------------------------------------}
+{ RemObjects Pascal Script
+{
+{ compiler: Delphi 2 and up, Kylix 3 and up
+{ platform: Win32, Linux
+{
+{ (c)opyright RemObjects Software. all rights reserved.
+{
+{----------------------------------------------------------------------------}
+
+{$I PascalScript.inc}
+
+interface
+
+{$R PascalScript_Core_Glyphs.res}
+
+procedure Register;
+
+implementation
+
+uses
+ Classes,
+ uPSComponent,
+ uPSComponentExt,
+ uPSDebugger,
+ uPSComponent_Default,
+ uPSComponent_COM,
+ uPSComponent_Forms,
+ uPSComponent_Controls,
+ uPSComponent_StdCtrls;
+
+procedure Register;
+begin
+ RegisterComponents('Pascal Script', [TPSScript,
+ TPSScriptDebugger,
+ TPSDllPlugin,
+ TPSImport_Classes,
+ TPSImport_DateUtils,
+ TPSImport_ComObj,
+ TPSImport_Forms,
+ TPSImport_Controls,
+ TPSImport_StdCtrls,
+ TPSScriptExtension]);
+end;
+
+end.
diff --git a/branches/script-component/Units/PascalScript/PascalScript_RO_Reg.pas b/branches/script-component/Units/PascalScript/PascalScript_RO_Reg.pas
new file mode 100644
index 0000000..6f6301f
--- /dev/null
+++ b/branches/script-component/Units/PascalScript/PascalScript_RO_Reg.pas
@@ -0,0 +1,34 @@
+unit PascalScript_RO_Reg;
+
+{----------------------------------------------------------------------------}
+{ RemObjects Pascal Script
+{
+{ compiler: Delphi 2 and up, Kylix 3 and up
+{ platform: Win32, Linux
+{
+{ (c)opyright RemObjects Software. all rights reserved.
+{
+{ Using this code requires a valid license of Pascal Script
+{ which can be obtained at http://www.remobjects.com.
+{----------------------------------------------------------------------------}
+
+{$I PascalScript.inc}
+
+interface
+
+{$R PascalScript_RO_Glyphs.res}
+
+procedure Register;
+
+implementation
+
+uses
+ Classes,
+ uROPSServerLink;
+
+procedure Register;
+begin
+ RegisterComponents('Pascal Script', [TPSRemObjectsSdkPlugin]);
+end;
+
+end.
diff --git a/branches/script-component/Units/PascalScript/arm.inc b/branches/script-component/Units/PascalScript/arm.inc
new file mode 100644
index 0000000..0639845
--- /dev/null
+++ b/branches/script-component/Units/PascalScript/arm.inc
@@ -0,0 +1,312 @@
+{ implementation of the arm procedure call standard for function calls in pascal script
+ Copyright (c) 2008 by Henry Vermaak (henry.vermaak@gmail.com)
+
+ todo: add eabi (define FPC_ABI_EABI) and wince support
+
+ notes:
+
+ most arm cpus don't allow unaligned access. by default (?) the linux kernel
+ is set up to try and correct unaligned access, which can lead to strange behaviour.
+ to turn this off, try (as root):
+
+ echo 4 > /proc/cpu/alignment
+
+ if you have an alignment problem, you will now get a crash with a backtrace like this:
+ (make sure you compile with -O- -gl)
+
+ An unhandled exception occurred at $0006C014 :
+ EBusError : Bus error or misaligned data access
+ $0006C014 PROCESSREPEAT, line 9670 of upscompiler.pas
+ $00068AAC TPSPASCALCOMPILER__PROCESSSUB, line 10459 of upscompiler.pas
+ $0007D0B4 TPSPASCALCOMPILER__COMPILE, line 11704 of upscompiler.pas
+
+ you can fix this by using the "unaligned" keyword around the pointer operation.
+ search for occurances of "unaligned" to see how this is done,
+ (use $ifdef FPC_REQUIRES_PROPER_ALIGNMENT).
+
+ for more information, visit:
+
+ http://www.aleph1.co.uk/oldsite/armlinux/book/afaq.html
+}
+
+const
+ rtINT = 0;
+ rtINT64 = 1;
+ rtFLOAT = 2;
+
+type
+ Trint = array[1..4] of dword;
+ Trfloat = array[1..4] of double;
+
+{$goto on}
+{ define labels }
+label
+ stack_loop,
+ load_regs,
+ asmcall_end,
+ int_result,
+ int64_result,
+ float_result;
+
+{ call a function from a pointer }
+{ resulttype: 0 = int, 1 = int64, 2 = float }
+function armasmcall(rint: Trint; rfloat: Trfloat; proc, stack: pointer; stacksize, resulttype: integer): pointer; assembler; nostackframe;
+asm
+ mov r12, r13
+ stmfd r13!, {r4, r5, r6, r7, r8, r9, r10, r11, r12, r14, r15}
+ sub r11, r12, #4
+ mov r4, #80 (* space for preserved registers and parameters *)
+ ldr r5, [r11, #4] (* stacksize we need for subroutine *)
+ add r4, r4, r5
+ sub r13, r13, r4 (* create stack space *)
+
+ (* store parameters on stack *)
+ str r0, [r11, #-44] (* rint *)
+ str r1, [r11, #-48] (* rfloat *)
+ str r2, [r11, #-52] (* proc *)
+ str r3, [r11, #-56] (* stack *)
+ ldr r0, [r11, #4]
+ str r0, [r11, #-60] (* stacksize *)
+ ldr r0, [r11, #8]
+ str r0, [r11, #-64] (* resulttype *)
+
+ (* store params for sub-routine that don't fit into r0-r3 at start of stack *)
+ ldr r0, [r11, #-60] (* stacksize *)
+ cmp r0, #0
+ beq load_regs (* skip if no stack *)
+ mov r1, r13 (* this points to the bottom now *)
+ ldr r2, [r11, #-56] (* stack pointer *)
+stack_loop:
+ ldmia r2!, {r4} (* get stack + update pos *)
+ stmia r1!, {r4} (* store stack + update pos *)
+ subs r0, r0, #4
+ bne stack_loop
+
+load_regs:
+ (* load general regs *)
+ ldr r4, [r11, #-44] (* rint *)
+ ldr r0, [r4]
+ ldr r1, [r4, #4]
+ ldr r2, [r4, #8]
+ ldr r3, [r4, #12]
+
+{$ifdef FPUFPA}
+ (* load float regs *)
+ ldr r4, [r11, #-48] (* rfloat *)
+ ldfd f0, [r4]
+ ldfd f1, [r4, #8]
+ ldfd f2, [r4, #16]
+ ldfd f3, [r4, #24]
+{$endif}
+
+ (* branch to the proc pointer *)
+ ldr r4, [r11, #-52]
+ mov r14, r15
+ mov r15, r4
+(* blx r4 *)
+
+ ldr r4, [r11, #-64] (* get resulttype *)
+ cmp r4, #1
+ blt int_result
+ beq int64_result
+ bgt float_result
+
+int_result:
+ str r0, [r11, #-72]
+ b asmcall_end
+
+int64_result:
+ str r0, [r11, #-72]
+ str r1, [r11, #-68]
+ b asmcall_end
+
+float_result:
+{$ifdef FPUFPA}
+ stfd f0, [r11, #-72]
+{$else}
+ b int64_result
+{$endif}
+ b asmcall_end
+
+asmcall_end:
+ sub r0, r11, #72 (* return pointer to result on stack *)
+
+ ldmea r11,{r4,r5,r6,r7,r8,r9,r10,r11,r13,r15}
+end;
+
+function TPSExec.InnerfuseCall(_Self, Address: Pointer; CallingConv: TPSCallingConvention; Params: TPSList; res: PPSVariantIFC): Boolean;
+var
+ rint: Trint; { registers r0 to r3 }
+ rfloat: Trfloat; { registers f0 to f3 }
+ st: packed array of byte; { stack }
+ i, j, rindex, findex, stindex: integer;
+ fvar: PPSVariantIFC;
+ IsConstructor: Boolean;
+
+ { add a dword to stack }
+ procedure addstackdword(value: dword);
+ begin
+ setlength(st, stindex+4);
+ pdword(@st[stindex])^ := value;
+ inc(stindex, 4);
+ end;
+
+ { add a float to stack }
+ procedure addstackfloat(value: pointer; size: integer);
+ begin
+ setlength(st, stindex + (size * 4));
+ if size = 1
+ then psingle(@st[stindex])^ := single(value^)
+ else pdouble(@st[stindex])^ := double(value^);
+ inc(stindex, size*4);
+ end;
+
+ { add to the general registers or overflow to stack }
+ procedure addgen(value: dword);
+ begin
+ if rindex <= 4
+ then begin
+ rint[rindex] := value;
+ inc(rindex);
+ end
+ else begin
+ addstackdword(value);
+ end;
+ end;
+ { add to the float registers or overflow to stack }
+ { size = 1 for single, 2 for double }
+ procedure addfloat(value: pointer; size: integer);
+ begin
+ if findex <= 4
+ then begin
+ if size = 1
+ then rfloat[findex] := single(value^)
+ else rfloat[findex] := double(value^);
+ inc(findex);
+ end
+ else begin
+ addstackfloat(value, size);
+ end;
+ end;
+
+begin
+ if (Integer(CallingConv) and 64) <> 0 then begin
+ IsConstructor := true;
+ CAllingConv := TPSCallingConvention(Integer(CallingConv) and not 64);
+ end else IsConstructor := false;
+
+ rindex := 1;
+ findex := 1;
+ stindex := 0;
+ setlength(st, stindex);
+ Result := False;
+
+ { the pointer of the result needs to be passed first in the case of some result types }
+ if assigned(res)
+ then begin
+ case res.atype.basetype of
+ btStaticArray, btRecord: addgen(dword(res.dta));
+ end;
+ end;
+
+ { process all parameters }
+ for i := 0 to Params.Count-1 do begin
+ if Params[i] = nil
+ then Exit;
+ fvar := Params[i];
+
+ { cook dynamic arrays - fpc stores size-1 at @array-4 }
+ if (fvar.aType.BaseType = btArray)
+ then dec(pdword(pointer(fvar.dta^)-4)^);
+
+ if fvar.varparam
+ then begin { var param }
+ case fvar.aType.BaseType of
+ { add var params here }
+ btArray, btVariant, btSet, btStaticArray, btRecord, btInterface, btClass, {$IFNDEF PS_NOWIDESTRING} btUnicodeString, btWideString, btWideChar, {$ENDIF}
+ btU8, btS8, btU16, btS16, btU32, btS32, btSingle, btDouble, btExtended, btString, btPChar, btChar, btCurrency
+ {$IFNDEF PS_NOINT64}, bts64{$ENDIF}: addgen(dword(fvar.dta));
+ else begin
+ writeln(stderr, 'Parameter type not recognised!');
+ Exit;
+ end;
+ end; { case }
+ end else begin { not a var param }
+ case fvar.aType.BaseType of
+// btArray, btVariant, btSet, btStaticArray, btRecord, btInterface, btClass, {$IFNDEF PS_NOWIDESTRING} btWideString, btWideChar, {$ENDIF}
+// btU8, btS8, btU16, btS16, btU32, btS32, btSingle, btDouble, btExtended, btString, btPChar, btChar, btCurrency
+// {$IFNDEF PS_NOINT64}, bts64{$ENDIF}: writeln('normal param');
+
+ { add normal params here }
+ btString: addgen(dword(pstring(fvar.dta)^));
+ btU8, btS8: addgen(dword(pbyte(fvar.dta)^));
+ btU16, BtS16: addgen(dword(pword(fvar.dta)^));
+ btU32, btS32: addgen(dword(pdword(fvar.dta)^));
+ btSingle: {$ifdef FPUFPA}
+ addfloat(fvar.dta, 1);
+ {$else}
+ addgen(dword(psingle(fvar.dta)^));
+ {$endif}
+ btDouble{, btExtended}: {$ifdef FPUFPA}
+ addfloat(fvar.dta, 2);
+ {$else}
+ begin
+ addgen(lo(qword(pdouble(fvar.dta)^)));
+ addgen(hi(qword(pdouble(fvar.dta)^)));
+ end;
+ {$endif}
+ btPChar: addgen(dword(ppchar(fvar.dta)^));
+ btChar: addgen(dword(pchar(fvar.dta)^));
+ {$IFNDEF PS_NOINT64}bts64:{$ENDIF} begin
+ addgen(dword(pint64(fvar.dta)^ and $ffffffff));
+ addgen(dword(pint64(fvar.dta)^ shr 32));
+ end;
+ btStaticArray: addgen(dword(fvar.dta));
+ btRecord: for j := 0 to (fvar.atype.realsize div 4)-1 do
+ addgen(pdword(fvar.dta + j*4)^);
+ btArray: addstackdword(dword(fvar.dta^)); { this is a bit weird }
+
+{ btVariant, btSet, btInterface, btClass }
+
+ else begin
+ writeln(stderr, 'Parameter type not implemented!');
+ Exit;
+ end;
+ end; { case }
+ end; { else }
+ end; { for }
+
+ if not assigned(res)
+ then begin
+ armasmcall(rint, rfloat, address, st, stindex, rtINT); { ignore return }
+ end
+ else begin
+ case res.atype.basetype of
+ { add result types here }
+ btString: pstring(res.dta)^ := pstring(armasmcall(rint, rfloat, address, st, stindex, rtINT))^;
+ btU8, btS8: pbyte(res.dta)^ := byte(pdword(armasmcall(rint, rfloat, address, st, stindex, rtINT))^);
+ btU16, btS16: pword(res.dta)^ := word(pdword(armasmcall(rint, rfloat, address, st, stindex, rtINT))^);
+ btU32, btS32: pdword(res.dta)^ := pdword(armasmcall(rint, rfloat, address, st, stindex, rtINT))^;
+ btSingle: psingle(res.dta)^ := pdouble(armasmcall(rint, rfloat, address, st, stindex, rtFLOAT))^;
+ btDouble{, btExtended}: pdouble(res.dta)^ := pdouble(armasmcall(rint, rfloat, address, st, stindex, rtFLOAT))^;
+ btPChar: ppchar(res.dta)^ := pchar(pdword(armasmcall(rint, rfloat, address, st, stindex, rtINT))^);
+ btChar: pchar(res.dta)^ := char(pdword(armasmcall(rint, rfloat, address, st, stindex, rtINT))^);
+ btStaticArray, btRecord: armasmcall(rint, rfloat, address, st, stindex, rtINT);
+ btArray: res.dta := armasmcall(rint, rfloat, address, st, stindex, rtINT);
+
+ else begin
+ writeln(stderr, 'Result type not implemented!');
+ exit;
+ end; { else }
+ end; { case }
+ end;
+
+ { cook dynamic arrays - fpc stores size-1 at @array-4 }
+ for i := 0 to Params.Count-1 do begin
+ fvar := Params[i];
+ if (fvar.aType.BaseType = btArray)
+ then inc(pdword(pointer(fvar.dta^)-4)^);
+ end;
+
+ Result := True;
+end;
diff --git a/branches/script-component/Units/PascalScript/eDefines.inc b/branches/script-component/Units/PascalScript/eDefines.inc
new file mode 100644
index 0000000..2f2e25f
--- /dev/null
+++ b/branches/script-component/Units/PascalScript/eDefines.inc
@@ -0,0 +1,493 @@
+{----------------------------------------------------------------------------}
+{file: eDefines.inc }
+{type: Delphi include file }
+{ }
+{compiler: Borland Pascal 7, }
+{ Delphi 1-7, 2005-2007 for Win32 }
+{ Kylix 1-3, }
+{ C++Builder 1-6, 2006-2007 }
+{ Free Pascal Compiler 2.x }
+{ }
+{platforms: DOS, DPMI, Win16, Win32, Win64, Linux, Mac OS X }
+{ }
+{author: mh@elitedev.com }
+{ }
+{contents: Defines that can be flexibily used to determine the exact }
+{ compiler version used. }
+{ }
+{(c)opyright elitedevelopments software. all rights reserved. }
+{ http://www.elitedev.com }
+{ }
+{ Third Party component developers are encouraged to use the set of defines }
+{ established in this file, rather then their own system, for checking their }
+{ component libraries agains different versions of Delphi and C++Builder. }
+{ }
+{ This file may be distributed freely with both free and commercial source }
+{ libraries, but you are asked to please leave this comment in place, and }
+{ to return any improvements you make to this file to the maintainer that }
+{ is noted above. }
+{----------------------------------------------------------------------------}
+
+{----------------------------------------------------------------------------}
+{ Compiler and OS version defines: }
+{ }
+{ exact compiler versions: }
+{ }
+{ BP7 Borland Pascal 7.0 }
+{ DELPHI1 Delphi 1.0 (any Delphi) }
+{ DELPHI2 Delphi 2.0 }
+{ DELPHI3 Delphi 3.0 }
+{ DELPHI4 Delphi 4.0 }
+{ DELPHI5 Delphi 5.0 }
+{ DELPHI6 Delphi 6.0 }
+{ DELPHI7 Delphi 7.0 }
+{ DELPHI9 Delphi 2005 }
+{ DELPHI2005 Delphi 2005 }
+{ DELPHI2006 Delphi 2006 }
+{ DELPHI2007 Delphi 2007 }
+{ KYLIX1 Kylix 1.0 }
+{ KYLIX2 Kylix 2.0 }
+{ KYLIX3 Kylix 3.0 }
+{ CBUILDER1 C++Builder 1.0 }
+{ CBUILDER3 C++Builder 3.0 }
+{ CBUILDER4 C++Builder 4.0 }
+{ CBUILDER5 C++Builder 5.0 }
+{ }
+{ }
+{ minimum compiler versions: }
+{ }
+{ DELPHI1UP Delphi 1.0 and above (any Delphi) }
+{ DELPHI2UP Delphi 2.0 and above }
+{ DELPHI3UP Delphi 3.0 and above }
+{ DELPHI4UP Delphi 4.0 and above }
+{ DELPHI5UP Delphi 5.0 and above }
+{ DELPHI6UP Delphi 6.0 and above }
+{ DELPHI7UP Delphi 7.0 and above }
+{ DELPHI9UP Delphi 9.0 (2005) and above }
+{ DELPHI10UP Delphi 10.0 (2006) and above }
+{ DELPHI11UP Delphi 11.0 (2007) and above }
+{ DELPHI2005UP Delphi 2005 and above }
+{ DELPHI2006UP Delphi 2006 and above }
+{ DELPHI2007UP Delphi 2007 and above }
+{ KYLIX1UP Kylix 1.0 and above (any Kylix) }
+{ KYLIX2UP Kylix 2.0 and above (any Kylix) }
+{ KYLIX3UP Kylix 3.0 and above (any Kylix) }
+{ CBUILDER1UP C++Builder 1.0 and above or Delphi 2 and above }
+{ CBUILDER3UP C++Builder 3.0 and above or Delphi 3.0 and above }
+{ CBUILDER4UP C++Builder 4.0 and above or Delphi 4.0 and above }
+{ CBUILDER5UP C++Builder 5.0 and above or Delphi 5.0 and above }
+{ CBUILDER6UP C++Builder 5.0 and above or Delphi 5.0 and above }
+{ }
+{ }
+{ compiler types: }
+{ }
+{ BP Borland Pascal (not Delphi or C++Builder) }
+{ DELPHI any Delphi version (but not C++Builder or Kylix) }
+{ KYLIX any Kylix version (not Delphi or C++Builder for Windows) }
+{ CBUILDER any C++Builder for Windows (Pascal) }
+{ }
+{ }
+{ target platforms compiler types: }
+{ }
+{ DELPHI_16BIT 16bit Delphi (but not C++Builder!) }
+{ DELPHI_32BIT 32bit Delphi (but not C++Builder) }
+{ KYLIX_32BIT 32bit Kylix (but not C++Builder) }
+{ CBUILDER_32BIT 32bit C++Builer's Pascal (but not Delphi) }
+{ }
+{ }
+{ target cpu types }
+{ }
+{ CPU16 16bit Delphi or Borland Pascal }
+{ CPU32 32bit Delphi or Free Pascal }
+{ CPU64 64bit Free Pascal }
+{ }
+{ target platforms }
+{ }
+{ DOS any DOS (plain and DPMI) }
+{ REALMODE 16bit realmode DOS }
+{ PROTECTEDMODE 16bit DPMI DOS }
+{ }
+{ MSWINDOWS any Windows platform }
+{ WIN16 16bit Windows }
+{ WIN32 32bit Windows }
+{ WIN64 64bit Windows }
+{ DOTNET .NET }
+{ }
+{ LINUX any Linux platform }
+{ LINUX32 32bit Linux }
+{ LINUX64 64bit Linux }
+{ }
+{ DARWIN Any Mac OS X }
+{ DARWIN32 32bit Mac OS X }
+{ DARWIN64 64bit Mac OS X }
+{----------------------------------------------------------------------------}
+
+{ defines for Borland Pascal 7.0 }
+{$IFDEF VER70}
+ {$DEFINE BP}
+ {$DEFINE BP7}
+ {$DEFINE 16BIT}
+ {$DEFINE CPU16}
+
+ { defines for BP7 DOS real mode }
+ {$IFDEF MSDOS}
+ {$DEFINE DOS}
+ {$DEFINE REALMODE}
+ {$ENDIF}
+
+ { defines for BP7 DOS protected mode }
+ {$IFDEF DPMI}
+ {$DEFINE DOS}
+ {$DEFINE PROTECTEDMODE}
+ {$ENDIF}
+
+ { defines for BP7 Windows }
+ {$IFDEF WINDOWS}
+ {$DEFINE MSWINDOWS}
+ {$DEFINE WIN16}
+ {$ENDIF}
+{$ENDIF}
+
+{ defines for Delphi 1.0 thru 7.0 }
+{$IFDEF MSWINDOWS}
+
+ { defines for Delphi 1.0 }
+ {$IFDEF VER80}
+ {$DEFINE DELPHI}
+ {$DEFINE DELPHI1}
+ {$DEFINE DELPHI1UP}
+ {$DEFINE DELPHI_16BIT}
+ {$DEFINE WIN16}
+ {$DEFINE 16BIT}
+ {$DEFINE CPU16}
+ {$ENDIF}
+
+ { defines for Delphi 2.0 }
+ {$IFDEF VER90}
+ {$DEFINE DELPHI}
+ {$DEFINE DELPHI2}
+ {$DEFINE DELPHI1UP}
+ {$DEFINE DELPHI2UP}
+ {$ENDIF}
+
+ { defines for C++Builder 1.0 }
+ {$IFDEF VER93}
+ {$DEFINE DELPHI1UP}
+ {$DEFINE DELPHI2UP}
+ {$DEFINE CBUILDER}
+ {$DEFINE CBUILDER1}
+ {$DEFINE CBUILDER1UP}
+ {$ENDIF}
+
+ { defines for Delphi 3.0 }
+ {$IFDEF VER100}
+ {$DEFINE DELPHI}
+ {$DEFINE DELPHI3}
+ {$DEFINE DELPHI1UP}
+ {$DEFINE DELPHI2UP}
+ {$DEFINE DELPHI3UP}
+ {$ENDIF}
+
+ { defines for C++Builder 3.0 }
+ {$IFDEF VER110}
+ {$DEFINE DELPHI1UP}
+ {$DEFINE DELPHI2UP}
+ {$DEFINE DELPHI3UP}
+ {$DEFINE CBUILDER}
+ {$DEFINE CBUILDER3}
+ {$DEFINE CBUILDER1UP}
+ {$DEFINE CBUILDER3UP}
+ {$ENDIF}
+
+ { defines for Delphi 4.0 }
+ {$IFDEF VER120}
+ {$DEFINE DELPHI}
+ {$DEFINE DELPHI4}
+ {$DEFINE DELPHI1UP}
+ {$DEFINE DELPHI2UP}
+ {$DEFINE DELPHI3UP}
+ {$DEFINE DELPHI4UP}
+ {$ENDIF}
+
+ { defines for C++Builder 4.0 }
+ {$IFDEF VER125}
+ {$DEFINE DELPHI1UP}
+ {$DEFINE DELPHI2UP}
+ {$DEFINE DELPHI3UP}
+ {$DEFINE DELPHI4UP}
+ {$DEFINE CBUILDER}
+ {$DEFINE CBUILDER4}
+ {$DEFINE CBUILDER1UP}
+ {$DEFINE CBUILDER3UP}
+ {$DEFINE CBUILDER4UP}
+ {$ENDIF}
+ { defines for Delphi 5.0 }
+ {$IFDEF VER130}
+ {$DEFINE DELPHI}
+ {$DEFINE DELPHI5}
+ {$DEFINE DELPHI1UP}
+ {$DEFINE DELPHI2UP}
+ {$DEFINE DELPHI3UP}
+ {$DEFINE DELPHI4UP}
+ {$DEFINE DELPHI5UP}
+ {$ENDIF}
+
+ { defines for C++Builder 5.0 }
+ {$IFDEF VER135}
+ {$DEFINE DELPHI1UP}
+ {$DEFINE DELPHI2UP}
+ {$DEFINE DELPHI3UP}
+ {$DEFINE DELPHI4UP}
+ {$DEFINE DELPHI5UP}
+ {$DEFINE CBUILDER}
+ {$DEFINE CBUILDER5}
+ {$DEFINE CBUILDER1UP}
+ {$DEFINE CBUILDER3UP}
+ {$DEFINE CBUILDER4UP}
+ {$DEFINE CBUILDER5UP}
+ {$ENDIF}
+
+ { defines for Delphi 6.0 }
+ {$IFDEF VER140}
+ {$DEFINE VER140UP}
+ {$DEFINE DELPHI}
+ {$DEFINE DELPHI6}
+ {$DEFINE DELPHI1UP}
+ {$DEFINE DELPHI2UP}
+ {$DEFINE DELPHI3UP}
+ {$DEFINE DELPHI4UP}
+ {$DEFINE DELPHI5UP}
+ {$DEFINE DELPHI6UP}
+ {$ENDIF}
+
+ { defines for Delphi 7.0 }
+ {$IFDEF VER150}
+ {$DEFINE VER140UP}
+ {$DEFINE DELPHI}
+ {$DEFINE DELPHI7}
+ {$DEFINE DELPHI1UP}
+ {$DEFINE DELPHI2UP}
+ {$DEFINE DELPHI3UP}
+ {$DEFINE DELPHI4UP}
+ {$DEFINE DELPHI5UP}
+ {$DEFINE DELPHI6UP}
+ {$DEFINE DELPHI7UP}
+ {$ENDIF}
+
+ { defines for Delphi 2005 }
+ {$IFDEF VER170}
+ {$DEFINE VER140UP}
+ {$DEFINE DELPHI}
+ {$DEFINE DELPHI9}
+ {$DEFINE DELPHI2005}
+ {$DEFINE DELPHI1UP}
+ {$DEFINE DELPHI2UP}
+ {$DEFINE DELPHI3UP}
+ {$DEFINE DELPHI4UP}
+ {$DEFINE DELPHI5UP}
+ {$DEFINE DELPHI6UP}
+ {$DEFINE DELPHI7UP}
+ {$DEFINE DELPHI9UP}
+ {$DEFINE DELPHI2005UP}
+ {$DEFINE BDS}
+ {$DEFINE BDS3}
+ {$DEFINE BDS3UP}
+ {$ENDIF}
+
+ { defines for Delphi 2006 }
+ {$IFDEF VER180}
+ {$DEFINE VER140UP}
+ {$DEFINE DELPHI}
+ {$DEFINE DELPHI10}
+ {$DEFINE DELPHI10A}
+ {$DEFINE DELPHI2006}
+ {$DEFINE DELPHI1UP}
+ {$DEFINE DELPHI2UP}
+ {$DEFINE DELPHI3UP}
+ {$DEFINE DELPHI4UP}
+ {$DEFINE DELPHI5UP}
+ {$DEFINE DELPHI6UP}
+ {$DEFINE DELPHI7UP}
+ {$DEFINE DELPHI9UP}
+ {$DEFINE DELPHI10UP}
+ {$DEFINE DELPHI2005UP}
+ {$DEFINE DELPHI2006UP}
+ {$DEFINE BDS}
+ {$DEFINE BDS4}
+ {$DEFINE BDS3UP}
+ {$DEFINE BDS4UP}
+ {$ENDIF}
+
+ { defines for Delphi 2007 }
+ {$IFDEF VER185}
+ {$UNDEF DELPHI10A} // declared in VER180
+ {$UNDEF DELPHI2006} // declared in VER180
+ {$UNDEF BDS4} // declared in VER180
+
+ {$DEFINE DELPHI10B}
+ {$DEFINE DELPHI10BUP}
+ {$DEFINE DELPHI11}
+ {$DEFINE DELPHI11UP}
+ {$DEFINE DELPHI2007}
+ {$DEFINE DELPHI2007UP}
+ {$DEFINE BDS5}
+ {$DEFINE BDS5UP}
+ {$ENDIF}
+
+ { defines for Delphi 2009 }
+ {$IFDEF VER200}
+ {$DEFINE VER140UP}
+ {$DEFINE DELPHI}
+
+ {$DEFINE DELPHI12}
+ {$DEFINE DELPHI1UP}
+ {$DEFINE DELPHI2UP}
+ {$DEFINE DELPHI3UP}
+ {$DEFINE DELPHI4UP}
+ {$DEFINE DELPHI5UP}
+ {$DEFINE DELPHI6UP}
+ {$DEFINE DELPHI7UP}
+ {$DEFINE DELPHI9UP}
+ {$DEFINE DELPHI10UP}
+ {$DEFINE DELPHI11UP}
+ {$DEFINE DELPHI12UP}
+
+ {$DEFINE DELPHI2009}
+ {$DEFINE DELPHI2005UP}
+ {$DEFINE DELPHI2006UP}
+ {$DEFINE DELPHI2007UP}
+ {$DEFINE DELPHI2009UP}
+
+ {$DEFINE BDS}
+ {$DEFINE BDS6}
+ {$DEFINE BDS3UP}
+ {$DEFINE BDS4UP}
+ {$DEFINE BDS5UP}
+ {$DEFINE BDS6UP}
+ {$ENDIF}
+
+ { defines for Delphi 2010 }
+ {$IFDEF VER210}
+ {$DEFINE VER140UP}
+ {$DEFINE DELPHI}
+
+ {$DEFINE DELPHI14}
+ {$DEFINE DELPHI1UP}
+ {$DEFINE DELPHI2UP}
+ {$DEFINE DELPHI3UP}
+ {$DEFINE DELPHI4UP}
+ {$DEFINE DELPHI5UP}
+ {$DEFINE DELPHI6UP}
+ {$DEFINE DELPHI7UP}
+ {$DEFINE DELPHI9UP}
+ {$DEFINE DELPHI10UP}
+ {$DEFINE DELPHI11UP}
+ {$DEFINE DELPHI12UP}
+ {$DEFINE DELPHI14UP}
+
+ {$DEFINE DELPHI2010}
+ {$DEFINE DELPHI2005UP}
+ {$DEFINE DELPHI2006UP}
+ {$DEFINE DELPHI2007UP}
+ {$DEFINE DELPHI2009UP}
+ {$DEFINE DELPHI2010UP}
+
+ {$DEFINE BDS}
+ {$DEFINE BDS7}
+ {$DEFINE BDS3UP}
+ {$DEFINE BDS4UP}
+ {$DEFINE BDS5UP}
+ {$DEFINE BDS6UP}
+ {$DEFINE BDS7UP}
+ {$ENDIF}
+
+
+ {$IFDEF WIN32}
+ {$DEFINE MSWINDOWS} //not automatically defined for Delphi 2 thru 5
+ {$DEFINE 32BIT}
+ {$DEFINE CPU32}
+ {$ENDIF}
+
+{$ENDIF MSWINDOWS}
+
+{ defines for "Delphi for .NET" }
+{$IFDEF CLR}
+ {$DEFINE DOTNET}
+{$ENDIF}
+
+{$IFDEF DELPHI}
+ {$IFDEF DELPHI2UP}
+ {$DEFINE DELPHI_32BIT}
+ {$ENDIF}
+{$ENDIF}
+
+{$IFDEF CBUILDER}
+ {$DEFINE CBUILDER_32BIT}
+{$ENDIF}
+
+{$IFNDEF FPC}
+
+ { Kylix 1.0 thru 3.0 }
+ {$IFDEF LINUX}
+
+ {$DEFINE VER140UP}
+
+ { Any Kylix }
+ {$DEFINE 32BIT}
+ {$DEFINE LINUX32}
+ {$DEFINE KYLIX_32BIT}
+ {$DEFINE KYLIX}
+ {$DEFINE KYLIX1UP}
+
+ {$IFDEF CONDITIONALEXPRESSIONS}
+ {$IF Declared(CompilerVersion)}
+
+ { Kylix 2.0 }
+ {$IF Declared(RTLVersion) and (RTLVersion = 14.1)}
+ {$DEFINE KYLIX2}
+ {$DEFINE KYLIX1UP}
+ {$DEFINE KYLIX2UP}
+ {$IFEND}
+
+ { Kylix 3.0 - Delphi portion }
+ {$IF Declared(RTLVersion) and (RTLVersion = 14.5)}
+ {$DEFINE KYLIX3}
+ {$DEFINE KYLIX1UP}
+ {$DEFINE KYLIX2UP}
+ {$DEFINE KYLIX3UP}
+ {$IFEND}
+
+ { Kylix 1.0 }
+ {$ELSE}
+ {$DEFINE KYLIX1}
+ {$IFEND}
+ {$ENDIF CONDITIONALEXPRESSIONS}
+
+ {$ENDIF LINUX}
+{$ENDIF}
+
+{ CPU }
+
+{$IFDEF FPC}
+ {$IFDEF MSWINDOWS}
+ {$IFDEF CPU64}
+ {$DEFINE WIN64}
+ {$ENDIF}
+ {$ENDIF}
+ {$IFDEF LINUX}
+ {$IFDEF CPU32}
+ {$DEFINE LINUX32}
+ {$ENDIF}
+ {$IFDEF CPU64}
+ {$DEFINE LINUX64}
+ {$ENDIF}
+ {$ENDIF}
+ {$IFDEF DARWIN}
+ {$IFDEF CPU32}
+ {$DEFINE DARWIN32}
+ {$ENDIF}
+ {$IFDEF CPU64}
+ {$DEFINE DARWIN64}
+ {$ENDIF}
+ {$ENDIF}
+{$ENDIF}
\ No newline at end of file
diff --git a/branches/script-component/Units/PascalScript/pascalscript.pas b/branches/script-component/Units/PascalScript/pascalscript.pas
new file mode 100644
index 0000000..0531780
--- /dev/null
+++ b/branches/script-component/Units/PascalScript/pascalscript.pas
@@ -0,0 +1,29 @@
+{ This file was automatically created by Lazarus. Do not edit!
+This source is only used to compile and install the package.
+ }
+
+unit PascalScript;
+
+interface
+
+uses
+ uPSRuntime, PascalScript_Core_Reg, uPSC_buttons, uPSC_classes, uPSC_controls,
+ uPSC_dateutils, uPSC_DB, uPSC_dll, uPSC_extctrls, uPSC_forms,
+ uPSC_graphics, uPSC_menus, uPSC_std, uPSC_stdctrls, uPSCompiler,
+ uPSComponent, uPSComponent_Controls, uPSComponent_DB, uPSComponent_Default,
+ uPSComponent_Forms, uPSComponent_StdCtrls, uPSComponentExt, uPSDebugger,
+ uPSDisassembly, uPSPreProcessor, uPSR_buttons, uPSR_classes, uPSR_controls,
+ uPSR_dateutils, uPSR_DB, uPSR_dll, uPSR_extctrls, uPSR_forms,
+ uPSR_graphics, uPSR_menus, uPSR_std, uPSR_stdctrls, uPSUtils,
+ LazarusPackageIntf;
+
+implementation
+
+procedure Register;
+begin
+ RegisterUnit('PascalScript_Core_Reg', @PascalScript_Core_Reg.Register);
+end;
+
+initialization
+ RegisterPackage('PascalScript', @Register);
+end.
diff --git a/branches/script-component/Units/PascalScript/powerpc.inc b/branches/script-component/Units/PascalScript/powerpc.inc
new file mode 100644
index 0000000..d40c4d5
--- /dev/null
+++ b/branches/script-component/Units/PascalScript/powerpc.inc
@@ -0,0 +1,343 @@
+{ implementation of the powerpc osx abi for function calls in pascal script
+ Copyright (c) 2007 by Henry Vermaak (henry.vermaak@gmail.com) }
+
+{$ifndef darwin}
+ {$fatal This code is Darwin specific at the moment!}
+{$endif}
+
+{$ifndef cpu32}
+ {$fatal This code is 32bit specific at the moment!}
+{$endif}
+
+const
+ rtINT = 0;
+ rtINT64 = 1;
+ rtFLOAT = 2;
+
+type
+ Trint = array[1..8] of dword;
+ Trfloat = array[1..13] of double;
+
+{$goto on}
+{ define labels }
+label
+ rfloat_loop,
+ stack_loop,
+ load_regs,
+ int_result,
+ int64_result,
+ float_result,
+ asmcall_end;
+
+{ call a function from a pointer }
+{ resulttype: 0 = int, 1 = int64, 2 = float }
+function ppcasmcall(rint: Trint; rfloat: Trfloat; proc, stack: pointer; stacksize, resulttype: integer): pointer; assembler; nostackframe;
+asm
+ mflr r0
+ stw r0, 8(r1)
+
+ { save non-volatile register/s - make sure the stack size is sufficient! }
+ stw r31, -4(r1) { stacksize }
+
+ stwu r1, -240(r1) { create stack }
+
+ { get all the params into the stack }
+ stw r3, 48(r1) { rint }
+ stw r4, 52(r1) { rfloat }
+ stw r5, 56(r1) { proc }
+ stw r6, 60(r1) { stack }
+ stw r7, 64(r1) { stacksize }
+ stw r8, 68(r1) { resulttype }
+ { result is stored in 72(r1) and 76(r1) (if returning int64) }
+
+ { write rint array into stack }
+ lwz r2, 48(r1) { rint }
+ lfd f0, 0(r2)
+ stfd f0, 80(r1) { rint[1], rint[2] }
+ lfd f0, 8(r2)
+ stfd f0, 88(r1) { rint[3], rint[4] }
+ lfd f0, 16(r2)
+ stfd f0, 96(r1) { rint[5], rint[6] }
+ lfd f0, 24(r2)
+ stfd f0, 104(r1) { rint[7], rint[8] }
+
+ { write rfloat array into stack }
+ lwz r2, 52(r1) { rfloat }
+ addi r4, r1, 112 { rfloat[1] from here upwards (8 bytes apart) }
+ subi r2, r2, 8 { src }
+ subi r4, r4, 8 { dest }
+ li r3, 13 { counter }
+
+rfloat_loop:
+ subic. r3, r3, 1 { dec counter }
+ lfdu f0, 8(r2) { load rfloat[x] + update }
+ stfdu f0, 8(r4) { store rfloat[x] + update }
+ bne cr0, rfloat_loop
+
+ { create new stack }
+ mflr r0
+ stw r0, 8(r1)
+ mr r12, r1 { remember previous stack to fill in regs later }
+
+ lwz r31, 64(r12) { load stacksize into r31 }
+ neg r3, r31 { negate }
+ stwux r1, r1, r3 { create new stack }
+
+ { build up the stack here }
+ mr r3, r31 { counter }
+ subic. r3, r3, 24 { don't write first 24 }
+ blt cr0, load_regs { don't fill in stack if there is none }
+
+ lwz r2, 60(r12) { pointer to stack }
+ addi r2, r2, 24 { start of params }
+ subi r2, r2, 1 { src }
+
+ addi r4, r1, 24 { start of params }
+ subi r4, r4, 1 { dest }
+
+stack_loop:
+ subic. r3, r3, 1 { dec counter }
+ lbzu r5, 1(r2) { load stack + update }
+ stbu r5, 1(r4) { store stack + update }
+ bne cr0, stack_loop
+
+load_regs: { now load the registers from the previous stack in r12 }
+ lwz r3, 80(r12)
+ lwz r4, 84(r12)
+ lwz r5, 88(r12)
+ lwz r6, 92(r12)
+ lwz r7, 96(r12)
+ lwz r8, 100(r12)
+ lwz r9, 104(r12)
+ lwz r10, 108(r12)
+
+ lfd f1, 112(r12)
+ lfd f2, 120(r12)
+ lfd f3, 128(r12)
+ lfd f4, 136(r12)
+ lfd f5, 144(r12)
+ lfd f6, 152(r12)
+ lfd f7, 160(r12)
+ lfd f8, 168(r12)
+ lfd f9, 176(r12)
+ lfd f10, 184(r12)
+ lfd f11, 192(r12)
+ lfd f12, 200(r12)
+ lfd f13, 208(r12)
+
+ { now call this function }
+ lwz r2, 56(r12) { proc }
+ mtctr r2 { move to ctr }
+ bctrl { branch and link to ctr }
+
+ { restore stack - use stacksize in r31 }
+ add r1, r1, r31
+ lwz r0, 8(r1)
+ mtlr r0
+
+ { check resulttype and put appropriate pointer into r3 }
+ lwz r2, 68(r1) { resulttype }
+ cmpwi cr0, r2, 0 { int result? }
+ beq cr0, int_result { branch if equal }
+
+ cmpwi cr0, r2, 1 { single result? }
+ beq cr0, int64_result { branch if equal }
+
+
+float_result: { the result is a double}
+ stfd f1, 72(r1) { write f1 to result on stack }
+ b asmcall_end
+
+
+int64_result: { the result is a single }
+ stw r3, 72(r1) { write high dword to result on stack }
+ stw r4, 76(r1) { write low dword to result on stack }
+ b asmcall_end
+
+
+int_result: { the result is dword }
+ stw r3, 72(r1) { write r3 to result on stack }
+
+
+asmcall_end: { epilogue }
+ addi r3, r1, 72 { pointer to result on the stack }
+ addi r1, r1, 240 { restore stack }
+
+ { restore non-volatile register/s }
+ lwz r31, -4(r1)
+
+ lwz r0, 8(r1)
+ mtlr r0
+ blr
+end;
+
+function TPSExec.InnerfuseCall(_Self, Address: Pointer; CallingConv: TPSCallingConvention; Params: TPSList; res: PPSVariantIFC): Boolean;
+var
+ rint: Trint; { registers r3 to r10 }
+ rfloat: Trfloat; { registers f1 to f13 }
+ st: packed array of byte; { stack }
+ i, j, rindex, findex, stindex: integer;
+ fvar: PPSVariantIFC;
+ IsConstructor: Boolean;
+ { add a dword to stack }
+ procedure addstackdword(value: dword);
+ begin
+ setlength(st, stindex+4);
+ pdword(@st[stindex])^ := value;
+ inc(stindex, 4);
+ end;
+
+ { add a float to stack }
+ procedure addstackfloat(value: pointer; size: integer);
+ begin
+ setlength(st, stindex + (size * 4));
+ if size = 1
+ then psingle(@st[stindex])^ := single(value^)
+ else pdouble(@st[stindex])^ := double(value^);
+ inc(stindex, size*4);
+ end;
+
+ { add to the general registers or overflow to stack }
+ procedure addgen(value: dword);
+ begin
+ if rindex <= 8
+ then begin
+ rint[rindex] := value;
+ inc(rindex);
+ addstackdword(value);
+ end
+ else begin
+ addstackdword(value);
+ end;
+ end;
+ { add to the float registers or overflow to stack }
+ { size = 1 for single, 2 for double }
+ procedure addfloat(value: pointer; size: integer);
+ begin
+ if findex <= 13
+ then begin
+ if size = 1
+ then rfloat[findex] := single(value^)
+ else rfloat[findex] := double(value^);
+ inc(findex);
+ inc(rindex, size);
+ addstackfloat(value, size);
+ end
+ else begin
+ addstackfloat(value, size);
+ end;
+ end;
+
+begin
+ if (Integer(CallingConv) and 64) <> 0 then begin
+ IsConstructor := true;
+ CAllingConv := TPSCallingConvention(Integer(CallingConv) and not 64);
+ end else IsConstructor := false;
+
+ rindex := 1;
+ findex := 1;
+ stindex := 24;
+ setlength(st, stindex);
+ Result := False;
+
+ { the pointer of the result needs to be passed first in the case of some result types }
+ if assigned(res)
+ then begin
+ case res.atype.basetype of
+ btStaticArray, btRecord: addgen(dword(res.dta));
+ end;
+ end;
+
+ { process all parameters }
+ for i := 0 to Params.Count-1 do begin
+ if Params[i] = nil
+ then Exit;
+ fvar := Params[i];
+
+ { cook dynamic arrays - fpc stores size-1 at @array-4 }
+ if (fvar.aType.BaseType = btArray)
+ then dec(pdword(pointer(fvar.dta^)-4)^);
+
+ if fvar.varparam
+ then begin { var param }
+ case fvar.aType.BaseType of
+ { add var params here }
+ btArray, btVariant, btSet, btStaticArray, btRecord, btInterface, btClass, {$IFNDEF PS_NOWIDESTRING} btWideString, btWideChar, {$ENDIF}
+ btU8, btS8, btU16, btS16, btU32, btS32, btSingle, btDouble, btExtended, btString, btPChar, btChar, btCurrency
+ {$IFNDEF PS_NOINT64}, bts64{$ENDIF}: addgen(dword(fvar.dta)); { TODO: test all }
+ else begin
+ writeln(stderr, 'Parameter type not recognised!');
+ Exit;
+ end;
+ end; { case }
+ end else begin { not a var param }
+ case fvar.aType.BaseType of
+// btArray, btVariant, btSet, btStaticArray, btRecord, btInterface, btClass, {$IFNDEF PS_NOWIDESTRING} btWideString, btWideChar, {$ENDIF}
+// btU8, btS8, btU16, btS16, btU32, btS32, btSingle, btDouble, btExtended, btString, btPChar, btChar, btCurrency
+// {$IFNDEF PS_NOINT64}, bts64{$ENDIF}: writeln('normal param');
+
+ { add normal params here }
+ btString: addgen(dword(pstring(fvar.dta)^));
+ btU8, btS8: addgen(dword(pbyte(fvar.dta)^));
+ btU16, BtS16: addgen(dword(pword(fvar.dta)^));
+ btU32, btS32: addgen(dword(pdword(fvar.dta)^));
+ btSingle: addfloat(fvar.dta, 1);
+ btDouble, btExtended: addfloat(fvar.dta, 2);
+ btPChar: addgen(dword(ppchar(fvar.dta)^));
+ btChar: addgen(dword(pchar(fvar.dta)^));
+ {$IFNDEF PS_NOINT64}bts64:{$ENDIF} begin
+ addgen(dword(pint64(fvar.dta)^ shr 32));
+ addgen(dword(pint64(fvar.dta)^ and $ffffffff));
+ end;
+ btStaticArray: addgen(dword(fvar.dta));
+ btRecord: for j := 0 to (fvar.atype.realsize div 4)-1 do
+ addgen(pdword(fvar.dta + j*4)^);
+ btArray: addgen(dword(fvar.dta^));
+
+ { TODO add and test }
+{ btVariant, btSet, btInterface, btClass }
+
+ else begin
+ writeln(stderr, 'Parameter type not implemented!');
+ Exit;
+ end;
+ end; { case }
+ end; { else }
+ end; { for }
+
+ if not assigned(res)
+ then begin
+ ppcasmcall(rint, rfloat, address, st, stindex, rtINT); { ignore return }
+ end
+ else begin
+ case res.atype.basetype of
+ { add result types here }
+ btString: pstring(res.dta)^ := pstring(ppcasmcall(rint, rfloat, address, st, stindex, rtINT))^;
+ btU8, btS8: pbyte(res.dta)^ := byte(pdword(ppcasmcall(rint, rfloat, address, st, stindex, rtINT))^);
+ btU16, btS16: pword(res.dta)^ := word(pdword(ppcasmcall(rint, rfloat, address, st, stindex, rtINT))^);
+ btU32, btS32: pdword(res.dta)^ := pdword(ppcasmcall(rint, rfloat, address, st, stindex, rtINT))^;
+ btSingle: psingle(res.dta)^ := pdouble(ppcasmcall(rint, rfloat, address, st, stindex, rtFLOAT))^;
+ btDouble, btExtended: pdouble(res.dta)^ := pdouble(ppcasmcall(rint, rfloat, address, st, stindex, rtFLOAT))^;
+ btPChar: ppchar(res.dta)^ := pchar(pdword(ppcasmcall(rint, rfloat, address, st, stindex, rtINT))^);
+ btChar: pchar(res.dta)^ := char(pdword(ppcasmcall(rint, rfloat, address, st, stindex, rtINT))^);
+ btStaticArray, btRecord: ppcasmcall(rint, rfloat, address, st, stindex, rtINT);
+ btArray: res.dta := ppcasmcall(rint, rfloat, address, st, stindex, rtINT);
+
+ { TODO add and test }
+
+ else begin
+ writeln(stderr, 'Result type not implemented!');
+ exit;
+ end; { else }
+ end; { case }
+ end;
+
+ { cook dynamic arrays - fpc stores size-1 at @array-4 }
+ for i := 0 to Params.Count-1 do begin
+ fvar := Params[i];
+ if (fvar.aType.BaseType = btArray)
+ then inc(pdword(pointer(fvar.dta^)-4)^);
+ end;
+
+ Result := True;
+end;
diff --git a/branches/script-component/Units/PascalScript/uPSC_DB.pas b/branches/script-component/Units/PascalScript/uPSC_DB.pas
new file mode 100644
index 0000000..890bb8e
--- /dev/null
+++ b/branches/script-component/Units/PascalScript/uPSC_DB.pas
@@ -0,0 +1,892 @@
+{ Compiletime DB support }
+Unit uPSC_DB;
+{
+This file has been generated by UnitParser v0.4, written by M. Knight.
+Source Code from Carlo Kok has been used to implement various sections of
+UnitParser. Components of ifps3 are used in the construction of UnitParser,
+code implementing the class wrapper is taken from Carlo Kok''s conv unility
+
+Licence :
+This software is provided 'as-is', without any expressed or implied
+warranty. In no event will the author be held liable for any damages
+arising from the use of this software.
+Permission is granted to anyone to use this software for any kind of
+application, and to alter it and redistribute it freely, subject to
+the following restrictions:
+1. The origin of this software must not be misrepresented, you must
+ not claim that you wrote the original software.
+2. Altered source versions must be plainly marked as such, and must
+ not be misrepresented as being the original software.
+3. You may not create a library that uses this library as a main part
+ of the program and sell that library.
+4. You must have a visible line in your programs aboutbox or
+ documentation that it is made using Innerfuse Script and where
+ Innerfuse Pascal Script can be found.
+5. This notice may not be removed or altered from any source
+ distribution.
+
+If you have any questions concerning this license write to Carlo Kok:
+ ck@carlo-kok.com or try the newsserver:
+ news://news.carlo-kok.com/
+}
+{$I PascalScript.inc}
+Interface
+uses
+ uPSCompiler;
+
+procedure SIRegisterTDATASET(CL: TPSPascalCompiler);
+procedure SIRegisterTPARAMS(CL: TPSPascalCompiler);
+procedure SIRegisterTPARAM(CL: TPSPascalCompiler);
+procedure SIRegisterTGUIDFIELD(CL: TPSPascalCompiler);
+procedure SIRegisterTVARIANTFIELD(CL: TPSPascalCompiler);
+procedure SIRegisterTREFERENCEFIELD(CL: TPSPascalCompiler);
+procedure SIRegisterTDATASETFIELD(CL: TPSPascalCompiler);
+procedure SIRegisterTARRAYFIELD(CL: TPSPascalCompiler);
+procedure SIRegisterTADTFIELD(CL: TPSPascalCompiler);
+procedure SIRegisterTOBJECTFIELD(CL: TPSPascalCompiler);
+procedure SIRegisterTGRAPHICFIELD(CL: TPSPascalCompiler);
+procedure SIRegisterTMEMOFIELD(CL: TPSPascalCompiler);
+procedure SIRegisterTBLOBFIELD(CL: TPSPascalCompiler);
+{$IFDEF DELPHI6UP}
+procedure SIRegisterTFMTBCDFIELD(CL: TPSPascalCompiler);
+{$ENDIF}
+procedure SIRegisterTBCDFIELD(CL: TPSPascalCompiler);
+procedure SIRegisterTVARBYTESFIELD(CL: TPSPascalCompiler);
+procedure SIRegisterTBYTESFIELD(CL: TPSPascalCompiler);
+procedure SIRegisterTBINARYFIELD(CL: TPSPascalCompiler);
+procedure SIRegisterTTIMEFIELD(CL: TPSPascalCompiler);
+procedure SIRegisterTDATEFIELD(CL: TPSPascalCompiler);
+procedure SIRegisterTDATETIMEFIELD(CL: TPSPascalCompiler);
+procedure SIRegisterTBOOLEANFIELD(CL: TPSPascalCompiler);
+procedure SIRegisterTCURRENCYFIELD(CL: TPSPascalCompiler);
+procedure SIRegisterTFLOATFIELD(CL: TPSPascalCompiler);
+procedure SIRegisterTAUTOINCFIELD(CL: TPSPascalCompiler);
+procedure SIRegisterTWORDFIELD(CL: TPSPascalCompiler);
+procedure SIRegisterTLARGEINTFIELD(CL: TPSPascalCompiler);
+procedure SIRegisterTSMALLINTFIELD(CL: TPSPascalCompiler);
+procedure SIRegisterTINTEGERFIELD(CL: TPSPascalCompiler);
+procedure SIRegisterTNUMERICFIELD(CL: TPSPascalCompiler);
+procedure SIRegisterTWIDESTRINGFIELD(CL: TPSPascalCompiler);
+procedure SIRegisterTSTRINGFIELD(CL: TPSPascalCompiler);
+procedure SIRegisterTFIELD(CL: TPSPascalCompiler);
+procedure SIRegisterTLOOKUPLIST(CL: TPSPascalCompiler);
+procedure SIRegisterTFIELDS(CL: TPSPascalCompiler);
+procedure SIRegisterTFIELDLIST(CL: TPSPascalCompiler);
+procedure SIRegisterTFIELDDEFLIST(CL: TPSPascalCompiler);
+procedure SIRegisterTFLATLIST(CL: TPSPascalCompiler);
+procedure SIRegisterTINDEXDEFS(CL: TPSPascalCompiler);
+procedure SIRegisterTINDEXDEF(CL: TPSPascalCompiler);
+procedure SIRegisterTFIELDDEFS(CL: TPSPascalCompiler);
+procedure SIRegisterTFIELDDEF(CL: TPSPascalCompiler);
+procedure SIRegisterTDEFCOLLECTION(CL: TPSPascalCompiler);
+procedure SIRegisterTNAMEDITEM(CL: TPSPascalCompiler);
+procedure SIRegister_DB(Cl: TPSPascalCompiler);
+
+implementation
+Uses Sysutils;
+
+Function RegClassS(cl : TPSPascalCompiler;Const InheritsFrom,Classname : String) : TPSCompileTimeClass;
+begin
+Result := cl.FindClass(Classname);
+if Result = nil then
+ Result := cl.AddClassN(cl.FindClass(InheritsFrom),Classname)
+else
+ Result.ClassInheritsFrom := cl.FindClass(InheritsFrom);
+end;
+
+procedure SIRegisterTDATASET(CL: TPSPascalCompiler);
+Begin
+With RegClassS(cl,'TCOMPONENT','TDATASET') do
+ begin
+ RegisterMethod('Function ACTIVEBUFFER : PCHAR');
+ RegisterMethod('Procedure APPEND');
+ RegisterMethod('Procedure APPENDRECORD( const VALUES : array of const)');
+// RegisterMethod('Function BOOKMARKVALID( BOOKMARK : TBOOKMARK) : BOOLEAN');
+ RegisterMethod('Procedure CANCEL');
+ RegisterMethod('Procedure CHECKBROWSEMODE');
+ RegisterMethod('Procedure CLEARFIELDS');
+ RegisterMethod('Procedure CLOSE');
+ RegisterMethod('Function CONTROLSDISABLED : BOOLEAN');
+// RegisterMethod('Function COMPAREBOOKMARKS( BOOKMARK1, BOOKMARK2 : TBOOKMARK) : INTEGER');
+ RegisterMethod('Function CREATEBLOBSTREAM( FIELD : TFIELD; MODE : TBLOBSTREAMMODE) : TSTREAM');
+ RegisterMethod('Procedure CURSORPOSCHANGED');
+ RegisterMethod('Procedure DELETE');
+ RegisterMethod('Procedure DISABLECONTROLS');
+ RegisterMethod('Procedure EDIT');
+ RegisterMethod('Procedure ENABLECONTROLS');
+{$IFDEF DELPHI2006UP}
+ RegisterMethod('Function FIELDBYNAME( const FIELDNAME : WIDESTRING) : TFIELD');
+ RegisterMethod('Function FINDFIELD( const FIELDNAME : WideString) : TFIELD');
+{$ELSE}
+ RegisterMethod('Function FIELDBYNAME( const FIELDNAME : STRING) : TFIELD');
+ RegisterMethod('Function FINDFIELD( const FIELDNAME : STRING) : TFIELD');
+{$ENDIF}
+ RegisterMethod('Function FINDFIRST : BOOLEAN');
+ RegisterMethod('Function FINDLAST : BOOLEAN');
+ RegisterMethod('Function FINDNEXT : BOOLEAN');
+ RegisterMethod('Function FINDPRIOR : BOOLEAN');
+ RegisterMethod('Procedure FIRST');
+// RegisterMethod('Procedure FREEBOOKMARK( BOOKMARK : TBOOKMARK)');
+// RegisterMethod('Function GETBOOKMARK : TBOOKMARK');
+ RegisterMethod('Function GETCURRENTRECORD( BUFFER : PCHAR) : BOOLEAN');
+// RegisterMethod('Procedure GETDETAILDATASETS( LIST : TLIST)');
+// RegisterMethod('Procedure GETFIELDLIST( LIST : TLIST; const FIELDNAMES : STRING)');
+// RegisterMethod('Procedure GETDETAILLINKFIELDS( MASTERFIELDS, DETAILFIELDS : TLIST)');
+// RegisterMethod('Function GETBLOBFIELDDATA( FIELDNO : INTEGER; var BUFFER : TBLOBBYTEDATA) : INTEGER');
+ RegisterMethod('Procedure GETFIELDNAMES( LIST : TSTRINGS)');
+// RegisterMethod('Procedure GOTOBOOKMARK( BOOKMARK : TBOOKMARK)');
+ RegisterMethod('Procedure INSERT');
+ RegisterMethod('Procedure INSERTRECORD( const VALUES : array of const)');
+ RegisterMethod('Function ISEMPTY : BOOLEAN');
+ RegisterMethod('Function ISLINKEDTO( DATASOURCE : TDATASOURCE) : BOOLEAN');
+ RegisterMethod('Function ISSEQUENCED : BOOLEAN');
+ RegisterMethod('Procedure LAST');
+ RegisterMethod('Function LOCATE( const KEYFIELDS : String; const KEYVALUES : VARIANT; OPTIONS : TLOCATEOPTIONS) : BOOLEAN');
+ RegisterMethod('Function LOOKUP( const KEYFIELDS : String; const KEYVALUES : VARIANT; const RESULTFIELDS : String) : VARIANT');
+ RegisterMethod('Function MOVEBY( DISTANCE : INTEGER) : INTEGER');
+ RegisterMethod('Procedure NEXT');
+ RegisterMethod('Procedure OPEN');
+ RegisterMethod('Procedure POST');
+ RegisterMethod('Procedure PRIOR');
+ RegisterMethod('Procedure REFRESH');
+// RegisterMethod('Procedure RESYNC( MODE : TRESYNCMODE)');
+ RegisterMethod('Procedure SETFIELDS( const VALUES : array of const)');
+ RegisterMethod('Function TRANSLATE( SRC, DEST : PCHAR; TOOEM : BOOLEAN) : INTEGER');
+ RegisterMethod('Procedure UPDATECURSORPOS');
+ RegisterMethod('Procedure UPDATERECORD');
+ RegisterMethod('Function UPDATESTATUS : TUPDATESTATUS');
+ RegisterProperty('AGGFIELDS', 'TFIELDS', iptr);
+ RegisterProperty('BOF', 'BOOLEAN', iptr);
+// RegisterProperty('BOOKMARK', 'TBOOKMARKSTR', iptrw);
+ RegisterProperty('CANMODIFY', 'BOOLEAN', iptr);
+ RegisterProperty('DATASETFIELD', 'TDATASETFIELD', iptrw);
+ RegisterProperty('DATASOURCE', 'TDATASOURCE', iptr);
+ RegisterProperty('DEFAULTFIELDS', 'BOOLEAN', iptr);
+ RegisterProperty('DESIGNER', 'TDATASETDESIGNER', iptr);
+ RegisterProperty('EOF', 'BOOLEAN', iptr);
+ RegisterProperty('BLOCKREADSIZE', 'INTEGER', iptrw);
+ RegisterProperty('FIELDCOUNT', 'INTEGER', iptr);
+ RegisterProperty('FIELDDEFS', 'TFIELDDEFS', iptrw);
+ RegisterProperty('FIELDDEFLIST', 'TFIELDDEFLIST', iptr);
+ RegisterProperty('FIELDS', 'TFIELDS', iptr);
+ RegisterProperty('FIELDLIST', 'TFIELDLIST', iptr);
+ RegisterProperty('FIELDVALUES', 'VARIANT String', iptrw);
+ RegisterProperty('FOUND', 'BOOLEAN', iptr);
+{$IFDEF DELPHI6UP}
+ RegisterProperty('ISUNIDIRECTIONAL', 'BOOLEAN', iptr);
+{$ENDIF}
+ RegisterProperty('MODIFIED', 'BOOLEAN', iptr);
+ RegisterProperty('OBJECTVIEW', 'BOOLEAN', iptrw);
+ RegisterProperty('RECORDCOUNT', 'INTEGER', iptr);
+ RegisterProperty('RECNO', 'INTEGER', iptrw);
+ RegisterProperty('RECORDSIZE', 'WORD', iptr);
+ RegisterProperty('SPARSEARRAYS', 'BOOLEAN', iptrw);
+ RegisterProperty('STATE', 'TDATASETSTATE', iptr);
+ RegisterProperty('FILTER', 'String', iptrw);
+ RegisterProperty('FILTERED', 'BOOLEAN', iptrw);
+ RegisterProperty('FILTEROPTIONS', 'TFILTEROPTIONS', iptrw);
+ RegisterProperty('ACTIVE', 'BOOLEAN', iptrw);
+ RegisterProperty('AUTOCALCFIELDS', 'BOOLEAN', iptrw);
+ RegisterProperty('BEFOREOPEN', 'TDATASETNOTIFYEVENT', iptrw);
+ RegisterProperty('AFTEROPEN', 'TDATASETNOTIFYEVENT', iptrw);
+ RegisterProperty('BEFORECLOSE', 'TDATASETNOTIFYEVENT', iptrw);
+ RegisterProperty('AFTERCLOSE', 'TDATASETNOTIFYEVENT', iptrw);
+ RegisterProperty('BEFOREINSERT', 'TDATASETNOTIFYEVENT', iptrw);
+ RegisterProperty('AFTERINSERT', 'TDATASETNOTIFYEVENT', iptrw);
+ RegisterProperty('BEFOREEDIT', 'TDATASETNOTIFYEVENT', iptrw);
+ RegisterProperty('AFTEREDIT', 'TDATASETNOTIFYEVENT', iptrw);
+ RegisterProperty('BEFOREPOST', 'TDATASETNOTIFYEVENT', iptrw);
+ RegisterProperty('AFTERPOST', 'TDATASETNOTIFYEVENT', iptrw);
+ RegisterProperty('BEFORECANCEL', 'TDATASETNOTIFYEVENT', iptrw);
+ RegisterProperty('AFTERCANCEL', 'TDATASETNOTIFYEVENT', iptrw);
+ RegisterProperty('BEFOREDELETE', 'TDATASETNOTIFYEVENT', iptrw);
+ RegisterProperty('AFTERDELETE', 'TDATASETNOTIFYEVENT', iptrw);
+ RegisterProperty('BEFORESCROLL', 'TDATASETNOTIFYEVENT', iptrw);
+ RegisterProperty('AFTERSCROLL', 'TDATASETNOTIFYEVENT', iptrw);
+ RegisterProperty('BEFOREREFRESH', 'TDATASETNOTIFYEVENT', iptrw);
+ RegisterProperty('AFTERREFRESH', 'TDATASETNOTIFYEVENT', iptrw);
+ RegisterProperty('ONCALCFIELDS', 'TDATASETNOTIFYEVENT', iptrw);
+ RegisterProperty('ONDELETEERROR', 'TDATASETERROREVENT', iptrw);
+ RegisterProperty('ONEDITERROR', 'TDATASETERROREVENT', iptrw);
+ RegisterProperty('ONFILTERRECORD', 'TFILTERRECORDEVENT', iptrw);
+ RegisterProperty('ONNEWRECORD', 'TDATASETNOTIFYEVENT', iptrw);
+ RegisterProperty('ONPOSTERROR', 'TDATASETERROREVENT', iptrw);
+ end;
+end;
+
+procedure SIRegisterTPARAMS(CL: TPSPascalCompiler);
+Begin
+With RegClassS(cl,'TCOLLECTION','TPARAMS') do
+ begin
+ RegisterMethod('Procedure ASSIGNVALUES( VALUE : TPARAMS)');
+ RegisterMethod('Procedure ADDPARAM( VALUE : TPARAM)');
+ RegisterMethod('Procedure REMOVEPARAM( VALUE : TPARAM)');
+ RegisterMethod('Function CREATEPARAM( FLDTYPE : TFIELDTYPE; const PARAMNAME : String; PARAMTYPE : TPARAMTYPE) : TPARAM');
+// RegisterMethod('Procedure GETPARAMLIST( LIST : TLIST; const PARAMNAMES : STRING)');
+ RegisterMethod('Function ISEQUAL( VALUE : TPARAMS) : BOOLEAN');
+ RegisterMethod('Function PARSESQL( SQL : String; DOCREATE : BOOLEAN) : String');
+ RegisterMethod('Function PARAMBYNAME( const VALUE : String) : TPARAM');
+ RegisterMethod('Function FINDPARAM( const VALUE : String) : TPARAM');
+ RegisterProperty('ITEMS', 'TPARAM INTEGER', iptrw);
+ RegisterProperty('PARAMVALUES', 'VARIANT String', iptrw);
+ end;
+end;
+
+procedure SIRegisterTPARAM(CL: TPSPascalCompiler);
+Begin
+With RegClassS(cl,'TCOLLECTIONITEM','TPARAM') do
+ begin
+ RegisterMethod('Procedure ASSIGNFIELD( FIELD : TFIELD)');
+ RegisterMethod('Procedure ASSIGNFIELDVALUE( FIELD : TFIELD; const VALUE : VARIANT)');
+ RegisterMethod('Procedure CLEAR');
+// RegisterMethod('Procedure GETDATA( BUFFER : POINTER)');
+ RegisterMethod('Function GETDATASIZE : INTEGER');
+ RegisterMethod('Procedure LOADFROMFILE( const FILENAME : String; BLOBTYPE : TBLOBTYPE)');
+ RegisterMethod('Procedure LOADFROMSTREAM( STREAM : TSTREAM; BLOBTYPE : TBLOBTYPE)');
+// RegisterMethod('Procedure SETBLOBDATA( BUFFER : POINTER; SIZE : INTEGER)');
+// RegisterMethod('Procedure SETDATA( BUFFER : POINTER)');
+{$IFDEF DELPHI6UP}
+ RegisterProperty('ASBCD', 'CURRENCY', iptrw);
+{$ENDIF}
+{$IFDEF DELPHI6UP}
+ RegisterProperty('ASFMTBCD', 'TBCD', iptrw);
+{$ENDIF}
+ RegisterProperty('ASBLOB', 'TBLOBDATA', iptrw);
+ RegisterProperty('ASBOOLEAN', 'BOOLEAN', iptrw);
+ RegisterProperty('ASCURRENCY', 'CURRENCY', iptrw);
+ RegisterProperty('ASDATE', 'TDATETIME', iptrw);
+ RegisterProperty('ASDATETIME', 'TDATETIME', iptrw);
+ RegisterProperty('ASFLOAT', 'DOUBLE', iptrw);
+ RegisterProperty('ASINTEGER', 'LONGINT', iptrw);
+ RegisterProperty('ASSMALLINT', 'LONGINT', iptrw);
+ RegisterProperty('ASMEMO', 'String', iptrw);
+ RegisterProperty('ASSTRING', 'String', iptrw);
+ RegisterProperty('ASTIME', 'TDATETIME', iptrw);
+ RegisterProperty('ASWORD', 'LONGINT', iptrw);
+ RegisterProperty('BOUND', 'BOOLEAN', iptrw);
+ RegisterProperty('ISNULL', 'BOOLEAN', iptr);
+ RegisterProperty('NATIVESTR', 'String', iptrw);
+ RegisterProperty('TEXT', 'String', iptrw);
+ RegisterProperty('DATATYPE', 'TFIELDTYPE', iptrw);
+{$IFDEF DELPHI6UP}
+ RegisterProperty('PRECISION', 'INTEGER', iptrw);
+ RegisterProperty('NUMERICSCALE', 'INTEGER', iptrw);
+ RegisterProperty('SIZE', 'INTEGER', iptrw);
+{$ENDIF}
+ RegisterProperty('NAME', 'String', iptrw);
+ RegisterProperty('PARAMTYPE', 'TPARAMTYPE', iptrw);
+ RegisterProperty('VALUE', 'VARIANT', iptrw);
+ end;
+end;
+
+procedure SIRegisterTGUIDFIELD(CL: TPSPascalCompiler);
+Begin
+With RegClassS(cl,'TFIELD','TGUIDFIELD') do
+ begin
+ end;
+end;
+
+procedure SIRegisterTVARIANTFIELD(CL: TPSPascalCompiler);
+Begin
+With RegClassS(cl,'TFIELD','TVARIANTFIELD') do
+ begin
+ end;
+end;
+
+procedure SIRegisterTREFERENCEFIELD(CL: TPSPascalCompiler);
+Begin
+With RegClassS(cl,'TDATASETFIELD','TREFERENCEFIELD') do
+ begin
+ RegisterProperty('REFERENCETABLENAME', 'String', iptrw);
+ end;
+end;
+
+procedure SIRegisterTDATASETFIELD(CL: TPSPascalCompiler);
+Begin
+With RegClassS(cl,'TOBJECTFIELD','TDATASETFIELD') do
+ begin
+ RegisterProperty('NESTEDDATASET', 'TDATASET', iptr);
+ RegisterProperty('INCLUDEOBJECTFIELD', 'BOOLEAN', iptrw);
+ end;
+end;
+
+procedure SIRegisterTARRAYFIELD(CL: TPSPascalCompiler);
+Begin
+With RegClassS(cl,'TOBJECTFIELD','TARRAYFIELD') do
+ begin
+ end;
+end;
+
+procedure SIRegisterTADTFIELD(CL: TPSPascalCompiler);
+Begin
+With RegClassS(cl,'TOBJECTFIELD','TADTFIELD') do
+ begin
+ end;
+end;
+
+procedure SIRegisterTOBJECTFIELD(CL: TPSPascalCompiler);
+Begin
+With RegClassS(cl,'TFIELD','TOBJECTFIELD') do
+ begin
+ RegisterProperty('FIELDCOUNT', 'INTEGER', iptr);
+ RegisterProperty('FIELDS', 'TFIELDS', iptr);
+ RegisterProperty('FIELDVALUES', 'VARIANT INTEGER', iptrw);
+ RegisterProperty('UNNAMED', 'BOOLEAN', iptr);
+ RegisterProperty('OBJECTTYPE', 'String', iptrw);
+ end;
+end;
+
+procedure SIRegisterTGRAPHICFIELD(CL: TPSPascalCompiler);
+Begin
+With RegClassS(cl,'TBLOBFIELD','TGRAPHICFIELD') do
+ begin
+ end;
+end;
+
+procedure SIRegisterTMEMOFIELD(CL: TPSPascalCompiler);
+Begin
+With RegClassS(cl,'TBLOBFIELD','TMEMOFIELD') do
+ begin
+ end;
+end;
+
+procedure SIRegisterTBLOBFIELD(CL: TPSPascalCompiler);
+Begin
+With RegClassS(cl,'TFIELD','TBLOBFIELD') do
+ begin
+ RegisterMethod('Procedure LOADFROMFILE( const FILENAME : String)');
+ RegisterMethod('Procedure LOADFROMSTREAM( STREAM : TSTREAM)');
+ RegisterMethod('Procedure SAVETOFILE( const FILENAME : String)');
+ RegisterMethod('Procedure SAVETOSTREAM( STREAM : TSTREAM)');
+ RegisterProperty('BLOBSIZE', 'INTEGER', iptr);
+ RegisterProperty('MODIFIED', 'BOOLEAN', iptrw);
+ RegisterProperty('VALUE', 'String', iptrw);
+ RegisterProperty('TRANSLITERATE', 'BOOLEAN', iptrw);
+ RegisterProperty('BLOBTYPE', 'TBLOBTYPE', iptrw);
+{$IFDEF DELPHI6UP}
+ RegisterProperty('GRAPHICHEADER', 'BOOLEAN', iptrw);
+{$ENDIF}
+ end;
+end;
+
+{$IFDEF DELPHI6UP}
+procedure SIRegisterTFMTBCDFIELD(CL: TPSPascalCompiler);
+Begin
+With RegClassS(cl,'TNUMERICFIELD','TFMTBCDFIELD') do
+ begin
+ RegisterProperty('VALUE', 'TBCD', iptrw);
+ RegisterProperty('CURRENCY', 'BOOLEAN', iptrw);
+ RegisterProperty('MAXVALUE', 'String', iptrw);
+ RegisterProperty('MINVALUE', 'String', iptrw);
+ RegisterProperty('PRECISION', 'INTEGER', iptrw);
+ end;
+end;
+{$ENDIF}
+
+procedure SIRegisterTBCDFIELD(CL: TPSPascalCompiler);
+Begin
+With RegClassS(cl,'TNUMERICFIELD','TBCDFIELD') do
+ begin
+ RegisterProperty('VALUE', 'CURRENCY', iptrw);
+ RegisterProperty('CURRENCY', 'BOOLEAN', iptrw);
+ RegisterProperty('MAXVALUE', 'CURRENCY', iptrw);
+ RegisterProperty('MINVALUE', 'CURRENCY', iptrw);
+ RegisterProperty('PRECISION', 'INTEGER', iptrw);
+ end;
+end;
+
+procedure SIRegisterTVARBYTESFIELD(CL: TPSPascalCompiler);
+Begin
+With RegClassS(cl,'TBYTESFIELD','TVARBYTESFIELD') do
+ begin
+ end;
+end;
+
+procedure SIRegisterTBYTESFIELD(CL: TPSPascalCompiler);
+Begin
+With RegClassS(cl,'TBINARYFIELD','TBYTESFIELD') do
+ begin
+ end;
+end;
+
+procedure SIRegisterTBINARYFIELD(CL: TPSPascalCompiler);
+Begin
+With RegClassS(cl,'TFIELD','TBINARYFIELD') do
+ begin
+ end;
+end;
+
+procedure SIRegisterTTIMEFIELD(CL: TPSPascalCompiler);
+Begin
+With RegClassS(cl,'TDATETIMEFIELD','TTIMEFIELD') do
+ begin
+ end;
+end;
+
+procedure SIRegisterTDATEFIELD(CL: TPSPascalCompiler);
+Begin
+With RegClassS(cl,'TDATETIMEFIELD','TDATEFIELD') do
+ begin
+ end;
+end;
+
+procedure SIRegisterTDATETIMEFIELD(CL: TPSPascalCompiler);
+Begin
+With RegClassS(cl,'TFIELD','TDATETIMEFIELD') do
+ begin
+ RegisterProperty('VALUE', 'TDATETIME', iptrw);
+ RegisterProperty('DISPLAYFORMAT', 'String', iptrw);
+ end;
+end;
+
+procedure SIRegisterTBOOLEANFIELD(CL: TPSPascalCompiler);
+Begin
+With RegClassS(cl,'TFIELD','TBOOLEANFIELD') do
+ begin
+ RegisterProperty('VALUE', 'BOOLEAN', iptrw);
+ RegisterProperty('DISPLAYVALUES', 'String', iptrw);
+ end;
+end;
+
+procedure SIRegisterTCURRENCYFIELD(CL: TPSPascalCompiler);
+Begin
+With RegClassS(cl,'TFLOATFIELD','TCURRENCYFIELD') do
+ begin
+ end;
+end;
+
+procedure SIRegisterTFLOATFIELD(CL: TPSPascalCompiler);
+Begin
+With RegClassS(cl,'TNUMERICFIELD','TFLOATFIELD') do
+ begin
+ RegisterProperty('VALUE', 'DOUBLE', iptrw);
+ RegisterProperty('CURRENCY', 'BOOLEAN', iptrw);
+ RegisterProperty('MAXVALUE', 'DOUBLE', iptrw);
+ RegisterProperty('MINVALUE', 'DOUBLE', iptrw);
+ RegisterProperty('PRECISION', 'INTEGER', iptrw);
+ end;
+end;
+
+procedure SIRegisterTAUTOINCFIELD(CL: TPSPascalCompiler);
+Begin
+With RegClassS(cl,'TINTEGERFIELD','TAUTOINCFIELD') do
+ begin
+ end;
+end;
+
+procedure SIRegisterTWORDFIELD(CL: TPSPascalCompiler);
+Begin
+With RegClassS(cl,'TINTEGERFIELD','TWORDFIELD') do
+ begin
+ end;
+end;
+
+procedure SIRegisterTLARGEINTFIELD(CL: TPSPascalCompiler);
+Begin
+With RegClassS(cl,'TNUMERICFIELD','TLARGEINTFIELD') do
+ begin
+ RegisterProperty('ASLARGEINT', 'LARGEINT', iptrw);
+ RegisterProperty('VALUE', 'LARGEINT', iptrw);
+ RegisterProperty('MAXVALUE', 'LARGEINT', iptrw);
+ RegisterProperty('MINVALUE', 'LARGEINT', iptrw);
+ end;
+end;
+
+procedure SIRegisterTSMALLINTFIELD(CL: TPSPascalCompiler);
+Begin
+With RegClassS(cl,'TINTEGERFIELD','TSMALLINTFIELD') do
+ begin
+ end;
+end;
+
+procedure SIRegisterTINTEGERFIELD(CL: TPSPascalCompiler);
+Begin
+With RegClassS(cl,'TNUMERICFIELD','TINTEGERFIELD') do
+ begin
+ RegisterProperty('VALUE', 'LONGINT', iptrw);
+ RegisterProperty('MAXVALUE', 'LONGINT', iptrw);
+ RegisterProperty('MINVALUE', 'LONGINT', iptrw);
+ end;
+end;
+
+procedure SIRegisterTNUMERICFIELD(CL: TPSPascalCompiler);
+Begin
+With RegClassS(cl,'TFIELD','TNUMERICFIELD') do
+ begin
+ RegisterProperty('DISPLAYFORMAT', 'String', iptrw);
+ RegisterProperty('EDITFORMAT', 'String', iptrw);
+ end;
+end;
+
+procedure SIRegisterTWIDESTRINGFIELD(CL: TPSPascalCompiler);
+Begin
+With RegClassS(cl,'TSTRINGFIELD','TWIDESTRINGFIELD') do
+ begin
+ RegisterProperty('VALUE', 'WIDESTRING', iptrw);
+ end;
+end;
+
+procedure SIRegisterTSTRINGFIELD(CL: TPSPascalCompiler);
+Begin
+With RegClassS(cl,'TFIELD','TSTRINGFIELD') do
+ begin
+ RegisterProperty('VALUE', 'String', iptrw);
+ RegisterProperty('FIXEDCHAR', 'BOOLEAN', iptrw);
+ RegisterProperty('TRANSLITERATE', 'BOOLEAN', iptrw);
+ end;
+end;
+
+procedure SIRegisterTFIELD(CL: TPSPascalCompiler);
+Begin
+With RegClassS(cl,'TCOMPONENT','TFIELD') do
+ begin
+//RegisterMethod('Procedure ASSIGNVALUE( const VALUE : TVARREC)');
+ RegisterMethod('Procedure CLEAR');
+ RegisterMethod('Procedure FOCUSCONTROL');
+// RegisterMethod('Function GETDATA( BUFFER : POINTER; NATIVEFORMAT : BOOLEAN) : BOOLEAN');
+ RegisterMethod('Function ISVALIDCHAR( INPUTCHAR : CHAR) : BOOLEAN');
+ RegisterMethod('Procedure REFRESHLOOKUPLIST');
+// RegisterMethod('Procedure SETDATA( BUFFER : POINTER; NATIVEFORMAT : BOOLEAN)');
+ RegisterMethod('Procedure SETFIELDTYPE( VALUE : TFIELDTYPE)');
+// RegisterMethod('Procedure VALIDATE( BUFFER : POINTER)');
+{$IFDEF DELPHI6UP}
+ RegisterProperty('ASBCD', 'TBCD', iptrw);
+{$ENDIF}
+ RegisterProperty('ASBOOLEAN', 'BOOLEAN', iptrw);
+ RegisterProperty('ASCURRENCY', 'CURRENCY', iptrw);
+ RegisterProperty('ASDATETIME', 'TDATETIME', iptrw);
+ RegisterProperty('ASFLOAT', 'DOUBLE', iptrw);
+ RegisterProperty('ASINTEGER', 'LONGINT', iptrw);
+ RegisterProperty('ASSTRING', 'String', iptrw);
+ RegisterProperty('ASVARIANT', 'VARIANT', iptrw);
+ RegisterProperty('ATTRIBUTESET', 'String', iptrw);
+ RegisterProperty('CALCULATED', 'BOOLEAN', iptrw);
+ RegisterProperty('CANMODIFY', 'BOOLEAN', iptr);
+ RegisterProperty('CURVALUE', 'VARIANT', iptr);
+ RegisterProperty('DATASET', 'TDATASET', iptrw);
+ RegisterProperty('DATASIZE', 'INTEGER', iptr);
+ RegisterProperty('DATATYPE', 'TFIELDTYPE', iptr);
+ RegisterProperty('DISPLAYNAME', 'String', iptr);
+ RegisterProperty('DISPLAYTEXT', 'String', iptr);
+ RegisterProperty('EDITMASK', 'TEDITMASK', iptrw);
+ RegisterProperty('EDITMASKPTR', 'TEDITMASK', iptr);
+ RegisterProperty('EDITMASK', 'String', iptrw);
+ RegisterProperty('EDITMASKPTR', 'String', iptr);
+ RegisterProperty('FIELDNO', 'INTEGER', iptr);
+ RegisterProperty('FULLNAME', 'String', iptr);
+ RegisterProperty('ISINDEXFIELD', 'BOOLEAN', iptr);
+ RegisterProperty('ISNULL', 'BOOLEAN', iptr);
+ RegisterProperty('LOOKUP', 'BOOLEAN', iptrw);
+ RegisterProperty('LOOKUPLIST', 'TLOOKUPLIST', iptr);
+ RegisterProperty('NEWVALUE', 'VARIANT', iptrw);
+ RegisterProperty('OFFSET', 'INTEGER', iptr);
+ RegisterProperty('OLDVALUE', 'VARIANT', iptr);
+ RegisterProperty('PARENTFIELD', 'TOBJECTFIELD', iptrw);
+ RegisterProperty('SIZE', 'INTEGER', iptrw);
+ RegisterProperty('TEXT', 'String', iptrw);
+ RegisterProperty('VALIDCHARS', 'TFIELDCHARS', iptrw);
+ RegisterProperty('VALUE', 'VARIANT', iptrw);
+ RegisterProperty('ALIGNMENT', 'TALIGNMENT', iptrw);
+ RegisterProperty('AUTOGENERATEVALUE', 'TAUTOREFRESHFLAG', iptrw);
+ RegisterProperty('CUSTOMCONSTRAINT', 'String', iptrw);
+ RegisterProperty('CONSTRAINTERRORMESSAGE', 'String', iptrw);
+ RegisterProperty('DEFAULTEXPRESSION', 'String', iptrw);
+ RegisterProperty('DISPLAYLABEL', 'String', iptrw);
+ RegisterProperty('DISPLAYWIDTH', 'INTEGER', iptrw);
+ RegisterProperty('FIELDKIND', 'TFIELDKIND', iptrw);
+ RegisterProperty('FIELDNAME', 'String', iptrw);
+ RegisterProperty('HASCONSTRAINTS', 'BOOLEAN', iptr);
+ RegisterProperty('INDEX', 'INTEGER', iptrw);
+ RegisterProperty('IMPORTEDCONSTRAINT', 'String', iptrw);
+ RegisterProperty('LOOKUPDATASET', 'TDATASET', iptrw);
+ RegisterProperty('LOOKUPKEYFIELDS', 'String', iptrw);
+ RegisterProperty('LOOKUPRESULTFIELD', 'String', iptrw);
+ RegisterProperty('KEYFIELDS', 'String', iptrw);
+ RegisterProperty('LOOKUPCACHE', 'BOOLEAN', iptrw);
+ RegisterProperty('ORIGIN', 'String', iptrw);
+ RegisterProperty('PROVIDERFLAGS', 'TPROVIDERFLAGS', iptrw);
+ RegisterProperty('READONLY', 'BOOLEAN', iptrw);
+ RegisterProperty('REQUIRED', 'BOOLEAN', iptrw);
+ RegisterProperty('VISIBLE', 'BOOLEAN', iptrw);
+ RegisterProperty('ONCHANGE', 'TFIELDNOTIFYEVENT', iptrw);
+ RegisterProperty('ONGETTEXT', 'TFIELDGETTEXTEVENT', iptrw);
+ RegisterProperty('ONSETTEXT', 'TFIELDSETTEXTEVENT', iptrw);
+ RegisterProperty('ONVALIDATE', 'TFIELDNOTIFYEVENT', iptrw);
+ end;
+end;
+
+procedure SIRegisterTLOOKUPLIST(CL: TPSPascalCompiler);
+Begin
+With RegClassS(cl,'TOBJECT','TLOOKUPLIST') do
+ begin
+ RegisterMethod('Constructor CREATE');
+ RegisterMethod('Procedure ADD( const AKEY, AVALUE : VARIANT)');
+ RegisterMethod('Procedure CLEAR');
+ RegisterMethod('Function VALUEOFKEY( const AKEY : VARIANT) : VARIANT');
+ end;
+end;
+
+procedure SIRegisterTFIELDS(CL: TPSPascalCompiler);
+Begin
+With RegClassS(cl,'TOBJECT','TFIELDS') do
+ begin
+ RegisterMethod('Constructor CREATE( ADATASET : TDATASET)');
+ RegisterMethod('Procedure ADD( FIELD : TFIELD)');
+ RegisterMethod('Procedure CHECKFIELDNAME( const FIELDNAME : String)');
+ RegisterMethod('Procedure CHECKFIELDNAMES( const FIELDNAMES : String)');
+ RegisterMethod('Procedure CLEAR');
+ RegisterMethod('Function FINDFIELD( const FIELDNAME : String) : TFIELD');
+ RegisterMethod('Function FIELDBYNAME( const FIELDNAME : String) : TFIELD');
+ RegisterMethod('Function FIELDBYNUMBER( FIELDNO : INTEGER) : TFIELD');
+ RegisterMethod('Procedure GETFIELDNAMES( LIST : TSTRINGS)');
+ RegisterMethod('Function INDEXOF( FIELD : TFIELD) : INTEGER');
+ RegisterMethod('Procedure REMOVE( FIELD : TFIELD)');
+ RegisterProperty('COUNT', 'INTEGER', iptr);
+ RegisterProperty('DATASET', 'TDATASET', iptr);
+ RegisterProperty('FIELDS', 'TFIELD INTEGER', iptrw);
+ end;
+end;
+
+procedure SIRegisterTFIELDLIST(CL: TPSPascalCompiler);
+Begin
+With RegClassS(cl,'TFLATLIST','TFIELDLIST') do
+ begin
+ RegisterMethod('Function FIELDBYNAME( const NAME : String) : TFIELD');
+ RegisterMethod('Function FIND( const NAME : String) : TFIELD');
+ RegisterProperty('FIELDS', 'TFIELD INTEGER', iptr);
+ end;
+end;
+
+procedure SIRegisterTFIELDDEFLIST(CL: TPSPascalCompiler);
+Begin
+With RegClassS(cl,'TFLATLIST','TFIELDDEFLIST') do
+ begin
+ RegisterMethod('Function FIELDBYNAME( const NAME : String) : TFIELDDEF');
+ RegisterMethod('Function FIND( const NAME : String) : TFIELDDEF');
+ RegisterProperty('FIELDDEFS', 'TFIELDDEF INTEGER', iptr);
+ end;
+end;
+
+procedure SIRegisterTFLATLIST(CL: TPSPascalCompiler);
+Begin
+With RegClassS(cl,'TSTRINGLIST','TFLATLIST') do
+ begin
+ RegisterMethod('Constructor CREATE( ADATASET : TDATASET)');
+ RegisterMethod('Procedure UPDATE');
+ RegisterProperty('DATASET', 'TDATASET', iptr);
+ end;
+end;
+
+procedure SIRegisterTINDEXDEFS(CL: TPSPascalCompiler);
+Begin
+With RegClassS(cl,'TDEFCOLLECTION','TINDEXDEFS') do
+ begin
+ RegisterMethod('Constructor CREATE( ADATASET : TDATASET)');
+ RegisterMethod('Function ADDINDEXDEF : TINDEXDEF');
+ RegisterMethod('Function FIND( const NAME : String) : TINDEXDEF');
+ RegisterMethod('Procedure UPDATE');
+ RegisterMethod('Function FINDINDEXFORFIELDS( const FIELDS : String) : TINDEXDEF');
+ RegisterMethod('Function GETINDEXFORFIELDS( const FIELDS : String; CASEINSENSITIVE : BOOLEAN) : TINDEXDEF');
+ RegisterMethod('Procedure ADD( const NAME, FIELDS : String; OPTIONS : TINDEXOPTIONS)');
+ RegisterProperty('ITEMS', 'TINDEXDEF INTEGER', iptrw);
+ end;
+end;
+
+procedure SIRegisterTINDEXDEF(CL: TPSPascalCompiler);
+Begin
+With RegClassS(cl,'TNAMEDITEM','TINDEXDEF') do
+ begin
+ RegisterMethod('Constructor CREATE( OWNER : TINDEXDEFS; const NAME, FIELDS : String; OPTIONS : TINDEXOPTIONS)');
+ RegisterProperty('FIELDEXPRESSION', 'String', iptr);
+ RegisterProperty('CASEINSFIELDS', 'String', iptrw);
+ RegisterProperty('DESCFIELDS', 'String', iptrw);
+ RegisterProperty('EXPRESSION', 'String', iptrw);
+ RegisterProperty('FIELDS', 'String', iptrw);
+ RegisterProperty('OPTIONS', 'TINDEXOPTIONS', iptrw);
+ RegisterProperty('SOURCE', 'String', iptrw);
+ RegisterProperty('GROUPINGLEVEL', 'INTEGER', iptrw);
+ end;
+end;
+
+procedure SIRegisterTFIELDDEFS(CL: TPSPascalCompiler);
+Begin
+With RegClassS(cl,'TDEFCOLLECTION','TFIELDDEFS') do
+ begin
+ RegisterMethod('Constructor CREATE( AOWNER : TPERSISTENT)');
+ RegisterMethod('Function ADDFIELDDEF : TFIELDDEF');
+ RegisterMethod('Function FIND( const NAME : String) : TFIELDDEF');
+ RegisterMethod('Procedure UPDATE');
+ RegisterMethod('Procedure ADD( const NAME : String; DATATYPE : TFIELDTYPE; SIZE : INTEGER; REQUIRED : BOOLEAN)');
+ RegisterProperty('HIDDENFIELDS', 'BOOLEAN', iptrw);
+ RegisterProperty('ITEMS', 'TFIELDDEF INTEGER', iptrw);
+ RegisterProperty('PARENTDEF', 'TFIELDDEF', iptr);
+ end;
+end;
+
+procedure SIRegisterTFIELDDEF(CL: TPSPascalCompiler);
+Begin
+With RegClassS(cl,'TNAMEDITEM','TFIELDDEF') do
+ begin
+// RegisterMethod('Constructor CREATE( OWNER : TFIELDDEFS; const NAME : STRING; DATATYPE : TFIELDTYPE; SIZE : INTEGER; REQUIRED : BOOLEAN; FIELDNO : INTEGER)');
+ RegisterMethod('Function ADDCHILD : TFIELDDEF');
+ RegisterMethod('Function CREATEFIELD( OWNER : TCOMPONENT; PARENTFIELD : TOBJECTFIELD; const FIELDNAME : String; CREATECHILDREN : BOOLEAN) : TFIELD');
+ RegisterMethod('Function HASCHILDDEFS : BOOLEAN');
+ RegisterProperty('FIELDCLASS', 'TFIELDCLASS', iptr);
+ RegisterProperty('FIELDNO', 'INTEGER', iptrw);
+ RegisterProperty('INTERNALCALCFIELD', 'BOOLEAN', iptrw);
+ RegisterProperty('PARENTDEF', 'TFIELDDEF', iptr);
+ RegisterProperty('REQUIRED', 'BOOLEAN', iptrw);
+ RegisterProperty('ATTRIBUTES', 'TFIELDATTRIBUTES', iptrw);
+ RegisterProperty('CHILDDEFS', 'TFIELDDEFS', iptrw);
+ RegisterProperty('DATATYPE', 'TFIELDTYPE', iptrw);
+ RegisterProperty('PRECISION', 'INTEGER', iptrw);
+ RegisterProperty('SIZE', 'INTEGER', iptrw);
+ end;
+end;
+
+procedure SIRegisterTDEFCOLLECTION(CL: TPSPascalCompiler);
+Begin
+With RegClassS(cl,'TOWNEDCOLLECTION','TDEFCOLLECTION') do
+ begin
+// RegisterMethod('Constructor CREATE( ADATASET : TDATASET; AOWNER : TPERSISTENT; ACLASS : TCOLLECTIONITEMCLASS)');
+ RegisterMethod('Function FIND( const ANAME : String) : TNAMEDITEM');
+ RegisterMethod('Procedure GETITEMNAMES( LIST : TSTRINGS)');
+ RegisterMethod('Function INDEXOF( const ANAME : String) : INTEGER');
+ RegisterProperty('DATASET', 'TDATASET', iptr);
+ RegisterProperty('UPDATED', 'BOOLEAN', iptrw);
+ end;
+end;
+
+procedure SIRegisterTNAMEDITEM(CL: TPSPascalCompiler);
+Begin
+With RegClassS(cl,'TCOLLECTIONITEM','TNAMEDITEM') do
+ begin
+ RegisterProperty('NAME', 'String', iptrw);
+ end;
+end;
+
+procedure SIRegister_DB(Cl: TPSPascalCompiler);
+Begin
+cl.AddTypeS('TFieldType', '(ftUnknown, ftString, ftSmallint, ftInteger, ftWord, ftBoolean, ftFloat, ftCurrency, ftBCD, ftDate, ftTime, ftDateTime,'+
+ 'ftBytes, ftVarBytes, ftAutoInc, ftBlob, ftMemo, ftGraphic, ftFmtMemo, ftParadoxOle, ftDBaseOle, ftTypedBinary, ftCursor, ftFixedChar, ftWideString,'+
+ 'ftLargeint, ftADT, ftArray, ftReference, ftDataSet, ftOraBlob, ftOraClob, ftVariant, ftInterface, ftIDispatch, ftGuid, ftTimeStamp, ftFMTBcd)');
+
+ CL.AddTypeS('TDataSetState', '(dsInactive, dsBrowse, dsEdit, dsInsert, dsSetKey, dsCalcFields, dsFilter, dsNewValue, dsOldValue, dsCurValue, dsBlockRead, dsInternalCalc, dsOpening)');
+
+cl.addTypeS('TLocateOption','(loCaseInsensitive, loPartialKey)');
+cl.addtypes('TLocateOptions','set of TLocateOption');
+cl.addtypes('TUpdateStatus','(usUnmodified, usModified, usInserted, usDeleted)');
+cl.addtypes('TUpdateStatusSet', 'set of TUpdateStatus');
+
+ cl.addTypeS('TPARAMTYPE', 'BYTE');
+RegClassS(cl,'TComponent','TDATASET');
+RegClassS(cl,'TComponent','TFIELD');
+RegClassS(cl,'TComponent','TFIELDDEFS');
+RegClassS(cl,'TComponent','TINDEXDEFS');
+RegClassS(cl, 'TComponent', 'TObjectField');
+RegClassS(cl, 'TComponent', 'TDataLink');
+RegClassS(cl, 'TComponent', 'TDataSource');
+RegClassS(cl, 'TComponent', 'TParam');
+
+SIRegisterTNAMEDITEM(Cl);
+Cl.addTypeS('TDEFUPDATEMETHOD', 'Procedure');
+SIRegisterTDEFCOLLECTION(Cl);
+cl.AddConstantN('FAHIDDENCOL','LONGINT').Value.tu32 := 1;
+cl.AddConstantN('FAREADONLY','LONGINT').Value.tu32 := 2;
+cl.AddConstantN('FAREQUIRED','LONGINT').Value.tu32 := 4;
+cl.AddConstantN('FALINK','LONGINT').Value.tu32 := 8;
+cl.AddConstantN('FAUNNAMED','LONGINT').Value.tu32 := 16;
+cl.AddConstantN('FAFIXED','LONGINT').Value.tu32 := 32;
+cl.addTypeS('TFIELDATTRIBUTES', 'BYTE');
+SIRegisterTFIELDDEF(Cl);
+SIRegisterTFIELDDEFS(Cl);
+cl.AddConstantN('IXPRIMARY','LONGINT').Value.tu32 := 1;
+cl.AddConstantN('IXUNIQUE','LONGINT').Value.tu32 := 2;
+cl.AddConstantN('IXDESCENDING','LONGINT').Value.tu32 := 4;
+cl.AddConstantN('IXCASEINSENSITIVE','LONGINT').Value.tu32 := 8;
+cl.AddConstantN('IXEXPRESSION','LONGINT').Value.tu32 := 16;
+cl.AddConstantN('IXNONMAINTAINED','LONGINT').Value.tu32 := 32;
+cl.addTypeS('TINDEXOPTIONS', 'BYTE');
+SIRegisterTINDEXDEF(Cl);
+SIRegisterTINDEXDEFS(Cl);
+SIRegisterTFLATLIST(Cl);
+SIRegisterTFIELDDEFLIST(Cl);
+SIRegisterTFIELDLIST(Cl);
+cl.AddConstantN('FKDATA','LONGINT').Value.tu32 := 1;
+cl.AddConstantN('FKCALCULATED','LONGINT').Value.tu32 := 2;
+cl.AddConstantN('FKLOOKUP','LONGINT').Value.tu32 := 4;
+cl.AddConstantN('FKINTERNALCALC','LONGINT').Value.tu32 := 8;
+cl.AddConstantN('FKAGGREGATE','LONGINT').Value.tu32 := 16;
+cl.addTypeS('TFIELDKINDS', 'BYTE');
+SIRegisterTFIELDS(Cl);
+cl.AddConstantN('PFINUPDATE','LONGINT').Value.tu32 := 1;
+cl.AddConstantN('PFINWHERE','LONGINT').Value.tu32 := 2;
+cl.AddConstantN('PFINKEY','LONGINT').Value.tu32 := 4;
+cl.AddConstantN('PFHIDDEN','LONGINT').Value.tu32 :=8;
+cl.addTypeS('TPROVIDERFLAGS', 'BYTE');
+cl.addTypeS('TFIELDNOTIFYEVENT', 'Procedure ( SENDER : TFIELD)');
+cl.addTypeS('TFIELDGETTEXTEVENT', 'Procedure ( SENDER : TFIELD; var TEXT : S'
+ +'TRING; DISPLAYTEXT : BOOLEAN)');
+cl.addTypeS('TFIELDSETTEXTEVENT', 'Procedure ( SENDER : TFIELD; const TEXT :'
+ +' String)');
+cl.addTypeS('TAUTOREFRESHFLAG', '( ARNONE, ARAUTOINC, ARDEFAULT )');
+SIRegisterTLOOKUPLIST(Cl);
+SIRegisterTFIELD(Cl);
+SIRegisterTSTRINGFIELD(Cl);
+SIRegisterTWIDESTRINGFIELD(Cl);
+SIRegisterTNUMERICFIELD(Cl);
+SIRegisterTINTEGERFIELD(Cl);
+SIRegisterTSMALLINTFIELD(Cl);
+cl.addTypeS('LARGEINT', 'INT64');
+SIRegisterTLARGEINTFIELD(Cl);
+SIRegisterTWORDFIELD(Cl);
+SIRegisterTAUTOINCFIELD(Cl);
+SIRegisterTFLOATFIELD(Cl);
+SIRegisterTCURRENCYFIELD(Cl);
+SIRegisterTBOOLEANFIELD(Cl);
+SIRegisterTDATETIMEFIELD(Cl);
+SIRegisterTDATEFIELD(Cl);
+SIRegisterTTIMEFIELD(Cl);
+SIRegisterTBINARYFIELD(Cl);
+SIRegisterTBYTESFIELD(Cl);
+SIRegisterTVARBYTESFIELD(Cl);
+SIRegisterTBCDFIELD(Cl);
+{$IFDEF DELPHI6UP}
+SIRegisterTFMTBCDFIELD(Cl);
+{$ENDIF}
+cl.addTypeS('TBLOBTYPE', 'BYTE');
+SIRegisterTBLOBFIELD(Cl);
+SIRegisterTMEMOFIELD(Cl);
+SIRegisterTGRAPHICFIELD(Cl);
+SIRegisterTOBJECTFIELD(Cl);
+SIRegisterTADTFIELD(Cl);
+SIRegisterTARRAYFIELD(Cl);
+SIRegisterTDATASETFIELD(Cl);
+SIRegisterTREFERENCEFIELD(Cl);
+SIRegisterTVARIANTFIELD(Cl);
+SIRegisterTGUIDFIELD(Cl);
+cl.addTypeS('TBLOBDATA', 'STRING');
+cl.AddConstantN('PTUNKNOWN','LONGINT').Value.tu32 := 1;
+cl.AddConstantN('PTINPUT','LONGINT').Value.tu32 := 2;
+cl.AddConstantN('PTOUTPUT','LONGINT').Value.tu32 := 4;
+cl.AddConstantN('PTINPUTOUTPUT','LONGINT').Value.tu32 := 8;
+cl.AddConstantN('PTRESULT','LONGINT').Value.tu32 := 16;
+RegClassS(cl,'TObject','TPARAMS');
+SIRegisterTPARAM(Cl);
+SIRegisterTPARAMS(Cl);
+cl.addTypeS('TDATAACTION', '( DAFAIL, DAABORT, DARETRY )');
+cl.addTypeS('TBLOBSTREAMMODE', '( BMREAD, BMWRITE, BMREADWRITE )');
+cl.addTypeS('TDATAOPERATION', 'Procedure');
+cl.addTypeS('TDATASETNOTIFYEVENT', 'Procedure ( DATASET : TDATASET)');
+cl.addTypeS('TDATASETERROREVENT', 'Procedure ( DATASET : TDATASET; E : TObject'
+ +'; var ACTION : TDATAACTION)');
+cl.addTypeS('TFILTERRECORDEVENT', 'Procedure ( DATASET : TDATASET; var ACCEP'
+ +'T : BOOLEAN)');
+SIRegisterTDATASET(Cl);
+end;
+
+{$IFDEF USEIMPORTER}
+initialization
+CIImporter.AddCallBack(@SIRegister_DB,PT_ClassImport);
+{$ENDIF}
+end.
diff --git a/branches/script-component/Units/PascalScript/uPSC_buttons.pas b/branches/script-component/Units/PascalScript/uPSC_buttons.pas
new file mode 100644
index 0000000..d06b97c
--- /dev/null
+++ b/branches/script-component/Units/PascalScript/uPSC_buttons.pas
@@ -0,0 +1,87 @@
+{ Compiletime Buttons support }
+unit uPSC_buttons;
+{$I PascalScript.inc}
+interface
+uses
+ uPSCompiler, uPSUtils;
+
+{
+ Will register files from:
+ Buttons
+
+ Requires
+ STD, classes, controls and graphics and StdCtrls
+}
+procedure SIRegister_Buttons_TypesAndConsts(Cl: TPSPascalCompiler);
+
+procedure SIRegisterTSPEEDBUTTON(Cl: TPSPascalCompiler);
+procedure SIRegisterTBITBTN(Cl: TPSPascalCompiler);
+
+procedure SIRegister_Buttons(Cl: TPSPascalCompiler);
+
+implementation
+
+procedure SIRegisterTSPEEDBUTTON(Cl: TPSPascalCompiler);
+begin
+ with Cl.AddClassN(cl.FindClass('TGRAPHICCONTROL'), 'TSPEEDBUTTON') do
+ begin
+ RegisterProperty('ALLOWALLUP', 'BOOLEAN', iptrw);
+ RegisterProperty('GROUPINDEX', 'INTEGER', iptrw);
+ RegisterProperty('DOWN', 'BOOLEAN', iptrw);
+ RegisterProperty('CAPTION', 'String', iptrw);
+ RegisterProperty('FONT', 'TFont', iptrw);
+ RegisterProperty('GLYPH', 'TBITMAP', iptrw);
+ RegisterProperty('LAYOUT', 'TBUTTONLAYOUT', iptrw);
+ RegisterProperty('MARGIN', 'INTEGER', iptrw);
+ RegisterProperty('NUMGLYPHS', 'BYTE', iptrw);
+ RegisterProperty('PARENTFONT', 'Boolean', iptrw);
+ RegisterProperty('PARENTSHOWHINT', 'Boolean', iptrw);
+ RegisterProperty('SPACING', 'INTEGER', iptrw);
+ RegisterProperty('ONCLICK', 'TNotifyEvent', iptrw);
+ RegisterProperty('ONDBLCLICK', 'TNotifyEvent', iptrw);
+ RegisterProperty('ONMOUSEDOWN', 'TMouseEvent', iptrw);
+ RegisterProperty('ONMOUSEMOVE', 'TMouseMoveEvent', iptrw);
+ RegisterProperty('ONMOUSEUP', 'TMouseEvent', iptrw);
+ end;
+end;
+
+procedure SIRegisterTBITBTN(Cl: TPSPascalCompiler);
+begin
+ with Cl.AddClassN(cl.FindClass('TBUTTON'), 'TBITBTN') do
+ begin
+ RegisterProperty('GLYPH', 'TBITMAP', iptrw);
+ RegisterProperty('KIND', 'TBITBTNKIND', iptrw);
+ RegisterProperty('LAYOUT', 'TBUTTONLAYOUT', iptrw);
+ RegisterProperty('MARGIN', 'INTEGER', iptrw);
+ RegisterProperty('NUMGLYPHS', 'BYTE', iptrw);
+ RegisterProperty('STYLE', 'TBUTTONSTYLE', iptrw);
+ RegisterProperty('SPACING', 'INTEGER', iptrw);
+ end;
+end;
+
+
+
+procedure SIRegister_Buttons_TypesAndConsts(Cl: TPSPascalCompiler);
+begin
+ Cl.AddTypeS('TButtonLayout', '(blGlyphLeft, blGlyphRight, blGlyphTop, blGlyphBottom)');
+ Cl.AddTypeS('TButtonState', '(bsUp, bsDisabled, bsDown, bsExclusive)');
+ Cl.AddTypeS('TButtonStyle', '(bsAutoDetect, bsWin31, bsNew)');
+ Cl.AddTypeS('TBitBtnKind', '(bkCustom, bkOK, bkCancel, bkHelp, bkYes, bkNo, bkClose, bkAbort, bkRetry, bkIgnore, bkAll)');
+
+end;
+
+procedure SIRegister_Buttons(Cl: TPSPascalCompiler);
+begin
+ SIRegister_Buttons_TypesAndConsts(cl);
+ SIRegisterTSPEEDBUTTON(cl);
+ SIRegisterTBITBTN(cl);
+end;
+
+// PS_MINIVCL changes by Martijn Laan (mlaan at wintax _dot_ nl)
+
+
+end.
+
+
+
+
diff --git a/branches/script-component/Units/PascalScript/uPSC_classes.pas b/branches/script-component/Units/PascalScript/uPSC_classes.pas
new file mode 100644
index 0000000..ee63e41
--- /dev/null
+++ b/branches/script-component/Units/PascalScript/uPSC_classes.pas
@@ -0,0 +1,320 @@
+{ Compiletime Classes support }
+unit uPSC_classes;
+
+{$I PascalScript.inc}
+interface
+uses
+ uPSCompiler, uPSUtils;
+
+{
+ Will register files from:
+ Classes (exception TPersistent and TComponent)
+
+ Register STD first
+
+}
+
+procedure SIRegister_Classes_TypesAndConsts(Cl: TPSPascalCompiler);
+
+procedure SIRegisterTStrings(cl: TPSPascalCompiler; Streams: Boolean);
+procedure SIRegisterTStringList(cl: TPSPascalCompiler);
+{$IFNDEF PS_MINIVCL}
+procedure SIRegisterTBITS(Cl: TPSPascalCompiler);
+{$ENDIF}
+procedure SIRegisterTSTREAM(Cl: TPSPascalCompiler);
+procedure SIRegisterTHANDLESTREAM(Cl: TPSPascalCompiler);
+{$IFNDEF PS_MINIVCL}
+procedure SIRegisterTMEMORYSTREAM(Cl: TPSPascalCompiler);
+{$ENDIF}
+procedure SIRegisterTFILESTREAM(Cl: TPSPascalCompiler);
+{$IFNDEF PS_MINIVCL}
+procedure SIRegisterTCUSTOMMEMORYSTREAM(Cl: TPSPascalCompiler);
+procedure SIRegisterTRESOURCESTREAM(Cl: TPSPascalCompiler);
+procedure SIRegisterTPARSER(Cl: TPSPascalCompiler);
+procedure SIRegisterTCOLLECTIONITEM(CL: TPSPascalCompiler);
+procedure SIRegisterTCOLLECTION(CL: TPSPascalCompiler);
+{$IFDEF DELPHI3UP}
+procedure SIRegisterTOWNEDCOLLECTION(CL: TPSPascalCompiler);
+{$ENDIF}
+{$ENDIF}
+
+procedure SIRegister_Classes(Cl: TPSPascalCompiler; Streams: Boolean{$IFDEF D4PLUS}=True{$ENDIF});
+
+implementation
+
+procedure SIRegisterTStrings(cl: TPSPascalCompiler; Streams: Boolean); // requires TPersistent
+begin
+ with Cl.AddClassN(cl.FindClass('TPersistent'), 'TStrings') do
+ begin
+ IsAbstract := True;
+ RegisterMethod('function Add(S: string): Integer;');
+ RegisterMethod('procedure Append(S: string);');
+ RegisterMethod('procedure AddStrings(Strings: TStrings);');
+ RegisterMethod('procedure Clear;');
+ RegisterMethod('procedure Delete(Index: Integer);');
+ RegisterMethod('function IndexOf(const S: string): Integer; ');
+ RegisterMethod('procedure Insert(Index: Integer; S: string); ');
+ RegisterProperty('Count', 'Integer', iptR);
+ RegisterProperty('Text', 'String', iptrw);
+ RegisterProperty('CommaText', 'String', iptrw);
+ if Streams then
+ begin
+ RegisterMethod('procedure LoadFromFile(FileName: string); ');
+ RegisterMethod('procedure SaveToFile(FileName: string); ');
+ end;
+ RegisterProperty('Strings', 'String Integer', iptRW);
+ SetDefaultPropery('Strings');
+ RegisterProperty('Objects', 'TObject Integer', iptRW);
+
+ {$IFNDEF PS_MINIVCL}
+ RegisterMethod('procedure BeginUpdate;');
+ RegisterMethod('procedure EndUpdate;');
+ RegisterMethod('function Equals(Strings: TStrings): Boolean;');
+ RegisterMethod('procedure Exchange(Index1, Index2: Integer);');
+ RegisterMethod('function IndexOfName(Name: string): Integer;');
+ if Streams then
+ RegisterMethod('procedure LoadFromStream(Stream: TStream); ');
+ RegisterMethod('procedure Move(CurIndex, NewIndex: Integer); ');
+ if Streams then
+ RegisterMethod('procedure SaveToStream(Stream: TStream); ');
+ RegisterMethod('procedure SetText(Text: PChar); ');
+ RegisterProperty('Names', 'String Integer', iptr);
+ RegisterProperty('Values', 'String String', iptRW);
+ RegisterMethod('function AddObject(S:String;AObject:TObject):integer');
+ RegisterMethod('function GetText:PChar');
+ RegisterMethod('function IndexofObject(AObject:tObject):Integer');
+ RegisterMethod('procedure InsertObject(Index:Integer;S:String;AObject:TObject)');
+ {$ENDIF}
+ end;
+end;
+
+procedure SIRegisterTSTRINGLIST(Cl: TPSPascalCompiler);
+begin
+ with Cl.AddClassN(cl.FindClass('TStrings'), 'TStringList') do
+ begin
+ RegisterMethod('function Find(S:String;var Index:Integer):Boolean');
+ RegisterMethod('procedure Sort');
+ RegisterProperty('Duplicates', 'TDuplicates', iptrw);
+ RegisterProperty('Sorted', 'Boolean', iptrw);
+ RegisterProperty('OnChange', 'TNotifyEvent', iptrw);
+ RegisterProperty('OnChanging', 'TNotifyEvent', iptrw);
+ end;
+end;
+
+{$IFNDEF PS_MINIVCL}
+procedure SIRegisterTBITS(Cl: TPSPascalCompiler);
+begin
+ with Cl.AddClassN(cl.FindClass('TObject'), 'TBits') do
+ begin
+ RegisterMethod('function OpenBit:Integer');
+ RegisterProperty('Bits', 'Boolean Integer', iptrw);
+ RegisterProperty('Size', 'Integer', iptrw);
+ end;
+end;
+{$ENDIF}
+
+procedure SIRegisterTSTREAM(Cl: TPSPascalCompiler);
+begin
+ with Cl.AddClassN(cl.FindClass('TOBJECT'), 'TStream') do
+ begin
+ IsAbstract := True;
+ RegisterMethod('function Read(Buffer:String;Count:LongInt):LongInt');
+ RegisterMethod('function Write(Buffer:String;Count:LongInt):LongInt');
+ RegisterMethod('function Seek(Offset:LongInt;Origin:Word):LongInt');
+ RegisterMethod('procedure ReadBuffer(Buffer:String;Count:LongInt)');
+ RegisterMethod('procedure WriteBuffer(Buffer:String;Count:LongInt)');
+ {$IFDEF DELPHI4UP}
+ RegisterMethod('function CopyFrom(Source:TStream;Count:Int64):LongInt');
+ {$ELSE}
+ RegisterMethod('function CopyFrom(Source:TStream;Count:Integer):LongInt');
+ {$ENDIF}
+ RegisterProperty('Position', 'LongInt', iptrw);
+ RegisterProperty('Size', 'LongInt', iptrw);
+ end;
+end;
+
+procedure SIRegisterTHANDLESTREAM(Cl: TPSPascalCompiler);
+begin
+ with Cl.AddClassN(cl.FindClass('TSTREAM'), 'THandleStream') do
+ begin
+ RegisterMethod('constructor Create(AHandle:Integer)');
+ RegisterProperty('Handle', 'Integer', iptr);
+ end;
+end;
+
+{$IFNDEF PS_MINIVCL}
+procedure SIRegisterTMEMORYSTREAM(Cl: TPSPascalCompiler);
+begin
+ with Cl.AddClassN(cl.FindClass('TCUSTOMMEMORYSTREAM'), 'TMemoryStream') do
+ begin
+ RegisterMethod('procedure Clear');
+ RegisterMethod('procedure LoadFromStream(Stream:TStream)');
+ RegisterMethod('procedure LoadFromFile(FileName:String)');
+ RegisterMethod('procedure SetSize(NewSize:LongInt)');
+ end;
+end;
+{$ENDIF}
+
+procedure SIRegisterTFILESTREAM(Cl: TPSPascalCompiler);
+begin
+ with Cl.AddClassN(cl.FindClass('THandleStream'), 'TFileStream') do
+ begin
+ RegisterMethod('constructor Create(FileName:String;Mode:Word)');
+ end;
+end;
+
+{$IFNDEF PS_MINIVCL}
+procedure SIRegisterTCUSTOMMEMORYSTREAM(Cl: TPSPascalCompiler);
+begin
+ with Cl.AddClassN(cl.FindClass('TSTREAM'), 'TCustomMemoryStream') do
+ begin
+ IsAbstract := True;
+ RegisterMethod('procedure SaveToStream(Stream:TStream)');
+ RegisterMethod('procedure SaveToFile(FileName:String)');
+ end;
+end;
+
+procedure SIRegisterTRESOURCESTREAM(Cl: TPSPascalCompiler);
+begin
+ with Cl.AddClassN(cl.FindClass('TCUSTOMMEMORYSTREAM'), 'TResourceStream') do
+ begin
+ RegisterMethod('constructor Create(Instance:THandle;ResName:String;ResType:PChar)');
+ RegisterMethod('constructor CreateFromId(Instance:THandle;ResId:Integer;ResType:PChar)');
+ end;
+end;
+
+procedure SIRegisterTPARSER(Cl: TPSPascalCompiler);
+begin
+ with Cl.AddClassN(cl.FindClass('TOBJECT'), 'TParser') do
+ begin
+ RegisterMethod('constructor Create(Stream:TStream)');
+ RegisterMethod('procedure CheckToken(t:char)');
+ RegisterMethod('procedure CheckTokenSymbol(s:string)');
+ RegisterMethod('procedure Error(Ident:Integer)');
+ RegisterMethod('procedure ErrorStr(Message:String)');
+ RegisterMethod('procedure HexToBinary(Stream:TStream)');
+ RegisterMethod('function NextToken:Char');
+ RegisterMethod('function SourcePos:LongInt');
+ RegisterMethod('function TokenComponentIdent:String');
+ RegisterMethod('function TokenFloat:Extended');
+ RegisterMethod('function TokenInt:LongInt');
+ RegisterMethod('function TokenString:String');
+ RegisterMethod('function TokenSymbolIs(S:String):Boolean');
+ RegisterProperty('SourceLine', 'Integer', iptr);
+ RegisterProperty('Token', 'Char', iptr);
+ end;
+end;
+
+procedure SIRegisterTCOLLECTIONITEM(CL: TPSPascalCompiler);
+Begin
+ if cl.FindClass('TCOLLECTION') = nil then cl.AddClassN(cl.FindClass('TPERSISTENT'), 'TCollection');
+ With cl.AddClassN(cl.FindClass('TPERSISTENT'),'TCollectionItem') do
+ begin
+ RegisterMethod('Constructor Create( Collection : TCollection)');
+ RegisterProperty('Collection', 'TCollection', iptrw);
+{$IFDEF DELPHI3UP} RegisterProperty('Id', 'Integer', iptr); {$ENDIF}
+ RegisterProperty('Index', 'Integer', iptrw);
+{$IFDEF DELPHI3UP} RegisterProperty('DisplayName', 'String', iptrw); {$ENDIF}
+ end;
+end;
+
+procedure SIRegisterTCOLLECTION(CL: TPSPascalCompiler);
+var
+ cr: TPSCompileTimeClass;
+Begin
+ cr := CL.FindClass('TCOLLECTION');
+ if cr = nil then cr := cl.AddClassN(cl.FindClass('TPERSISTENT'), 'TCollection');
+With cr do
+ begin
+// RegisterMethod('constructor Create( ItemClass : TCollectionItemClass)');
+{$IFDEF DELPHI3UP} RegisterMethod('function Owner : TPersistent'); {$ENDIF}
+ RegisterMethod('function Add : TCollectionItem');
+ RegisterMethod('procedure BeginUpdate');
+ RegisterMethod('procedure Clear');
+{$IFDEF DELPHI5UP} RegisterMethod('procedure Delete( Index : Integer)'); {$ENDIF}
+ RegisterMethod('procedure EndUpdate');
+{$IFDEF DELPHI3UP} RegisterMethod('function FindItemId( Id : Integer) : TCollectionItem'); {$ENDIF}
+{$IFDEF DELPHI3UP} RegisterMethod('function Insert( Index : Integer) : TCollectionItem'); {$ENDIF}
+ RegisterProperty('Count', 'Integer', iptr);
+{$IFDEF DELPHI3UP} RegisterProperty('ItemClass', 'TCollectionItemClass', iptr); {$ENDIF}
+ RegisterProperty('Items', 'TCollectionItem Integer', iptrw);
+ end;
+end;
+
+{$IFDEF DELPHI3UP}
+procedure SIRegisterTOWNEDCOLLECTION(CL: TPSPascalCompiler);
+Begin
+With Cl.AddClassN(cl.FindClass('TCOLLECTION'),'TOwnedCollection') do
+ begin
+// RegisterMethod('Constructor CREATE( AOWNER : TPERSISTENT; ITEMCLASS : TCOLLECTIONITEMCLASS)');
+ end;
+end;
+{$ENDIF}
+{$ENDIF}
+
+procedure SIRegister_Classes_TypesAndConsts(Cl: TPSPascalCompiler);
+begin
+ cl.AddConstantN('soFromBeginning', 'Longint').Value.ts32 := 0;
+ cl.AddConstantN('soFromCurrent', 'Longint').Value.ts32 := 1;
+ cl.AddConstantN('soFromEnd', 'Longint').Value.ts32 := 2;
+ cl.AddConstantN('toEOF', 'Char').SetString(#0);
+ cl.AddConstantN('toSymbol', 'Char').SetString(#1);
+ cl.AddConstantN('toString', 'Char').SetString(#2);
+ cl.AddConstantN('toInteger', 'Char').SetString(#3);
+ cl.AddConstantN('toFloat', 'Char').SetString(#4);
+ cl.AddConstantN('fmCreate', 'Longint').Value.ts32 := $FFFF;
+ cl.AddConstantN('fmOpenRead', 'Longint').Value.ts32 := 0;
+ cl.AddConstantN('fmOpenWrite', 'Longint').Value.ts32 := 1;
+ cl.AddConstantN('fmOpenReadWrite', 'Longint').Value.ts32 := 2;
+ cl.AddConstantN('fmShareCompat', 'Longint').Value.ts32 := 0;
+ cl.AddConstantN('fmShareExclusive', 'Longint').Value.ts32 := $10;
+ cl.AddConstantN('fmShareDenyWrite', 'Longint').Value.ts32 := $20;
+ cl.AddConstantN('fmShareDenyRead', 'Longint').Value.ts32 := $30;
+ cl.AddConstantN('fmShareDenyNone', 'Longint').Value.ts32 := $40;
+ cl.AddConstantN('SecsPerDay', 'Longint').Value.ts32 := 86400;
+ cl.AddConstantN('MSecPerDay', 'Longint').Value.ts32 := 86400000;
+ cl.AddConstantN('DateDelta', 'Longint').Value.ts32 := 693594;
+ cl.AddTypeS('TAlignment', '(taLeftJustify, taRightJustify, taCenter)');
+ cl.AddTypeS('THelpEvent', 'function (Command: Word; Data: Longint; var CallHelp: Boolean): Boolean');
+ cl.AddTypeS('TGetStrProc', 'procedure(const S: string)');
+ cl.AddTypeS('TDuplicates', '(dupIgnore, dupAccept, dupError)');
+ cl.AddTypeS('TOperation', '(opInsert, opRemove)');
+ cl.AddTypeS('THANDLE', 'Longint');
+
+ cl.AddTypeS('TNotifyEvent', 'procedure (Sender: TObject)');
+end;
+
+procedure SIRegister_Classes(Cl: TPSPascalCompiler; Streams: Boolean);
+begin
+ SIRegister_Classes_TypesAndConsts(Cl);
+ if Streams then
+ SIRegisterTSTREAM(Cl);
+ SIRegisterTStrings(cl, Streams);
+ SIRegisterTStringList(cl);
+ {$IFNDEF PS_MINIVCL}
+ SIRegisterTBITS(cl);
+ {$ENDIF}
+ if Streams then
+ begin
+ SIRegisterTHANDLESTREAM(Cl);
+ SIRegisterTFILESTREAM(Cl);
+ {$IFNDEF PS_MINIVCL}
+ SIRegisterTCUSTOMMEMORYSTREAM(Cl);
+ SIRegisterTMEMORYSTREAM(Cl);
+ SIRegisterTRESOURCESTREAM(Cl);
+ {$ENDIF}
+ end;
+ {$IFNDEF PS_MINIVCL}
+ SIRegisterTPARSER(Cl);
+ SIRegisterTCOLLECTIONITEM(Cl);
+ SIRegisterTCOLLECTION(Cl);
+ {$IFDEF DELPHI3UP}
+ SIRegisterTOWNEDCOLLECTION(Cl);
+ {$ENDIF}
+ {$ENDIF}
+end;
+
+// PS_MINIVCL changes by Martijn Laan (mlaan at wintax _dot_ nl)
+
+
+end.
diff --git a/branches/script-component/Units/PascalScript/uPSC_comobj.pas b/branches/script-component/Units/PascalScript/uPSC_comobj.pas
new file mode 100644
index 0000000..543d941
--- /dev/null
+++ b/branches/script-component/Units/PascalScript/uPSC_comobj.pas
@@ -0,0 +1,28 @@
+{ compiletime ComObj support }
+unit uPSC_comobj;
+
+{$I PascalScript.inc}
+interface
+uses
+ uPSCompiler, uPSUtils;
+
+{
+
+Will register:
+
+function CreateOleObject(const ClassName: String): IDispatch;
+function GetActiveOleObject(const ClassName: String): IDispatch;
+
+}
+
+procedure SIRegister_ComObj(cl: TPSPascalCompiler);
+
+implementation
+
+procedure SIRegister_ComObj(cl: TPSPascalCompiler);
+begin
+ cl.AddDelphiFunction('function CreateOleObject(const ClassName: String): IDispatch;');
+ cl.AddDelphiFunction('function GetActiveOleObject(const ClassName: String): IDispatch;');
+end;
+
+end.
diff --git a/branches/script-component/Units/PascalScript/uPSC_controls.pas b/branches/script-component/Units/PascalScript/uPSC_controls.pas
new file mode 100644
index 0000000..f37d43c
--- /dev/null
+++ b/branches/script-component/Units/PascalScript/uPSC_controls.pas
@@ -0,0 +1,236 @@
+{ Compiletime Controls support }
+unit uPSC_controls;
+{$I PascalScript.inc}
+interface
+uses
+ uPSCompiler, uPSUtils;
+
+{
+ Will register files from:
+ Controls
+
+ Register the STD, Classes (at least the types&consts) and Graphics libraries first
+
+}
+
+procedure SIRegister_Controls_TypesAndConsts(Cl: TPSPascalCompiler);
+
+procedure SIRegisterTControl(Cl: TPSPascalCompiler);
+procedure SIRegisterTWinControl(Cl: TPSPascalCompiler);
+procedure SIRegisterTGraphicControl(cl: TPSPascalCompiler);
+procedure SIRegisterTCustomControl(cl: TPSPascalCompiler);
+procedure SIRegisterTDragObject(cl: TPSPascalCompiler);
+
+procedure SIRegister_Controls(Cl: TPSPascalCompiler);
+
+
+implementation
+
+procedure SIRegisterTControl(Cl: TPSPascalCompiler);
+begin
+ with Cl.AddClassN(cl.FindClass('TComponent'), 'TCONTROL') do
+ begin
+ RegisterMethod('constructor Create(AOwner: TComponent);');
+ RegisterMethod('procedure BringToFront;');
+ RegisterMethod('procedure Hide;');
+ RegisterMethod('procedure Invalidate;virtual;');
+ RegisterMethod('procedure refresh;');
+ RegisterMethod('procedure Repaint;virtual;');
+ RegisterMethod('procedure SendToBack;');
+ RegisterMethod('procedure Show;');
+ RegisterMethod('procedure Update;virtual;');
+ RegisterMethod('procedure SetBounds(x,y,w,h: Integer);virtual;');
+ RegisterProperty('Left', 'Integer', iptRW);
+ RegisterProperty('Top', 'Integer', iptRW);
+ RegisterProperty('Width', 'Integer', iptRW);
+ RegisterProperty('Height', 'Integer', iptRW);
+ RegisterProperty('Hint', 'String', iptRW);
+ RegisterProperty('Align', 'TAlign', iptRW);
+ RegisterProperty('ClientHeight', 'Longint', iptRW);
+ RegisterProperty('ClientWidth', 'Longint', iptRW);
+ RegisterProperty('ShowHint', 'Boolean', iptRW);
+ RegisterProperty('Visible', 'Boolean', iptRW);
+ RegisterProperty('ENABLED', 'BOOLEAN', iptrw);
+ RegisterProperty('CURSOR', 'TCURSOR', iptrw);
+
+ {$IFNDEF PS_MINIVCL}
+ RegisterMethod('function Dragging: Boolean;');
+ RegisterMethod('function HasParent: Boolean');
+ RegisterMethod('procedure BEGINDRAG(IMMEDIATE:BOOLEAN)');
+ RegisterMethod('function CLIENTTOSCREEN(POINT:TPOINT):TPOINT');
+ RegisterMethod('procedure ENDDRAG(DROP:BOOLEAN)');
+ {$IFNDEF CLX}
+ RegisterMethod('function GETTEXTBUF(BUFFER:PCHAR;BUFSIZE:INTEGER):INTEGER');
+ RegisterMethod('function GETTEXTLEN:INTEGER');
+ RegisterMethod('procedure SETTEXTBUF(BUFFER:PCHAR)');
+ RegisterMethod('function PERFORM(MSG:CARDINAL;WPARAM,LPARAM:LONGINT):LONGINT');
+ {$ENDIF}
+ RegisterMethod('function SCREENTOCLIENT(POINT:TPOINT):TPOINT');
+ {$ENDIF}
+ end;
+end;
+
+procedure SIRegisterTWinControl(Cl: TPSPascalCompiler); // requires TControl
+begin
+ with Cl.AddClassN(cl.FindClass('TControl'), 'TWINCONTROL') do
+ begin
+
+ with Cl.FindClass('TControl') do
+ begin
+ RegisterProperty('Parent', 'TWinControl', iptRW);
+ end;
+
+ {$IFNDEF CLX}
+ RegisterProperty('Handle', 'Longint', iptR);
+ {$ENDIF}
+ RegisterProperty('Showing', 'Boolean', iptR);
+ RegisterProperty('TabOrder', 'Integer', iptRW);
+ RegisterProperty('TabStop', 'Boolean', iptRW);
+ RegisterMethod('function CANFOCUS:BOOLEAN');
+ RegisterMethod('function FOCUSED:BOOLEAN');
+ RegisterProperty('CONTROLS', 'TCONTROL INTEGER', iptr);
+ RegisterProperty('CONTROLCOUNT', 'INTEGER', iptr);
+
+ {$IFNDEF PS_MINIVCL}
+ RegisterMethod('function HandleAllocated: Boolean;');
+ RegisterMethod('procedure HandleNeeded;');
+ RegisterMethod('procedure EnableAlign;');
+ RegisterMethod('procedure RemoveControl(AControl: TControl);');
+ RegisterMethod('procedure InsertControl(AControl: TControl);');
+ RegisterMethod('procedure Realign;');
+ RegisterMethod('procedure ScaleBy(M, D: Integer);');
+ RegisterMethod('procedure ScrollBy(DeltaX, DeltaY: Integer);');
+ RegisterMethod('procedure SetFocus; virtual;');
+ {$IFNDEF CLX}
+ RegisterMethod('procedure PAINTTO(DC:Longint;X,Y:INTEGER)');
+ {$ENDIF}
+
+ RegisterMethod('function CONTAINSCONTROL(CONTROL:TCONTROL):BOOLEAN');
+ RegisterMethod('procedure DISABLEALIGN');
+ RegisterMethod('procedure UPDATECONTROLSTATE');
+
+ RegisterProperty('BRUSH', 'TBRUSH', iptr);
+ RegisterProperty('HELPCONTEXT', 'LONGINT', iptrw);
+ {$ENDIF}
+ end;
+end;
+procedure SIRegisterTGraphicControl(cl: TPSPascalCompiler); // requires TControl
+begin
+ Cl.AddClassN(cl.FindClass('TControl'), 'TGRAPHICCONTROL');
+end;
+
+procedure SIRegisterTCustomControl(cl: TPSPascalCompiler); // requires TWinControl
+begin
+ Cl.AddClassN(cl.FindClass('TWinControl'), 'TCUSTOMCONTROL');
+end;
+
+procedure SIRegister_Controls_TypesAndConsts(Cl: TPSPascalCompiler);
+begin
+{$IFNDEF FPC}
+ Cl.addTypeS('TEShiftState','(ssShift, ssAlt, ssCtrl, ssLeft, ssRight, ssMiddle, ssDouble)');
+ {$ELSE}
+ Cl.addTypeS('TEShiftState','(ssShift, ssAlt, ssCtrl, ssLeft, ssRight, ssMiddle, ssDouble,' +
+ 'ssMeta, ssSuper, ssHyper, ssAltGr, ssCaps, ssNum,ssScroll,ssTriple,ssQuad)');
+ {$ENDIF}
+ Cl.addTypeS('TShiftState','set of TEShiftState');
+ cl.AddTypeS('TMouseButton', '(mbLeft, mbRight, mbMiddle)');
+ cl.AddTypeS('TDragMode', '(dmManual, dmAutomatic)');
+ cl.AddTypeS('TDragState', '(dsDragEnter, dsDragLeave, dsDragMove)');
+ cl.AddTypeS('TDragKind', '(dkDrag, dkDock)');
+ cl.AddTypeS('TMouseEvent', 'procedure (Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);');
+ cl.AddTypeS('TMouseMoveEvent', 'procedure(Sender: TObject; Shift: TShiftState; X, Y: Integer);');
+ cl.AddTypeS('TKeyEvent', 'procedure (Sender: TObject; var Key: Word; Shift: TShiftState);');
+ cl.AddTypeS('TKeyPressEvent', 'procedure(Sender: TObject; var Key: Char);');
+ cl.AddTypeS('TDragOverEvent', 'procedure(Sender, Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean)');
+ cl.AddTypeS('TDragDropEvent', 'procedure(Sender, Source: TObject;X, Y: Integer)');
+ cl.AddTypeS('HWND', 'Longint');
+
+ cl.AddTypeS('TEndDragEvent', 'procedure(Sender, Target: TObject; X, Y: Integer)');
+
+ cl.addTypeS('TAlign', '(alNone, alTop, alBottom, alLeft, alRight, alClient)');
+
+ cl.addTypeS('TAnchorKind', '(akTop, akLeft, akRight, akBottom)');
+ cl.addTypeS('TAnchors','set of TAnchorKind');
+ cl.AddTypeS('TModalResult', 'Integer');
+ cl.AddTypeS('TCursor', 'Integer');
+ cl.AddTypeS('TPoint', 'record x,y: Longint; end;');
+
+ cl.AddConstantN('mrNone', 'Integer').Value.ts32 := 0;
+ cl.AddConstantN('mrOk', 'Integer').Value.ts32 := 1;
+ cl.AddConstantN('mrCancel', 'Integer').Value.ts32 := 2;
+ cl.AddConstantN('mrAbort', 'Integer').Value.ts32 := 3;
+ cl.AddConstantN('mrRetry', 'Integer').Value.ts32 := 4;
+ cl.AddConstantN('mrIgnore', 'Integer').Value.ts32 := 5;
+ cl.AddConstantN('mrYes', 'Integer').Value.ts32 := 6;
+ cl.AddConstantN('mrNo', 'Integer').Value.ts32 := 7;
+ cl.AddConstantN('mrAll', 'Integer').Value.ts32 := 8;
+ cl.AddConstantN('mrNoToAll', 'Integer').Value.ts32 := 9;
+ cl.AddConstantN('mrYesToAll', 'Integer').Value.ts32 := 10;
+ cl.AddConstantN('crDefault', 'Integer').Value.ts32 := 0;
+ cl.AddConstantN('crNone', 'Integer').Value.ts32 := -1;
+ cl.AddConstantN('crArrow', 'Integer').Value.ts32 := -2;
+ cl.AddConstantN('crCross', 'Integer').Value.ts32 := -3;
+ cl.AddConstantN('crIBeam', 'Integer').Value.ts32 := -4;
+ cl.AddConstantN('crSizeNESW', 'Integer').Value.ts32 := -6;
+ cl.AddConstantN('crSizeNS', 'Integer').Value.ts32 := -7;
+ cl.AddConstantN('crSizeNWSE', 'Integer').Value.ts32 := -8;
+ cl.AddConstantN('crSizeWE', 'Integer').Value.ts32 := -9;
+ cl.AddConstantN('crUpArrow', 'Integer').Value.ts32 := -10;
+ cl.AddConstantN('crHourGlass', 'Integer').Value.ts32 := -11;
+ cl.AddConstantN('crDrag', 'Integer').Value.ts32 := -12;
+ cl.AddConstantN('crNoDrop', 'Integer').Value.ts32 := -13;
+ cl.AddConstantN('crHSplit', 'Integer').Value.ts32 := -14;
+ cl.AddConstantN('crVSplit', 'Integer').Value.ts32 := -15;
+ cl.AddConstantN('crMultiDrag', 'Integer').Value.ts32 := -16;
+ cl.AddConstantN('crSQLWait', 'Integer').Value.ts32 := -17;
+ cl.AddConstantN('crNo', 'Integer').Value.ts32 := -18;
+ cl.AddConstantN('crAppStart', 'Integer').Value.ts32 := -19;
+ cl.AddConstantN('crHelp', 'Integer').Value.ts32 := -20;
+{$IFDEF DELPHI3UP}
+ cl.AddConstantN('crHandPoint', 'Integer').Value.ts32 := -21;
+{$ENDIF}
+{$IFDEF DELPHI4UP}
+ cl.AddConstantN('crSizeAll', 'Integer').Value.ts32 := -22;
+{$ENDIF}
+end;
+
+procedure SIRegisterTDragObject(cl: TPSPascalCompiler);
+begin
+ with CL.AddClassN(CL.FindClass('TObject'),'TDragObject') do
+ begin
+{$IFNDEF PS_MINIVCL}
+{$IFDEF DELPHI4UP}
+ RegisterMethod('Procedure Assign( Source : TDragObject)');
+{$ENDIF}
+{$IFNDEF FPC}
+ RegisterMethod('Function GetName : String');
+ RegisterMethod('Function Instance : Longint');
+{$ENDIF}
+ RegisterMethod('Procedure HideDragImage');
+ RegisterMethod('Procedure ShowDragImage');
+{$IFDEF DELPHI4UP}
+ RegisterProperty('Cancelling', 'Boolean', iptrw);
+ RegisterProperty('DragHandle', 'Longint', iptrw);
+ RegisterProperty('DragPos', 'TPoint', iptrw);
+ RegisterProperty('DragTargetPos', 'TPoint', iptrw);
+ RegisterProperty('MouseDeltaX', 'Double', iptr);
+ RegisterProperty('MouseDeltaY', 'Double', iptr);
+{$ENDIF}
+{$ENDIF}
+ end;
+ Cl.AddTypeS('TStartDragEvent', 'procedure (Sender: TObject; var DragObject: TDragObject)');
+end;
+
+procedure SIRegister_Controls(Cl: TPSPascalCompiler);
+begin
+ SIRegister_Controls_TypesAndConsts(cl);
+ SIRegisterTDragObject(cl);
+ SIRegisterTControl(Cl);
+ SIRegisterTWinControl(Cl);
+ SIRegisterTGraphicControl(cl);
+ SIRegisterTCustomControl(cl);
+end;
+
+// PS_MINIVCL changes by Martijn Laan (mlaan at wintax _dot_ nl)
+
+end.
diff --git a/branches/script-component/Units/PascalScript/uPSC_dateutils.pas b/branches/script-component/Units/PascalScript/uPSC_dateutils.pas
new file mode 100644
index 0000000..0adf504
--- /dev/null
+++ b/branches/script-component/Units/PascalScript/uPSC_dateutils.pas
@@ -0,0 +1,34 @@
+{ Compile time Date Time library }
+unit uPSC_dateutils;
+
+interface
+uses
+ SysUtils, uPSCompiler, uPSUtils;
+
+
+procedure RegisterDateTimeLibrary_C(S: TPSPascalCompiler);
+
+implementation
+
+procedure RegisterDatetimeLibrary_C(S: TPSPascalCompiler);
+begin
+ s.AddType('TDateTime', btDouble).ExportName := True;
+ s.AddDelphiFunction('function EncodeDate(Year, Month, Day: Word): TDateTime;');
+ s.AddDelphiFunction('function EncodeTime(Hour, Min, Sec, MSec: Word): TDateTime;');
+ s.AddDelphiFunction('function TryEncodeDate(Year, Month, Day: Word; var Date: TDateTime): Boolean;');
+ s.AddDelphiFunction('function TryEncodeTime(Hour, Min, Sec, MSec: Word; var Time: TDateTime): Boolean;');
+ s.AddDelphiFunction('procedure DecodeDate(const DateTime: TDateTime; var Year, Month, Day: Word);');
+ s.AddDelphiFunction('procedure DecodeTime(const DateTime: TDateTime; var Hour, Min, Sec, MSec: Word);');
+ s.AddDelphiFunction('function DayOfWeek(const DateTime: TDateTime): Word;');
+ s.AddDelphiFunction('function Date: TDateTime;');
+ s.AddDelphiFunction('function Time: TDateTime;');
+ s.AddDelphiFunction('function Now: TDateTime;');
+ s.AddDelphiFunction('function DateTimeToUnix(D: TDateTime): Int64;');
+ s.AddDelphiFunction('function UnixToDateTime(U: Int64): TDateTime;');
+
+ s.AddDelphiFunction('function DateToStr(D: TDateTime): String;');
+ s.AddDelphiFunction('function StrToDate(const s: String): TDateTime;');
+ s.AddDelphiFunction('function FormatDateTime(const fmt: String; D: TDateTime): String;');
+end;
+
+end.
diff --git a/branches/script-component/Units/PascalScript/uPSC_dll.pas b/branches/script-component/Units/PascalScript/uPSC_dll.pas
new file mode 100644
index 0000000..8eff0c7
--- /dev/null
+++ b/branches/script-component/Units/PascalScript/uPSC_dll.pas
@@ -0,0 +1,158 @@
+{ Compiletime DLL importing support }
+unit uPSC_dll;
+
+{$I PascalScript.inc}
+interface
+{
+
+ Function FindWindow(c1, c2: PChar): Cardinal; external 'FindWindow@user32.dll stdcall';
+
+}
+uses
+ uPSCompiler, uPSUtils;
+
+
+{$IFDEF DELPHI3UP }
+resourceString
+{$ELSE }
+const
+{$ENDIF }
+
+ RPS_Invalid_External = 'Invalid External';
+ RPS_InvalidCallingConvention = 'Invalid Calling Convention';
+
+
+
+function DllExternalProc(Sender: TPSPascalCompiler; Decl: TPSParametersDecl; const OriginalName, FExternal: tbtstring): TPSRegProc;
+type
+
+ TDllCallingConvention = (clRegister
+ , clPascal
+ , ClCdecl
+ , ClStdCall
+ );
+
+var
+ DefaultCC: TDllCallingConvention;
+
+procedure RegisterDll_Compiletime(cs: TPSPascalCompiler);
+
+implementation
+
+function rpos(ch: tbtchar; const s: tbtstring): Longint;
+var
+ i: Longint;
+begin
+ for i := length(s) downto 1 do
+ if s[i] = ch then begin Result := i; exit; end;
+ result := 0;
+end;
+
+function RemoveQuotes(s: tbtstring): tbtstring;
+begin
+ result := s;
+ if result = '' then exit;
+ if Result[1] = '"' then delete(result ,1,1);
+ if (Result <> '') and (Result[Length(result)] = '"') then delete(result, length(result), 1);
+end;
+
+function DllExternalProc(Sender: TPSPascalCompiler; Decl: TPSParametersDecl; const OriginalName, FExternal: tbtstring): TPSRegProc;
+var
+ FuncName,
+ Name,
+ FuncCC, s, s2: AnsiString;
+ CC: TDllCallingConvention;
+ DelayLoad, LoadWithAlteredSearchPath: Boolean;
+
+begin
+ Name := FastUpperCase(OriginalName);
+ DelayLoad := False;
+ LoadWithAlteredSearchPath := false;
+ FuncCC := FExternal;
+
+ if (pos(tbtChar('@'), FuncCC) = 0) then
+ begin
+ Sender.MakeError('', ecCustomError, tbtString(RPS_Invalid_External));
+ Result := nil;
+ exit;
+ end;
+ FuncName := copy(FuncCC, 1, rpos('@', FuncCC)-1)+#0;
+ delete(FuncCc, 1, length(FuncName));
+ if pos(tbtchar(' '), Funccc) <> 0 then
+ begin
+ if FuncCC[1] = '"' then
+ begin
+ Delete(FuncCC, 1, 1);
+ FuncName := RemoveQuotes(copy(FuncCC, 1, pos(tbtchar('"'), FuncCC)-1))+#0+FuncName;
+ Delete(FuncCC,1, pos(tbtchar('"'), FuncCC));
+ if (FuncCC <> '') and( FuncCC[1] = ' ') then delete(FuncCC,1,1);
+ end else
+ begin
+ FuncName := copy(FuncCc, 1, pos(tbtchar(' '),FuncCC)-1)+#0+FuncName;
+ Delete(FuncCC, 1, pos(tbtchar(' '), FuncCC));
+ end;
+ if pos(tbtchar(' '), FuncCC) > 0 then
+ begin
+ s := Copy(FuncCC, pos(tbtchar(' '), Funccc)+1, MaxInt);
+ FuncCC := FastUpperCase(Copy(FuncCC, 1, pos(tbtchar(' '), FuncCC)-1));
+ Delete(FuncCC, pos(tbtchar(' '), Funccc), MaxInt);
+ repeat
+ if pos(tbtchar(' '), s) > 0 then begin
+ s2 := Copy(s, 1, pos(tbtchar(' '), s)-1);
+ delete(s, 1, pos(tbtchar(' '), s));
+ end else begin
+ s2 := s;
+ s := '';
+ end;
+ if FastUppercase(s2) = 'DELAYLOAD' then
+ DelayLoad := True
+ {$IFNDEF LINUX}
+ else
+ if FastUppercase(s2) = 'LOADWITHALTEREDSEARCHPATH' then
+ LoadWithAlteredSearchPath := True
+ {$ENDIF}
+ else
+ begin
+ Sender.MakeError('', ecCustomError, 'Invalid External');
+ Result := nil;
+ exit;
+ end;
+ until s = '';
+
+ end else
+ FuncCC := FastUpperCase(FuncCC);
+ if FuncCC = 'STDCALL' then cc := ClStdCall else
+ if FuncCC = 'CDECL' then cc := ClCdecl else
+ if FuncCC = 'REGISTER' then cc := clRegister else
+ if FuncCC = 'PASCAL' then cc := clPascal else
+ begin
+ Sender.MakeError('', ecCustomError, tbtstring(RPS_InvalidCallingConvention));
+ Result := nil;
+ exit;
+ end;
+ end else
+ begin
+ FuncName := RemoveQuotes(FuncCC)+#0+FuncName;
+ FuncCC := '';
+ cc := DefaultCC;
+ end;
+ FuncName := 'dll:'+FuncName+tbtchar(cc)+tbtchar(bytebool(DelayLoad)) +tbtchar(bytebool(LoadWithAlteredSearchPath))+ declToBits(Decl);
+ Result := TPSRegProc.Create;
+ Result.ImportDecl := FuncName;
+ Result.Decl.Assign(Decl);
+ Result.Name := Name;
+ Result.OrgName := OriginalName;
+ Result.ExportName := False;
+end;
+
+procedure RegisterDll_Compiletime(cs: TPSPascalCompiler);
+begin
+ cs.OnExternalProc := DllExternalProc;
+ cs.AddFunction('procedure UnloadDll(s: string)');
+ cs.AddFunction('function DLLGetLastError: Longint');
+end;
+
+begin
+ DefaultCc := clRegister;
+end.
+
diff --git a/branches/script-component/Units/PascalScript/uPSC_extctrls.pas b/branches/script-component/Units/PascalScript/uPSC_extctrls.pas
new file mode 100644
index 0000000..16c2102
--- /dev/null
+++ b/branches/script-component/Units/PascalScript/uPSC_extctrls.pas
@@ -0,0 +1,327 @@
+{ Compiletime Extctrls support }
+unit uPSC_extctrls;
+
+{$I PascalScript.inc}
+interface
+uses
+ uPSCompiler, uPSUtils;
+
+(*
+ Will register files from:
+ ExtCtrls
+
+Requires:
+ STD, classes, controls, graphics {$IFNDEF PS_MINIVCL}, stdctrls {$ENDIF}
+*)
+
+procedure SIRegister_ExtCtrls_TypesAndConsts(cl: TPSPascalCompiler);
+
+procedure SIRegisterTSHAPE(Cl: TPSPascalCompiler);
+procedure SIRegisterTIMAGE(Cl: TPSPascalCompiler);
+procedure SIRegisterTPAINTBOX(Cl: TPSPascalCompiler);
+procedure SIRegisterTBEVEL(Cl: TPSPascalCompiler);
+procedure SIRegisterTTIMER(Cl: TPSPascalCompiler);
+procedure SIRegisterTCUSTOMPANEL(Cl: TPSPascalCompiler);
+procedure SIRegisterTPANEL(Cl: TPSPascalCompiler);
+{$IFNDEF CLX}
+procedure SIRegisterTPAGE(Cl: TPSPascalCompiler);
+procedure SIRegisterTNOTEBOOK(Cl: TPSPascalCompiler);
+procedure SIRegisterTHEADER(Cl: TPSPascalCompiler);
+{$ENDIF}
+procedure SIRegisterTCUSTOMRADIOGROUP(Cl: TPSPascalCompiler);
+procedure SIRegisterTRADIOGROUP(Cl: TPSPascalCompiler);
+
+procedure SIRegister_ExtCtrls(cl: TPSPascalCompiler);
+
+implementation
+procedure SIRegisterTSHAPE(Cl: TPSPascalCompiler);
+begin
+ with Cl.AddClassN(cl.FindClass('TGRAPHICCONTROL'), 'TSHAPE') do
+ begin
+ RegisterProperty('BRUSH', 'TBRUSH', iptrw);
+ RegisterProperty('PEN', 'TPEN', iptrw);
+ RegisterProperty('SHAPE', 'TSHAPETYPE', iptrw);
+
+ {$IFNDEF PS_MINIVCL}
+ RegisterMethod('procedure STYLECHANGED(SENDER:TOBJECT)');
+ RegisterProperty('DRAGCURSOR', 'Longint', iptrw);
+ RegisterProperty('DRAGMODE', 'TDragMode', iptrw);
+ RegisterProperty('PARENTSHOWHINT', 'Boolean', iptrw);
+ RegisterProperty('ONDRAGDROP', 'TDragDropEvent', iptrw);
+ RegisterProperty('ONDRAGOVER', 'TDragOverEvent', iptrw);
+ RegisterProperty('ONENDDRAG', 'TEndDragEvent', iptrw);
+ RegisterProperty('ONMOUSEDOWN', 'TMouseEvent', iptrw);
+ RegisterProperty('ONMOUSEMOVE', 'TMouseMoveEvent', iptrw);
+ RegisterProperty('ONMOUSEUP', 'TMouseEvent', iptrw);
+ RegisterProperty('ONSTARTDRAG', 'TStartDragEvent', iptrw);
+ {$ENDIF}
+ end;
+end;
+
+procedure SIRegisterTIMAGE(Cl: TPSPascalCompiler);
+begin
+ with Cl.AddClassN(cl.FindClass('TGRAPHICCONTROL'), 'TIMAGE') do
+ begin
+ RegisterProperty('CANVAS', 'TCANVAS', iptr);
+ RegisterProperty('AUTOSIZE', 'BOOLEAN', iptrw);
+ RegisterProperty('CENTER', 'BOOLEAN', iptrw);
+ RegisterProperty('PICTURE', 'TPICTURE', iptrw);
+ RegisterProperty('STRETCH', 'BOOLEAN', iptrw);
+ RegisterProperty('ONCLICK', 'TNotifyEvent', iptrw);
+ RegisterProperty('ONDBLCLICK', 'TNotifyEvent', iptrw);
+
+ {$IFNDEF PS_MINIVCL}
+ RegisterProperty('DRAGCURSOR', 'Longint', iptrw);
+ RegisterProperty('DRAGMODE', 'TDragMode', iptrw);
+ RegisterProperty('PARENTSHOWHINT', 'Boolean', iptrw);
+ RegisterProperty('POPUPMENU', 'TPopupMenu', iptrw);
+ RegisterProperty('ONDRAGDROP', 'TDragDropEvent', iptrw);
+ RegisterProperty('ONDRAGOVER', 'TDragOverEvent', iptrw);
+ RegisterProperty('ONENDDRAG', 'TEndDragEvent', iptrw);
+ RegisterProperty('ONMOUSEDOWN', 'TMouseEvent', iptrw);
+ RegisterProperty('ONMOUSEMOVE', 'TMouseMoveEvent', iptrw);
+ RegisterProperty('ONMOUSEUP', 'TMouseEvent', iptrw);
+ RegisterProperty('ONSTARTDRAG', 'TStartDragEvent', iptrw);
+ {$ENDIF}
+ end;
+end;
+
+procedure SIRegisterTPAINTBOX(Cl: TPSPascalCompiler);
+begin
+ with Cl.AddClassN(cl.FindClass('TGRAPHICCONTROL'), 'TPAINTBOX') do
+ begin
+ RegisterProperty('CANVAS', 'TCanvas', iptr);
+ RegisterProperty('COLOR', 'TColor', iptrw);
+ RegisterProperty('FONT', 'TFont', iptrw);
+ RegisterProperty('PARENTCOLOR', 'Boolean', iptrw);
+ RegisterProperty('PARENTFONT', 'Boolean', iptrw);
+ RegisterProperty('ONCLICK', 'TNotifyEvent', iptrw);
+ RegisterProperty('ONDBLCLICK', 'TNotifyEvent', iptrw);
+ RegisterProperty('ONPAINT', 'TNOTIFYEVENT', iptrw);
+
+ {$IFNDEF PS_MINIVCL}
+ RegisterProperty('DRAGCURSOR', 'Longint', iptrw);
+ RegisterProperty('DRAGMODE', 'TDragMode', iptrw);
+ RegisterProperty('PARENTSHOWHINT', 'Boolean', iptrw);
+ RegisterProperty('POPUPMENU', 'TPopupMenu', iptrw);
+ RegisterProperty('ONDRAGDROP', 'TDragDropEvent', iptrw);
+ RegisterProperty('ONDRAGOVER', 'TDragOverEvent', iptrw);
+ RegisterProperty('ONENDDRAG', 'TEndDragEvent', iptrw);
+ RegisterProperty('ONMOUSEDOWN', 'TMouseEvent', iptrw);
+ RegisterProperty('ONMOUSEMOVE', 'TMouseMoveEvent', iptrw);
+ RegisterProperty('ONMOUSEUP', 'TMouseEvent', iptrw);
+ RegisterProperty('ONSTARTDRAG', 'TStartDragEvent', iptrw);
+ {$ENDIF}
+ end;
+end;
+
+procedure SIRegisterTBEVEL(Cl: TPSPascalCompiler);
+begin
+ with Cl.AddClassN(cl.FindClass('TGRAPHICCONTROL'), 'TBEVEL') do
+ begin
+ RegisterProperty('SHAPE', 'TBEVELSHAPE', iptrw);
+ RegisterProperty('STYLE', 'TBEVELSTYLE', iptrw);
+
+ {$IFNDEF PS_MINIVCL}
+ RegisterProperty('PARENTSHOWHINT', 'Boolean', iptrw);
+ {$ENDIF}
+ end;
+end;
+
+procedure SIRegisterTTIMER(Cl: TPSPascalCompiler);
+begin
+ with Cl.AddClassN(cl.FindClass('TCOMPONENT'), 'TTIMER') do
+ begin
+ RegisterProperty('ENABLED', 'BOOLEAN', iptrw);
+ RegisterProperty('INTERVAL', 'CARDINAL', iptrw);
+ RegisterProperty('ONTIMER', 'TNOTIFYEVENT', iptrw);
+ end;
+end;
+
+procedure SIRegisterTCUSTOMPANEL(Cl: TPSPascalCompiler);
+begin
+ Cl.AddClassN(cl.FindClass('TCUSTOMCONTROL'), 'TCUSTOMPANEL');
+end;
+
+procedure SIRegisterTPANEL(Cl: TPSPascalCompiler);
+begin
+ with Cl.AddClassN(cl.FindClass('TCUSTOMPANEL'), 'TPANEL') do
+ begin
+ RegisterProperty('ALIGNMENT', 'TAlignment', iptrw);
+ RegisterProperty('BEVELINNER', 'TPanelBevel', iptrw);
+ RegisterProperty('BEVELOUTER', 'TPanelBevel', iptrw);
+ RegisterProperty('BEVELWIDTH', 'TBevelWidth', iptrw);
+ RegisterProperty('BORDERWIDTH', 'TBorderWidth', iptrw);
+ RegisterProperty('BORDERSTYLE', 'TBorderStyle', iptrw);
+ RegisterProperty('CAPTION', 'String', iptrw);
+ RegisterProperty('COLOR', 'TColor', iptrw);
+ RegisterProperty('FONT', 'TFont', iptrw);
+ RegisterProperty('PARENTCOLOR', 'Boolean', iptrw);
+ RegisterProperty('PARENTFONT', 'Boolean', iptrw);
+ RegisterProperty('ONCLICK', 'TNotifyEvent', iptrw);
+ RegisterProperty('ONDBLCLICK', 'TNotifyEvent', iptrw);
+ RegisterProperty('ONENTER', 'TNotifyEvent', iptrw);
+ RegisterProperty('ONEXIT', 'TNotifyEvent', iptrw);
+
+ {$IFNDEF PS_MINIVCL}
+ RegisterProperty('DRAGCURSOR', 'Longint', iptrw);
+ RegisterProperty('DRAGMODE', 'TDragMode', iptrw);
+ RegisterProperty('CTL3D', 'Boolean', iptrw);
+ RegisterProperty('LOCKED', 'Boolean', iptrw);
+ RegisterProperty('PARENTCTL3D', 'Boolean', iptrw);
+ RegisterProperty('PARENTSHOWHINT', 'Boolean', iptrw);
+ RegisterProperty('POPUPMENU', 'TPopupMenu', iptrw);
+ RegisterProperty('ONDRAGDROP', 'TDragDropEvent', iptrw);
+ RegisterProperty('ONDRAGOVER', 'TDragOverEvent', iptrw);
+ RegisterProperty('ONENDDRAG', 'TEndDragEvent', iptrw);
+ RegisterProperty('ONMOUSEDOWN', 'TMouseEvent', iptrw);
+ RegisterProperty('ONMOUSEMOVE', 'TMouseMoveEvent', iptrw);
+ RegisterProperty('ONMOUSEUP', 'TMouseEvent', iptrw);
+ RegisterProperty('ONRESIZE', 'TNotifyEvent', iptrw);
+ RegisterProperty('ONSTARTDRAG', 'TStartDragEvent', iptrw);
+ {$ENDIF}
+ end;
+end;
+{$IFNDEF CLX}
+procedure SIRegisterTPAGE(Cl: TPSPascalCompiler);
+begin
+ with Cl.AddClassN(cl.FindClass('TCUSTOMCONTROL'), 'TPAGE') do
+ begin
+ RegisterProperty('CAPTION', 'String', iptrw);
+ end;
+end;
+procedure SIRegisterTNOTEBOOK(Cl: TPSPascalCompiler);
+begin
+ with Cl.AddClassN(cl.FindClass('TCUSTOMCONTROL'), 'TNOTEBOOK') do
+ begin
+ RegisterProperty('ACTIVEPAGE', 'String', iptrw);
+ RegisterProperty('COLOR', 'TColor', iptrw);
+ RegisterProperty('FONT', 'TFont', iptrw);
+ RegisterProperty('PAGEINDEX', 'INTEGER', iptrw);
+ RegisterProperty('PAGES', 'TSTRINGS', iptrw);
+ RegisterProperty('PARENTCOLOR', 'Boolean', iptrw);
+ RegisterProperty('PARENTFONT', 'Boolean', iptrw);
+ RegisterProperty('ONCLICK', 'TNotifyEvent', iptrw);
+ RegisterProperty('ONDBLCLICK', 'TNotifyEvent', iptrw);
+ RegisterProperty('ONENTER', 'TNotifyEvent', iptrw);
+ RegisterProperty('ONEXIT', 'TNotifyEvent', iptrw);
+ RegisterProperty('ONPAGECHANGED', 'TNOTIFYEVENT', iptrw);
+
+ {$IFNDEF PS_MINIVCL}
+ RegisterProperty('CTL3D', 'Boolean', iptrw);
+ RegisterProperty('DRAGCURSOR', 'Longint', iptrw);
+ RegisterProperty('DRAGMODE', 'TDragMode', iptrw);
+ RegisterProperty('PARENTCTL3D', 'Boolean', iptrw);
+ RegisterProperty('PARENTSHOWHINT', 'Boolean', iptrw);
+ RegisterProperty('POPUPMENU', 'TPopupMenu', iptrw);
+ RegisterProperty('ONDRAGDROP', 'TDragDropEvent', iptrw);
+ RegisterProperty('ONDRAGOVER', 'TDragOverEvent', iptrw);
+ RegisterProperty('ONENDDRAG', 'TEndDragEvent', iptrw);
+ RegisterProperty('ONMOUSEDOWN', 'TMouseEvent', iptrw);
+ RegisterProperty('ONMOUSEMOVE', 'TMouseMoveEvent', iptrw);
+ RegisterProperty('ONMOUSEUP', 'TMouseEvent', iptrw);
+ RegisterProperty('ONSTARTDRAG', 'TStartDragEvent', iptrw);
+ {$ENDIF}
+ end;
+end;
+
+procedure SIRegisterTHEADER(Cl: TPSPascalCompiler);
+begin
+ with Cl.AddClassN(cl.FindClass('TCUSTOMCONTROL'), 'THEADER') do
+ begin
+ RegisterProperty('SECTIONWIDTH', 'INTEGER INTEGER', iptrw);
+ RegisterProperty('ALLOWRESIZE', 'BOOLEAN', iptrw);
+ RegisterProperty('BORDERSTYLE', 'TBORDERSTYLE', iptrw);
+ RegisterProperty('FONT', 'TFont', iptrw);
+ RegisterProperty('PARENTFONT', 'Boolean', iptrw);
+ RegisterProperty('SECTIONS', 'TSTRINGS', iptrw);
+ RegisterProperty('ONSIZING', 'TSECTIONEVENT', iptrw);
+ RegisterProperty('ONSIZED', 'TSECTIONEVENT', iptrw);
+
+ {$IFNDEF PS_MINIVCL}
+ RegisterProperty('PARENTSHOWHINT', 'Boolean', iptrw);
+ RegisterProperty('POPUPMENU', 'TPopupMenu', iptrw);
+ {$ENDIF}
+ end;
+end;
+{$ENDIF}
+
+procedure SIRegisterTCUSTOMRADIOGROUP(Cl: TPSPascalCompiler);
+begin
+ Cl.AddClassN(cl.FindClass('TCUSTOMGROUPBOX'), 'TCUSTOMRADIOGROUP');
+end;
+
+procedure SIRegisterTRADIOGROUP(Cl: TPSPascalCompiler);
+begin
+ with Cl.AddClassN(cl.FindClass('TCUSTOMRADIOGROUP'), 'TRADIOGROUP') do
+ begin
+ RegisterProperty('CAPTION', 'String', iptrw);
+ RegisterProperty('COLOR', 'TColor', iptrw);
+ RegisterProperty('COLUMNS', 'Integer', iptrw);
+ RegisterProperty('FONT', 'TFont', iptrw);
+ RegisterProperty('ITEMINDEX', 'Integer', iptrw);
+ RegisterProperty('ITEMS', 'TStrings', iptrw);
+ RegisterProperty('PARENTCOLOR', 'Boolean', iptrw);
+ RegisterProperty('PARENTFONT', 'Boolean', iptrw);
+ RegisterProperty('ONCLICK', 'TNotifyEvent', iptrw);
+ RegisterProperty('ONENTER', 'TNotifyEvent', iptrw);
+ RegisterProperty('ONEXIT', 'TNotifyEvent', iptrw);
+
+ {$IFNDEF PS_MINIVCL}
+ RegisterProperty('CTL3D', 'Boolean', iptrw);
+ RegisterProperty('DRAGCURSOR', 'Longint', iptrw);
+ RegisterProperty('DRAGMODE', 'TDragMode', iptrw);
+ RegisterProperty('PARENTCTL3D', 'Boolean', iptrw);
+ RegisterProperty('PARENTSHOWHINT', 'Boolean', iptrw);
+ RegisterProperty('POPUPMENU', 'TPopupMenu', iptrw);
+ RegisterProperty('ONDRAGDROP', 'TDragDropEvent', iptrw);
+ RegisterProperty('ONDRAGOVER', 'TDragOverEvent', iptrw);
+ RegisterProperty('ONENDDRAG', 'TEndDragEvent', iptrw);
+ RegisterProperty('ONSTARTDRAG', 'TStartDragEvent', iptrw);
+ {$ENDIF}
+ end;
+end;
+
+procedure SIRegister_ExtCtrls_TypesAndConsts(cl: TPSPascalCompiler);
+begin
+ cl.AddTypeS('TShapeType', '(stRectangle, stSquare, stRoundRect, stRoundSquare, stEllipse, stCircle)');
+ cl.AddTypeS('TBevelStyle', '(bsLowered, bsRaised)');
+ cl.AddTypeS('TBevelShape', '(bsBox, bsFrame, bsTopLine, bsBottomLine, bsLeftLine, bsRightLine,bsSpacer)');
+ cl.AddTypeS('TPanelBevel', '(bvNone, bvLowered, bvRaised,bvSpace)');
+ cl.AddTypeS('TBevelWidth', 'Longint');
+ cl.AddTypeS('TBorderWidth', 'Longint');
+ cl.AddTypeS('TSectionEvent', 'procedure(Sender: TObject; ASection, AWidth: Integer)');
+end;
+
+procedure SIRegister_ExtCtrls(cl: TPSPascalCompiler);
+begin
+ SIRegister_ExtCtrls_TypesAndConsts(cl);
+
+ {$IFNDEF PS_MINIVCL}
+ SIRegisterTSHAPE(Cl);
+ SIRegisterTIMAGE(Cl);
+ SIRegisterTPAINTBOX(Cl);
+ {$ENDIF}
+ SIRegisterTBEVEL(Cl);
+ {$IFNDEF PS_MINIVCL}
+ SIRegisterTTIMER(Cl);
+ {$ENDIF}
+ SIRegisterTCUSTOMPANEL(Cl);
+ SIRegisterTPANEL(Cl);
+ {$IFNDEF PS_MINIVCL}
+ {$IFNDEF CLX}
+ SIRegisterTPAGE(Cl);
+ SIRegisterTNOTEBOOK(Cl);
+ SIRegisterTHEADER(Cl);
+ {$ENDIF}
+ SIRegisterTCUSTOMRADIOGROUP(Cl);
+ SIRegisterTRADIOGROUP(Cl);
+ {$ENDIF}
+end;
+
+end.
+
+
+
+
+
diff --git a/branches/script-component/Units/PascalScript/uPSC_forms.pas b/branches/script-component/Units/PascalScript/uPSC_forms.pas
new file mode 100644
index 0000000..d115ebb
--- /dev/null
+++ b/branches/script-component/Units/PascalScript/uPSC_forms.pas
@@ -0,0 +1,271 @@
+{ Compiletime Forms support }
+unit uPSC_forms;
+{$I PascalScript.inc}
+
+interface
+uses
+ uPSCompiler, uPSUtils;
+
+procedure SIRegister_Forms_TypesAndConsts(Cl: TPSPascalCompiler);
+
+
+procedure SIRegisterTCONTROLSCROLLBAR(Cl: TPSPascalCompiler);
+procedure SIRegisterTSCROLLINGWINCONTROL(Cl: TPSPascalCompiler);
+procedure SIRegisterTSCROLLBOX(Cl: TPSPascalCompiler);
+procedure SIRegisterTFORM(Cl: TPSPascalCompiler);
+procedure SIRegisterTAPPLICATION(Cl: TPSPascalCompiler);
+
+procedure SIRegister_Forms(Cl: TPSPascalCompiler);
+
+implementation
+
+procedure SIRegisterTCONTROLSCROLLBAR(Cl: TPSPascalCompiler);
+begin
+ with Cl.AddClassN(cl.FindClass('TPERSISTENT'), 'TCONTROLSCROLLBAR') do
+ begin
+ RegisterProperty('KIND', 'TSCROLLBARKIND', iptr);
+ RegisterProperty('SCROLLPOS', 'INTEGER', iptr);
+ RegisterProperty('MARGIN', 'WORD', iptrw);
+ RegisterProperty('INCREMENT', 'TSCROLLBARINC', iptrw);
+ RegisterProperty('RANGE', 'INTEGER', iptrw);
+ RegisterProperty('POSITION', 'INTEGER', iptrw);
+ RegisterProperty('TRACKING', 'BOOLEAN', iptrw);
+ RegisterProperty('VISIBLE', 'BOOLEAN', iptrw);
+ end;
+end;
+
+procedure SIRegisterTSCROLLINGWINCONTROL(Cl: TPSPascalCompiler);
+begin
+ with Cl.AddClassN(cl.FindClass('TWINCONTROL'), 'TSCROLLINGWINCONTROL') do
+ begin
+ RegisterMethod('procedure SCROLLINVIEW(ACONTROL:TCONTROL)');
+ RegisterProperty('HORZSCROLLBAR', 'TCONTROLSCROLLBAR', iptrw);
+ RegisterProperty('VERTSCROLLBAR', 'TCONTROLSCROLLBAR', iptrw);
+ end;
+end;
+
+procedure SIRegisterTSCROLLBOX(Cl: TPSPascalCompiler);
+begin
+ with Cl.AddClassN(cl.FindClass('TSCROLLINGWINCONTROL'), 'TSCROLLBOX') do
+ begin
+ RegisterProperty('BORDERSTYLE', 'TBORDERSTYLE', iptrw);
+ RegisterProperty('COLOR', 'TCOLOR', iptrw);
+ RegisterProperty('FONT', 'TFONT', iptrw);
+ RegisterProperty('AUTOSCROLL', 'BOOLEAN', iptrw);
+ RegisterProperty('PARENTCOLOR', 'BOOLEAN', iptrw);
+ RegisterProperty('PARENTFONT', 'BOOLEAN', iptrw);
+ RegisterProperty('ONCLICK', 'TNOTIFYEVENT', iptrw);
+ RegisterProperty('ONDBLCLICK', 'TNOTIFYEVENT', iptrw);
+ RegisterProperty('ONENTER', 'TNOTIFYEVENT', iptrw);
+ RegisterProperty('ONEXIT', 'TNOTIFYEVENT', iptrw);
+
+ {$IFNDEF PS_MINIVCL}
+ RegisterProperty('ONRESIZE', 'TNOTIFYEVENT', iptrw);
+ RegisterProperty('DRAGCURSOR', 'TCURSOR', iptrw);
+ RegisterProperty('DRAGMODE', 'TDRAGMODE', iptrw);
+ RegisterProperty('PARENTSHOWHINT', 'BOOLEAN', iptrw);
+ RegisterProperty('POPUPMENU', 'TPOPUPMENU', iptrw);
+ RegisterProperty('CTL3D', 'BOOLEAN', iptrw);
+ RegisterProperty('PARENTCTL3D', 'BOOLEAN', iptrw);
+ RegisterProperty('ONDRAGDROP', 'TDRAGDROPEVENT', iptrw);
+ RegisterProperty('ONDRAGOVER', 'TDRAGOVEREVENT', iptrw);
+ RegisterProperty('ONENDDRAG', 'TENDDRAGEVENT', iptrw);
+ RegisterProperty('ONMOUSEDOWN', 'TMOUSEEVENT', iptrw);
+ RegisterProperty('ONMOUSEMOVE', 'TMOUSEMOVEEVENT', iptrw);
+ RegisterProperty('ONMOUSEUP', 'TMOUSEEVENT', iptrw);
+ {$ENDIF}
+ end;
+end;
+
+procedure SIRegisterTFORM(Cl: TPSPascalCompiler);
+begin
+ with Cl.AddClassN(cl.FindClass('TSCROLLINGWINCONTROL'), 'TFORM') do
+ begin
+ {$IFDEF DELPHI4UP}
+ RegisterMethod('constructor CREATENEW(AOWNER:TCOMPONENT; Dummy: Integer)');
+ {$ELSE}
+ RegisterMethod('constructor CREATENEW(AOWNER:TCOMPONENT)');
+ {$ENDIF}
+ RegisterMethod('procedure CLOSE');
+ RegisterMethod('procedure HIDE');
+ RegisterMethod('procedure SHOW');
+ RegisterMethod('function SHOWMODAL:INTEGER');
+ RegisterMethod('procedure RELEASE');
+ RegisterProperty('ACTIVE', 'BOOLEAN', iptr);
+ RegisterProperty('ACTIVECONTROL', 'TWINCONTROL', iptrw);
+ RegisterProperty('BORDERICONS', 'TBorderIcons', iptrw);
+ RegisterProperty('BORDERSTYLE', 'TFORMBORDERSTYLE', iptrw);
+ RegisterProperty('CAPTION', 'NativeString', iptrw);
+ RegisterProperty('AUTOSCROLL', 'BOOLEAN', iptrw);
+ RegisterProperty('COLOR', 'TCOLOR', iptrw);
+ RegisterProperty('FONT', 'TFONT', iptrw);
+ RegisterProperty('FORMSTYLE', 'TFORMSTYLE', iptrw);
+ RegisterProperty('KEYPREVIEW', 'BOOLEAN', iptrw);
+ RegisterProperty('POSITION', 'TPOSITION', iptrw);
+ RegisterProperty('ONACTIVATE', 'TNOTIFYEVENT', iptrw);
+ RegisterProperty('ONCLICK', 'TNOTIFYEVENT', iptrw);
+ RegisterProperty('ONDBLCLICK', 'TNOTIFYEVENT', iptrw);
+ RegisterProperty('ONCLOSE', 'TCLOSEEVENT', iptrw);
+ RegisterProperty('ONCLOSEQUERY', 'TCLOSEQUERYEVENT', iptrw);
+ RegisterProperty('ONCREATE', 'TNOTIFYEVENT', iptrw);
+ RegisterProperty('ONDESTROY', 'TNOTIFYEVENT', iptrw);
+ RegisterProperty('ONDEACTIVATE', 'TNOTIFYEVENT', iptrw);
+ RegisterProperty('ONHIDE', 'TNOTIFYEVENT', iptrw);
+ RegisterProperty('ONKEYDOWN', 'TKEYEVENT', iptrw);
+ RegisterProperty('ONKEYPRESS', 'TKEYPRESSEVENT', iptrw);
+ RegisterProperty('ONKEYUP', 'TKEYEVENT', iptrw);
+ RegisterProperty('ONRESIZE', 'TNOTIFYEVENT', iptrw);
+ RegisterProperty('ONSHOW', 'TNOTIFYEVENT', iptrw);
+
+
+ {$IFNDEF PS_MINIVCL}
+ {$IFNDEF CLX}
+ RegisterMethod('procedure ARRANGEICONS');
+// RegisterMethod('function GETFORMIMAGE:TBITMAP');
+ RegisterMethod('procedure PRINT');
+ RegisterMethod('procedure SENDCANCELMODE(SENDER:TCONTROL)');
+ RegisterProperty('ACTIVEOLECONTROL', 'TWINCONTROL', iptrw);
+ RegisterProperty('OLEFORMOBJECT', 'TOLEFORMOBJECT', iptrw);
+ RegisterProperty('CLIENTHANDLE', 'LONGINT', iptr);
+ RegisterProperty('TILEMODE', 'TTILEMODE', iptrw);
+ {$ENDIF}
+ RegisterMethod('procedure CASCADE');
+ RegisterMethod('function CLOSEQUERY:BOOLEAN');
+ RegisterMethod('procedure DEFOCUSCONTROL(CONTROL:TWINCONTROL;REMOVING:BOOLEAN)');
+ RegisterMethod('procedure FOCUSCONTROL(CONTROL:TWINCONTROL)');
+ RegisterMethod('procedure NEXT');
+ RegisterMethod('procedure PREVIOUS');
+ RegisterMethod('function SETFOCUSEDCONTROL(CONTROL:TWINCONTROL):BOOLEAN');
+ RegisterMethod('procedure TILE');
+ RegisterProperty('ACTIVEMDICHILD', 'TFORM', iptr);
+ RegisterProperty('CANVAS', 'TCANVAS', iptr);
+ RegisterProperty('DROPTARGET', 'BOOLEAN', iptrw);
+ RegisterProperty('MODALRESULT', 'Longint', iptrw);
+ RegisterProperty('MDICHILDCOUNT', 'INTEGER', iptr);
+ RegisterProperty('MDICHILDREN', 'TFORM INTEGER', iptr);
+ RegisterProperty('ICON', 'TICON', iptrw);
+ RegisterProperty('MENU', 'TMAINMENU', iptrw);
+ RegisterProperty('OBJECTMENUITEM', 'TMENUITEM', iptrw);
+ RegisterProperty('PIXELSPERINCH', 'INTEGER', iptrw);
+ RegisterProperty('PRINTSCALE', 'TPRINTSCALE', iptrw);
+ RegisterProperty('SCALED', 'BOOLEAN', iptrw);
+ RegisterProperty('WINDOWSTATE', 'TWINDOWSTATE', iptrw);
+ RegisterProperty('WINDOWMENU', 'TMENUITEM', iptrw);
+ RegisterProperty('CTL3D', 'BOOLEAN', iptrw);
+ RegisterProperty('POPUPMENU', 'TPOPUPMENU', iptrw);
+ RegisterProperty('ONDRAGDROP', 'TDRAGDROPEVENT', iptrw);
+ RegisterProperty('ONDRAGOVER', 'TDRAGOVEREVENT', iptrw);
+ RegisterProperty('ONMOUSEDOWN', 'TMOUSEEVENT', iptrw);
+ RegisterProperty('ONMOUSEMOVE', 'TMOUSEMOVEEVENT', iptrw);
+ RegisterProperty('ONMOUSEUP', 'TMOUSEEVENT', iptrw);
+ RegisterProperty('ONPAINT', 'TNOTIFYEVENT', iptrw);
+ {$ENDIF}
+ end;
+end;
+
+procedure SIRegisterTAPPLICATION(Cl: TPSPascalCompiler);
+begin
+ with Cl.AddClassN(cl.FindClass('TCOMPONENT'), 'TAPPLICATION') do
+ begin
+ RegisterMethod('procedure BRINGTOFRONT');
+{$IFDEF PS_PANSICHAR}
+ RegisterMethod('function MESSAGEBOX(TEXT,CAPTION:PANSICHAR;FLAGS:WORD):INTEGER');
+{$ELSE}
+ RegisterMethod('function MESSAGEBOX(TEXT,CAPTION:PCHAR;FLAGS:WORD):INTEGER');
+{$ENDIF}
+ RegisterMethod('procedure MINIMIZE');
+ RegisterMethod('procedure PROCESSMESSAGES');
+ RegisterMethod('procedure RESTORE');
+ RegisterMethod('procedure TERMINATE');
+ RegisterProperty('ACTIVE', 'BOOLEAN', iptr);
+ RegisterProperty('EXENAME', 'NativeString', iptr);
+ {$IFNDEF CLX}
+ RegisterProperty('HANDLE', 'LONGINT', iptrw);
+ RegisterProperty('UPDATEFORMATSETTINGS', 'BOOLEAN', iptrw);
+ {$ENDIF}
+ RegisterProperty('HINT', 'NativeString', iptrw);
+ RegisterProperty('MAINFORM', 'TFORM', iptr);
+ RegisterProperty('SHOWHINT', 'BOOLEAN', iptrw);
+ RegisterProperty('SHOWMAINFORM', 'BOOLEAN', iptrw);
+ RegisterProperty('TERMINATED', 'BOOLEAN', iptr);
+ RegisterProperty('TITLE', 'NativeString', iptrw);
+ RegisterProperty('ONACTIVATE', 'TNOTIFYEVENT', iptrw);
+ RegisterProperty('ONDEACTIVATE', 'TNOTIFYEVENT', iptrw);
+ RegisterProperty('ONIDLE', 'TIDLEEVENT', iptrw);
+ RegisterProperty('ONHINT', 'TNOTIFYEVENT', iptrw);
+ RegisterProperty('ONMINIMIZE', 'TNOTIFYEVENT', iptrw);
+ RegisterProperty('ONRESTORE', 'TNOTIFYEVENT', iptrw);
+
+ {$IFNDEF PS_MINIVCL}
+ RegisterMethod('procedure CONTROLDESTROYED(CONTROL:TCONTROL)');
+ RegisterMethod('procedure CANCELHINT');
+ RegisterMethod('procedure HANDLEEXCEPTION(SENDER:TOBJECT)');
+ RegisterMethod('procedure HANDLEMESSAGE');
+ RegisterMethod('procedure HIDEHINT');
+// RegisterMethod('procedure HINTMOUSEMESSAGE(CONTROL:TCONTROL;var MESSAGE:TMESSAGE)');
+ RegisterMethod('procedure INITIALIZE');
+ RegisterMethod('procedure NORMALIZETOPMOSTS');
+ RegisterMethod('procedure RESTORETOPMOSTS');
+ RegisterMethod('procedure RUN');
+// RegisterMethod('procedure SHOWEXCEPTION(E:EXCEPTION)');
+ {$IFNDEF CLX}
+ RegisterMethod('function HELPCOMMAND(COMMAND:INTEGER;DATA:LONGINT):BOOLEAN');
+ RegisterMethod('function HELPCONTEXT(CONTEXT:THELPCONTEXT):BOOLEAN');
+ RegisterMethod('function HELPJUMP(JUMPID:NativeString):BOOLEAN');
+ RegisterProperty('DIALOGHANDLE', 'LONGINT', iptrw);
+ RegisterMethod('procedure CREATEHANDLE');
+// RegisterMethod('procedure HOOKMAINWINDOW(HOOK:TWINDOWHOOK)');
+// RegisterMethod('procedure UNHOOKMAINWINDOW(HOOK:TWINDOWHOOK)');
+ {$ENDIF}
+ RegisterProperty('HELPFILE', 'NativeString', iptrw);
+ RegisterProperty('HINTCOLOR', 'TCOLOR', iptrw);
+ RegisterProperty('HINTPAUSE', 'INTEGER', iptrw);
+ RegisterProperty('HINTSHORTPAUSE', 'INTEGER', iptrw);
+ RegisterProperty('HINTHIDEPAUSE', 'INTEGER', iptrw);
+ RegisterProperty('ICON', 'TICON', iptrw);
+ RegisterProperty('ONHELP', 'THELPEVENT', iptrw);
+ {$ENDIF}
+ end;
+end;
+
+procedure SIRegister_Forms_TypesAndConsts(Cl: TPSPascalCompiler);
+begin
+ Cl.AddTypeS('TIdleEvent', 'procedure (Sender: TObject; var Done: Boolean)');
+ cl.AddTypeS('TScrollBarKind', '(sbHorizontal, sbVertical)');
+ cl.AddTypeS('TScrollBarInc', 'SmallInt');
+ cl.AddTypeS('TFormBorderStyle', '(bsNone, bsSingle, bsSizeable, bsDialog, bsToolWindow, bsSizeToolWin)');
+ cl.AddTypeS('TBorderStyle', 'TFormBorderStyle');
+ cl.AddTypeS('TWindowState', '(wsNormal, wsMinimized, wsMaximized)');
+ cl.AddTypeS('TFormStyle', '(fsNormal, fsMDIChild, fsMDIForm, fsStayOnTop)');
+ cl.AddTypeS('TPosition', '(poDesigned, poDefault, poDefaultPosOnly, poDefaultSizeOnly, poScreenCenter, poDesktopCenter, poMainFormCenter, poOwnerFormCenter)');
+ cl.AddTypeS('TPrintScale', '(poNone, poProportional, poPrintToFit)');
+ cl.AddTypeS('TCloseAction', '(caNone, caHide, caFree, caMinimize)');
+ cl.AddTypeS('TCloseEvent' ,'procedure(Sender: TObject; var Action: TCloseAction)');
+ cl.AddTypeS('TCloseQueryEvent' ,'procedure(Sender: TObject; var CanClose: Boolean)');
+ cl.AddTypeS('TBorderIcon' ,'(biSystemMenu, biMinimize, biMaximize, biHelp)');
+ cl.AddTypeS('TBorderIcons', 'set of TBorderIcon');
+ cl.AddTypeS('THELPCONTEXT', 'Longint');
+end;
+
+procedure SIRegister_Forms(Cl: TPSPascalCompiler);
+begin
+ SIRegister_Forms_TypesAndConsts(cl);
+
+ {$IFNDEF PS_MINIVCL}
+ SIRegisterTCONTROLSCROLLBAR(cl);
+ {$ENDIF}
+ SIRegisterTScrollingWinControl(cl);
+ {$IFNDEF PS_MINIVCL}
+ SIRegisterTSCROLLBOX(cl);
+ {$ENDIF}
+ SIRegisterTForm(Cl);
+ {$IFNDEF PS_MINIVCL}
+ SIRegisterTApplication(Cl);
+ {$ENDIF}
+end;
+
+// PS_MINIVCL changes by Martijn Laan (mlaan at wintax _dot_ nl)
+
+
+end.
+
diff --git a/branches/script-component/Units/PascalScript/uPSC_graphics.pas b/branches/script-component/Units/PascalScript/uPSC_graphics.pas
new file mode 100644
index 0000000..2e4c92b
--- /dev/null
+++ b/branches/script-component/Units/PascalScript/uPSC_graphics.pas
@@ -0,0 +1,275 @@
+{ Compiletime Graphics support }
+unit uPSC_graphics;
+
+{$I PascalScript.inc}
+interface
+uses
+ uPSCompiler, uPSUtils;
+
+
+
+procedure SIRegister_Graphics_TypesAndConsts(Cl: TPSPascalCompiler);
+procedure SIRegisterTGRAPHICSOBJECT(Cl: TPSPascalCompiler);
+procedure SIRegisterTFont(Cl: TPSPascalCompiler);
+procedure SIRegisterTPEN(Cl: TPSPascalCompiler);
+procedure SIRegisterTBRUSH(Cl: TPSPascalCompiler);
+procedure SIRegisterTCanvas(cl: TPSPascalCompiler);
+procedure SIRegisterTGraphic(CL: TPSPascalCompiler);
+procedure SIRegisterTBitmap(CL: TPSPascalCompiler; Streams: Boolean);
+
+procedure SIRegister_Graphics(Cl: TPSPascalCompiler; Streams: Boolean);
+
+implementation
+{$IFNDEF PS_NOGRAPHCONST}
+uses
+ {$IFDEF CLX}QGraphics{$ELSE}Graphics{$ENDIF};
+{$ELSE}
+{$IFNDEF CLX}
+{$IFNDEF FPC}
+uses
+ Windows;
+{$ENDIF}
+{$ENDIF}
+{$ENDIF}
+
+procedure SIRegisterTGRAPHICSOBJECT(Cl: TPSPascalCompiler);
+begin
+ with Cl.AddClassN(cl.FindClass('TPERSISTENT'), 'TGRAPHICSOBJECT') do
+ begin
+ RegisterProperty('ONCHANGE', 'TNOTIFYEVENT', iptrw);
+ end;
+end;
+
+procedure SIRegisterTFont(Cl: TPSPascalCompiler);
+begin
+ with Cl.AddClassN(cl.FindClass('TGraphicsObject'), 'TFONT') do
+ begin
+ RegisterMethod('constructor Create;');
+{$IFNDEF CLX}
+ RegisterProperty('Handle', 'Integer', iptRW);
+{$ENDIF}
+ RegisterProperty('Color', 'TColor', iptRW);
+ RegisterProperty('Height', 'Integer', iptRW);
+ RegisterProperty('Name', 'String', iptRW);
+ RegisterProperty('Pitch', 'Byte', iptRW);
+ RegisterProperty('Size', 'Integer', iptRW);
+ RegisterProperty('PixelsPerInch', 'Integer', iptRW);
+ RegisterProperty('Style', 'TFontStyles', iptrw);
+ end;
+end;
+
+procedure SIRegisterTCanvas(cl: TPSPascalCompiler); // requires TPersistent
+begin
+ with Cl.AddClassN(cl.FindClass('TPersistent'), 'TCANVAS') do
+ begin
+ RegisterMethod('procedure Arc(X1, Y1, X2, Y2, X3, Y3, X4, Y4: Integer);');
+ RegisterMethod('procedure Chord(X1, Y1, X2, Y2, X3, Y3, X4, Y4: Integer);');
+// RegisterMethod('procedure Draw(X, Y: Integer; Graphic: TGraphic);');
+ RegisterMethod('procedure Ellipse(X1, Y1, X2, Y2: Integer);');
+ RegisterMethod('procedure FillRect(const Rect: TRect);');
+{$IFNDEF CLX}
+ RegisterMethod('procedure FloodFill(X, Y: Integer; Color: TColor; FillStyle: Byte);');
+{$ENDIF}
+ RegisterMethod('procedure LineTo(X, Y: Integer);');
+ RegisterMethod('procedure MoveTo(X, Y: Integer);');
+ RegisterMethod('procedure Pie(X1, Y1, X2, Y2, X3, Y3, X4, Y4: Integer);');
+ RegisterMethod('procedure Rectangle(X1, Y1, X2, Y2: Integer);');
+ RegisterMethod('procedure Refresh;');
+ RegisterMethod('procedure RoundRect(X1, Y1, X2, Y2, X3, Y3: Integer);');
+ RegisterMethod('function TextHeight(Text: String): Integer;');
+ RegisterMethod('procedure TextOut(X, Y: Integer; Text: String);');
+ RegisterMethod('function TextWidth(Text: String): Integer;');
+{$IFNDEF CLX}
+ RegisterProperty('Handle', 'Integer', iptRw);
+{$ENDIF}
+ RegisterProperty('Pixels', 'Integer Integer Integer', iptRW);
+ RegisterProperty('Brush', 'TBrush', iptR);
+ RegisterProperty('CopyMode', 'Byte', iptRw);
+ RegisterProperty('Font', 'TFont', iptR);
+ RegisterProperty('Pen', 'TPen', iptR);
+ end;
+end;
+
+procedure SIRegisterTPEN(Cl: TPSPascalCompiler);
+begin
+ with Cl.AddClassN(cl.FindClass('TGRAPHICSOBJECT'), 'TPEN') do
+ begin
+ RegisterMethod('constructor CREATE');
+ RegisterProperty('COLOR', 'TCOLOR', iptrw);
+ RegisterProperty('MODE', 'TPENMODE', iptrw);
+ RegisterProperty('STYLE', 'TPENSTYLE', iptrw);
+ RegisterProperty('WIDTH', 'INTEGER', iptrw);
+ end;
+end;
+
+procedure SIRegisterTBRUSH(Cl: TPSPascalCompiler);
+begin
+ with Cl.AddClassN(cl.FindClass('TGRAPHICSOBJECT'), 'TBRUSH') do
+ begin
+ RegisterMethod('constructor CREATE');
+ RegisterProperty('COLOR', 'TCOLOR', iptrw);
+ RegisterProperty('STYLE', 'TBRUSHSTYLE', iptrw);
+ end;
+end;
+
+procedure SIRegister_Graphics_TypesAndConsts(Cl: TPSPascalCompiler);
+{$IFDEF PS_NOGRAPHCONST}
+const
+ clSystemColor = {$IFDEF DELPHI7UP} $FF000000 {$ELSE} $80000000 {$ENDIF};
+{$ENDIF}
+begin
+{$IFNDEF PS_NOGRAPHCONST}
+ cl.AddConstantN('clScrollBar', 'Integer').Value.ts32 := clScrollBar;
+ cl.AddConstantN('clBackground', 'Integer').Value.ts32 := clBackground;
+ cl.AddConstantN('clActiveCaption', 'Integer').Value.ts32 := clActiveCaption;
+ cl.AddConstantN('clInactiveCaption', 'Integer').Value.ts32 := clInactiveCaption;
+ cl.AddConstantN('clMenu', 'Integer').Value.ts32 := clMenu;
+ cl.AddConstantN('clWindow', 'Integer').Value.ts32 := clWindow;
+ cl.AddConstantN('clWindowFrame', 'Integer').Value.ts32 := clWindowFrame;
+ cl.AddConstantN('clMenuText', 'Integer').Value.ts32 := clMenuText;
+ cl.AddConstantN('clWindowText', 'Integer').Value.ts32 := clWindowText;
+ cl.AddConstantN('clCaptionText', 'Integer').Value.ts32 := clCaptionText;
+ cl.AddConstantN('clActiveBorder', 'Integer').Value.ts32 := clActiveBorder;
+ cl.AddConstantN('clInactiveBorder', 'Integer').Value.ts32 := clInactiveCaption;
+ cl.AddConstantN('clAppWorkSpace', 'Integer').Value.ts32 := clAppWorkSpace;
+ cl.AddConstantN('clHighlight', 'Integer').Value.ts32 := clHighlight;
+ cl.AddConstantN('clHighlightText', 'Integer').Value.ts32 := clHighlightText;
+ cl.AddConstantN('clBtnFace', 'Integer').Value.ts32 := clBtnFace;
+ cl.AddConstantN('clBtnShadow', 'Integer').Value.ts32 := clBtnShadow;
+ cl.AddConstantN('clGrayText', 'Integer').Value.ts32 := clGrayText;
+ cl.AddConstantN('clBtnText', 'Integer').Value.ts32 := clBtnText;
+ cl.AddConstantN('clInactiveCaptionText', 'Integer').Value.ts32 := clInactiveCaptionText;
+ cl.AddConstantN('clBtnHighlight', 'Integer').Value.ts32 := clBtnHighlight;
+ cl.AddConstantN('cl3DDkShadow', 'Integer').Value.ts32 := cl3DDkShadow;
+ cl.AddConstantN('cl3DLight', 'Integer').Value.ts32 := cl3DLight;
+ cl.AddConstantN('clInfoText', 'Integer').Value.ts32 := clInfoText;
+ cl.AddConstantN('clInfoBk', 'Integer').Value.ts32 := clInfoBk;
+{$ELSE}
+{$IFNDEF CLX} // These are VCL-only; CLX uses different constant values
+ cl.AddConstantN('clScrollBar', 'Integer').Value.ts32 := Integer(clSystemColor or COLOR_SCROLLBAR);
+ cl.AddConstantN('clBackground', 'Integer').Value.ts32 := Integer(clSystemColor or COLOR_BACKGROUND);
+ cl.AddConstantN('clActiveCaption', 'Integer').Value.ts32 := Integer(clSystemColor or COLOR_ACTIVECAPTION);
+ cl.AddConstantN('clInactiveCaption', 'Integer').Value.ts32 := Integer(clSystemColor or COLOR_INACTIVECAPTION);
+ cl.AddConstantN('clMenu', 'Integer').Value.ts32 := Integer(clSystemColor or COLOR_MENU);
+ cl.AddConstantN('clWindow', 'Integer').Value.ts32 := Integer(clSystemColor or COLOR_WINDOW);
+ cl.AddConstantN('clWindowFrame', 'Integer').Value.ts32 := Integer(clSystemColor or COLOR_WINDOWFRAME);
+ cl.AddConstantN('clMenuText', 'Integer').Value.ts32 := Integer(clSystemColor or COLOR_MENUTEXT);
+ cl.AddConstantN('clWindowText', 'Integer').Value.ts32 := Integer(clSystemColor or COLOR_WINDOWTEXT);
+ cl.AddConstantN('clCaptionText', 'Integer').Value.ts32 := Integer(clSystemColor or COLOR_CAPTIONTEXT);
+ cl.AddConstantN('clActiveBorder', 'Integer').Value.ts32 := Integer(clSystemColor or COLOR_ACTIVEBORDER);
+ cl.AddConstantN('clInactiveBorder', 'Integer').Value.ts32 := Integer(clSystemColor or COLOR_INACTIVEBORDER);
+ cl.AddConstantN('clAppWorkSpace', 'Integer').Value.ts32 := Integer(clSystemColor or COLOR_APPWORKSPACE);
+ cl.AddConstantN('clHighlight', 'Integer').Value.ts32 := Integer(clSystemColor or COLOR_HIGHLIGHT);
+ cl.AddConstantN('clHighlightText', 'Integer').Value.ts32 := Integer(clSystemColor or COLOR_HIGHLIGHTTEXT);
+ cl.AddConstantN('clBtnFace', 'Integer').Value.ts32 := Integer(clSystemColor or COLOR_BTNFACE);
+ cl.AddConstantN('clBtnShadow', 'Integer').Value.ts32 := Integer(clSystemColor or COLOR_BTNSHADOW);
+ cl.AddConstantN('clGrayText', 'Integer').Value.ts32 := Integer(clSystemColor or COLOR_GRAYTEXT);
+ cl.AddConstantN('clBtnText', 'Integer').Value.ts32 := Integer(clSystemColor or COLOR_BTNTEXT);
+ cl.AddConstantN('clInactiveCaptionText', 'Integer').Value.ts32 := Integer(clSystemColor or COLOR_INACTIVECAPTIONTEXT);
+ cl.AddConstantN('clBtnHighlight', 'Integer').Value.ts32 := Integer(clSystemColor or COLOR_BTNHIGHLIGHT);
+ cl.AddConstantN('cl3DDkShadow', 'Integer').Value.ts32 := Integer(clSystemColor or COLOR_3DDKSHADOW);
+ cl.AddConstantN('cl3DLight', 'Integer').Value.ts32 := Integer(clSystemColor or COLOR_3DLIGHT);
+ cl.AddConstantN('clInfoText', 'Integer').Value.ts32 := Integer(clSystemColor or COLOR_INFOTEXT);
+ cl.AddConstantN('clInfoBk', 'Integer').Value.ts32 := Integer(clSystemColor or COLOR_INFOBK);
+{$ENDIF}
+{$ENDIF}
+ cl.AddConstantN('clBlack', 'Integer').Value.ts32 := $000000;
+ cl.AddConstantN('clMaroon', 'Integer').Value.ts32 := $000080;
+ cl.AddConstantN('clGreen', 'Integer').Value.ts32 := $008000;
+ cl.AddConstantN('clOlive', 'Integer').Value.ts32 := $008080;
+ cl.AddConstantN('clNavy', 'Integer').Value.ts32 := $800000;
+ cl.AddConstantN('clPurple', 'Integer').Value.ts32 := $800080;
+ cl.AddConstantN('clTeal', 'Integer').Value.ts32 := $808000;
+ cl.AddConstantN('clGray', 'Integer').Value.ts32 := $808080;
+ cl.AddConstantN('clSilver', 'Integer').Value.ts32 := $C0C0C0;
+ cl.AddConstantN('clRed', 'Integer').Value.ts32 := $0000FF;
+ cl.AddConstantN('clLime', 'Integer').Value.ts32 := $00FF00;
+ cl.AddConstantN('clYellow', 'Integer').Value.ts32 := $00FFFF;
+ cl.AddConstantN('clBlue', 'Integer').Value.ts32 := $FF0000;
+ cl.AddConstantN('clFuchsia', 'Integer').Value.ts32 := $FF00FF;
+ cl.AddConstantN('clAqua', 'Integer').Value.ts32 := $FFFF00;
+ cl.AddConstantN('clLtGray', 'Integer').Value.ts32 := $C0C0C0;
+ cl.AddConstantN('clDkGray', 'Integer').Value.ts32 := $808080;
+ cl.AddConstantN('clWhite', 'Integer').Value.ts32 := $FFFFFF;
+ cl.AddConstantN('clNone', 'Integer').Value.ts32 := $1FFFFFFF;
+ cl.AddConstantN('clDefault', 'Integer').Value.ts32 := $20000000;
+
+ Cl.addTypeS('TFONTSTYLE', '(FSBOLD, FSITALIC, FSUNDERLINE, FSSTRIKEOUT)');
+ Cl.addTypeS('TFONTSTYLES', 'set of TFONTSTYLE');
+
+ cl.AddTypeS('TFontPitch', '(fpDefault, fpVariable, fpFixed)');
+ cl.AddTypeS('TPenStyle', '(psSolid, psDash, psDot, psDashDot, psDashDotDot, psClear, psInsideFrame)');
+ cl.AddTypeS('TPenMode', '(pmBlack, pmWhite, pmNop, pmNot, pmCopy, pmNotCopy, pmMergePenNot, pmMaskPenNot, pmMergeNotPen, pmMaskNotPen, pmMerge, pmNotMerge, pmMask, pmNotMask, pmXor, pmNotXor)');
+ cl.AddTypeS('TBrushStyle', '(bsSolid, bsClear, bsHorizontal, bsVertical, bsFDiagonal, bsBDiagonal, bsCross, bsDiagCross)');
+ cl.addTypeS('TColor', 'integer');
+
+{$IFNDEF CLX}
+ cl.addTypeS('HBITMAP', 'Integer');
+ cl.addTypeS('HPALETTE', 'Integer');
+{$ENDIF}
+end;
+
+procedure SIRegisterTGraphic(CL: TPSPascalCompiler);
+begin
+ with CL.AddClassN(CL.FindClass('TPersistent'),'TGraphic') do
+ begin
+ RegisterMethod('constructor Create');
+ RegisterMethod('Procedure LoadFromFile( const Filename : String)');
+ RegisterMethod('Procedure SaveToFile( const Filename : String)');
+ RegisterProperty('Empty', 'Boolean', iptr);
+ RegisterProperty('Height', 'Integer', iptrw);
+ RegisterProperty('Modified', 'Boolean', iptrw);
+ RegisterProperty('Width', 'Integer', iptrw);
+ RegisterProperty('OnChange', 'TNotifyEvent', iptrw);
+ end;
+end;
+
+procedure SIRegisterTBitmap(CL: TPSPascalCompiler; Streams: Boolean);
+begin
+ with CL.AddClassN(CL.FindClass('TGraphic'),'TBitmap') do
+ begin
+ if Streams then begin
+ RegisterMethod('Procedure LoadFromStream( Stream : TStream)');
+ RegisterMethod('Procedure SaveToStream( Stream : TStream)');
+ end;
+ RegisterProperty('Canvas', 'TCanvas', iptr);
+{$IFNDEF CLX}
+ RegisterProperty('Handle', 'HBITMAP', iptrw);
+{$ENDIF}
+
+ {$IFNDEF IFPS_MINIVCL}
+ RegisterMethod('Procedure Dormant');
+ RegisterMethod('Procedure FreeImage');
+{$IFNDEF CLX}
+ RegisterMethod('Procedure LoadFromClipboardFormat( AFormat : Word; AData : THandle; APalette : HPALETTE)');
+{$ENDIF}
+ RegisterMethod('Procedure LoadFromResourceName( Instance : THandle; const ResName : String)');
+ RegisterMethod('Procedure LoadFromResourceID( Instance : THandle; ResID : Integer)');
+{$IFNDEF CLX}
+ RegisterMethod('Function ReleaseHandle : HBITMAP');
+ RegisterMethod('Function ReleasePalette : HPALETTE');
+ RegisterMethod('Procedure SaveToClipboardFormat( var Format : Word; var Data : THandle; var APalette : HPALETTE)');
+ RegisterProperty('Monochrome', 'Boolean', iptrw);
+ RegisterProperty('Palette', 'HPALETTE', iptrw);
+ RegisterProperty('IgnorePalette', 'Boolean', iptrw);
+{$ENDIF}
+ RegisterProperty('TransparentColor', 'TColor', iptr);
+ {$ENDIF}
+ end;
+end;
+
+procedure SIRegister_Graphics(Cl: TPSPascalCompiler; Streams: Boolean);
+begin
+ SIRegister_Graphics_TypesAndConsts(Cl);
+ SIRegisterTGRAPHICSOBJECT(Cl);
+ SIRegisterTFont(Cl);
+ SIRegisterTPEN(cl);
+ SIRegisterTBRUSH(cl);
+ SIRegisterTCanvas(cl);
+ SIRegisterTGraphic(Cl);
+ SIRegisterTBitmap(Cl, Streams);
+end;
+
+// PS_MINIVCL changes by Martijn Laan (mlaan at wintax _dot_ nl)
+
+End.
diff --git a/branches/script-component/Units/PascalScript/uPSC_menus.pas b/branches/script-component/Units/PascalScript/uPSC_menus.pas
new file mode 100644
index 0000000..0ee0d87
--- /dev/null
+++ b/branches/script-component/Units/PascalScript/uPSC_menus.pas
@@ -0,0 +1,214 @@
+{ Menus Import Unit }
+Unit uPSC_menus;
+{$I PascalScript.inc}
+Interface
+Uses uPSCompiler;
+
+procedure SIRegisterTMENUITEMSTACK(CL: TPSPascalCompiler);
+procedure SIRegisterTPOPUPLIST(CL: TPSPascalCompiler);
+procedure SIRegisterTPOPUPMENU(CL: TPSPascalCompiler);
+procedure SIRegisterTMAINMENU(CL: TPSPascalCompiler);
+procedure SIRegisterTMENU(CL: TPSPascalCompiler);
+procedure SIRegisterTMENUITEM(CL: TPSPascalCompiler);
+procedure SIRegister_Menus(Cl: TPSPascalCompiler);
+
+implementation
+
+procedure SIRegisterTMENUITEMSTACK(CL: TPSPascalCompiler);
+begin
+ With cl.AddClassN(Cl.FindClass('TSTACK'),'TMENUITEMSTACK') do
+ begin
+ RegisterMethod('Procedure CLEARITEM( AITEM : TMENUITEM)');
+ end;
+end;
+
+procedure SIRegisterTPOPUPLIST(CL: TPSPascalCompiler);
+begin
+ With cl.AddClassN(Cl.FindClass('TLIST'),'TPOPUPLIST') do
+ begin
+ RegisterProperty('WINDOW', 'HWND', iptr);
+ RegisterMethod('Procedure ADD( POPUP : TPOPUPMENU)');
+ RegisterMethod('Procedure REMOVE( POPUP : TPOPUPMENU)');
+ end;
+end;
+
+procedure SIRegisterTPOPUPMENU(CL: TPSPascalCompiler);
+var
+ cc: TPSCompileTimeClass;
+begin
+ With cl.AddClassN(Cl.FindClass('TMENU'),'TPOPUPMENU') do
+ begin
+ cc := Cl.FindClass('TLabel');
+ if cc <> nil then
+ RegisterProperty('POPUPMENU', 'TPOPUPMENU', iptRW);
+ with Cl.FindClass('TForm') do
+ begin
+ RegisterProperty('POPUPMENU', 'TPOPUPMENU', iptRW);
+ end;
+ RegisterMethod('Constructor CREATE( AOWNER : TCOMPONENT)');
+ RegisterMethod('Procedure POPUP( X, Y : INTEGER)');
+ RegisterProperty('POPUPCOMPONENT', 'TCOMPONENT', iptrw);
+ RegisterProperty('ALIGNMENT', 'TPOPUPALIGNMENT', iptrw);
+ RegisterProperty('AUTOPOPUP', 'BOOLEAN', iptrw);
+ RegisterProperty('HELPCONTEXT', 'THELPCONTEXT', iptrw);
+ RegisterProperty('MENUANIMATION', 'TMENUANIMATION', iptrw);
+ RegisterProperty('TRACKBUTTON', 'TTRACKBUTTON', iptrw);
+ RegisterProperty('ONPOPUP', 'TNOTIFYEVENT', iptrw);
+ end;
+end;
+
+procedure SIRegisterTMAINMENU(CL: TPSPascalCompiler);
+begin
+ With cl.AddClassN(Cl.FindClass('TMENU'),'TMAINMENU') do
+ begin
+ RegisterMethod('Procedure MERGE( MENU : TMAINMENU)');
+ RegisterMethod('Procedure UNMERGE( MENU : TMAINMENU)');
+ RegisterMethod('Procedure POPULATEOLE2MENU( SHAREDMENU : HMENU; GROUPS : array of INTEGER; var WIDTHS : array of LONGINT)');
+ RegisterMethod('Procedure GETOLE2ACCELERATORTABLE( var ACCELTABLE : HACCEL; var ACCELCOUNT : INTEGER; GROUPS : array of INTEGER)');
+ RegisterMethod('Procedure SETOLE2MENUHANDLE( HANDLE : HMENU)');
+ RegisterProperty('AUTOMERGE', 'BOOLEAN', iptrw);
+ end;
+end;
+
+procedure SIRegisterTMENU(CL: TPSPascalCompiler);
+begin
+ With cl.AddClassN(Cl.FindClass('TCOMPONENT'),'TMENU') do
+ begin
+ RegisterMethod('Constructor CREATE( AOWNER : TCOMPONENT)');
+ RegisterMethod('Function DISPATCHCOMMAND( ACOMMAND : WORD) : BOOLEAN');
+ RegisterMethod('Function DISPATCHPOPUP( AHANDLE : HMENU) : BOOLEAN');
+ RegisterMethod('Function FINDITEM( VALUE : INTEGER; KIND : TFINDITEMKIND) : TMENUITEM');
+ RegisterMethod('Function GETHELPCONTEXT( VALUE : INTEGER; BYCOMMAND : BOOLEAN) : THELPCONTEXT');
+ RegisterProperty('IMAGES', 'TCUSTOMIMAGELIST', iptrw);
+ RegisterMethod('Function ISRIGHTTOLEFT : BOOLEAN');
+ RegisterMethod('Procedure PARENTBIDIMODECHANGED( ACONTROL : TOBJECT)');
+ RegisterMethod('Procedure PROCESSMENUCHAR( var MESSAGE : TWMMENUCHAR)');
+ RegisterProperty('AUTOHOTKEYS', 'TMENUAUTOFLAG', iptrw);
+ RegisterProperty('AUTOLINEREDUCTION', 'TMENUAUTOFLAG', iptrw);
+ RegisterProperty('BIDIMODE', 'TBIDIMODE', iptrw);
+ RegisterProperty('HANDLE', 'HMENU', iptr);
+ RegisterProperty('OWNERDRAW', 'BOOLEAN', iptrw);
+ RegisterProperty('PARENTBIDIMODE', 'BOOLEAN', iptrw);
+ RegisterProperty('WINDOWHANDLE', 'HWND', iptrw);
+ RegisterProperty('ITEMS', 'TMENUITEM', iptr);
+ end;
+end;
+
+procedure SIRegisterTMENUITEM(CL: TPSPascalCompiler);
+begin
+ With cl.AddClassN(Cl.FindClass('TCOMPONENT'),'TMENUITEM') do
+ begin
+ RegisterMethod('Constructor CREATE( AOWNER : TCOMPONENT)');
+ RegisterMethod('Procedure INITIATEACTION');
+ RegisterMethod('Procedure INSERT( INDEX : INTEGER; ITEM : TMENUITEM)');
+ RegisterMethod('Procedure DELETE( INDEX : INTEGER)');
+ RegisterMethod('Procedure CLEAR');
+ RegisterMethod('Procedure CLICK');
+ RegisterMethod('Function FIND( ACAPTION : String) : TMENUITEM');
+ RegisterMethod('Function INDEXOF( ITEM : TMENUITEM) : INTEGER');
+ RegisterMethod('Function ISLINE : BOOLEAN');
+ RegisterMethod('Function GETIMAGELIST : TCUSTOMIMAGELIST');
+ RegisterMethod('Function GETPARENTCOMPONENT : TCOMPONENT');
+ RegisterMethod('Function GETPARENTMENU : TMENU');
+ RegisterMethod('Function HASPARENT : BOOLEAN');
+ RegisterMethod('Function NEWTOPLINE : INTEGER');
+ RegisterMethod('Function NEWBOTTOMLINE : INTEGER');
+ RegisterMethod('Function INSERTNEWLINEBEFORE( AITEM : TMENUITEM) : INTEGER');
+ RegisterMethod('Function INSERTNEWLINEAFTER( AITEM : TMENUITEM) : INTEGER');
+ RegisterMethod('Procedure ADD( ITEM : TMENUITEM)');
+ RegisterMethod('Procedure REMOVE( ITEM : TMENUITEM)');
+ RegisterMethod('Function RETHINKHOTKEYS : BOOLEAN');
+ RegisterMethod('Function RETHINKLINES : BOOLEAN');
+ RegisterProperty('COMMAND', 'WORD', iptr);
+ RegisterProperty('HANDLE', 'HMENU', iptr);
+ RegisterProperty('COUNT', 'INTEGER', iptr);
+ RegisterProperty('ITEMS', 'TMENUITEM INTEGER', iptr);
+ RegisterProperty('MENUINDEX', 'INTEGER', iptrw);
+ RegisterProperty('PARENT', 'TMENUITEM', iptr);
+ {$IFDEF DELPHI5UP}
+ RegisterProperty('ACTION', 'TBASICACTION', iptrw);
+ {$ENDIF}
+ RegisterProperty('AUTOHOTKEYS', 'TMENUITEMAUTOFLAG', iptrw);
+ RegisterProperty('AUTOLINEREDUCTION', 'TMENUITEMAUTOFLAG', iptrw);
+ RegisterProperty('BITMAP', 'TBITMAP', iptrw);
+ RegisterProperty('CAPTION', 'String', iptrw);
+ RegisterProperty('CHECKED', 'BOOLEAN', iptrw);
+ RegisterProperty('SUBMENUIMAGES', 'TCUSTOMIMAGELIST', iptrw);
+ RegisterProperty('DEFAULT', 'BOOLEAN', iptrw);
+ RegisterProperty('ENABLED', 'BOOLEAN', iptrw);
+ RegisterProperty('GROUPINDEX', 'BYTE', iptrw);
+ RegisterProperty('HELPCONTEXT', 'THELPCONTEXT', iptrw);
+ RegisterProperty('HINT', 'String', iptrw);
+ RegisterProperty('IMAGEINDEX', 'TIMAGEINDEX', iptrw);
+ RegisterProperty('RADIOITEM', 'BOOLEAN', iptrw);
+ RegisterProperty('SHORTCUT', 'TSHORTCUT', iptrw);
+ RegisterProperty('VISIBLE', 'BOOLEAN', iptrw);
+ RegisterProperty('ONCLICK', 'TNOTIFYEVENT', iptrw);
+ {$IFNDEF FPC} RegisterProperty('ONDRAWITEM', 'TMENUDRAWITEMEVENT', iptrw);
+ RegisterProperty('ONADVANCEDDRAWITEM', 'TADVANCEDMENUDRAWITEMEVENT', iptrw);
+ RegisterProperty('ONMEASUREITEM', 'TMENUMEASUREITEMEVENT', iptrw);{$ENDIF}
+ end;
+end;
+
+procedure SIRegister_Menus(Cl: TPSPascalCompiler);
+begin
+ Cl.AddTypeS('HMenu', 'Cardinal');
+ Cl.AddTypeS('HACCEL', 'Cardinal');
+
+ cl.addClassN(cl.FindClass('EXCEPTION'),'EMENUERROR');
+ Cl.addTypeS('TMENUBREAK', '( MBNONE, MBBREAK, MBBARBREAK )');
+{$IFNDEF FPC}
+ Cl.addTypeS('TMENUDRAWITEMEVENT', 'Procedure ( SENDER : TOBJECT; ACANVAS : TC'
+ +'ANVAS; ARECT : TRECT; SELECTED : BOOLEAN)');
+ Cl.addTypeS('TADVANCEDMENUDRAWITEMEVENT', 'Procedure ( SENDER : TOBJECT; ACAN'
+ +'VAS : TCANVAS; ARECT : TRECT; STATE : TOWNERDRAWSTATE)');
+ Cl.addTypeS('TMENUMEASUREITEMEVENT', 'Procedure ( SENDER : TOBJECT; ACANVAS :'
+ +' TCANVAS; var WIDTH, HEIGHT : INTEGER)');
+{$ENDIF}
+ Cl.addTypeS('TMENUITEMAUTOFLAG', '( MAAUTOMATIC, MAMANUAL, MAPARENT )');
+ Cl.AddTypeS('TMenuAutoFlag', 'TMENUITEMAUTOFLAG');
+ Cl.addTypeS('TSHORTCUT', 'WORD');
+ cl.addClassN(cl.FindClass('TACTIONLINK'),'TMENUACTIONLINK');
+ SIRegisterTMENUITEM(Cl);
+ Cl.addTypeS('TMENUCHANGEEVENT', 'Procedure ( SENDER : TOBJECT; SOURCE : TMENU'
+ +'ITEM; REBUILD : BOOLEAN)');
+ Cl.addTypeS('TFINDITEMKIND', '( FKCOMMAND, FKHANDLE, FKSHORTCUT )');
+ SIRegisterTMENU(Cl);
+ SIRegisterTMAINMENU(Cl);
+ Cl.addTypeS('TPOPUPALIGNMENT', '( PALEFT, PARIGHT, PACENTER )');
+ Cl.addTypeS('TTRACKBUTTON', '( TBRIGHTBUTTON, TBLEFTBUTTON )');
+ Cl.addTypeS('TMENUANIMATIONS', '( MALEFTTORIGHT, MARIGHTTOLEFT, MATOPTOBOTTOM'
+ +', MABOTTOMTOTOP, MANONE )');
+ Cl.addTypeS('TMENUANIMATION', 'set of TMENUANIMATIONS');
+ SIRegisterTPOPUPMENU(Cl);
+ SIRegisterTPOPUPLIST(Cl);
+ SIRegisterTMENUITEMSTACK(Cl);
+ Cl.addTypeS('TCMENUITEM', 'TMENUITEM');
+{$IFNDEF FPC}
+//TODO: it should work,but somehow TShiftState is not defined
+ Cl.AddDelphiFunction('Function SHORTCUT( KEY : WORD; SHIFT : TSHIFTSTATE) : T'
+ +'SHORTCUT');
+ Cl.AddDelphiFunction('Procedure SHORTCUTTOKEY( SHORTCUT : TSHORTCUT; var KEY '
+ +': WORD; var SHIFT : TSHIFTSTATE)');
+{$ENDIF}
+ Cl.AddDelphiFunction('Function SHORTCUTTOTEXT( SHORTCUT : TSHORTCUT) : String'
+ +'');
+ Cl.AddDelphiFunction('Function TEXTTOSHORTCUT( TEXT : String) : TSHORTCUT');
+ Cl.AddDelphiFunction('Function NEWMENU( OWNER : TCOMPONENT; const ANAME : STR'
+ +'ING; ITEMS : array of TMenuItem) : TMAINMENU');
+ Cl.AddDelphiFunction('Function NEWPOPUPMENU( OWNER : TCOMPONENT; const ANAME '
+ +': String; ALIGNMENT : TPOPUPALIGNMENT; AUTOPOPUP : BOOLEAN; const ITEMS : array of '
+ +'TCMENUITEM) : TPOPUPMENU');
+ Cl.AddDelphiFunction('Function NEWSUBMENU( const ACAPTION : String; HCTX : WO'
+ +'RD; const ANAME : String; ITEMS : array of TMenuItem; AENABLED : BOOLEAN) : TMENUITEM');
+ Cl.AddDelphiFunction('Function NEWITEM( const ACAPTION : String; ASHORTCUT : '
+ +'TSHORTCUT; ACHECKED, AENABLED : BOOLEAN; AONCLICK : TNOTIFYEVENT; HCTX : W'
+ +'ORD; const ANAME : String) : TMENUITEM');
+ Cl.AddDelphiFunction('Function NEWLINE : TMENUITEM');
+{$IFNDEF FPC}
+ Cl.AddDelphiFunction('Procedure DRAWMENUITEM( MENUITEM : TMENUITEM; ACANVAS :'
+ +' TCANVAS; ARECT : TRECT; STATE : TOWNERDRAWSTATE)');
+{$ENDIF}
+end;
+
+end.
diff --git a/branches/script-component/Units/PascalScript/uPSC_std.pas b/branches/script-component/Units/PascalScript/uPSC_std.pas
new file mode 100644
index 0000000..6cdc64b
--- /dev/null
+++ b/branches/script-component/Units/PascalScript/uPSC_std.pas
@@ -0,0 +1,87 @@
+{ Compiletime TObject, TPersistent and TComponent definitions }
+unit uPSC_std;
+{$I PascalScript.inc}
+interface
+uses
+ uPSCompiler, uPSUtils;
+
+{
+ Will register files from:
+ System
+ Classes (Only TComponent and TPersistent)
+
+}
+
+procedure SIRegister_Std_TypesAndConsts(Cl: TPSPascalCompiler);
+procedure SIRegisterTObject(CL: TPSPascalCompiler);
+procedure SIRegisterTPersistent(Cl: TPSPascalCompiler);
+procedure SIRegisterTComponent(Cl: TPSPascalCompiler);
+
+procedure SIRegister_Std(Cl: TPSPascalCompiler);
+
+implementation
+
+procedure SIRegisterTObject(CL: TPSPascalCompiler);
+begin
+ with Cl.AddClassN(nil, 'TObject') do
+ begin
+ RegisterMethod('constructor Create');
+ RegisterMethod('procedure Free');
+ end;
+end;
+
+procedure SIRegisterTPersistent(Cl: TPSPascalCompiler);
+begin
+ with Cl.AddClassN(cl.FindClass('TObject'), 'TPersistent') do
+ begin
+ RegisterMethod('procedure Assign(Source: TPersistent)');
+ end;
+end;
+
+procedure SIRegisterTComponent(Cl: TPSPascalCompiler);
+begin
+ with Cl.AddClassN(cl.FindClass('TPersistent'), 'TComponent') do
+ begin
+ RegisterMethod('function FindComponent(AName: String): TComponent;');
+ RegisterMethod('constructor Create(AOwner: TComponent); virtual;');
+
+ RegisterProperty('Owner', 'TComponent', iptRW);
+ RegisterMethod('procedure DestroyComponents');
+ RegisterMethod('procedure Destroying');
+ RegisterMethod('procedure FreeNotification(AComponent:TComponent)');
+ RegisterMethod('procedure InsertComponent(AComponent:TComponent)');
+ RegisterMethod('procedure RemoveComponent(AComponent:TComponent)');
+ RegisterProperty('Components', 'TComponent Integer', iptr);
+ RegisterProperty('ComponentCount', 'Integer', iptr);
+ RegisterProperty('ComponentIndex', 'Integer', iptrw);
+ RegisterProperty('ComponentState', 'Byte', iptr);
+ RegisterProperty('Designinfo', 'LongInt', iptrw);
+ RegisterProperty('Name', 'String', iptrw);
+ RegisterProperty('Tag', 'LongInt', iptrw);
+ end;
+end;
+
+
+
+
+procedure SIRegister_Std_TypesAndConsts(Cl: TPSPascalCompiler);
+begin
+ Cl.AddTypeS('TComponentStateE', '(csLoading, csReading, csWriting, csDestroying, csDesigning, csAncestor, csUpdating, csFixups, csFreeNotification, csInline, csDesignInstance)');
+ cl.AddTypeS('TComponentState', 'set of TComponentStateE');
+ Cl.AddTypeS('TRect', 'record Left, Top, Right, Bottom: Integer; end;');
+end;
+
+procedure SIRegister_Std(Cl: TPSPascalCompiler);
+begin
+ SIRegister_Std_TypesAndConsts(Cl);
+ SIRegisterTObject(CL);
+ SIRegisterTPersistent(Cl);
+ SIRegisterTComponent(Cl);
+end;
+
+// PS_MINIVCL changes by Martijn Laan (mlaan at wintax _dot_ nl)
+
+
+End.
+
+
diff --git a/branches/script-component/Units/PascalScript/uPSC_stdctrls.pas b/branches/script-component/Units/PascalScript/uPSC_stdctrls.pas
new file mode 100644
index 0000000..340de77
--- /dev/null
+++ b/branches/script-component/Units/PascalScript/uPSC_stdctrls.pas
@@ -0,0 +1,633 @@
+{ Compiletime STDCtrls support }
+unit uPSC_stdctrls;
+
+{$I PascalScript.inc}
+interface
+uses
+ uPSCompiler, uPSUtils;
+
+{
+ Will register files from:
+ stdctrls
+
+Requires:
+ STD, classes, controls and graphics
+}
+
+procedure SIRegister_StdCtrls_TypesAndConsts(cl: TPSPascalCompiler);
+
+
+
+procedure SIRegisterTCUSTOMGROUPBOX(Cl: TPSPascalCompiler);
+procedure SIRegisterTGROUPBOX(Cl: TPSPascalCompiler);
+procedure SIRegisterTCUSTOMLABEL(Cl: TPSPascalCompiler);
+procedure SIRegisterTLABEL(Cl: TPSPascalCompiler);
+procedure SIRegisterTCUSTOMEDIT(Cl: TPSPascalCompiler);
+procedure SIRegisterTEDIT(Cl: TPSPascalCompiler);
+procedure SIRegisterTCUSTOMMEMO(Cl: TPSPascalCompiler);
+procedure SIRegisterTMEMO(Cl: TPSPascalCompiler);
+procedure SIRegisterTCUSTOMCOMBOBOX(Cl: TPSPascalCompiler);
+procedure SIRegisterTCOMBOBOX(Cl: TPSPascalCompiler);
+procedure SIRegisterTBUTTONCONTROL(Cl: TPSPascalCompiler);
+procedure SIRegisterTBUTTON(Cl: TPSPascalCompiler);
+procedure SIRegisterTCUSTOMCHECKBOX(Cl: TPSPascalCompiler);
+procedure SIRegisterTCHECKBOX(Cl: TPSPascalCompiler);
+procedure SIRegisterTRADIOBUTTON(Cl: TPSPascalCompiler);
+procedure SIRegisterTCUSTOMLISTBOX(Cl: TPSPascalCompiler);
+procedure SIRegisterTLISTBOX(Cl: TPSPascalCompiler);
+procedure SIRegisterTSCROLLBAR(Cl: TPSPascalCompiler);
+
+procedure SIRegister_StdCtrls(cl: TPSPascalCompiler);
+
+
+implementation
+
+procedure SIRegisterTCUSTOMGROUPBOX(Cl: TPSPascalCompiler);
+begin
+ Cl.AddClassN(cl.FindClass('TCUSTOMCONTROL'), 'TCUSTOMGROUPBOX');
+end;
+
+
+procedure SIRegisterTGROUPBOX(Cl: TPSPascalCompiler);
+begin
+ with Cl.AddClassN(cl.FindClass('TCUSTOMGROUPBOX'), 'TGROUPBOX') do
+ begin
+ RegisterProperty('CAPTION', 'String', iptrw);
+ RegisterProperty('COLOR', 'TColor', iptrw);
+ RegisterProperty('FONT', 'TFont', iptrw);
+ RegisterProperty('PARENTCOLOR', 'Boolean', iptrw);
+ RegisterProperty('PARENTFONT', 'Boolean', iptrw);
+ RegisterProperty('ONCLICK', 'TNotifyEvent', iptrw);
+ RegisterProperty('ONDBLCLICK', 'TNotifyEvent', iptrw);
+ RegisterProperty('ONENTER', 'TNotifyEvent', iptrw);
+ RegisterProperty('ONEXIT', 'TNotifyEvent', iptrw);
+
+ {$IFNDEF PS_MINIVCL}
+ RegisterProperty('CTL3D', 'Boolean', iptrw);
+ RegisterProperty('DRAGCURSOR', 'Longint', iptrw);
+ RegisterProperty('DRAGMODE', 'TDragMode', iptrw);
+ RegisterProperty('PARENTCTL3D', 'Boolean', iptrw);
+ RegisterProperty('PARENTSHOWHINT', 'Boolean', iptrw);
+ RegisterProperty('POPUPMENU', 'TPopupMenu', iptrw);
+ RegisterProperty('ONDRAGDROP', 'TDragDropEvent', iptrw);
+ RegisterProperty('ONDRAGOVER', 'TDragOverEvent', iptrw);
+ RegisterProperty('ONENDDRAG', 'TEndDragEvent', iptrw);
+ RegisterProperty('ONMOUSEDOWN', 'TMouseEvent', iptrw);
+ RegisterProperty('ONMOUSEMOVE', 'TMouseMoveEvent', iptrw);
+ RegisterProperty('ONMOUSEUP', 'TMouseEvent', iptrw);
+ RegisterProperty('ONSTARTDRAG', 'TStartDragEvent', iptrw);
+ {$ENDIF}
+ end;
+end;
+
+
+
+
+
+procedure SIRegisterTCUSTOMLABEL(Cl: TPSPascalCompiler);
+begin
+ with Cl.AddClassN(cl.FindClass('TGRAPHICCONTROL'), 'TCUSTOMLABEL') do
+ begin
+ {$IFNDEF PS_MINIVCL}
+{$IFNDEF CLX}
+ RegisterProperty('CANVAS', 'TCANVAS', iptr);
+{$ENDIF}
+ {$ENDIF}
+ end;
+end;
+
+
+procedure SIRegisterTLABEL(Cl: TPSPascalCompiler);
+begin
+ with Cl.AddClassN(cl.FindClass('TCUSTOMLABEL'), 'TLABEL') do
+ begin
+ RegisterProperty('ALIGNMENT', 'TAlignment', iptrw);
+ RegisterProperty('AUTOSIZE', 'Boolean', iptrw);
+ RegisterProperty('CAPTION', 'String', iptrw);
+ RegisterProperty('COLOR', 'TColor', iptrw);
+ RegisterProperty('DRAGCURSOR', 'Longint', iptrw);
+ RegisterProperty('DRAGMODE', 'TDragMode', iptrw);
+ RegisterProperty('FOCUSCONTROL', 'TWinControl', iptrw);
+ RegisterProperty('FONT', 'TFont', iptrw);
+ RegisterProperty('LAYOUT', 'TTextLayout', iptrw);
+ RegisterProperty('PARENTCOLOR', 'Boolean', iptrw);
+ RegisterProperty('PARENTFONT', 'Boolean', iptrw);
+ RegisterProperty('PARENTSHOWHINT', 'Boolean', iptrw);
+ RegisterProperty('SHOWACCELCHAR', 'Boolean', iptrw);
+ RegisterProperty('TRANSPARENT', 'Boolean', iptrw);
+ RegisterProperty('WORDWRAP', 'Boolean', iptrw);
+ RegisterProperty('ONCLICK', 'TNotifyEvent', iptrw);
+ RegisterProperty('ONDBLCLICK', 'TNotifyEvent', iptrw);
+ RegisterProperty('ONDRAGDROP', 'TDragDropEvent', iptrw);
+ RegisterProperty('ONDRAGOVER', 'TDragOverEvent', iptrw);
+ RegisterProperty('ONENDDRAG', 'TEndDragEvent', iptrw);
+ RegisterProperty('ONMOUSEDOWN', 'TMouseEvent', iptrw);
+ RegisterProperty('ONMOUSEMOVE', 'TMouseMoveEvent', iptrw);
+ RegisterProperty('ONMOUSEUP', 'TMouseEvent', iptrw);
+ RegisterProperty('ONSTARTDRAG', 'TStartDragEvent', iptrw);
+ end;
+end;
+
+
+
+
+
+
+
+procedure SIRegisterTCUSTOMEDIT(Cl: TPSPascalCompiler);
+begin
+ with Cl.AddClassN(cl.FindClass('TWINCONTROL'), 'TCUSTOMEDIT') do
+ begin
+ RegisterMethod('procedure CLEAR');
+ RegisterMethod('procedure CLEARSELECTION');
+ RegisterMethod('procedure SELECTALL');
+ RegisterProperty('MODIFIED', 'BOOLEAN', iptrw);
+ RegisterProperty('SELLENGTH', 'INTEGER', iptrw);
+ RegisterProperty('SELSTART', 'INTEGER', iptrw);
+ RegisterProperty('SELTEXT', 'String', iptrw);
+ RegisterProperty('TEXT', 'String', iptrw);
+
+ {$IFNDEF PS_MINIVCL}
+ RegisterMethod('procedure COPYTOCLIPBOARD');
+ RegisterMethod('procedure CUTTOCLIPBOARD');
+ RegisterMethod('procedure PASTEFROMCLIPBOARD');
+ RegisterMethod('function GETSELTEXTBUF(BUFFER:PCHAR;BUFSIZE:INTEGER):INTEGER');
+ RegisterMethod('procedure SETSELTEXTBUF(BUFFER:PCHAR)');
+ {$ENDIF}
+ end;
+end;
+
+
+
+
+procedure SIRegisterTEDIT(Cl: TPSPascalCompiler);
+begin
+ with Cl.AddClassN(cl.FindClass('TCUSTOMEDIT'), 'TEDIT') do
+ begin
+ RegisterProperty('AUTOSELECT', 'Boolean', iptrw);
+ RegisterProperty('AUTOSIZE', 'Boolean', iptrw);
+ RegisterProperty('BORDERSTYLE', 'TBorderStyle', iptrw);
+ RegisterProperty('CHARCASE', 'TEditCharCase', iptrw);
+ RegisterProperty('COLOR', 'TColor', iptrw);
+ RegisterProperty('FONT', 'TFont', iptrw);
+ RegisterProperty('HIDESELECTION', 'Boolean', iptrw);
+ RegisterProperty('MAXLENGTH', 'Integer', iptrw);
+ RegisterProperty('PARENTCOLOR', 'Boolean', iptrw);
+ RegisterProperty('PARENTFONT', 'Boolean', iptrw);
+ RegisterProperty('PASSWORDCHAR', 'Char', iptrw);
+ RegisterProperty('READONLY', 'Boolean', iptrw);
+ RegisterProperty('TEXT', 'String', iptrw);
+ RegisterProperty('ONCHANGE', 'TNotifyEvent', iptrw);
+ RegisterProperty('ONCLICK', 'TNotifyEvent', iptrw);
+ RegisterProperty('ONDBLCLICK', 'TNotifyEvent', iptrw);
+ RegisterProperty('ONENTER', 'TNotifyEvent', iptrw);
+ RegisterProperty('ONEXIT', 'TNotifyEvent', iptrw);
+ RegisterProperty('ONKEYDOWN', 'TKeyEvent', iptrw);
+ RegisterProperty('ONKEYPRESS', 'TKeyPressEvent', iptrw);
+ RegisterProperty('ONKEYUP', 'TKeyEvent', iptrw);
+
+ {$IFNDEF PS_MINIVCL}
+ RegisterProperty('CTL3D', 'Boolean', iptrw);
+ RegisterProperty('DRAGCURSOR', 'Longint', iptrw);
+ RegisterProperty('DRAGMODE', 'TDragMode', iptrw);
+ RegisterProperty('OEMCONVERT', 'Boolean', iptrw);
+ RegisterProperty('PARENTCTL3D', 'Boolean', iptrw);
+ RegisterProperty('PARENTSHOWHINT', 'Boolean', iptrw);
+ RegisterProperty('POPUPMENU', 'TPopupMenu', iptrw);
+ RegisterProperty('ONDRAGDROP', 'TDragDropEvent', iptrw);
+ RegisterProperty('ONDRAGOVER', 'TDragOverEvent', iptrw);
+ RegisterProperty('ONENDDRAG', 'TEndDragEvent', iptrw);
+ RegisterProperty('ONMOUSEDOWN', 'TMouseEvent', iptrw);
+ RegisterProperty('ONMOUSEMOVE', 'TMouseMoveEvent', iptrw);
+ RegisterProperty('ONMOUSEUP', 'TMouseEvent', iptrw);
+ RegisterProperty('ONSTARTDRAG', 'TStartDragEvent', iptrw);
+ {$ENDIF}
+ end;
+end;
+
+
+
+
+procedure SIRegisterTCUSTOMMEMO(Cl: TPSPascalCompiler);
+begin
+ with Cl.AddClassN(cl.FindClass('TCUSTOMEDIT'), 'TCUSTOMMEMO') do
+ begin
+ {$IFNDEF CLX}
+ RegisterProperty('LINES', 'TSTRINGS', iptrw);
+ {$ENDIF}
+ end;
+end;
+
+
+procedure SIRegisterTMEMO(Cl: TPSPascalCompiler);
+begin
+ with Cl.AddClassN(cl.FindClass('TCUSTOMMEMO'), 'TMEMO') do
+ begin
+ {$IFDEF CLX}
+ RegisterProperty('LINES', 'TSTRINGS', iptrw);
+ {$ENDIF}
+ RegisterProperty('ALIGNMENT', 'TAlignment', iptrw);
+ RegisterProperty('BORDERSTYLE', 'TBorderStyle', iptrw);
+ RegisterProperty('COLOR', 'TColor', iptrw);
+ RegisterProperty('FONT', 'TFont', iptrw);
+ RegisterProperty('HIDESELECTION', 'Boolean', iptrw);
+ RegisterProperty('MAXLENGTH', 'Integer', iptrw);
+ RegisterProperty('PARENTCOLOR', 'Boolean', iptrw);
+ RegisterProperty('PARENTFONT', 'Boolean', iptrw);
+ RegisterProperty('READONLY', 'Boolean', iptrw);
+ RegisterProperty('SCROLLBARS', 'TScrollStyle', iptrw);
+ RegisterProperty('WANTRETURNS', 'Boolean', iptrw);
+ RegisterProperty('WANTTABS', 'Boolean', iptrw);
+ RegisterProperty('WORDWRAP', 'Boolean', iptrw);
+ RegisterProperty('ONCHANGE', 'TNotifyEvent', iptrw);
+ RegisterProperty('ONCLICK', 'TNotifyEvent', iptrw);
+ RegisterProperty('ONDBLCLICK', 'TNotifyEvent', iptrw);
+ RegisterProperty('ONENTER', 'TNotifyEvent', iptrw);
+ RegisterProperty('ONEXIT', 'TNotifyEvent', iptrw);
+ RegisterProperty('ONKEYDOWN', 'TKeyEvent', iptrw);
+ RegisterProperty('ONKEYPRESS', 'TKeyPressEvent', iptrw);
+ RegisterProperty('ONKEYUP', 'TKeyEvent', iptrw);
+
+ {$IFNDEF PS_MINIVCL}
+ RegisterProperty('CTL3D', 'Boolean', iptrw);
+ RegisterProperty('DRAGCURSOR', 'Longint', iptrw);
+ RegisterProperty('DRAGMODE', 'TDragMode', iptrw);
+ RegisterProperty('OEMCONVERT', 'Boolean', iptrw);
+ RegisterProperty('PARENTCTL3D', 'Boolean', iptrw);
+ RegisterProperty('PARENTSHOWHINT', 'Boolean', iptrw);
+ RegisterProperty('POPUPMENU', 'TPopupMenu', iptrw);
+ RegisterProperty('ONDRAGDROP', 'TDragDropEvent', iptrw);
+ RegisterProperty('ONDRAGOVER', 'TDragOverEvent', iptrw);
+ RegisterProperty('ONENDDRAG', 'TEndDragEvent', iptrw);
+ RegisterProperty('ONMOUSEDOWN', 'TMouseEvent', iptrw);
+ RegisterProperty('ONMOUSEMOVE', 'TMouseMoveEvent', iptrw);
+ RegisterProperty('ONMOUSEUP', 'TMouseEvent', iptrw);
+ RegisterProperty('ONSTARTDRAG', 'TStartDragEvent', iptrw);
+ {$ENDIF}
+ end;
+end;
+
+
+
+
+
+procedure SIRegisterTCUSTOMCOMBOBOX(Cl: TPSPascalCompiler);
+begin
+ with Cl.AddClassN(cl.FindClass('TWINCONTROL'), 'TCUSTOMCOMBOBOX') do
+ begin
+ RegisterProperty('DROPPEDDOWN', 'BOOLEAN', iptrw);
+ RegisterProperty('ITEMS', 'TSTRINGS', iptrw);
+ RegisterProperty('ITEMINDEX', 'INTEGER', iptrw);
+
+ {$IFNDEF PS_MINIVCL}
+ RegisterMethod('procedure CLEAR');
+ RegisterMethod('procedure SELECTALL');
+ RegisterProperty('CANVAS', 'TCANVAS', iptr);
+ RegisterProperty('SELLENGTH', 'INTEGER', iptrw);
+ RegisterProperty('SELSTART', 'INTEGER', iptrw);
+ RegisterProperty('SELTEXT', 'String', iptrw);
+ {$ENDIF}
+ end;
+end;
+
+
+procedure SIRegisterTCOMBOBOX(Cl: TPSPascalCompiler);
+begin
+ with Cl.AddClassN(cl.FindClass('TCUSTOMCOMBOBOX'), 'TCOMBOBOX') do
+ begin
+ RegisterProperty('STYLE', 'TComboBoxStyle', iptrw);
+ RegisterProperty('COLOR', 'TColor', iptrw);
+ RegisterProperty('DROPDOWNCOUNT', 'Integer', iptrw);
+ RegisterProperty('FONT', 'TFont', iptrw);
+ RegisterProperty('MAXLENGTH', 'Integer', iptrw);
+ RegisterProperty('PARENTCOLOR', 'Boolean', iptrw);
+ RegisterProperty('PARENTFONT', 'Boolean', iptrw);
+ RegisterProperty('SORTED', 'Boolean', iptrw);
+ RegisterProperty('TEXT', 'String', iptrw);
+ RegisterProperty('ONCHANGE', 'TNotifyEvent', iptrw);
+ RegisterProperty('ONCLICK', 'TNotifyEvent', iptrw);
+ RegisterProperty('ONDBLCLICK', 'TNotifyEvent', iptrw);
+ RegisterProperty('ONDROPDOWN', 'TNotifyEvent', iptrw);
+ RegisterProperty('ONENTER', 'TNotifyEvent', iptrw);
+ RegisterProperty('ONEXIT', 'TNotifyEvent', iptrw);
+ RegisterProperty('ONKEYDOWN', 'TKeyEvent', iptrw);
+ RegisterProperty('ONKEYPRESS', 'TKeyPressEvent', iptrw);
+ RegisterProperty('ONKEYUP', 'TKeyEvent', iptrw);
+
+ {$IFNDEF PS_MINIVCL}
+ RegisterProperty('CTL3D', 'Boolean', iptrw);
+ RegisterProperty('DRAGMODE', 'TDragMode', iptrw);
+ RegisterProperty('DRAGCURSOR', 'Longint', iptrw);
+ RegisterProperty('ITEMHEIGHT', 'Integer', iptrw);
+ RegisterProperty('PARENTCTL3D', 'Boolean', iptrw);
+ RegisterProperty('PARENTSHOWHINT', 'Boolean', iptrw);
+ RegisterProperty('POPUPMENU', 'TPopupMenu', iptrw);
+ RegisterProperty('ONDRAGDROP', 'TDragDropEvent', iptrw);
+ RegisterProperty('ONDRAGOVER', 'TDragOverEvent', iptrw);
+ RegisterProperty('ONDRAWITEM', 'TDrawItemEvent', iptrw);
+ RegisterProperty('ONENDDRAG', 'TEndDragEvent', iptrw);
+ RegisterProperty('ONMEASUREITEM', 'TMeasureItemEvent', iptrw);
+ RegisterProperty('ONSTARTDRAG', 'TStartDragEvent', iptrw);
+ {$ENDIF}
+ end;
+end;
+
+
+
+procedure SIRegisterTBUTTONCONTROL(Cl: TPSPascalCompiler);
+begin
+ with Cl.AddClassN(cl.FindClass('TWINCONTROL'), 'TBUTTONCONTROL') do
+ begin
+ end;
+end;
+
+
+
+procedure SIRegisterTBUTTON(Cl: TPSPascalCompiler);
+begin
+ with Cl.AddClassN(cl.FindClass('TBUTTONCONTROL'), 'TBUTTON') do
+ begin
+ RegisterProperty('CANCEL', 'BOOLEAN', iptrw);
+ RegisterProperty('CAPTION', 'String', iptrw);
+ RegisterProperty('DEFAULT', 'BOOLEAN', iptrw);
+ RegisterProperty('FONT', 'TFont', iptrw);
+ RegisterProperty('MODALRESULT', 'LONGINT', iptrw);
+ RegisterProperty('PARENTFONT', 'Boolean', iptrw);
+ RegisterProperty('ONCLICK', 'TNotifyEvent', iptrw);
+ RegisterProperty('ONENTER', 'TNotifyEvent', iptrw);
+ RegisterProperty('ONEXIT', 'TNotifyEvent', iptrw);
+
+ {$IFNDEF PS_MINIVCL}
+ RegisterProperty('DRAGCURSOR', 'Longint', iptrw);
+ RegisterProperty('DRAGMODE', 'TDragMode', iptrw);
+ RegisterProperty('PARENTSHOWHINT', 'Boolean', iptrw);
+ RegisterProperty('POPUPMENU', 'TPopupMenu', iptrw);
+ RegisterProperty('ONDRAGDROP', 'TDragDropEvent', iptrw);
+ RegisterProperty('ONDRAGOVER', 'TDragOverEvent', iptrw);
+ RegisterProperty('ONENDDRAG', 'TEndDragEvent', iptrw);
+ RegisterProperty('ONKEYDOWN', 'TKeyEvent', iptrw);
+ RegisterProperty('ONKEYPRESS', 'TKeyPressEvent', iptrw);
+ RegisterProperty('ONKEYUP', 'TKeyEvent', iptrw);
+ RegisterProperty('ONMOUSEDOWN', 'TMouseEvent', iptrw);
+ RegisterProperty('ONMOUSEMOVE', 'TMouseMoveEvent', iptrw);
+ RegisterProperty('ONMOUSEUP', 'TMouseEvent', iptrw);
+ RegisterProperty('ONSTARTDRAG', 'TStartDragEvent', iptrw);
+ {$ENDIF}
+ end;
+end;
+
+
+
+procedure SIRegisterTCUSTOMCHECKBOX(Cl: TPSPascalCompiler);
+begin
+ with Cl.AddClassN(cl.FindClass('TBUTTONCONTROL'), 'TCUSTOMCHECKBOX') do
+ begin
+ end;
+end;
+
+
+
+procedure SIRegisterTCHECKBOX(Cl: TPSPascalCompiler);
+begin
+ with Cl.AddClassN(cl.FindClass('TCUSTOMCHECKBOX'), 'TCHECKBOX') do
+ begin
+ RegisterProperty('ALIGNMENT', 'TAlignment', iptrw);
+ RegisterProperty('ALLOWGRAYED', 'Boolean', iptrw);
+ RegisterProperty('CAPTION', 'String', iptrw);
+ RegisterProperty('CHECKED', 'Boolean', iptrw);
+ RegisterProperty('COLOR', 'TColor', iptrw);
+ RegisterProperty('FONT', 'TFont', iptrw);
+ RegisterProperty('PARENTCOLOR', 'Boolean', iptrw);
+ RegisterProperty('PARENTFONT', 'Boolean', iptrw);
+ RegisterProperty('STATE', 'TCheckBoxState', iptrw);
+ RegisterProperty('ONCLICK', 'TNotifyEvent', iptrw);
+ RegisterProperty('ONENTER', 'TNotifyEvent', iptrw);
+ RegisterProperty('ONEXIT', 'TNotifyEvent', iptrw);
+
+ {$IFNDEF PS_MINIVCL}
+ RegisterProperty('CTL3D', 'Boolean', iptrw);
+ RegisterProperty('DRAGCURSOR', 'Longint', iptrw);
+ RegisterProperty('DRAGMODE', 'TDragMode', iptrw);
+ RegisterProperty('PARENTCTL3D', 'Boolean', iptrw);
+ RegisterProperty('PARENTSHOWHINT', 'Boolean', iptrw);
+ RegisterProperty('POPUPMENU', 'TPopupMenu', iptrw);
+ RegisterProperty('ONDRAGDROP', 'TDragDropEvent', iptrw);
+ RegisterProperty('ONDRAGOVER', 'TDragOverEvent', iptrw);
+ RegisterProperty('ONENDDRAG', 'TEndDragEvent', iptrw);
+ RegisterProperty('ONKEYDOWN', 'TKeyEvent', iptrw);
+ RegisterProperty('ONKEYPRESS', 'TKeyPressEvent', iptrw);
+ RegisterProperty('ONKEYUP', 'TKeyEvent', iptrw);
+ RegisterProperty('ONMOUSEDOWN', 'TMouseEvent', iptrw);
+ RegisterProperty('ONMOUSEMOVE', 'TMouseMoveEvent', iptrw);
+ RegisterProperty('ONMOUSEUP', 'TMouseEvent', iptrw);
+ RegisterProperty('ONSTARTDRAG', 'TStartDragEvent', iptrw);
+ {$ENDIF}
+ end;
+end;
+
+
+
+
+
+procedure SIRegisterTRADIOBUTTON(Cl: TPSPascalCompiler);
+begin
+ with Cl.AddClassN(cl.FindClass('TBUTTONCONTROL'), 'TRADIOBUTTON') do
+ begin
+ RegisterProperty('ALIGNMENT', 'TALIGNMENT', iptrw);
+ RegisterProperty('CAPTION', 'String', iptrw);
+ RegisterProperty('CHECKED', 'BOOLEAN', iptrw);
+ RegisterProperty('COLOR', 'TColor', iptrw);
+ RegisterProperty('FONT', 'TFont', iptrw);
+ RegisterProperty('PARENTCOLOR', 'Boolean', iptrw);
+ RegisterProperty('PARENTFONT', 'Boolean', iptrw);
+ RegisterProperty('ONCLICK', 'TNotifyEvent', iptrw);
+ RegisterProperty('ONDBLCLICK', 'TNotifyEvent', iptrw);
+ RegisterProperty('ONENTER', 'TNotifyEvent', iptrw);
+ RegisterProperty('ONEXIT', 'TNotifyEvent', iptrw);
+
+ {$IFNDEF PS_MINIVCL}
+ RegisterProperty('CTL3D', 'Boolean', iptrw);
+ RegisterProperty('DRAGCURSOR', 'Longint', iptrw);
+ RegisterProperty('DRAGMODE', 'TDragMode', iptrw);
+ RegisterProperty('PARENTCTL3D', 'Boolean', iptrw);
+ RegisterProperty('PARENTSHOWHINT', 'Boolean', iptrw);
+ RegisterProperty('POPUPMENU', 'TPopupMenu', iptrw);
+ RegisterProperty('ONDRAGDROP', 'TDragDropEvent', iptrw);
+ RegisterProperty('ONDRAGOVER', 'TDragOverEvent', iptrw);
+ RegisterProperty('ONENDDRAG', 'TEndDragEvent', iptrw);
+ RegisterProperty('ONKEYDOWN', 'TKeyEvent', iptrw);
+ RegisterProperty('ONKEYPRESS', 'TKeyPressEvent', iptrw);
+ RegisterProperty('ONKEYUP', 'TKeyEvent', iptrw);
+ RegisterProperty('ONMOUSEDOWN', 'TMouseEvent', iptrw);
+ RegisterProperty('ONMOUSEMOVE', 'TMouseMoveEvent', iptrw);
+ RegisterProperty('ONMOUSEUP', 'TMouseEvent', iptrw);
+ RegisterProperty('ONSTARTDRAG', 'TStartDragEvent', iptrw);
+ {$ENDIF}
+ end;
+end;
+
+
+
+procedure SIRegisterTCUSTOMLISTBOX(Cl: TPSPascalCompiler);
+begin
+ with Cl.AddClassN(cl.FindClass('TWINCONTROL'), 'TCUSTOMLISTBOX') do
+ begin
+ RegisterProperty('ITEMS', 'TSTRINGS', iptrw);
+ RegisterProperty('ITEMINDEX', 'INTEGER', iptrw);
+ RegisterProperty('SELCOUNT', 'INTEGER', iptr);
+ RegisterProperty('SELECTED', 'BOOLEAN INTEGER', iptrw);
+
+ {$IFNDEF PS_MINIVCL}
+ RegisterMethod('procedure CLEAR');
+ RegisterMethod('function ITEMATPOS(POS:TPOINT;EXISTING:BOOLEAN):INTEGER');
+ RegisterMethod('function ITEMRECT(INDEX:INTEGER):TRECT');
+ RegisterProperty('CANVAS', 'TCANVAS', iptr);
+ RegisterProperty('TOPINDEX', 'INTEGER', iptrw);
+ {$ENDIF}
+ end;
+end;
+
+
+
+procedure SIRegisterTLISTBOX(Cl: TPSPascalCompiler);
+begin
+ with Cl.AddClassN(cl.FindClass('TCUSTOMLISTBOX'), 'TLISTBOX') do
+ begin
+ RegisterProperty('BORDERSTYLE', 'TBorderStyle', iptrw);
+ RegisterProperty('COLOR', 'TColor', iptrw);
+ RegisterProperty('FONT', 'TFont', iptrw);
+ RegisterProperty('MULTISELECT', 'Boolean', iptrw);
+ RegisterProperty('PARENTCOLOR', 'Boolean', iptrw);
+ RegisterProperty('PARENTFONT', 'Boolean', iptrw);
+ RegisterProperty('SORTED', 'Boolean', iptrw);
+ RegisterProperty('STYLE', 'TListBoxStyle', iptrw);
+ RegisterProperty('ONCLICK', 'TNotifyEvent', iptrw);
+ RegisterProperty('ONDBLCLICK', 'TNotifyEvent', iptrw);
+ RegisterProperty('ONENTER', 'TNotifyEvent', iptrw);
+ RegisterProperty('ONEXIT', 'TNotifyEvent', iptrw);
+ RegisterProperty('ONKEYDOWN', 'TKeyEvent', iptrw);
+ RegisterProperty('ONKEYPRESS', 'TKeyPressEvent', iptrw);
+ RegisterProperty('ONKEYUP', 'TKeyEvent', iptrw);
+
+ {$IFNDEF PS_MINIVCL}
+ RegisterProperty('COLUMNS', 'Integer', iptrw);
+ RegisterProperty('CTL3D', 'Boolean', iptrw);
+ RegisterProperty('DRAGCURSOR', 'Longint', iptrw);
+ RegisterProperty('DRAGMODE', 'TDragMode', iptrw);
+ RegisterProperty('EXTENDEDSELECT', 'Boolean', iptrw);
+ RegisterProperty('INTEGRALHEIGHT', 'Boolean', iptrw);
+ RegisterProperty('ITEMHEIGHT', 'Integer', iptrw);
+ RegisterProperty('PARENTCTL3D', 'Boolean', iptrw);
+ RegisterProperty('PARENTSHOWHINT', 'Boolean', iptrw);
+ RegisterProperty('POPUPMENU', 'TPopupMenu', iptrw);
+ RegisterProperty('TABWIDTH', 'Integer', iptrw);
+ RegisterProperty('ONDRAGDROP', 'TDragDropEvent', iptrw);
+ RegisterProperty('ONDRAGOVER', 'TDragOverEvent', iptrw);
+ RegisterProperty('ONDRAWITEM', 'TDrawItemEvent', iptrw);
+ RegisterProperty('ONENDDRAG', 'TEndDragEvent', iptrw);
+ RegisterProperty('ONMEASUREITEM', 'TMeasureItemEvent', iptrw);
+ RegisterProperty('ONMOUSEDOWN', 'TMouseEvent', iptrw);
+ RegisterProperty('ONMOUSEMOVE', 'TMouseMoveEvent', iptrw);
+ RegisterProperty('ONMOUSEUP', 'TMouseEvent', iptrw);
+ RegisterProperty('ONSTARTDRAG', 'TStartDragEvent', iptrw);
+ {$ENDIF}
+ end;
+end;
+
+
+
+
+
+
+procedure SIRegisterTSCROLLBAR(Cl: TPSPascalCompiler);
+begin
+ with Cl.AddClassN(cl.FindClass('TWINCONTROL'), 'TSCROLLBAR') do
+ begin
+ RegisterProperty('KIND', 'TSCROLLBARKIND', iptrw);
+ RegisterProperty('MAX', 'INTEGER', iptrw);
+ RegisterProperty('MIN', 'INTEGER', iptrw);
+ RegisterProperty('POSITION', 'INTEGER', iptrw);
+ RegisterProperty('ONCHANGE', 'TNOTIFYEVENT', iptrw);
+ RegisterProperty('ONENTER', 'TNotifyEvent', iptrw);
+ RegisterProperty('ONEXIT', 'TNotifyEvent', iptrw);
+
+ {$IFNDEF PS_MINIVCL}
+ RegisterMethod('procedure SETPARAMS(APOSITION,AMIN,AMAX:INTEGER)');
+ RegisterProperty('CTL3D', 'Boolean', iptrw);
+ RegisterProperty('DRAGCURSOR', 'Longint', iptrw);
+ RegisterProperty('DRAGMODE', 'TDragMode', iptrw);
+ RegisterProperty('LARGECHANGE', 'TSCROLLBARINC', iptrw);
+ RegisterProperty('PARENTCTL3D', 'Boolean', iptrw);
+ RegisterProperty('PARENTSHOWHINT', 'Boolean', iptrw);
+ RegisterProperty('POPUPMENU', 'TPopupMenu', iptrw);
+ RegisterProperty('SMALLCHANGE', 'TSCROLLBARINC', iptrw);
+ RegisterProperty('ONDRAGDROP', 'TDragDropEvent', iptrw);
+ RegisterProperty('ONDRAGOVER', 'TDragOverEvent', iptrw);
+ RegisterProperty('ONENDDRAG', 'TEndDragEvent', iptrw);
+ RegisterProperty('ONKEYDOWN', 'TKeyEvent', iptrw);
+ RegisterProperty('ONKEYPRESS', 'TKeyPressEvent', iptrw);
+ RegisterProperty('ONKEYUP', 'TKeyEvent', iptrw);
+ RegisterProperty('ONSCROLL', 'TSCROLLEVENT', iptrw);
+ RegisterProperty('ONSTARTDRAG', 'TStartDragEvent', iptrw);
+ {$ENDIF}
+ end;
+end;
+
+
+
+procedure SIRegister_StdCtrls_TypesAndConsts(cl: TPSPascalCompiler);
+begin
+ cl.AddTypeS('TEditCharCase', '(ecNormal, ecUpperCase, ecLowerCase)');
+ cl.AddTypeS('TScrollStyle', '(ssNone, ssHorizontal, ssVertical, ssBoth)');
+ cl.AddTypeS('TComboBoxStyle', '(csDropDown, csSimple, csDropDownList, csOwnerDrawFixed, csOwnerDrawVariable)');
+ cl.AddTypeS('TDrawItemEvent', 'procedure(Control: TWinControl; Index: Integer; Rect: TRect; State: Byte)');
+ cl.AddTypeS('TMeasureItemEvent', 'procedure(Control: TWinControl; Index: Integer; var Height: Integer)');
+ cl.AddTypeS('TCheckBoxState', '(cbUnchecked, cbChecked, cbGrayed)');
+ cl.AddTypeS('TListBoxStyle', '(lbStandard, lbOwnerDrawFixed, lbOwnerDrawVariable)');
+ cl.AddTypeS('TScrollCode', '(scLineUp, scLineDown, scPageUp, scPageDown, scPosition, scTrack, scTop, scBottom, scEndScroll)');
+ cl.AddTypeS('TScrollEvent', 'procedure(Sender: TObject; ScrollCode: TScrollCode;var ScrollPos: Integer)');
+
+ Cl.addTypeS('TEOwnerDrawState', '(odSelected, odGrayed, odDisabled, odChecked,'
+ +' odFocused, odDefault, odHotLight, odInactive, odNoAccel, odNoFocusRect,'
+ +' odReserved1, odReserved2, odComboBoxEdit)');
+ cl.AddTypeS('TTextLayout', '( tlTop, tlCenter, tlBottom )');
+ cl.AddTypeS('TOwnerDrawState', 'set of TEOwnerDrawState');
+end;
+
+
+procedure SIRegister_stdctrls(cl: TPSPascalCompiler);
+begin
+ SIRegister_StdCtrls_TypesAndConsts(cl);
+ {$IFNDEF PS_MINIVCL}
+ SIRegisterTCUSTOMGROUPBOX(Cl);
+ SIRegisterTGROUPBOX(Cl);
+ {$ENDIF}
+ SIRegisterTCUSTOMLABEL(Cl);
+ SIRegisterTLABEL(Cl);
+ SIRegisterTCUSTOMEDIT(Cl);
+ SIRegisterTEDIT(Cl);
+ SIRegisterTCUSTOMMEMO(Cl);
+ SIRegisterTMEMO(Cl);
+ SIRegisterTCUSTOMCOMBOBOX(Cl);
+ SIRegisterTCOMBOBOX(Cl);
+ SIRegisterTBUTTONCONTROL(Cl);
+ SIRegisterTBUTTON(Cl);
+ SIRegisterTCUSTOMCHECKBOX(Cl);
+ SIRegisterTCHECKBOX(Cl);
+ SIRegisterTRADIOBUTTON(Cl);
+ SIRegisterTCUSTOMLISTBOX(Cl);
+ SIRegisterTLISTBOX(Cl);
+ {$IFNDEF PS_MINIVCL}
+ SIRegisterTSCROLLBAR(Cl);
+ {$ENDIF}
+end;
+
+// PS_MINIVCL changes by Martijn Laan (mlaan at wintax _dot_ nl)
+
+
+end.
+
+
+
+
+
diff --git a/branches/script-component/Units/PascalScript/uPSCompiler.pas b/branches/script-component/Units/PascalScript/uPSCompiler.pas
new file mode 100644
index 0000000..4ec5d8e
--- /dev/null
+++ b/branches/script-component/Units/PascalScript/uPSCompiler.pas
@@ -0,0 +1,15674 @@
+unit uPSCompiler;
+{$I PascalScript.inc}
+interface
+uses
+ {$IFNDEF DELPHI3UP}{$IFNDEF PS_NOINTERFACES}{$IFNDEF LINUX}Windows, Ole2,{$ENDIF}
+ {$ENDIF}{$ENDIF}SysUtils, uPSUtils;
+
+
+type
+{$IFNDEF PS_NOINTERFACES}
+ TPSInterface = class;
+{$ENDIF}
+
+ TPSParameterMode = (pmIn, pmOut, pmInOut);
+ TPSPascalCompiler = class;
+ TPSType = class;
+ TPSValue = class;
+ TPSParameters = class;
+
+ TPSSubOptType = (tMainBegin, tProcBegin, tSubBegin, tOneLiner, tifOneliner, tRepeat, tTry, tTryEnd
+ {$IFDEF PS_USESSUPPORT},tUnitInit, tUnitFinish {$ENDIF}); //nvds
+
+
+ {TPSExternalClass is used when external classes need to be called}
+ TPSCompileTimeClass = class;
+ TPSAttributes = class;
+ TPSAttribute = class;
+
+ EPSCompilerException = class(Exception) end;
+
+ TPSParameterDecl = class(TObject)
+ private
+ FName: tbtString;
+ FOrgName: tbtString;
+ FMode: TPSParameterMode;
+ FType: TPSType;
+ {$IFDEF PS_USESSUPPORT}
+ FDeclareUnit: tbtString;
+ {$ENDIF}
+ FDeclarePos: Cardinal;
+ FDeclareRow: Cardinal;
+ FDeclareCol: Cardinal;
+ procedure SetName(const s: tbtString);
+ public
+
+ property Name: tbtString read FName;
+
+ property OrgName: tbtString read FOrgName write SetName;
+
+ property aType: TPSType read FType write FType;
+
+ property Mode: TPSParameterMode read FMode write FMode;
+
+ {$IFDEF PS_USESSUPPORT}
+ property DeclareUnit: tbtString read FDeclareUnit write FDeclareUnit;
+ {$ENDIF}
+
+ property DeclarePos: Cardinal read FDeclarePos write FDeclarePos;
+
+ property DeclareRow: Cardinal read FDeclareRow write FDeclareRow;
+
+ property DeclareCol: Cardinal read FDeclareCol write FDeclareCol;
+
+ end;
+
+
+ TPSParametersDecl = class(TObject)
+ private
+ FParams: TPSList;
+ FResult: TPSType;
+ function GetParam(I: Longint): TPSParameterDecl;
+ function GetParamCount: Longint;
+ public
+
+ property Params[I: Longint]: TPSParameterDecl read GetParam;
+
+ property ParamCount: Longint read GetParamCount;
+
+
+ function AddParam: TPSParameterDecl;
+
+ procedure DeleteParam(I: Longint);
+
+
+ property Result : TPSType read FResult write FResult;
+
+
+ procedure Assign(Params: TPSParametersDecl);
+
+
+ function Same(d: TPSParametersDecl): boolean;
+
+
+ constructor Create;
+
+ destructor Destroy; override;
+ end;
+
+
+ TPSRegProc = class(TObject)
+ private
+ FNameHash: Longint;
+ FName: tbtString;
+ FDecl: TPSParametersDecl;
+ FExportName: Boolean;
+ FImportDecl: tbtString;
+ FOrgName: tbtString;
+ procedure SetName(const Value: tbtString);
+ public
+
+ property OrgName: tbtString read FOrgName write FOrgName;
+
+ property Name: tbtString read FName write SetName;
+
+ property NameHash: Longint read FNameHash;
+
+ property Decl: TPSParametersDecl read FDecl;
+
+ property ExportName: Boolean read FExportName write FExportName;
+
+ property ImportDecl: tbtString read FImportDecl write FImportDecl;
+
+
+ constructor Create;
+
+ destructor Destroy; override;
+ end;
+
+ PIFPSRegProc = TPSRegProc;
+
+ PIfRVariant = ^TIfRVariant;
+
+ TIfRVariant = record
+
+ FType: TPSType;
+ case Byte of
+ 1: (tu8: TbtU8);
+ 2: (tS8: TbtS8);
+ 3: (tu16: TbtU16);
+ 4: (ts16: TbtS16);
+ 5: (tu32: TbtU32);
+ 6: (ts32: TbtS32);
+ 7: (tsingle: TbtSingle);
+ 8: (tdouble: TbtDouble);
+ 9: (textended: TbtExtended);
+ 11: (tcurrency: tbtCurrency);
+ 10: (tstring: Pointer);
+ {$IFNDEF PS_NOINT64}
+ 17: (ts64: Tbts64);
+ {$ENDIF}
+ 19: (tchar: tbtChar);
+ {$IFNDEF PS_NOWIDESTRING}
+ 18: (twidestring: Pointer);
+ 20: (twidechar: tbtwidechar);
+ {$ENDIF}
+ 21: (ttype: TPSType);
+ 22: (tunistring: Pointer);
+ end;
+
+ TPSRecordFieldTypeDef = class(TObject)
+ private
+ FFieldOrgName: tbtString;
+ FFieldName: tbtString;
+ FFieldNameHash: Longint;
+ FType: TPSType;
+ procedure SetFieldOrgName(const Value: tbtString);
+ public
+
+ property FieldOrgName: tbtString read FFieldOrgName write SetFieldOrgName;
+
+ property FieldName: tbtString read FFieldName;
+
+ property FieldNameHash: Longint read FFieldNameHash;
+
+ property aType: TPSType read FType write FType;
+ end;
+
+ PIFPSRecordFieldTypeDef = TPSRecordFieldTypeDef;
+
+ TPSType = class(TObject)
+ private
+ FNameHash: Longint;
+ FName: tbtString;
+ FBaseType: TPSBaseType;
+ {$IFDEF PS_USESSUPPORT}
+ FDeclareUnit: tbtString;
+ {$ENDIF}
+ FDeclarePos: Cardinal;
+ FDeclareRow: Cardinal;
+ FDeclareCol: Cardinal;
+ FUsed: Boolean;
+ FExportName: Boolean;
+ FOriginalName: tbtString;
+ FAttributes: TPSAttributes;
+ FFinalTypeNo: cardinal;
+ procedure SetName(const Value: tbtString);
+ public
+
+ constructor Create;
+
+ destructor Destroy; override;
+
+ property Attributes: TPSAttributes read FAttributes;
+
+
+ property FinalTypeNo: cardinal read FFinalTypeNo;
+
+
+ property OriginalName: tbtString read FOriginalName write FOriginalName;
+
+ property Name: tbtString read FName write SetName;
+
+ property NameHash: Longint read FNameHash;
+
+ property BaseType: TPSBaseType read FBaseType write FBaseType;
+
+ {$IFDEF PS_USESSUPPORT}
+ property DeclareUnit: tbtString read FDeclareUnit write FDeclareUnit;
+ {$ENDIF}
+
+ property DeclarePos: Cardinal read FDeclarePos write FDeclarePos;
+
+ property DeclareRow: Cardinal read FDeclareRow write FDeclareRow;
+
+ property DeclareCol: Cardinal read FDeclareCol write FDeclareCol;
+
+ property Used: Boolean read FUsed;
+
+ property ExportName: Boolean read FExportName write FExportName;
+
+ procedure Use;
+ end;
+
+
+ PIFPSType = TPSType;
+
+ TPSVariantType = class(TPSType)
+ private
+ public
+ function GetDynInvokeProcNo(Owner: TPSPascalCompiler; const Name: tbtString; Params: TPSParameters): Cardinal; virtual;
+ function GetDynIvokeSelfType(Owner: TPSPascalCompiler): TPSType; virtual;
+ function GetDynInvokeParamType(Owner: TPSPascalCompiler): TPSType; virtual;
+ function GetDynIvokeResulType(Owner: TPSPascalCompiler): TPSType; virtual;
+ end;
+
+
+ TPSRecordType = class(TPSType)
+ private
+ FRecordSubVals: TPSList;
+ public
+
+ constructor Create;
+
+ destructor Destroy; override;
+
+ function RecValCount: Longint;
+
+ function RecVal(I: Longint): PIFPSRecordFieldTypeDef;
+
+ function AddRecVal: PIFPSRecordFieldTypeDef;
+ end;
+
+ TPSClassType = class(TPSType)
+ private
+ FCL: TPSCompiletimeClass;
+ public
+
+ property Cl: TPSCompileTimeClass read FCL write FCL;
+ end;
+ TPSExternalClass = class;
+ TPSUndefinedClassType = class(TPSType)
+ private
+ FExtClass: TPSExternalClass;
+ public
+ property ExtClass: TPSExternalClass read FExtClass write FExtClass;
+ end;
+{$IFNDEF PS_NOINTERFACES}
+
+ TPSInterfaceType = class(TPSType)
+ private
+ FIntf: TPSInterface;
+ public
+
+ property Intf: TPSInterface read FIntf write FIntf;
+ end;
+{$ENDIF}
+
+
+ TPSProceduralType = class(TPSType)
+ private
+ FProcDef: TPSParametersDecl;
+ public
+
+ property ProcDef: TPSParametersDecl read FProcDef;
+
+ constructor Create;
+
+ destructor Destroy; override;
+ end;
+
+ TPSArrayType = class(TPSType)
+ private
+ FArrayTypeNo: TPSType;
+ public
+
+ property ArrayTypeNo: TPSType read FArrayTypeNo write FArrayTypeNo;
+ end;
+
+ TPSStaticArrayType = class(TPSArrayType)
+ private
+ FStartOffset: Longint;
+ FLength: Cardinal;
+ public
+
+ property StartOffset: Longint read FStartOffset write FStartOffset;
+
+ property Length: Cardinal read FLength write FLength;
+ end;
+
+ TPSSetType = class(TPSType)
+ private
+ FSetType: TPSType;
+ function GetByteSize: Longint;
+ function GetBitSize: Longint;
+ public
+
+ property SetType: TPSType read FSetType write FSetType;
+
+ property ByteSize: Longint read GetByteSize;
+
+ property BitSize: Longint read GetBitSize;
+ end;
+
+ TPSTypeLink = class(TPSType)
+ private
+ FLinkTypeNo: TPSType;
+ public
+
+ property LinkTypeNo: TPSType read FLinkTypeNo write FLinkTypeNo;
+ end;
+
+ TPSEnumType = class(TPSType)
+ private
+ FHighValue: Cardinal;
+ public
+
+ property HighValue: Cardinal read FHighValue write FHighValue;
+ end;
+
+
+ TPSProcedure = class(TObject)
+ private
+ FAttributes: TPSAttributes;
+ public
+
+ property Attributes: TPSAttributes read FAttributes;
+
+
+ constructor Create;
+
+ destructor Destroy; override;
+ end;
+
+ TPSAttributeType = class;
+
+ TPSAttributeTypeField = class(TObject)
+ private
+ FOwner: TPSAttributeType;
+ FFieldOrgName: tbtString;
+ FFieldName: tbtString;
+ FFieldNameHash: Longint;
+ FFieldType: TPSType;
+ FHidden: Boolean;
+ procedure SetFieldOrgName(const Value: tbtString);
+ public
+
+ constructor Create(AOwner: TPSAttributeType);
+
+ property Owner: TPSAttributeType read FOwner;
+
+ property FieldOrgName: tbtString read FFieldOrgName write SetFieldOrgName;
+
+ property FieldName: tbtString read FFieldName;
+
+ property FieldNameHash: Longint read FFieldNameHash;
+
+ property FieldType: TPSType read FFieldType write FFieldType;
+
+ property Hidden: Boolean read FHidden write FHidden;
+ end;
+
+ TPSApplyAttributeToType = function (Sender: TPSPascalCompiler; aType: TPSType; Attr: TPSAttribute): Boolean;
+
+ TPSApplyAttributeToProc = function (Sender: TPSPascalCompiler; aProc: TPSProcedure; Attr: TPSAttribute): Boolean;
+ { An attribute type }
+ TPSAttributeType = class(TPSType)
+ private
+ FFields: TPSList;
+ FName: tbtString;
+ FOrgname: tbtString;
+ FNameHash: Longint;
+ FAAProc: TPSApplyAttributeToProc;
+ FAAType: TPSApplyAttributeToType;
+ function GetField(I: Longint): TPSAttributeTypeField;
+ function GetFieldCount: Longint;
+ procedure SetName(const s: tbtString);
+ public
+
+ property OnApplyAttributeToType: TPSApplyAttributeToType read FAAType write FAAType;
+
+ property OnApplyAttributeToProc: TPSApplyAttributeToProc read FAAProc write FAAProc;
+
+ property Fields[i: Longint]: TPSAttributeTypeField read GetField;
+
+ property FieldCount: Longint read GetFieldCount;
+
+ procedure DeleteField(I: Longint);
+
+ function AddField: TPSAttributeTypeField;
+
+ property Name: tbtString read FName;
+
+ property OrgName: tbtString read FOrgName write SetName;
+
+ property NameHash: Longint read FNameHash;
+
+ constructor Create;
+
+ destructor Destroy; override;
+ end;
+
+ TPSAttribute = class(TObject)
+ private
+ FAttribType: TPSAttributeType;
+ FValues: TPSList;
+ function GetValueCount: Longint;
+ function GetValue(I: Longint): PIfRVariant;
+ public
+
+ constructor Create(AttribType: TPSAttributeType);
+
+ procedure Assign(Item: TPSAttribute);
+
+ property AType: TPSAttributeType read FAttribType;
+
+ property Count: Longint read GetValueCount;
+
+ property Values[i: Longint]: PIfRVariant read GetValue; default;
+
+ procedure DeleteValue(i: Longint);
+
+ function AddValue(v: PIFRVariant): Longint;
+
+ destructor Destroy; override;
+ end;
+
+
+ TPSAttributes = class(TObject)
+ private
+ FItems: TPSList;
+ function GetCount: Longint;
+ function GetItem(I: Longint): TPSAttribute;
+ public
+
+ procedure Assign(attr: TPSAttributes; Move: Boolean);
+
+ property Count: Longint read GetCount;
+
+ property Items[i: Longint]: TPSAttribute read GetItem; default;
+
+ procedure Delete(i: Longint);
+
+ function Add(AttribType: TPSAttributeType): TPSAttribute;
+
+ function FindAttribute(const Name: tbtString): TPSAttribute;
+
+ constructor Create;
+
+ destructor Destroy; override;
+ end;
+
+
+ TPSProcVar = class(TObject)
+ private
+ FNameHash: Longint;
+ FName: tbtString;
+ FOrgName: tbtString;
+ FType: TPSType;
+ FUsed: Boolean;
+ {$IFDEF PS_USESSUPPORT}
+ FDeclareUnit: tbtString;
+ {$ENDIF}
+ FDeclarePos, FDeclareRow, FDeclareCol: Cardinal;
+ procedure SetName(const Value: tbtString);
+ public
+
+ property OrgName: tbtString read FOrgName write FOrgname;
+
+ property NameHash: Longint read FNameHash;
+
+ property Name: tbtString read FName write SetName;
+
+ property AType: TPSType read FType write FType;
+
+ property Used: Boolean read FUsed;
+
+ {$IFDEF PS_USESSUPPORT}
+ property DeclareUnit: tbtString read FDeclareUnit write FDeclareUnit;
+ {$ENDIF}
+
+ property DeclarePos: Cardinal read FDeclarePos write FDeclarePos;
+
+ property DeclareRow: Cardinal read FDeclareRow write FDeclareRow;
+
+ property DeclareCol: Cardinal read FDeclareCol write FDeclareCol;
+
+ procedure Use;
+ end;
+
+ PIFPSProcVar = TPSProcVar;
+
+ TPSExternalProcedure = class(TPSProcedure)
+ private
+ FRegProc: TPSRegProc;
+ public
+
+ property RegProc: TPSRegProc read FRegProc write FRegProc;
+ end;
+
+
+ TPSInternalProcedure = class(TPSProcedure)
+ private
+ FForwarded: Boolean;
+ FData: tbtString;
+ FNameHash: Longint;
+ FName: tbtString;
+ FDecl: TPSParametersDecl;
+ FProcVars: TPSList;
+ FUsed: Boolean;
+ FOutputDeclPosition: Cardinal;
+ FResultUsed: Boolean;
+ FLabels: TIfStringList;
+ FGotos: TIfStringList;
+ FDeclareRow: Cardinal;
+ {$IFDEF PS_USESSUPPORT}
+ FDeclareUnit: tbtString;
+ {$ENDIF}
+ FDeclarePos: Cardinal;
+ FDeclareCol: Cardinal;
+ FOriginalName: tbtString;
+ procedure SetName(const Value: tbtString);
+ public
+
+ constructor Create;
+
+ destructor Destroy; override;
+ {Attributes}
+
+
+ property Forwarded: Boolean read FForwarded write FForwarded;
+
+ property Data: tbtString read FData write FData;
+
+ property Decl: TPSParametersDecl read FDecl;
+
+ property OriginalName: tbtString read FOriginalName write FOriginalName;
+
+ property Name: tbtString read FName write SetName;
+
+ property NameHash: Longint read FNameHash;
+
+ property ProcVars: TPSList read FProcVars;
+
+ property Used: Boolean read FUsed;
+
+ {$IFDEF PS_USESSUPPORT}
+ property DeclareUnit: tbtString read FDeclareUnit write FDeclareUnit;
+ {$ENDIF}
+
+ property DeclarePos: Cardinal read FDeclarePos write FDeclarePos;
+
+ property DeclareRow: Cardinal read FDeclareRow write FDeclareRow;
+
+ property DeclareCol: Cardinal read FDeclareCol write FDeclareCol;
+
+ property OutputDeclPosition: Cardinal read FOutputDeclPosition write FOutputDeclPosition;
+
+ property ResultUsed: Boolean read FResultUsed;
+
+
+ property Labels: TIfStringList read FLabels;
+
+ property Gotos: TIfStringList read FGotos;
+
+ procedure Use;
+
+ procedure ResultUse;
+ end;
+
+ TPSVar = class(TObject)
+ private
+ FNameHash: Longint;
+ FOrgName: tbtString;
+ FName: tbtString;
+ FType: TPSType;
+ FUsed: Boolean;
+ FExportName: tbtString;
+ FDeclareRow: Cardinal;
+ {$IFDEF PS_USESSUPPORT}
+ FDeclareUnit: tbtString;
+ {$ENDIF}
+ FDeclarePos: Cardinal;
+ FDeclareCol: Cardinal;
+ FSaveAsPointer: Boolean;
+ procedure SetName(const Value: tbtString);
+ public
+
+ property SaveAsPointer: Boolean read FSaveAsPointer write FSaveAsPointer;
+
+ property ExportName: tbtString read FExportName write FExportName;
+
+ property Used: Boolean read FUsed;
+
+ property aType: TPSType read FType write FType;
+
+ property OrgName: tbtString read FOrgName write FOrgName;
+
+ property Name: tbtString read FName write SetName;
+
+ property NameHash: Longint read FNameHash;
+
+ {$IFDEF PS_USESSUPPORT}
+ property DeclareUnit: tbtString read FDeclareUnit write FDeclareUnit;
+ {$ENDIF}
+
+ property DeclarePos: Cardinal read FDeclarePos write FDeclarePos;
+
+ property DeclareRow: Cardinal read FDeclareRow write FDeclareRow;
+
+ property DeclareCol: Cardinal read FDeclareCol write FDeclareCol;
+
+ procedure Use;
+ end;
+
+ PIFPSVar = TPSVar;
+
+ TPSConstant = class(TObject)
+ private
+
+ FOrgName: tbtString;
+
+ FNameHash: Longint;
+
+ FName: tbtString;
+
+ FDeclareRow: Cardinal;
+ {$IFDEF PS_USESSUPPORT}
+ FDeclareUnit: tbtString;
+ {$ENDIF}
+ FDeclarePos: Cardinal;
+ FDeclareCol: Cardinal;
+
+ FValue: PIfRVariant;
+ procedure SetName(const Value: tbtString);
+ public
+
+ property OrgName: tbtString read FOrgName write FOrgName;
+
+ property Name: tbtString read FName write SetName;
+
+ property NameHash: Longint read FNameHash;
+
+ property Value: PIfRVariant read FValue write FValue;
+
+ {$IFDEF PS_USESSUPPORT}
+ property DeclareUnit: tbtString read FDeclareUnit write FDeclareUnit;
+ {$ENDIF}
+
+ property DeclarePos: Cardinal read FDeclarePos write FDeclarePos;
+
+ property DeclareRow: Cardinal read FDeclareRow write FDeclareRow;
+
+ property DeclareCol: Cardinal read FDeclareCol write FDeclareCol;
+
+
+ procedure SetSet(const val);
+
+
+ procedure SetInt(const Val: Longint);
+
+ procedure SetUInt(const Val: Cardinal);
+ {$IFNDEF PS_NOINT64}
+
+ procedure SetInt64(const Val: Int64);
+ {$ENDIF}
+
+ procedure SetString(const Val: tbtString);
+
+ procedure SetChar(c: tbtChar);
+ {$IFNDEF PS_NOWIDESTRING}
+
+ procedure SetWideChar(const val: WideChar);
+
+ procedure SetWideString(const val: tbtwidestring);
+ procedure SetUnicodeString(const val: tbtunicodestring);
+ {$ENDIF}
+
+ procedure SetExtended(const Val: Extended);
+
+
+ destructor Destroy; override;
+ end;
+
+ PIFPSConstant = TPSConstant;
+
+ TPSPascalCompilerErrorType = (
+ ecUnknownIdentifier,
+ ecIdentifierExpected,
+ ecCommentError,
+ ecStringError,
+ ecCharError,
+ ecSyntaxError,
+ ecUnexpectedEndOfFile,
+ ecSemicolonExpected,
+ ecBeginExpected,
+ ecPeriodExpected,
+ ecDuplicateIdentifier,
+ ecColonExpected,
+ ecUnknownType,
+ ecCloseRoundExpected,
+ ecTypeMismatch,
+ ecInternalError,
+ ecAssignmentExpected,
+ ecThenExpected,
+ ecDoExpected,
+ ecNoResult,
+ ecOpenRoundExpected,
+ ecCommaExpected,
+ ecToExpected,
+ ecIsExpected,
+ ecOfExpected,
+ ecCloseBlockExpected,
+ ecVariableExpected,
+ ecStringExpected,
+ ecEndExpected,
+ ecUnSetLabel,
+ ecNotInLoop,
+ ecInvalidJump,
+ ecOpenBlockExpected,
+ ecWriteOnlyProperty,
+ ecReadOnlyProperty,
+ ecClassTypeExpected,
+ ecCustomError,
+ ecDivideByZero,
+ ecMathError,
+ ecUnsatisfiedForward,
+ ecForwardParameterMismatch,
+ ecInvalidnumberOfParameters
+ {$IFDEF PS_USESSUPPORT}
+ , ecNotAllowed,
+ ecUnitNotFoundOrContainsErrors,
+ ecCrossReference
+ {$ENDIF}
+ );
+
+ TPSPascalCompilerHintType = (
+ ehVariableNotUsed,
+ ehFunctionNotUsed,
+ ehCustomHint
+ );
+
+ TPSPascalCompilerWarningType = (
+ ewCalculationAlwaysEvaluatesTo,
+ ewIsNotNeeded,
+ ewAbstractClass,
+ ewCustomWarning
+ );
+
+ TPSPascalCompilerMessage = class(TObject)
+ protected
+
+ FRow: Cardinal;
+
+ FCol: Cardinal;
+
+ FModuleName: tbtString;
+
+ FParam: tbtString;
+
+ FPosition: Cardinal;
+
+ procedure SetParserPos(Parser: TPSPascalParser);
+ public
+
+ property ModuleName: tbtString read FModuleName write FModuleName;
+
+ property Param: tbtString read FParam write FParam;
+
+ property Pos: Cardinal read FPosition write FPosition;
+
+ property Row: Cardinal read FRow write FRow;
+
+ property Col: Cardinal read FCol write FCol;
+
+ function ErrorType: tbtString; virtual; abstract;
+
+ procedure SetCustomPos(Pos, Row, Col: Cardinal);
+
+ function MessageToString: tbtString; virtual;
+
+ function ShortMessageToString: tbtString; virtual; abstract;
+ end;
+
+ TPSPascalCompilerError = class(TPSPascalCompilerMessage)
+ protected
+
+ FError: TPSPascalCompilerErrorType;
+ public
+
+ property Error: TPSPascalCompilerErrorType read FError;
+
+ function ErrorType: tbtString; override;
+ function ShortMessageToString: tbtString; override;
+ end;
+
+ TPSPascalCompilerHint = class(TPSPascalCompilerMessage)
+ protected
+
+ FHint: TPSPascalCompilerHintType;
+ public
+
+ property Hint: TPSPascalCompilerHintType read FHint;
+
+ function ErrorType: tbtString; override;
+ function ShortMessageToString: tbtString; override;
+ end;
+
+ TPSPascalCompilerWarning = class(TPSPascalCompilerMessage)
+ protected
+
+ FWarning: TPSPascalCompilerWarningType;
+ public
+
+ property Warning: TPSPascalCompilerWarningType read FWarning;
+
+ function ErrorType: tbtString; override;
+ function ShortMessageToString: tbtString; override;
+ end;
+ TPSDuplicCheck = set of (dcTypes, dcProcs, dcVars, dcConsts);
+
+ TPSBlockInfo = class(TObject)
+ private
+ FOwner: TPSBlockInfo;
+ FWithList: TPSList;
+ FProcNo: Cardinal;
+ FProc: TPSInternalProcedure;
+ FSubType: TPSSubOptType;
+ public
+
+ property WithList: TPSList read FWithList;
+
+ property ProcNo: Cardinal read FProcNo write FProcNo;
+
+ property Proc: TPSInternalProcedure read FProc write FProc;
+
+ property SubType: TPSSubOptType read FSubType write FSubType;
+
+ procedure Clear;
+
+ constructor Create(Owner: TPSBlockInfo);
+
+ destructor Destroy; override;
+ end;
+
+
+
+ TPSBinOperatorType = (otAdd, otSub, otMul, otDiv, otMod, otShl, otShr, otAnd, otOr, otXor, otAs, otIntDiv,
+ otGreaterEqual, otLessEqual, otGreater, otLess, otEqual,
+ otNotEqual, otIs, otIn);
+
+ TPSUnOperatorType = (otNot, otMinus, otCast);
+
+ TPSOnUseVariable = procedure (Sender: TPSPascalCompiler; VarType: TPSVariableType; VarNo: Longint; ProcNo, Position: Cardinal; const PropData: tbtString);
+
+ TPSOnUses = function(Sender: TPSPascalCompiler; const Name: tbtString): Boolean;
+
+ TPSOnExportCheck = function(Sender: TPSPascalCompiler; Proc: TPSInternalProcedure; const ProcDecl: tbtString): Boolean;
+
+ {$IFNDEF PS_USESSUPPORT}
+ TPSOnWriteLineEvent = function (Sender: TPSPascalCompiler; Position: Cardinal): Boolean;
+ {$ELSE}
+ TPSOnWriteLineEvent = function (Sender: TPSPascalCompiler; FileName: tbtString; Position: Cardinal): Boolean;
+ {$ENDIF}
+
+ TPSOnExternalProc = function (Sender: TPSPascalCompiler; Decl: TPSParametersDecl; const Name, FExternal: tbtString): TPSRegProc;
+
+ TPSOnTranslateLineInfoProc = procedure (Sender: TPSPascalCompiler; var Pos, Row, Col: Cardinal; var Name: tbtString);
+ TPSOnNotify = function (Sender: TPSPascalCompiler): Boolean;
+
+ TPSOnFunction = procedure(name: tbtString; Pos, Row, Col: Integer) of object;
+
+
+ TPSPascalCompiler = class
+ protected
+ FAnyString: TPSType;
+ FUnitName: tbtString;
+ FID: Pointer;
+ FOnExportCheck: TPSOnExportCheck;
+ FDefaultBoolType: TPSType;
+ FRegProcs: TPSList;
+ FConstants: TPSList;
+ FProcs: TPSList;
+ FTypes: TPSList;
+ FAttributeTypes: TPSList;
+ FVars: TPSList;
+ FOutput: tbtString;
+ FParser: TPSPascalParser;
+ FParserHadError: Boolean;
+ FMessages: TPSList;
+ FOnUses: TPSOnUses;
+ FUtf8Decode: Boolean;
+ FIsUnit: Boolean;
+ FAllowNoBegin: Boolean;
+ FAllowNoEnd: Boolean;
+ FAllowUnit: Boolean;
+ FBooleanShortCircuit: Boolean;
+ FDebugOutput: tbtString;
+ FOnExternalProc: TPSOnExternalProc;
+ FOnUseVariable: TPSOnUseVariable;
+ FOnBeforeOutput: TPSOnNotify;
+ FOnBeforeCleanup: TPSOnNotify;
+ FOnWriteLine: TPSOnWriteLineEvent;
+ FContinueOffsets, FBreakOffsets: TPSList;
+ FOnTranslateLineInfo: TPSOnTranslateLineInfoProc;
+ FAutoFreeList: TPSList;
+ FClasses: TPSList;
+ FOnFunctionStart: TPSOnFunction;
+ FOnFunctionEnd: TPSOnFunction;
+
+
+ FWithCount: Integer;
+ FTryCount: Integer;
+ FExceptFinallyCount: Integer;
+
+
+ {$IFDEF PS_USESSUPPORT}
+ FUnitInits : TPSList; //nvds
+ FUnitFinits: TPSList; //nvds
+ FUses : TPSStringList;
+ fUnits : TPSUnitList;
+ fUnit : TPSUnit;
+ fModule : tbtString;
+ {$ENDIF}
+ fInCompile : Integer;
+{$IFNDEF PS_NOINTERFACES}
+ FInterfaces: TPSList;
+{$ENDIF}
+
+ FCurrUsedTypeNo: Cardinal;
+ FGlobalBlock: TPSBlockInfo;
+
+ function IsBoolean(aType: TPSType): Boolean;
+ {$IFNDEF PS_NOWIDESTRING}
+
+ function GetWideString(Src: PIfRVariant; var s: Boolean): tbtwidestring;
+ function GetUnicodeString(Src: PIfRVariant; var s: Boolean): tbtunicodestring;
+ {$ENDIF}
+ function PreCalc(FUseUsedTypes: Boolean; Var1Mod: Byte; var1: PIFRVariant; Var2Mod: Byte;
+ Var2: PIfRVariant; Cmd: TPSBinOperatorType; Pos, Row, Col: Cardinal): Boolean;
+
+ function FindBaseType(BaseType: TPSBaseType): TPSType;
+
+ function IsIntBoolType(aType: TPSType): Boolean;
+ function GetTypeCopyLink(p: TPSType): TPSType;
+
+ function at2ut(p: TPSType): TPSType;
+ procedure UseProc(procdecl: TPSParametersDecl);
+
+
+ function GetMsgCount: Longint;
+
+ function GetMsg(l: Longint): TPSPascalCompilerMessage;
+
+
+ function MakeExportDecl(decl: TPSParametersDecl): tbtString;
+
+
+ procedure DefineStandardTypes;
+
+ procedure DefineStandardProcedures;
+
+ function ReadReal(const s: tbtString): PIfRVariant;
+ function ReadString: PIfRVariant;
+ function ReadInteger(const s: tbtString): PIfRVariant;
+ function ReadAttributes(Dest: TPSAttributes): Boolean;
+ function ReadConstant(FParser: TPSPascalParser; StopOn: TPSPasToken): PIfRVariant;
+
+ function ApplyAttribsToFunction(func: TPSProcedure): boolean;
+ function ProcessFunction(AlwaysForward: Boolean; Att: TPSAttributes): Boolean;
+ function ValidateParameters(BlockInfo: TPSBlockInfo; Params: TPSParameters; ParamTypes: TPSParametersDecl): boolean;
+
+ function IsVarInCompatible(ft1, ft2: TPSType): Boolean;
+ function GetTypeNo(BlockInfo: TPSBlockInfo; p: TPSValue): TPSType;
+ function DoVarBlock(proc: TPSInternalProcedure): Boolean;
+ function DoTypeBlock(FParser: TPSPascalParser): Boolean;
+ function ReadType(const Name: tbtString; FParser: TPSPascalParser): TPSType;
+ function ProcessLabel(Proc: TPSInternalProcedure): Boolean;
+ function ProcessSub(BlockInfo: TPSBlockInfo): Boolean;
+ function ProcessLabelForwards(Proc: TPSInternalProcedure): Boolean;
+
+ procedure WriteDebugData(const s: tbtString);
+
+ procedure Debug_SavePosition(ProcNo: Cardinal; Proc: TPSInternalProcedure);
+
+ procedure Debug_WriteParams(ProcNo: Cardinal; Proc: TPSInternalProcedure);
+
+ procedure Debug_WriteLine(BlockInfo: TPSBlockInfo);
+
+
+ function IsCompatibleType(p1, p2: TPSType; Cast: Boolean): Boolean;
+
+ function IsDuplicate(const s: tbtString; const check: TPSDuplicCheck): Boolean;
+ {$IFDEF PS_USESSUPPORT}
+ function IsInLocalUnitList(s: tbtString): Boolean;
+ {$ENDIF}
+
+ function NewProc(const OriginalName, Name: tbtString): TPSInternalProcedure;
+
+ function AddUsedFunction(var Proc: TPSInternalProcedure): Cardinal;
+
+ function AddUsedFunction2(var Proc: TPSExternalProcedure): Cardinal;
+
+
+ function CheckCompatProc(P: TPSType; ProcNo: Cardinal): Boolean;
+
+
+ procedure ParserError(Parser: TObject; Kind: TPSParserErrorKind);
+
+ function ReadTypeAddProcedure(const Name: tbtString; FParser: TPSPascalParser): TPSType;
+
+ function VarIsDuplicate(Proc: TPSInternalProcedure; const VarNames, s: tbtString): Boolean;
+
+ function IsProcDuplicLabel(Proc: TPSInternalProcedure; const s: tbtString): Boolean;
+
+ procedure CheckForUnusedVars(Func: TPSInternalProcedure);
+ function ProcIsDuplic(Decl: TPSParametersDecl; const FunctionName, FunctionParamNames: tbtString; const s: tbtString; Func: TPSInternalProcedure): Boolean;
+ public
+ function GetConstant(const Name: tbtString): TPSConstant;
+
+ function UseExternalProc(const Name: tbtString): TPSParametersDecl;
+
+ function FindProc(const aName: tbtString): Cardinal;
+
+ function GetTypeCount: Longint;
+
+ function GetType(I: Longint): TPSType;
+
+ function GetVarCount: Longint;
+
+ function GetVar(I: Longint): TPSVar;
+
+ function GetProcCount: Longint;
+
+ function GetProc(I: Longint): TPSProcedure;
+
+ function GetConstCount: Longint;
+
+ function GetConst(I: Longint): TPSConstant;
+
+ function GetRegProcCount: Longint;
+
+ function GetRegProc(I: Longint): TPSRegProc;
+
+ function AddAttributeType: TPSAttributeType;
+ function FindAttributeType(const Name: tbtString): TPSAttributeType;
+
+ procedure AddToFreeList(Obj: TObject);
+
+ property ID: Pointer read FID write FID;
+
+ function MakeError(const Module: tbtString; E: TPSPascalCompilerErrorType; const
+ Param: tbtString): TPSPascalCompilerMessage;
+
+ function MakeWarning(const Module: tbtString; E: TPSPascalCompilerWarningType;
+ const Param: tbtString): TPSPascalCompilerMessage;
+
+ function MakeHint(const Module: tbtString; E: TPSPascalCompilerHintType;
+ const Param: tbtString): TPSPascalCompilerMessage;
+
+{$IFNDEF PS_NOINTERFACES}
+
+ function AddInterface(InheritedFrom: TPSInterface; Guid: TGuid; const Name: tbtString): TPSInterface;
+
+ function FindInterface(const Name: tbtString): TPSInterface;
+
+{$ENDIF}
+ function AddClass(InheritsFrom: TPSCompileTimeClass; aClass: TClass): TPSCompileTimeClass;
+
+ function AddClassN(InheritsFrom: TPSCompileTimeClass; const aClass: tbtString): TPSCompileTimeClass;
+
+
+ function FindClass(const aClass: tbtString): TPSCompileTimeClass;
+
+ function AddFunction(const Header: tbtString): TPSRegProc;
+
+ function AddDelphiFunction(const Decl: tbtString): TPSRegProc;
+
+ function AddType(const Name: tbtString; const BaseType: TPSBaseType): TPSType;
+
+ function AddTypeS(const Name, Decl: tbtString): TPSType;
+
+ function AddTypeCopy(const Name: tbtString; TypeNo: TPSType): TPSType;
+
+ function AddTypeCopyN(const Name, FType: tbtString): TPSType;
+
+ function AddConstant(const Name: tbtString; FType: TPSType): TPSConstant;
+
+ function AddConstantN(const Name, FType: tbtString): TPSConstant;
+
+ function AddVariable(const Name: tbtString; FType: TPSType): TPSVar;
+
+ function AddVariableN(const Name, FType: tbtString): TPSVar;
+
+ function AddUsedVariable(const Name: tbtString; FType: TPSType): TPSVar;
+
+ function AddUsedVariableN(const Name, FType: tbtString): TPSVar;
+
+ function AddUsedPtrVariable(const Name: tbtString; FType: TPSType): TPSVar;
+
+ function AddUsedPtrVariableN(const Name, FType: tbtString): TPSVar;
+
+ function FindType(const Name: tbtString): TPSType;
+
+ function MakeDecl(decl: TPSParametersDecl): tbtString;
+
+ function Compile(const s: tbtString): Boolean;
+
+ function GetOutput(var s: tbtString): Boolean;
+
+ function GetDebugOutput(var s: tbtString): Boolean;
+
+ procedure Clear;
+
+ constructor Create;
+
+ destructor Destroy; override;
+
+ property MsgCount: Longint read GetMsgCount;
+
+ property Msg[l: Longint]: TPSPascalCompilerMessage read GetMsg;
+
+ property OnTranslateLineInfo: TPSOnTranslateLineInfoProc read FOnTranslateLineInfo write FOnTranslateLineInfo;
+
+ property OnUses: TPSOnUses read FOnUses write FOnUses;
+
+ property OnExportCheck: TPSOnExportCheck read FOnExportCheck write FOnExportCheck;
+
+ property OnWriteLine: TPSOnWriteLineEvent read FOnWriteLine write FOnWriteLine;
+
+ property OnExternalProc: TPSOnExternalProc read FOnExternalProc write FOnExternalProc;
+
+ property OnUseVariable: TPSOnUseVariable read FOnUseVariable write FOnUseVariable;
+
+ property OnBeforeOutput: TPSOnNotify read FOnBeforeOutput write FOnBeforeOutput;
+
+ property OnBeforeCleanup: TPSOnNotify read FOnBeforeCleanup write FOnBeforeCleanup;
+
+ property OnFunctionStart: TPSOnFunction read FOnFunctionStart write FOnFunctionStart;
+
+ property OnFunctionEnd: TPSOnFunction read FOnFunctionEnd write FOnFunctionEnd;
+
+ property IsUnit: Boolean read FIsUnit;
+
+ property AllowNoBegin: Boolean read FAllowNoBegin write FAllowNoBegin;
+
+ property AllowUnit: Boolean read FAllowUnit write FAllowUnit;
+
+ property AllowNoEnd: Boolean read FAllowNoEnd write FAllowNoEnd;
+
+
+ property BooleanShortCircuit: Boolean read FBooleanShortCircuit write FBooleanShortCircuit;
+
+ property UTF8Decode: Boolean read FUtf8Decode write FUtf8Decode;
+
+ property UnitName: tbtString read FUnitName;
+ end;
+ TIFPSPascalCompiler = TPSPascalCompiler;
+
+ TPSValue = class(TObject)
+ private
+ FPos, FRow, FCol: Cardinal;
+ public
+
+ property Pos: Cardinal read FPos write FPos;
+
+ property Row: Cardinal read FRow write FRow;
+
+ property Col: Cardinal read FCol write FCol;
+
+ procedure SetParserPos(P: TPSPascalParser);
+
+ end;
+
+ TPSParameter = class(TObject)
+ private
+ FValue: TPSValue;
+ FTempVar: TPSValue;
+ FParamMode: TPSParameterMode;
+ FExpectedType: TPSType;
+ public
+
+ property Val: TPSValue read FValue write FValue;
+
+ property ExpectedType: TPSType read FExpectedType write FExpectedType;
+
+ property TempVar: TPSValue read FTempVar write FTempVar;
+
+ property ParamMode: TPSParameterMode read FParamMode write FParamMode;
+
+ destructor Destroy; override;
+ end;
+
+ TPSParameters = class(TObject)
+ private
+ FItems: TPSList;
+ function GetCount: Cardinal;
+ function GetItem(I: Longint): TPSParameter;
+ public
+
+ constructor Create;
+
+ destructor Destroy; override;
+
+ property Count: Cardinal read GetCount;
+
+ property Item[I: Longint]: TPSParameter read GetItem; default;
+
+ procedure Delete(I: Cardinal);
+
+ function Add: TPSParameter;
+ end;
+
+ TPSSubItem = class(TObject)
+ private
+ FType: TPSType;
+ public
+
+ property aType: TPSType read FType write FType;
+ end;
+
+ TPSSubNumber = class(TPSSubItem)
+ private
+ FSubNo: Cardinal;
+ public
+
+ property SubNo: Cardinal read FSubNo write FSubNo;
+ end;
+
+ TPSSubValue = class(TPSSubItem)
+ private
+ FSubNo: TPSValue;
+ public
+
+ property SubNo: TPSValue read FSubNo write FSubNo;
+
+ destructor Destroy; override;
+ end;
+
+ TPSValueVar = class(TPSValue)
+ private
+ FRecItems: TPSList;
+ function GetRecCount: Cardinal;
+ function GetRecItem(I: Cardinal): TPSSubItem;
+ public
+ constructor Create;
+ destructor Destroy; override;
+
+ function RecAdd(Val: TPSSubItem): Cardinal;
+
+ procedure RecDelete(I: Cardinal);
+
+ property RecItem[I: Cardinal]: TPSSubItem read GetRecItem;
+
+ property RecCount: Cardinal read GetRecCount;
+ end;
+
+ TPSValueGlobalVar = class(TPSValueVar)
+ private
+ FAddress: Cardinal;
+ public
+
+ property GlobalVarNo: Cardinal read FAddress write FAddress;
+ end;
+
+
+ TPSValueLocalVar = class(TPSValueVar)
+ private
+ FLocalVarNo: Longint;
+ public
+
+ property LocalVarNo: Longint read FLocalVarNo write FLocalVarNo;
+ end;
+
+ TPSValueParamVar = class(TPSValueVar)
+ private
+ FParamNo: Longint;
+ public
+
+ property ParamNo: Longint read FParamNo write FParamNo;
+ end;
+
+ TPSValueAllocatedStackVar = class(TPSValueLocalVar)
+ private
+ FProc: TPSInternalProcedure;
+ public
+
+ property Proc: TPSInternalProcedure read FProc write FProc;
+ destructor Destroy; override;
+ end;
+
+ TPSValueData = class(TPSValue)
+ private
+ FData: PIfRVariant;
+ public
+
+ property Data: PIfRVariant read FData write FData;
+ destructor Destroy; override;
+ end;
+
+ TPSValueReplace = class(TPSValue)
+ private
+ FPreWriteAllocated: Boolean;
+ FFreeOldValue: Boolean;
+ FFreeNewValue: Boolean;
+ FOldValue: TPSValue;
+ FNewValue: TPSValue;
+ FReplaceTimes: Longint;
+ public
+
+ property OldValue: TPSValue read FOldValue write FOldValue;
+
+ property NewValue: TPSValue read FNewValue write FNewValue;
+ {Should it free the old value when destroyed?}
+ property FreeOldValue: Boolean read FFreeOldValue write FFreeOldValue;
+ property FreeNewValue: Boolean read FFreeNewValue write FFreeNewValue;
+ property PreWriteAllocated: Boolean read FPreWriteAllocated write FPreWriteAllocated;
+
+ property ReplaceTimes: Longint read FReplaceTimes write FReplaceTimes;
+
+ constructor Create;
+ destructor Destroy; override;
+ end;
+
+
+ TPSUnValueOp = class(TPSValue)
+ private
+ FVal1: TPSValue;
+ FOperator: TPSUnOperatorType;
+ FType: TPSType;
+ public
+
+ property Val1: TPSValue read FVal1 write FVal1;
+ {The operator}
+ property Operator: TPSUnOperatorType read FOperator write FOperator;
+
+ property aType: TPSType read FType write FType;
+ destructor Destroy; override;
+ end;
+
+ TPSBinValueOp = class(TPSValue)
+ private
+ FVal1,
+ FVal2: TPSValue;
+ FOperator: TPSBinOperatorType;
+ FType: TPSType;
+ public
+
+ property Val1: TPSValue read FVal1 write FVal1;
+
+ property Val2: TPSValue read FVal2 write FVal2;
+ {The operator for this value}
+ property Operator: TPSBinOperatorType read FOperator write FOperator;
+
+ property aType: TPSType read FType write FType;
+
+ destructor Destroy; override;
+ end;
+
+ TPSValueNil = class(TPSValue)
+ end;
+
+ TPSValueProcPtr = class(TPSValue)
+ private
+ FProcNo: Cardinal;
+ public
+
+ property ProcPtr: Cardinal read FProcNo write FProcNo;
+ end;
+
+ TPSValueProc = class(TPSValue)
+ private
+ FSelfPtr: TPSValue;
+ FParameters: TPSParameters;
+ FResultType: TPSType;
+ public
+ property ResultType: TPSType read FResultType write FResultType;
+
+ property SelfPtr: TPSValue read FSelfPtr write FSelfPtr;
+
+ property Parameters: TPSParameters read FParameters write FParameters;
+ destructor Destroy; override;
+ end;
+
+ TPSValueProcNo = class(TPSValueProc)
+ private
+ FProcNo: Cardinal;
+ public
+
+ property ProcNo: Cardinal read FProcNo write FProcNo;
+ end;
+
+ TPSValueProcVal = class(TPSValueProc)
+ private
+ FProcNo: TPSValue;
+ public
+
+ property ProcNo: TPSValue read FProcNo write FProcNo;
+
+ destructor Destroy; override;
+ end;
+
+ TPSValueArray = class(TPSValue)
+ private
+ FItems: TPSList;
+ function GetCount: Cardinal;
+ function GetItem(I: Cardinal): TPSValue;
+ public
+ function Add(Item: TPSValue): Cardinal;
+ procedure Delete(I: Cardinal);
+ property Item[I: Cardinal]: TPSValue read GetItem;
+ property Count: Cardinal read GetCount;
+
+ constructor Create;
+ destructor Destroy; override;
+ end;
+
+ TPSDelphiClassItem = class;
+
+ TPSPropType = (iptRW, iptR, iptW);
+
+ TPSCompileTimeClass = class
+ private
+ FInheritsFrom: TPSCompileTimeClass;
+ FClass: TClass;
+ FClassName: tbtString;
+ FClassNameHash: Longint;
+ FClassItems: TPSList;
+ FDefaultProperty: Cardinal;
+ FIsAbstract: Boolean;
+ FCastProc,
+ FNilProc: Cardinal;
+ FType: TPSType;
+
+ FOwner: TPSPascalCompiler;
+ function GetCount: Longint;
+ function GetItem(i: Longint): TPSDelphiClassItem;
+ public
+
+ property aType: TPSType read FType;
+
+ property Items[i: Longint]: TPSDelphiClassItem read GetItem;
+
+ property Count: Longint read GetCount;
+
+ property IsAbstract: Boolean read FIsAbstract write FIsAbstract;
+
+
+ property ClassInheritsFrom: TPSCompileTimeClass read FInheritsFrom write FInheritsFrom;
+
+ function RegisterMethod(const Decl: tbtString): Boolean;
+
+ procedure RegisterProperty(const PropertyName, PropertyType: tbtString; PropAC: TPSPropType);
+
+ procedure RegisterPublishedProperties;
+
+ function RegisterPublishedProperty(const Name: tbtString): Boolean;
+
+ procedure SetDefaultPropery(const Name: tbtString);
+
+ constructor Create(ClassName: tbtString; aOwner: TPSPascalCompiler; aType: TPSType);
+
+ class function CreateC(FClass: TClass; aOwner: TPSPascalCompiler; aType: TPSType): TPSCompileTimeClass;
+
+
+ destructor Destroy; override;
+
+
+ function IsCompatibleWith(aType: TPSType): Boolean;
+
+ function SetNil(var ProcNo: Cardinal): Boolean;
+
+ function CastToType(IntoType: TPSType; var ProcNo: Cardinal): Boolean;
+
+
+ function Property_Find(const Name: tbtString; var Index: IPointer): Boolean;
+
+ function Property_Get(Index: IPointer; var ProcNo: Cardinal): Boolean;
+
+ function Property_Set(Index: IPointer; var ProcNo: Cardinal): Boolean;
+
+ function Property_GetHeader(Index: IPointer; Dest: TPSParametersDecl): Boolean;
+
+
+ function Func_Find(const Name: tbtString; var Index: IPointer): Boolean;
+
+ function Func_Call(Index: IPointer; var ProcNo: Cardinal): Boolean;
+
+
+ function ClassFunc_Find(const Name: tbtString; var Index: IPointer): Boolean;
+
+ function ClassFunc_Call(Index: IPointer; var ProcNo: Cardinal): Boolean;
+ end;
+
+ TPSDelphiClassItem = class(TObject)
+ private
+ FOwner: TPSCompileTimeClass;
+ FOrgName: tbtString;
+ FName: tbtString;
+ FNameHash: Longint;
+ FDecl: TPSParametersDecl;
+ procedure SetName(const s: tbtString);
+ public
+
+ constructor Create(Owner: TPSCompileTimeClass);
+
+ destructor Destroy; override;
+
+ property Decl: TPSParametersDecl read FDecl;
+
+ property Name: tbtString read FName;
+
+ property OrgName: tbtString read FOrgName write SetName;
+
+ property NameHash: Longint read FNameHash;
+
+ property Owner: TPSCompileTimeClass read FOwner;
+ end;
+
+ TPSDelphiClassItemMethod = class(TPSDelphiClassItem)
+ private
+ FMethodNo: Cardinal;
+ public
+
+ property MethodNo: Cardinal read FMethodNo write FMethodNo;
+ end;
+
+ TPSDelphiClassItemProperty = class(TPSDelphiClassItem)
+ private
+ FReadProcNo: Cardinal;
+ FWriteProcNo: Cardinal;
+ FAccessType: TPSPropType;
+ public
+
+ property AccessType: TPSPropType read FAccessType write FAccessType;
+
+ property ReadProcNo: Cardinal read FReadProcNo write FReadProcNo;
+
+ property WriteProcNo: Cardinal read FWriteProcNo write FWriteProcNo;
+ end;
+
+
+ TPSDelphiClassItemConstructor = class(TPSDelphiClassItemMethod)
+ end;
+
+{$IFNDEF PS_NOINTERFACES}
+
+ TPSInterface = class(TObject)
+ private
+ FOwner: TPSPascalCompiler;
+ FType: TPSType;
+ FInheritedFrom: TPSInterface;
+ FGuid: TGuid;
+ FCastProc,
+ FNilProc: Cardinal;
+ FItems: TPSList;
+ FName: tbtString;
+ FNameHash: Longint;
+ procedure SetInheritedFrom(p: TPSInterface);
+ public
+
+ constructor Create(Owner: TPSPascalCompiler; InheritedFrom: TPSInterface; Guid: TGuid; const Name: tbtString; aType: TPSType);
+
+ destructor Destroy; override;
+
+ property aType: TPSType read FType;
+
+ property InheritedFrom: TPSInterface read FInheritedFrom write SetInheritedFrom;
+
+ property Guid: TGuid read FGuid write FGuid;
+
+ property Name: tbtString read FName write FName;
+
+ property NameHash: Longint read FNameHash;
+
+
+ function RegisterMethod(const Declaration: tbtString; const cc: TPSCallingConvention): Boolean;
+
+ function RegisterMethodEx(const Declaration: tbtString; const cc: TPSCallingConvention; const CustomParser: TPSPascalParser): Boolean;
+
+ procedure RegisterDummyMethod;
+
+ function IsCompatibleWith(aType: TPSType): Boolean;
+
+ function SetNil(var ProcNo: Cardinal): Boolean;
+
+ function CastToType(IntoType: TPSType; var ProcNo: Cardinal): Boolean;
+
+ function Func_Find(const Name: tbtString; var Index: Cardinal): Boolean;
+
+ function Func_Call(Index: Cardinal; var ProcNo: Cardinal): Boolean;
+ end;
+
+
+ TPSInterfaceMethod = class(TObject)
+ private
+ FName: tbtString;
+ FDecl: TPSParametersDecl;
+ FNameHash: Longint;
+ FCC: TPSCallingConvention;
+ FScriptProcNo: Cardinal;
+ FOrgName: tbtString;
+ FOwner: TPSInterface;
+ FOffsetCache: Cardinal;
+ function GetAbsoluteProcOffset: Cardinal;
+ public
+
+ property AbsoluteProcOffset: Cardinal read GetAbsoluteProcOffset;
+
+ property ScriptProcNo: Cardinal read FScriptProcNo;
+
+ property OrgName: tbtString read FOrgName;
+
+ property Name: tbtString read FName;
+
+ property NameHash: Longint read FNameHash;
+
+ property Decl: TPSParametersDecl read FDecl;
+
+ property CC: TPSCallingConvention read FCC;
+
+
+ constructor Create(Owner: TPSInterface);
+
+ destructor Destroy; override;
+ end;
+{$ENDIF}
+
+
+ TPSExternalClass = class(TObject)
+ protected
+
+ SE: TPSPascalCompiler;
+
+ FTypeNo: TPSType;
+ public
+
+ function SelfType: TPSType; virtual;
+
+ constructor Create(Se: TPSPascalCompiler; TypeNo: TPSType);
+
+ function ClassFunc_Find(const Name: tbtString; var Index: Cardinal): Boolean; virtual;
+
+ function ClassFunc_Call(Index: Cardinal; var ProcNo: Cardinal): Boolean; virtual;
+
+ function Func_Find(const Name: tbtString; var Index: Cardinal): Boolean; virtual;
+
+ function Func_Call(Index: Cardinal; var ProcNo: Cardinal): Boolean; virtual;
+
+ function IsCompatibleWith(Cl: TPSExternalClass): Boolean; virtual;
+
+ function SetNil(var ProcNo: Cardinal): Boolean; virtual;
+
+ function CastToType(IntoType: TPSType; var ProcNo: Cardinal): Boolean; virtual;
+
+ function CompareClass(OtherTypeNo: TPSType; var ProcNo: Cardinal): Boolean; virtual;
+ end;
+
+
+function ExportCheck(Sender: TPSPascalCompiler; Proc: TPSInternalProcedure;
+ Types: array of TPSBaseType; Modes: array of TPSParameterMode): Boolean;
+
+
+procedure SetVarExportName(P: TPSVar; const ExpName: tbtString);
+
+function AddImportedClassVariable(Sender: TPSPascalCompiler; const VarName, VarType: tbtString): Boolean;
+
+const
+ {Invalid value, this is returned by most functions of pascal script that return a cardinal, when they fail}
+ InvalidVal = Cardinal(-1);
+
+type
+ TIFPSCompileTimeClass = TPSCompileTimeClass;
+ TIFPSInternalProcedure = TPSInternalProcedure;
+ TIFPSPascalCompilerError = TPSPascalCompilerError;
+
+ TPMFuncType = (mftProc
+ , mftConstructor
+ );
+
+
+function PS_mi2s(i: Cardinal): tbtString;
+
+function ParseMethod(Owner: TPSPascalCompiler; const FClassName: tbtString; Decl: tbtString; var OrgName: tbtString; DestDecl: TPSParametersDecl; var Func: TPMFuncType): Boolean;
+function ParseMethodEx(Owner: TPSPascalCompiler; const FClassName: tbtString; Decl: tbtString; var OrgName: tbtString; DestDecl: TPSParametersDecl; var Func: TPMFuncType; CustomParser: TPSPascalParser): Boolean;
+
+function DeclToBits(const Decl: TPSParametersDecl): tbtString;
+
+function NewVariant(FType: TPSType): PIfRVariant;
+procedure DisposeVariant(p: PIfRVariant);
+
+implementation
+
+uses Classes, typInfo;
+
+{$IFDEF DELPHI3UP}
+resourceString
+{$ELSE}
+const
+{$ENDIF}
+
+ RPS_OnUseEventOnly = 'This function can only be called from within the OnUses event';
+ RPS_UnableToRegisterFunction = 'Unable to register function %s';
+ RPS_UnableToRegisterConst = 'Unable to register constant %s';
+ RPS_InvalidTypeForVar = 'Invalid type for variable %s';
+ RPS_InvalidType = 'Invalid Type';
+ RPS_UnableToRegisterType = 'Unable to register type %s';
+ RPS_UnknownInterface = 'Unknown interface: %s';
+ RPS_ConstantValueMismatch = 'Constant Value Type Mismatch';
+ RPS_ConstantValueNotAssigned = 'Constant Value is not assigned';
+
+ RPS_Error = 'Error';
+ RPS_UnknownIdentifier = 'Unknown identifier ''%s''';
+ RPS_IdentifierExpected = 'Identifier expected';
+ RPS_CommentError = 'Comment error';
+ RPS_StringError = 'String error';
+ RPS_CharError = 'Char error';
+ RPS_SyntaxError = 'Syntax error';
+ RPS_EOF = 'Unexpected end of file';
+ RPS_SemiColonExpected = 'Semicolon ('';'') expected';
+ RPS_BeginExpected = '''BEGIN'' expected';
+ RPS_PeriodExpected = 'period (''.'') expected';
+ RPS_DuplicateIdent = 'Duplicate identifier ''%s''';
+ RPS_ColonExpected = 'colon ('':'') expected';
+ RPS_UnknownType = 'Unknown type ''%s''';
+ RPS_CloseRoundExpected = 'Closing parenthesis expected';
+ RPS_TypeMismatch = 'Type mismatch';
+ RPS_InternalError = 'Internal error (%s)';
+ RPS_AssignmentExpected = 'Assignment expected';
+ RPS_ThenExpected = '''THEN'' expected';
+ RPS_DoExpected = '''DO'' expected';
+ RPS_NoResult = 'No result';
+ RPS_OpenRoundExpected = 'opening parenthesis (''('')expected';
+ RPS_CommaExpected = 'comma ('','') expected';
+ RPS_ToExpected = '''TO'' expected';
+ RPS_IsExpected = 'is (''='') expected';
+ RPS_OfExpected = '''OF'' expected';
+ RPS_CloseBlockExpected = 'Closing square bracket ('']'') expected';
+ RPS_VariableExpected = 'Variable Expected';
+ RPS_StringExpected = 'String Expected';
+ RPS_EndExpected = '''END'' expected';
+ RPS_UnSetLabel = 'Label ''%s'' not set';
+ RPS_NotInLoop = 'Not in a loop';
+ RPS_InvalidJump = 'Invalid jump';
+ RPS_OpenBlockExpected = 'Opening square brackets (''['') expected';
+ RPS_WriteOnlyProperty = 'Write-only property';
+ RPS_ReadOnlyProperty = 'Read-only property';
+ RPS_ClassTypeExpected = 'Class type expected';
+ RPS_DivideByZero = 'Divide by Zero';
+ RPS_MathError = 'Math Error';
+ RPS_UnsatisfiedForward = 'Unsatisfied Forward %s';
+ RPS_ForwardParameterMismatch = 'Forward Parameter Mismatch';
+ RPS_InvalidNumberOfParameter = 'Invalid number of parameters';
+ RPS_UnknownError = 'Unknown error';
+ {$IFDEF PS_USESSUPPORT}
+ RPS_NotAllowed = '%s is not allowed at this position';
+ RPS_UnitNotFound = 'Unit ''%s'' not found or contains errors';
+ RPS_CrossReference = 'Cross-Reference error of ''%s''';
+ {$ENDIF}
+
+
+ RPS_Hint = 'Hint';
+ RPS_VariableNotUsed = 'Variable ''%s'' never used';
+ RPS_FunctionNotUsed = 'Function ''%s'' never used';
+ RPS_UnknownHint = 'Unknown hint';
+
+
+ RPS_Warning = 'Warning';
+ RPS_CalculationAlwaysEvaluatesTo = 'Calculation always evaluates to %s';
+ RPS_IsNotNeeded = '%s is not needed';
+ RPS_AbstractClass = 'Abstract Class Construction';
+ RPS_UnknownWarning = 'Unknown warning';
+
+
+ {$IFDEF DEBUG }
+ RPS_UnableToRegister = 'Unable to register %s';
+ {$ENDIF}
+
+ RPS_NotArrayProperty = 'Not an array property';
+ RPS_NotProperty = 'Not a property';
+ RPS_UnknownProperty = 'Unknown Property';
+
+function DeclToBits(const Decl: TPSParametersDecl): tbtString;
+var
+ i: longint;
+begin
+ Result := '';
+ if Decl.Result = nil then
+ begin
+ Result := Result + #0;
+ end else
+ Result := Result + #1;
+ for i := 0 to Decl.ParamCount -1 do
+ begin
+ if Decl.Params[i].Mode <> pmIn then
+ Result := Result + #1
+ else
+ Result := Result + #0;
+ end;
+end;
+
+
+procedure BlockWriteByte(BlockInfo: TPSBlockInfo; b: Byte);
+begin
+ BlockInfo.Proc.Data := BlockInfo.Proc.Data + tbtChar(b);
+end;
+
+procedure BlockWriteData(BlockInfo: TPSBlockInfo; const Data; Len: Longint);
+begin
+ SetLength(BlockInfo.Proc.FData, Length(BlockInfo.Proc.FData) + Len);
+ Move(Data, BlockInfo.Proc.FData[Length(BlockInfo.Proc.FData) - Len + 1], Len);
+end;
+
+procedure BlockWriteLong(BlockInfo: TPSBlockInfo; l: Cardinal);
+begin
+ BlockWriteData(BlockInfo, l, 4);
+end;
+
+procedure BlockWriteVariant(BlockInfo: TPSBlockInfo; p: PIfRVariant);
+var
+ du8: tbtu8;
+ du16: tbtu16;
+begin
+ BlockWriteLong(BlockInfo, p^.FType.FinalTypeNo);
+ case p.FType.BaseType of
+ btType: BlockWriteData(BlockInfo, p^.ttype.FinalTypeno, 4);
+ {$IFNDEF PS_NOWIDESTRING}
+ btWideString:
+ begin
+ BlockWriteLong(BlockInfo, Length(tbtWideString(p^.twidestring)));
+ BlockWriteData(BlockInfo, tbtwidestring(p^.twidestring)[1], 2*Length(tbtWideString(p^.twidestring)));
+ end;
+ btUnicodeString:
+ begin
+ BlockWriteLong(BlockInfo, Length(tbtUnicodeString(p^.twidestring)));
+ BlockWriteData(BlockInfo, tbtUnicodeString(p^.twidestring)[1], 2*Length(tbtUnicodeString(p^.twidestring)));
+ end;
+ btWideChar: BlockWriteData(BlockInfo, p^.twidechar, 2);
+ {$ENDIF}
+ btSingle: BlockWriteData(BlockInfo, p^.tsingle, sizeof(tbtSingle));
+ btDouble: BlockWriteData(BlockInfo, p^.tdouble, sizeof(tbtDouble));
+ btExtended: BlockWriteData(BlockInfo, p^.textended, sizeof(tbtExtended));
+ btCurrency: BlockWriteData(BlockInfo, p^.tcurrency, sizeof(tbtCurrency));
+ btChar: BlockWriteData(BlockInfo, p^.tchar, 1);
+ btSet:
+ begin
+ BlockWriteData(BlockInfo, tbtString(p^.tstring)[1], Length(tbtString(p^.tstring)));
+ end;
+ btString:
+ begin
+ BlockWriteLong(BlockInfo, Length(tbtString(p^.tstring)));
+ BlockWriteData(BlockInfo, tbtString(p^.tstring)[1], Length(tbtString(p^.tstring)));
+ end;
+ btenum:
+ begin
+ if TPSEnumType(p^.FType).HighValue <=256 then
+ begin
+ du8 := tbtu8(p^.tu32);
+ BlockWriteData(BlockInfo, du8, 1)
+ end
+ else if TPSEnumType(p^.FType).HighValue <=65536 then
+ begin
+ du16 := tbtu16(p^.tu32);
+ BlockWriteData(BlockInfo, du16, 2)
+ end;
+ end;
+
+ bts8,btu8: BlockWriteData(BlockInfo, p^.tu8, 1);
+ bts16,btu16: BlockWriteData(BlockInfo, p^.tu16, 2);
+ bts32,btu32: BlockWriteData(BlockInfo, p^.tu32, 4);
+ {$IFNDEF PS_NOINT64}
+ bts64: BlockWriteData(BlockInfo, p^.ts64, 8);
+ {$ENDIF}
+ btProcPtr: BlockWriteData(BlockInfo, p^.tu32, 4);
+ {$IFDEF DEBUG}
+ {$IFNDEF FPC}
+ else
+ asm int 3; end;
+ {$ENDIF}
+ {$ENDIF}
+ end;
+end;
+
+
+
+function ExportCheck(Sender: TPSPascalCompiler; Proc: TPSInternalProcedure; Types: array of TPSBaseType; Modes: array of TPSParameterMode): Boolean;
+var
+ i: Longint;
+ ttype: TPSType;
+begin
+ if High(Types) <> High(Modes)+1 then
+ begin
+ Result := False;
+ exit;
+ end;
+ if High(Types) <> Proc.Decl.ParamCount then
+ begin
+ Result := False;
+ exit;
+ end;
+ TType := Proc.Decl.Result;
+ if TType = nil then
+ begin
+ if Types[0] <> btReturnAddress then
+ begin
+ Result := False;
+ exit;
+ end;
+ end else
+ begin
+ if TType.BaseType <> Types[0] then
+ begin
+ Result := False;
+ exit;
+ end;
+ end;
+ for i := 0 to High(Modes) do
+ begin
+ TType := Proc.Decl.Params[i].aType;
+ if Modes[i] <> Proc.Decl.Params[i].Mode then
+ begin
+ Result := False;
+ exit;
+ end;
+ if TType.BaseType <> Types[i+1] then
+ begin
+ Result := False;
+ exit;
+ end;
+ end;
+ Result := True;
+end;
+
+procedure SetVarExportName(P: TPSVar; const ExpName: tbtString);
+begin
+ if p <> nil then
+ p.exportname := ExpName;
+end;
+
+function FindAndAddType(Owner: TPSPascalCompiler; const Name, Decl: tbtString): TPSType;
+var
+ tt: TPSType;
+begin
+ Result := Owner.FindType(Name);
+ if Result = nil then
+ begin
+ tt := Owner.AddTypeS(Name, Decl);
+ tt.ExportName := True;
+ Result := tt;
+ end;
+end;
+
+function ParseMethod(Owner: TPSPascalCompiler; const FClassName: tbtString; Decl: tbtString; var OrgName: tbtString; DestDecl: TPSParametersDecl; var Func: TPMFuncType): Boolean;
+begin
+ Result := ParseMethodEx(Owner, FClassName, Decl, OrgName, DestDecl, Func, nil);
+end;
+
+function ParseMethodEx(Owner: TPSPascalCompiler; const FClassName: tbtString; Decl: tbtString; var OrgName: tbtString; DestDecl: TPSParametersDecl; var Func: TPMFuncType; CustomParser: TPSPascalParser): Boolean;
+var
+ Parser: TPSPascalParser;
+ FuncType: Byte;
+ VNames: tbtString;
+ modifier: TPSParameterMode;
+ VCType: TPSType;
+ ERow, EPos, ECol: Integer;
+
+begin
+ if CustomParser = nil then begin
+ Parser := TPSPascalParser.Create;
+ Parser.SetText(Decl);
+ end else
+ Parser := CustomParser;
+ if Parser.CurrTokenId = CSTII_Function then
+ FuncType:= 0
+ else if Parser.CurrTokenId = CSTII_Procedure then
+ FuncType := 1
+ else if (Parser.CurrTokenId = CSTII_Constructor) and (FClassName <> '') then
+ FuncType := 2
+ else
+ begin
+ if Parser <> CustomParser then
+ Parser.Free;
+ Result := False;
+ exit;
+ end;
+ Parser.Next;
+ if Parser.CurrTokenId <> CSTI_Identifier then
+ begin
+ if Parser <> CustomParser then
+ Parser.Free
+ else
+ Owner.MakeError('', ecIdentifierExpected, '');
+ Result := False;
+ exit;
+ end; {if}
+ OrgName := Parser.OriginalToken;
+ Parser.Next;
+ if Parser.CurrTokenId = CSTI_OpenRound then
+ begin
+ Parser.Next;
+ if Parser.CurrTokenId <> CSTI_CloseRound then
+ begin
+ while True do
+ begin
+ if Parser.CurrTokenId = CSTII_Const then
+ begin
+ modifier := pmIn;
+ Parser.Next;
+ end
+ else
+ if Parser.CurrTokenId = CSTII_Var then
+ begin
+ modifier := pmInOut;
+ Parser.Next;
+ end
+ else
+ if Parser.CurrTokenId = CSTII_Out then
+ begin
+ modifier := pmOut;
+ Parser.Next;
+ end
+ else
+ modifier := pmIn;
+ if Parser.CurrTokenId <> CSTI_Identifier then
+ begin
+ if Parser <> CustomParser then
+ Parser.Free
+ else
+ Owner.MakeError('', ecIdentifierExpected, '');
+ Result := False;
+ exit;
+ end;
+ EPos:=Parser.CurrTokenPos;
+ ERow:=Parser.Row;
+ ECol:=Parser.Col;
+
+ VNames := Parser.OriginalToken + '|';
+ Parser.Next;
+ while Parser.CurrTokenId = CSTI_Comma do
+ begin
+ Parser.Next;
+ if Parser.CurrTokenId <> CSTI_Identifier then
+ begin
+ if Parser <> CustomParser then
+ Parser.Free
+ else
+ Owner.MakeError('', ecIdentifierExpected, '');
+ Result := False;
+ exit;
+ end;
+ VNames := VNames + Parser.OriginalToken + '|';
+ Parser.Next;
+ end;
+ if Parser.CurrTokenId <> CSTI_Colon then
+ begin
+ if Parser <> CustomParser then
+ Parser.Free
+ else
+ Owner.MakeError('', ecColonExpected, '');
+ Result := False;
+ exit;
+ end;
+ Parser.Next;
+ if Parser.CurrTokenID = CSTII_Array then
+ begin
+ Parser.nExt;
+ if Parser.CurrTokenId <> CSTII_Of then
+ begin
+ if Parser <> CustomParser then
+ Parser.Free
+ else
+ Owner.MakeError('', ecOfExpected, '');
+ Result := False;
+ exit;
+ end;
+ Parser.Next;
+ if Parser.CurrTokenId = CSTII_Const then
+ begin
+ VCType := FindAndAddType(Owner, '!OPENARRAYOFCONST', 'array of ___Pointer')
+ end
+ else begin
+ VCType := Owner.GetTypeCopyLink(Owner.FindType(Parser.GetToken));
+ if VCType = nil then
+ begin
+ if Parser <> CustomParser then
+ Parser.Free
+ else
+ Owner.MakeError('', ecUnknownType, Parser.GetToken);
+ Result := False;
+ exit;
+ end;
+ case VCType.BaseType of
+ btU8: VCType := FindAndAddType(Owner, '!OPENARRAYOFU8', 'array of byte');
+ btS8: VCType := FindAndAddType(Owner, '!OPENARRAYOFS8', 'array of ShortInt');
+ btU16: VCType := FindAndAddType(Owner, '!OPENARRAYOFU16', 'array of SmallInt');
+ btS16: VCType := FindAndAddType(Owner, '!OPENARRAYOFS16', 'array of Word');
+ btU32: VCType := FindAndAddType(Owner, '!OPENARRAYOFU32', 'array of Cardinal');
+ btS32: VCType := FindAndAddType(Owner, '!OPENARRAYOFS32', 'array of Longint');
+ btSingle: VCType := FindAndAddType(Owner, '!OPENARRAYOFSINGLE', 'array of Single');
+ btDouble: VCType := FindAndAddType(Owner, '!OPENARRAYOFDOUBLE', 'array of Double');
+ btExtended: VCType := FindAndAddType(Owner, '!OPENARRAYOFEXTENDED', 'array of Extended');
+ btString: VCType := FindAndAddType(Owner, '!OPENARRAYOFSTRING', 'array of String');
+ btPChar: VCType := FindAndAddType(Owner, '!OPENARRAYOFPCHAR', {$IFDEF PS_PANSICHAR}'array of PAnsiChar'{$ELSE}'array of PChar'{$ENDIF});
+ btNotificationVariant, btVariant: VCType := FindAndAddType(Owner, '!OPENARRAYOFVARIANT', 'array of variant');
+ {$IFNDEF PS_NOINT64}btS64: VCType := FindAndAddType(Owner, '!OPENARRAYOFS64', 'array of Int64');{$ENDIF}
+ btChar: VCType := FindAndAddType(Owner, '!OPENARRAYOFCHAR', 'array of Char');
+ {$IFNDEF PS_NOWIDESTRING}
+ btWideString: VCType := FindAndAddType(Owner, '!OPENARRAYOFWIDESTRING', 'array of WideString');
+ btUnicodeString: VCType := FindAndAddType(Owner, '!OPENARRAYOFUNICODESTRING', 'array of UnicodeString');
+ btWideChar: VCType := FindAndAddType(Owner, '!OPENARRAYOFWIDECHAR', 'array of WideChar');
+ {$ENDIF}
+ btClass: VCType := FindAndAddType(Owner, '!OPENARRAYOFTOBJECT', 'array of TObject');
+ btRecord: VCType := FindAndAddType(Owner, '!OPENARRAYOFRECORD_'+FastUpperCase(Parser.OriginalToken), 'array of ' +FastUpperCase(Parser.OriginalToken));
+ else
+ begin
+ if Parser <> CustomParser then
+ Parser.Free;
+ Result := False;
+ exit;
+ end;
+ end;
+ end;
+ end else if Parser.CurrTokenID = CSTII_Const then
+ VCType := nil // any type
+ else begin
+ VCType := Owner.FindType(Parser.GetToken);
+ if VCType = nil then
+ begin
+ if Parser <> CustomParser then
+ Parser.Free
+ else
+ Owner.MakeError('', ecUnknownType, Parser.GetToken);
+ Result := False;
+ exit;
+ end;
+ end;
+ while Pos(tbtchar('|'), VNames) > 0 do
+ begin
+ with DestDecl.AddParam do
+ begin
+ {$IFDEF PS_USESSUPPORT}
+ DeclareUnit:=Owner.fModule;
+ {$ENDIF}
+ DeclarePos := EPos;
+ DeclareRow := ERow;
+ DeclareCol := ECol;
+ Mode := modifier;
+ OrgName := copy(VNames, 1, Pos(tbtchar('|'), VNames) - 1);
+ aType := VCType;
+ end;
+ Delete(VNames, 1, Pos(tbtchar('|'), VNames));
+ end;
+ Parser.Next;
+ if Parser.CurrTokenId = CSTI_CloseRound then
+ break;
+ if Parser.CurrTokenId <> CSTI_Semicolon then
+ begin
+ if Parser <> CustomParser then
+ Parser.Free
+ else
+ Owner.MakeError('', ecSemiColonExpected, '');
+ Result := False;
+ exit;
+ end;
+ Parser.Next;
+ end; {while}
+ end; {if}
+ Parser.Next;
+ end; {if}
+ if FuncType = 0 then
+ begin
+ if Parser.CurrTokenId <> CSTI_Colon then
+ begin
+ if Parser <> CustomParser then
+ Parser.Free
+ else
+ Owner.MakeError('', ecColonExpected, '');
+ Result := False;
+ exit;
+ end;
+
+ Parser.Next;
+ VCType := Owner.FindType(Parser.GetToken);
+ if VCType = nil then
+ begin
+ if Parser <> CustomParser then
+ Parser.Free
+ else
+ Owner.MakeError('', ecUnknownType, Parser.GetToken);
+ Result := False;
+ exit;
+ end;
+ Parser.Next;
+ end
+ else if FuncType = 2 then {constructor}
+ begin
+ VCType := Owner.FindType(FClassName)
+ end else
+ VCType := nil;
+ DestDecl.Result := VCType;
+ if Parser <> CustomParser then
+ Parser.Free;
+ if FuncType = 2 then
+ Func := mftConstructor
+ else
+ Func := mftProc;
+ Result := True;
+end;
+
+
+
+function TPSPascalCompiler.FindProc(const aName: tbtString): Cardinal;
+var
+ l, h: Longint;
+ x: TPSProcedure;
+ xr: TPSRegProc;
+ name: tbtString;
+
+begin
+ name := FastUpperCase(aName);
+ h := MakeHash(Name);
+ if FProcs = nil then
+ begin
+ result := InvalidVal;
+ Exit;
+ end;
+
+ for l := FProcs.Count - 1 downto 0 do
+ begin
+ x := FProcs.Data^[l];
+ if x.ClassType = TPSInternalProcedure then
+ begin
+ if (TPSInternalProcedure(x).NameHash = h) and
+ (TPSInternalProcedure(x).Name = Name) then
+ begin
+ Result := l;
+ exit;
+ end;
+ end
+ else
+ begin
+ if (TPSExternalProcedure(x).RegProc.NameHash = h) and
+ (TPSExternalProcedure(x).RegProc.Name = Name) {$IFDEF PS_USESSUPPORT} and
+ (IsInLocalUnitList(TPSInternalProcedure(x).DeclareUnit)){$ENDIF} then
+ begin
+ Result := l;
+ exit;
+ end;
+ end;
+ end;
+ for l := FRegProcs.Count - 1 downto 0 do
+ begin
+ xr := FRegProcs[l];
+ if (xr.NameHash = h) and (xr.Name = Name) then
+ begin
+ x := TPSExternalProcedure.Create;
+ TPSExternalProcedure(x).RegProc := xr;
+ FProcs.Add(x);
+ Result := FProcs.Count - 1;
+ exit;
+ end;
+ end;
+ Result := InvalidVal;
+end; {findfunc}
+
+function TPSPascalCompiler.UseExternalProc(const Name: tbtString): TPSParametersDecl;
+var
+ ProcNo: cardinal;
+ proc: TPSProcedure;
+begin
+ ProcNo := FindProc(FastUppercase(Name));
+ if ProcNo = InvalidVal then Result := nil
+ else
+ begin
+ proc := TPSProcedure(FProcs[ProcNo]);
+ if Proc is TPSExternalProcedure then
+ begin
+ Result := TPSExternalProcedure(Proc).RegProc.Decl;
+ end else result := nil;
+ end;
+end;
+
+
+
+function TPSPascalCompiler.FindBaseType(BaseType: TPSBaseType): TPSType;
+var
+ l: Longint;
+ x: TPSType;
+begin
+ for l := 0 to FTypes.Count -1 do
+ begin
+ X := FTypes[l];
+ if (x.BaseType = BaseType) and (x.ClassType = TPSType) then
+ begin
+ Result := at2ut(x);
+ exit;
+ end;
+ end;
+ X := TPSType.Create;
+ x.Name := '';
+ x.BaseType := BaseType;
+ {$IFDEF PS_USESSUPPORT}
+ x.DeclareUnit:=fModule;
+ {$ENDIF}
+ x.DeclarePos := InvalidVal;
+ x.DeclareCol := 0;
+ x.DeclareRow := 0;
+ FTypes.Add(x);
+ Result := at2ut(x);
+end;
+
+function TPSPascalCompiler.MakeDecl(decl: TPSParametersDecl): tbtString;
+var
+ i: Longint;
+begin
+ if Decl.Result = nil then result := '0' else
+ result := Decl.Result.Name;
+
+ for i := 0 to decl.ParamCount -1 do
+ begin
+ if decl.GetParam(i).Mode = pmIn then
+ Result := Result + ' @'
+ else
+ Result := Result + ' !';
+ Result := Result + decl.GetParam(i).aType.Name;
+ end;
+end;
+
+
+{ TPSPascalCompiler }
+
+const
+ BtTypeCopy = 255;
+
+
+type
+ TFuncType = (ftProc, ftFunc);
+
+function PS_mi2s(i: Cardinal): tbtString;
+begin
+ SetLength(Result, 4);
+ Cardinal((@Result[1])^) := i;
+end;
+
+
+
+
+function TPSPascalCompiler.AddType(const Name: tbtString; const BaseType: TPSBaseType): TPSType;
+begin
+ if FProcs = nil then
+ begin
+ raise EPSCompilerException.Create(RPS_OnUseEventOnly);
+ end;
+
+ case BaseType of
+ btProcPtr: Result := TPSProceduralType.Create;
+ BtTypeCopy: Result := TPSTypeLink.Create;
+ btRecord: Result := TPSRecordType.Create;
+ btArray: Result := TPSArrayType.Create;
+ btStaticArray: Result := TPSStaticArrayType.Create;
+ btEnum: Result := TPSEnumType.Create;
+ btClass: Result := TPSClassType.Create;
+ btExtClass: REsult := TPSUndefinedClassType.Create;
+ btNotificationVariant, btVariant: Result := TPSVariantType.Create;
+{$IFNDEF PS_NOINTERFACES}
+ btInterface: Result := TPSInterfaceType.Create;
+{$ENDIF}
+ else
+ Result := TPSType.Create;
+ end;
+ Result.Name := FastUppercase(Name);
+ Result.OriginalName := Name;
+ Result.BaseType := BaseType;
+ {$IFDEF PS_USESSUPPORT}
+ Result.DeclareUnit:=fModule;
+ {$ENDIF}
+ Result.DeclarePos := InvalidVal;
+ Result.DeclareCol := 0;
+ Result.DeclareRow := 0;
+ FTypes.Add(Result);
+end;
+
+
+function TPSPascalCompiler.AddFunction(const Header: tbtString): TPSRegProc;
+var
+ Parser: TPSPascalParser;
+ i: Integer;
+ IsFunction: Boolean;
+ VNames, Name: tbtString;
+ Decl: TPSParametersDecl;
+ modifier: TPSParameterMode;
+ VCType: TPSType;
+ x: TPSRegProc;
+begin
+ if FProcs = nil then
+ raise EPSCompilerException.Create(RPS_OnUseEventOnly);
+
+ Parser := TPSPascalParser.Create;
+ Parser.SetText(Header);
+ Decl := TPSParametersDecl.Create;
+ x := nil;
+ try
+ if Parser.CurrTokenId = CSTII_Function then
+ IsFunction := True
+ else if Parser.CurrTokenId = CSTII_Procedure then
+ IsFunction := False
+ else
+ Raise EPSCompilerException.CreateFmt(RPS_UnableToRegisterFunction, ['']);
+ Parser.Next;
+ if Parser.CurrTokenId <> CSTI_Identifier then
+ Raise EPSCompilerException.CreateFmt(RPS_UnableToRegisterFunction, ['']);
+ Name := Parser.OriginalToken;
+ Parser.Next;
+ if Parser.CurrTokenId = CSTI_OpenRound then
+ begin
+ Parser.Next;
+ if Parser.CurrTokenId <> CSTI_CloseRound then
+ begin
+ while True do
+ begin
+ if Parser.CurrTokenId = CSTII_Out then
+ begin
+ Modifier := pmOut;
+ Parser.Next;
+ end else
+ if Parser.CurrTokenId = CSTII_Const then
+ begin
+ Modifier := pmIn;
+ Parser.Next;
+ end else
+ if Parser.CurrTokenId = CSTII_Var then
+ begin
+ modifier := pmInOut;
+ Parser.Next;
+ end
+ else
+ modifier := pmIn;
+ if Parser.CurrTokenId <> CSTI_Identifier then
+ raise EPSCompilerException.CreateFmt(RPS_UnableToRegisterFunction, [Name]);
+ VNames := Parser.OriginalToken + '|';
+ Parser.Next;
+ while Parser.CurrTokenId = CSTI_Comma do
+ begin
+ Parser.Next;
+ if Parser.CurrTokenId <> CSTI_Identifier then
+ Raise EPSCompilerException.CreateFmt(RPS_UnableToRegisterFunction, [Name]);
+ VNames := VNames + Parser.OriginalToken + '|';
+ Parser.Next;
+ end;
+ if Parser.CurrTokenId <> CSTI_Colon then
+ begin
+ Parser.Free;
+ Raise EPSCompilerException.CreateFmt(RPS_UnableToRegisterFunction, [Name]);
+ end;
+ Parser.Next;
+ VCType := FindType(Parser.GetToken);
+ if VCType = nil then
+ Raise EPSCompilerException.CreateFmt(RPS_UnableToRegisterFunction, [Name]);
+ while Pos(tbtchar('|'), VNames) > 0 do
+ begin
+ with Decl.AddParam do
+ begin
+ Mode := modifier;
+ OrgName := copy(VNames, 1, Pos(tbtchar('|'), VNames) - 1);
+ aType := VCType;
+ end;
+ Delete(VNames, 1, Pos(tbtchar('|'), VNames));
+ end;
+ Parser.Next;
+ if Parser.CurrTokenId = CSTI_CloseRound then
+ break;
+ if Parser.CurrTokenId <> CSTI_Semicolon then
+ Raise EPSCompilerException.CreateFmt(RPS_UnableToRegisterFunction, [Name]);
+ Parser.Next;
+ end; {while}
+ end; {if}
+ Parser.Next;
+ end; {if}
+ if IsFunction then
+ begin
+ if Parser.CurrTokenId <> CSTI_Colon then
+ Raise EPSCompilerException.CreateFmt(RPS_UnableToRegisterFunction, [Name]);
+
+ Parser.Next;
+ VCType := FindType(Parser.GetToken);
+ if VCType = nil then
+ Raise EPSCompilerException.CreateFmt(RPS_UnableToRegisterFunction, [Name]);
+ end
+ else
+ VCType := nil;
+ Decl.Result := VCType;
+ X := TPSRegProc.Create;
+ x.OrgName := Name;
+ x.Name := FastUpperCase(Name);
+ x.ExportName := True;
+ x.Decl.Assign(decl);
+ if Decl.Result = nil then
+ begin
+ x.ImportDecl := x.ImportDecl + #0;
+ end else
+ x.ImportDecl := x.ImportDecl + #1;
+ for i := 0 to Decl.ParamCount -1 do
+ begin
+ if Decl.Params[i].Mode <> pmIn then
+ x.ImportDecl := x.ImportDecl + #1
+ else
+ x.ImportDecl := x.ImportDecl + #0;
+ end;
+
+ FRegProcs.Add(x);
+ finally
+ Decl.Free;
+ Parser.Free;
+ end;
+ Result := x;
+end;
+
+function TPSPascalCompiler.MakeHint(const Module: tbtString; E: TPSPascalCompilerHintType; const Param: tbtString): TPSPascalCompilerMessage;
+var
+ n: TPSPascalCompilerHint;
+begin
+ N := TPSPascalCompilerHint.Create;
+ n.FHint := e;
+ n.SetParserPos(FParser);
+ n.FModuleName := Module;
+ n.FParam := Param;
+ FMessages.Add(n);
+ Result := n;
+end;
+
+function TPSPascalCompiler.MakeError(const Module: tbtString; E:
+ TPSPascalCompilerErrorType; const Param: tbtString): TPSPascalCompilerMessage;
+var
+ n: TPSPascalCompilerError;
+begin
+ N := TPSPascalCompilerError.Create;
+ n.FError := e;
+ n.SetParserPos(FParser);
+ {$IFNDEF PS_USESSUPPORT}
+ n.FModuleName := Module;
+ {$ELSE}
+ if Module <> '' then
+ n.FModuleName := Module
+ else
+ n.FModuleName := fModule;
+ {$ENDIF}
+ n.FParam := Param;
+ FMessages.Add(n);
+ Result := n;
+end;
+
+function TPSPascalCompiler.MakeWarning(const Module: tbtString; E:
+ TPSPascalCompilerWarningType; const Param: tbtString): TPSPascalCompilerMessage;
+var
+ n: TPSPascalCompilerWarning;
+begin
+ N := TPSPascalCompilerWarning.Create;
+ n.FWarning := e;
+ n.SetParserPos(FParser);
+ n.FModuleName := Module;
+ n.FParam := Param;
+ FMessages.Add(n);
+ Result := n;
+end;
+
+procedure TPSPascalCompiler.Clear;
+var
+ l: Longint;
+begin
+ FDebugOutput := '';
+ FOutput := '';
+ for l := 0 to FMessages.Count - 1 do
+ TPSPascalCompilerMessage(FMessages[l]).Free;
+ FMessages.Clear;
+ for L := FAutoFreeList.Count -1 downto 0 do
+ begin
+ TObject(FAutoFreeList[l]).Free;
+ end;
+ FAutoFreeList.Clear;
+end;
+
+procedure CopyVariantContents(Src, Dest: PIfRVariant);
+begin
+ case src.FType.BaseType of
+ btu8, bts8: dest^.tu8 := src^.tu8;
+ btu16, bts16: dest^.tu16 := src^.tu16;
+ btenum, btu32, bts32: dest^.tu32 := src^.tu32;
+ btsingle: Dest^.tsingle := src^.tsingle;
+ btdouble: Dest^.tdouble := src^.tdouble;
+ btextended: Dest^.textended := src^.textended;
+ btCurrency: Dest^.tcurrency := Src^.tcurrency;
+ btchar: Dest^.tchar := src^.tchar;
+ {$IFNDEF PS_NOINT64}bts64: dest^.ts64 := src^.ts64;{$ENDIF}
+ btset, btstring: tbtstring(dest^.tstring) := tbtstring(src^.tstring);
+ {$IFNDEF PS_NOWIDESTRING}
+ btunicodestring: tbtunicodestring(dest^.tunistring) := tbtunicodestring(src^.tunistring);
+ btwidestring: tbtwidestring(dest^.twidestring) := tbtwidestring(src^.twidestring);
+ btwidechar: Dest^.tchar := src^.tchar;
+ {$ENDIF}
+ end;
+end;
+
+function DuplicateVariant(Src: PIfRVariant): PIfRVariant;
+begin
+ New(Result);
+ FillChar(Result^, SizeOf(TIfRVariant), 0);
+ CopyVariantContents(Src, Result);
+end;
+
+
+procedure InitializeVariant(Vari: PIfRVariant; FType: TPSType);
+begin
+ FillChar(vari^, SizeOf(TIfRVariant), 0);
+ if FType.BaseType = btSet then
+ begin
+ SetLength(tbtstring(vari^.tstring), TPSSetType(FType).ByteSize);
+ fillchar(tbtstring(vari^.tstring)[1], length(tbtstring(vari^.tstring)), 0);
+ end;
+ vari^.FType := FType;
+end;
+
+function NewVariant(FType: TPSType): PIfRVariant;
+begin
+ New(Result);
+ InitializeVariant(Result, FType);
+end;
+
+procedure FinalizeA(var s: tbtString); overload; begin s := ''; end;
+procedure FinalizeW(var s: tbtwidestring); overload; begin s := ''; end;
+procedure FinalizeU(var s: tbtunicodestring); overload; begin s := ''; end;
+
+procedure FinalizeVariant(var p: TIfRVariant);
+begin
+ if (p.FType.BaseType = btString) or (p.FType.basetype = btSet) then
+ finalizeA(tbtstring(p.tstring))
+ {$IFNDEF PS_NOWIDESTRING}
+ else if p.FType.BaseType = btWideString then
+ finalizeW(tbtWideString(p.twidestring)) // tbtwidestring
+ else if p.FType.BaseType = btUnicodeString then
+ finalizeU(tbtUnicodeString(p.tunistring)); // tbtwidestring
+ {$ENDIF}
+end;
+
+procedure DisposeVariant(p: PIfRVariant);
+begin
+ if p <> nil then
+ begin
+ FinalizeVariant(p^);
+ Dispose(p);
+ end;
+end;
+
+
+
+function TPSPascalCompiler.GetTypeCopyLink(p: TPSType): TPSType;
+begin
+ if p = nil then
+ Result := nil
+ else
+ if p.BaseType = BtTypeCopy then
+ begin
+ Result := TPSTypeLink(p).LinkTypeNo;
+ end else Result := p;
+end;
+
+function IsIntType(b: TPSBaseType): Boolean;
+begin
+ case b of
+ btU8, btS8, btU16, btS16, btU32, btS32{$IFNDEF PS_NOINT64}, btS64{$ENDIF}: Result := True;
+ else
+ Result := False;
+ end;
+end;
+
+function IsRealType(b: TPSBaseType): Boolean;
+begin
+ case b of
+ btSingle, btDouble, btCurrency, btExtended: Result := True;
+ else
+ Result := False;
+ end;
+end;
+
+function IsIntRealType(b: TPSBaseType): Boolean;
+begin
+ case b of
+ btSingle, btDouble, btCurrency, btExtended, btU8, btS8, btU16, btS16, btU32, btS32{$IFNDEF PS_NOINT64}, btS64{$ENDIF}:
+ Result := True;
+ else
+ Result := False;
+ end;
+
+end;
+
+function DiffRec(p1, p2: TPSSubItem): Boolean;
+begin
+ if p1.ClassType = p2.ClassType then
+ begin
+ if P1.ClassType = TPSSubNumber then
+ Result := TPSSubNumber(p1).SubNo <> TPSSubNumber(p2).SubNo
+ else if P1.ClassType = TPSSubValue then
+ Result := TPSSubValue(p1).SubNo <> TPSSubValue(p2).SubNo
+ else
+ Result := False;
+ end else Result := True;
+end;
+
+function SameReg(x1, x2: TPSValue): Boolean;
+var
+ I: Longint;
+begin
+ if (x1.ClassType = x2.ClassType) and (X1 is TPSValueVar) then
+ begin
+ if
+ ((x1.ClassType = TPSValueGlobalVar) and (TPSValueGlobalVar(x1).GlobalVarNo = TPSValueGlobalVar(x2).GlobalVarNo)) or
+ ((x1.ClassType = TPSValueLocalVar) and (TPSValueLocalVar(x1).LocalVarNo = TPSValueLocalVar(x2).LocalVarNo)) or
+ ((x1.ClassType = TPSValueParamVar) and (TPSValueParamVar(x1).ParamNo = TPSValueParamVar(x2).ParamNo)) or
+ ((x1.ClassType = TPSValueAllocatedStackVar) and (TPSValueAllocatedStackVar(x1).LocalVarNo = TPSValueAllocatedStackVar(x2).LocalVarNo)) then
+ begin
+ if TPSValueVar(x1).GetRecCount <> TPSValueVar(x2).GetRecCount then
+ begin
+ Result := False;
+ exit;
+ end;
+ for i := 0 to TPSValueVar(x1).GetRecCount -1 do
+ begin
+ if DiffRec(TPSValueVar(x1).RecItem[i], TPSValueVar(x2).RecItem[i]) then
+ begin
+ Result := False;
+ exit;
+ end;
+ end;
+ Result := True;
+ end else Result := False;
+ end
+ else
+ Result := False;
+end;
+
+function GetUInt(Src: PIfRVariant; var s: Boolean): Cardinal;
+begin
+ case Src.FType.BaseType of
+ btU8: Result := Src^.tu8;
+ btS8: Result := Src^.ts8;
+ btU16: Result := Src^.tu16;
+ btS16: Result := Src^.ts16;
+ btU32: Result := Src^.tu32;
+ btS32: Result := Src^.ts32;
+ {$IFNDEF PS_NOINT64}
+ bts64: Result := src^.ts64;
+ {$ENDIF}
+ btChar: Result := ord(Src^.tchar);
+ {$IFNDEF PS_NOWIDESTRING}
+ btWideChar: Result := ord(tbtwidechar(src^.twidechar));
+ {$ENDIF}
+ btEnum: Result := src^.tu32;
+ else
+ begin
+ s := False;
+ Result := 0;
+ end;
+ end;
+end;
+
+function GetInt(Src: PIfRVariant; var s: Boolean): Longint;
+begin
+ case Src.FType.BaseType of
+ btU8: Result := Src^.tu8;
+ btS8: Result := Src^.ts8;
+ btU16: Result := Src^.tu16;
+ btS16: Result := Src^.ts16;
+ btU32: Result := Src^.tu32;
+ btS32: Result := Src^.ts32;
+ {$IFNDEF PS_NOINT64}
+ bts64: Result := src^.ts64;
+ {$ENDIF}
+ btChar: Result := ord(Src^.tchar);
+ {$IFNDEF PS_NOWIDESTRING}
+ btWideChar: Result := ord(tbtwidechar(src^.twidechar));
+ {$ENDIF}
+ btEnum: Result := src^.tu32;
+ else
+ begin
+ s := False;
+ Result := 0;
+ end;
+ end;
+end;
+{$IFNDEF PS_NOINT64}
+function GetInt64(Src: PIfRVariant; var s: Boolean): Int64;
+begin
+ case Src.FType.BaseType of
+ btU8: Result := Src^.tu8;
+ btS8: Result := Src^.ts8;
+ btU16: Result := Src^.tu16;
+ btS16: Result := Src^.ts16;
+ btU32: Result := Src^.tu32;
+ btS32: Result := Src^.ts32;
+ bts64: Result := src^.ts64;
+ btChar: Result := ord(Src^.tchar);
+ {$IFNDEF PS_NOWIDESTRING}
+ btWideChar: Result := ord(tbtwidechar(src^.twidechar));
+ {$ENDIF}
+ btEnum: Result := src^.tu32;
+ else
+ begin
+ s := False;
+ Result := 0;
+ end;
+ end;
+end;
+{$ENDIF}
+
+function GetReal(Src: PIfRVariant; var s: Boolean): Extended;
+begin
+ case Src.FType.BaseType of
+ btU8: Result := Src^.tu8;
+ btS8: Result := Src^.ts8;
+ btU16: Result := Src^.tu16;
+ btS16: Result := Src^.ts16;
+ btU32: Result := Src^.tu32;
+ btS32: Result := Src^.ts32;
+ {$IFNDEF PS_NOINT64}
+ bts64: Result := src^.ts64;
+ {$ENDIF}
+ btChar: Result := ord(Src^.tchar);
+ {$IFNDEF PS_NOWIDESTRING}
+ btWideChar: Result := ord(tbtwidechar(src^.twidechar));
+ {$ENDIF}
+ btSingle: Result := Src^.tsingle;
+ btDouble: Result := Src^.tdouble;
+ btCurrency: Result := SRc^.tcurrency;
+ btExtended: Result := Src^.textended;
+ else
+ begin
+ s := False;
+ Result := 0;
+ end;
+ end;
+end;
+
+function GetString(Src: PIfRVariant; var s: Boolean): tbtString;
+begin
+ case Src.FType.BaseType of
+ btChar: Result := Src^.tchar;
+ btString: Result := tbtstring(src^.tstring);
+ {$IFNDEF PS_NOWIDESTRING}
+ btWideChar: Result := tbtstring(src^.twidechar);
+ btWideString: Result := tbtstring(tbtWideString(src^.twidestring));
+ btUnicodeString: Result := tbtstring(tbtUnicodeString(src^.tunistring));
+ {$ENDIF}
+ else
+ begin
+ s := False;
+ Result := '';
+ end;
+ end;
+end;
+
+{$IFNDEF PS_NOWIDESTRING}
+function TPSPascalCompiler.GetWideString(Src: PIfRVariant; var s: Boolean): tbtwidestring;
+begin
+ case Src.FType.BaseType of
+ btChar: Result := tbtWidestring(Src^.tchar);
+ btString: Result := tbtWidestring(tbtstring(src^.tstring));
+ btWideChar: Result := src^.twidechar;
+ btWideString: Result := tbtWideString(src^.twidestring);
+ btUnicodeString: result := tbtUnicodeString(src^.tunistring);
+ else
+ begin
+ s := False;
+ Result := '';
+ end;
+ end;
+end;
+function TPSPascalCompiler.GetUnicodeString(Src: PIfRVariant; var s: Boolean): tbtunicodestring;
+begin
+ case Src.FType.BaseType of
+ btChar: Result := tbtWidestring(Src^.tchar);
+ btString: Result := tbtWidestring(tbtstring(src^.tstring));
+ btWideChar: Result := src^.twidechar;
+ btWideString: Result := tbtWideString(src^.twidestring);
+ btUnicodeString: result := tbtUnicodeString(src^.tunistring);
+ else
+ begin
+ s := False;
+ Result := '';
+ end;
+ end;
+end;
+{$ENDIF}
+
+function ab(b: Longint): Longint;
+begin
+ ab := Longint(b = 0);
+end;
+
+procedure Set_Union(Dest, Src: PByteArray; ByteSize: Integer);
+var
+ i: Longint;
+begin
+ for i := ByteSize -1 downto 0 do
+ Dest^[i] := Dest^[i] or Src^[i];
+end;
+
+procedure Set_Diff(Dest, Src: PByteArray; ByteSize: Integer);
+var
+ i: Longint;
+begin
+ for i := ByteSize -1 downto 0 do
+ Dest^[i] := Dest^[i] and not Src^[i];
+end;
+
+procedure Set_Intersect(Dest, Src: PByteArray; ByteSize: Integer);
+var
+ i: Longint;
+begin
+ for i := ByteSize -1 downto 0 do
+ Dest^[i] := Dest^[i] and Src^[i];
+end;
+
+procedure Set_Subset(Dest, Src: PByteArray; ByteSize: Integer; var Val: Boolean);
+var
+ i: Integer;
+begin
+ for i := ByteSize -1 downto 0 do
+ begin
+ if not (Src^[i] and Dest^[i] = Dest^[i]) then
+ begin
+ Val := False;
+ exit;
+ end;
+ end;
+ Val := True;
+end;
+
+procedure Set_Equal(Dest, Src: PByteArray; ByteSize: Integer; var Val: Boolean);
+var
+ i: Longint;
+begin
+ for i := ByteSize -1 downto 0 do
+ begin
+ if Dest^[i] <> Src^[i] then
+ begin
+ Val := False;
+ exit;
+ end;
+ end;
+ val := True;
+end;
+
+procedure Set_membership(Item: Longint; Src: PByteArray; var Val: Boolean);
+begin
+ Val := (Src^[Item shr 3] and (1 shl (Item and 7))) <> 0;
+end;
+
+procedure Set_MakeMember(Item: Longint; Src: PByteArray);
+begin
+ Src^[Item shr 3] := Src^[Item shr 3] or (1 shl (Item and 7));
+end;
+
+procedure ConvertToBoolean(SE: TPSPascalCompiler; FUseUsedTypes: Boolean; var1: PIFRVariant; b: Boolean);
+begin
+ FinalizeVariant(var1^);
+ if FUseUsedTypes then
+ Var1^.FType := se.at2ut(se.FDefaultBoolType)
+ else
+ Var1^.FType := Se.FDefaultBoolType;
+ var1^.tu32 := Ord(b);
+end;
+
+procedure ConvertToString(SE: TPSPascalCompiler; FUseUsedTypes: Boolean; var1: PIFRVariant; const s: tbtString);
+var
+ atype: TPSType;
+begin
+ FinalizeVariant(var1^);
+ atype := se.FindBaseType(btString);
+ if FUseUsedTypes then
+ InitializeVariant(var1, se.at2ut(atype))
+ else
+ InitializeVariant(var1, atype);
+ tbtstring(var1^.tstring) := s;
+end;
+{$IFNDEF PS_NOWIDESTRING}
+procedure ConvertToUnicodeString(SE: TPSPascalCompiler; FUseUsedTypes: Boolean; var1: PIFRVariant; const s: tbtunicodestring);
+var
+ atype: TPSType;
+begin
+ FinalizeVariant(var1^);
+ atype := se.FindBaseType(btUnicodeString);
+ if FUseUsedTypes then
+ InitializeVariant(var1, se.at2ut(atype))
+ else
+ InitializeVariant(var1, atype);
+ tbtunicodestring(var1^.tunistring) := s;
+end;
+{$ENDIF}
+procedure ConvertToFloat(SE: TPSPascalCompiler; FUseUsedTypes: Boolean; var1: PIfRVariant; NewType: TPSType);
+var
+ vartemp: PIfRVariant;
+ b: Boolean;
+begin
+ New(vartemp);
+ b := false;
+ if FUseUsedTypes then
+ NewType := se.at2ut(NewType);
+ InitializeVariant(vartemp, var1.FType);
+ CopyVariantContents(var1, vartemp);
+ FinalizeVariant(var1^);
+ InitializeVariant(var1, newtype);
+ case var1.ftype.basetype of
+ btSingle:
+ begin
+ if (vartemp.ftype.BaseType = btu8) or (vartemp.ftype.BaseType = btu16) or (vartemp.ftype.BaseType = btu32) then
+ var1^.tsingle := GetUInt(vartemp, b)
+ else
+ var1^.tsingle := GetInt(vartemp, b)
+ end;
+ btDouble:
+ begin
+ if (vartemp.ftype.BaseType = btu8) or (vartemp.ftype.BaseType = btu16) or (vartemp.ftype.BaseType = btu32) then
+ var1^.tdouble := GetUInt(vartemp, b)
+ else
+ var1^.tdouble := GetInt(vartemp, b)
+ end;
+ btExtended:
+ begin
+ if (vartemp.ftype.BaseType = btu8) or (vartemp.ftype.BaseType = btu16) or (vartemp.ftype.BaseType = btu32) then
+ var1^.textended:= GetUInt(vartemp, b)
+ else
+ var1^.textended:= GetInt(vartemp, b)
+ end;
+ btCurrency:
+ begin
+ if (vartemp.ftype.BaseType = btu8) or (vartemp.ftype.BaseType = btu16) or (vartemp.ftype.BaseType = btu32) then
+ var1^.tcurrency:= GetUInt(vartemp, b)
+ else
+ var1^.tcurrency:= GetInt(vartemp, b)
+ end;
+ end;
+ DisposeVariant(vartemp);
+end;
+
+
+function TPSPascalCompiler.IsCompatibleType(p1, p2: TPSType; Cast: Boolean): Boolean;
+begin
+ if
+ ((p1.BaseType = btProcPtr) and (p2 = p1)) or
+ (p1.BaseType = btPointer) or
+ (p2.BaseType = btPointer) or
+ ((p1.BaseType = btNotificationVariant) or (p1.BaseType = btVariant)) or
+ ((p2.BaseType = btNotificationVariant) or (p2.BaseType = btVariant)) or
+ (IsIntType(p1.BaseType) and IsIntType(p2.BaseType)) or
+ (IsRealType(p1.BaseType) and IsIntRealType(p2.BaseType)) or
+ (((p1.basetype = btPchar) or (p1.BaseType = btString)) and ((p2.BaseType = btString) or (p2.BaseType = btPchar))) or
+ (((p1.basetype = btPchar) or (p1.BaseType = btString)) and (p2.BaseType = btChar)) or
+ (((p1.BaseType = btArray) or (p1.BaseType = btStaticArray)) and (
+ (p2.BaseType = btArray) or (p2.BaseType = btStaticArray)) and IsCompatibleType(TPSArrayType(p1).ArrayTypeNo, TPSArrayType(p2).ArrayTypeNo, False)) or
+ ((p1.BaseType = btChar) and (p2.BaseType = btChar)) or
+ ((p1.BaseType = btSet) and (p2.BaseType = btSet)) or
+ {$IFNDEF PS_NOWIDESTRING}
+ ((p1.BaseType = btWideChar) and (p2.BaseType = btChar)) or
+ ((p1.BaseType = btWideChar) and (p2.BaseType = btWideChar)) or
+ ((p1.BaseType = btWidestring) and (p2.BaseType = btChar)) or
+ ((p1.BaseType = btWidestring) and (p2.BaseType = btWideChar)) or
+ ((p1.BaseType = btWidestring) and ((p2.BaseType = btString) or (p2.BaseType = btPchar) or (p2.BaseType = btUnicodeString))) or
+ ((p1.BaseType = btWidestring) and ((p2.BaseType = btWidestring))) or
+ ((p1.BaseType = btUnicodeString) and (p2.BaseType = btChar)) or
+ ((p1.BaseType = btUnicodeString) and (p2.BaseType = btWideChar)) or
+ ((p1.BaseType = btUnicodeString) and ((p2.BaseType = btString) or (p2.BaseType = btPchar) or (p2.BaseType = btUnicodeString))) or
+ ((p1.BaseType = btUnicodeString) and (p2.BaseType = btWidestring)) or
+ (((p1.basetype = btPchar) or (p1.BaseType = btString)) and (p2.BaseType = btWideString)or (p2.BaseType = btUnicodeString)) or
+ (((p1.basetype = btPchar) or (p1.BaseType = btString)) and (p2.BaseType = btWidechar)) or
+ (((p1.basetype = btPchar) or (p1.BaseType = btString)) and (p2.BaseType = btchar)) or
+ {$ENDIF}
+ ((p1.BaseType = btRecord) and (p2.BaseType = btrecord) and (not IsVarInCompatible(p1, p2))) or
+ ((p1.BaseType = btEnum) and (p2.BaseType = btEnum)) or
+ (Cast and IsIntType(P1.BaseType) and (p2.baseType = btEnum)) or
+ (Cast and (p1.baseType = btEnum) and IsIntType(P2.BaseType))
+ then
+ Result := True
+ // nx change start - allow casting class -> integer and vice versa
+ else if p1.BaseType = btclass then
+ Result := TPSClassType(p1).cl.IsCompatibleWith(p2) or (p2.BaseType in [btU32, btS32])
+ else if (p1.BaseType in [btU32, btS32]) then
+ Result := (p2.BaseType = btClass)
+ // nx change end
+{$IFNDEF PS_NOINTERFACES}
+ else if p1.BaseType = btInterface then
+ Result := TPSInterfaceType(p1).Intf.IsCompatibleWith(p2)
+{$ENDIF}
+ else if ((p1.BaseType = btExtClass) and (p2.BaseType = btExtClass)) then
+ begin
+ Result := TPSUndefinedClassType(p1).ExtClass.IsCompatibleWith(TPSUndefinedClassType(p2).ExtClass);
+ end
+ else
+ Result := False;
+end;
+
+
+function TPSPascalCompiler.PreCalc(FUseUsedTypes: Boolean; Var1Mod: Byte; var1: PIFRVariant; Var2Mod: Byte; Var2: PIfRVariant; Cmd: TPSBinOperatorType; Pos, Row, Col: Cardinal): Boolean;
+ { var1=dest, var2=src }
+var
+ b: Boolean;
+
+begin
+ Result := True;
+ try
+ if (IsRealType(var2.FType.BaseType) and IsIntType(var1.FType.BaseType)) then
+ ConvertToFloat(Self, FUseUsedTypes, var1, var2^.FType);
+ case Cmd of
+ otAdd:
+ begin { + }
+ case var1.FType.BaseType of
+ btU8: var1^.tu8 := var1^.tu8 + GetUint(Var2, Result);
+ btS8: var1^.ts8 := var1^.ts8 + GetInt(Var2, Result);
+ btU16: var1^.tu16 := var1^.tu16 + GetUint(Var2, Result);
+ btS16: var1^.ts16 := var1^.ts16 + Getint(Var2, Result);
+ btEnum, btU32: var1^.tu32 := var1^.tu32 + GetUint(Var2, Result);
+ btS32: var1^.ts32 := var1^.ts32 + Getint(Var2, Result);
+ {$IFNDEF PS_NOINT64}btS64: var1^.ts64 := var1^.ts64 + GetInt64(Var2, Result); {$ENDIF}
+ btSingle: var1^.tsingle := var1^.tsingle + GetReal( Var2, Result);
+ btDouble: var1^.tdouble := var1^.tdouble + GetReal( Var2, Result);
+ btExtended: var1^.textended := var1^.textended + GetReal( Var2, Result);
+ btCurrency: var1^.tcurrency := var1^.tcurrency + GetReal( Var2, Result);
+ btSet:
+ begin
+ if (var1.FType = var2.FType) then
+ begin
+ Set_Union(var1.tstring, var2.tstring, TPSSetType(var1.FType).ByteSize);
+ end else Result := False;
+ end;
+ btChar:
+ begin
+ ConvertToString(Self, FUseUsedTypes, var1, getstring(Var1, b)+getstring(Var2, b));
+ end;
+ btString: tbtstring(var1^.tstring) := tbtstring(var1^.tstring) + GetString(Var2, Result);
+ {$IFNDEF PS_NOWIDESTRING}
+ btwideString: tbtwidestring(var1^.twidestring) := tbtwidestring(var1^.twidestring) + GetWideString(Var2, Result);
+ btUnicodeString: tbtunicodestring(var1^.tunistring) := tbtunicodestring(var1^.tunistring) + GetUnicodeString(Var2, Result);
+ btWidechar:
+ begin
+ ConvertToUnicodeString(Self, FUseUsedTypes, var1, GetUnicodeString(Var1, b)+GetUnicodeString(Var2, b));
+ end;
+ {$ENDIF}
+ else Result := False;
+ end;
+ end;
+ otSub:
+ begin { - }
+ case Var1.FType.BaseType of
+ btU8: var1^.tu8 := var1^.tu8 - GetUint(Var2, Result);
+ btS8: var1^.ts8 := var1^.ts8 - Getint(Var2, Result);
+ btU16: var1^.tu16 := var1^.tu16 - GetUint(Var2, Result);
+ btS16: var1^.ts16 := var1^.ts16 - Getint(Var2, Result);
+ btEnum, btU32: var1^.tu32 := var1^.tu32 - GetUint(Var2, Result);
+ btS32: var1^.ts32 := var1^.ts32 - Getint(Var2, Result);
+ {$IFNDEF PS_NOINT64}btS64: var1^.ts64 := var1^.ts64 - GetInt64(Var2, Result); {$ENDIF}
+ btSingle: var1^.tsingle := var1^.tsingle - GetReal( Var2, Result);
+ btDouble: var1^.tdouble := var1^.tdouble - GetReal(Var2, Result);
+ btExtended: var1^.textended := var1^.textended - GetReal(Var2, Result);
+ btCurrency: var1^.tcurrency := var1^.tcurrency - GetReal( Var2, Result);
+ btSet:
+ begin
+ if (var1.FType = var2.FType) then
+ begin
+ Set_Diff(var1.tstring, var2.tstring, TPSSetType(var1.FType).ByteSize);
+ end else Result := False;
+ end;
+ else Result := False;
+ end;
+ end;
+ otMul:
+ begin { * }
+ case Var1.FType.BaseType of
+ btU8: var1^.tu8 := var1^.tu8 * GetUint(Var2, Result);
+ btS8: var1^.ts8 := var1^.ts8 * Getint(Var2, Result);
+ btU16: var1^.tu16 := var1^.tu16 * GetUint(Var2, Result);
+ btS16: var1^.ts16 := var1^.ts16 * Getint(Var2, Result);
+ btU32: var1^.tu32 := var1^.tu32 * GetUint(Var2, Result);
+ btS32: var1^.ts32 := var1^.ts32 * Getint(Var2, Result);
+ {$IFNDEF PS_NOINT64}btS64: var1^.ts64 := var1^.ts64 * GetInt64(Var2, Result); {$ENDIF}
+ btSingle: var1^.tsingle := var1^.tsingle * GetReal(Var2, Result);
+ btDouble: var1^.tdouble := var1^.tdouble * GetReal(Var2, Result);
+ btExtended: var1^.textended := var1^.textended * GetReal( Var2, Result);
+ btCurrency: var1^.tcurrency := var1^.tcurrency * GetReal( Var2, Result);
+ btSet:
+ begin
+ if (var1.FType = var2.FType) then
+ begin
+ Set_Intersect(var1.tstring, var2.tstring, TPSSetType(var1.FType).ByteSize);
+ end else Result := False;
+ end;
+ else Result := False;
+ end;
+ end;
+{$IFDEF PS_DELPHIDIV}
+ otDiv:
+ begin { / }
+ if IsIntType(var1.FType.BaseType) then
+ ConvertToFloat(self, FUseUsedTypes, var1, Self.FindType('EXTENDED'));
+ case Var1.FType.BaseType of
+ btSingle: var1^.tsingle := var1^.tsingle / GetReal( Var2, Result);
+ btDouble: var1^.tdouble := var1^.tdouble / GetReal( Var2, Result);
+ btExtended: var1^.textended := var1^.textended / GetReal( Var2, Result);
+ btCurrency: var1^.tcurrency := var1^.tcurrency / GetReal( Var2, Result);
+ else Result := False;
+ end;
+ end;
+ otIntDiv:
+ begin { / }
+ case Var1.FType.BaseType of
+ btU8: var1^.tu8 := var1^.tu8 div GetUint(Var2, Result);
+ btS8: var1^.ts8 := var1^.ts8 div Getint(Var2, Result);
+ btU16: var1^.tu16 := var1^.tu16 div GetUint(Var2, Result);
+ btS16: var1^.ts16 := var1^.ts16 div Getint(Var2, Result);
+ btU32: var1^.tu32 := var1^.tu32 div GetUint(Var2, Result);
+ btS32: var1^.ts32 := var1^.ts32 div Getint(Var2, Result);
+ {$IFNDEF PS_NOINT64}btS64: var1^.ts64 := var1^.ts64 div GetInt64(Var2, Result); {$ENDIF}
+ else Result := False;
+ end;
+ end;
+{$ELSE}
+ otDiv, otIntDiv:
+ begin { / }
+ case Var1.FType.BaseType of
+ btU8: var1^.tu8 := var1^.tu8 div GetUint(Var2, Result);
+ btS8: var1^.ts8 := var1^.ts8 div Getint(Var2, Result);
+ btU16: var1^.tu16 := var1^.tu16 div GetUint(Var2, Result);
+ btS16: var1^.ts16 := var1^.ts16 div Getint(Var2, Result);
+ btU32: var1^.tu32 := var1^.tu32 div GetUint(Var2, Result);
+ btS32: var1^.ts32 := var1^.ts32 div Getint(Var2, Result);
+ {$IFNDEF PS_NOINT64}btS64: var1^.ts64 := var1^.ts64 div GetInt64(Var2, Result); {$ENDIF}
+ btSingle: var1^.tsingle := var1^.tsingle / GetReal( Var2, Result);
+ btDouble: var1^.tdouble := var1^.tdouble / GetReal( Var2, Result);
+ btExtended: var1^.textended := var1^.textended / GetReal( Var2, Result);
+ btCurrency: var1^.tcurrency := var1^.tcurrency / GetReal( Var2, Result);
+ else Result := False;
+ end;
+ end;
+{$ENDIF}
+ otMod:
+ begin { MOD }
+ case Var1.FType.BaseType of
+ btU8: var1^.tu8 := var1^.tu8 mod GetUint(Var2, Result);
+ btS8: var1^.ts8 := var1^.ts8 mod Getint(Var2, Result);
+ btU16: var1^.tu16 := var1^.tu16 mod GetUint(Var2, Result);
+ btS16: var1^.ts16 := var1^.ts16 mod Getint(Var2, Result);
+ btU32: var1^.tu32 := var1^.tu32 mod GetUint(Var2, Result);
+ btS32: var1^.ts32 := var1^.ts32 mod Getint(Var2, Result);
+ {$IFNDEF PS_NOINT64}btS64: var1^.ts64 := var1^.ts64 mod GetInt64(Var2, Result); {$ENDIF}
+ else Result := False;
+ end;
+ end;
+ otshl:
+ begin { SHL }
+ case Var1.FType.BaseType of
+ btU8: var1^.tu8 := var1^.tu8 shl GetUint(Var2, Result);
+ btS8: var1^.ts8 := var1^.ts8 shl Getint(Var2, Result);
+ btU16: var1^.tu16 := var1^.tu16 shl GetUint(Var2, Result);
+ btS16: var1^.ts16 := var1^.ts16 shl Getint(Var2, Result);
+ btU32: var1^.tu32 := var1^.tu32 shl GetUint(Var2, Result);
+ btS32: var1^.ts32 := var1^.ts32 shl Getint(Var2, Result);
+ {$IFNDEF PS_NOINT64}btS64: var1^.ts64 := var1^.ts64 shl GetInt64(Var2, Result); {$ENDIF}
+ else Result := False;
+ end;
+ end;
+ otshr:
+ begin { SHR }
+ case Var1.FType.BaseType of
+ btU8: var1^.tu8 := var1^.tu8 shr GetUint(Var2, Result);
+ btS8: var1^.ts8 := var1^.ts8 shr Getint(Var2, Result);
+ btU16: var1^.tu16 := var1^.tu16 shr GetUint(Var2, Result);
+ btS16: var1^.ts16 := var1^.ts16 shr Getint(Var2, Result);
+ btU32: var1^.tu32 := var1^.tu32 shr GetUint(Var2, Result);
+ btS32: var1^.ts32 := var1^.ts32 shr Getint(Var2, Result);
+ {$IFNDEF PS_NOINT64}btS64: var1^.ts64 := var1^.ts64 shr GetInt64( Var2, Result); {$ENDIF}
+ else Result := False;
+ end;
+ end;
+ otAnd:
+ begin { AND }
+ case Var1.FType.BaseType of
+ btU8: var1^.tu8 := var1^.tu8 and GetUint(Var2, Result);
+ btS8: var1^.ts8 := var1^.ts8 and Getint(Var2, Result);
+ btU16: var1^.tu16 := var1^.tu16 and GetUint(Var2, Result);
+ btS16: var1^.ts16 := var1^.ts16 and Getint(Var2, Result);
+ btU32: var1^.tu32 := var1^.tu32 and GetUint(Var2, Result);
+ btS32: var1^.ts32 := var1^.ts32 and Getint(Var2, Result);
+ btEnum: var1^.ts32 := var1^.ts32 and Getint(Var2, Result);
+ {$IFNDEF PS_NOINT64}btS64: var1^.ts64 := var1^.ts64 and GetInt64(Var2, Result); {$ENDIF}
+ else Result := False;
+ end;
+ end;
+ otor:
+ begin { OR }
+ case Var1.FType.BaseType of
+ btU8: var1^.tu8 := var1^.tu8 or GetUint(Var2, Result);
+ btS8: var1^.ts8 := var1^.ts8 or Getint(Var2, Result);
+ btU16: var1^.tu16 := var1^.tu16 or GetUint(Var2, Result);
+ btS16: var1^.ts16 := var1^.ts16 or Getint(Var2, Result);
+ btU32: var1^.tu32 := var1^.tu32 or GetUint(Var2, Result);
+ btS32: var1^.ts32 := var1^.ts32 or Getint(Var2, Result);
+ {$IFNDEF PS_NOINT64}btS64: var1^.ts64 := var1^.ts64 or GetInt64(Var2, Result); {$ENDIF}
+ btEnum: var1^.ts32 := var1^.ts32 or Getint(Var2, Result);
+ else Result := False;
+ end;
+ end;
+ otxor:
+ begin { XOR }
+ case Var1.FType.BaseType of
+ btU8: var1^.tu8 := var1^.tu8 xor GetUint(Var2, Result);
+ btS8: var1^.ts8 := var1^.ts8 xor Getint(Var2, Result);
+ btU16: var1^.tu16 := var1^.tu16 xor GetUint(Var2, Result);
+ btS16: var1^.ts16 := var1^.ts16 xor Getint(Var2, Result);
+ btU32: var1^.tu32 := var1^.tu32 xor GetUint(Var2, Result);
+ btS32: var1^.ts32 := var1^.ts32 xor Getint(Var2, Result);
+ {$IFNDEF PS_NOINT64}btS64: var1^.ts64 := var1^.ts64 xor GetInt64(Var2, Result); {$ENDIF}
+ btEnum: var1^.ts32 := var1^.ts32 xor Getint(Var2, Result);
+ else Result := False;
+ end;
+ end;
+ otGreaterEqual:
+ begin { >= }
+ case Var1.FType.BaseType of
+ btU8: b := var1^.tu8 >= GetUint(Var2, Result);
+ btS8: b := var1^.ts8 >= Getint(Var2, Result);
+ btU16: b := var1^.tu16 >= GetUint(Var2, Result);
+ btS16: b := var1^.ts16 >= Getint(Var2, Result);
+ btU32: b := var1^.tu32 >= GetUint(Var2, Result);
+ btS32: b := var1^.ts32 >= Getint(Var2, Result);
+ {$IFNDEF PS_NOINT64}btS64: b := var1^.ts64 >= GetInt64(Var2, Result); {$ENDIF}
+ btSingle: b := var1^.tsingle >= GetReal( Var2, Result);
+ btDouble: b := var1^.tdouble >= GetReal( Var2, Result);
+ btExtended: b := var1^.textended >= GetReal( Var2, Result);
+ btCurrency: b := var1^.tcurrency >= GetReal( Var2, Result);
+ btSet:
+ begin
+ if (var1.FType = var2.FType) then
+ begin
+ Set_Subset(var2.tstring, var1.tstring, TPSSetType(var1.FType).ByteSize, b);
+ end else Result := False;
+ end;
+ else
+ Result := False;
+ end;
+ ConvertToBoolean(Self, FUseUsedTypes, Var1, b);
+ end;
+ otLessEqual:
+ begin { <= }
+ case Var1.FType.BaseType of
+ btU8: b := var1^.tu8 <= GetUint(Var2, Result);
+ btS8: b := var1^.ts8 <= Getint(Var2, Result);
+ btU16: b := var1^.tu16 <= GetUint(Var2, Result);
+ btS16: b := var1^.ts16 <= Getint(Var2, Result);
+ btU32: b := var1^.tu32 <= GetUint(Var2, Result);
+ btS32: b := var1^.ts32 <= Getint(Var2, Result);
+ {$IFNDEF PS_NOINT64}btS64: b := var1^.ts64 <= GetInt64(Var2, Result); {$ENDIF}
+ btSingle: b := var1^.tsingle <= GetReal( Var2, Result);
+ btDouble: b := var1^.tdouble <= GetReal( Var2, Result);
+ btExtended: b := var1^.textended <= GetReal( Var2, Result);
+ btCurrency: b := var1^.tcurrency <= GetReal( Var2, Result);
+ btSet:
+ begin
+ if (var1.FType = var2.FType) then
+ begin
+ Set_Subset(var1.tstring, var2.tstring, TPSSetType(var1.FType).ByteSize, b);
+ end else Result := False;
+ end;
+ else
+ Result := False;
+ end;
+ ConvertToBoolean(Self, FUseUsedTypes, Var1, b);
+ end;
+ otGreater:
+ begin { > }
+ case Var1.FType.BaseType of
+ btU8: b := var1^.tu8 > GetUint(Var2, Result);
+ btS8: b := var1^.ts8 > Getint(Var2, Result);
+ btU16: b := var1^.tu16 > GetUint(Var2, Result);
+ btS16: b := var1^.ts16 > Getint(Var2, Result);
+ btU32: b := var1^.tu32 > GetUint(Var2, Result);
+ btS32: b := var1^.ts32 > Getint(Var2, Result);
+ {$IFNDEF PS_NOINT64}btS64: b := var1^.ts64 > GetInt64(Var2, Result); {$ENDIF}
+ btSingle: b := var1^.tsingle > GetReal( Var2, Result);
+ btDouble: b := var1^.tdouble > GetReal( Var2, Result);
+ btExtended: b := var1^.textended > GetReal( Var2, Result);
+ btCurrency: b := var1^.tcurrency > GetReal( Var2, Result);
+ else
+ Result := False;
+ end;
+ ConvertToBoolean(Self, FUseUsedTypes, Var1, b);
+ end;
+ otLess:
+ begin { < }
+ case Var1.FType.BaseType of
+ btU8: b := var1^.tu8 < GetUint(Var2, Result);
+ btS8: b := var1^.ts8 < Getint(Var2, Result);
+ btU16: b := var1^.tu16 < GetUint(Var2, Result);
+ btS16: b := var1^.ts16 < Getint(Var2, Result);
+ btU32: b := var1^.tu32 < GetUint(Var2, Result);
+ btS32: b := var1^.ts32 < Getint(Var2, Result);
+ {$IFNDEF PS_NOINT64}btS64: b := var1^.ts64 < GetInt64(Var2, Result); {$ENDIF}
+ btSingle: b := var1^.tsingle < GetReal( Var2, Result);
+ btDouble: b := var1^.tdouble < GetReal( Var2, Result);
+ btExtended: b := var1^.textended < GetReal( Var2, Result);
+ btCurrency: b := var1^.tcurrency < GetReal( Var2, Result);
+ else
+ Result := False;
+ end;
+ ConvertToBoolean(Self, FUseUsedTypes, Var1, b);
+ end;
+ otNotEqual:
+ begin { <> }
+ case Var1.FType.BaseType of
+ btU8: b := var1^.tu8 <> GetUint(Var2, Result);
+ btS8: b := var1^.ts8 <> Getint(Var2, Result);
+ btU16: b := var1^.tu16 <> GetUint(Var2, Result);
+ btS16: b := var1^.ts16 <> Getint(Var2, Result);
+ btU32: b := var1^.tu32 <> GetUint(Var2, Result);
+ {$IFNDEF PS_NOINT64}btS64: b := var1^.ts64 <> GetInt64(Var2, Result); {$ENDIF}
+ btS32: b := var1^.ts32 <> Getint(Var2, Result);
+ btSingle: b := var1^.tsingle <> GetReal( Var2, Result);
+ btDouble: b := var1^.tdouble <> GetReal( Var2, Result);
+ btExtended: b := var1^.textended <> GetReal( Var2, Result);
+ btCurrency: b := var1^.tcurrency <> GetReal( Var2, Result);
+ btEnum: b := var1^.ts32 <> Getint(Var2, Result);
+ btString: b := tbtstring(var1^.tstring) <> GetString(var2, Result);
+ btChar: b := var1^.tchar <> GetString(var2, Result);
+ {$IFNDEF PS_NOWIDESTRING}
+ btWideString: b := tbtWideString(var1^.twidestring) <> GetWideString(var2, Result);
+ btUnicodeString: b := tbtUnicodeString(var1^.tunistring) <> GetUnicodeString(var2, Result);
+ btWideChar: b := var1^.twidechar <> GetUnicodeString(var2, Result);
+ {$ENDIF}
+ btSet:
+ begin
+ if (var1.FType = var2.FType) then
+ begin
+ Set_Equal(var1.tstring, var2.tstring, TPSSetType(var1.FType).GetByteSize, b);
+ b := not b;
+ end else Result := False;
+ end;
+ else
+ Result := False;
+ end;
+ ConvertToBoolean(Self, FUseUsedTypes, Var1, b);
+ end;
+ otEqual:
+ begin { = }
+ case Var1.FType.BaseType of
+ btU8: b := var1^.tu8 = GetUint(Var2, Result);
+ btS8: b := var1^.ts8 = Getint(Var2, Result);
+ btU16: b := var1^.tu16 = GetUint(Var2, Result);
+ btS16: b := var1^.ts16 = Getint(Var2, Result);
+ btU32: b := var1^.tu32 = GetUint(Var2, Result);
+ btS32: b := var1^.ts32 = Getint(Var2, Result);
+ {$IFNDEF PS_NOINT64}btS64: b := var1^.ts64 = GetInt64(Var2, Result); {$ENDIF}
+ btSingle: b := var1^.tsingle = GetReal( Var2, Result);
+ btDouble: b := var1^.tdouble = GetReal( Var2, Result);
+ btExtended: b := var1^.textended = GetReal( Var2, Result);
+ btCurrency: b := var1^.tcurrency = GetReal( Var2, Result);
+ btEnum: b := var1^.ts32 = Getint(Var2, Result);
+ btString: b := tbtstring(var1^.tstring) = GetString(var2, Result);
+ btChar: b := var1^.tchar = GetString(var2, Result);
+ {$IFNDEF PS_NOWIDESTRING}
+ btWideString: b := tbtWideString(var1^.twidestring) = GetWideString(var2, Result);
+ btUnicodeString: b := tbtUnicodeString(var1^.twidestring) = GetUnicodeString(var2, Result);
+ btWideChar: b := var1^.twidechar = GetUnicodeString(var2, Result);
+ {$ENDIF}
+ btSet:
+ begin
+ if (var1.FType = var2.FType) then
+ begin
+ Set_Equal(var1.tstring, var2.tstring, TPSSetType(var1.FType).ByteSize, b);
+ end else Result := False;
+ end;
+ else
+ Result := False;
+ end;
+ ConvertToBoolean(Self, FUseUsedTypes, Var1, b);
+ end;
+ otIn:
+ begin
+ if (var2.Ftype.BaseType = btset) and (TPSSetType(var2).SetType = Var1.FType) then
+ begin
+ Set_membership(GetUint(var1, result), var2.tstring, b);
+ end else Result := False;
+ end;
+ else
+ Result := False;
+ end;
+ except
+ on E: EDivByZero do
+ begin
+ Result := False;
+ MakeError('', ecDivideByZero, '');
+ Exit;
+ end;
+ on E: EZeroDivide do
+ begin
+ Result := False;
+ MakeError('', ecDivideByZero, '');
+ Exit;
+ end;
+ on E: EMathError do
+ begin
+ Result := False;
+ MakeError('', ecMathError, tbtstring(e.Message));
+ Exit;
+ end;
+ on E: Exception do
+ begin
+ Result := False;
+ MakeError('', ecInternalError, tbtstring(E.Message));
+ Exit;
+ end;
+ end;
+ if not Result then
+ begin
+ with MakeError('', ecTypeMismatch, '') do
+ begin
+ FPosition := Pos;
+ FRow := Row;
+ FCol := Col;
+ end;
+ end;
+end;
+
+function TPSPascalCompiler.IsDuplicate(const s: tbtString; const check: TPSDuplicCheck): Boolean;
+var
+ h, l: Longint;
+ x: TPSProcedure;
+begin
+ h := MakeHash(s);
+ if (s = 'RESULT') then
+ begin
+ Result := True;
+ exit;
+ end;
+ if dcTypes in Check then
+ for l := FTypes.Count - 1 downto 0 do
+ begin
+ if (TPSType(FTypes.Data[l]).NameHash = h) and
+ (TPSType(FTypes.Data[l]).Name = s) then
+ begin
+ Result := True;
+ exit;
+ end;
+ end;
+
+ if dcProcs in Check then
+ for l := FProcs.Count - 1 downto 0 do
+ begin
+ x := FProcs.Data[l];
+ if x.ClassType = TPSInternalProcedure then
+ begin
+ if (h = TPSInternalProcedure(x).NameHash) and (s = TPSInternalProcedure(x).Name) then
+ begin
+ Result := True;
+ exit;
+ end;
+ end
+ else
+ begin
+ if (TPSExternalProcedure(x).RegProc.NameHash = h) and
+ (TPSExternalProcedure(x).RegProc.Name = s) then
+ begin
+ Result := True;
+ exit;
+ end;
+ end;
+ end;
+ if dcVars in Check then
+ for l := FVars.Count - 1 downto 0 do
+ begin
+ if (TPSVar(FVars.Data[l]).NameHash = h) and
+ (TPSVar(FVars.Data[l]).Name = s) then
+ begin
+ Result := True;
+ exit;
+ end;
+ end;
+ if dcConsts in Check then
+ for l := FConstants.Count -1 downto 0 do
+ begin
+ if (TPSConstant(FConstants.Data[l]).NameHash = h) and
+ (TPSConstant(FConstants.Data[l]).Name = s) then
+ begin
+ Result := TRue;
+ exit;
+ end;
+ end;
+ Result := False;
+end;
+
+procedure ClearRecSubVals(RecSubVals: TPSList);
+var
+ I: Longint;
+begin
+ for I := 0 to RecSubVals.Count - 1 do
+ TPSRecordFieldTypeDef(RecSubVals[I]).Free;
+ RecSubVals.Free;
+end;
+
+function TPSPascalCompiler.ReadTypeAddProcedure(const Name: tbtString; FParser: TPSPascalParser): TPSType;
+var
+ IsFunction: Boolean;
+ VNames: tbtString;
+ modifier: TPSParameterMode;
+ Decl: TPSParametersDecl;
+ VCType: TPSType;
+begin
+ if FParser.CurrTokenId = CSTII_Function then
+ IsFunction := True
+ else
+ IsFunction := False;
+ Decl := TPSParametersDecl.Create;
+ try
+ FParser.Next;
+ if FParser.CurrTokenId = CSTI_OpenRound then
+ begin
+ FParser.Next;
+ if FParser.CurrTokenId <> CSTI_CloseRound then
+ begin
+ while True do
+ begin
+ if FParser.CurrTokenId = CSTII_Const then
+ begin
+ Modifier := pmIn;
+ FParser.Next;
+ end else
+ if FParser.CurrTokenId = CSTII_Out then
+ begin
+ Modifier := pmOut;
+ FParser.Next;
+ end else
+ if FParser.CurrTokenId = CSTII_Var then
+ begin
+ modifier := pmInOut;
+ FParser.Next;
+ end
+ else
+ modifier := pmIn;
+ if FParser.CurrTokenId <> CSTI_Identifier then
+ begin
+ Result := nil;
+ if FParser = Self.FParser then
+ MakeError('', ecIdentifierExpected, '');
+ exit;
+ end;
+ VNames := FParser.OriginalToken + '|';
+ FParser.Next;
+ while FParser.CurrTokenId = CSTI_Comma do
+ begin
+ FParser.Next;
+ if FParser.CurrTokenId <> CSTI_Identifier then
+ begin
+ Result := nil;
+ if FParser = Self.FParser then
+ MakeError('', ecIdentifierExpected, '');
+ exit;
+ end;
+ VNames := VNames + FParser.GetToken + '|';
+ FParser.Next;
+ end;
+ if FParser.CurrTokenId <> CSTI_Colon then
+ begin
+ Result := nil;
+ if FParser = Self.FParser then
+ MakeError('', ecColonExpected, '');
+ exit;
+ end;
+ FParser.Next;
+ if FParser.CurrTokenId <> CSTI_Identifier then
+ begin
+ Result := nil;
+ if FParser = self.FParser then
+ MakeError('', ecIdentifierExpected, '');
+ exit;
+ end;
+ VCType := FindType(FParser.GetToken);
+ if VCType = nil then
+ begin
+ if FParser = self.FParser then
+ MakeError('', ecUnknownIdentifier, FParser.OriginalToken);
+ Result := nil;
+ exit;
+ end;
+ while Pos(tbtchar('|'), VNames) > 0 do
+ begin
+ with Decl.AddParam do
+ begin
+ Mode := modifier;
+ OrgName := copy(VNames, 1, Pos(tbtchar('|'), VNames) - 1);
+ FType := VCType;
+ end;
+ Delete(VNames, 1, Pos(tbtchar('|'), VNames));
+ end;
+ FParser.Next;
+ if FParser.CurrTokenId = CSTI_CloseRound then
+ break;
+ if FParser.CurrTokenId <> CSTI_Semicolon then
+ begin
+ if FParser = Self.FParser then
+ MakeError('', ecSemicolonExpected, '');
+ Result := nil;
+ exit;
+ end;
+ FParser.Next;
+ end; {while}
+ end; {if}
+ FParser.Next;
+ end; {if}
+ if IsFunction then
+ begin
+ if FParser.CurrTokenId <> CSTI_Colon then
+ begin
+ if FParser = Self.FParser then
+ MakeError('', ecColonExpected, '');
+ Result := nil;
+ exit;
+ end;
+ FParser.Next;
+ if FParser.CurrTokenId <> CSTI_Identifier then
+ begin
+ Result := nil;
+ if FParser = Self.FParser then
+ MakeError('', ecIdentifierExpected, '');
+ exit;
+ end;
+ VCType := self.FindType(FParser.GetToken);
+ if VCType = nil then
+ begin
+ if FParser = self.FParser then
+ MakeError('', ecUnknownIdentifier, FParser.OriginalToken);
+ Result := nil;
+ exit;
+ end;
+ FParser.Next;
+ end
+ else
+ VCType := nil;
+ Decl.Result := VcType;
+ VCType := TPSProceduralType.Create;
+ VCType.Name := FastUppercase(Name);
+ VCType.OriginalName := Name;
+ VCType.BaseType := btProcPtr;
+ {$IFDEF PS_USESSUPPORT}
+ VCType.DeclareUnit:=fModule;
+ {$ENDIF}
+ VCType.DeclarePos := FParser.CurrTokenPos;
+ VCType.DeclareRow := FParser.Row;
+ VCType.DeclareCol := FParser.Col;
+ TPSProceduralType(VCType).ProcDef.Assign(Decl);
+ FTypes.Add(VCType);
+ Result := VCType;
+ finally
+ Decl.Free;
+ end;
+end; {ReadTypeAddProcedure}
+
+
+function TPSPascalCompiler.ReadType(const Name: tbtString; FParser: TPSPascalParser): TPSType; // InvalidVal = Invalid
+var
+ TypeNo: TPSType;
+ h, l: Longint;
+ FieldName,fieldorgname,s: tbtString;
+ RecSubVals: TPSList;
+ FArrayStart, FArrayLength: Longint;
+ rvv: PIFPSRecordFieldTypeDef;
+ p, p2: TPSType;
+ tempf: PIfRVariant;
+{$IFNDEF PS_NOINTERFACES}
+ InheritedFrom: tbtString;
+ Guid: TGUID;
+ Intf: TPSInterface;
+{$ENDIF}
+begin
+ if (FParser.CurrTokenID = CSTII_Function) or (FParser.CurrTokenID = CSTII_Procedure) then
+ begin
+ Result := ReadTypeAddProcedure(Name, FParser);
+ Exit;
+ end else if FParser.CurrTokenId = CSTII_Set then
+ begin
+ FParser.Next;
+ if FParser.CurrTokenId <> CSTII_Of then
+ begin
+ MakeError('', ecOfExpected, '');
+ Result := nil;
+ Exit;
+ end;
+ FParser.Next;
+ if FParser.CurrTokenID <> CSTI_Identifier then
+ begin
+ MakeError('', ecIdentifierExpected, '');
+ Result := nil;
+ exit;
+ end;
+ TypeNo := FindType(FParser.GetToken);
+ if TypeNo = nil then
+ begin
+ MakeError('', ecUnknownIdentifier, '');
+ Result := nil;
+ exit;
+ end;
+ if (TypeNo.BaseType = btEnum) or (TypeNo.BaseType = btChar) or (TypeNo.BaseType = btU8) then
+ begin
+ FParser.Next;
+ p2 := TPSSetType.Create;
+ p2.Name := FastUppercase(Name);
+ p2.OriginalName := Name;
+ p2.BaseType := btSet;
+ {$IFDEF PS_USESSUPPORT}
+ p2.DeclareUnit:=fModule;
+ {$ENDIF}
+ p2.DeclarePos := FParser.CurrTokenPos;
+ p2.DeclareRow := FParser.Row;
+ p2.DeclareCol := FParser.Col;
+ TPSSetType(p2).SetType := TypeNo;
+ FTypes.Add(p2);
+ Result := p2;
+ end else
+ begin
+ MakeError('', ecTypeMismatch, '');
+ Result := nil;
+ end;
+ exit;
+ end else if FParser.CurrTokenId = CSTI_OpenRound then
+ begin
+ FParser.Next;
+ L := 0;
+ P2 := TPSEnumType.Create;
+ P2.Name := FastUppercase(Name);
+ p2.OriginalName := Name;
+ p2.BaseType := btEnum;
+ {$IFDEF PS_USESSUPPORT}
+ p2.DeclareUnit:=fModule;
+ {$ENDIF}
+ p2.DeclarePos := FParser.CurrTokenPos;
+ p2.DeclareRow := FParser.Row;
+ p2.DeclareCol := FParser.Col;
+ FTypes.Add(p2);
+
+ repeat
+ if FParser.CurrTokenId <> CSTI_Identifier then
+ begin
+ if FParser = Self.FParser then
+ MakeError('', ecIdentifierExpected, '');
+ Result := nil;
+ exit;
+ end;
+ s := FParser.OriginalToken;
+ if IsDuplicate(FastUppercase(s), [dcTypes]) then
+ begin
+ if FParser = Self.FParser then
+ MakeError('', ecDuplicateIdentifier, s);
+ Result := nil;
+ Exit;
+ end;
+ with AddConstant(s, p2) do
+ begin
+ FValue.tu32 := L;
+ {$IFDEF PS_USESSUPPORT}
+ DeclareUnit:=fModule;
+ {$ENDIF}
+ DeclarePos:=FParser.CurrTokenPos;
+ DeclareRow:=FParser.Row;
+ DeclareCol:=FParser.Col;
+ end;
+ Inc(L);
+ FParser.Next;
+ if FParser.CurrTokenId = CSTI_CloseRound then
+ Break
+ else if FParser.CurrTokenId <> CSTI_Comma then
+ begin
+ if FParser = Self.FParser then
+ MakeError('', ecCloseRoundExpected, '');
+ Result := nil;
+ Exit;
+ end;
+ FParser.Next;
+ until False;
+ FParser.Next;
+ TPSEnumType(p2).HighValue := L-1;
+ Result := p2;
+ exit;
+ end else
+ if FParser.CurrTokenId = CSTII_Array then
+ begin
+ FParser.Next;
+ if FParser.CurrTokenID = CSTI_OpenBlock then
+ begin
+ FParser.Next;
+ tempf := ReadConstant(FParser, CSTI_TwoDots);
+ if tempf = nil then
+ begin
+ Result := nil;
+ exit;
+ end;
+ case tempf.FType.BaseType of
+ btU8: FArrayStart := tempf.tu8;
+ btS8: FArrayStart := tempf.ts8;
+ btU16: FArrayStart := tempf.tu16;
+ btS16: FArrayStart := tempf.ts16;
+ btU32: FArrayStart := tempf.tu32;
+ btS32: FArrayStart := tempf.ts32;
+ {$IFNDEF PS_NOINT64}
+ bts64: FArrayStart := tempf.ts64;
+ {$ENDIF}
+ else
+ begin
+ DisposeVariant(tempf);
+ MakeError('', ecTypeMismatch, '');
+ Result := nil;
+ exit;
+ end;
+ end;
+ DisposeVariant(tempf);
+ if FParser.CurrTokenID <> CSTI_TwoDots then
+ begin
+ MakeError('', ecPeriodExpected, '');
+ Result := nil;
+ exit;
+ end;
+ FParser.Next;
+ tempf := ReadConstant(FParser, CSTI_CloseBlock);
+ if tempf = nil then
+ begin
+ Result := nil;
+ exit;
+ end;
+ case tempf.FType.BaseType of
+ btU8: FArrayLength := tempf.tu8;
+ btS8: FArrayLength := tempf.ts8;
+ btU16: FArrayLength := tempf.tu16;
+ btS16: FArrayLength := tempf.ts16;
+ btU32: FArrayLength := tempf.tu32;
+ btS32: FArrayLength := tempf.ts32;
+ {$IFNDEF PS_NOINT64}
+ bts64: FArrayLength := tempf.ts64;
+ {$ENDIF}
+ else
+ DisposeVariant(tempf);
+ MakeError('', ecTypeMismatch, '');
+ Result := nil;
+ exit;
+ end;
+ DisposeVariant(tempf);
+ FArrayLength := FArrayLength - FArrayStart + 1;
+ if (FArrayLength < 0) or (FArrayLength > MaxInt div 4) then
+ begin
+ MakeError('', ecTypeMismatch, '');
+ Result := nil;
+ exit;
+ end;
+ if FParser.CurrTokenID <> CSTI_CloseBlock then
+ begin
+ MakeError('', ecCloseBlockExpected, '');
+ Result := nil;
+ exit;
+ end;
+ FParser.Next;
+ end else
+ begin
+ FArrayStart := 0;
+ FArrayLength := -1;
+ end;
+ if FParser.CurrTokenId <> CSTII_Of then
+ begin
+ if FParser = Self.FParser then
+ MakeError('', ecOfExpected, '');
+ Result := nil;
+ exit;
+ end;
+ FParser.Next;
+ TypeNo := ReadType('', FParser);
+ if TypeNo = nil then
+ begin
+ if FParser = Self.FParser then
+ MakeError('', ecUnknownIdentifier, '');
+ Result := nil;
+ exit;
+ end;
+ if (Name = '') and (FArrayLength = -1) then
+ begin
+ if TypeNo.Used then
+ begin
+ for h := 0 to FTypes.Count -1 do
+ begin
+ p := FTypes[H];
+ if (p.BaseType = btArray) and (TPSArrayType(p).ArrayTypeNo = TypeNo) and (Copy(p.Name, 1, 1) <> '!') then
+ begin
+ Result := p;
+ exit;
+ end;
+ end;
+ end;
+ end;
+ if FArrayLength <> -1 then
+ begin
+ p := TPSStaticArrayType.Create;
+ TPSStaticArrayType(p).StartOffset := FArrayStart;
+ TPSStaticArrayType(p).Length := FArrayLength;
+ p.BaseType := btStaticArray;
+ end else
+ begin
+ p := TPSArrayType.Create;
+ p.BaseType := btArray;
+ end;
+ p.Name := FastUppercase(Name);
+ p.OriginalName := Name;
+ {$IFDEF PS_USESSUPPORT}
+ p.DeclareUnit:=fModule;
+ {$ENDIF}
+ p.DeclarePos := FParser.CurrTokenPos;
+ p.DeclareRow := FParser.Row;
+ p.DeclareCol := FParser.Col;
+ TPSArrayType(p).ArrayTypeNo := TypeNo;
+ FTypes.Add(p);
+ Result := p;
+ Exit;
+ end
+ else if FParser.CurrTokenId = CSTII_Record then
+ begin
+ FParser.Next;
+ RecSubVals := TPSList.Create;
+ repeat
+ repeat
+ if FParser.CurrTokenId <> CSTI_Identifier then
+ begin
+ ClearRecSubVals(RecSubVals);
+ if FParser = Self.FParser then
+ MakeError('', ecIdentifierExpected, '');
+ Result := nil;
+ exit;
+ end;
+ FieldName := FParser.GetToken;
+ s := S+FParser.OriginalToken+'|';
+ FParser.Next;
+ h := MakeHash(FieldName);
+ for l := 0 to RecSubVals.Count - 1 do
+ begin
+ if (PIFPSRecordFieldTypeDef(RecSubVals[l]).FieldNameHash = h) and
+ (PIFPSRecordFieldTypeDef(RecSubVals[l]).FieldName = FieldName) then
+ begin
+ if FParser = Self.FParser then
+ MakeError('', ecDuplicateIdentifier, FParser.OriginalToken);
+ ClearRecSubVals(RecSubVals);
+ Result := nil;
+ exit;
+ end;
+ end;
+ if FParser.CurrTokenID = CSTI_Colon then Break else
+ if FParser.CurrTokenID <> CSTI_Comma then
+ begin
+ if FParser = Self.FParser then
+ MakeError('', ecColonExpected, '');
+ ClearRecSubVals(RecSubVals);
+ Result := nil;
+ exit;
+ end;
+ FParser.Next;
+ until False;
+ FParser.Next;
+ p := ReadType('', FParser);
+ if p = nil then
+ begin
+ ClearRecSubVals(RecSubVals);
+ Result := nil;
+ exit;
+ end;
+ p := GetTypeCopyLink(p);
+ if FParser.CurrTokenId <> CSTI_Semicolon then
+ begin
+ ClearRecSubVals(RecSubVals);
+ if FParser = Self.FParser then
+ MakeError('', ecSemicolonExpected, '');
+ Result := nil;
+ exit;
+ end; {if}
+ FParser.Next;
+ while Pos(tbtchar('|'), s) > 0 do
+ begin
+ fieldorgname := copy(s, 1, Pos(tbtchar('|'), s)-1);
+ Delete(s, 1, length(FieldOrgName)+1);
+ rvv := TPSRecordFieldTypeDef.Create;
+ rvv.FieldOrgName := fieldorgname;
+ rvv.FType := p;
+ RecSubVals.Add(rvv);
+ end;
+ until FParser.CurrTokenId = CSTII_End;
+ FParser.Next; // skip CSTII_End
+ P := TPSRecordType.Create;
+ p.Name := FastUppercase(Name);
+ p.OriginalName := Name;
+ p.BaseType := btRecord;
+ {$IFDEF PS_USESSUPPORT}
+ p.DeclareUnit:=fModule;
+ {$ENDIF}
+ p.DeclarePos := FParser.CurrTokenPos;
+ p.DeclareRow := FParser.Row;
+ p.DeclareCol := FParser.Col;
+ for l := 0 to RecSubVals.Count -1 do
+ begin
+ rvv := RecSubVals[l];
+ with TPSRecordType(p).AddRecVal do
+ begin
+ FieldOrgName := rvv.FieldOrgName;
+ FType := rvv.FType;
+ end;
+ rvv.Free;
+ end;
+ RecSubVals.Free;
+ FTypes.Add(p);
+ Result := p;
+ Exit;
+{$IFNDEF PS_NOINTERFACES}
+ end else if FParser.CurrTokenId = CSTII_Interface then
+ begin
+ FParser.Next;
+ if FParser.CurrTokenId <> CSTI_OpenRound then
+ begin
+ MakeError('', ecOpenRoundExpected, '');
+ Result := nil;
+ Exit;
+ end;
+ FParser.Next;
+ if FParser.CurrTokenID <> CSTI_Identifier then
+ begin
+ MakeError('', ecIdentifierExpected, '');
+ Result := nil;
+ exit;
+ end;
+ InheritedFrom := FParser.GetToken;
+ TypeNo := FindType(InheritedFrom);
+ if TypeNo = nil then
+ begin
+ MakeError('', ecUnknownType, FParser.GetToken);
+ Result := nil;
+ exit;
+ end;
+ if TypeNo.BaseType <> btInterface then
+ begin
+ MakeError('', ecTypeMismatch, '');
+ Result := nil;
+ Exit;
+ end;
+ FParser.Next;
+ if FParser.CurrTokenId <> CSTI_CloseRound then
+ begin
+ MakeError('', ecCloseRoundExpected, '');
+ Result := nil;
+ Exit;
+ end;
+{$IFNDEF PS_NOINTERFACEGUIDBRACKETS}
+ FParser.Next;
+ if FParser.CurrTokenId <> CSTI_OpenBlock then
+ begin
+ MakeError('', ecOpenBlockExpected, '');
+ Result := nil;
+ Exit;
+ end;
+{$ENDIF}
+ FParser.Next;
+ if FParser.CurrTokenId <> CSTI_String then
+ begin
+ MakeError('', ecStringExpected, '');
+ Result := nil;
+ Exit;
+ end;
+ s := FParser.GetToken;
+ try
+ Guid := StringToGuid(String(Copy(s, 2, Length(s)-2)));
+ except
+ on e: Exception do
+ begin
+ MakeError('', ecCustomError, tbtstring(e.Message));
+ Result := nil;
+ Exit;
+ end;
+ end;
+{$IFNDEF PS_NOINTERFACEGUIDBRACKETS}
+ FParser.Next;
+ if FParser.CurrTokenId <> CSTI_CloseBlock then
+ begin
+ MakeError('', ecCloseBlockExpected, '');
+ Result := nil;
+ Exit;
+ end;
+{$ENDIF}
+ Intf := AddInterface(FindInterface(InheritedFrom), Guid, Name);
+ FParser.Next;
+ repeat
+ if not Intf.RegisterMethodEx('', cdStdCall, FParser) then begin
+ MakeError('', ecCustomError, 'Invalid method');
+ Result := nil;
+ Exit;
+ end;
+ FParser.Next;
+ until FParser.CurrTokenId = CSTII_End;
+ FParser.Next; // skip CSTII_End
+ Result := Intf.FType;
+ Exit;
+{$ENDIF}
+ end else if FParser.CurrTokenId = CSTI_Identifier then
+ begin
+ s := FParser.GetToken;
+ h := MakeHash(s);
+ Typeno := nil;
+ for l := 0 to FTypes.Count - 1 do
+ begin
+ p2 := FTypes[l];
+ if (p2.NameHash = h) and (p2.Name = s) then
+ begin
+ FParser.Next;
+ Typeno := GetTypeCopyLink(p2);
+ Break;
+ end;
+ end;
+ if Typeno = nil then
+ begin
+ Result := nil;
+ if FParser = Self.FParser then
+ MakeError('', ecUnknownType, FParser.OriginalToken);
+ exit;
+ end;
+ if Name <> '' then
+ begin
+ p := TPSTypeLink.Create;
+ p.Name := FastUppercase(Name);
+ p.OriginalName := Name;
+ p.BaseType := BtTypeCopy;
+ {$IFDEF PS_USESSUPPORT}
+ p.DeclareUnit:=fModule;
+ {$ENDIF}
+ p.DeclarePos := FParser.CurrTokenPos;
+ p.DeclareRow := FParser.Row;
+ p.DeclareCol := FParser.Col;
+ TPSTypeLink(p).LinkTypeNo := TypeNo;
+ FTypes.Add(p);
+ Result := p;
+ Exit;
+ end else
+ begin
+ Result := TypeNo;
+ exit;
+ end;
+ end;
+ Result := nil;
+ if FParser = Self.FParser then
+ MakeError('', ecIdentifierExpected, '');
+ Exit;
+end;
+
+function TPSPascalCompiler.VarIsDuplicate(Proc: TPSInternalProcedure; const Varnames, s: tbtString): Boolean;
+var
+ h, l: Longint;
+ x: TPSProcedure;
+ v: tbtString;
+begin
+ h := MakeHash(s);
+ if (s = 'RESULT') then
+ begin
+ Result := True;
+ exit;
+ end;
+
+ for l := FProcs.Count - 1 downto 0 do
+ begin
+ x := FProcs.Data[l];
+ if x.ClassType = TPSInternalProcedure then
+ begin
+ if (h = TPSInternalProcedure(x).NameHash) and (s = TPSInternalProcedure(x).Name) then
+ begin
+ Result := True;
+ exit;
+ end;
+ end
+ else
+ begin
+ if (TPSExternalProcedure(x).RegProc.NameHash = h) and (TPSExternalProcedure(x).RegProc.Name = s) then
+ begin
+ Result := True;
+ exit;
+ end;
+ end;
+ end;
+ if proc <> nil then
+ begin
+ for l := proc.ProcVars.Count - 1 downto 0 do
+ begin
+ if (PIFPSProcVar(proc.ProcVars.Data[l]).NameHash = h) and
+ (PIFPSProcVar(proc.ProcVars.Data[l]).Name = s) then
+ begin
+ Result := True;
+ exit;
+ end;
+ end;
+ for l := Proc.FDecl.ParamCount -1 downto 0 do
+ begin
+ if (Proc.FDecl.Params[l].Name = s) then
+ begin
+ Result := True;
+ exit;
+ end;
+ end;
+ end
+ else
+ begin
+ for l := FVars.Count - 1 downto 0 do
+ begin
+ if (TPSVar(FVars.Data[l]).NameHash = h) and
+ (TPSVar(FVars.Data[l]).Name = s) then
+ begin
+ Result := True;
+ exit;
+ end;
+ end;
+ end;
+ v := VarNames;
+ while Pos(tbtchar('|'), v) > 0 do
+ begin
+ if FastUppercase(copy(v, 1, Pos(tbtchar('|'), v) - 1)) = s then
+ begin
+ Result := True;
+ exit;
+ end;
+ Delete(v, 1, Pos(tbtchar('|'), v));
+ end;
+ for l := FConstants.Count -1 downto 0 do
+ begin
+ if (TPSConstant(FConstants.Data[l]).NameHash = h) and
+ (TPSConstant(FConstants.Data[l]).Name = s) then
+ begin
+ Result := True;
+ exit;
+ end;
+ end;
+ Result := False;
+end;
+
+
+function TPSPascalCompiler.DoVarBlock(proc: TPSInternalProcedure): Boolean;
+var
+ VarName, s: tbtString;
+ VarType: TPSType;
+ VarNo: Cardinal;
+ v: TPSVar;
+ vp: PIFPSProcVar;
+ EPos, ERow, ECol: Integer;
+begin
+ Result := False;
+ FParser.Next; // skip CSTII_Var
+ if FParser.CurrTokenId <> CSTI_Identifier then
+ begin
+ MakeError('', ecIdentifierExpected, '');
+ exit;
+ end;
+ repeat
+ VarNAme := '';
+ if VarIsDuplicate(proc, VarName, FParser.GetToken) then
+ begin
+ MakeError('', ecDuplicateIdentifier, FParser.OriginalToken);
+ exit;
+ end;
+ VarName := FParser.OriginalToken + '|';
+ Varno := 0;
+ if @FOnUseVariable <> nil then
+ begin
+ if Proc <> nil then
+ FOnUseVariable(Self, ivtVariable, Proc.ProcVars.Count + VarNo, FProcs.Count -1, FParser.CurrTokenPos, '')
+ else
+ FOnUseVariable(Self, ivtGlobal, FVars.Count + VarNo, InvalidVal, FParser.CurrTokenPos, '')
+ end;
+ EPos:=FParser.CurrTokenPos;
+ ERow:=FParser.Row;
+ ECol:=FParser.Col;
+ FParser.Next;
+ while FParser.CurrTokenId = CSTI_Comma do
+ begin
+ FParser.Next;
+ if FParser.CurrTokenId <> CSTI_Identifier then
+ begin
+ MakeError('', ecIdentifierExpected, '');
+ end;
+ if VarIsDuplicate(proc, VarName, FParser.GetToken) then
+ begin
+ MakeError('', ecDuplicateIdentifier, FParser.OriginalToken);
+ exit;
+ end;
+ VarName := VarName + FParser.OriginalToken + '|';
+ Inc(varno);
+ if @FOnUseVariable <> nil then
+ begin
+ if Proc <> nil then
+ FOnUseVariable(Self, ivtVariable, Proc.ProcVars.Count + VarNo, FProcs.Count -1, FParser.CurrTokenPos, '')
+ else
+ FOnUseVariable(Self, ivtGlobal, FVars.Count + VarNo, InvalidVal, FParser.CurrTokenPos, '')
+ end;
+ FParser.Next;
+ end;
+ if FParser.CurrTokenId <> CSTI_Colon then
+ begin
+ MakeError('', ecColonExpected, '');
+ exit;
+ end;
+ FParser.Next;
+ VarType := at2ut(ReadType('', FParser));
+ if VarType = nil then
+ begin
+ exit;
+ end;
+ while Pos(tbtchar('|'), VarName) > 0 do
+ begin
+ s := copy(VarName, 1, Pos(tbtchar('|'), VarName) - 1);
+ Delete(VarName, 1, Pos(tbtchar('|'), VarName));
+ if proc = nil then
+ begin
+ v := TPSVar.Create;
+ v.OrgName := s;
+ v.Name := FastUppercase(s);
+ {$IFDEF PS_USESSUPPORT}
+ v.DeclareUnit:=fModule;
+ {$ENDIF}
+ v.DeclarePos := EPos;
+ v.DeclareRow := ERow;
+ v.DeclareCol := ECol;
+ v.FType := VarType;
+ FVars.Add(v);
+ end
+ else
+ begin
+ vp := TPSProcVar.Create;
+ vp.OrgName := s;
+ vp.Name := FastUppercase(s);
+ vp.aType := VarType;
+ {$IFDEF PS_USESSUPPORT}
+ vp.DeclareUnit:=fModule;
+ {$ENDIF}
+ vp.DeclarePos := EPos;
+ vp.DeclareRow := ERow;
+ vp.DeclareCol := ECol;
+ proc.ProcVars.Add(vp);
+ end;
+ end;
+ if FParser.CurrTokenId <> CSTI_Semicolon then
+ begin
+ MakeError('', ecSemicolonExpected, '');
+ exit;
+ end;
+ FParser.Next;
+ until FParser.CurrTokenId <> CSTI_Identifier;
+ Result := True;
+end;
+
+function TPSPascalCompiler.NewProc(const OriginalName, Name: tbtString): TPSInternalProcedure;
+begin
+ Result := TPSInternalProcedure.Create;
+ Result.OriginalName := OriginalName;
+ Result.Name := Name;
+ {$IFDEF PS_USESSUPPORT}
+ Result.DeclareUnit:=fModule;
+ {$ENDIF}
+ Result.DeclarePos := FParser.CurrTokenPos;
+ Result.DeclareRow := FParser.Row;
+ Result.DeclareCol := FParser.Col;
+ FProcs.Add(Result);
+end;
+
+function TPSPascalCompiler.IsProcDuplicLabel(Proc: TPSInternalProcedure; const s: tbtString): Boolean;
+var
+ i: Longint;
+ h: Longint;
+ u: tbtString;
+begin
+ h := MakeHash(s);
+ if s = 'RESULT' then
+ Result := True
+ else if Proc.Name = s then
+ Result := True
+ else if IsDuplicate(s, [dcVars, dcConsts, dcProcs]) then
+ Result := True
+ else
+ begin
+ for i := 0 to Proc.Decl.ParamCount -1 do
+ begin
+ if Proc.Decl.Params[i].Name = s then
+ begin
+ Result := True;
+ exit;
+ end;
+ end;
+ for i := 0 to Proc.ProcVars.Count -1 do
+ begin
+ if (PIFPSProcVar(Proc.ProcVars[I]).NameHash = h) and (PIFPSProcVar(Proc.ProcVars[I]).Name = s) then
+ begin
+ Result := True;
+ exit;
+ end;
+ end;
+ for i := 0 to Proc.FLabels.Count -1 do
+ begin
+ u := Proc.FLabels[I];
+ delete(u, 1, 4);
+ if Longint((@u[1])^) = h then
+ begin
+ delete(u, 1, 4);
+ if u = s then
+ begin
+ Result := True;
+ exit;
+ end;
+ end;
+ end;
+ Result := False;
+ end;
+end;
+
+
+function TPSPascalCompiler.ProcessLabel(Proc: TPSInternalProcedure): Boolean;
+var
+ CurrLabel: tbtString;
+begin
+ FParser.Next;
+ while true do
+ begin
+ if FParser.CurrTokenId <> CSTI_Identifier then
+ begin
+ MakeError('', ecIdentifierExpected, '');
+ Result := False;
+ exit;
+ end;
+ CurrLabel := FParser.GetToken;
+ if IsProcDuplicLabel(Proc, CurrLabel) then
+ begin
+ MakeError('', ecDuplicateIdentifier, CurrLabel);
+ Result := False;
+ exit;
+ end;
+ FParser.Next;
+ Proc.FLabels.Add(#$FF#$FF#$FF#$FF+PS_mi2s(MakeHash(CurrLabel))+CurrLabel);
+ if FParser.CurrTokenId = CSTI_Semicolon then
+ begin
+ FParser.Next;
+ Break;
+ end;
+ if FParser.CurrTokenId <> CSTI_Comma then
+ begin
+ MakeError('', ecCommaExpected, '');
+ Result := False;
+ exit;
+ end;
+ FParser.Next;
+ end;
+ Result := True;
+end;
+
+procedure TPSPascalCompiler.Debug_SavePosition(ProcNo: Cardinal; Proc: TPSInternalProcedure);
+var
+ Row,
+ Col,
+ Pos: Cardinal;
+ s: tbtString;
+begin
+ Row := FParser.Row;
+ Col := FParser.Col;
+ Pos := FParser.CurrTokenPos;
+ {$IFNDEF PS_USESSUPPORT}
+ s := '';
+ {$ELSE}
+ s := fModule;
+ {$ENDIF}
+ if @FOnTranslateLineInfo <> nil then
+ FOnTranslateLineInfo(Self, Pos, Row, Col, S);
+ {$IFDEF FPC}
+ WriteDebugData(#4 + s + #1);
+ WriteDebugData(Ps_mi2s(ProcNo));
+ WriteDebugData(Ps_mi2s(Length(Proc.Data)));
+ WriteDebugData(Ps_mi2s(Pos));
+ WriteDebugData(Ps_mi2s(Row));
+ WriteDebugData(Ps_mi2s(Col));
+ {$ELSE}
+ WriteDebugData(#4 + s + #1 + PS_mi2s(ProcNo) + PS_mi2s(Length(Proc.Data)) + PS_mi2s(Pos) + PS_mi2s(Row)+ PS_mi2s(Col));
+ {$ENDIF}
+end;
+
+procedure TPSPascalCompiler.Debug_WriteParams(ProcNo: Cardinal; Proc: TPSInternalProcedure);
+var
+ I: Longint;
+ s: tbtString;
+begin
+ s := #2 + PS_mi2s(ProcNo);
+ if Proc.Decl.Result <> nil then
+ begin
+ s := s + 'Result' + #1;
+ end;
+ for i := 0 to Proc.Decl.ParamCount -1 do
+ s := s + Proc.Decl.Params[i].OrgName + #1;
+ s := s + #0#3 + PS_mi2s(ProcNo);
+ for I := 0 to Proc.ProcVars.Count - 1 do
+ begin
+ s := s + PIFPSProcVar(Proc.ProcVars[I]).OrgName + #1;
+ end;
+ s := s + #0;
+ WriteDebugData(s);
+end;
+
+procedure TPSPascalCompiler.CheckForUnusedVars(Func: TPSInternalProcedure);
+var
+ i: Integer;
+ p: PIFPSProcVar;
+begin
+ for i := 0 to Func.ProcVars.Count -1 do
+ begin
+ p := Func.ProcVars[I];
+ if not p.Used then
+ begin
+ with MakeHint({$IFDEF PS_USESSUPPORT}p.DeclareUnit{$ELSE}''{$ENDIF}, ehVariableNotUsed, p.Name) do
+ begin
+ FRow := p.DeclareRow;
+ FCol := p.DeclareCol;
+ FPosition := p.DeclarePos;
+ end;
+ end;
+ end;
+ if (not Func.ResultUsed) and (Func.Decl.Result <> nil) then
+ begin
+ with MakeHint({$IFDEF PS_USESSUPPORT}Func.DeclareUnit{$ELSE}''{$ENDIF}, ehVariableNotUsed, 'Result') do
+ begin
+ FRow := Func.DeclareRow;
+ FCol := Func.DeclareCol;
+ FPosition := Func.DeclarePos;
+ end;
+ end;
+end;
+
+function TPSPascalCompiler.ProcIsDuplic(Decl: TPSParametersDecl; const FunctionName, FunctionParamNames: tbtString; const s: tbtString; Func: TPSInternalProcedure): Boolean;
+var
+ i: Longint;
+ u: tbtString;
+begin
+ if s = 'RESULT' then
+ Result := True
+ else if FunctionName = s then
+ Result := True
+ else
+ begin
+ for i := 0 to Decl.ParamCount -1 do
+ begin
+ if Decl.Params[i].Name = s then
+ begin
+ Result := True;
+ exit;
+ end;
+ GRFW(u);
+ end;
+ u := FunctionParamNames;
+ while Pos(tbtchar('|'), u) > 0 do
+ begin
+ if copy(u, 1, Pos(tbtchar('|'), u) - 1) = s then
+ begin
+ Result := True;
+ exit;
+ end;
+ Delete(u, 1, Pos(tbtchar('|'), u));
+ end;
+ if Func = nil then
+ begin
+ result := False;
+ exit;
+ end;
+ for i := 0 to Func.ProcVars.Count -1 do
+ begin
+ if s = PIFPSProcVar(Func.ProcVars[I]).Name then
+ begin
+ Result := True;
+ exit;
+ end;
+ end;
+ for i := 0 to Func.FLabels.Count -1 do
+ begin
+ u := Func.FLabels[I];
+ delete(u, 1, 4);
+ if u = s then
+ begin
+ Result := True;
+ exit;
+ end;
+ end;
+ Result := False;
+ end;
+end;
+procedure WriteProcVars(Func:TPSInternalProcedure; t: TPSList);
+var
+ l: Longint;
+ v: PIFPSProcVar;
+begin
+ for l := 0 to t.Count - 1 do
+ begin
+ v := t[l];
+ Func.Data := Func.Data + chr(cm_pt)+ PS_mi2s(v.AType.FinalTypeNo);
+ end;
+end;
+
+
+function TPSPascalCompiler.ApplyAttribsToFunction(func: TPSProcedure): boolean;
+var
+ i: Longint;
+begin
+ for i := 0 to Func.Attributes.Count -1 do
+ begin
+ if @Func.Attributes.Items[i].AType.OnApplyAttributeToProc <> nil then
+ begin
+ if not Func.Attributes.Items[i].AType.OnApplyAttributeToProc(Self, Func, Func.Attributes.Items[i]) then
+ begin
+ Result := false;
+ exit;
+ end;
+ end;
+ end;
+ result := true;
+end;
+
+
+function TPSPascalCompiler.ProcessFunction(AlwaysForward: Boolean; Att: TPSAttributes): Boolean;
+var
+ FunctionType: TFuncType;
+ OriginalName, FunctionName: tbtString;
+ FunctionParamNames: tbtString;
+ FunctionTempType: TPSType;
+ ParamNo: Cardinal;
+ FunctionDecl: TPSParametersDecl;
+ modifier: TPSParameterMode;
+ Func: TPSInternalProcedure;
+ F2: TPSProcedure;
+ EPos, ECol, ERow: Cardinal;
+ E2Pos, E2Col, E2Row: Cardinal;
+ pp: TPSRegProc;
+ pp2: TPSExternalProcedure;
+ FuncNo, I: Longint;
+ Block: TPSBlockInfo;
+begin
+ if att = nil then
+ begin
+ Att := TPSAttributes.Create;
+ if not ReadAttributes(Att) then
+ begin
+ att.free;
+ Result := false;
+ exit;
+ end;
+ end;
+
+ if FParser.CurrTokenId = CSTII_Procedure then
+ FunctionType := ftProc
+ else
+ FunctionType := ftFunc;
+ Func := nil;
+ EPos := FParser.CurrTokenPos;
+ ERow := FParser.Row;
+ ECol := FParser.Col;
+ FParser.Next;
+ Result := False;
+ if FParser.CurrTokenId <> CSTI_Identifier then
+ begin
+ MakeError('', ecIdentifierExpected, '');
+ att.free;
+ exit;
+ end;
+ if assigned(FOnFunctionStart) then
+ {$IFDEF PS_USESSUPPORT}
+ FOnFunctionStart(fModule + '.' + FParser.OriginalToken, EPos, ERow, ECol);
+ {$ELSE}
+ FOnFunctionStart(FParser.OriginalToken, EPos, ERow, ECol);
+ {$ENDIF}
+ EPos := FParser.CurrTokenPos;
+ ERow := FParser.Row;
+ ECol := FParser.Col;
+ OriginalName := FParser.OriginalToken;
+ FunctionName := FParser.GetToken;
+ FuncNo := -1;
+ for i := 0 to FProcs.Count -1 do
+ begin
+ f2 := FProcs[I];
+ if (f2.ClassType = TPSInternalProcedure) and (TPSInternalProcedure(f2).Name = FunctionName) and (TPSInternalProcedure(f2).Forwarded) then
+ begin
+ Func := FProcs[I];
+ FuncNo := i;
+ Break;
+ end;
+ end;
+ if (Func = nil) and IsDuplicate(FunctionName, [dcTypes, dcProcs, dcVars, dcConsts]) then
+ begin
+ att.free;
+ MakeError('', ecDuplicateIdentifier, FunctionName);
+ exit;
+ end;
+ FParser.Next;
+ FunctionDecl := TPSParametersDecl.Create;
+ try
+ if FParser.CurrTokenId = CSTI_OpenRound then
+ begin
+ FParser.Next;
+ if FParser.CurrTokenId = CSTI_CloseRound then
+ begin
+ FParser.Next;
+ end
+ else
+ begin
+ if FunctionType = ftFunc then
+ ParamNo := 1
+ else
+ ParamNo := 0;
+ while True do
+ begin
+ if FParser.CurrTokenId = CSTII_Const then
+ begin
+ modifier := pmIn;
+ FParser.Next;
+ end
+ else
+ if FParser.CurrTokenId = CSTII_Out then
+ begin
+ modifier := pmOut;
+ FParser.Next;
+ end
+ else
+ if FParser.CurrTokenId = CSTII_Var then
+ begin
+ modifier := pmInOut;
+ FParser.Next;
+ end
+ else
+ modifier := pmIn;
+ if FParser.CurrTokenId <> CSTI_Identifier then
+ begin
+ MakeError('', ecIdentifierExpected, '');
+ exit;
+ end;
+ E2Pos := FParser.CurrTokenPos;
+ E2Row := FParser.Row;
+ E2Col := FParser.Col;
+ FunctionParamNames := '';
+ if ProcIsDuplic(FunctionDecl, FunctionName, FunctionParamNames, FParser.GetToken, Func) then
+ begin
+ MakeError('', ecDuplicateIdentifier, FParser.OriginalToken);
+ exit;
+ end;
+ FunctionParamNames := FParser.OriginalToken + '|';
+ if @FOnUseVariable <> nil then
+ begin
+ FOnUseVariable(Self, ivtParam, ParamNo, FProcs.Count, FParser.CurrTokenPos, '');
+ end;
+ inc(ParamNo);
+ FParser.Next;
+ while FParser.CurrTokenId = CSTI_Comma do
+ begin
+ FParser.Next;
+ if FParser.CurrTokenId <> CSTI_Identifier then
+ begin
+ MakeError('', ecIdentifierExpected, '');
+ exit;
+ end;
+ if ProcIsDuplic(FunctionDecl, FunctionName, FunctionParamNames, FParser.GetToken, Func) then
+ begin
+ MakeError('', ecDuplicateIdentifier, '');
+ exit;
+ end;
+ if @FOnUseVariable <> nil then
+ begin
+ FOnUseVariable(Self, ivtParam, ParamNo, FProcs.Count, FParser.CurrTokenPos, '');
+ end;
+ inc(ParamNo);
+ FunctionParamNames := FunctionParamNames + FParser.OriginalToken +
+ '|';
+ FParser.Next;
+ end;
+ if FParser.CurrTokenId <> CSTI_Colon then
+ begin
+ MakeError('', ecColonExpected, '');
+ exit;
+ end;
+ FParser.Next;
+ FunctionTempType := at2ut(ReadType('', FParser));
+ if FunctionTempType = nil then
+ begin
+ exit;
+ end;
+ while Pos(tbtchar('|'), FunctionParamNames) > 0 do
+ begin
+ with FunctionDecl.AddParam do
+ begin
+ OrgName := copy(FunctionParamNames, 1, Pos(tbtchar('|'), FunctionParamNames) - 1);
+ Mode := modifier;
+ aType := FunctionTempType;
+ {$IFDEF PS_USESSUPPORT}
+ DeclareUnit:=fModule;
+ {$ENDIF}
+ DeclarePos:=E2Pos;
+ DeclareRow:=E2Row;
+ DeclareCol:=E2Col;
+ end;
+ Delete(FunctionParamNames, 1, Pos(tbtchar('|'), FunctionParamNames));
+ end;
+ if FParser.CurrTokenId = CSTI_CloseRound then
+ break;
+ if FParser.CurrTokenId <> CSTI_Semicolon then
+ begin
+ MakeError('', ecSemicolonExpected, '');
+ exit;
+ end;
+ FParser.Next;
+ end;
+ FParser.Next;
+ end;
+ end;
+ if FunctionType = ftFunc then
+ begin
+ if FParser.CurrTokenId <> CSTI_Colon then
+ begin
+ MakeError('', ecColonExpected, '');
+ exit;
+ end;
+ FParser.Next;
+ FunctionTempType := at2ut(ReadType('', FParser));
+ if FunctionTempType = nil then
+ exit;
+ FunctionDecl.Result := FunctionTempType;
+ end;
+ if FParser.CurrTokenId <> CSTI_Semicolon then
+ begin
+ MakeError('', ecSemicolonExpected, '');
+ exit;
+ end;
+ FParser.Next;
+ if (Func = nil) and (FParser.CurrTokenID = CSTII_External) then
+ begin
+ FParser.Next;
+ if FParser.CurrTokenID <> CSTI_String then
+ begin
+ MakeError('', ecStringExpected, '');
+ exit;
+ end;
+ FunctionParamNames := FParser.GetToken;
+ FunctionParamNames := copy(FunctionParamNames, 2, length(FunctionParamNames) - 2);
+ FParser.Next;
+ if FParser.CurrTokenID <> CSTI_Semicolon then
+ begin
+ MakeError('', ecSemicolonExpected, '');
+ exit;
+ end;
+ FParser.Next;
+ if @FOnExternalProc = nil then
+ begin
+ MakeError('', ecSemicolonExpected, '');
+ exit;
+ end;
+ pp := FOnExternalProc(Self, FunctionDecl, OriginalName, FunctionParamNames);
+ if pp = nil then
+ begin
+ MakeError('', ecCustomError, '');
+ exit;
+ end;
+ pp2 := TPSExternalProcedure.Create;
+ pp2.Attributes.Assign(att, true);
+ pp2.RegProc := pp;
+ FProcs.Add(pp2);
+ FRegProcs.Add(pp);
+ Result := ApplyAttribsToFunction(pp2);
+ Exit;
+ end else if (FParser.CurrTokenID = CSTII_Forward) or AlwaysForward then
+ begin
+ if Func <> nil then
+ begin
+ MakeError('', ecBeginExpected, '');
+ exit;
+ end;
+ if not AlwaysForward then
+ begin
+ FParser.Next;
+ if FParser.CurrTokenID <> CSTI_Semicolon then
+ begin
+ MakeError('', ecSemicolonExpected, '');
+ Exit;
+ end;
+ FParser.Next;
+ end;
+ Func := NewProc(OriginalName, FunctionName);
+ Func.Attributes.Assign(Att, True);
+ Func.Forwarded := True;
+ {$IFDEF PS_USESSUPPORT}
+ Func.FDeclareUnit := fModule;
+ {$ENDIF}
+ Func.FDeclarePos := EPos;
+ Func.FDeclareRow := ERow;
+ Func.FDeclarePos := ECol;
+ Func.Decl.Assign(FunctionDecl);
+ Result := ApplyAttribsToFunction(Func);
+ exit;
+ end;
+ if (Func = nil) then
+ begin
+ Func := NewProc(OriginalName, FunctionName);
+ Func.Attributes.Assign(att, True);
+ Func.Decl.Assign(FunctionDecl);
+ {$IFDEF PS_USESSUPPORT}
+ Func.FDeclareUnit := fModule;
+ {$ENDIF}
+ Func.FDeclarePos := EPos;
+ Func.FDeclareRow := ERow;
+ Func.FDeclareCol := ECol;
+ FuncNo := FProcs.Count -1;
+ if not ApplyAttribsToFunction(Func) then
+ begin
+ result := false;
+ exit;
+ end;
+ end else begin
+ if not FunctionDecl.Same(Func.Decl) then
+ begin
+ MakeError('', ecForwardParameterMismatch, '');
+ Result := false;
+ exit;
+ end;
+ Func.Forwarded := False;
+ end;
+ if FParser.CurrTokenID = CSTII_Export then
+ begin
+ FParser.Next;
+ if FParser.CurrTokenID <> CSTI_Semicolon then
+ begin
+ MakeError('', ecSemicolonExpected, '');
+ exit;
+ end;
+ FParser.Next;
+ end;
+ while FParser.CurrTokenId <> CSTII_Begin do
+ begin
+ if FParser.CurrTokenId = CSTII_Var then
+ begin
+ if not DoVarBlock(Func) then
+ exit;
+ end else if FParser.CurrTokenId = CSTII_Label then
+ begin
+ if not ProcessLabel(Func) then
+ Exit;
+ end else
+ begin
+ MakeError('', ecBeginExpected, '');
+ exit;
+ end;
+ end;
+ Debug_WriteParams(FuncNo, Func);
+ WriteProcVars(Func, Func.ProcVars);
+ Block := TPSBlockInfo.Create(FGlobalBlock);
+ Block.SubType := tProcBegin;
+ Block.ProcNo := FuncNo;
+ Block.Proc := Func;
+ if not ProcessSub(Block) then
+ begin
+ Block.Free;
+ exit;
+ end;
+ Block.Free;
+ CheckForUnusedVars(Func);
+ Result := ProcessLabelForwards(Func);
+ if assigned(FOnFunctionEnd) then
+ {$IFDEF PS_USESSUPPORT}
+ OnFunctionEnd(fModule + '.' + OriginalName, FParser.CurrTokenPos, FParser.Row, FParser.Col);
+ {$ELSE}
+ OnFunctionEnd(OriginalName, FParser.CurrTokenPos, FParser.Row, FParser.Col);
+ {$ENDIF}
+ finally
+ FunctionDecl.Free;
+ att.Free;
+ end;
+end;
+
+function GetParamType(BlockInfo: TPSBlockInfo; I: Longint): TPSType;
+begin
+ if BlockInfo.Proc.Decl.Result <> nil then dec(i);
+ if i = -1 then
+ Result := BlockInfo.Proc.Decl.Result
+ else
+ begin
+ Result := BlockInfo.Proc.Decl.Params[i].aType;
+ end;
+end;
+
+function TPSPascalCompiler.GetTypeNo(BlockInfo: TPSBlockInfo; p: TPSValue): TPSType;
+begin
+ if p.ClassType = TPSUnValueOp then
+ Result := TPSUnValueOp(p).aType
+ else if p.ClassType = TPSBinValueOp then
+ Result := TPSBinValueOp(p).aType
+ else if p.ClassType = TPSValueArray then
+ Result := at2ut(FindType('TVariantArray'))
+ else if p.ClassType = TPSValueData then
+ Result := TPSValueData(p).Data.FType
+ else if p is TPSValueProc then
+ Result := TPSValueProc(p).ResultType
+ else if (p is TPSValueVar) and (TPSValueVar(p).RecCount > 0) then
+ Result := TPSValueVar(p).RecItem[TPSValueVar(p).RecCount - 1].aType
+ else if p.ClassType = TPSValueGlobalVar then
+ Result := TPSVar(FVars[TPSValueGlobalVar(p).GlobalVarNo]).FType
+ else if p.ClassType = TPSValueParamVar then
+ Result := GetParamType(BlockInfo, TPSValueParamVar(p).ParamNo)
+ else if p is TPSValueLocalVar then
+ Result := TPSProcVar(BlockInfo.Proc.ProcVars[TPSValueLocalVar(p).LocalVarNo]).AType
+ else if p.classtype = TPSValueReplace then
+ Result := GetTypeNo(BlockInfo, TPSValueReplace(p).NewValue)
+ else
+ Result := nil;
+end;
+
+function TPSPascalCompiler.IsVarInCompatible(ft1, ft2: TPSType): Boolean;
+begin
+ ft1 := GetTypeCopyLink(ft1);
+ ft2 := GetTypeCopyLink(ft2);
+ Result := (ft1 <> ft2) and (ft2 <> nil);
+end;
+
+function TPSPascalCompiler.ValidateParameters(BlockInfo: TPSBlockInfo; Params: TPSParameters; ParamTypes: TPSParametersDecl): boolean;
+var
+ i, c: Longint;
+ pType: TPSType;
+
+begin
+ UseProc(ParamTypes);
+ c := 0;
+ for i := 0 to ParamTypes.ParamCount -1 do
+ begin
+ while (c < Longint(Params.Count)) and (Params[c].Val = nil) do
+ Inc(c);
+ if c >= Longint(Params.Count) then
+ begin
+ MakeError('', ecInvalidnumberOfParameters, '');
+ Result := False;
+ exit;
+ end;
+ Params[c].ExpectedType := ParamTypes.Params[i].aType;
+ Params[c].ParamMode := ParamTypes.Params[i].Mode;
+ if ParamTypes.Params[i].Mode <> pmIn then
+ begin
+ if not (Params[c].Val is TPSValueVar) then
+ begin
+ with MakeError('', ecVariableExpected, '') do
+ begin
+ Row := Params[c].Val.Row;
+ Col := Params[c].Val.Col;
+ Pos := Params[c].Val.Pos;
+ end;
+ result := false;
+ exit;
+ end;
+ PType := Params[c].ExpectedType;
+ if (PType = nil) or ((PType.BaseType = btArray) and (TPSArrayType(PType).ArrayTypeNo = nil) and (GetTypeNo(BlockInfo, Params[c].Val).BaseType = btArray)) or
+ (PType = FAnyString) then
+ begin
+ Params[c].ExpectedType := GetTypeNo(BlockInfo, Params[c].Val);
+ if PType <> nil then
+ if (Params[c].ExpectedType = nil) or not (Params[c].ExpectedType.BaseType in [btString, btWideString, btUnicodeString, btChar, btWideChar]) then begin
+ MakeError('', ecTypeMismatch, '');
+ Result := False;
+ exit;
+ end;
+ if Params[c].ExpectedType.BaseType = btChar then
+ Params[c].ExpectedType := FindBaseType(btString) else
+ if Params[c].ExpectedType.BaseType = btWideChar then
+ Params[c].ExpectedType := FindBaseType(btUnicodeString);
+ end else if (PType.BaseType = btArray) and (GetTypeNo(BlockInfo, Params[c].Val).BaseType = btArray) then
+ begin
+ if TPSArrayType(GetTypeNo(BlockInfo, Params[c].Val)).ArrayTypeNo <> TPSArrayType(PType).ArrayTypeNo then
+ begin
+ MakeError('', ecTypeMismatch, '');
+ Result := False;
+ exit;
+ end;
+ end else if IsVarInCompatible(PType, GetTypeNo(BlockInfo, Params[c].Val)) then
+ begin
+ MakeError('', ecTypeMismatch, '');
+ Result := False;
+ exit;
+ end;
+ end;
+ Inc(c);
+ end;
+ for i := c to Params.Count -1 do
+ begin
+ if Params[i].Val <> nil then
+ begin
+ MakeError('', ecInvalidnumberOfParameters, '');
+ Result := False;
+ exit;
+ end;
+ end;
+ Result := true;
+end;
+
+function TPSPascalCompiler.DoTypeBlock(FParser: TPSPascalParser): Boolean;
+var
+ VOrg,VName: tbtString;
+ Attr: TPSAttributes;
+ FType: TPSType;
+ i: Longint;
+begin
+ Result := False;
+ FParser.Next;
+ repeat
+ Attr := TPSAttributes.Create;
+ if not ReadAttributes(Attr) then
+ begin
+ Attr.Free;
+ exit;
+ end;
+ if (FParser.CurrTokenID = CSTII_Procedure) or (FParser.CurrTokenID = CSTII_Function) then
+ begin
+ Result := ProcessFunction(false, Attr);
+ exit;
+ end;
+ if FParser.CurrTokenId <> CSTI_Identifier then
+ begin
+ MakeError('', ecIdentifierExpected, '');
+ Attr.Free;
+ exit;
+ end;
+
+ VName := FParser.GetToken;
+ VOrg := FParser.OriginalToken;
+ if IsDuplicate(VName, [dcTypes, dcProcs, dcVars]) then
+ begin
+ MakeError('', ecDuplicateIdentifier, FParser.OriginalToken);
+ Attr.Free;
+ exit;
+ end;
+
+ FParser.Next;
+ if FParser.CurrTokenId <> CSTI_Equal then
+ begin
+ MakeError('', ecIsExpected, '');
+ Attr.Free;
+ exit;
+ end;
+ FParser.Next;
+ FType := ReadType(VOrg, FParser);
+ if Ftype = nil then
+ begin
+ Attr.Free;
+ Exit;
+ end;
+ FType.Attributes.Assign(Attr, True);
+ for i := 0 to FType.Attributes.Count -1 do
+ begin
+ if @FType.Attributes[i].FAttribType.FAAType <> nil then
+ FType.Attributes[i].FAttribType.FAAType(Self, FType, Attr[i]);
+ end;
+ Attr.Free;
+ if FParser.CurrTokenID <> CSTI_Semicolon then
+ begin
+ MakeError('', ecSemicolonExpected, '');
+ Exit;
+ end;
+ FParser.Next;
+ until (FParser.CurrTokenId <> CSTI_Identifier) and (FParser.CurrTokenID <> CSTI_OpenBlock);
+ Result := True;
+end;
+
+procedure TPSPascalCompiler.Debug_WriteLine(BlockInfo: TPSBlockInfo);
+var
+ b: Boolean;
+begin
+ if @FOnWriteLine <> nil then begin
+ {$IFNDEF PS_USESSUPPORT}
+ b := FOnWriteLine(Self, FParser.CurrTokenPos);
+ {$ELSE}
+ b := FOnWriteLine(Self, FModule, FParser.CurrTokenPos);
+ {$ENDIF}
+ end else
+ b := true;
+ if b then Debug_SavePosition(BlockInfo.ProcNo, BlockInfo.Proc);
+end;
+
+
+function TPSPascalCompiler.ReadReal(const s: tbtString): PIfRVariant;
+var
+ C: Integer;
+begin
+ New(Result);
+ InitializeVariant(Result, FindBaseType(btExtended));
+ Val(string(s), Result^.textended, C);
+end;
+
+function TPSPascalCompiler.ReadString: PIfRVariant;
+{$IFNDEF PS_NOWIDESTRING}var wchar: Boolean;{$ENDIF}
+
+ function ParseString({$IFNDEF PS_NOWIDESTRING}var res: tbtunicodestring{$ELSE}var res: tbtString{$ENDIF}): Boolean;
+ var
+ temp3: {$IFNDEF PS_NOWIDESTRING}tbtunicodestring{$ELSE}tbtString{$ENDIF};
+
+ function ChrToStr(s: tbtString): {$IFNDEF PS_NOWIDESTRING}widechar{$ELSE}tbtchar{$ENDIF};
+ var
+ w: Longint;
+ begin
+ Delete(s, 1, 1); {First char : #}
+ w := StrToInt(s);
+ Result := {$IFNDEF PS_NOWIDESTRING}widechar{$ELSE}tbtchar{$ENDIF}(w);
+ {$IFNDEF PS_NOWIDESTRING}if w > $FF then wchar := true;{$ENDIF}
+ end;
+
+ function PString(s: tbtString): tbtString;
+ var
+ i: Longint;
+ begin
+ s := copy(s, 2, Length(s) - 2);
+ i := length(s);
+ while i > 0 do
+ begin
+ if (i < length(s)) and (s[i] = #39) and (s[i + 1] = #39) then
+ begin
+ Delete(s, i, 1);
+ dec(i);
+ end;
+ dec(i);
+ end;
+ PString := s;
+ end;
+ var
+ lastwasstring: Boolean;
+ begin
+ temp3 := '';
+ while (FParser.CurrTokenId = CSTI_String) or (FParser.CurrTokenId = CSTI_Char) do
+ begin
+ lastwasstring := FParser.CurrTokenId = CSTI_String;
+ if FParser.CurrTokenId = CSTI_String then
+ begin
+ if UTF8Decode then
+ begin
+ temp3 := temp3 + {$IFNDEF PS_NOWIDESTRING}{$IFDEF DELPHI6UP}System.{$IFDEF DELPHI2009UP}UTF8ToWidestring{$ELSE}UTF8Decode{$ENDIF}{$ENDIF}{$ENDIF}(PString(FParser.GetToken));
+ {$IFNDEF PS_NOWIDESTRING}wchar:=true;{$ENDIF}
+ end else
+ temp3 := temp3 + tbtUnicodestring(PString(FParser.GetToken));
+
+ FParser.Next;
+ if FParser.CurrTokenId = CSTI_String then
+ temp3 := temp3 + #39;
+ end {if}
+ else
+ begin
+ temp3 := temp3 + ChrToStr(FParser.GetToken);
+ FParser.Next;
+ end; {else if}
+ if lastwasstring and (FParser.CurrTokenId = CSTI_String) then
+ begin
+ MakeError('', ecSyntaxError, '');
+ result := false;
+ exit;
+ end;
+ end; {while}
+ res := temp3;
+ result := true;
+ end;
+var
+{$IFNDEF PS_NOWIDESTRING}
+ w: tbtunicodestring;
+{$ENDIF}
+ s: tbtString;
+begin
+ {$IFNDEF PS_NOWIDESTRING}wchar:=false;{$ENDIF}
+ if not ParseString({$IFDEF PS_NOWIDESTRING} s {$ELSE} w {$ENDIF}) then
+ begin
+ result := nil;
+ exit;
+ end;
+{$IFNDEF PS_NOWIDESTRING}
+ if wchar then
+ begin
+ New(Result);
+ if Length(w) = 1 then
+ begin
+ InitializeVariant(Result, at2ut(FindBaseType(btwidechar)));
+ Result^.twidechar := w[1];
+ end else begin
+ InitializeVariant(Result, at2ut(FindBaseType(btUnicodeString)));
+ tbtunicodestring(Result^.tunistring) := w;
+ end;
+ end else begin
+ s := tbtstring(w);
+{$ENDIF}
+ New(Result);
+ if Length(s) = 1 then
+ begin
+ InitializeVariant(Result, at2ut(FindBaseType(btchar)));
+ Result^.tchar := s[1];
+ end else begin
+ InitializeVariant(Result, at2ut(FindBaseType(btstring)));
+ tbtstring(Result^.tstring) := s;
+ end;
+{$IFNDEF PS_NOWIDESTRING}
+ end;
+{$ENDIF}
+end;
+
+
+function TPSPascalCompiler.ReadInteger(const s: tbtString): PIfRVariant;
+var
+ R: {$IFNDEF PS_NOINT64}Int64;{$ELSE}Longint;{$ENDIF}
+begin
+ New(Result);
+{$IFNDEF PS_NOINT64}
+ r := StrToInt64Def(string(s), 0);
+ if (r >= Low(Integer)) and (r <= High(Integer)) then
+ begin
+ InitializeVariant(Result, at2ut(FindBaseType(bts32)));
+ Result^.ts32 := r;
+ end else if (r <= $FFFFFFFF) then
+ begin
+ InitializeVariant(Result, at2ut(FindBaseType(btu32)));
+ Result^.tu32 := r;
+ end else
+ begin
+ InitializeVariant(Result, at2ut(FindBaseType(bts64)));
+ Result^.ts64 := r;
+ end;
+{$ELSE}
+ r := StrToIntDef(s, 0);
+ InitializeVariant(Result, at2ut(FindBaseType(bts32)));
+ Result^.ts32 := r;
+{$ENDIF}
+end;
+
+function TPSPascalCompiler.ProcessSub(BlockInfo: TPSBlockInfo): Boolean;
+
+ function AllocStackReg2(MType: TPSType): TPSValue;
+ var
+ x: TPSProcVar;
+ begin
+{$IFDEF DEBUG}
+ if (mtype = nil) or (not mtype.Used) then asm int 3; end;
+{$ENDIF}
+ x := TPSProcVar.Create;
+ {$IFDEF PS_USESSUPPORT}
+ x.DeclareUnit:=fModule;
+ {$ENDIF}
+ x.DeclarePos := FParser.CurrTokenPos;
+ x.DeclareRow := FParser.Row;
+ x.DeclareCol := FParser.Col;
+ x.Name := '';
+ x.AType := MType;
+ x.Use;
+ BlockInfo.Proc.ProcVars.Add(x);
+ Result := TPSValueAllocatedStackVar.Create;
+ Result.SetParserPos(FParser);
+ TPSValueAllocatedStackVar(Result).Proc := BlockInfo.Proc;
+ with TPSValueAllocatedStackVar(Result) do
+ begin
+ LocalVarNo := proc.ProcVars.Count -1;
+ end;
+ end;
+
+ function AllocStackReg(MType: TPSType): TPSValue;
+ begin
+ Result := AllocStackReg2(MType);
+ BlockWriteByte(BlockInfo, Cm_Pt);
+ BlockWriteLong(BlockInfo, MType.FinalTypeNo);
+ end;
+
+ function AllocPointer(MDestType: TPSType): TPSValue;
+ begin
+ Result := AllocStackReg(at2ut(FindBaseType(btPointer)));
+ TPSProcVar(BlockInfo.Proc.ProcVars[TPSValueAllocatedStackVar(Result).LocalVarNo]).AType := MDestType;
+ end;
+
+ function WriteCalculation(InData, OutReg: TPSValue): Boolean; forward;
+ function PreWriteOutRec(var X: TPSValue; FArrType: TPSType): Boolean; forward;
+ function WriteOutRec(x: TPSValue; AllowData: Boolean): Boolean; forward;
+ procedure AfterWriteOutRec(var x: TPSValue); forward;
+
+ function CheckCompatType(V1, v2: TPSValue): Boolean;
+ var
+ p1, P2: TPSType;
+ begin
+ p1 := GetTypeNo(BlockInfo, V1);
+ P2 := GetTypeNo(BlockInfo, v2);
+ if (p1 = nil) or (p2 = nil) then
+ begin
+ if ((p1 <> nil) and ({$IFNDEF PS_NOINTERFACES}(p1.ClassType = TPSInterfaceType) or {$ENDIF}(p1.BaseType = btProcPtr)) and (v2.ClassType = TPSValueNil)) or
+ ((p2 <> nil) and ({$IFNDEF PS_NOINTERFACES}(p2.ClassType = TPSInterfaceType) or {$ENDIF}(p2.BaseType = btProcPtr)) and (v1.ClassType = TPSValueNil)) then
+ begin
+ Result := True;
+ exit;
+ end else
+ if ((p1 <> nil) and ({$IFNDEF PS_NOINTERFACES}(p1.ClassType = TPSInterfaceType) or {$ENDIF}(p1.ClassType = TPSClassType)) and (v2.ClassType = TPSValueNil)) or
+ ((p2 <> nil) and ({$IFNDEF PS_NOINTERFACES}(p2.ClassType = TPSInterfaceType) or {$ENDIF}(p2.ClassType = TPSClassType)) and (v1.ClassType = TPSValueNil)) then
+ begin
+ Result := True;
+ exit;
+ end else
+ if ((p1 <> nil) and ({$IFNDEF PS_NOINTERFACES}(p1.ClassType = TPSInterfaceType) or {$ENDIF}(p1.ClassType = TPSUndefinedClassType)) and (v2.ClassType = TPSValueNil)) or
+ ((p2 <> nil) and ({$IFNDEF PS_NOINTERFACES}(p2.ClassType = TPSInterfaceType) or {$ENDIF}(p2.ClassType = TPSUndefinedClassType)) and (v1.ClassType = TPSValueNil)) then
+ begin
+ Result := True;
+ exit;
+ end else
+ if (v1.ClassType = TPSValueProcPtr) and (p2 <> nil) and (p2.BaseType = btProcPtr) then
+ begin
+ Result := CheckCompatProc(p2, TPSValueProcPtr(v1).ProcPtr);
+ exit;
+ end else if (v2.ClassType = TPSValueProcPtr) and (p1 <> nil) and (p1.BaseType = btProcPtr) then
+ begin
+ Result := CheckCompatProc(p1, TPSValueProcPtr(v2).ProcPtr);
+ exit;
+ end;
+ Result := False;
+ end else
+ if (p1 <> nil) and (p1.BaseType = btSet) and (v2 is TPSValueArray) then
+ begin
+ Result := True;
+ end else
+ Result := IsCompatibleType(p1, p2, False);
+ end;
+
+ function _ProcessFunction(ProcCall: TPSValueProc; ResultRegister: TPSValue): Boolean; forward;
+ function ProcessFunction2(ProcNo: Cardinal; Par: TPSParameters; ResultReg: TPSValue): Boolean;
+ var
+ Temp: TPSValueProcNo;
+ i: Integer;
+ begin
+ Temp := TPSValueProcNo.Create;
+ Temp.Parameters := Par;
+ Temp.ProcNo := ProcNo;
+ if TObject(FProcs[ProcNo]).ClassType = TPSInternalProcedure then
+ Temp.ResultType := TPSInternalProcedure(FProcs[ProcNo]).Decl.Result
+ else
+ Temp.ResultType := TPSExternalProcedure(FProcs[ProcNo]).RegProc.Decl.Result;
+ if (Temp.ResultType <> nil) and (Temp.ResultType = FAnyString) then begin // workaround to make the result type match
+ for i := 0 to Par.Count -1 do begin
+ if Par[i].ExpectedType.BaseType in [btString, btWideString] then
+ Temp.ResultType := Par[i].ExpectedType;
+ end;
+ end;
+ Result := _ProcessFunction(Temp, ResultReg);
+ Temp.Parameters := nil;
+ Temp.Free;
+ end;
+
+ function MakeNil(NilPos, NilRow, nilCol: Cardinal;ivar: TPSValue): Boolean;
+ var
+ Procno: Cardinal;
+ PF: TPSType;
+ Par: TPSParameters;
+ begin
+ Pf := GetTypeNo(BlockInfo, IVar);
+ if not (Ivar is TPSValueVar) then
+ begin
+ with MakeError('', ecTypeMismatch, '') do
+ begin
+ FPosition := nilPos;
+ FRow := NilRow;
+ FCol := nilCol;
+ end;
+ Result := False;
+ exit;
+ end;
+ if (pf.BaseType = btProcPtr) then
+ begin
+ Result := True;
+ end else
+ if (pf.BaseType = btString) or (pf.BaseType = btPChar) then
+ begin
+ if not PreWriteOutRec(iVar, nil) then
+ begin
+ Result := false;
+ exit;
+ end;
+ BlockWriteByte(BlockInfo, CM_A);
+ WriteOutRec(ivar, False);
+ BlockWriteByte(BlockInfo, 1);
+ BlockWriteLong(BlockInfo, GetTypeNo(BlockInfo, IVar).FinalTypeNo);
+ BlockWriteLong(BlockInfo, 0); //empty tbtString
+ AfterWriteOutRec(ivar);
+ Result := True;
+ end else if (pf.BaseType = btClass) {$IFNDEF PS_NOINTERFACES}or (pf.BaseType = btInterface){$ENDIF} then
+ begin
+{$IFNDEF PS_NOINTERFACES}
+ if (pf.BaseType = btClass) then
+ begin
+{$ENDIF}
+ if not TPSClassType(pf).Cl.SetNil(ProcNo) then
+ begin
+ with MakeError('', ecTypeMismatch, '') do
+ begin
+ FPosition := nilPos;
+ FRow := NilRow;
+ FCol := nilCol;
+ end;
+ Result := False;
+ exit;
+ end;
+{$IFNDEF PS_NOINTERFACES}
+ end else
+ begin
+ if not TPSInterfaceType(pf).Intf.SetNil(ProcNo) then
+ begin
+ with MakeError('', ecTypeMismatch, '') do
+ begin
+ FPosition := nilPos;
+ FRow := NilRow;
+ FCol := nilCol;
+ end;
+ Result := False;
+ exit;
+ end;
+ end;
+{$ENDIF}
+ Par := TPSParameters.Create;
+ with par.Add do
+ begin
+ Val := IVar;
+ ExpectedType := GetTypeNo(BlockInfo, ivar);
+{$IFDEF DEBUG}
+ if not ExpectedType.Used then asm int 3; end;
+{$ENDIF}
+ ParamMode := pmInOut;
+ end;
+ Result := ProcessFunction2(ProcNo, Par, nil);
+
+ Par[0].Val := nil; // don't free IVAR
+
+ Par.Free;
+ end else if pf.BaseType = btExtClass then
+ begin
+ if not TPSUndefinedClassType(pf).ExtClass.SetNil(ProcNo) then
+ begin
+ with MakeError('', ecTypeMismatch, '') do
+ begin
+ FPosition := nilPos;
+ FRow := NilRow;
+ FCol := nilCol;
+ end;
+ Result := False;
+ exit;
+ end;
+ Par := TPSParameters.Create;
+ with par.Add do
+ begin
+ Val := IVar;
+ ExpectedType := GetTypeNo(BlockInfo, ivar);
+ ParamMode := pmInOut;
+ end;
+ Result := ProcessFunction2(ProcNo, Par, nil);
+
+ Par[0].Val := nil; // don't free IVAR
+
+ Par.Free;
+ end else begin
+ with MakeError('', ecTypeMismatch, '') do
+ begin
+ FPosition := nilPos;
+ FRow := NilRow;
+ FCol := nilCol;
+ end;
+ Result := False;
+ end;
+ end;
+ function DoBinCalc(BVal: TPSBinValueOp; Output: TPSValue): Boolean;
+ var
+ tmpp, tmpc: TPSValue;
+ jend, jover: Cardinal;
+ procno: Cardinal;
+
+ begin
+ if BVal.Operator >= otGreaterEqual then
+ begin
+ if BVal.FVal1.ClassType = TPSValueNil then
+ begin
+ tmpp := AllocStackReg(GetTypeNo(BlockInfo, BVal.FVal2));
+ if not MakeNil(BVal.FVal1.Pos, BVal.FVal1.Row, BVal.FVal1.Col, tmpp) then
+ begin
+ tmpp.Free;
+ Result := False;
+ exit;
+ end;
+ tmpc := TPSValueReplace.Create;
+ with TPSValueReplace(tmpc) do
+ begin
+ OldValue := BVal.FVal1;
+ NewValue := tmpp;
+ end;
+ BVal.FVal1 := tmpc;
+ end;
+ if BVal.FVal2.ClassType = TPSValueNil then
+ begin
+ tmpp := AllocStackReg(GetTypeNo(BlockInfo, BVal.FVal1));
+ if not MakeNil(BVal.FVal2.Pos, BVal.FVal2.Row, BVal.FVal2.Col, tmpp) then
+ begin
+ tmpp.Free;;
+ Result := False;
+ exit;
+ end;
+ tmpc := TPSValueReplace.Create;
+ with TPSValueReplace(tmpc) do
+ begin
+ OldValue := BVal.FVal2;
+ NewValue := tmpp;
+ end;
+ BVal.FVal2 := tmpc;
+ end;
+ if GetTypeNo(BlockInfo, BVal.FVal1).BaseType = btExtClass then
+ begin
+ if not TPSUndefinedClassType(GetTypeNo(BlockInfo, BVal.FVal1)).ExtClass.CompareClass(GetTypeNo(BlockInfo, Bval.FVal2), ProcNo) then
+ begin
+ Result := False;
+ exit;
+ end;
+ tmpp := TPSValueProcNo.Create;
+ with TPSValueProcNo(tmpp) do
+ begin
+ ResultType := at2ut(FDefaultBoolType);
+ Parameters := TPSParameters.Create;
+ ProcNo := procno;
+ Pos := BVal.Pos;
+ Col := BVal.Col;
+ Row := BVal.Row;
+ with parameters.Add do
+ begin
+ Val := BVal.FVal1;
+ ExpectedType := GetTypeNo(BlockInfo, Val);
+ end;
+ with parameters.Add do
+ begin
+ Val := BVal.FVal2;
+ ExpectedType := GetTypeNo(BlockInfo, Val);
+ end;
+ end;
+ if Bval.Operator = otNotEqual then
+ begin
+ tmpc := TPSUnValueOp.Create;
+ TPSUnValueOp(tmpc).Operator := otNot;
+ TPSUnValueOp(tmpc).Val1 := tmpp;
+ TPSUnValueOp(tmpc).aType := GetTypeNo(BlockInfo, tmpp);
+ end else tmpc := tmpp;
+ Result := WriteCalculation(tmpc, Output);
+ with TPSValueProcNo(tmpp) do
+ begin
+ Parameters[0].Val := nil;
+ Parameters[1].Val := nil;
+ end;
+ tmpc.Free;
+ if BVal.Val1.ClassType = TPSValueReplace then
+ begin
+ tmpp := TPSValueReplace(BVal.Val1).OldValue;
+ BVal.Val1.Free;
+ BVal.Val1 := tmpp;
+ end;
+ if BVal.Val2.ClassType = TPSValueReplace then
+ begin
+ tmpp := TPSValueReplace(BVal.Val2).OldValue;
+ BVal.Val2.Free;
+ BVal.Val2 := tmpp;
+ end;
+ exit;
+ end;
+ if not (PreWriteOutRec(Output, nil) and PreWriteOutRec(BVal.FVal1, GetTypeNo(BlockInfo, BVal.FVal2)) and PreWriteOutRec(BVal.FVal2, GetTypeNo(BlockInfo, BVal.FVal1))) then
+ begin
+ Result := False;
+ exit;
+ end;
+ BlockWriteByte(BlockInfo, CM_CO);
+ case BVal.Operator of
+ otGreaterEqual: BlockWriteByte(BlockInfo, 0);
+ otLessEqual: BlockWriteByte(BlockInfo, 1);
+ otGreater: BlockWriteByte(BlockInfo, 2);
+ otLess: BlockWriteByte(BlockInfo, 3);
+ otEqual: BlockWriteByte(BlockInfo, 5);
+ otNotEqual: BlockWriteByte(BlockInfo, 4);
+ otIn: BlockWriteByte(BlockInfo, 6);
+ otIs: BlockWriteByte(BlockInfo, 7);
+ end;
+
+ if not (WriteOutRec(Output, False) and writeOutRec(BVal.FVal1, True) and writeOutRec(BVal.FVal2, True)) then
+ begin
+ Result := False;
+ exit;
+ end;
+ AfterWriteOutrec(BVal.FVal1);
+ AfterWriteOutrec(BVal.FVal2);
+ AfterWriteOutrec(Output);
+ if BVal.Val1.ClassType = TPSValueReplace then
+ begin
+ tmpp := TPSValueReplace(BVal.Val1).OldValue;
+ BVal.Val1.Free;
+ BVal.Val1 := tmpp;
+ end;
+ if BVal.Val2.ClassType = TPSValueReplace then
+ begin
+ tmpp := TPSValueReplace(BVal.Val2).OldValue;
+ BVal.Val2.Free;
+ BVal.Val2 := tmpp;
+ end;
+ end else begin
+ if (BVal.aType <> nil) and (BVal.aType <> GetTypeNo(BlockInfo, Output)) then begin
+ tmpp := AllocStackReg(BVal.aType);
+ PreWriteOutrec(tmpp, nil);
+ DoBinCalc(BVal, tmpp);
+ afterwriteoutrec(tmpp);
+ result := WriteCalculation(tmpp, output);
+ tmpp.Free;
+ exit;
+ end;
+
+ if not PreWriteOutRec(Output, nil) then
+ begin
+ Result := False;
+ exit;
+ end;
+ if not SameReg(Output, BVal.Val1) then
+ begin
+ if not WriteCalculation(BVal.FVal1, Output) then
+ begin
+ Result := False;
+ exit;
+ end;
+ end;
+ if (FBooleanShortCircuit) and (IsBoolean(BVal.aType)) then
+ begin
+ if BVal.Operator = otAnd then
+ begin
+ BlockWriteByte(BlockInfo, Cm_CNG);
+ jover := Length(BlockInfo.Proc.FData);
+ BlockWriteLong(BlockInfo, 0);
+ WriteOutRec(Output, True);
+ jend := Length(BlockInfo.Proc.FData);
+ end else if BVal.Operator = otOr then
+ begin
+ BlockWriteByte(BlockInfo, Cm_CG);
+ jover := Length(BlockInfo.Proc.FData);
+ BlockWriteLong(BlockInfo, 0);
+ WriteOutRec(Output, True);
+ jend := Length(BlockInfo.Proc.FData);
+ end else
+ begin
+ jover := 0;
+ jend := 0;
+ end;
+ end else
+ begin
+ jover := 0;
+ jend := 0;
+ end;
+ if not PreWriteOutrec(BVal.FVal2, GetTypeNo(BlockInfo, Output)) then
+ begin
+ Result := False;
+ exit;
+ end;
+ BlockWriteByte(BlockInfo, Cm_CA);
+ if BVAL.Operator = otIntDiv then
+ BlockWriteByte(BlockInfo, Ord(otDiv))
+ else
+ BlockWriteByte(BlockInfo, Ord(BVal.Operator));
+ if not (WriteOutRec(Output, False) and WriteOutRec(BVal.FVal2, True)) then
+ begin
+ Result := False;
+ exit;
+ end;
+ AfterWriteOutRec(BVal.FVal2);
+ if FBooleanShortCircuit and (IsBoolean(BVal.aType)) and (JOver <> JEnd) then
+ begin
+ {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
+ unaligned(Cardinal((@BlockInfo.Proc.FData[jover+1])^)) := Cardinal(Length(BlockInfo.Proc.FData)) - jend;
+ {$else}
+ Cardinal((@BlockInfo.Proc.FData[jover+1])^) := Cardinal(Length(BlockInfo.Proc.FData)) - jend;
+ {$endif}
+ end;
+ AfterWriteOutRec(Output);
+ end;
+ Result := True;
+ end;
+
+ function DoUnCalc(Val: TPSUnValueOp; Output: TPSValue): Boolean;
+ var
+ Tmp: TPSValue;
+ begin
+ if not PreWriteOutRec(Output, nil) then
+ begin
+ Result := False;
+ exit;
+ end;
+ case Val.Operator of
+ otNot:
+ begin
+ if not SameReg(Val.FVal1, Output) then
+ begin
+ if not WriteCalculation(Val.FVal1, Output) then
+ begin
+ Result := False;
+ exit;
+ end;
+ end;
+ if IsBoolean(GetTypeNo(BlockInfo, Val)) then
+ BlockWriteByte(BlockInfo, cm_bn)
+ else
+ BlockWriteByte(BlockInfo, cm_in);
+ if not WriteOutRec(Output, True) then
+ begin
+ Result := False;
+ exit;
+ end;
+ end;
+ otMinus:
+ begin
+ if not SameReg(Val.FVal1, Output) then
+ begin
+ if not WriteCalculation(Val.FVal1, Output) then
+ begin
+ Result := False;
+ exit;
+ end;
+ end;
+ BlockWriteByte(BlockInfo, cm_vm);
+ if not WriteOutRec(Output, True) then
+ begin
+ Result := False;
+ exit;
+ end;
+ end;
+ otCast:
+ begin
+ if ((Val.aType.BaseType = btChar) and (Val.aType.BaseType <> btU8)) {$IFNDEF PS_NOWIDESTRING}or
+ ((Val.aType.BaseType = btWideChar) and (Val.aType.BaseType <> btU16)){$ENDIF} then
+ begin
+ Tmp := AllocStackReg(Val.aType);
+ end else
+ Tmp := Output;
+ if not (PreWriteOutRec(Val.FVal1, GetTypeNo(BlockInfo, Tmp)) and PreWriteOutRec(Tmp, GetTypeNo(BlockInfo, Tmp))) then
+ begin
+ Result := False;
+ if tmp <> Output then Tmp.Free;
+ exit;
+ end;
+ BlockWriteByte(BlockInfo, CM_A);
+ if not (WriteOutRec(Tmp, False) and WriteOutRec(Val.FVal1, True)) then
+ begin
+ Result := false;
+ if tmp <> Output then Tmp.Free;
+ exit;
+ end;
+ AfterWriteOutRec(val.Fval1);
+ if Tmp <> Output then
+ begin
+ if not WriteCalculation(Tmp, Output) then
+ begin
+ Result := false;
+ Tmp.Free;
+ exit;
+ end;
+ end;
+ AfterWriteOutRec(Tmp);
+ if Tmp <> Output then
+ Tmp.Free;
+ end;
+ {else donothing}
+ end;
+ AfterWriteOutRec(Output);
+ Result := True;
+ end;
+
+
+ function GetAddress(Val: TPSValue): Cardinal;
+ begin
+ if Val.ClassType = TPSValueGlobalVar then
+ Result := TPSValueGlobalVar(val).GlobalVarNo
+ else if Val.ClassType = TPSValueLocalVar then
+ Result := PSAddrStackStart + TPSValueLocalVar(val).LocalVarNo + 1
+ else if Val.ClassType = TPSValueParamVar then
+ Result := PSAddrStackStart - TPSValueParamVar(val).ParamNo -1
+ else if Val.ClassType = TPSValueAllocatedStackVar then
+ Result := PSAddrStackStart + TPSValueAllocatedStackVar(val).LocalVarNo + 1
+ else
+ Result := InvalidVal;
+ end;
+
+
+ function PreWriteOutRec(var X: TPSValue; FArrType: TPSType): Boolean;
+ var
+ rr: TPSSubItem;
+ tmpp,
+ tmpc: TPSValue;
+ i: Longint;
+ function MakeSet(SetType: TPSSetType; arr: TPSValueArray): Boolean;
+ var
+ c, i: Longint;
+ dataval: TPSValueData;
+ mType: TPSType;
+ begin
+ Result := True;
+ dataval := TPSValueData.Create;
+ dataval.Data := NewVariant(FarrType);
+ for i := 0 to arr.count -1 do
+ begin
+ mType := GetTypeNo(BlockInfo, arr.Item[i]);
+ if mType <> SetType.SetType then
+ begin
+ with MakeError('', ecTypeMismatch, '') do
+ begin
+ FCol := arr.item[i].Col;
+ FRow := arr.item[i].Row;
+ FPosition := arr.item[i].Pos;
+ end;
+ DataVal.Free;
+ Result := False;
+ exit;
+ end;
+ if arr.Item[i] is TPSValueData then
+ begin
+ c := GetInt(TPSValueData(arr.Item[i]).Data, Result);
+ if not Result then
+ begin
+ dataval.Free;
+ exit;
+ end;
+ Set_MakeMember(c, dataval.Data.tstring);
+ end else
+ begin
+ DataVal.Free;
+ MakeError('', ecTypeMismatch, '');
+ Result := False;
+ exit;
+ end;
+ end;
+ tmpc := TPSValueReplace.Create;
+ with TPSValueReplace(tmpc) do
+ begin
+ OldValue := x;
+ NewValue := dataval;
+ PreWriteAllocated := True;
+ end;
+ x := tmpc;
+ end;
+ begin
+ Result := True;
+ if x.ClassType = TPSValueReplace then
+ begin
+ if TPSValueReplace(x).PreWriteAllocated then
+ begin
+ inc(TPSValueReplace(x).FReplaceTimes);
+ end;
+ end else
+ if x.ClassType = TPSValueProcPtr then
+ begin
+ if FArrType = nil then
+ begin
+ MakeError('', ecTypeMismatch, '');
+ Result := False;
+ Exit;
+ end;
+ tmpp := TPSValueData.Create;
+ TPSValueData(tmpp).Data := NewVariant(FArrType);
+ TPSValueData(tmpp).Data.tu32 := TPSValueProcPtr(x).ProcPtr;
+ tmpc := TPSValueReplace.Create;
+ with TPSValueReplace(tmpc) do
+ begin
+ PreWriteAllocated := True;
+ OldValue := x;
+ NewValue := tmpp;
+ end;
+ x := tmpc;
+ end else
+ if x.ClassType = TPSValueNil then
+ begin
+ if FArrType = nil then
+ begin
+ MakeError('', ecTypeMismatch, '');
+ Result := False;
+ Exit;
+ end;
+ tmpp := AllocStackReg(FArrType);
+ if not MakeNil(x.Pos, x.Row, x.Col, tmpp) then
+ begin
+ tmpp.Free;
+ Result := False;
+ exit;
+ end;
+ tmpc := TPSValueReplace.Create;
+ with TPSValueReplace(tmpc) do
+ begin
+ PreWriteAllocated := True;
+ OldValue := x;
+ NewValue := tmpp;
+ end;
+ x := tmpc;
+ end else
+ if x.ClassType = TPSValueArray then
+ begin
+ if FArrType = nil then
+ begin
+ MakeError('', ecTypeMismatch, '');
+ Result := False;
+ Exit;
+ end;
+ if TPSType(FArrType).BaseType = btSet then
+ begin
+ Result := MakeSet(TPSSetType(FArrType), TPSValueArray(x));
+ exit;
+ end;
+ if TPSType(FarrType).BaseType = btVariant then
+ FArrType := FindAndAddType(self, '', 'array of variant');
+ if TPSType(FarrType).BaseType <> btArray then
+ FArrType := FindAndAddType(self, '', 'array of variant');
+
+ tmpp := AllocStackReg(FArrType);
+ tmpc := AllocStackReg(FindBaseType(bts32));
+ BlockWriteByte(BlockInfo, CM_A);
+ WriteOutrec(tmpc, False);
+ BlockWriteByte(BlockInfo, 1);
+ BlockWriteLong(BlockInfo, FindBaseType(bts32).FinalTypeNo);
+ BlockWriteLong(BlockInfo, TPSValueArray(x).Count);
+ BlockWriteByte(BlockInfo, CM_PV);
+ WriteOutrec(tmpp, False);
+ BlockWriteByte(BlockInfo, CM_C);
+ BlockWriteLong(BlockInfo, FindProc('SETARRAYLENGTH'));
+ BlockWriteByte(BlockInfo, CM_PO);
+ tmpc.Free;
+ rr := TPSSubNumber.Create;
+ rr.aType := TPSArrayType(FArrType).ArrayTypeNo;
+ TPSValueVar(tmpp).RecAdd(rr);
+ for i := 0 to TPSValueArray(x).Count -1 do
+ begin
+ TPSSubNumber(rr).SubNo := i;
+ tmpc := TPSValueArray(x).Item[i];
+ if not PreWriteOutRec(tmpc, GetTypeNo(BlockInfo, tmpc)) then
+ begin
+ tmpp.Free;
+ Result := false;
+ exit;
+ end;
+ if TPSArrayType(FArrType).ArrayTypeNo.BaseType = btPointer then
+ BlockWriteByte(BlockInfo, cm_spc)
+ else
+ BlockWriteByte(BlockInfo, cm_a);
+ if not (WriteOutrec(tmpp, False) and WriteOutRec(tmpc, True)) then
+ begin
+ Tmpp.Free;
+ Result := false;
+ exit;
+ end;
+ AfterWriteOutRec(tmpc);
+ end;
+ TPSValueVar(tmpp).RecDelete(0);
+ tmpc := TPSValueReplace.Create;
+ with TPSValueReplace(tmpc) do
+ begin
+ PreWriteAllocated := True;
+ OldValue := x;
+ NewValue := tmpp;
+ end;
+ x := tmpc;
+ end else if (x.ClassType = TPSUnValueOp) then
+ begin
+ tmpp := AllocStackReg(GetTypeNo(BlockInfo, x));
+ if not DoUnCalc(TPSUnValueOp(x), tmpp) then
+ begin
+ Result := False;
+ exit;
+ end;
+ tmpc := TPSValueReplace.Create;
+ with TPSValueReplace(tmpc) do
+ begin
+ PreWriteAllocated := True;
+ OldValue := x;
+ NewValue := tmpp;
+ end;
+ x := tmpc;
+ end else if (x.ClassType = TPSBinValueOp) then
+ begin
+ tmpp := AllocStackReg(GetTypeNo(BlockInfo, x));
+ if not DoBinCalc(TPSBinValueOp(x), tmpp) then
+ begin
+ tmpp.Free;
+ Result := False;
+ exit;
+ end;
+ tmpc := TPSValueReplace.Create;
+ with TPSValueReplace(tmpc) do
+ begin
+ PreWriteAllocated := True;
+ OldValue := x;
+ NewValue := tmpp;
+ end;
+ x := tmpc;
+ end else if x is TPSValueProc then
+ begin
+ tmpp := AllocStackReg(TPSValueProc(x).ResultType);
+ if not WriteCalculation(x, tmpp) then
+ begin
+ tmpp.Free;
+ Result := False;
+ exit;
+ end;
+ tmpc := TPSValueReplace.Create;
+ with TPSValueReplace(tmpc) do
+ begin
+ PreWriteAllocated := True;
+ OldValue := x;
+ NewValue := tmpp;
+ end;
+ x := tmpc;
+ end else if (x is TPSValueVar) and (TPSValueVar(x).RecCount <> 0) then
+ begin
+ if TPSValueVar(x).RecCount = 1 then
+ begin
+ rr := TPSValueVar(x).RecItem[0];
+ if rr.ClassType <> TPSSubValue then
+ exit; // there is no need pre-calculate anything
+ if (TPSSubValue(rr).SubNo is TPSValueVar) and (TPSValueVar(TPSSubValue(rr).SubNo).RecCount = 0) then
+ exit;
+ end; //if
+ tmpp := AllocPointer(GetTypeNo(BlockInfo, x));
+ BlockWriteByte(BlockInfo, cm_sp);
+ WriteOutRec(tmpp, True);
+ BlockWriteByte(BlockInfo, 0);
+ BlockWriteLong(BlockInfo, GetAddress(x));
+ for i := 0 to TPSValueVar(x).RecCount - 1 do
+ begin
+ rr := TPSValueVar(x).RecItem[I];
+ if rr.ClassType = TPSSubNumber then
+ begin
+ BlockWriteByte(BlockInfo, cm_sp);
+ WriteOutRec(tmpp, false);
+ BlockWriteByte(BlockInfo, 2);
+ BlockWriteLong(BlockInfo, GetAddress(tmpp));
+ BlockWriteLong(BlockInfo, TPSSubNumber(rr).SubNo);
+ end else begin // if rr.classtype = TPSSubValue then begin
+ tmpc := AllocStackReg(FindBaseType(btU32));
+ if not WriteCalculation(TPSSubValue(rr).SubNo, tmpc) then
+ begin
+ tmpc.Free;
+ tmpp.Free;
+ Result := False;
+ exit;
+ end; //if
+ BlockWriteByte(BlockInfo, cm_sp);
+ WriteOutRec(tmpp, false);
+ BlockWriteByte(BlockInfo, 3);
+ BlockWriteLong(BlockInfo, GetAddress(tmpp));
+ BlockWriteLong(BlockInfo, GetAddress(tmpc));
+ tmpc.Free;
+ end;
+ end; // for
+ tmpc := TPSValueReplace.Create;
+ with TPSValueReplace(tmpc) do
+ begin
+ OldValue := x;
+ NewValue := tmpp;
+ PreWriteAllocated := True;
+ end;
+ x := tmpc;
+ end;
+
+ end;
+
+ procedure AfterWriteOutRec(var x: TPSValue);
+ var
+ tmp: TPSValue;
+ begin
+ if (x.ClassType = TPSValueReplace) and (TPSValueReplace(x).PreWriteAllocated) then
+ begin
+ Dec(TPSValueReplace(x).FReplaceTimes);
+ if TPSValueReplace(x).ReplaceTimes = 0 then
+ begin
+ tmp := TPSValueReplace(x).OldValue;
+ x.Free;
+ x := tmp;
+ end;
+ end;
+ end; //afterwriteoutrec
+
+ function WriteOutRec(x: TPSValue; AllowData: Boolean): Boolean;
+ var
+ rr: TPSSubItem;
+ begin
+ Result := True;
+ if x.ClassType = TPSValueReplace then
+ Result := WriteOutRec(TPSValueReplace(x).NewValue, AllowData)
+ else if x is TPSValueVar then
+ begin
+ if TPSValueVar(x).RecCount = 0 then
+ begin
+ BlockWriteByte(BlockInfo, 0);
+ BlockWriteLong(BlockInfo, GetAddress(x));
+ end
+ else
+ begin
+ rr := TPSValueVar(x).RecItem[0];
+ if rr.ClassType = TPSSubNumber then
+ begin
+ BlockWriteByte(BlockInfo, 2);
+ BlockWriteLong(BlockInfo, GetAddress(x));
+ BlockWriteLong(BlockInfo, TPSSubNumber(rr).SubNo);
+ end
+ else
+ begin
+ BlockWriteByte(BlockInfo, 3);
+ BlockWriteLong(BlockInfo, GetAddress(x));
+ BlockWriteLong(BlockInfo, GetAddress(TPSSubValue(rr).SubNo));
+ end;
+ end;
+ end else if x.ClassType = TPSValueData then
+ begin
+ if AllowData then
+ begin
+ BlockWriteByte(BlockInfo, 1);
+ BlockWriteVariant(BlockInfo, TPSValueData(x).Data)
+ end
+ else
+ begin
+ Result := False;
+ exit;
+ end;
+ end else
+ Result := False;
+ end;
+
+ function ReadParameters(IsProperty: Boolean; Dest: TPSParameters): Boolean; forward;
+{$IFNDEF PS_NOIDISPATCH}
+ function ReadIDispatchParameters(const ProcName: tbtString; aVariantType: TPSVariantType; FSelf: TPSValue): TPSValue; forward;
+{$ENDIF}
+ function ReadProcParameters(ProcNo: Cardinal; FSelf: TPSValue): TPSValue; forward;
+ function ReadVarParameters(ProcNoVar: TPSValue): TPSValue; forward;
+
+ function calc(endOn: TPSPasToken): TPSValue; forward;
+ procedure CheckNotificationVariant(var Val: TPSValue);
+ var
+ aType: TPSType;
+ Call: TPSValueProcNo;
+ tmp: TPSValue;
+ begin
+ if not (Val is TPSValueGlobalVar) then exit;
+ aType := GetTypeNo(BlockInfo, Val);
+ if (AType = nil) or (AType.BaseType <> btNotificationVariant) then exit;
+ if FParser.CurrTokenId = CSTI_Assignment then
+ begin
+ Call := TPSValueProcNo.Create;
+ Call.ResultType := nil;
+ Call.SetParserPos(FParser);
+ Call.ProcNo := FindProc('!NOTIFICATIONVARIANTSET');;
+ Call.SetParserPos(FParser);
+ Call.Parameters := TPSParameters.Create;
+ Tmp := TPSValueData.Create;
+ TPSVAlueData(tmp).Data := NewVariant(at2ut(FindBaseType(btString)));
+ tbtString(TPSValueData(tmp).Data.tstring) := TPSVar(FVars[TPSValueGlobalVar(Val).GlobalVarNo]).OrgName;
+ with call.Parameters.Add do
+ begin
+ Val := tmp;
+ ExpectedType := TPSValueData(tmp).Data.FType;
+ end;
+ FParser.Next;
+ tmp := Calc(CSTI_SemiColon);
+ if tmp = nil then
+ begin
+ Val.Free;
+ Val := nil;
+ exit;
+ end;
+ with Call.Parameters.Add do
+ begin
+ Val := tmp;
+ ExpectedType := at2ut(FindBaseType(btVariant));
+ end;
+ Val.Free;
+ Val := Call;
+ end else begin
+ Call := TPSValueProcNo.Create;
+ Call.ResultType := AT2UT(FindBaseType(btVariant));
+ Call.SetParserPos(FParser);
+ Call.ProcNo := FindProc('!NOTIFICATIONVARIANTGET');
+ Call.SetParserPos(FParser);
+ Call.Parameters := TPSParameters.Create;
+ Tmp := TPSValueData.Create;
+ TPSVAlueData(tmp).Data := NewVariant(at2ut(FindBaseType(btString)));
+ tbtString(TPSValueData(tmp).Data.tstring) := TPSVar(FVars[TPSValueGlobalVar(Val).GlobalVarNo]).OrgName;
+ with call.Parameters.Add do
+ begin
+ Val := tmp;
+ ExpectedType := TPSValueData(tmp).Data.FType;
+ end;
+ Val.Free;
+ Val := Call;
+ end;
+ end;
+
+ procedure CheckProcCall(var x: TPSValue);
+ var
+ aType: TPSType;
+ begin
+ if FParser.CurrTokenId in [CSTI_Dereference, CSTI_OpenRound] then
+ begin
+ aType := GetTypeNo(BlockInfo, x);
+ if (aType = nil) or (aType.BaseType <> btProcPtr) then
+ begin
+ MakeError('', ecTypeMismatch, '');
+ x.Free;
+ x := nil;
+ Exit;
+ end;
+ if FParser.CurrTokenId = CSTI_Dereference then
+ FParser.Next;
+ x := ReadVarParameters(x);
+ end;
+ end;
+
+ procedure CheckFurther(var x: TPSValue; ImplicitPeriod: Boolean);
+ var
+ t: Cardinal;
+ rr: TPSSubItem;
+ L: Longint;
+ u: TPSType;
+ Param: TPSParameter;
+ tmp, tmpn: TPSValue;
+ tmp3: TPSValueProcNo;
+ tmp2: Boolean;
+
+ function FindSubR(const n: tbtString; FType: TPSType): Cardinal;
+ var
+ h, I: Longint;
+ rvv: PIFPSRecordFieldTypeDef;
+ begin
+ h := MakeHash(n);
+ for I := 0 to TPSRecordType(FType).RecValCount - 1 do
+ begin
+ rvv := TPSRecordType(FType).RecVal(I);
+ if (rvv.FieldNameHash = h) and (rvv.FieldName = n) then
+ begin
+ Result := I;
+ exit;
+ end;
+ end;
+ Result := InvalidVal;
+ end;
+
+ begin
+(* if not (x is TPSValueVar) then
+ Exit;*)
+ u := GetTypeNo(BlockInfo, x);
+ if u = nil then exit;
+ while True do
+ begin
+ if (u.BaseType = btClass) {$IFNDEF PS_NOINTERFACES}or (u.BaseType = btInterface){$ENDIF}
+ {$IFNDEF PS_NOIDISPATCH}or ((u.BaseType = btVariant) or (u.BaseType = btNotificationVariant)){$ENDIF} or (u.BaseType = btExtClass) then exit;
+ if FParser.CurrTokenId = CSTI_OpenBlock then
+ begin
+ if (u.BaseType = btString) {$IFNDEF PS_NOWIDESTRING} or (u.BaseType = btWideString) or (u.BaseType = btUnicodeString) {$ENDIF} then
+ begin
+ FParser.Next;
+ tmp := Calc(CSTI_CloseBlock);
+ if tmp = nil then
+ begin
+ x.Free;
+ x := nil;
+ exit;
+ end;
+ if not IsIntType(GetTypeNo(BlockInfo, tmp).BaseType) then
+ begin
+ MakeError('', ecTypeMismatch, '');
+ tmp.Free;
+ x.Free;
+ x := nil;
+ exit;
+ end;
+ FParser.Next;
+ if FParser.CurrTokenId = CSTI_Assignment then
+ begin
+ if not (x is TPSValueVar) then begin
+ MakeError('', ecVariableExpected, '');
+ tmp.Free;
+ x.Free;
+ x := nil;
+ exit;
+ end;
+ {$IFNDEF PS_NOWIDESTRING}
+ if (u.BaseType = btWideString) or (u.BaseType = btUnicodeString) then
+ l := FindProc('WSTRSET')
+ else
+ {$ENDIF}
+ l := FindProc('STRSET');
+ if l = -1 then
+ begin
+ MakeError('', ecUnknownIdentifier, 'StrSet');
+ tmp.Free;
+ x.Free;
+ x := nil;
+ exit;
+ end;
+ tmp3 := TPSValueProcNo.Create;
+ tmp3.ResultType := nil;
+ tmp3.SetParserPos(FParser);
+ tmp3.ProcNo := L;
+ tmp3.SetParserPos(FParser);
+ tmp3.Parameters := TPSParameters.Create;
+ param := tmp3.Parameters.Add;
+ with tmp3.Parameters.Add do
+ begin
+ Val := tmp;
+ ExpectedType := GetTypeNo(BlockInfo, tmp);
+{$IFDEF DEBUG}
+ if not ExpectedType.Used then asm int 3; end;
+{$ENDIF}
+ end;
+ with tmp3.Parameters.Add do
+ begin
+ Val := x;
+ ExpectedType := GetTypeNo(BlockInfo, x);
+{$IFDEF DEBUG}
+ if not ExpectedType.Used then asm int 3; end;
+{$ENDIF}
+ ParamMode := pmInOut;
+ end;
+ x := tmp3;
+ FParser.Next;
+ tmp := Calc(CSTI_SemiColon);
+ if tmp = nil then
+ begin
+ x.Free;
+ x := nil;
+ exit;
+ end;
+ if (GetTypeNo(BlockInfo, Tmp).BaseType <> btChar)
+ {$IFNDEF PS_NOWIDESTRING} and (GetTypeno(BlockInfo, Tmp).BaseType <> btWideChar) {$ENDIF} then
+ begin
+ x.Free;
+ x := nil;
+ Tmp.Free;
+ MakeError('', ecTypeMismatch, '');
+ exit;
+
+ end;
+ param.Val := tmp;
+ Param.ExpectedType := GetTypeNo(BlockInfo, tmp);
+{$IFDEF DEBUG}
+ if not Param.ExpectedType.Used then asm int 3; end;
+{$ENDIF}
+ end else begin
+ {$IFNDEF PS_NOWIDESTRING}
+ if (u.BaseType = btWideString) or (u.BaseType = btUnicodeString) then
+ l := FindProc('WSTRGET')
+ else
+ {$ENDIF}
+ l := FindProc('STRGET');
+ if l = -1 then
+ begin
+ MakeError('', ecUnknownIdentifier, 'StrGet');
+ tmp.Free;
+ x.Free;
+ x := nil;
+ exit;
+ end;
+ tmp3 := TPSValueProcNo.Create;
+ {$IFNDEF PS_NOWIDESTRING}
+ if (u.BaseType = btWideString) or (u.BaseType = btUnicodeString) then
+ tmp3.ResultType := FindBaseType(btWideChar)
+ else
+ {$ENDIF}
+ tmp3.ResultType := FindBaseType(btChar);
+ tmp3.ProcNo := L;
+ tmp3.SetParserPos(FParser);
+ tmp3.Parameters := TPSParameters.Create;
+ with tmp3.Parameters.Add do
+ begin
+ Val := x;
+ ExpectedType := GetTypeNo(BlockInfo, x);
+{$IFDEF DEBUG}
+ if not ExpectedType.Used then asm int 3; end;
+{$ENDIF}
+
+ if x is TPSValueVar then
+ ParamMode := pmInOut
+ else
+ parammode := pmIn;
+ end;
+ with tmp3.Parameters.Add do
+ begin
+ Val := tmp;
+ ExpectedType := GetTypeNo(BlockInfo, tmp);
+{$IFDEF DEBUG}
+ if not ExpectedType.Used then asm int 3; end;
+{$ENDIF}
+ end;
+ x := tmp3;
+ end;
+ Break;
+ end else if ((u.BaseType = btArray) or (u.BaseType = btStaticArray)) and (x is TPSValueVar) then
+ begin
+ FParser.Next;
+ tmp := calc(CSTI_CloseBlock);
+ if tmp = nil then
+ begin
+ x.Free;
+ x := nil;
+ exit;
+ end;
+ if not IsIntType(GetTypeNo(BlockInfo, tmp).BaseType) then
+ begin
+ MakeError('', ecTypeMismatch, '');
+ tmp.Free;
+ x.Free;
+ x := nil;
+ exit;
+ end;
+ if (tmp.ClassType = TPSValueData) then
+ begin
+ rr := TPSSubNumber.Create;
+ TPSValueVar(x).RecAdd(rr);
+ if (u.BaseType = btStaticArray) then
+ TPSSubNumber(rr).SubNo := Cardinal(GetInt(TPSValueData(tmp).Data, tmp2) - TPSStaticArrayType(u).StartOffset)
+ else
+ TPSSubNumber(rr).SubNo := GetUInt(TPSValueData(tmp).Data, tmp2);
+ tmp.Free;
+ rr.aType := TPSArrayType(u).ArrayTypeNo;
+ u := rr.aType;
+ end
+ else
+ begin
+ if (u.BaseType = btStaticArray) then
+ begin
+ tmpn := TPSBinValueOp.Create;
+ TPSBinValueOp(tmpn).Operator := otSub;
+ TPSBinValueOp(tmpn).Val1 := tmp;
+ tmp := TPSValueData.Create;
+ TPSValueData(tmp).Data := NewVariant(FindBaseType(btS32));
+ TPSValueData(tmp).Data.ts32 := TPSStaticArrayType(u).StartOffset;
+ TPSBinValueOp(tmpn).Val2 := tmp;
+ TPSBinValueOp(tmpn).aType := FindBaseType(btS32);
+ tmp := tmpn;
+ end;
+ rr := TPSSubValue.Create;
+ TPSValueVar(x).recAdd(rr);
+ TPSSubValue(rr).SubNo := tmp;
+ rr.aType := TPSArrayType(u).ArrayTypeNo;
+ u := rr.aType;
+ end;
+ if FParser.CurrTokenId <> CSTI_CloseBlock then
+ begin
+ MakeError('', ecCloseBlockExpected, '');
+ x.Free;
+ x := nil;
+ exit;
+ end;
+ Fparser.Next;
+ end else begin
+ MakeError('', ecSemicolonExpected, '');
+ x.Free;
+ x := nil;
+ exit;
+ end;
+ end
+ else if (FParser.CurrTokenId = CSTI_Period) or (ImplicitPeriod) then
+ begin
+ if not ImplicitPeriod then
+ FParser.Next;
+ if u.BaseType = btRecord then
+ begin
+ t := FindSubR(FParser.GetToken, u);
+ if t = InvalidVal then
+ begin
+ if ImplicitPeriod then exit;
+ MakeError('', ecUnknownIdentifier, FParser.GetToken);
+ x.Free;
+ x := nil;
+ exit;
+ end;
+ if (x is TPSValueProcNo) then
+ begin
+ ImplicitPeriod := False;
+ FParser.Next;
+
+ tmp := AllocStackReg(u);
+ WriteCalculation(x,tmp);
+ TPSVar(BlockInfo.Proc.FProcVars[TPSValueAllocatedStackVar(tmp).LocalVarNo]).Use;
+
+ rr := TPSSubNumber.Create;
+ TPSValueVar(tmp).RecAdd(rr);
+ TPSSubNumber(rr).SubNo := t;
+ rr.aType := TPSRecordType(u).RecVal(t).FType;
+ u := rr.aType;
+
+ tmpn := TPSValueReplace.Create;
+ with TPSValueReplace(tmpn) do
+ begin
+ FreeOldValue := true;
+ FreeNewValue := true;
+ OldValue := tmp;
+ NewValue := AllocStackReg(u);
+ PreWriteAllocated := true;
+ end;
+
+ if not WriteCalculation(tmp,TPSValueReplace(tmpn).NewValue) then
+ begin
+ {MakeError('',ecInternalError,'');}
+ x.Free;
+ x := nil;
+ exit;
+ end;
+ x.Free;
+ x := tmpn;
+ end else
+ begin
+ if not (x is TPSValueVar) then begin
+ MakeError('', ecVariableExpected, FParser.GetToken);
+ x.Free;
+ x := nil;
+ exit;
+ end;
+ ImplicitPeriod := False;
+ FParser.Next;
+ rr := TPSSubNumber.Create;
+ TPSValueVar(x).RecAdd(rr);
+ TPSSubNumber(rr).SubNo := t;
+ rr.aType := TPSRecordType(u).RecVal(t).FType;
+ u := rr.aType;
+ end;
+ end
+ else
+ begin
+ x.Free;
+ MakeError('', ecSemicolonExpected, '');
+ x := nil;
+ exit;
+ end;
+ end
+ else
+ break;
+ end;
+ end;
+
+
+
+ procedure CheckClassArrayProperty(var P: TPSValue; const VarType: TPSVariableType; VarNo: Cardinal);
+ var
+ Tempp: TPSValue;
+ aType: TPSClassType;
+ procno: Cardinal;
+ Idx: IPointer;
+ Decl: TPSParametersDecl;
+ begin
+ if p = nil then exit;
+ if (GetTypeNo(BlockInfo, p) = nil) or (GetTypeNo(BlockInfo, p).BaseType <> btClass) then exit;
+ aType := TPSClassType(GetTypeNo(BlockInfo, p));
+ if FParser.CurrTokenID = CSTI_OpenBlock then
+ begin
+ if not TPSClassType(aType).Cl.Property_Find('', Idx) then
+ begin
+ MakeError('', ecPeriodExpected, '');
+ p.Free;
+ p := nil;
+ exit;
+ end;
+ if VarNo <> InvalidVal then
+ begin
+ if @FOnUseVariable <> nil then
+ FOnUseVariable(Self, VarType, VarNo, BlockInfo.ProcNo, FParser.CurrTokenPos, '[Default]');
+ end;
+ Decl := TPSParametersDecl.Create;
+ TPSClassType(aType).Cl.Property_GetHeader(Idx, Decl);
+ tempp := p;
+ P := TPSValueProcNo.Create;
+ with TPSValueProcNo(P) do
+ begin
+ Parameters := TPSParameters.Create;
+ Parameters.Add;
+ end;
+ if not (ReadParameters(True, TPSValueProc(P).Parameters) and
+ ValidateParameters(BlockInfo, TPSValueProc(P).Parameters, Decl)) then
+ begin
+ tempp.Free;
+ Decl.Free;
+ p.Free;
+ p := nil;
+ exit;
+ end;
+ with TPSValueProcNo(p).Parameters[0] do
+ begin
+ Val := tempp;
+ ExpectedType := GetTypeNo(BlockInfo, tempp);
+ end;
+ if FParser.CurrTokenId = CSTI_Assignment then
+ begin
+ FParser.Next;
+ TempP := Calc(CSTI_SemiColon);
+ if TempP = nil then
+ begin
+ Decl.Free;
+ P.Free;
+ p := nil;
+ exit;
+ end;
+ with TPSValueProc(p).Parameters.Add do
+ begin
+ Val := Tempp;
+ ExpectedType := at2ut(Decl.Result);
+ end;
+ if not TPSClassType(aType).Cl.Property_Set(Idx, procno) then
+ begin
+ Decl.Free;
+ MakeError('', ecReadOnlyProperty, '');
+ p.Free;
+ p := nil;
+ exit;
+ end;
+ TPSValueProcNo(p).ProcNo := procno;
+ TPSValueProcNo(p).ResultType := nil;
+ end
+ else
+ begin
+ if not TPSClassType(aType).Cl.Property_Get(Idx, procno) then
+ begin
+ Decl.Free;
+ MakeError('', ecWriteOnlyProperty, '');
+ p.Free;
+ p := nil;
+ exit;
+ end;
+ TPSValueProcNo(p).ProcNo := procno;
+ TPSValueProcNo(p).ResultType := TPSExternalProcedure(FProcs[procno]).RegProc.Decl.Result;
+ end; // if FParser.CurrTokenId = CSTI_Assign
+ Decl.Free;
+ end;
+ end;
+
+ procedure CheckExtClass(var P: TPSValue; const VarType: TPSVariableType; VarNo: Cardinal; ImplicitPeriod: Boolean);
+ var
+ Temp, Idx: Cardinal;
+ FType: TPSType;
+ s: tbtString;
+
+ begin
+ FType := GetTypeNo(BlockInfo, p);
+ if FType = nil then Exit;
+ if FType.BaseType <> btExtClass then Exit;
+ while (FParser.CurrTokenID = CSTI_Period) or (ImplicitPeriod) do
+ begin
+ if not ImplicitPeriod then
+ FParser.Next;
+ if FParser.CurrTokenID <> CSTI_Identifier then
+ begin
+ if ImplicitPeriod then exit;
+ MakeError('', ecIdentifierExpected, '');
+ p.Free;
+ P := nil;
+ Exit;
+ end;
+ s := FParser.GetToken;
+ if TPSUndefinedClassType(FType).ExtClass.Func_Find(s, Idx) then
+ begin
+ FParser.Next;
+ TPSUndefinedClassType(FType).ExtClass.Func_Call(Idx, Temp);
+ P := ReadProcParameters(Temp, P);
+ if p = nil then
+ begin
+ Exit;
+ end;
+ end else
+ begin
+ if ImplicitPeriod then exit;
+ MakeError('', ecUnknownIdentifier, s);
+ p.Free;
+ P := nil;
+ Exit;
+ end;
+ ImplicitPeriod := False;
+ FType := GetTypeNo(BlockInfo, p);
+ if (FType = nil) or (FType.BaseType <> btExtClass) then Exit;
+ end; {while}
+ end;
+
+ procedure CheckClass(var P: TPSValue; const VarType: TPSVariableType; VarNo: Cardinal; ImplicitPeriod: Boolean);
+ var
+ Procno: Cardinal;
+ Idx: IPointer;
+ FType: TPSType;
+ TempP: TPSValue;
+ Decl: TPSParametersDecl;
+ s: tbtString;
+
+ pinfo, pinfonew: tbtString;
+ ppos: Cardinal;
+
+ begin
+ FType := GetTypeNo(BlockInfo, p);
+ if FType = nil then exit;
+ pinfo := '';
+ if (FType.BaseType <> btClass) then Exit;
+ while (FParser.CurrTokenID = CSTI_Period) or (ImplicitPeriod) do
+ begin
+ if not ImplicitPeriod then
+ FParser.Next;
+ if FParser.CurrTokenID <> CSTI_Identifier then
+ begin
+ if ImplicitPeriod then exit;
+ MakeError('', ecIdentifierExpected, '');
+ p.Free;
+ P := nil;
+ Exit;
+ end;
+ s := FParser.GetToken;
+ if TPSClassType(FType).Cl.Func_Find(s, Idx) then
+ begin
+ FParser.Next;
+ VarNo := InvalidVal;
+ TPSClassType(FType).cl.Func_Call(Idx, Procno);
+ P := ReadProcParameters(Procno, P);
+ if p = nil then
+ begin
+ Exit;
+ end;
+ end else if TPSClassType(FType).cl.Property_Find(s, Idx) then
+ begin
+ ppos := FParser.CurrTokenPos;
+ pinfonew := FParser.OriginalToken;
+ FParser.Next;
+ if VarNo <> InvalidVal then
+ begin
+ if pinfo = '' then
+ pinfo := pinfonew
+ else
+ pinfo := pinfo + '.' + pinfonew;
+ if @FOnUseVariable <> nil then
+ FOnUseVariable(Self, VarType, VarNo, BlockInfo.ProcNo, ppos, pinfo);
+ end;
+ Decl := TPSParametersDecl.Create;
+ TPSClassType(FType).cl.Property_GetHeader(Idx, Decl);
+ TempP := P;
+ p := TPSValueProcNo.Create;
+ with TPSValueProcNo(p) do
+ begin
+ Parameters := TPSParameters.Create;
+ Parameters.Add;
+ Pos := FParser.CurrTokenPos;
+ row := FParser.Row;
+ Col := FParser.Col;
+ end;
+ if Decl.ParamCount <> 0 then
+ begin
+ if not (ReadParameters(True, TPSValueProc(P).Parameters) and
+ ValidateParameters(BlockInfo, TPSValueProc(P).Parameters, Decl)) then
+ begin
+ Tempp.Free;
+ Decl.Free;
+ p.Free;
+ P := nil;
+ exit;
+ end;
+ end; // if
+ with TPSValueProcNo(p).Parameters[0] do
+ begin
+ Val := TempP;
+ ExpectedType := at2ut(GetTypeNo(BlockInfo, TempP));
+ end;
+ if FParser.CurrTokenId = CSTI_Assignment then
+ begin
+ FParser.Next;
+ TempP := Calc(CSTI_SemiColon);
+ if TempP = nil then
+ begin
+ Decl.Free;
+ P.Free;
+ p := nil;
+ exit;
+ end;
+ with TPSValueProc(p).Parameters.Add do
+ begin
+ Val := Tempp;
+ ExpectedType := at2ut(Decl.Result);
+{$IFDEF DEBUG}
+ if not ExpectedType.Used then asm int 3; end;
+{$ENDIF}
+ end;
+
+ if not TPSClassType(FType).cl.Property_Set(Idx, Procno) then
+ begin
+ MakeError('', ecReadOnlyProperty, '');
+ Decl.Free;
+ p.Free;
+ p := nil;
+ exit;
+ end;
+ TPSValueProcNo(p).ProcNo := Procno;
+ TPSValueProcNo(p).ResultType := nil;
+ Decl.Free;
+ Exit;
+ end else begin
+ if not TPSClassType(FType).cl.Property_Get(Idx, Procno) then
+ begin
+ MakeError('', ecWriteOnlyProperty, '');
+ Decl.Free;
+ p.Free;
+ p := nil;
+ exit;
+ end;
+ TPSValueProcNo(p).ProcNo := ProcNo;
+ TPSValueProcNo(p).ResultType := TPSExternalProcedure(FProcs[ProcNo]).RegProc.Decl.Result;
+ end; // if FParser.CurrTokenId = CSTI_Assign
+ Decl.Free;
+ end else
+ begin
+ if ImplicitPeriod then exit;
+ MakeError('', ecUnknownIdentifier, s);
+ p.Free;
+ P := nil;
+ Exit;
+ end;
+ ImplicitPeriod := False;
+ FType := GetTypeNo(BlockInfo, p);
+ if (FType = nil) or (FType.BaseType <> btClass) then Exit;
+ end; {while}
+ end;
+{$IFNDEF PS_NOIDISPATCH}
+ procedure CheckIntf(var P: TPSValue; const VarType: TPSVariableType; VarNo: Cardinal; ImplicitPeriod: Boolean);
+ var
+ Procno, Idx: Cardinal;
+ FType: TPSType;
+ s: tbtString;
+
+ CheckArrayProperty,HasArrayProperty:boolean;
+ begin
+ FType := GetTypeNo(BlockInfo, p);
+ if FType = nil then exit;
+ if (FType.BaseType <> btInterface) and (Ftype.BaseType <> BtVariant) and (FType.BaseType = btNotificationVariant) then Exit;
+
+ CheckArrayProperty:=(FParser.CurrTokenID=CSTI_OpenBlock)and
+ (Ftype.BaseType = BtVariant);
+ while (FParser.CurrTokenID = CSTI_Period)
+ or (ImplicitPeriod)or (CheckArrayProperty) do begin
+
+ HasArrayProperty:=CheckArrayProperty;
+ if CheckArrayProperty then begin
+ CheckArrayProperty:=false;
+ end else begin
+ if not ImplicitPeriod then
+ FParser.Next;
+ end;
+ if FParser.CurrTokenID <> CSTI_Identifier then
+ begin
+ if ImplicitPeriod then exit;
+ if not HasArrayProperty then begin
+ MakeError('', ecIdentifierExpected, '');
+ p.Free;
+ P := nil;
+ Exit;
+ end;
+ end;
+ if (FType.BaseType = btVariant) or (FType.BaseType = btNotificationVariant) then
+ begin
+ if HasArrayProperty then begin
+ s:='';
+ end else begin
+ s := FParser.OriginalToken;
+ FParser.Next;
+ end;
+ ImplicitPeriod := False;
+ FType := GetTypeNo(BlockInfo, p);
+ p := ReadIDispatchParameters(s, TPSVariantType(FType), p);
+ if (FType = nil) or (FType.BaseType <> btInterface) then Exit;
+ end else
+ begin
+ s := FParser.GetToken;
+ if (FType is TPSInterfaceType) and (TPSInterfaceType(FType).Intf.Func_Find(s, Idx)) then
+ begin
+ FParser.Next;
+ TPSInterfaceType(FType).Intf.Func_Call(Idx, Procno);
+ P := ReadProcParameters(Procno, P);
+ if p = nil then
+ begin
+ Exit;
+ end;
+ end else
+ begin
+ if ImplicitPeriod then exit;
+ MakeError('', ecUnknownIdentifier, s);
+ p.Free;
+ P := nil;
+ Exit;
+ end;
+ ImplicitPeriod := False;
+ FType := GetTypeNo(BlockInfo, p);
+ if (FType = nil) or ((FType.BaseType <> btInterface) and (Ftype.BaseType <> btVariant) and (Ftype.BaseType <> btNotificationVariant)) then Exit;
+ end;
+ end; {while}
+ end;
+ {$ENDIF}
+ function ExtCheckClassType(FType: TPSType; const ParserPos: Cardinal): TPSValue;
+ var
+ FType2: TPSType;
+ ProcNo, Idx: Cardinal;
+ Temp, ResV: TPSValue;
+ begin
+ if FParser.CurrTokenID = CSTI_OpenRound then
+ begin
+ FParser.Next;
+ Temp := Calc(CSTI_CloseRound);
+ if Temp = nil then
+ begin
+ Result := nil;
+ exit;
+ end;
+ if FParser.CurrTokenID <> CSTI_CloseRound then
+ begin
+ temp.Free;
+ MakeError('', ecCloseRoundExpected, '');
+ Result := nil;
+ exit;
+ end;
+ FType2 := GetTypeNo(BlockInfo, Temp);
+ if (FType.basetype = BtClass) and (ftype2.BaseType = btClass) and (ftype <> ftype2) then
+ begin
+ if not TPSUndefinedClassType(FType2).ExtClass.CastToType(AT2UT(FType), ProcNo) then
+ begin
+ temp.Free;
+ MakeError('', ecTypeMismatch, '');
+ Result := nil;
+ exit;
+ end;
+ Result := TPSValueProcNo.Create;
+ TPSValueProcNo(Result).Parameters := TPSParameters.Create;
+ TPSValueProcNo(Result).ResultType := at2ut(FType);
+ TPSValueProcNo(Result).ProcNo := ProcNo;
+ with TPSValueProcNo(Result).Parameters.Add do
+ begin
+ Val := Temp;
+ ExpectedType := GetTypeNo(BlockInfo, temp);
+ end;
+ with TPSValueProcNo(Result).Parameters.Add do
+ begin
+ ExpectedType := at2ut(FindBaseType(btu32));
+ Val := TPSValueData.Create;
+ with TPSValueData(val) do
+ begin
+ SetParserPos(FParser);
+ Data := NewVariant(ExpectedType);
+ Data.tu32 := at2ut(FType).FinalTypeNo;
+ end;
+ end;
+ FParser.Next;
+ Exit;
+ end;
+ if not IsCompatibleType(FType, FType2, True) then
+ begin
+ temp.Free;
+ MakeError('', ecTypeMismatch, '');
+ Result := nil;
+ exit;
+ end;
+ FParser.Next;
+ Result := TPSUnValueOp.Create;
+ with TPSUnValueOp(Result) do
+ begin
+ Operator := otCast;
+ Val1 := Temp;
+ SetParserPos(FParser);
+ aType := AT2UT(FType);
+ end;
+ exit;
+ end;
+ if FParser.CurrTokenId <> CSTI_Period then
+ begin
+ Result := nil;
+ MakeError('', ecPeriodExpected, '');
+ Exit;
+ end;
+ if FType.BaseType <> btExtClass then
+ begin
+ Result := nil;
+ MakeError('', ecClassTypeExpected, '');
+ Exit;
+ end;
+ FParser.Next;
+ if not TPSUndefinedClassType(FType).ExtClass.ClassFunc_Find(FParser.GetToken, Idx) then
+ begin
+ Result := nil;
+ MakeError('', ecUnknownIdentifier, FParser.OriginalToken);
+ Exit;
+ end;
+ FParser.Next;
+ TPSUndefinedClassType(FType).ExtClass.ClassFunc_Call(Idx, ProcNo);
+ Temp := TPSValueData.Create;
+ with TPSValueData(Temp) do
+ begin
+ Data := NewVariant(at2ut(FindBaseType(btu32)));
+ Data.tu32 := at2ut(FType).FinalTypeNo;
+ end;
+ ResV := ReadProcParameters(ProcNo, Temp);
+ if ResV <> nil then
+ begin
+ TPSValueProc(Resv).ResultType := at2ut(FType);
+ Result := Resv;
+ end else begin
+ Result := nil;
+ end;
+ end;
+
+ function CheckClassType(TypeNo: TPSType; const ParserPos: Cardinal): TPSValue;
+ var
+ FType2: TPSType;
+ ProcNo: Cardinal;
+ Idx: IPointer;
+ Temp, ResV: TPSValue;
+ dta: PIfRVariant;
+ begin
+ if typeno.BaseType = btExtClass then
+ begin
+ Result := ExtCheckClassType(TypeNo, PArserPos);
+ exit;
+ end;
+ if FParser.CurrTokenID = CSTI_OpenRound then
+ begin
+ FParser.Next;
+ Temp := Calc(CSTI_CloseRound);
+ if Temp = nil then
+ begin
+ Result := nil;
+ exit;
+ end;
+ if FParser.CurrTokenID <> CSTI_CloseRound then
+ begin
+ temp.Free;
+ MakeError('', ecCloseRoundExpected, '');
+ Result := nil;
+ exit;
+ end;
+ FType2 := GetTypeNo(BlockInfo, Temp);
+ if ((typeno.BaseType = btClass){$IFNDEF PS_NOINTERFACES} or (TypeNo.basetype = btInterface){$ENDIF}) and
+ ((ftype2.BaseType = btClass){$IFNDEF PS_NOINTERFACES} or (ftype2.BaseType = btInterface){$ENDIF}) and (TypeNo <> ftype2) then
+ begin
+{$IFNDEF PS_NOINTERFACES}
+ if FType2.basetype = btClass then
+ begin
+{$ENDIF}
+ if not TPSClassType(FType2).Cl.CastToType(AT2UT(TypeNo), ProcNo) then
+ begin
+ temp.Free;
+ MakeError('', ecTypeMismatch, '');
+ Result := nil;
+ exit;
+ end;
+{$IFNDEF PS_NOINTERFACES}
+ end else begin
+ if not TPSInterfaceType(FType2).Intf.CastToType(AT2UT(TypeNo), ProcNo) then
+ begin
+ temp.Free;
+ MakeError('', ecTypeMismatch, '');
+ Result := nil;
+ exit;
+ end;
+ end;
+{$ENDIF}
+ Result := TPSValueProcNo.Create;
+ TPSValueProcNo(Result).Parameters := TPSParameters.Create;
+ TPSValueProcNo(Result).ResultType := at2ut(TypeNo);
+ TPSValueProcNo(Result).ProcNo := ProcNo;
+ with TPSValueProcNo(Result).Parameters.Add do
+ begin
+ Val := Temp;
+ ExpectedType := GetTypeNo(BlockInfo, temp);
+{$IFDEF DEBUG}
+ if not ExpectedType.Used then asm int 3; end;
+{$ENDIF}
+ end;
+ with TPSValueProcNo(Result).Parameters.Add do
+ begin
+ ExpectedType := at2ut(FindBaseType(btu32));
+{$IFDEF DEBUG}
+ if not ExpectedType.Used then asm int 3; end;
+{$ENDIF}
+ Val := TPSValueData.Create;
+ with TPSValueData(val) do
+ begin
+ SetParserPos(FParser);
+ Data := NewVariant(ExpectedType);
+ Data.tu32 := at2ut(TypeNo).FinalTypeNo;
+ end;
+ end;
+ FParser.Next;
+ Exit;
+ end;
+ if not IsCompatibleType(TypeNo, FType2, True) then
+ begin
+ temp.Free;
+ MakeError('', ecTypeMismatch, '');
+ Result := nil;
+ exit;
+ end;
+ FParser.Next;
+ Result := TPSUnValueOp.Create;
+ with TPSUnValueOp(Result) do
+ begin
+ Operator := otCast;
+ Val1 := Temp;
+ SetParserPos(FParser);
+ aType := AT2UT(TypeNo);
+ end;
+
+ exit;
+ end else
+ if FParser.CurrTokenId <> CSTI_Period then
+ begin
+ Result := TPSValueData.Create;
+ Result.SetParserPos(FParser);
+ New(dta);
+ TPSValueData(Result).Data := dta;
+ InitializeVariant(dta, at2ut(FindBaseType(btType)));
+ dta.ttype := at2ut(TypeNo);
+ Exit;
+ end;
+ if TypeNo.BaseType <> btClass then
+ begin
+ Result := nil;
+ MakeError('', ecClassTypeExpected, '');
+ Exit;
+ end;
+ FParser.Next;
+ if not TPSClassType(TypeNo).Cl.ClassFunc_Find(FParser.GetToken, Idx) then
+ begin
+ Result := nil;
+ MakeError('', ecUnknownIdentifier, FParser.OriginalToken);
+ Exit;
+ end;
+ FParser.Next;
+ TPSClassType(TypeNo).Cl.ClassFunc_Call(Idx, ProcNo);
+ Temp := TPSValueData.Create;
+ with TPSValueData(Temp) do
+ begin
+ Data := NewVariant(at2ut(FindBaseType(btu32)));
+ Data.tu32 := at2ut(TypeNo).FinalTypeNo;
+ end;
+ ResV := ReadProcParameters(ProcNo, Temp);
+ if ResV <> nil then
+ begin
+ TPSValueProc(Resv).ResultType := at2ut(TypeNo);
+ Result := Resv;
+ end else begin
+ Result := nil;
+ end;
+ end;
+
+ function GetIdentifier(const FType: Byte): TPSValue;
+ {
+ FType:
+ 0 = Anything
+ 1 = Only variables
+ 2 = Not constants
+ }
+
+
+ var
+ vt: TPSVariableType;
+ vno: Cardinal;
+ TWith, Temp: TPSValue;
+ l, h: Longint;
+ s, u: tbtString;
+ t: TPSConstant;
+ Temp1: TPSType;
+ temp2: CArdinal;
+ bi: TPSBlockInfo;
+ lOldRecCount: Integer;
+
+ begin
+ s := FParser.GetToken;
+
+ if FType <> 1 then
+ begin
+ bi := BlockInfo;
+ while bi <> nil do
+ begin
+ for l := bi.WithList.Count -1 downto 0 do
+ begin
+ TWith := TPSValueAllocatedStackVar.Create;
+ TPSValueAllocatedStackVar(TWith).LocalVarNo := TPSValueAllocatedStackVar(TPSValueReplace(bi.WithList[l]).NewValue).LocalVarNo;
+ Temp := TWith;
+ VNo := TPSValueAllocatedStackVar(Temp).LocalVarNo;
+ lOldRecCount := TPSValueVar(TWith).GetRecCount;
+ vt := ivtVariable;
+ if Temp = TWith then CheckFurther(TWith, True);
+ if Temp = TWith then CheckClass(TWith, vt, vno, True);
+ if Temp = TWith then CheckExtClass(TWith, vt, vno, True);
+ if (Temp <> TWith) or (Cardinal(lOldRecCount) <> TPSValueVar(TWith).GetRecCount) then
+ begin
+ repeat
+ Temp := TWith;
+ if TWith <> nil then CheckFurther(TWith, False);
+ if TWith <> nil then CheckClass(TWith, vt, vno, False);
+ if TWith <> nil then CheckExtClass(TWith, vt, vno, False);
+{$IFNDEF PS_NOIDISPATCH}if TWith <> nil then CheckIntf(TWith, vt, vno, False);{$ENDIF}
+ if TWith <> nil then CheckProcCall(TWith);
+ if TWith <> nil then CheckClassArrayProperty(TWith, vt, vno);
+ vno := InvalidVal;
+ until (TWith = nil) or (Temp = TWith);
+ Result := TWith;
+ Exit;
+ end;
+ TWith.Free;
+ end;
+ bi := bi.FOwner;
+ end;
+ end;
+
+ if s = 'RESULT' then
+ begin
+ if BlockInfo.proc.Decl.Result = nil then
+ begin
+ Result := nil;
+ MakeError('', ecUnknownIdentifier, FParser.OriginalToken);
+ end
+ else
+ begin
+ BlockInfo.Proc.ResultUse;
+ Result := TPSValueParamVar.Create;
+ with TPSValueParamVar(Result) do
+ begin
+ SetParserPos(FParser);
+ ParamNo := 0;
+ end;
+ vno := 0;
+ vt := ivtParam;
+ if @FOnUseVariable <> nil then
+ FOnUseVariable(Self, vt, vno, BlockInfo.ProcNo, FParser.CurrTokenPos, '');
+ FParser.Next;
+ repeat
+ Temp := Result;
+ if Result <> nil then CheckFurther(Result, False);
+ if Result <> nil then CheckClass(Result, vt, vno, False);
+ if Result <> nil then CheckExtClass(Result, vt, vno, False);
+{$IFNDEF PS_NOIDISPATCH}if Result <> nil then CheckIntf(Result, vt, vno, False);{$ENDIF}
+ if Result <> nil then CheckProcCall(Result);
+ if Result <> nil then CheckClassArrayProperty(Result, vt, vno);
+ vno := InvalidVal;
+ until (Result = nil) or (Temp = Result);
+ end;
+ exit;
+ end;
+ if BlockInfo.Proc.Decl.Result = nil then
+ l := 0
+ else
+ l := 1;
+ for h := 0 to BlockInfo.proc.Decl.ParamCount -1 do
+ begin
+ if BlockInfo.proc.Decl.Params[h].Name = s then
+ begin
+ Result := TPSValueParamVar.Create;
+ with TPSValueParamVar(Result) do
+ begin
+ SetParserPos(FParser);
+ ParamNo := l;
+ end;
+ vt := ivtParam;
+ vno := L;
+ if @FOnUseVariable <> nil then
+ FOnUseVariable(Self, vt, vno, BlockInfo.ProcNo, FParser.CurrTokenPos, '');
+ FParser.Next;
+ repeat
+ Temp := Result;
+ if Result <> nil then CheckFurther(Result, False);
+ if Result <> nil then CheckClass(Result, vt, vno, False);
+ if Result <> nil then CheckExtClass(Result, vt, vno, False);
+{$IFNDEF PS_NOIDISPATCH}if Result <> nil then CheckIntf(Result, vt, vno, False);{$ENDIF}
+ if Result <> nil then CheckProcCall(Result);
+ if Result <> nil then CheckClassArrayProperty(Result, vt, vno);
+ vno := InvalidVal;
+ until (Result = nil) or (Temp = Result);
+ exit;
+ end;
+ Inc(l);
+ GRFW(u);
+ end;
+
+ h := MakeHash(s);
+
+ for l := 0 to BlockInfo.Proc.ProcVars.Count - 1 do
+ begin
+ if (PIFPSProcVar(BlockInfo.Proc.ProcVars[l]).NameHash = h) and
+ (PIFPSProcVar(BlockInfo.Proc.ProcVars[l]).Name = s) then
+ begin
+ PIFPSProcVar(BlockInfo.Proc.ProcVars[l]).Use;
+ vno := l;
+ vt := ivtVariable;
+ if @FOnUseVariable <> nil then
+ FOnUseVariable(Self, vt, vno, BlockInfo.ProcNo, FParser.CurrTokenPos, '');
+ Result := TPSValueLocalVar.Create;
+ with TPSValueLocalVar(Result) do
+ begin
+ LocalVarNo := l;
+ SetParserPos(FParser);
+ end;
+ FParser.Next;
+ repeat
+ Temp := Result;
+ if Result <> nil then CheckFurther(Result, False);
+ if Result <> nil then CheckClass(Result, vt, vno, False);
+ if Result <> nil then CheckExtClass(Result, vt, vno, False);
+{$IFNDEF PS_NOIDISPATCH}if Result <> nil then CheckIntf(Result, vt, vno, False);{$ENDIF}
+ if Result <> nil then CheckProcCall(Result);
+ if Result <> nil then CheckClassArrayProperty(Result, vt, vno);
+ vno := InvalidVal;
+ until (Result = nil) or (Temp = Result);
+
+ exit;
+ end;
+ end;
+
+ for l := 0 to FVars.Count - 1 do
+ begin
+ if (TPSVar(FVars[l]).NameHash = h) and
+ (TPSVar(FVars[l]).Name = s) {$IFDEF PS_USESSUPPORT} and
+ (IsInLocalUnitList(TPSVar(FVars[l]).FDeclareUnit)){$ENDIF} then
+ begin
+ TPSVar(FVars[l]).Use;
+ Result := TPSValueGlobalVar.Create;
+ with TPSValueGlobalVar(Result) do
+ begin
+ SetParserPos(FParser);
+ GlobalVarNo := l;
+
+ end;
+ vt := ivtGlobal;
+ vno := l;
+ if @FOnUseVariable <> nil then
+ FOnUseVariable(Self, vt, vno, BlockInfo.ProcNo, FParser.CurrTokenPos, '');
+ FParser.Next;
+ repeat
+ Temp := Result;
+ if Result <> nil then CheckNotificationVariant(Result);
+ if Result <> nil then CheckFurther(Result, False);
+ if Result <> nil then CheckClass(Result, vt, vno, False);
+ if Result <> nil then CheckExtClass(Result, vt, vno, False);
+{$IFNDEF PS_NOIDISPATCH}if Result <> nil then CheckIntf(Result, vt, vno, False);{$ENDIF}
+ if Result <> nil then CheckProcCall(Result);
+ if Result <> nil then CheckClassArrayProperty(Result, vt, vno);
+ vno := InvalidVal;
+ until (Result = nil) or (Temp = Result);
+ exit;
+ end;
+ end;
+ Temp1 := FindType(FParser.GetToken);
+ if Temp1 <> nil then
+ begin
+ l := FParser.CurrTokenPos;
+ if FType = 1 then
+ begin
+ Result := nil;
+ MakeError('', ecVariableExpected, FParser.OriginalToken);
+ exit;
+ end;
+ vt := ivtGlobal;
+ vno := InvalidVal;
+ FParser.Next;
+ Result := CheckClassType(Temp1, l);
+ repeat
+ Temp := Result;
+ if Result <> nil then CheckFurther(Result, False);
+ if Result <> nil then CheckClass(Result, vt, vno, False);
+ if Result <> nil then CheckExtClass(Result, vt, vno, False);
+{$IFNDEF PS_NOIDISPATCH}if Result <> nil then CheckIntf(Result, vt, vno, False);{$ENDIF}
+ if Result <> nil then CheckProcCall(Result);
+ if Result <> nil then CheckClassArrayProperty(Result, vt, vno);
+ vno := InvalidVal;
+ until (Result = nil) or (Temp = Result);
+
+ exit;
+ end;
+ Temp2 := FindProc(FParser.GetToken);
+ if Temp2 <> InvalidVal then
+ begin
+ if FType = 1 then
+ begin
+ Result := nil;
+ MakeError('', ecVariableExpected, FParser.OriginalToken);
+ exit;
+ end;
+ FParser.Next;
+ Result := ReadProcParameters(Temp2, nil);
+ if Result = nil then
+ exit;
+ Result.SetParserPos(FParser);
+ vt := ivtGlobal;
+ vno := InvalidVal;
+ repeat
+ Temp := Result;
+ if Result <> nil then CheckFurther(Result, False);
+ if Result <> nil then CheckClass(Result, vt, vno, False);
+ if Result <> nil then CheckExtClass(Result, vt, vno, False);
+{$IFNDEF PS_NOIDISPATCH}if Result <> nil then CheckIntf(Result, vt, vno, False);{$ENDIF}
+ if Result <> nil then CheckProcCall(Result);
+ if Result <> nil then CheckClassArrayProperty(Result, vt, vno);
+ vno := InvalidVal;
+ until (Result = nil) or (Temp = Result);
+ exit;
+ end;
+ for l := 0 to FConstants.Count -1 do
+ begin
+ t := TPSConstant(FConstants[l]);
+ if (t.NameHash = h) and (t.Name = s) {$IFDEF PS_USESSUPPORT} and
+ (IsInLocalUnitList(t.FDeclareUnit)) {$ENDIF} then
+ begin
+ if FType <> 0 then
+ begin
+ Result := nil;
+ MakeError('', ecVariableExpected, FParser.OriginalToken);
+ exit;
+ end;
+ fparser.next;
+ Result := TPSValueData.Create;
+ with TPSValueData(Result) do
+ begin
+ SetParserPos(FParser);
+ Data := NewVariant(at2ut(t.Value.FType));
+ CopyVariantContents(t.Value, Data);
+ end;
+ vt := ivtGlobal;
+ vno := InvalidVal;
+ repeat
+ Temp := Result;
+ if Result <> nil then CheckFurther(Result, False);
+ if Result <> nil then CheckClass(Result, vt, vno, False);
+ if Result <> nil then CheckExtClass(Result, vt, vno, False);
+{$IFNDEF PS_NOIDISPATCH}if Result <> nil then CheckIntf(Result, vt, vno, False);{$ENDIF}
+ if Result <> nil then CheckProcCall(Result);
+ if Result <> nil then CheckClassArrayProperty(Result, vt, vno);
+ vno := InvalidVal;
+ until (Result = nil) or (Temp = Result);
+ exit;
+ end;
+ end;
+ Result := nil;
+ MakeError('', ecUnknownIdentifier, FParser.OriginalToken);
+ end;
+
+ function calc(endOn: TPSPasToken): TPSValue;
+ function TryEvalConst(var P: TPSValue): Boolean; forward;
+
+
+ function ReadExpression: TPSValue; forward;
+ function ReadTerm: TPSValue; forward;
+ function ReadFactor: TPSValue;
+ var
+ NewVar: TPSValue;
+ NewVarU: TPSUnValueOp;
+ Proc: TPSProcedure;
+ function ReadArray: Boolean;
+ var
+ tmp: TPSValue;
+ begin
+ FParser.Next;
+ NewVar := TPSValueArray.Create;
+ NewVar.SetParserPos(FParser);
+ if FParser.CurrTokenID <> CSTI_CloseBlock then
+ begin
+ while True do
+ begin
+ tmp := nil;
+ Tmp := ReadExpression();
+ if Tmp = nil then
+ begin
+ Result := False;
+ NewVar.Free;
+ exit;
+ end;
+ if not TryEvalConst(tmp) then
+ begin
+ tmp.Free;
+ NewVar.Free;
+ Result := False;
+ exit;
+ end;
+ TPSValueArray(NewVar).Add(tmp);
+ if FParser.CurrTokenID = CSTI_CloseBlock then Break;
+ if FParser.CurrTokenID <> CSTI_Comma then
+ begin
+ MakeError('', ecCloseBlockExpected, '');
+ NewVar.Free;
+ Result := False;
+ exit;
+ end;
+ FParser.Next;
+ end;
+ end;
+ FParser.Next;
+ Result := True;
+ end;
+
+ function CallAssigned(P: TPSValue): TPSValue;
+ var
+ temp: TPSValueProcNo;
+ begin
+ temp := TPSValueProcNo.Create;
+ temp.ProcNo := FindProc('!ASSIGNED');
+ temp.ResultType := at2ut(FDefaultBoolType);
+ temp.Parameters := TPSParameters.Create;
+ with Temp.Parameters.Add do
+ begin
+ Val := p;
+ ExpectedType := GetTypeNo(BlockInfo, p);
+{$IFDEF DEBUG}
+ if not ExpectedType.Used then asm int 3; end;
+{$ENDIF}
+ FParamMode := pmIn;
+ end;
+ Result := Temp;
+ end;
+
+ function CallSucc(P: TPSValue): TPSValue;
+ var
+ temp: TPSBinValueOp;
+ begin
+ temp := TPSBinValueOp.Create;
+ temp.SetParserPos(FParser);
+ temp.FOperator := otAdd;
+ temp.FVal2 := TPSValueData.Create;
+ TPSValueData(Temp.FVal2).Data := NewVariant(FindBaseType(bts32));
+ TPSValueData(Temp.FVal2).Data.ts32 := 1;
+ temp.FVal1 := p;
+ Temp.FType := GetTypeNo(BlockInfo, P);
+ result := temp;
+ end;
+
+ function CallPred(P: TPSValue): TPSValue;
+ var
+ temp: TPSBinValueOp;
+ begin
+ temp := TPSBinValueOp.Create;
+ temp.SetParserPos(FParser);
+ temp.FOperator := otSub;
+ temp.FVal2 := TPSValueData.Create;
+ TPSValueData(Temp.FVal2).Data := NewVariant(FindBaseType(bts32));
+ TPSValueData(Temp.FVal2).Data.ts32 := 1;
+ temp.FVal1 := p;
+ Temp.FType := GetTypeNo(BlockInfo, P);
+ result := temp;
+ end;
+
+ begin
+ case fParser.CurrTokenID of
+ CSTI_OpenBlock:
+ begin
+ if not ReadArray then
+ begin
+ Result := nil;
+ exit;
+ end;
+ end;
+ CSTII_Not:
+ begin
+ FParser.Next;
+ NewVar := ReadFactor;
+ if NewVar = nil then
+ begin
+ Result := nil;
+ exit;
+ end;
+ NewVarU := TPSUnValueOp.Create;
+ NewVarU.SetParserPos(FParser);
+ NewVarU.aType := GetTypeNo(BlockInfo, NewVar);
+ NewVarU.Operator := otNot;
+ NewVarU.Val1 := NewVar;
+ NewVar := NewVarU;
+ end;
+ CSTI_Plus:
+ begin
+ FParser.Next;
+ NewVar := ReadTerm;
+ if NewVar = nil then
+ begin
+ Result := nil;
+ exit;
+ end;
+ end;
+ CSTI_Minus:
+ begin
+ FParser.Next;
+ NewVar := ReadTerm;
+ if NewVar = nil then
+ begin
+ Result := nil;
+ exit;
+ end;
+ NewVarU := TPSUnValueOp.Create;
+ NewVarU.SetParserPos(FParser);
+ NewVarU.aType := GetTypeNo(BlockInfo, NewVar);
+ NewVarU.Operator := otMinus;
+ NewVarU.Val1 := NewVar;
+ NewVar := NewVarU;
+ end;
+ CSTII_Nil:
+ begin
+ FParser.Next;
+ NewVar := TPSValueNil.Create;
+ NewVar.SetParserPos(FParser);
+ end;
+ CSTI_AddressOf:
+ begin
+ FParser.Next;
+ if FParser.CurrTokenID <> CSTI_Identifier then
+ begin
+ MakeError('', ecIdentifierExpected, '');
+ Result := nil;
+ exit;
+ end;
+ NewVar := TPSValueProcPtr.Create;
+ NewVar.SetParserPos(FParser);
+ TPSValueProcPtr(NewVar).ProcPtr := FindProc(FParser.GetToken);
+ if TPSValueProcPtr(NewVar).ProcPtr = InvalidVal then
+ begin
+ MakeError('', ecUnknownIdentifier, FParser.OriginalToken);
+ NewVar.Free;
+ Result := nil;
+ exit;
+ end;
+ Proc := FProcs[TPSValueProcPtr(NewVar).ProcPtr];
+ if Proc.ClassType <> TPSInternalProcedure then
+ begin
+ MakeError('', ecUnknownIdentifier, FParser.OriginalToken);
+ NewVar.Free;
+ Result := nil;
+ exit;
+ end;
+ FParser.Next;
+ end;
+ CSTI_OpenRound:
+ begin
+ FParser.Next;
+ NewVar := ReadExpression();
+ if NewVar = nil then
+ begin
+ Result := nil;
+ exit;
+ end;
+ if FParser.CurrTokenId <> CSTI_CloseRound then
+ begin
+ NewVar.Free;
+ Result := nil;
+ MakeError('', ecCloseRoundExpected, '');
+ exit;
+ end;
+ FParser.Next;
+ end;
+ CSTI_Char, CSTI_String:
+ begin
+ NewVar := TPSValueData.Create;
+ NewVar.SetParserPos(FParser);
+ TPSValueData(NewVar).Data := ReadString;
+ if TPSValueData(NewVar).Data = nil then
+ begin
+ NewVar.Free;
+ Result := nil;
+ exit;
+ end;
+ end;
+ CSTI_HexInt, CSTI_Integer:
+ begin
+ NewVar := TPSValueData.Create;
+ NewVar.SetParserPos(FParser);
+ TPSValueData(NewVar).Data := ReadInteger(FParser.GetToken);
+ FParser.Next;
+ end;
+ CSTI_Real:
+ begin
+ NewVar := TPSValueData.Create;
+ NewVar.SetParserPos(FParser);
+ TPSValueData(NewVar).Data := ReadReal(FParser.GetToken);
+ FParser.Next;
+ end;
+ CSTII_Ord:
+ begin
+ FParser.Next;
+ if fParser.Currtokenid <> CSTI_OpenRound then
+ begin
+ Result := nil;
+ MakeError('', ecOpenRoundExpected, '');
+ exit;
+ end;
+ FParser.Next;
+ NewVar := ReadExpression();
+ if NewVar = nil then
+ begin
+ Result := nil;
+ exit;
+ end;
+ if FParser.CurrTokenId <> CSTI_CloseRound then
+ begin
+ NewVar.Free;
+ Result := nil;
+ MakeError('', ecCloseRoundExpected, '');
+ exit;
+ end;
+ if not ((GetTypeNo(BlockInfo, NewVar).BaseType = btChar) or
+ {$IFNDEF PS_NOWIDESTRING} (GetTypeNo(BlockInfo, NewVar).BaseType = btWideChar) or{$ENDIF}
+ (GetTypeNo(BlockInfo, NewVar).BaseType = btEnum) or (IsIntType(GetTypeNo(BlockInfo, NewVar).BaseType))) then
+ begin
+ NewVar.Free;
+ Result := nil;
+ MakeError('', ecTypeMismatch, '');
+ exit;
+ end;
+ NewVarU := TPSUnValueOp.Create;
+ NewVarU.SetParserPos(FParser);
+ NewVarU.Operator := otCast;
+ NewVarU.FType := at2ut(FindBaseType(btu32));
+ NewVarU.Val1 := NewVar;
+ NewVar := NewVarU;
+ FParser.Next;
+ end;
+ CSTII_Chr:
+ begin
+ FParser.Next;
+ if fParser.Currtokenid <> CSTI_OpenRound then
+ begin
+ Result := nil;
+ MakeError('', ecOpenRoundExpected, '');
+ exit;
+ end;
+ FParser.Next;
+ NewVar := ReadExpression();
+ if NewVar = nil then
+ begin
+ Result := nil;
+ exit;
+ end;
+ if FParser.CurrTokenId <> CSTI_CloseRound then
+ begin
+ NewVar.Free;
+ Result := nil;
+ MakeError('', ecCloseRoundExpected, '');
+ exit;
+ end;
+ if not (IsIntType(GetTypeNo(BlockInfo, NewVar).BaseType)) then
+ begin
+ NewVar.Free;
+ Result := nil;
+ MakeError('', ecTypeMismatch, '');
+ exit;
+ end;
+ NewVarU := TPSUnValueOp.Create;
+ NewVarU.SetParserPos(FParser);
+ NewVarU.Operator := otCast;
+ NewVarU.FType := at2ut(FindBaseType(btChar));
+ NewVarU.Val1 := NewVar;
+ NewVar := NewVarU;
+ FParser.Next;
+ end;
+ CSTI_Identifier:
+ begin
+ if FParser.GetToken = 'SUCC' then
+ begin
+ FParser.Next;
+ if FParser.CurrTokenID <> CSTI_OpenRound then
+ begin
+ Result := nil;
+ MakeError('', ecOpenRoundExpected, '');
+ exit;
+ end;
+ FParser.Next;
+ NewVar := ReadExpression;
+ if NewVar = nil then
+ begin
+ result := nil;
+ exit;
+ end;
+ if (GetTypeNo(BlockInfo, NewVar) = nil) or (not IsIntType(GetTypeNo(BlockInfo, NewVar).BaseType) and
+ (GetTypeNo(BlockInfo, NewVar).BaseType <> btEnum)) then
+ begin
+ NewVar.Free;
+ Result := nil;
+ MakeError('', ecTypeMismatch, '');
+ exit;
+ end;
+ if FParser.CurrTokenID <> CSTI_CloseRound then
+ begin
+ NewVar.Free;
+ Result := nil;
+ MakeError('', eccloseRoundExpected, '');
+ exit;
+ end;
+ NewVar := CallSucc(NewVar);
+ FParser.Next;
+ end else
+ if FParser.GetToken = 'PRED' then
+ begin
+ FParser.Next;
+ if FParser.CurrTokenID <> CSTI_OpenRound then
+ begin
+ Result := nil;
+ MakeError('', ecOpenRoundExpected, '');
+ exit;
+ end;
+ FParser.Next;
+ NewVar := ReadExpression;
+ if NewVar = nil then
+ begin
+ result := nil;
+ exit;
+ end;
+ if (GetTypeNo(BlockInfo, NewVar) = nil) or (not IsIntType(GetTypeNo(BlockInfo, NewVar).BaseType) and
+ (GetTypeNo(BlockInfo, NewVar).BaseType <> btEnum)) then
+ begin
+ NewVar.Free;
+ Result := nil;
+ MakeError('', ecTypeMismatch, '');
+ exit;
+ end;
+ if FParser.CurrTokenID <> CSTI_CloseRound then
+ begin
+ NewVar.Free;
+ Result := nil;
+ MakeError('', eccloseRoundExpected, '');
+ exit;
+ end;
+ NewVar := CallPred(NewVar);
+ FParser.Next;
+ end else
+ if FParser.GetToken = 'ASSIGNED' then
+ begin
+ FParser.Next;
+ if FParser.CurrTokenID <> CSTI_OpenRound then
+ begin
+ Result := nil;
+ MakeError('', ecOpenRoundExpected, '');
+ exit;
+ end;
+ FParser.Next;
+ NewVar := GetIdentifier(0);
+ if NewVar = nil then
+ begin
+ result := nil;
+ exit;
+ end;
+ if (GetTypeNo(BlockInfo, NewVar) = nil) or ((GetTypeNo(BlockInfo, NewVar).BaseType <> btClass) and
+ (GetTypeNo(BlockInfo, NewVar).BaseType <> btPChar) and
+ (GetTypeNo(BlockInfo, NewVar).BaseType <> btString)) then
+ begin
+ NewVar.Free;
+ Result := nil;
+ MakeError('', ecTypeMismatch, '');
+ exit;
+ end;
+ if FParser.CurrTokenID <> CSTI_CloseRound then
+ begin
+ NewVar.Free;
+ Result := nil;
+ MakeError('', eccloseRoundExpected, '');
+ exit;
+ end;
+ NewVar := CallAssigned(NewVar);
+ FParser.Next;
+ end else
+ begin
+ NewVar := GetIdentifier(0);
+ if NewVar = nil then
+ begin
+ Result := nil;
+ exit;
+ end;
+ end;
+ end;
+ else
+ begin
+ MakeError('', ecSyntaxError, '');
+ Result := nil;
+ exit;
+ end;
+ end; {case}
+ Result := NewVar;
+ end; // ReadFactor
+
+ function GetResultType(p1, P2: TPSValue; Cmd: TPSBinOperatorType): TPSType;
+ var
+ pp, t1, t2: PIFPSType;
+ begin
+ t1 := GetTypeNo(BlockInfo, p1);
+ t2 := GetTypeNo(BlockInfo, P2);
+ if (t1 = nil) or (t2 = nil) then
+ begin
+ if ((p1.ClassType = TPSValueNil) or (p2.ClassType = TPSValueNil)) and ((t1 <> nil) or (t2 <> nil)) then
+ begin
+ if p1.ClassType = TPSValueNil then
+ pp := t2
+ else
+ pp := t1;
+ if (pp.BaseType = btPchar) or (pp.BaseType = btString) or (pp.BaseType = btClass) {$IFNDEF PS_NOINTERFACES}or (pp.BaseType =btInterface){$ENDIF} or (pp.BaseType = btProcPtr) then
+ Result := AT2UT(FDefaultBoolType)
+ else
+ Result := nil;
+ exit;
+ end;
+ Result := nil;
+ exit;
+ end;
+ case Cmd of
+ otAdd: {plus}
+ begin
+ if ((t1.BaseType = btVariant) or (t1.BaseType = btNotificationVariant)) and (
+ ((t2.BaseType = btVariant) or (t2.BaseType = btNotificationVariant)) or
+ (t2.BaseType = btString) or
+ {$IFNDEF PS_NOWIDESTRING}
+ (t2.BaseType = btwideString) or
+ (t2.BaseType = btUnicodestring) or
+ (t2.BaseType = btwidechar) or
+ {$ENDIF}
+ (t2.BaseType = btPchar) or
+ (t2.BaseType = btChar) or
+ (isIntRealType(t2.BaseType))) then
+ Result := t1
+ else
+ if ((t2.BaseType = btVariant) or (t2.BaseType = btNotificationVariant)) and (
+ ((t1.BaseType = btVariant) or (t1.BaseType = btNotificationVariant)) or
+ (t1.BaseType = btString) or
+ {$IFNDEF PS_NOWIDESTRING}
+ (t1.BaseType = btUnicodestring) or
+ (t1.BaseType = btwideString) or
+ (t1.BaseType = btwidechar) or
+ {$ENDIF}
+ (t1.BaseType = btPchar) or
+ (t1.BaseType = btChar) or
+ (isIntRealType(t1.BaseType))) then
+ Result := t2
+ else if ((t1.BaseType = btSet) and (t2.BaseType = btSet)) and (t1 = t2) then
+ Result := t1
+ else if IsIntType(t1.BaseType) and IsIntType(t2.BaseType) then
+ Result := t1
+ else if IsIntRealType(t1.BaseType) and
+ IsIntRealType(t2.BaseType) then
+ begin
+ if IsRealType(t1.BaseType) then
+ Result := t1
+ else
+ Result := t2;
+ end
+ else if (t1.basetype = btSet) and (t2.Name = 'TVARIANTARRAY') then
+ Result := t1
+ else if (t2.basetype = btSet) and (t1.Name = 'TVARIANTARRAY') then
+ Result := t2
+ else if ((t1.BaseType = btPchar) or(t1.BaseType = btString) or (t1.BaseType = btChar)) and ((t2.BaseType = btPchar) or(t2.BaseType = btString) or (t2.BaseType = btChar)) then
+ Result := at2ut(FindBaseType(btString))
+ {$IFNDEF PS_NOWIDESTRING}
+ else if ((t1.BaseType = btString) or (t1.BaseType = btChar) or (t1.BaseType = btPchar)or (t1.BaseType = btWideString) or (t1.BaseType = btWideChar) or (t1.BaseType = btUnicodeString)) and
+ ((t2.BaseType = btString) or (t2.BaseType = btChar) or (t2.BaseType = btPchar) or (t2.BaseType = btWideString) or (t2.BaseType = btWideChar) or (t2.BaseType = btUnicodeString)) then
+ Result := at2ut(FindBaseType(btWideString))
+ {$ENDIF}
+ else
+ Result := nil;
+ end;
+
+ otSub, otMul, otIntDiv, otDiv: { - * / }
+ begin
+ if ((t1.BaseType = btVariant) or (t1.BaseType = btNotificationVariant)) and (
+ ((t2.BaseType = btVariant) or (t2.BaseType = btNotificationVariant)) or
+ (isIntRealType(t2.BaseType))) then
+ Result := t1
+ else if ((t1.BaseType = btSet) and (t2.BaseType = btSet)) and (t1 = t2) and ((cmd = otSub) or (cmd = otMul)) then
+ Result := t1
+ else if (t1.basetype = btSet) and (t2.Name = 'TVARIANTARRAY') and ((cmd = otSub) or (cmd = otMul)) then
+ Result := t1
+ else if (t2.basetype = btSet) and (t1.Name = 'TVARIANTARRAY') and ((cmd = otSub) or (cmd = otMul)) then
+ Result := t2
+ else
+ if ((t2.BaseType = btVariant) or (t2.BaseType = btNotificationVariant)) and (
+ ((t1.BaseType = btVariant) or (t1.BaseType = btNotificationVariant)) or
+ (isIntRealType(t1.BaseType))) then
+ Result := t2
+ else if IsIntType(t1.BaseType) and IsIntType(t2.BaseType) then begin
+ Result := t1;
+{$IFDEF PS_DELPHIDIV}
+ if Cmd = otDiv then
+ result := FindBaseType(btExtended);
+{$ENDIF}
+ end else if IsIntRealType(t1.BaseType) and
+ IsIntRealType(t2.BaseType) then
+ begin
+ if IsRealType(t1.BaseType) then
+ Result := t1
+ else
+ Result := t2;
+{$IFDEF PS_DELPHIDIV}
+ if Cmd = otIntDiv then //intdiv only works
+ result := nil;
+{$ENDIF}
+ end
+ else
+ Result := nil;
+ end;
+ otAnd, otOr, otXor: {and,or,xor}
+ begin
+ if ((t1.BaseType = btVariant) or (t1.BaseType = btNotificationVariant)) and (
+ ((t2.BaseType = btVariant) or (t2.BaseType = btNotificationVariant)) or
+ (isIntType(t2.BaseType))) then
+ Result := t1
+ else
+ if ((t2.BaseType = btVariant) or (t2.BaseType = btNotificationVariant)) and (
+ ((t1.BaseType = btVariant) or (t1.BaseType = btNotificationVariant)) or
+ (isIntType(t1.BaseType))) then
+ Result := t2
+ else if IsIntType(t1.BaseType) and IsIntType(t2.BaseType) then
+ Result := t1
+ else if (IsBoolean(t1)) and ((t2 = t1) or ((t2.BaseType = btVariant)
+ or (t2.BaseType = btNotificationVariant))) then
+ begin
+ Result := t1;
+ if ((p1.ClassType = TPSValueData) or (p2.ClassType = TPSValueData)) then
+ begin
+ if cmd = otAnd then {and}
+ begin
+ if p1.ClassType = TPSValueData then
+ begin
+ if (TPSValueData(p1).FData^.tu8 <> 0) then
+ begin
+ with MakeWarning('', ewIsNotNeeded, '"True and"') do
+ begin
+ FRow := p1.Row;
+ FCol := p1.Col;
+ FPosition := p1.Pos;
+ end;
+ end else
+ begin
+ with MakeWarning('', ewCalculationAlwaysEvaluatesTo, 'False') do
+ begin
+ FRow := p1.Row;
+ FCol := p1.Col;
+ FPosition := p1.Pos;
+ end;
+ end;
+ end else begin
+ if (TPSValueData(p2).Data.tu8 <> 0) then
+ begin
+ with MakeWarning('', ewIsNotNeeded, '"and True"') do
+ begin
+ FRow := p1.Row;
+ FCol := p1.Col;
+ FPosition := p1.Pos;
+ end;
+ end
+ else
+ begin
+ with MakeWarning('', ewCalculationAlwaysEvaluatesTo, 'False') do
+ begin
+ FRow := p1.Row;
+ FCol := p1.Col;
+ FPosition := p1.Pos;
+ end;
+ end;
+ end;
+ end else if cmd = otOr then {or}
+ begin
+ if p1.ClassType = TPSValueData then
+ begin
+ if (TPSValueData(p1).Data.tu8 <> 0) then
+ begin
+ with MakeWarning('', ewCalculationAlwaysEvaluatesTo, 'True') do
+ begin
+ FRow := p1.Row;
+ FCol := p1.Col;
+ FPosition := p1.Pos;
+ end;
+ end
+ else
+ begin
+ with MakeWarning('', ewIsNotNeeded, '"False or"') do
+ begin
+ FRow := p1.Row;
+ FCol := p1.Col;
+ FPosition := p1.Pos;
+ end;
+ end
+ end else begin
+ if (TPSValueData(p2).Data.tu8 <> 0) then
+ begin
+ with MakeWarning('', ewCalculationAlwaysEvaluatesTo, 'True') do
+ begin
+ FRow := p1.Row;
+ FCol := p1.Col;
+ FPosition := p1.Pos;
+ end;
+ end
+ else
+ begin
+ with MakeWarning('', ewIsNotNeeded, '"or False"') do
+ begin
+ FRow := p1.Row;
+ FCol := p1.Col;
+ FPosition := p1.Pos;
+ end;
+ end
+ end;
+ end;
+ end;
+ end else
+ Result := nil;
+ end;
+ otMod, otShl, otShr: {mod,shl,shr}
+ begin
+ if ((t1.BaseType = btVariant) or (t1.BaseType = btNotificationVariant)) and (
+ ((t2.BaseType = btVariant) or (t2.BaseType = btNotificationVariant)) or
+ (isIntType(t2.BaseType))) then
+ Result := t1
+ else
+ if ((t2.BaseType = btVariant) or (t2.BaseType = btNotificationVariant)) and (
+ ((t1.BaseType = btVariant) or (t1.BaseType = btNotificationVariant)) or
+ (isIntType(t1.BaseType))) then
+ Result := t2
+ else if IsIntType(t1.BaseType) and IsIntType(t2.BaseType) then
+ Result := t1
+ else
+ Result := nil;
+ end;
+ otGreater, otLess, otGreaterEqual, otLessEqual: { >=, <=, >, <}
+ begin
+ if ((t1.BaseType = btVariant) or (t1.BaseType = btNotificationVariant)) and (
+ ((t2.BaseType = btVariant) or (t2.BaseType = btNotificationVariant)) or
+ (t2.BaseType = btString) or
+ (t2.BaseType = btPchar) or
+ (t2.BaseType = btChar) or
+ (isIntRealType(t2.BaseType))) then
+ Result := FDefaultBoolType
+ else if ((t1.BaseType = btSet) and (t2.BaseType = btSet)) and (t1 = t2) and ((cmd = otGreaterEqual) or (cmd = otLessEqual)) then
+ Result := FDefaultBoolType
+ else
+ if ((t2.BaseType = btVariant) or (t2.BaseType = btNotificationVariant)) and (
+ ((t1.BaseType = btVariant) or (t1.BaseType = btNotificationVariant)) or
+ (t1.BaseType = btString) or
+ (t1.BaseType = btPchar) or
+ (t1.BaseType = btChar) or
+ (isIntRealType(t1.BaseType))) then
+ Result := FDefaultBoolType
+ else if IsIntType(t1.BaseType) and IsIntType(t2.BaseType) then
+ Result := FDefaultBoolType
+ else if IsIntRealType(t1.BaseType) and
+ IsIntRealType(t2.BaseType) then
+ Result := FDefaultBoolType
+ else if
+ ((t1.BaseType = btString) or (t1.BaseType = btChar) {$IFNDEF PS_NOWIDESTRING} or (t1.BaseType = btWideString) or (t1.BaseType = btWideChar) or (t1.BaseType = btUnicodestring){$ENDIF}) and
+ ((t2.BaseType = btString) or (t2.BaseType = btChar) {$IFNDEF PS_NOWIDESTRING} or (t2.BaseType = btWideString) or (t2.BaseType = btWideChar) or (t2.BaseType = btUnicodestring){$ENDIF}) then
+ Result := FDefaultBoolType
+ else if ((t1.BaseType = btVariant) or (t1.BaseType = btNotificationVariant)) or ((t2.BaseType = btVariant) or (t2.BaseType = btNotificationVariant)) then
+ Result := FDefaultBoolType
+ else
+ Result := nil;
+ end;
+ otEqual, otNotEqual: {=, <>}
+ begin
+ if ((t1.BaseType = btVariant) or (t1.BaseType = btNotificationVariant)) and (
+ ((t2.BaseType = btVariant) or (t2.BaseType = btNotificationVariant)) or
+ (t2.BaseType = btString) or
+ (t2.BaseType = btPchar) or
+ (t2.BaseType = btChar) or
+ (isIntRealType(t2.BaseType))) then
+ Result := FDefaultBoolType
+ else if ((t1.BaseType = btSet) and (t2.BaseType = btSet)) and (t1 = t2) then
+ Result := FDefaultBoolType
+ else
+ if ((t2.BaseType = btVariant) or (t2.BaseType = btNotificationVariant)) and (
+ ((t1.BaseType = btVariant) or (t1.BaseType = btNotificationVariant)) or
+ (t1.BaseType = btString) or
+ (t1.BaseType = btPchar) or
+ (t1.BaseType = btChar) or
+ (isIntRealType(t1.BaseType))) then
+ Result := FDefaultBoolType
+ else if IsIntType(t1.BaseType) and IsIntType(t2.BaseType) then
+ Result := FDefaultBoolType
+ else if IsIntRealType(t1.BaseType) and
+ IsIntRealType(t2.BaseType) then
+ Result := FDefaultBoolType
+ else if
+ ((t1.BaseType = btString) or (t1.BaseType = btChar) {$IFNDEF PS_NOWIDESTRING} or (t1.BaseType = btWideString) or (t1.BaseType = btWideChar) or (t1.BaseType = btUnicodestring){$ENDIF}) and
+ ((t2.BaseType = btString) or (t2.BaseType = btChar) {$IFNDEF PS_NOWIDESTRING} or (t2.BaseType = btWideString) or (t2.BaseType = btWideChar) or (t2.BaseType = btUnicodestring){$ENDIF}) then
+ Result := FDefaultBoolType
+ else if (t1.basetype = btSet) and (t2.Name = 'TVARIANTARRAY') then
+ Result := FDefaultBoolType
+ else if (t2.basetype = btSet) and (t1.Name = 'TVARIANTARRAY') then
+ Result := FDefaultBoolType
+ else if (t1.BaseType = btEnum) and (t1 = t2) then
+ Result := FDefaultBoolType
+ else if (t1.BaseType = btClass) and (t2.BaseType = btClass) then
+ Result := FDefaultBoolType
+ else if (t1 = t2) then
+ Result := FDefaultBoolType
+ else if ((t1.BaseType = btVariant) or (t1.BaseType = btNotificationVariant)) or ((t2.BaseType = btVariant) or (t2.BaseType = btNotificationVariant)) then
+ Result := FDefaultBoolType
+ else Result := nil;
+ end;
+ otIn:
+ begin
+ if (t2.Name = 'TVARIANTARRAY') then
+ Result := FDefaultBoolType
+ else
+ if (t2.BaseType = btSet) and (TPSSetType(t2).SetType = t1) then
+ Result := FDefaultBoolType
+ else
+ Result := nil;
+ end;
+ otIs:
+ begin
+ if t2.BaseType = btType then
+ begin
+ Result := FDefaultBoolType
+ end else
+ Result := nil;
+ end;
+ otAs:
+ begin
+ if t2.BaseType = btType then
+ begin
+ Result := at2ut(TPSValueData(p2).Data.ttype);
+ end else
+ Result := nil;
+ end;
+ else
+ Result := nil;
+ end;
+ end;
+
+
+ function ReadTerm: TPSValue;
+ var
+ F1, F2: TPSValue;
+ fType: TPSType;
+ F: TPSBinValueOp;
+ Token: TPSPasToken;
+ Op: TPSBinOperatorType;
+ begin
+ F1 := ReadFactor;
+ if F1 = nil then
+ begin
+ Result := nil;
+ exit;
+ end;
+ while FParser.CurrTokenID in [CSTI_Multiply, CSTI_Divide, CSTII_Div, CSTII_Mod, CSTII_And, CSTII_Shl, CSTII_Shr, CSTII_As] do
+ begin
+ Token := FParser.CurrTokenID;
+ FParser.Next;
+ F2 := ReadFactor;
+ if f2 = nil then
+ begin
+ f1.Free;
+ Result := nil;
+ exit;
+ end;
+ case Token of
+ CSTI_Multiply: Op := otMul;
+ CSTI_Divide: Op := otDiv;
+ CSTII_div: Op := otIntDiv;
+ CSTII_mod: Op := otMod;
+ CSTII_and: Op := otAnd;
+ CSTII_shl: Op := otShl;
+ CSTII_shr: Op := otShr;
+ CSTII_As: Op := otAs;
+ else
+ Op := otAdd;
+ end;
+ if (Op = otAs) and (f2 is TPSValueData) and (TPSValueData(f2).Data.FType.BaseType = btType) then begin
+ fType := TPSValueData(f2).Data.ttype;
+ f2.Free;
+ f2 := TPSUnValueOp.Create;
+ TPSUnValueOp(F2).Val1 := f1;
+ TPSUnValueOp(F2).SetParserPos(FParser);
+ TPSUnValueOp(f2).FType := fType;
+ TPSUnValueOp(f2).Operator := otCast;
+ f1 := f2;
+ end else begin
+ F := TPSBinValueOp.Create;
+ f.Val1 := F1;
+ f.Val2 := F2;
+ f.Operator := Op;
+ f.aType := GetResultType(F1, F2, Op);
+ if f.aType = nil then
+ begin
+ MakeError('', ecTypeMismatch, '');
+ f.Free;
+ Result := nil;
+ exit;
+ end;
+ f1 := f;
+ end;
+ end;
+ Result := F1;
+ end; // ReadTerm
+
+ function ReadSimpleExpression: TPSValue;
+ var
+ F1, F2: TPSValue;
+ F: TPSBinValueOp;
+ Token: TPSPasToken;
+ Op: TPSBinOperatorType;
+ begin
+ F1 := ReadTerm;
+ if F1 = nil then
+ begin
+ Result := nil;
+ exit;
+ end;
+ while FParser.CurrTokenID in [CSTI_Plus, CSTI_Minus, CSTII_Or, CSTII_Xor] do
+ begin
+ Token := FParser.CurrTokenID;
+ FParser.Next;
+ F2 := ReadTerm;
+ if f2 = nil then
+ begin
+ f1.Free;
+ Result := nil;
+ exit;
+ end;
+ case Token of
+ CSTI_Plus: Op := otAdd;
+ CSTI_Minus: Op := otSub;
+ CSTII_or: Op := otOr;
+ CSTII_xor: Op := otXor;
+ else
+ Op := otAdd;
+ end;
+ F := TPSBinValueOp.Create;
+ f.Val1 := F1;
+ f.Val2 := F2;
+ f.Operator := Op;
+ f.aType := GetResultType(F1, F2, Op);
+ if f.aType = nil then
+ begin
+ MakeError('', ecTypeMismatch, '');
+ f.Free;
+ Result := nil;
+ exit;
+ end;
+ f1 := f;
+ end;
+ Result := F1;
+ end; // ReadSimpleExpression
+
+
+ function ReadExpression: TPSValue;
+ var
+ F1, F2: TPSValue;
+ F: TPSBinValueOp;
+ Token: TPSPasToken;
+ Op: TPSBinOperatorType;
+ begin
+ F1 := ReadSimpleExpression;
+ if F1 = nil then
+ begin
+ Result := nil;
+ exit;
+ end;
+ while FParser.CurrTokenID in [ CSTI_GreaterEqual, CSTI_LessEqual, CSTI_Greater, CSTI_Less, CSTI_Equal, CSTI_NotEqual, CSTII_in, CSTII_is] do
+ begin
+ Token := FParser.CurrTokenID;
+ FParser.Next;
+ F2 := ReadSimpleExpression;
+ if f2 = nil then
+ begin
+ f1.Free;
+ Result := nil;
+ exit;
+ end;
+ case Token of
+ CSTI_GreaterEqual: Op := otGreaterEqual;
+ CSTI_LessEqual: Op := otLessEqual;
+ CSTI_Greater: Op := otGreater;
+ CSTI_Less: Op := otLess;
+ CSTI_Equal: Op := otEqual;
+ CSTI_NotEqual: Op := otNotEqual;
+ CSTII_in: Op := otIn;
+ CSTII_is: Op := otIs;
+ else
+ Op := otAdd;
+ end;
+ F := TPSBinValueOp.Create;
+ f.Val1 := F1;
+ f.Val2 := F2;
+ f.Operator := Op;
+ f.aType := GetResultType(F1, F2, Op);
+ if f.aType = nil then
+ begin
+ MakeError('', ecTypeMismatch, '');
+ f.Free;
+ Result := nil;
+ exit;
+ end;
+ f1 := f;
+ end;
+ Result := F1;
+ end; // ReadExpression
+
+ function TryEvalConst(var P: TPSValue): Boolean;
+ var
+ preplace: TPSValue;
+ begin
+ if p is TPSBinValueOp then
+ begin
+ if not (TryEvalConst(TPSBinValueOp(p).FVal1) and TryEvalConst(TPSBinValueOp(p).FVal2)) then
+ begin
+ Result := False;
+ exit;
+ end;
+ if (TPSBinValueOp(p).FVal1.ClassType = TPSValueData) and (TPSBinValueOp(p).FVal2.ClassType = TPSValueData) then
+ begin
+ if not PreCalc(True, 0, TPSValueData(TPSBinValueOp(p).Val1).Data, 0, TPSValueData(TPSBinValueOp(p).Val2).Data, TPSBinValueOp(p).Operator, p.Pos, p.Row, p.Col) then
+ begin
+ Result := False;
+ exit;
+ end;
+ preplace := TPSValueData.Create;
+ preplace.Pos := p.Pos;
+ preplace.Row := p.Row;
+ preplace.Col := p.Col;
+ TPSValueData(preplace).Data := TPSValueData(TPSBinValueOp(p).Val1).Data;
+ TPSValueData(TPSBinValueOp(p).Val1).Data := nil;
+ p.Free;
+ p := preplace;
+ end;
+ end else if p is TPSUnValueOp then
+ begin
+ if not TryEvalConst(TPSUnValueOp(p).FVal1) then
+ begin
+ Result := False;
+ exit;
+ end;
+ if TPSUnValueOp(p).FVal1.ClassType = TPSValueData then
+ begin
+//
+ case TPSUnValueOp(p).Operator of
+ otNot:
+ begin
+ case TPSValueData(TPSUnValueOp(p).FVal1).Data^.FType.BaseType of
+ btEnum:
+ begin
+ if IsBoolean(TPSValueData(TPSUnValueOp(p).FVal1).Data^.FType) then
+ begin
+ TPSValueData(TPSUnValueOp(p).FVal1).Data^.tu8 := (not TPSValueData(TPSUnValueOp(p).FVal1).Data^.tu8) and 1;
+ end else
+ begin
+ MakeError('', ecTypeMismatch, '');
+ Result := False;
+ exit;
+ end;
+ end;
+ btU8: TPSValueData(TPSUnValueOp(p).FVal1).Data^.tu8 := not TPSValueData(TPSUnValueOp(p).FVal1).Data^.tu8;
+ btU16: TPSValueData(TPSUnValueOp(p).FVal1).Data^.tu16 := not TPSValueData(TPSUnValueOp(p).FVal1).Data^.tu16;
+ btU32: TPSValueData(TPSUnValueOp(p).FVal1).Data^.tu32 := not TPSValueData(TPSUnValueOp(p).FVal1).Data^.tu32;
+ bts8: TPSValueData(TPSUnValueOp(p).FVal1).Data^.ts8 := not TPSValueData(TPSUnValueOp(p).FVal1).Data^.ts8;
+ bts16: TPSValueData(TPSUnValueOp(p).FVal1).Data^.ts16 := not TPSValueData(TPSUnValueOp(p).FVal1).Data^.ts16;
+ bts32: TPSValueData(TPSUnValueOp(p).FVal1).Data^.ts32 := not TPSValueData(TPSUnValueOp(p).FVal1).Data^.ts32;
+ {$IFNDEF PS_NOINT64}
+ bts64: TPSValueData(TPSUnValueOp(p).FVal1).Data^.ts64 := not TPSValueData(TPSUnValueOp(p).FVal1).Data^.ts64;
+ {$ENDIF}
+ else
+ begin
+ MakeError('', ecTypeMismatch, '');
+ Result := False;
+ exit;
+ end;
+ end;
+ preplace := TPSUnValueOp(p).Val1;
+ TPSUnValueOp(p).Val1 := nil;
+ p.Free;
+ p := preplace;
+ end;
+ otMinus:
+ begin
+ case TPSValueData(TPSUnValueOp(p).FVal1).Data^.FType.BaseType of
+ btU8: TPSValueData(TPSUnValueOp(p).FVal1).Data^.tu8 := -TPSValueData(TPSUnValueOp(p).FVal1).Data^.tu8;
+ btU16: TPSValueData(TPSUnValueOp(p).FVal1).Data^.tu16 := -TPSValueData(TPSUnValueOp(p).FVal1).Data^.tu16;
+ btU32: TPSValueData(TPSUnValueOp(p).FVal1).Data^.tu32 := -TPSValueData(TPSUnValueOp(p).FVal1).Data^.tu32;
+ bts8: TPSValueData(TPSUnValueOp(p).FVal1).Data^.ts8 := -TPSValueData(TPSUnValueOp(p).FVal1).Data^.ts8;
+ bts16: TPSValueData(TPSUnValueOp(p).FVal1).Data^.ts16 := -TPSValueData(TPSUnValueOp(p).FVal1).Data^.ts16;
+ bts32: TPSValueData(TPSUnValueOp(p).FVal1).Data^.ts32 := -TPSValueData(TPSUnValueOp(p).FVal1).Data^.ts32;
+ {$IFNDEF PS_NOINT64}
+ bts64: TPSValueData(TPSUnValueOp(p).FVal1).Data^.ts64 := -TPSValueData(TPSUnValueOp(p).FVal1).Data^.ts64;
+ {$ENDIF}
+ btSingle: TPSValueData(TPSUnValueOp(p).FVal1).Data^.tsingle := -TPSValueData(TPSUnValueOp(p).FVal1).Data^.tsingle;
+ btDouble: TPSValueData(TPSUnValueOp(p).FVal1).Data^.tdouble := -TPSValueData(TPSUnValueOp(p).FVal1).Data^.tdouble;
+ btExtended: TPSValueData(TPSUnValueOp(p).FVal1).Data^.textended := -TPSValueData(TPSUnValueOp(p).FVal1).Data^.textended;
+ btCurrency: TPSValueData(TPSUnValueOp(p).FVal1).Data^.tcurrency := -TPSValueData(TPSUnValueOp(p).FVal1).Data^.tcurrency;
+ else
+ begin
+ MakeError('', ecTypeMismatch, '');
+ Result := False;
+ exit;
+ end;
+ end;
+ preplace := TPSUnValueOp(p).Val1;
+ TPSUnValueOp(p).Val1 := nil;
+ p.Free;
+ p := preplace;
+ end;
+ otCast:
+ begin
+ preplace := TPSValueData.Create;
+ TPSValueData(preplace).Data := NewVariant(TPSUnValueOp(p).FType);
+ case TPSUnValueOp(p).FType.BaseType of
+ btU8:
+ begin
+ case TPSValueData(TPSUnValueOp(p).FVal1).Data.Ftype.basetype of
+ btchar: TPSValueData(preplace).Data.tu8 := ord(TPSValueData(TPSUnValueOp(p).FVal1).Data^.tchar);
+ {$IFNDEF PS_NOWIDESTRING}
+ btwidechar: TPSValueData(preplace).Data.tu8 := ord(TPSValueData(TPSUnValueOp(p).FVal1).Data^.twidechar);
+ {$ENDIF}
+ btU8: TPSValueData(preplace).Data.tu8 := TPSValueData(TPSUnValueOp(p).FVal1).Data^.tu8;
+ btS8: TPSValueData(preplace).Data.tu8 := TPSValueData(TPSUnValueOp(p).FVal1).Data^.tS8;
+ btU16: TPSValueData(preplace).Data.tu8 := TPSValueData(TPSUnValueOp(p).FVal1).Data^.tu16;
+ btS16: TPSValueData(preplace).Data.tu8 := TPSValueData(TPSUnValueOp(p).FVal1).Data^.tS16;
+ btU32: TPSValueData(preplace).Data.tu8 := TPSValueData(TPSUnValueOp(p).FVal1).Data^.tU32;
+ btS32: TPSValueData(preplace).Data.tu8 := TPSValueData(TPSUnValueOp(p).FVal1).Data^.tS32;
+ {$IFNDEF PS_NOINT64}
+ btS64: TPSValueData(preplace).Data.tu8 := TPSValueData(TPSUnValueOp(p).FVal1).Data^.ts64;
+ {$ENDIF}
+ else
+ begin
+ MakeError('', ecTypeMismatch, '');
+ preplace.Free;
+ Result := False;
+ exit;
+ end;
+ end;
+ end;
+ btS8:
+ begin
+ case TPSValueData(TPSUnValueOp(p).FVal1).Data.Ftype.basetype of
+ btchar: TPSValueData(preplace).Data.ts8 := ord(TPSValueData(TPSUnValueOp(p).FVal1).Data^.tchar);
+ {$IFNDEF PS_NOWIDESTRING}
+ btwidechar: TPSValueData(preplace).Data.ts8 := ord(TPSValueData(TPSUnValueOp(p).FVal1).Data^.twidechar);
+ {$ENDIF}
+ btU8: TPSValueData(preplace).Data.ts8 := TPSValueData(TPSUnValueOp(p).FVal1).Data^.tu8;
+ btS8: TPSValueData(preplace).Data.ts8 := TPSValueData(TPSUnValueOp(p).FVal1).Data^.tS8;
+ btU16: TPSValueData(preplace).Data.ts8 := TPSValueData(TPSUnValueOp(p).FVal1).Data^.tu16;
+ btS16: TPSValueData(preplace).Data.ts8 := TPSValueData(TPSUnValueOp(p).FVal1).Data^.tS16;
+ btU32: TPSValueData(preplace).Data.ts8 := TPSValueData(TPSUnValueOp(p).FVal1).Data^.tU32;
+ btS32: TPSValueData(preplace).Data.ts8 := TPSValueData(TPSUnValueOp(p).FVal1).Data^.tS32;
+ {$IFNDEF PS_NOINT64}
+ btS64: TPSValueData(preplace).Data.ts8 := TPSValueData(TPSUnValueOp(p).FVal1).Data^.ts64;
+ {$ENDIF}
+ else
+ begin
+ MakeError('', ecTypeMismatch, '');
+ preplace.Free;
+ Result := False;
+ exit;
+ end;
+ end;
+ end;
+ btU16:
+ begin
+ case TPSValueData(TPSUnValueOp(p).FVal1).Data.Ftype.basetype of
+ btchar: TPSValueData(preplace).Data.tu16 := ord(TPSValueData(TPSUnValueOp(p).FVal1).Data^.tchar);
+ {$IFNDEF PS_NOWIDESTRING}
+ btwidechar: TPSValueData(preplace).Data.tu16 := ord(TPSValueData(TPSUnValueOp(p).FVal1).Data^.twidechar);
+ {$ENDIF}
+ btU8: TPSValueData(preplace).Data.tu16 := TPSValueData(TPSUnValueOp(p).FVal1).Data^.tu8;
+ btS8: TPSValueData(preplace).Data.tu16 := TPSValueData(TPSUnValueOp(p).FVal1).Data^.tS8;
+ btU16: TPSValueData(preplace).Data.ts16 := TPSValueData(TPSUnValueOp(p).FVal1).Data^.tu16;
+ btS16: TPSValueData(preplace).Data.tu16 := TPSValueData(TPSUnValueOp(p).FVal1).Data^.tS16;
+ btU32: TPSValueData(preplace).Data.tu16 := TPSValueData(TPSUnValueOp(p).FVal1).Data^.tU32;
+ btS32: TPSValueData(preplace).Data.tu16 := TPSValueData(TPSUnValueOp(p).FVal1).Data^.tS32;
+ {$IFNDEF PS_NOINT64}
+ btS64: TPSValueData(preplace).Data.tu16 := TPSValueData(TPSUnValueOp(p).FVal1).Data^.ts64;
+ {$ENDIF}
+ else
+ begin
+ MakeError('', ecTypeMismatch, '');
+ preplace.Free;
+ Result := False;
+ exit;
+ end;
+ end;
+ end;
+ bts16:
+ begin
+ case TPSValueData(TPSUnValueOp(p).FVal1).Data.Ftype.basetype of
+ btchar: TPSValueData(preplace).Data.ts16 := ord(TPSValueData(TPSUnValueOp(p).FVal1).Data^.tchar);
+ {$IFNDEF PS_NOWIDESTRING}
+ btwidechar: TPSValueData(preplace).Data.ts16 := ord(TPSValueData(TPSUnValueOp(p).FVal1).Data^.twidechar);
+ {$ENDIF}
+ btU8: TPSValueData(preplace).Data.ts16 := TPSValueData(TPSUnValueOp(p).FVal1).Data^.tu8;
+ btS8: TPSValueData(preplace).Data.ts16 := TPSValueData(TPSUnValueOp(p).FVal1).Data^.tS8;
+ btU16: TPSValueData(preplace).Data.ts16 := TPSValueData(TPSUnValueOp(p).FVal1).Data^.tu16;
+ btS16: TPSValueData(preplace).Data.ts16 := TPSValueData(TPSUnValueOp(p).FVal1).Data^.tS16;
+ btU32: TPSValueData(preplace).Data.ts16 := TPSValueData(TPSUnValueOp(p).FVal1).Data^.tU32;
+ btS32: TPSValueData(preplace).Data.ts16 := TPSValueData(TPSUnValueOp(p).FVal1).Data^.tS32;
+ {$IFNDEF PS_NOINT64}
+ btS64: TPSValueData(preplace).Data.ts16 := TPSValueData(TPSUnValueOp(p).FVal1).Data^.ts64;
+ {$ENDIF}
+ else
+ begin
+ MakeError('', ecTypeMismatch, '');
+ preplace.Free;
+ Result := False;
+ exit;
+ end;
+ end;
+ end;
+ btU32:
+ begin
+ case TPSValueData(TPSUnValueOp(p).FVal1).Data.Ftype.basetype of
+ btchar: TPSValueData(preplace).Data.tu32 := ord(TPSValueData(TPSUnValueOp(p).FVal1).Data^.tchar);
+ {$IFNDEF PS_NOWIDESTRING}
+ btwidechar: TPSValueData(preplace).Data.tu32 := ord(TPSValueData(TPSUnValueOp(p).FVal1).Data^.twidechar);
+ {$ENDIF}
+ btU8: TPSValueData(preplace).Data.tu32 := TPSValueData(TPSUnValueOp(p).FVal1).Data^.tu8;
+ btS8: TPSValueData(preplace).Data.tu32 := TPSValueData(TPSUnValueOp(p).FVal1).Data^.tS8;
+ btU16: TPSValueData(preplace).Data.tu32 := TPSValueData(TPSUnValueOp(p).FVal1).Data^.tu16;
+ btS16: TPSValueData(preplace).Data.tu32 := TPSValueData(TPSUnValueOp(p).FVal1).Data^.tS16;
+ btU32: TPSValueData(preplace).Data.tu32 := TPSValueData(TPSUnValueOp(p).FVal1).Data^.tU32;
+ btS32: TPSValueData(preplace).Data.tu32 := TPSValueData(TPSUnValueOp(p).FVal1).Data^.tS32;
+ {$IFNDEF PS_NOINT64}
+ btS64: TPSValueData(preplace).Data.tu32 := TPSValueData(TPSUnValueOp(p).FVal1).Data^.ts64;
+ {$ENDIF}
+ else
+ begin
+ MakeError('', ecTypeMismatch, '');
+ preplace.Free;
+ Result := False;
+ exit;
+ end;
+ end;
+ end;
+ btS32:
+ begin
+ case TPSValueData(TPSUnValueOp(p).FVal1).Data.Ftype.basetype of
+ btchar: TPSValueData(preplace).Data.ts32 := ord(TPSValueData(TPSUnValueOp(p).FVal1).Data^.tchar);
+ {$IFNDEF PS_NOWIDESTRING}
+ btwidechar: TPSValueData(preplace).Data.ts32 := ord(TPSValueData(TPSUnValueOp(p).FVal1).Data^.twidechar);
+ {$ENDIF}
+ btU8: TPSValueData(preplace).Data.ts32 := TPSValueData(TPSUnValueOp(p).FVal1).Data^.tu8;
+ btS8: TPSValueData(preplace).Data.ts32 := TPSValueData(TPSUnValueOp(p).FVal1).Data^.tS8;
+ btU16: TPSValueData(preplace).Data.ts32 := TPSValueData(TPSUnValueOp(p).FVal1).Data^.tu16;
+ btS16: TPSValueData(preplace).Data.ts32 := TPSValueData(TPSUnValueOp(p).FVal1).Data^.tS16;
+ btU32: TPSValueData(preplace).Data.ts32 := TPSValueData(TPSUnValueOp(p).FVal1).Data^.tU32;
+ btS32: TPSValueData(preplace).Data.ts32 := TPSValueData(TPSUnValueOp(p).FVal1).Data^.tS32;
+ {$IFNDEF PS_NOINT64}
+ btS64: TPSValueData(preplace).Data.tu32 := TPSValueData(TPSUnValueOp(p).FVal1).Data^.ts64;
+ {$ENDIF}
+ else
+ begin
+ MakeError('', ecTypeMismatch, '');
+ preplace.Free;
+ Result := False;
+ exit;
+ end;
+ end;
+ end;
+ {$IFNDEF PS_NOINT64}
+ btS64:
+ begin
+ case TPSValueData(TPSUnValueOp(p).FVal1).Data.Ftype.basetype of
+ btchar: TPSValueData(preplace).Data.ts64 := ord(TPSValueData(TPSUnValueOp(p).FVal1).Data^.tchar);
+ {$IFNDEF PS_NOWIDESTRING}
+ btwidechar: TPSValueData(preplace).Data.ts64 := ord(TPSValueData(TPSUnValueOp(p).FVal1).Data^.twidechar);
+ {$ENDIF}
+ btU8: TPSValueData(preplace).Data.ts64 := TPSValueData(TPSUnValueOp(p).FVal1).Data^.tu8;
+ btS8: TPSValueData(preplace).Data.ts64 := TPSValueData(TPSUnValueOp(p).FVal1).Data^.tS8;
+ btU16: TPSValueData(preplace).Data.ts64 := TPSValueData(TPSUnValueOp(p).FVal1).Data^.tu16;
+ btS16: TPSValueData(preplace).Data.ts64 := TPSValueData(TPSUnValueOp(p).FVal1).Data^.tS16;
+ btU32: TPSValueData(preplace).Data.ts64 := TPSValueData(TPSUnValueOp(p).FVal1).Data^.tU32;
+ btS32: TPSValueData(preplace).Data.ts64 := TPSValueData(TPSUnValueOp(p).FVal1).Data^.tS32;
+ btS64: TPSValueData(preplace).Data.ts64 := TPSValueData(TPSUnValueOp(p).FVal1).Data^.ts64;
+ else
+ begin
+ MakeError('', ecTypeMismatch, '');
+ preplace.Free;
+ Result := False;
+ exit;
+ end;
+ end;
+ end;
+ {$ENDIF}
+ btChar:
+ begin
+ case TPSValueData(TPSUnValueOp(p).FVal1).Data.Ftype.basetype of
+ btchar: TPSValueData(preplace).Data.tchar := TPSValueData(TPSUnValueOp(p).FVal1).Data^.tchar;
+ btU8: TPSValueData(preplace).Data.tchar := tbtchar(TPSValueData(TPSUnValueOp(p).FVal1).Data^.tu8);
+ btS8: TPSValueData(preplace).Data.tchar := tbtchar(TPSValueData(TPSUnValueOp(p).FVal1).Data^.tS8);
+ btU16: TPSValueData(preplace).Data.tchar := tbtchar(TPSValueData(TPSUnValueOp(p).FVal1).Data^.tu16);
+ btS16: TPSValueData(preplace).Data.tchar := tbtchar(TPSValueData(TPSUnValueOp(p).FVal1).Data^.tS16);
+ btU32: TPSValueData(preplace).Data.tchar := tbtchar(TPSValueData(TPSUnValueOp(p).FVal1).Data^.tU32);
+ btS32: TPSValueData(preplace).Data.tchar := tbtchar(TPSValueData(TPSUnValueOp(p).FVal1).Data^.tS32);
+ {$IFNDEF PS_NOINT64}
+ btS64: TPSValueData(preplace).Data.tchar := tbtchar(TPSValueData(TPSUnValueOp(p).FVal1).Data^.ts64);
+ {$ENDIF}
+ else
+ begin
+ MakeError('', ecTypeMismatch, '');
+ Result := False;
+ preplace.Free;
+ exit;
+ end;
+ end;
+ end;
+ else
+ begin
+ MakeError('', ecTypeMismatch, '');
+ Result := False;
+ preplace.Free;
+ exit;
+ end;
+ end;
+ p.Free;
+ p := preplace;
+ end;
+ else
+ begin
+ MakeError('', ecTypeMismatch, '');
+ Result := False;
+ exit;
+ end;
+ end; // case
+ end; // if
+ end;
+ Result := True;
+ end;
+
+ var
+ Temp, Val: TPSValue;
+ vt: TPSVariableType;
+
+begin
+ Val := ReadExpression;
+ if Val = nil then
+ begin
+ Result := nil;
+ exit;
+ end;
+ vt := ivtGlobal;
+ repeat
+ Temp := Val;
+ if Val <> nil then CheckFurther(Val, False);
+ if Val <> nil then CheckClass(Val, vt, InvalidVal, False);
+ if Val <> nil then CheckExtClass(Val, vt, InvalidVal, False);
+{$IFNDEF PS_NOIDISPATCH}if Val <> nil then CheckIntf(Val, vt, InvalidVal, False);{$ENDIF}
+ if Val <> nil then CheckProcCall(Val);
+ if Val<> nil then CheckClassArrayProperty(Val, vt, InvalidVal);
+ until (Val = nil) or (Temp = Val);
+
+ if not TryEvalConst(Val) then
+ begin
+ Val.Free;
+ Result := nil;
+ exit;
+ end;
+ Result := Val;
+ end;
+
+ function ReadParameters(IsProperty: Boolean; Dest: TPSParameters): Boolean;
+ var
+ sr,cr: TPSPasToken;
+ begin
+ if IsProperty then
+ begin
+ sr := CSTI_OpenBlock;
+ cr := CSTI_CloseBlock;
+ end else begin
+ sr := CSTI_OpenRound;
+ cr := CSTI_CloseRound;
+ end;
+ if FParser.CurrTokenId = sr then
+ begin
+ FParser.Next;
+ if FParser.CurrTokenId = cr then
+ begin
+ FParser.Next;
+ Result := True;
+ exit;
+ end;
+ end else
+ begin
+ result := True;
+ exit;
+ end;
+ repeat
+ with Dest.Add do
+ begin
+ Val := calc(CSTI_CloseRound);
+ if Val = nil then
+ begin
+ result := false;
+ exit;
+ end;
+ end;
+ if FParser.CurrTokenId = cr then
+ begin
+ FParser.Next;
+ Break;
+ end;
+ if FParser.CurrTokenId <> CSTI_Comma then
+ begin
+ MakeError('', ecCommaExpected, '');
+ Result := false;
+ exit;
+ end; {if}
+ FParser.Next;
+ until False;
+ Result := true;
+ end;
+
+ function ReadProcParameters(ProcNo: Cardinal; FSelf: TPSValue): TPSValue;
+ var
+ Decl: TPSParametersDecl;
+ begin
+ if TPSProcedure(FProcs[ProcNo]).ClassType = TPSInternalProcedure then
+ Decl := TPSInternalProcedure(FProcs[ProcNo]).Decl
+ else
+ Decl := TPSExternalProcedure(FProcs[ProcNo]).RegProc.Decl;
+ UseProc(Decl);
+ Result := TPSValueProcNo.Create;
+ TPSValueProcNo(Result).ProcNo := ProcNo;
+ TPSValueProcNo(Result).ResultType := Decl.Result;
+ with TPSValueProcNo(Result) do
+ begin
+ SetParserPos(FParser);
+ Parameters := TPSParameters.Create;
+ if FSelf <> nil then
+ begin
+ Parameters.Add;
+ end;
+ end;
+
+ if not ReadParameters(False, TPSValueProc(Result).Parameters) then
+ begin
+ FSelf.Free;
+ Result.Free;
+ Result := nil;
+ exit;
+ end;
+
+ if not ValidateParameters(BlockInfo, TPSValueProc(Result).Parameters, Decl) then
+ begin
+ FSelf.Free;
+ Result.Free;
+ Result := nil;
+ exit;
+ end;
+ if FSelf <> nil then
+ begin
+ with TPSValueProcNo(Result).Parameters[0] do
+ begin
+ Val := FSelf;
+ ExpectedType := GetTypeNo(BlockInfo, FSelf);
+ end;
+ end;
+ end;
+ {$IFNDEF PS_NOIDISPATCH}
+
+ function ReadIDispatchParameters(const ProcName: tbtString; aVariantType: TPSVariantType; FSelf: TPSValue): TPSValue;
+ var
+ Par: TPSParameters;
+ PropSet: Boolean;
+ i: Longint;
+ Temp: TPSValue;
+ begin
+ Par := TPSParameters.Create;
+ try
+ if not ReadParameters(FParser.CurrTokenID = CSTI_OpenBlock, Par) then
+ begin
+ FSelf.Free;
+ Result := nil;
+ exit;
+ end;
+
+ if FParser.CurrTokenID = CSTI_Assignment then
+ begin
+ FParser.Next;
+ PropSet := True;
+ Temp := calc(CSTI_SemiColon);
+ if temp = nil then
+ begin
+ FSelf.Free;
+ Result := nil;
+ exit;
+ end;
+ with par.Add do
+ begin
+ FValue := Temp;
+ end;
+ end else
+ begin
+ PropSet := False;
+ end;
+
+ Result := TPSValueProcNo.Create;
+ TPSValueProcNo(Result).ResultType := aVariantType;
+ with TPSValueProcNo(Result) do
+ begin
+ SetParserPos(FParser);
+ Parameters := TPSParameters.Create;
+ if FSelf <> nil then
+ begin
+ with Parameters.Add do
+ begin
+ Val := FSelf;
+ ExpectedType := aVariantType.GetDynIvokeSelfType(Self);
+ end;
+ with Parameters.Add do
+ begin
+ Val := TPSValueData.Create;
+ TPSValueData(Val).Data := NewVariant(FDefaultBoolType);
+ TPSValueData(Val).Data.tu8 := Ord(PropSet);
+ ExpectedType := FDefaultBoolType;
+ end;
+
+ with Parameters.Add do
+ begin
+ Val := TPSValueData.Create;
+ TPSValueData(Val).Data := NewVariant(FindBaseType(btString));
+ tbtString(TPSValueData(Val).data.tString) := Procname;
+ ExpectedType := FindBaseType(btString);
+ end;
+
+ with Parameters.Add do
+ begin
+ val := TPSValueArray.Create;
+ ExpectedType := aVariantType.GetDynInvokeParamType(Self);
+ temp := Val;
+ end;
+ for i := 0 to Par.Count -1 do
+ begin
+ TPSValueArray(Temp).Add(par.Item[i].Val);
+ par.Item[i].val := nil;
+ end;
+ end;
+ end;
+ TPSValueProcNo(Result).ProcNo := aVariantType.GetDynInvokeProcNo(Self, ProcName, TPSValueProcNo(Result).Parameters);
+ finally
+ Par.Free;
+ end;
+
+ end;
+
+ {$ENDIF}
+
+ function ReadVarParameters(ProcNoVar: TPSValue): TPSValue;
+ var
+ Decl: TPSParametersDecl;
+ begin
+ Decl := TPSProceduralType(GetTypeNo(BlockInfo, ProcnoVar)).ProcDef;
+ UseProc(Decl);
+
+ Result := TPSValueProcVal.Create;
+
+ with TPSValueProcVal(Result) do
+ begin
+ ResultType := Decl.Result;
+ ProcNo := ProcNoVar;
+ Parameters := TPSParameters.Create;
+ end;
+
+ if not ReadParameters(False, TPSValueProc(Result).Parameters) then
+ begin
+ Result.Free;
+ Result := nil;
+ exit;
+ end;
+
+ if not ValidateParameters(BlockInfo, TPSValueProc(Result).Parameters, Decl) then
+ begin
+ Result.Free;
+ Result := nil;
+ exit;
+ end;
+ end;
+
+
+ function WriteCalculation(InData, OutReg: TPSValue): Boolean;
+
+ function CheckOutreg(Where, Outreg: TPSValue; aRoot: Boolean): Boolean;
+ var
+ i: Longint;
+ begin
+ Result := False;
+ if Outreg is TPSValueReplace
+ then Outreg:=TPSValueReplace(Outreg).OldValue;
+ if Where is TPSValueVar then begin
+ if TPSValueVar(Where).GetRecCount > 0 then result := true;
+ if SAmeReg(Where, OutReg) and not aRoot then
+ result := true;
+ end else
+ if Where.ClassType = TPSUnValueOp then
+ begin
+ if CheckOutReg(TPSUnValueOp(Where).Val1, OutReg, aRoot) then
+ Result := True;
+ end else if Where.ClassType = TPSBinValueOp then
+ begin
+ if CheckOutreg(TPSBinValueOp(Where).Val1, OutReg, aRoot) or CheckOutreg(TPSBinValueOp(Where).Val2, OutReg, False) then
+ Result := True;
+ end else if Where is TPSValueVar then
+ begin
+ if SameReg(Where, OutReg) then
+ Result := True;
+ end else if Where is TPSValueProc then
+ begin
+ for i := 0 to TPSValueProc(Where).Parameters.Count -1 do
+ begin
+ if Checkoutreg(TPSValueProc(Where).Parameters[i].Val, Outreg, false) then
+ begin
+ Result := True;
+ break;
+ end;
+ end;
+ end;
+ end;
+ begin
+ if not CheckCompatType(Outreg, InData) then
+ begin
+ MakeError('', ecTypeMismatch, '');
+ Result := False;
+ exit;
+ end;
+ if SameReg(OutReg, InData) then
+ begin
+ Result := True;
+ exit;
+ end;
+ if InData is TPSValueProc then
+ begin
+ Result := _ProcessFunction(TPSValueProc(indata), OutReg)
+ end else begin
+ if not PreWriteOutRec(OutReg, nil) then
+ begin
+ Result := False;
+ exit;
+ end;
+ if (not CheckOutReg(InData, OutReg, true)) and (InData is TPSBinValueOp) or (InData is TPSUnValueOp) then
+ begin
+ if InData is TPSBinValueOp then
+ begin
+ if not DoBinCalc(TPSBinValueOp(InData), OutReg) then
+ begin
+ AfterWriteOutRec(OutReg);
+ Result := False;
+ exit;
+ end;
+ end else
+ begin
+ if not DoUnCalc(TPSUnValueOp(InData), OutReg) then
+ begin
+ AfterWriteOutRec(OutReg);
+ Result := False;
+ exit;
+ end;
+ end;
+ end else if (InData is TPSBinValueOp) and (not CheckOutReg(TPSBinValueOp(InData).Val2, OutReg, false)) then
+ begin
+ if not DoBinCalc(TPSBinValueOp(InData), OutReg) then
+ begin
+ AfterWriteOutRec(OutReg);
+ Result := False;
+ exit;
+ end;
+ end else begin
+ if not PreWriteOutRec(InData, GetTypeNo(BlockInfo, OutReg)) then
+ begin
+ Result := False;
+ exit;
+ end;
+ BlockWriteByte(BlockInfo, CM_A);
+ if not (WriteOutRec(OutReg, False) and WriteOutRec(InData, True)) then
+ begin
+ Result := False;
+ exit;
+ end;
+ AfterWriteOutRec(InData);
+ end;
+ AfterWriteOutRec(OutReg);
+ Result := True;
+ end;
+ end; {WriteCalculation}
+
+
+ function _ProcessFunction(ProcCall: TPSValueProc; ResultRegister: TPSValue): Boolean;
+ var
+ res: TPSType;
+ tmp: TPSParameter;
+ lTv: TPSValue;
+ resreg: TPSValue;
+ l: Longint;
+
+ function Cleanup: Boolean;
+ var
+ i: Longint;
+ begin
+ for i := 0 to ProcCall.Parameters.Count -1 do
+ begin
+ if ProcCall.Parameters[i].TempVar <> nil then
+ ProcCall.Parameters[i].TempVar.Free;
+ ProcCall.Parameters[i].TempVar := nil;
+ end;
+ if ProcCall is TPSValueProcVal then
+ AfterWriteOutRec(TPSValueProcVal(ProcCall).fProcNo);
+ if ResReg <> nil then
+ AfterWriteOutRec(resreg);
+ if ResReg <> nil then
+ begin
+ if ResReg <> ResultRegister then
+ begin
+ if ResultRegister <> nil then
+ begin
+ if not WriteCalculation(ResReg, ResultRegister) then
+ begin
+ Result := False;
+ resreg.Free;
+ exit;
+ end;
+ end;
+ resreg.Free;
+ end;
+ end;
+ Result := True;
+ end;
+
+ begin
+ Res := ProcCall.ResultType;
+ if ProcCall.ResultType = FAnyString then
+ begin
+ for l := ProcCall.Parameters.Count - 1 downto 0 do
+ begin
+ Tmp := ProcCall.Parameters[l];
+ if (Tmp.ParamMode <> pmOut) and (Tmp.ExpectedType = FAnyString) then
+ begin
+ Res := GetTypeNo(BlockInfo, tmp.Val);
+ Break;
+ end;
+ end;
+ end;
+ Result := False;
+ if (res = nil) and (ResultRegister <> nil) then
+ begin
+ MakeError('', ecNoResult, '');
+ exit;
+ end
+ else if (res <> nil) then
+ begin
+ if (ResultRegister = nil) or (Res <> GetTypeNo(BlockInfo, ResultRegister)) then
+ begin
+ resreg := AllocStackReg(res);
+
+ end else resreg := ResultRegister;
+ end
+ else
+ resreg := nil;
+ if ResReg <> nil then
+ begin
+ if not PreWriteOutRec(resreg, nil) then
+ begin
+ Cleanup;
+ exit;
+ end;
+ end;
+ if Proccall is TPSValueProcVal then
+ begin
+ if not PreWriteOutRec(TPSValueProcVal(ProcCall).fProcNo, nil) then
+ begin
+ Cleanup;
+ exit;
+ end;
+ end;
+ for l := ProcCall.Parameters.Count - 1 downto 0 do
+ begin
+ Tmp := ProcCall.Parameters[l];
+ if (Tmp.ParamMode <> pmIn) then
+ begin
+ if IsVarInCompatible(GetTypeNo(BlockInfo, tmp.Val), tmp.ExpectedType) then
+ begin
+ with MakeError('', ecTypeMismatch, '') do
+ begin
+ pos := tmp.Val.Pos;
+ row := tmp.Val.row;
+ col := tmp.Val.col;
+ end;
+ Cleanup;
+ exit;
+ end;
+ if Copy(tmp.ExpectedType.Name, 1, 10) = '!OPENARRAY' then begin
+ tmp.TempVar := AllocPointer(tmp.ExpectedType);
+ lTv := AllocStackReg(tmp.ExpectedType);
+ if not PreWriteOutRec(Tmp.FValue, nil) then
+ begin
+ cleanup;
+ exit;
+ end;
+ BlockWriteByte(BlockInfo, CM_A);
+ WriteOutRec(lTv, False);
+ WriteOutRec(Tmp.FValue, False);
+ AfterWriteOutRec(Tmp.FValue);
+
+ BlockWriteByte(BlockInfo, cm_sp);
+ WriteOutRec(tmp.TempVar, False);
+ WriteOutRec(lTv, False);
+
+ lTv.Free;
+// BlockWriteByte(BlockInfo, CM_PO); // pop the temp var
+
+ end else begin
+ tmp.TempVar := AllocPointer(GetTypeNo(BlockInfo, Tmp.FValue));
+ if not PreWriteOutRec(Tmp.FValue, nil) then
+ begin
+ cleanup;
+ exit;
+ end;
+ BlockWriteByte(BlockInfo, cm_sp);
+ WriteOutRec(tmp.TempVar, False);
+ WriteOutRec(Tmp.FValue, False);
+ AfterWriteOutRec(Tmp.FValue);
+ end;
+ end
+ else
+ begin
+ if (Tmp.ExpectedType = nil) or (Tmp.ExpectedType = FAnyString) then
+ Tmp.ExpectedType := GetTypeNo(BlockInfo, tmp.Val);
+ if Tmp.ExpectedType.BaseType = btPChar then
+ begin
+ Tmp.TempVar := AllocStackReg(at2ut(FindBaseType(btstring)))
+ end else
+ begin
+ Tmp.TempVar := AllocStackReg(Tmp.ExpectedType);
+ end;
+ if not WriteCalculation(Tmp.Val, Tmp.TempVar) then
+ begin
+ Cleanup;
+ exit;
+ end;
+ end;
+ end; {for}
+ if res <> nil then
+ begin
+ BlockWriteByte(BlockInfo, CM_PV);
+
+ if not WriteOutRec(resreg, False) then
+ begin
+ Cleanup;
+ MakeError('', ecInternalError, '00015');
+ exit;
+ end;
+ end;
+ if ProcCall is TPSValueProcVal then
+ begin
+ BlockWriteByte(BlockInfo, Cm_cv);
+ WriteOutRec(TPSValueProcVal(ProcCall).ProcNo, True);
+ end else begin
+ BlockWriteByte(BlockInfo, CM_C);
+ BlockWriteLong(BlockInfo, TPSValueProcNo(ProcCall).ProcNo);
+ end;
+ if res <> nil then
+ BlockWriteByte(BlockInfo, CM_PO);
+ if not Cleanup then
+ begin
+ Result := False;
+ exit;
+ end;
+ Result := True;
+ end; {ProcessVarFunction}
+
+ function HasInvalidJumps(StartPos, EndPos: Cardinal): Boolean;
+ var
+ I, J: Longint;
+ Ok: LongBool;
+ FLabelsInBlock: TIfStringList;
+ s: tbtString;
+ begin
+ FLabelsInBlock := TIfStringList.Create;
+ for i := 0 to BlockInfo.Proc.FLabels.Count -1 do
+ begin
+ s := BlockInfo.Proc.FLabels[I];
+ if (Cardinal((@s[1])^) >= StartPos) and (Cardinal((@s[1])^) <= EndPos) then
+ begin
+ Delete(s, 1, 8);
+ FLabelsInBlock.Add(s);
+ end;
+ end;
+ for i := 0 to BlockInfo.Proc.FGotos.Count -1 do
+ begin
+ s := BlockInfo.Proc.FGotos[I];
+ if (Cardinal((@s[1])^) >= StartPos) and (Cardinal((@s[1])^) <= EndPos) then
+ begin
+ Delete(s, 1, 4);
+ s := BlockInfo.Proc.FLabels[Cardinal((@s[1])^)];
+ Delete(s,1,8);
+ OK := False;
+ for J := 0 to FLabelsInBlock.Count -1 do
+ begin
+ if FLabelsInBlock[J] = s then
+ begin
+ Ok := True;
+ Break;
+ end;
+ end;
+ if not Ok then
+ begin
+ MakeError('', ecInvalidJump, '');
+ Result := True;
+ FLabelsInBlock.Free;
+ exit;
+ end;
+ end else begin
+ Delete(s, 1, 4);
+ s := BlockInfo.Proc.FLabels[Cardinal((@s[1])^)];
+ Delete(s,1,8);
+ OK := True;
+ for J := 0 to FLabelsInBlock.Count -1 do
+ begin
+ if FLabelsInBlock[J] = s then
+ begin
+ Ok := False;
+ Break;
+ end;
+ end;
+ if not Ok then
+ begin
+ MakeError('', ecInvalidJump, '');
+ Result := True;
+ FLabelsInBlock.Free;
+ exit;
+ end;
+ end;
+ end;
+ FLabelsInBlock.Free;
+ Result := False;
+ end;
+
+ function ProcessFor: Boolean;
+ { Process a for x := y to z do }
+ var
+ VariableVar: TPSValue;
+ TempBool,
+ InitVal,
+ finVal: TPSValue;
+ Block: TPSBlockInfo;
+ Backwards: Boolean;
+ FPos, NPos, EPos, RPos: Longint;
+ OldCO, OldBO: TPSList;
+ I: Longint;
+ iOldWithCount: Integer;
+ iOldTryCount: Integer;
+ iOldExFnlCount: Integer;
+ lType: TPSType;
+ begin
+ Debug_WriteLine(BlockInfo);
+ Result := False;
+ FParser.Next;
+ if FParser.CurrTokenId <> CSTI_Identifier then
+ begin
+ MakeError('', ecIdentifierExpected, '');
+ exit;
+ end;
+ VariableVar := GetIdentifier(1);
+ if VariableVar = nil then
+ exit;
+ lType := GetTypeNo(BlockInfo, VariableVar);
+ if lType = nil then begin
+ MakeError('', ecTypeMismatch, '');
+ VariableVar.Free;
+ exit;
+ end;
+ case lType.BaseType of
+ btU8, btS8, btU16, btS16, btU32, btS32, {$IFNDEF PS_NOINT64} btS64, {$ENDIF} btVariant: ;
+ else
+ begin
+ MakeError('', ecTypeMismatch, '');
+ VariableVar.Free;
+ exit;
+ end;
+ end;
+ if FParser.CurrTokenId <> CSTI_Assignment then
+ begin
+ MakeError('', ecAssignmentExpected, '');
+ VariableVar.Free;
+ exit;
+ end;
+ FParser.Next;
+ InitVal := calc(CSTII_DownTo);
+ if InitVal = nil then
+ begin
+ VariableVar.Free;
+ exit;
+ end;
+ if FParser.CurrTokenId = CSTII_To then
+ Backwards := False
+ else if FParser.CurrTokenId = CSTII_DownTo then
+ Backwards := True
+ else
+ begin
+ MakeError('', ecToExpected, '');
+ VariableVar.Free;
+ InitVal.Free;
+ exit;
+ end;
+ FParser.Next;
+ finVal := calc(CSTII_do);
+ if finVal = nil then
+ begin
+ VariableVar.Free;
+ InitVal.Free;
+ exit;
+ end;
+ lType := GetTypeNo(BlockInfo, finVal);
+ if lType = nil then begin
+ MakeError('', ecTypeMismatch, '');
+ VariableVar.Free;
+ InitVal.Free;
+ exit;
+ end;
+ case lType.BaseType of
+ btVariant, btU8, btS8, btU16, btS16, btU32, {$IFNDEF PS_NOINT64} btS64, {$ENDIF} btS32: ;
+ else
+ begin
+ MakeError('', ecTypeMismatch, '');
+ VariableVar.Free;
+ InitVal.Free;
+ exit;
+ end;
+ end;
+ if FParser.CurrTokenId <> CSTII_do then
+ begin
+ MakeError('', ecDoExpected, '');
+ finVal.Free;
+ InitVal.Free;
+ VariableVar.Free;
+ exit;
+ end;
+ FParser.Next;
+ if not WriteCalculation(InitVal, VariableVar) then
+ begin
+ VariableVar.Free;
+ InitVal.Free;
+ finVal.Free;
+ exit;
+ end;
+ InitVal.Free;
+ TempBool := AllocStackReg(at2ut(FDefaultBoolType));
+ NPos := Length(BlockInfo.Proc.Data);
+ if not (PreWriteOutRec(VariableVar, nil) and PreWriteOutRec(finVal, nil)) then
+ begin
+ TempBool.Free;
+ VariableVar.Free;
+ finVal.Free;
+ exit;
+ end;
+ BlockWriteByte(BlockInfo, CM_CO);
+ if Backwards then
+ begin
+ BlockWriteByte(BlockInfo, 0); { >= }
+ end
+ else
+ begin
+ BlockWriteByte(BlockInfo, 1); { <= }
+ end;
+ if not (WriteOutRec(TempBool, False) and WriteOutRec(VariableVar, True) and WriteOutRec(finVal, True)) then
+ begin
+ TempBool.Free;
+ VariableVar.Free;
+ finVal.Free;
+ exit;
+ end;
+ AfterWriteOutRec(finVal);
+ AfterWriteOutRec(VariableVar);
+ finVal.Free;
+ BlockWriteByte(BlockInfo, Cm_CNG);
+ EPos := Length(BlockInfo.Proc.Data);
+ BlockWriteLong(BlockInfo, $12345678);
+ WriteOutRec(TempBool, False);
+ RPos := Length(BlockInfo.Proc.Data);
+ OldCO := FContinueOffsets;
+ FContinueOffsets := TPSList.Create;
+ OldBO := FBreakOffsets;
+ FBreakOffsets := TPSList.Create;
+ Block := TPSBlockInfo.Create(BlockInfo);
+ Block.SubType := tOneLiner;
+
+ iOldWithCount := FWithCount;
+ FWithCount := 0;
+ iOldTryCount := FTryCount;
+ FTryCount := 0;
+ iOldExFnlCount := FExceptFinallyCount;
+ FExceptFinallyCount := 0;
+
+ if not ProcessSub(Block) then
+ begin
+ Block.Free;
+ TempBool.Free;
+ VariableVar.Free;
+ FBreakOffsets.Free;
+ FContinueOffsets.Free;
+ FContinueOffsets := OldCO;
+ FBreakOffsets := OldBo;
+
+ FWithCount := iOldWithCount;
+ FTryCount := iOldTryCount;
+ FExceptFinallyCount := iOldExFnlCount;
+
+ exit;
+ end;
+ Block.Free;
+ FPos := Length(BlockInfo.Proc.Data);
+ if not PreWriteOutRec(VariableVar, nil) then
+ begin
+ TempBool.Free;
+ VariableVar.Free;
+ FBreakOffsets.Free;
+ FContinueOffsets.Free;
+ FContinueOffsets := OldCO;
+ FBreakOffsets := OldBo;
+
+ FWithCount := iOldWithCount;
+ FTryCount := iOldTryCount;
+ FExceptFinallyCount := iOldExFnlCount;
+
+ exit;
+ end;
+ if Backwards then
+ BlockWriteByte(BlockInfo, cm_dec)
+ else
+ BlockWriteByte(BlockInfo, cm_inc);
+ if not WriteOutRec(VariableVar, False) then
+ begin
+ TempBool.Free;
+ VariableVar.Free;
+ FBreakOffsets.Free;
+ FContinueOffsets.Free;
+ FContinueOffsets := OldCO;
+ FBreakOffsets := OldBo;
+
+ FWithCount := iOldWithCount;
+ FTryCount := iOldTryCount;
+ FExceptFinallyCount := iOldExFnlCount;
+
+ exit;
+ end;
+ AfterWriteOutRec(VariableVar);
+ BlockWriteByte(BlockInfo, Cm_G);
+ BlockWriteLong(BlockInfo, Longint(NPos - Length(BlockInfo.Proc.Data) - 4));
+ {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
+ unaligned(Longint((@BlockInfo.Proc.Data[EPos + 1])^)) := Length(BlockInfo.Proc.Data) - RPos;
+ {$else}
+ Longint((@BlockInfo.Proc.Data[EPos + 1])^) := Length(BlockInfo.Proc.Data) - RPos;
+ {$endif}
+ for i := 0 to FBreakOffsets.Count -1 do
+ begin
+ EPos := IPointer(FBreakOffsets[I]);
+ {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
+ unaligned(Longint((@BlockInfo.Proc.Data[EPos - 3])^)) := Length(BlockInfo.Proc.Data) - Longint(EPos);
+ {$else}
+ Longint((@BlockInfo.Proc.Data[EPos - 3])^) := Length(BlockInfo.Proc.Data) - Longint(EPos);
+ {$endif}
+ end;
+ for i := 0 to FContinueOffsets.Count -1 do
+ begin
+ EPos := IPointer(FContinueOffsets[I]);
+ {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
+ unaligned(Longint((@BlockInfo.Proc.Data[EPos - 3])^)) := Longint(FPos) - Longint(EPos);
+ {$else}
+ Longint((@BlockInfo.Proc.Data[EPos - 3])^) := Longint(FPos) - Longint(EPos);
+ {$endif}
+ end;
+ FBreakOffsets.Free;
+ FContinueOffsets.Free;
+ FContinueOffsets := OldCO;
+ FBreakOffsets := OldBo;
+
+ FWithCount := iOldWithCount;
+ FTryCount := iOldTryCount;
+ FExceptFinallyCount := iOldExFnlCount;
+
+ TempBool.Free;
+ VariableVar.Free;
+ if HasInvalidJumps(RPos, Length(BlockInfo.Proc.Data)) then
+ begin
+ Result := False;
+ exit;
+ end;
+ Result := True;
+ end; {ProcessFor}
+
+ function ProcessWhile: Boolean;
+ var
+ vin, vout: TPSValue;
+ SPos, EPos: Cardinal;
+ OldCo, OldBO: TPSList;
+ I: Longint;
+ Block: TPSBlockInfo;
+
+ iOldWithCount: Integer;
+ iOldTryCount: Integer;
+ iOldExFnlCount: Integer;
+
+ begin
+ Result := False;
+ Debug_WriteLine(BlockInfo);
+ FParser.Next;
+ vout := calc(CSTII_do);
+ if vout = nil then
+ exit;
+ if FParser.CurrTokenId <> CSTII_do then
+ begin
+ vout.Free;
+ MakeError('', ecDoExpected, '');
+ exit;
+ end;
+ vin := AllocStackReg(at2ut(FDefaultBoolType));
+ SPos := Length(BlockInfo.Proc.Data); // start position
+ OldCo := FContinueOffsets;
+ FContinueOffsets := TPSList.Create;
+ OldBO := FBreakOffsets;
+ FBreakOffsets := TPSList.Create;
+ if not WriteCalculation(vout, vin) then
+ begin
+ vout.Free;
+ vin.Free;
+ FBreakOffsets.Free;
+ FContinueOffsets.Free;
+ FContinueOffsets := OldCO;
+ FBreakOffsets := OldBo;
+ exit;
+ end;
+ vout.Free;
+ FParser.Next; // skip DO
+ BlockWriteByte(BlockInfo, Cm_CNG); // only goto if expression is false
+ BlockWriteLong(BlockInfo, $12345678);
+ EPos := Length(BlockInfo.Proc.Data);
+ if not WriteOutRec(vin, False) then
+ begin
+ MakeError('', ecInternalError, '00017');
+ vin.Free;
+ FBreakOffsets.Free;
+ FContinueOffsets.Free;
+ FContinueOffsets := OldCO;
+ FBreakOffsets := OldBo;
+ exit;
+ end;
+ Block := TPSBlockInfo.Create(BlockInfo);
+ Block.SubType := tOneLiner;
+
+ iOldWithCount := FWithCount;
+ FWithCount := 0;
+ iOldTryCount := FTryCount;
+ FTryCount := 0;
+ iOldExFnlCount := FExceptFinallyCount;
+ FExceptFinallyCount := 0;
+
+ if not ProcessSub(Block) then
+ begin
+ Block.Free;
+ vin.Free;
+ FBreakOffsets.Free;
+ FContinueOffsets.Free;
+ FContinueOffsets := OldCO;
+ FBreakOffsets := OldBo;
+
+ FWithCount := iOldWithCount;
+ FTryCount := iOldTryCount;
+ FExceptFinallyCount := iOldExFnlCount;
+
+ exit;
+ end;
+ Block.Free;
+ Debug_WriteLine(BlockInfo);
+ BlockWriteByte(BlockInfo, Cm_G);
+ BlockWriteLong(BlockInfo, Longint(SPos) - Length(BlockInfo.Proc.Data) - 4);
+ {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
+ unaligned(Longint((@BlockInfo.Proc.Data[EPos - 3])^)) := Length(BlockInfo.Proc.Data) - Longint(EPos) - 5;
+ {$else}
+ Longint((@BlockInfo.Proc.Data[EPos - 3])^) := Length(BlockInfo.Proc.Data) - Longint(EPos) - 5;
+ {$endif}
+ for i := 0 to FBreakOffsets.Count -1 do
+ begin
+ EPos := Cardinal(FBreakOffsets[I]);
+ {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
+ unaligned(Longint((@BlockInfo.Proc.Data[EPos - 3])^)) := Length(BlockInfo.Proc.Data) - Longint(EPos);
+ {$else}
+ Longint((@BlockInfo.Proc.Data[EPos - 3])^) := Length(BlockInfo.Proc.Data) - Longint(EPos);
+ {$endif}
+ end;
+ for i := 0 to FContinueOffsets.Count -1 do
+ begin
+ EPos := Cardinal(FContinueOffsets[I]);
+ {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
+ unaligned(Longint((@BlockInfo.Proc.Data[EPos - 3])^)) := Longint(SPos) - Longint(EPos);
+ {$else}
+ Longint((@BlockInfo.Proc.Data[EPos - 3])^) := Longint(SPos) - Longint(EPos);
+ {$endif}
+ end;
+ FBreakOffsets.Free;
+ FContinueOffsets.Free;
+ FContinueOffsets := OldCO;
+ FBreakOffsets := OldBo;
+
+ FWithCount := iOldWithCount;
+ FTryCount := iOldTryCount;
+ FExceptFinallyCount := iOldExFnlCount;
+
+ vin.Free;
+ if HasInvalidJumps(EPos, Length(BlockInfo.Proc.Data)) then
+ begin
+ Result := False;
+ exit;
+ end;
+ Result := True;
+ end;
+
+ function ProcessRepeat: Boolean;
+ var
+ vin, vout: TPSValue;
+ CPos, SPos, EPos: Cardinal;
+ I: Longint;
+ OldCo, OldBO: TPSList;
+ Block: TPSBlockInfo;
+
+ iOldWithCount: Integer;
+ iOldTryCount: Integer;
+ iOldExFnlCount: Integer;
+
+ begin
+ Result := False;
+ Debug_WriteLine(BlockInfo);
+ FParser.Next;
+ OldCo := FContinueOffsets;
+ FContinueOffsets := TPSList.Create;
+ OldBO := FBreakOffsets;
+ FBreakOffsets := TPSList.Create;
+ vin := AllocStackReg(at2ut(FDefaultBoolType));
+ SPos := Length(BlockInfo.Proc.Data);
+ Block := TPSBlockInfo.Create(BlockInfo);
+ Block.SubType := tRepeat;
+
+ iOldWithCount := FWithCount;
+ FWithCount := 0;
+ iOldTryCount := FTryCount;
+ FTryCount := 0;
+ iOldExFnlCount := FExceptFinallyCount;
+ FExceptFinallyCount := 0;
+
+ if not ProcessSub(Block) then
+ begin
+ Block.Free;
+ FBreakOffsets.Free;
+ FContinueOffsets.Free;
+ FContinueOffsets := OldCO;
+ FBreakOffsets := OldBo;
+
+ FWithCount := iOldWithCount;
+ FTryCount := iOldTryCount;
+ FExceptFinallyCount := iOldExFnlCount;
+
+ vin.Free;
+ exit;
+ end;
+ Block.Free;
+ FParser.Next; //cstii_until
+ vout := calc(CSTI_Semicolon);
+ if vout = nil then
+ begin
+ FBreakOffsets.Free;
+ FContinueOffsets.Free;
+ FContinueOffsets := OldCO;
+ FBreakOffsets := OldBo;
+
+ FWithCount := iOldWithCount;
+ FTryCount := iOldTryCount;
+ FExceptFinallyCount := iOldExFnlCount;
+
+ vin.Free;
+ exit;
+ end;
+ CPos := Length(BlockInfo.Proc.Data);
+ if not WriteCalculation(vout, vin) then
+ begin
+ vout.Free;
+ vin.Free;
+ FBreakOffsets.Free;
+ FContinueOffsets.Free;
+ FContinueOffsets := OldCO;
+ FBreakOffsets := OldBo;
+
+ FWithCount := iOldWithCount;
+ FTryCount := iOldTryCount;
+ FExceptFinallyCount := iOldExFnlCount;
+
+ exit;
+ end;
+ vout.Free;
+ BlockWriteByte(BlockInfo, Cm_CNG);
+ BlockWriteLong(BlockInfo, $12345678);
+ EPos := Length(BlockInfo. Proc.Data);
+ if not WriteOutRec(vin, False) then
+ begin
+ MakeError('', ecInternalError, '00016');
+ vin.Free;
+ FBreakOffsets.Free;
+ FContinueOffsets.Free;
+ FContinueOffsets := OldCO;
+ FBreakOffsets := OldBo;
+
+ FWithCount := iOldWithCount;
+ FTryCount := iOldTryCount;
+ FExceptFinallyCount := iOldExFnlCount;
+
+ exit;
+ end;
+ {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
+ unaligned(Longint((@BlockInfo.Proc.Data[EPos - 3])^)) := Longint(SPos) -
+ Length(BlockInfo.Proc.Data);
+ {$else}
+ Longint((@BlockInfo.Proc.Data[EPos - 3])^) := Longint(SPos) -
+ Length(BlockInfo.Proc.Data);
+ {$endif}
+ for i := 0 to FBreakOffsets.Count -1 do
+ begin
+ EPos := Cardinal(FBreakOffsets[I]);
+ {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
+ unaligned(Longint((@BlockInfo.Proc.Data[EPos - 3])^)) := Length(BlockInfo. Proc.Data) - Longint(EPos);
+ {$else}
+ Longint((@BlockInfo.Proc.Data[EPos - 3])^) := Length(BlockInfo. Proc.Data) - Longint(EPos);
+ {$endif}
+ end;
+ for i := 0 to FContinueOffsets.Count -1 do
+ begin
+ EPos := Cardinal(FContinueOffsets[I]);
+ {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
+ unaligned(Longint((@BlockInfo.Proc.Data[EPos - 3])^)) := Longint(CPos) - Longint(EPos);
+ {$else}
+ Longint((@BlockInfo.Proc.Data[EPos - 3])^) := Longint(CPos) - Longint(EPos);
+ {$endif}
+ end;
+ FBreakOffsets.Free;
+ FContinueOffsets.Free;
+ FContinueOffsets := OldCO;
+ FBreakOffsets := OldBo;
+
+ FWithCount := iOldWithCount;
+ FTryCount := iOldTryCount;
+ FExceptFinallyCount := iOldExFnlCount;
+
+ vin.Free;
+ if HasInvalidJumps(SPos, Length(BlockInfo. Proc.Data)) then
+ begin
+ Result := False;
+ exit;
+ end;
+ Result := True;
+ end; {ProcessRepeat}
+
+ function ProcessIf: Boolean;
+ var
+ vout, vin: TPSValue;
+ SPos, EPos: Cardinal;
+ Block: TPSBlockInfo;
+ begin
+ Result := False;
+ Debug_WriteLine(BlockInfo);
+ FParser.Next;
+ vout := calc(CSTII_Then);
+ if vout = nil then
+ exit;
+ if FParser.CurrTokenId <> CSTII_Then then
+ begin
+ vout.Free;
+ MakeError('', ecThenExpected, '');
+ exit;
+ end;
+ vin := AllocStackReg(at2ut(FDefaultBoolType));
+ if not WriteCalculation(vout, vin) then
+ begin
+ vout.Free;
+ vin.Free;
+ exit;
+ end;
+ vout.Free;
+ BlockWriteByte(BlockInfo, cm_sf);
+ if not WriteOutRec(vin, False) then
+ begin
+ MakeError('', ecInternalError, '00018');
+ vin.Free;
+ exit;
+ end;
+ BlockWriteByte(BlockInfo, 1);
+ vin.Free;
+ BlockWriteByte(BlockInfo, cm_fg);
+ BlockWriteLong(BlockInfo, $12345678);
+ SPos := Length(BlockInfo.Proc.Data);
+ FParser.Next; // skip then
+ Block := TPSBlockInfo.Create(BlockInfo);
+ Block.SubType := tifOneliner;
+ if not ProcessSub(Block) then
+ begin
+ Block.Free;
+ exit;
+ end;
+ Block.Free;
+ if FParser.CurrTokenId = CSTII_Else then
+ begin
+ BlockWriteByte(BlockInfo, Cm_G);
+ BlockWriteLong(BlockInfo, $12345678);
+ EPos := Length(BlockInfo.Proc.Data);
+ {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
+ unaligned(Longint((@BlockInfo.Proc.Data[SPos - 3])^)) := Length(BlockInfo.Proc.Data) - Longint(SPos);
+ {$else}
+ Longint((@BlockInfo.Proc.Data[SPos - 3])^) := Length(BlockInfo.Proc.Data) - Longint(SPos);
+ {$endif}
+ FParser.Next;
+ Block := TPSBlockInfo.Create(BlockInfo);
+ Block.SubType := tOneLiner;
+ if not ProcessSub(Block) then
+ begin
+ Block.Free;
+ exit;
+ end;
+ Block.Free;
+ {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
+ unaligned(Longint((@BlockInfo.Proc.Data[EPos - 3])^)) := Length(BlockInfo.Proc.Data) - Longint(EPos);
+ {$else}
+ Longint((@BlockInfo.Proc.Data[EPos - 3])^) := Length(BlockInfo.Proc.Data) - Longint(EPos);
+ {$endif}
+ end
+ else
+ begin
+ {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
+ unaligned(Longint((@BlockInfo.Proc.Data[SPos - 3])^)) := Length(BlockInfo.Proc.Data) - Longint(SPos) + 5 - 5;
+ {$else}
+ Longint((@BlockInfo.Proc.Data[SPos - 3])^) := Length(BlockInfo.Proc.Data) - Longint(SPos) + 5 - 5;
+ {$endif}
+ end;
+ Result := True;
+ end; {ProcessIf}
+
+ function _ProcessLabel: Longint; {0 = failed; 1 = successful; 2 = no label}
+ var
+ I, H: Longint;
+ s: tbtString;
+ begin
+ h := MakeHash(FParser.GetToken);
+ for i := 0 to BlockInfo.Proc.FLabels.Count -1 do
+ begin
+ s := BlockInfo.Proc.FLabels[I];
+ delete(s, 1, 4);
+ if Longint((@s[1])^) = h then
+ begin
+ delete(s, 1, 4);
+ if s = FParser.GetToken then
+ begin
+ s := BlockInfo.Proc.FLabels[I];
+ Cardinal((@s[1])^) := Length(BlockInfo.Proc.Data);
+ BlockInfo.Proc.FLabels[i] := s;
+ FParser.Next;
+ if fParser.CurrTokenId = CSTI_Colon then
+ begin
+ Result := 1;
+ FParser.Next;
+ exit;
+ end else begin
+ MakeError('', ecColonExpected, '');
+ Result := 0;
+ Exit;
+ end;
+ end;
+ end;
+ end;
+ result := 2;
+ end;
+
+ function ProcessIdentifier: Boolean;
+ var
+ vin, vout: TPSValue;
+ begin
+ Result := False;
+ Debug_WriteLine(BlockInfo);
+ vin := Calc(CSTI_Assignment);//GetIdentifier(2);
+ if vin <> nil then
+ begin
+ if vin is TPSValueVar then
+ begin // assignment needed
+ if FParser.CurrTokenId <> CSTI_Assignment then
+ begin
+ MakeError('', ecAssignmentExpected, '');
+ vin.Free;
+ exit;
+ end;
+ FParser.Next;
+ vout := calc(CSTI_Semicolon);
+ if vout = nil then
+ begin
+ vin.Free;
+ exit;
+ end;
+ if not WriteCalculation(vout, vin) then
+ begin
+ vin.Free;
+ vout.Free;
+ exit;
+ end;
+ vin.Free;
+ vout.Free;
+ end else if vin is TPSValueProc then
+ begin
+ Result := _ProcessFunction(TPSValueProc(vin), nil);
+ vin.Free;
+ Exit;
+ end else
+ begin
+ MakeError('', ecInternalError, '20');
+ vin.Free;
+ REsult := False;
+ exit;
+ end;
+ end
+ else
+ begin
+ Result := False;
+ exit;
+ end;
+ Result := True;
+ end; {ProcessIdentifier}
+
+ function ProcessCase: Boolean;
+ var
+ V1, V2, TempRec, Val, CalcItem: TPSValue;
+ p: TPSBinValueOp;
+ SPos, CurrP: Cardinal;
+ I: Longint;
+ EndReloc: TPSList;
+ Block: TPSBlockInfo;
+
+ function NewRec(val: TPSValue): TPSValueReplace;
+ begin
+ Result := TPSValueReplace.Create;
+ Result.SetParserPos(FParser);
+ Result.FNewValue := Val;
+ Result.FreeNewValue := False;
+ end;
+
+ function Combine(v1, v2: TPSValue; Op: TPSBinOperatorType): TPSValue;
+ begin
+ if V1 = nil then
+ begin
+ Result := v2;
+ end else if v2 = nil then
+ begin
+ Result := V1;
+ end else
+ begin
+ Result := TPSBinValueOp.Create;
+ TPSBinValueOp(Result).FType := FDefaultBoolType;
+ TPSBinValueOp(Result).Operator := Op;
+ Result.SetParserPos(FParser);
+ TPSBinValueOp(Result).FVal1 := V1;
+ TPSBinValueOp(Result).FVal2 := V2;
+ end;
+ end;
+
+
+ begin
+ Debug_WriteLine(BlockInfo);
+ FParser.Next;
+ Val := calc(CSTII_of);
+ if Val = nil then
+ begin
+ ProcessCase := False;
+ exit;
+ end; {if}
+ if FParser.CurrTokenId <> CSTII_Of then
+ begin
+ MakeError('', ecOfExpected, '');
+ val.Free;
+ ProcessCase := False;
+ exit;
+ end; {if}
+ FParser.Next;
+ TempRec := AllocStackReg(GetTypeNo(BlockInfo, Val));
+ if not WriteCalculation(Val, TempRec) then
+ begin
+ TempRec.Free;
+ val.Free;
+ ProcessCase := False;
+ exit;
+ end; {if}
+ val.Free;
+ EndReloc := TPSList.Create;
+ CalcItem := AllocStackReg(at2ut(FDefaultBoolType));
+ SPos := Length(BlockInfo.Proc.Data);
+ repeat
+ V1 := nil;
+ while true do
+ begin
+ Val := calc(CSTI_Colon);
+ if (Val = nil) then
+ begin
+ V1.Free;
+ CalcItem.Free;
+ TempRec.Free;
+ EndReloc.Free;
+ ProcessCase := False;
+ exit;
+ end; {if}
+ if fParser.CurrTokenID = CSTI_TwoDots then begin
+ FParser.Next;
+ V2 := Calc(CSTI_colon);
+ if V2 = nil then begin
+ V1.Free;
+ CalcItem.Free;
+ TempRec.Free;
+ EndReloc.Free;
+ ProcessCase := False;
+ Val.Free;
+ exit;
+ end;
+ p := TPSBinValueOp.Create;
+ p.SetParserPos(FParser);
+ p.Operator := otGreaterEqual;
+ p.aType := at2ut(FDefaultBoolType);
+ p.Val2 := Val;
+ p.Val1 := NewRec(TempRec);
+ Val := p;
+ p := TPSBinValueOp.Create;
+ p.SetParserPos(FParser);
+ p.Operator := otLessEqual;
+ p.aType := at2ut(FDefaultBoolType);
+ p.Val2 := V2;
+ p.Val1 := NewRec(TempRec);
+ P := TPSBinValueOp(Combine(Val,P, otAnd));
+ end else begin
+ p := TPSBinValueOp.Create;
+ p.SetParserPos(FParser);
+ p.Operator := otEqual;
+ p.aType := at2ut(FDefaultBoolType);
+ p.Val1 := Val;
+ p.Val2 := NewRec(TempRec);
+ end;
+ V1 := Combine(V1, P, otOr);
+ if FParser.CurrTokenId = CSTI_Colon then Break;
+ if FParser.CurrTokenID <> CSTI_Comma then
+ begin
+ MakeError('', ecColonExpected, '');
+ V1.Free;
+ CalcItem.Free;
+ TempRec.Free;
+ EndReloc.Free;
+ ProcessCase := False;
+ exit;
+ end;
+ FParser.Next;
+ end;
+ FParser.Next;
+ if not WriteCalculation(V1, CalcItem) then
+ begin
+ CalcItem.Free;
+ v1.Free;
+ EndReloc.Free;
+ ProcessCase := False;
+ exit;
+ end;
+ v1.Free;
+ BlockWriteByte(BlockInfo, Cm_CNG);
+ BlockWriteLong(BlockInfo, $12345678);
+ CurrP := Length(BlockInfo.Proc.Data);
+ WriteOutRec(CalcItem, False);
+ Block := TPSBlockInfo.Create(BlockInfo);
+ Block.SubType := tifOneliner;
+ if not ProcessSub(Block) then
+ begin
+ Block.Free;
+ CalcItem.Free;
+ TempRec.Free;
+ EndReloc.Free;
+ ProcessCase := False;
+ exit;
+ end;
+ Block.Free;
+ BlockWriteByte(BlockInfo, Cm_G);
+ BlockWriteLong(BlockInfo, $12345678);
+ EndReloc.Add(Pointer(Length(BlockInfo.Proc.Data)));
+ {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
+ unaligned(Cardinal((@BlockInfo.Proc.Data[CurrP - 3])^)) := Cardinal(Length(BlockInfo.Proc.Data)) - CurrP - 5;
+ {$else}
+ Cardinal((@BlockInfo.Proc.Data[CurrP - 3])^) := Cardinal(Length(BlockInfo.Proc.Data)) - CurrP - 5;
+ {$endif}
+ if FParser.CurrTokenID = CSTI_Semicolon then FParser.Next;
+ if FParser.CurrTokenID = CSTII_Else then
+ begin
+ FParser.Next;
+ Block := TPSBlockInfo.Create(BlockInfo);
+ Block.SubType := tOneliner;
+ if not ProcessSub(Block) then
+ begin
+ Block.Free;
+ CalcItem.Free;
+ TempRec.Free;
+ EndReloc.Free;
+ ProcessCase := False;
+ exit;
+ end;
+ Block.Free;
+ if FParser.CurrTokenID = CSTI_Semicolon then FParser.Next;
+ if FParser.CurrtokenId <> CSTII_End then
+ begin
+ MakeError('', ecEndExpected, '');
+ CalcItem.Free;
+ TempRec.Free;
+ EndReloc.Free;
+ ProcessCase := False;
+ exit;
+ end;
+ end;
+ until FParser.CurrTokenID = CSTII_End;
+ FParser.Next;
+ for i := 0 to EndReloc.Count -1 do
+ begin
+ {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
+ unaligned(Cardinal((@BlockInfo.Proc.Data[Cardinal(EndReloc[I])- 3])^)) := Cardinal(Length(BlockInfo.Proc.Data)) - Cardinal(EndReloc[I]);
+ {$else}
+ Cardinal((@BlockInfo.Proc.Data[Cardinal(EndReloc[I])- 3])^) := Cardinal(Length(BlockInfo.Proc.Data)) - Cardinal(EndReloc[I]);
+ {$endif}
+ end;
+ CalcItem.Free;
+ TempRec.Free;
+ EndReloc.Free;
+ if FContinueOffsets <> nil then
+ begin
+ for i := 0 to FContinueOffsets.Count -1 do
+ begin
+ if Cardinal(FContinueOffsets[i]) >= SPos then
+ begin
+ {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
+ unaligned(Byte((@BlockInfo.Proc.Data[Longint(FContinueOffsets[i]) - 4])^)) := Cm_P2G;
+ {$else}
+ Byte((@BlockInfo.Proc.Data[Longint(FContinueOffsets[i]) - 4])^) := Cm_P2G;
+ {$endif}
+ end;
+ end;
+ end;
+ if FBreakOffsets <> nil then
+ begin
+ for i := 0 to FBreakOffsets.Count -1 do
+ begin
+ if Cardinal(FBreakOffsets[i]) >= SPos then
+ begin
+ {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
+ unaligned(Byte((@BlockInfo.Proc.Data[Longint(FBreakOffsets[i]) - 4])^)) := Cm_P2G;
+ {$else}
+ Byte((@BlockInfo.Proc.Data[Longint(FBreakOffsets[i]) - 4])^) := Cm_P2G;
+ {$endif}
+ end;
+ end;
+ end;
+ if HasInvalidJumps(SPos, Length(BlockInfo.Proc.Data)) then
+ begin
+ Result := False;
+ exit;
+ end;
+ Result := True;
+ end; {ProcessCase}
+ function ProcessGoto: Boolean;
+ var
+ I, H: Longint;
+ s: tbtString;
+ begin
+ Debug_WriteLine(BlockInfo);
+ FParser.Next;
+ h := MakeHash(FParser.GetToken);
+ for i := 0 to BlockInfo.Proc.FLabels.Count -1 do
+ begin
+ s := BlockInfo.Proc.FLabels[I];
+ delete(s, 1, 4);
+ if Longint((@s[1])^) = h then
+ begin
+ delete(s, 1, 4);
+ if s = FParser.GetToken then
+ begin
+ FParser.Next;
+ BlockWriteByte(BlockInfo, Cm_G);
+ BlockWriteLong(BlockInfo, $12345678);
+ BlockInfo.Proc.FGotos.Add(PS_mi2s(length(BlockInfo.Proc.Data))+PS_mi2s(i));
+ Result := True;
+ exit;
+ end;
+ end;
+ end;
+ MakeError('', ecUnknownIdentifier, FParser.OriginalToken);
+ Result := False;
+ end; {ProcessGoto}
+
+ function ProcessWith: Boolean;
+ var
+ Block: TPSBlockInfo;
+ aVar, aReplace: TPSValue;
+ aType: TPSType;
+
+ iStartOffset: Integer;
+
+ tmp: TPSValue;
+ begin
+ Debug_WriteLine(BlockInfo);
+ Block := TPSBlockInfo.Create(BlockInfo);
+ Block.SubType := tOneLiner;
+
+ FParser.Next;
+ repeat
+ aVar := GetIdentifier(0);
+ if aVar = nil then
+ begin
+ block.Free;
+ Result := False;
+ exit;
+ end;
+ AType := GetTypeNo(BlockInfo, aVar);
+ if (AType = nil) or ((aType.BaseType <> btRecord) and (aType.BaseType <> btClass)) then
+ begin
+ MakeError('', ecClassTypeExpected, '');
+ Block.Free;
+ Result := False;
+ exit;
+ end;
+
+ aReplace := TPSValueReplace.Create;
+ aReplace.SetParserPos(FParser);
+ TPSValueReplace(aReplace).FreeOldValue := True;
+ TPSValueReplace(aReplace).FreeNewValue := True;
+ TPSValueReplace(aReplace).OldValue := aVar;
+
+ //if aVar.InheritsFrom(TPSVar) then TPSVar(aVar).Use;
+ tmp := AllocPointer(GetTypeNo(BlockInfo, aVar));
+ TPSProcVar(BlockInfo.Proc.ProcVars[TPSValueAllocatedStackVar(tmp).LocalVarNo]).Use;
+ PreWriteOutRec(tmp,GetTypeNo(BlockInfo, tmp));
+ PreWriteOutRec(aVar,GetTypeNo(BlockInfo, aVar));
+ BlockWriteByte(BlockInfo, cm_sp);
+ WriteOutRec(tmp, false);
+ WriteOutRec(aVar, false);
+ TPSValueReplace(aReplace).NewValue := tmp;
+
+
+
+ Block.WithList.Add(aReplace);
+
+ if FParser.CurrTokenID = CSTII_do then
+ begin
+ FParser.Next;
+ Break;
+ end else
+ if FParser.CurrTokenId <> CSTI_Comma then
+ begin
+ MakeError('', ecDoExpected, '');
+ Block.Free;
+ Result := False;
+ exit;
+ end;
+ FParser.Next;
+ until False;
+
+
+ inc(FWithCount);
+
+ iStartOffset := Length(Block.Proc.Data);
+
+ if not (ProcessSub(Block) and (not HasInvalidJumps(iStartOffset,Length(BlockInfo.Proc.Data) + 1)) ) then
+ begin
+ dec(FWithCount);
+ Block.Free;
+ Result := False;
+ exit;
+ end;
+ dec(FWithCount);
+
+ AfterWriteOutRec(aVar);
+ AfterWriteOutRec(tmp);
+ Block.Free;
+ Result := True;
+ end;
+
+ function ProcessTry: Boolean;
+ var
+ FStartOffset: Cardinal;
+ iBlockStartOffset: Integer;
+ Block: TPSBlockInfo;
+ begin
+ FParser.Next;
+ BlockWriteByte(BlockInfo, cm_puexh);
+ FStartOffset := Length(BlockInfo.Proc.Data) + 1;
+ BlockWriteLong(BlockInfo, InvalidVal);
+ BlockWriteLong(BlockInfo, InvalidVal);
+ BlockWriteLong(BlockInfo, InvalidVal);
+ BlockWriteLong(BlockInfo, InvalidVal);
+ Block := TPSBlockInfo.Create(BlockInfo);
+ Block.SubType := tTry;
+ inc(FTryCount);
+ if ProcessSub(Block) and (not HasInvalidJumps(FStartOffset,Length(BlockInfo.Proc.Data) + 1)) then
+ begin
+ dec(FTryCount);
+ Block.Free;
+ BlockWriteByte(BlockInfo, cm_poexh);
+ BlockWriteByte(BlockInfo, 0);
+ if FParser.CurrTokenID = CSTII_Except then
+ begin
+ FParser.Next;
+ Cardinal((@BlockInfo.Proc.Data[FStartOffset + 4])^) := Cardinal(Length(BlockInfo.Proc.Data)) - FStartOffset - 15;
+ iBlockStartOffset := Length(BlockInfo.Proc.Data) ;
+ Block := TPSBlockInfo.Create(BlockInfo);
+ Block.SubType := tTryEnd;
+ inc(FExceptFinallyCount);
+ if ProcessSub(Block) and (not HasInvalidJumps(iBlockStartOffset,Length(BlockInfo.Proc.Data) + 1)) then
+ begin
+ dec(FExceptFinallyCount);
+ Block.Free;
+ BlockWriteByte(BlockInfo, cm_poexh);
+ BlockWriteByte(BlockInfo, 2);
+ if FParser.CurrTokenId = CSTII_Finally then
+ begin
+ Cardinal((@BlockInfo.Proc.Data[FStartOffset + 8])^) := Cardinal(Length(BlockInfo.Proc.Data)) - FStartOffset - 15;
+ iBlockStartOffset := Length(BlockInfo.Proc.Data) ;
+ Block := TPSBlockInfo.Create(BlockInfo);
+ Block.SubType := tTryEnd;
+ FParser.Next;
+ inc(FExceptFinallyCount);
+ if ProcessSub(Block) and (not HasInvalidJumps(iBlockStartOffset,Length(BlockInfo.Proc.Data) + 1)) then
+ begin
+ dec(FExceptFinallyCount);
+ Block.Free;
+ if FParser.CurrTokenId = CSTII_End then
+ begin
+ BlockWriteByte(BlockInfo, cm_poexh);
+ BlockWriteByte(BlockInfo, 3);
+ end else begin
+ MakeError('', ecEndExpected, '');
+ Result := False;
+ exit;
+ end;
+ end else
+ begin
+ Block.Free;
+ Result := False;
+ dec(FExceptFinallyCount);
+ exit;
+ end;
+ end else if FParser.CurrTokenID <> CSTII_End then
+ begin
+ MakeError('', ecEndExpected, '');
+ Result := False;
+ exit;
+ end;
+ FParser.Next;
+ end else
+ begin
+ Block.Free;
+ Result := False;
+ dec(FExceptFinallyCount);
+ exit;
+ end;
+ end else if FParser.CurrTokenId = CSTII_Finally then
+ begin
+ FParser.Next;
+ Cardinal((@BlockInfo.Proc.Data[FStartOffset])^) := Cardinal(Length(BlockInfo.Proc.Data)) - FStartOffset - 15;
+ iBlockStartOffset := Length(BlockInfo.Proc.Data) ;
+ Block := TPSBlockInfo.Create(BlockInfo);
+ Block.SubType := tTryEnd;
+ inc(FExceptFinallyCount);
+ if ProcessSub(Block) and (not HasInvalidJumps(iBlockStartOffset,Length(BlockInfo.Proc.Data) + 1)) then
+ begin
+ dec(FExceptFinallyCount);
+ Block.Free;
+ BlockWriteByte(BlockInfo, cm_poexh);
+ BlockWriteByte(BlockInfo, 1);
+ if FParser.CurrTokenId = CSTII_Except then
+ begin
+ Cardinal((@BlockInfo.Proc.Data[FStartOffset + 4])^) := Cardinal(Length(BlockInfo.Proc.Data)) - FStartOffset - 15;
+ iBlockStartOffset := Length(BlockInfo.Proc.Data) ;
+ FParser.Next;
+ Block := TPSBlockInfo.Create(BlockInfo);
+ Block.SubType := tTryEnd;
+ inc(FExceptFinallyCount);
+ if ProcessSub(Block) and (not HasInvalidJumps(iBlockStartOffset,Length(BlockInfo.Proc.Data) + 1)) then
+ begin
+ dec(FExceptFinallyCount);
+ Block.Free;
+ if FParser.CurrTokenId = CSTII_End then
+ begin
+ BlockWriteByte(BlockInfo, cm_poexh);
+ BlockWriteByte(BlockInfo, 2);
+ end else begin
+ MakeError('', ecEndExpected, '');
+ Result := False;
+ exit;
+ end;
+ end else
+ begin
+ Block.Free;
+ Result := False;
+ dec(FExceptFinallyCount);
+ exit;
+ end;
+ end else if FParser.CurrTokenID <> CSTII_End then
+ begin
+ MakeError('', ecEndExpected, '');
+ Result := False;
+ exit;
+ end;
+ FParser.Next;
+ end else
+ begin
+ Block.Free;
+ Result := False;
+ dec(FExceptFinallyCount);
+ exit;
+ end;
+ end;
+ end else
+ begin
+ Block.Free;
+ Result := False;
+ dec(FTryCount);
+ exit;
+ end;
+ Cardinal((@BlockInfo.Proc.Data[FStartOffset + 12])^) := Cardinal(Length(BlockInfo.Proc.Data)) - FStartOffset - 15;
+ Result := True;
+ end; {ProcessTry}
+
+var
+ i: Integer;
+ Block: TPSBlockInfo;
+
+begin
+ ProcessSub := False;
+ if (BlockInfo.SubType = tProcBegin) or (BlockInfo.SubType= tMainBegin) or
+{$IFDEF PS_USESSUPPORT}
+ (BlockInfo.SubType = tUnitInit) or (BlockInfo.SubType= tUnitFinish) or // NvdS
+{$endif}
+ (BlockInfo.SubType= tSubBegin) then
+ begin
+ FParser.Next; // skip CSTII_Begin
+ end;
+ while True do
+ begin
+ case FParser.CurrTokenId of
+ CSTII_Goto:
+ begin
+ if not ProcessGoto then
+ Exit;
+ if (BlockInfo.SubType = tifOneliner) or (BlockInfo.SubType = TOneLiner) then
+ break;
+ end;
+ CSTII_With:
+ begin
+ if not ProcessWith then
+ Exit;
+ if (BlockInfo.SubType = tifOneliner) or (BlockInfo.SubType = TOneLiner) then
+ break;
+ end;
+ CSTII_Try:
+ begin
+ if not ProcessTry then
+ Exit;
+ if (BlockInfo.SubType = tifOneliner) or (BlockInfo.SubType = TOneLiner) then
+ break;
+ end;
+ CSTII_Finally, CSTII_Except:
+ begin
+ if (BlockInfo.SubType = tTry) or (BlockInfo.SubType = tTryEnd) then
+ Break
+ else
+ begin
+ MakeError('', ecEndExpected, '');
+ Exit;
+ end;
+ end;
+ CSTII_Begin:
+ begin
+ Block := TPSBlockInfo.Create(BlockInfo);
+ Block.SubType := tSubBegin;
+ if not ProcessSub(Block) then
+ begin
+ Block.Free;
+ Exit;
+ end;
+ Block.Free;
+
+ FParser.Next; // skip END
+ if (BlockInfo.SubType = tifOneliner) or (BlockInfo.SubType = TOneLiner) then
+ break;
+ end;
+ CSTI_Semicolon:
+ begin
+
+ if (BlockInfo.SubType = tifOneliner) or (BlockInfo.SubType = TOneLiner) then
+ break
+ else FParser.Next;
+ end;
+ CSTII_until:
+ begin
+ Debug_WriteLine(BlockInfo);
+ if BlockInfo.SubType = tRepeat then
+ begin
+ break;
+ end
+ else
+ begin
+ MakeError('', ecIdentifierExpected, '');
+ exit;
+ end;
+ if (BlockInfo.SubType = tifOneliner) or (BlockInfo.SubType = TOneLiner) then
+ break;
+ end;
+ CSTII_Else:
+ begin
+ if BlockInfo.SubType = tifOneliner then
+ break
+ else
+ begin
+ MakeError('', ecIdentifierExpected, '');
+ exit;
+ end;
+ end;
+ CSTII_repeat:
+ begin
+ if not ProcessRepeat then
+ exit;
+ if (BlockInfo.SubType = tifOneliner) or (BlockInfo.SubType = TOneLiner) then
+ break;
+ end;
+ CSTII_For:
+ begin
+ if not ProcessFor then
+ exit;
+ if (BlockInfo.SubType = tifOneliner) or (BlockInfo.SubType = TOneLiner) then
+ break;
+ end;
+ CSTII_While:
+ begin
+ if not ProcessWhile then
+ exit;
+ if (BlockInfo.SubType = tifOneliner) or (BlockInfo.SubType = TOneLiner) then
+ break;
+ end;
+ CSTII_Exit:
+ begin
+ Debug_WriteLine(BlockInfo);
+ BlockWriteByte(BlockInfo, Cm_R);
+ FParser.Next;
+ if (BlockInfo.SubType = tifOneliner) or (BlockInfo.SubType = TOneLiner) then
+ break;
+ end;
+ CSTII_Case:
+ begin
+ if not ProcessCase then
+ exit;
+ if (BlockInfo.SubType = tifOneliner) or (BlockInfo.SubType = TOneLiner) then
+ break;
+ end;
+ CSTII_If:
+ begin
+ if not ProcessIf then
+ exit;
+ if (BlockInfo.SubType = tifOneliner) or (BlockInfo.SubType = TOneLiner) then
+ break;
+ end;
+ CSTI_OpenRound,
+ CSTI_Identifier:
+ begin
+ case _ProcessLabel of
+ 0: Exit;
+ 1: ;
+ else
+ begin
+ if FParser.GetToken = 'BREAK' then
+ begin
+ if FBreakOffsets = nil then
+ begin
+ MakeError('', ecNotInLoop, '');
+ exit;
+ end;
+ for i := 0 to FExceptFinallyCount - 1 do
+ begin
+ BlockWriteByte(BlockInfo, cm_poexh);
+ BlockWriteByte(BlockInfo, 1);
+ end;
+
+ for i := 0 to FTryCount - 1 do
+ begin
+ BlockWriteByte(BlockInfo, cm_poexh);
+ BlockWriteByte(BlockInfo, 0);
+ BlockWriteByte(BlockInfo, cm_poexh);
+ BlockWriteByte(BlockInfo, 1);
+ end;
+
+ for i := 0 to FWithCount - 1 do
+ BlockWriteByte(BlockInfo,cm_po);
+ BlockWriteByte(BlockInfo, Cm_G);
+ BlockWriteLong(BlockInfo, $12345678);
+ FBreakOffsets.Add(Pointer(Length(BlockInfo.Proc.Data)));
+ FParser.Next;
+ if (BlockInfo.SubType= tifOneliner) or (BlockInfo.SubType = TOneLiner) then
+ break;
+ end else if FParser.GetToken = 'CONTINUE' then
+ begin
+ if FBreakOffsets = nil then
+ begin
+ MakeError('', ecNotInLoop, '');
+ exit;
+ end;
+ for i := 0 to FExceptFinallyCount - 1 do
+ begin
+ BlockWriteByte(BlockInfo, cm_poexh);
+ BlockWriteByte(BlockInfo, 1);
+ end;
+
+ for i := 0 to FTryCount - 1 do
+ begin
+ BlockWriteByte(BlockInfo, cm_poexh);
+ BlockWriteByte(BlockInfo, 0);
+ BlockWriteByte(BlockInfo, cm_poexh);
+ BlockWriteByte(BlockInfo, 1);
+ end;
+
+ for i := 0 to FWithCount - 1 do
+ BlockWriteByte(BlockInfo,cm_po);
+ BlockWriteByte(BlockInfo, Cm_G);
+ BlockWriteLong(BlockInfo, $12345678);
+ FContinueOffsets.Add(Pointer(Length(BlockInfo.Proc.Data)));
+ FParser.Next;
+ if (BlockInfo.SubType = tifOneliner) or (BlockInfo.SubType = TOneLiner) then
+ break;
+ end else
+ if not ProcessIdentifier then
+ exit;
+ if (BlockInfo.SubType = tifOneliner) or (BlockInfo.SubType = TOneLiner) then
+ break;
+ end;
+ end; {case}
+
+ if (BlockInfo.SubType = tifOneliner) or (BlockInfo.SubType = TOneLiner) then
+ break;
+
+ end;
+ {$IFDEF PS_USESSUPPORT}
+ CSTII_Finalization: //NvdS
+ begin //
+ if (BlockInfo.SubType = tUnitInit) then //
+ begin //
+ break; //
+ end //
+ else //
+ begin //
+ MakeError('', ecIdentifierExpected, ''); //
+ exit; //
+ end; //
+ end; //nvds
+ {$endif}
+ CSTII_End:
+ begin
+ if (BlockInfo.SubType = tTryEnd) or (BlockInfo.SubType = tMainBegin) or
+ (BlockInfo.SubType = tSubBegin) or (BlockInfo.SubType = tifOneliner) or
+ (BlockInfo.SubType = tProcBegin) or (BlockInfo.SubType = TOneLiner)
+ {$IFDEF PS_USESSUPPORT} or (BlockInfo.SubType = tUnitInit) or (BlockInfo.SubType = tUnitFinish) {$endif} then //nvds
+ begin
+ break;
+ end
+ else
+ begin
+ MakeError('', ecIdentifierExpected, '');
+ exit;
+ end;
+ end;
+ CSTI_EOF:
+ begin
+ MakeError('', ecUnexpectedEndOfFile, '');
+ exit;
+ end;
+ else
+ begin
+ MakeError('', ecIdentifierExpected, '');
+ exit;
+ end;
+ end;
+ end;
+ if (BlockInfo.SubType = tMainBegin) or (BlockInfo.SubType = tProcBegin)
+ {$IFDEF PS_USESSUPPORT} or (BlockInfo.SubType = tUnitInit) or (BlockInfo.SubType = tUnitFinish) {$endif} then //nvds
+ begin
+ Debug_WriteLine(BlockInfo);
+ BlockWriteByte(BlockInfo, Cm_R);
+ {$IFDEF PS_USESSUPPORT}
+ if FParser.CurrTokenId = CSTII_End then //nvds
+ begin
+ {$endif}
+ FParser.Next; // skip end
+ if ((BlockInfo.SubType = tMainBegin)
+ {$IFDEF PS_USESSUPPORT} or (BlockInfo.SubType = tUnitInit) or (BlockInfo.SubType = tUnitFinish){$endif}) //nvds
+ and (FParser.CurrTokenId <> CSTI_Period) then
+ begin
+ MakeError('', ecPeriodExpected, '');
+ exit;
+ end;
+ if (BlockInfo.SubType = tProcBegin) and (FParser.CurrTokenId <> CSTI_Semicolon) then
+ begin
+ MakeError('', ecSemicolonExpected, '');
+ exit;
+ end;
+ FParser.Next;
+ {$IFDEF PS_USESSUPPORT}
+ end; //nvds
+ {$endif}
+ end
+ else if (BlockInfo.SubType = tifOneliner) or (BlockInfo.SubType = TOneLiner) then
+ begin
+ if (FParser.CurrTokenID <> CSTII_Else) and (FParser.CurrTokenID <> CSTII_End) then
+ if FParser.CurrTokenID <> CSTI_Semicolon then
+ begin
+ MakeError('', ecSemicolonExpected, '');
+ exit;
+ end;
+ end;
+
+ ProcessSub := True;
+end;
+procedure TPSPascalCompiler.UseProc(procdecl: TPSParametersDecl);
+var
+ i: Longint;
+begin
+ if procdecl.Result <> nil then
+ procdecl.Result := at2ut(procdecl.Result);
+ for i := 0 to procdecl.ParamCount -1 do
+ begin
+ procdecl.Params[i].aType := at2ut(procdecl.Params[i].aType);
+ end;
+end;
+
+function TPSPascalCompiler.at2ut(p: TPSType): TPSType;
+var
+ i: Longint;
+begin
+ p := GetTypeCopyLink(p);
+ if p = nil then
+ begin
+ Result := nil;
+ exit;
+ end;
+ if not p.Used then
+ begin
+ p.Use;
+ case p.BaseType of
+ btStaticArray, btArray: TPSArrayType(p).ArrayTypeNo := at2ut(TPSArrayType(p).ArrayTypeNo);
+ btRecord:
+ begin
+ for i := 0 to TPSRecordType(p).RecValCount -1 do
+ begin
+ TPSRecordType(p).RecVal(i).aType := at2ut(TPSRecordType(p).RecVal(i).aType);
+ end;
+ end;
+ btSet: TPSSetType(p).SetType := at2ut(TPSSetType(p).SetType);
+ btProcPtr:
+ begin
+ UseProc(TPSProceduralType(p).ProcDef);
+ end;
+ end;
+ p.FFinalTypeNo := FCurrUsedTypeNo;
+ inc(FCurrUsedTypeNo);
+ end;
+ Result := p;
+end;
+
+function TPSPascalCompiler.ProcessLabelForwards(Proc: TPSInternalProcedure): Boolean;
+var
+ i: Longint;
+ s, s2: tbtString;
+begin
+ for i := 0 to Proc.FLabels.Count -1 do
+ begin
+ s := Proc.FLabels[I];
+ if Longint((@s[1])^) = -1 then
+ begin
+ delete(s, 1, 8);
+ MakeError('', ecUnSetLabel, s);
+ Result := False;
+ exit;
+ end;
+ end;
+ for i := Proc.FGotos.Count -1 downto 0 do
+ begin
+ s := Proc.FGotos[I];
+ s2 := Proc.FLabels[Cardinal((@s[5])^)];
+ Cardinal((@Proc.Data[Cardinal((@s[1])^)-3])^) := Cardinal((@s2[1])^) - Cardinal((@s[1])^) ;
+ end;
+ Result := True;
+end;
+
+
+type
+ TCompilerState = (csStart, csProgram, csUnit, csUses, csInterface, csInterfaceUses, csImplementation);
+
+function TPSPascalCompiler.Compile(const s: tbtString): Boolean;
+var
+ Position: TCompilerState;
+ i: Longint;
+ {$IFDEF PS_USESSUPPORT}
+ OldFileName: tbtString;
+ OldParser : TPSPascalParser;
+ OldIsUnit : Boolean;
+ OldUnit : TPSUnit;
+ {$ENDIF}
+
+ procedure Cleanup;
+ var
+ I: Longint;
+ PT: TPSType;
+ begin
+ {$IFDEF PS_USESSUPPORT}
+ if fInCompile>1 then
+ begin
+ dec(fInCompile);
+ exit;
+ end;
+ {$ENDIF}
+
+ if @FOnBeforeCleanup <> nil then
+ FOnBeforeCleanup(Self); // no reason it actually read the result of this call
+ FGlobalBlock.Free;
+ FGlobalBlock := nil;
+
+ for I := 0 to FRegProcs.Count - 1 do
+ TObject(FRegProcs[I]).Free;
+ FRegProcs.Free;
+ for i := 0 to FConstants.Count -1 do
+ begin
+ TPSConstant(FConstants[I]).Free;
+ end;
+ Fconstants.Free;
+ for I := 0 to FVars.Count - 1 do
+ begin
+ TPSVar(FVars[I]).Free;
+ end;
+ FVars.Free;
+ FVars := nil;
+ for I := 0 to FProcs.Count - 1 do
+ TPSProcedure(FProcs[I]).Free;
+ FProcs.Free;
+ FProcs := nil;
+ for I := 0 to FTypes.Count - 1 do
+ begin
+ PT := FTypes[I];
+ pt.Free;
+ end;
+ FTypes.Free;
+
+{$IFNDEF PS_NOINTERFACES}
+ for i := FInterfaces.Count -1 downto 0 do
+ TPSInterface(FInterfaces[i]).Free;
+ FInterfaces.Free;
+{$ENDIF}
+
+ for i := FClasses.Count -1 downto 0 do
+ begin
+ TPSCompileTimeClass(FClasses[I]).Free;
+ end;
+ FClasses.Free;
+ for i := FAttributeTypes.Count -1 downto 0 do
+ begin
+ TPSAttributeType(FAttributeTypes[i]).Free;
+ end;
+ FAttributeTypes.Free;
+ FAttributeTypes := nil;
+
+ {$IFDEF PS_USESSUPPORT}
+ for I := 0 to FUnitInits.Count - 1 do //nvds
+ begin //nvds
+ TPSBlockInfo(FUnitInits[I]).free; //nvds
+ end; //nvds
+ FUnitInits.Free; //nvds
+ FUnitInits := nil; //
+ for I := 0 to FUnitFinits.Count - 1 do //nvds
+ begin //nvds
+ TPSBlockInfo(FUnitFinits[I]).free; //nvds
+ end; //nvds
+ FUnitFinits.Free; //
+ FUnitFinits := nil; //
+
+ FreeAndNil(fUnits);
+ FreeAndNil(FUses);
+ fInCompile:=0;
+ {$ENDIF}
+ end;
+
+ function MakeOutput: Boolean;
+
+ procedure WriteByte(b: Byte);
+ begin
+ FOutput := FOutput + tbtChar(b);
+ end;
+
+ procedure WriteData(const Data; Len: Longint);
+ var
+ l: Longint;
+ begin
+ if Len < 0 then Len := 0;
+ l := Length(FOutput);
+ SetLength(FOutput, l + Len);
+ Move(Data, FOutput[l + 1], Len);
+ end;
+
+ procedure WriteLong(l: Cardinal);
+ begin
+ WriteData(l, 4);
+ end;
+
+ procedure WriteVariant(p: PIfRVariant);
+ begin
+ WriteLong(p^.FType.FinalTypeNo);
+ case p.FType.BaseType of
+ btType: WriteLong(p^.ttype.FinalTypeNo);
+ {$IFNDEF PS_NOWIDESTRING}
+ btWideString:
+ begin
+ WriteLong(Length(tbtWideString(p^.twidestring)));
+ WriteData(tbtwidestring(p^.twidestring)[1], 2*Length(tbtWideString(p^.twidestring)));
+ end;
+ btUnicodeString:
+ begin
+ WriteLong(Length(tbtUnicodestring(p^.twidestring)));
+ WriteData(tbtUnicodestring(p^.twidestring)[1], 2*Length(tbtUnicodestring(p^.twidestring)));
+ end;
+ btWideChar: WriteData(p^.twidechar, 2);
+ {$ENDIF}
+ btSingle: WriteData(p^.tsingle, sizeof(tbtSingle));
+ btDouble: WriteData(p^.tsingle, sizeof(tbtDouble));
+ btExtended: WriteData(p^.tsingle, sizeof(tbtExtended));
+ btCurrency: WriteData(p^.tsingle, sizeof(tbtCurrency));
+ btChar: WriteData(p^.tchar, 1);
+ btSet:
+ begin
+ WriteData(tbtString(p^.tstring)[1], Length(tbtString(p^.tstring)));
+ end;
+ btString:
+ begin
+ WriteLong(Length(tbtString(p^.tstring)));
+ WriteData(tbtString(p^.tstring)[1], Length(tbtString(p^.tstring)));
+ end;
+ btenum:
+ begin
+ if TPSEnumType(p^.FType).HighValue <=256 then
+ WriteData( p^.tu32, 1)
+ else if TPSEnumType(p^.FType).HighValue <=65536 then
+ WriteData(p^.tu32, 2)
+ else
+ WriteData(p^.tu32, 4);
+ end;
+ bts8,btu8: WriteData(p^.tu8, 1);
+ bts16,btu16: WriteData(p^.tu16, 2);
+ bts32,btu32: WriteData(p^.tu32, 4);
+ {$IFNDEF PS_NOINT64}
+ bts64: WriteData(p^.ts64, 8);
+ {$ENDIF}
+ btProcPtr: WriteData(p^.tu32, 4);
+ {$IFDEF DEBUG}
+ else
+ asm int 3; end;
+ {$ENDIF}
+ end;
+ end;
+
+ procedure WriteAttributes(attr: TPSAttributes);
+ var
+ i, j: Longint;
+ begin
+ WriteLong(attr.Count);
+ for i := 0 to Attr.Count -1 do
+ begin
+ j := Length(attr[i].FAttribType.Name);
+ WriteLong(j);
+ WriteData(Attr[i].FAttribType.Name[1], j);
+ WriteLong(Attr[i].Count);
+ for j := 0 to Attr[i].Count -1 do
+ begin
+ WriteVariant(Attr[i][j]);
+ end;
+ end;
+ end;
+
+ procedure WriteTypes;
+ var
+ l, n: Longint;
+ bt: TPSBaseType;
+ x: TPSType;
+ s: tbtString;
+ FExportName: tbtString;
+ Items: TPSList;
+ procedure WriteTypeNo(TypeNo: Cardinal);
+ begin
+ WriteData(TypeNo, 4);
+ end;
+ begin
+ Items := TPSList.Create;
+ try
+ for l := 0 to FCurrUsedTypeNo -1 do
+ Items.Add(nil);
+ for l := 0 to FTypes.Count -1 do
+ begin
+ x := FTypes[l];
+ if x.Used then
+ Items[x.FinalTypeNo] := x;
+ end;
+ for l := 0 to Items.Count - 1 do
+ begin
+ x := Items[l];
+ if x.FExportName then
+ FExportName := x.Name
+ else
+ FExportName := '';
+ if (x.BaseType = btExtClass) and (x is TPSUndefinedClassType) then
+ begin
+ x := GetTypeCopyLink(TPSUndefinedClassType(x).ExtClass.SelfType);
+ end;
+ bt := x.BaseType;
+ if (x.BaseType = btType) or (x.BaseType = btNotificationVariant) then
+ begin
+ bt := btU32;
+ end else
+ if (x.BaseType = btEnum) then begin
+ if TPSEnumType(x).HighValue <= 256 then
+ bt := btU8
+ else if TPSEnumType(x).HighValue <= 65536 then
+ bt := btU16
+ else
+ bt := btU32;
+ end;
+ if FExportName <> '' then
+ begin
+ WriteByte(bt + 128);
+ end
+ else
+ WriteByte(bt);
+{$IFNDEF PS_NOINTERFACES} if x.BaseType = btInterface then
+ begin
+ WriteData(TPSInterfaceType(x).Intf.Guid, Sizeof(TGuid));
+ end else {$ENDIF} if x.BaseType = btClass then
+ begin
+ WriteLong(Length(TPSClassType(X).Cl.FClassName));
+ WriteData(TPSClassType(X).Cl.FClassName[1], Length(TPSClassType(X).Cl.FClassName));
+ end else
+ if (x.BaseType = btProcPtr) then
+ begin
+ s := DeclToBits(TPSProceduralType(x).ProcDef);
+ WriteLong(Length(s));
+ WriteData(s[1], Length(s));
+ end else
+ if (x.BaseType = btSet) then
+ begin
+ WriteLong(TPSSetType(x).BitSize);
+ end else
+ if (x.BaseType = btArray) or (x.basetype = btStaticArray) then
+ begin
+ WriteLong(TPSArrayType(x).ArrayTypeNo.FinalTypeNo);
+ if (x.baseType = btstaticarray) then begin
+ WriteLong(TPSStaticArrayType(x).Length);
+ WriteLong(TPSStaticArrayType(x).StartOffset); //<-additional StartOffset
+ end;
+ end else if x.BaseType = btRecord then
+ begin
+ n := TPSRecordType(x).RecValCount;
+ WriteData( n, 4);
+ for n := 0 to TPSRecordType(x).RecValCount - 1 do
+ WriteTypeNo(TPSRecordType(x).RecVal(n).FType.FinalTypeNo);
+ end;
+ if FExportName <> '' then
+ begin
+ WriteLong(Length(FExportName));
+ WriteData(FExportName[1], length(FExportName));
+ end;
+ WriteAttributes(x.Attributes);
+ end;
+ finally
+ Items.Free;
+ end;
+ end;
+
+ procedure WriteVars;
+ var
+ l,j : Longint;
+ x: TPSVar;
+ begin
+ for l := 0 to FVars.Count - 1 do
+ begin
+ x := FVars[l];
+ if x.SaveAsPointer then
+ begin
+ for j := FTypes.count -1 downto 0 do
+ begin
+ if TPSType(FTypes[j]).BaseType = btPointer then
+ begin
+ WriteLong(TPSType(FTypes[j]).FinalTypeNo);
+ break;
+ end;
+ end;
+ end else
+ WriteLong(x.FType.FinalTypeNo);
+ if x.exportname <> '' then
+ begin
+ WriteByte( 1);
+ WriteLong(Length(X.ExportName));
+ WriteData( X.ExportName[1], length(X.ExportName));
+ end else
+ WriteByte( 0);
+ end;
+ end;
+
+ procedure WriteProcs;
+ var
+ l: Longint;
+ xp: TPSProcedure;
+ xo: TPSInternalProcedure;
+ xe: TPSExternalProcedure;
+ s: tbtString;
+ att: Byte;
+ begin
+ for l := 0 to FProcs.Count - 1 do
+ begin
+ xp := FProcs[l];
+ if xp.Attributes.Count <> 0 then att := 4 else att := 0;
+ if xp.ClassType = TPSInternalProcedure then
+ begin
+ xo := TPSInternalProcedure(xp);
+ xo.OutputDeclPosition := Length(FOutput);
+ WriteByte(att or 2); // exported
+ WriteLong(0); // offset is unknown at this time
+ WriteLong(0); // length is also unknown at this time
+ WriteLong(Length(xo.Name));
+ WriteData( xo.Name[1], length(xo.Name));
+ s := MakeExportDecl(xo.Decl);
+ WriteLong(Length(s));
+ WriteData( s[1], length(S));
+ end
+ else
+ begin
+ xe := TPSExternalProcedure(xp);
+ if xe.RegProc.ImportDecl <> '' then
+ begin
+ WriteByte( att or 3); // imported
+ if xe.RegProc.FExportName then
+ begin
+ WriteByte(Length(xe.RegProc.Name));
+ WriteData(xe.RegProc.Name[1], Length(xe.RegProc.Name) and $FF);
+ end else begin
+ WriteByte(0);
+ end;
+ WriteLong(Length(xe.RegProc.ImportDecl));
+ WriteData(xe.RegProc.ImportDecl[1], Length(xe.RegProc.ImportDecl));
+ end else begin
+ WriteByte(att or 1); // imported
+ WriteByte(Length(xe.RegProc.Name));
+ WriteData(xe.RegProc.Name[1], Length(xe.RegProc.Name) and $FF);
+ end;
+ end;
+ if xp.Attributes.Count <> 0 then
+ WriteAttributes(xp.Attributes);
+ end;
+ end;
+
+ procedure WriteProcs2;
+ var
+ l: Longint;
+ L2: Cardinal;
+ x: TPSProcedure;
+ begin
+ for l := 0 to FProcs.Count - 1 do
+ begin
+ x := FProcs[l];
+ if x.ClassType = TPSInternalProcedure then
+ begin
+ if TPSInternalProcedure(x).Data = '' then
+ TPSInternalProcedure(x).Data := Chr(Cm_R);
+ L2 := Length(FOutput);
+ Move(L2, FOutput[TPSInternalProcedure(x).OutputDeclPosition + 2], 4);
+ // write position
+ WriteData(TPSInternalProcedure(x).Data[1], Length(TPSInternalProcedure(x).Data));
+ L2 := Cardinal(Length(FOutput)) - L2;
+ Move(L2, FOutput[TPSInternalProcedure(x).OutputDeclPosition + 6], 4); // write length
+ end;
+ end;
+ end;
+
+
+
+ {$IFDEF PS_USESSUPPORT}
+ function FindMainProc: Cardinal;
+ var
+ l: Longint;
+ Proc : TPSInternalProcedure;
+ ProcData : tbtString;
+ Calls : Integer;
+
+ procedure WriteProc(const aData: Longint);
+ var
+ l: Longint;
+ begin
+ ProcData := ProcData + Chr(cm_c);
+ l := Length(ProcData);
+ SetLength(ProcData, l + 4);
+ Move(aData, ProcData[l + 1], 4);
+ inc(Calls);
+ end;
+ begin
+ ProcData := ''; Calls := 1;
+ for l := 0 to FUnitInits.Count-1 do
+ if (FUnitInits[l] <> nil) and
+ (TPSBlockInfo(FUnitInits[l]).Proc.Data<>'') then
+ WriteProc(TPSBlockInfo(FUnitInits[l]).FProcNo);
+
+ WriteProc(FGlobalBlock.FProcNo);
+
+ for l := FUnitFinits.Count-1 downto 0 do
+ if (FUnitFinits[l] <> nil) and
+ (TPSBlockInfo(FUnitFinits[l]).Proc.Data<>'') then
+ WriteProc(TPSBlockInfo(FUnitFinits[l]).FProcNo);
+
+ if Calls = 1 then begin
+ Result := FGlobalBlock.FProcNo;
+ end else
+ begin
+ Proc := NewProc('Master proc', '!MASTERPROC');
+ Result := FindProc('!MASTERPROC');
+ Proc.data := Procdata + Chr(cm_R);
+ end;
+ end;
+ {$ELSE}
+ function FindMainProc: Cardinal;
+ var
+ l: Longint;
+ begin
+ for l := 0 to FProcs.Count - 1 do
+ begin
+ if (TPSProcedure(FProcs[l]).ClassType = TPSInternalProcedure) and
+ (TPSInternalProcedure(FProcs[l]).Name = PSMainProcName) then
+ begin
+ Result := l;
+ exit;
+ end;
+ end;
+ Result := InvalidVal;
+ end;
+ {$ENDIF}
+
+ procedure CreateDebugData;
+ var
+ I: Longint;
+ p: TPSProcedure;
+ pv: TPSVar;
+ s: tbtString;
+ begin
+ s := #0;
+ for I := 0 to FProcs.Count - 1 do
+ begin
+ p := FProcs[I];
+ if p.ClassType = TPSInternalProcedure then
+ begin
+ if TPSInternalProcedure(p).Name = PSMainProcName then
+ s := s + #1
+ else
+ s := s + TPSInternalProcedure(p).OriginalName + #1;
+ end
+ else
+ begin
+ s := s+ TPSExternalProcedure(p).RegProc.OrgName + #1;
+ end;
+ end;
+ s := s + #0#1;
+ for I := 0 to FVars.Count - 1 do
+ begin
+ pv := FVars[I];
+ s := s + pv.OrgName + #1;
+ end;
+ s := s + #0;
+ WriteDebugData(s);
+ end;
+
+ var //nvds
+ MainProc : Cardinal; //nvds
+
+ begin
+ if @FOnBeforeOutput <> nil then
+ begin
+ if not FOnBeforeOutput(Self) then
+ begin
+ Result := false;
+ exit;
+ end;
+ end;
+ MainProc := FindMainProc; //NvdS (need it here becose FindMainProc can create a New proc.
+ CreateDebugData;
+ WriteLong(PSValidHeader);
+ WriteLong(PSCurrentBuildNo);
+ WriteLong(FCurrUsedTypeNo);
+ WriteLong(FProcs.Count);
+ WriteLong(FVars.Count);
+ WriteLong(MainProc); //nvds
+ WriteLong(0);
+ WriteTypes;
+ WriteProcs;
+ WriteVars;
+ WriteProcs2;
+
+ Result := true;
+ end;
+
+ function CheckExports: Boolean;
+ var
+ i: Longint;
+ p: TPSProcedure;
+ begin
+ if @FOnExportCheck = nil then
+ begin
+ result := true;
+ exit;
+ end;
+ for i := 0 to FProcs.Count -1 do
+ begin
+ p := FProcs[I];
+ if p.ClassType = TPSInternalProcedure then
+ begin
+ if not FOnExportCheck(Self, TPSInternalProcedure(p), MakeDecl(TPSInternalProcedure(p).Decl)) then
+ begin
+ Result := false;
+ exit;
+ end;
+ end;
+ end;
+ Result := True;
+ end;
+ function DoConstBlock: Boolean;
+ var
+ COrgName: tbtString;
+ CTemp, CValue: PIFRVariant;
+ Cp: TPSConstant;
+ TokenPos, TokenRow, TokenCol: Integer;
+ begin
+ FParser.Next;
+ repeat
+ if FParser.CurrTokenID <> CSTI_Identifier then
+ begin
+ MakeError('', ecIdentifierExpected, '');
+ Result := False;
+ Exit;
+ end;
+ TokenPos := FParser.CurrTokenPos;
+ TokenRow := FParser.Row;
+ TokenCol := FParser.Col;
+ COrgName := FParser.OriginalToken;
+ if IsDuplicate(FastUpperCase(COrgName), [dcVars, dcProcs, dcConsts]) then
+ begin
+ MakeError('', ecDuplicateIdentifier, COrgName);
+ Result := False;
+ exit;
+ end;
+ FParser.Next;
+ if FParser.CurrTokenID <> CSTI_Equal then
+ begin
+ MakeError('', ecIsExpected, '');
+ Result := False;
+ Exit;
+ end;
+ FParser.Next;
+ CValue := ReadConstant(FParser, CSTI_SemiColon);
+ if CValue = nil then
+ begin
+ Result := False;
+ Exit;
+ end;
+ if FParser.CurrTokenID <> CSTI_Semicolon then
+ begin
+ MakeError('', ecSemicolonExpected, '');
+ Result := False;
+ exit;
+ end;
+ cp := TPSConstant.Create;
+ cp.Orgname := COrgName;
+ cp.Name := FastUpperCase(COrgName);
+ {$IFDEF PS_USESSUPPORT}
+ cp.DeclareUnit:=fModule;
+ {$ENDIF}
+ cp.DeclarePos := TokenPos;
+ cp.DeclareRow := TokenRow;
+ cp.DeclareCol := TokenCol;
+ New(CTemp);
+ InitializeVariant(CTemp, CValue.FType);
+ CopyVariantContents(cvalue, CTemp);
+ cp.Value := CTemp;
+ FConstants.Add(cp);
+ DisposeVariant(CValue);
+ FParser.Next;
+ until FParser.CurrTokenId <> CSTI_Identifier;
+ Result := True;
+ end;
+
+ function ProcessUses: Boolean;
+ var
+ {$IFNDEF PS_USESSUPPORT}
+ FUses: TIfStringList;
+ {$ENDIF}
+ I: Longint;
+ s: tbtString;
+ {$IFDEF PS_USESSUPPORT}
+ Parse: Boolean;
+ ParseUnit: tbtString;
+ ParserPos: TPSPascalParser;
+ {$ENDIF}
+ begin
+ FParser.Next;
+ {$IFNDEF PS_USESSUPPORT}
+ FUses := TIfStringList.Create;
+ FUses.Add('SYSTEM');
+ {$ENDIF}
+ repeat
+ if FParser.CurrTokenID <> CSTI_Identifier then
+ begin
+ MakeError('', ecIdentifierExpected, '');
+ {$IFNDEF PS_USESSUPPORT}
+ FUses.Free;
+ {$ENDIF}
+ Result := False;
+ exit;
+ end;
+ s := FParser.GetToken;
+ {$IFDEF PS_USESSUPPORT}
+ Parse:=true;
+ {$ENDIF}
+ for i := 0 to FUses.Count -1 do
+ begin
+ if FUses[I] = s then
+ begin
+ {$IFNDEF PS_USESSUPPORT}
+ MakeError('', ecDuplicateIdentifier, s);
+ FUses.Free;
+ Result := False;
+ exit;
+ {$ELSE}
+ Parse:=false;
+ {$ENDIF}
+ end;
+ end;
+ {$IFDEF PS_USESSUPPORT}
+ if fUnits.GetUnit(S).HasUses(fModule) then
+ begin
+ MakeError('', ecCrossReference, s);
+ Result := False;
+ exit;
+ end;
+
+ fUnit.AddUses(S);
+
+ if Parse then
+ begin
+ {$ENDIF}
+ FUses.Add(s);
+ if @FOnUses <> nil then
+ begin
+ try
+ {$IFDEF PS_USESSUPPORT}
+ OldFileName:=fModule;
+ fModule:=FParser.OriginalToken;
+ ParseUnit:=FParser.OriginalToken;
+ ParserPos:=FParser;
+ {$ENDIF}
+ if not OnUses(Self, FParser.GetToken) then
+ begin
+ {$IFNDEF PS_USESSUPPORT}
+ FUses.Free;
+ {$ELSE}
+ FParser:=ParserPos;
+ fModule:=OldFileName;
+ MakeError(OldFileName, ecUnitNotFoundOrContainsErrors, ParseUnit);
+ {$ENDIF}
+ Result := False;
+ exit;
+ end;
+ {$IFDEF PS_USESSUPPORT}
+ fModule:=OldFileName;
+ {$ENDIF}
+ except
+ on e: Exception do
+ begin
+ MakeError('', ecCustomError, tbtstring(e.Message));
+ {$IFNDEF PS_USESSUPPORT}
+ FUses.Free;
+ {$ENDIF}
+ Result := False;
+ exit;
+ end;
+ end;
+ end;
+ {$IFDEF PS_USESSUPPORT}
+ end;
+ {$ENDIF}
+ FParser.Next;
+ if FParser.CurrTokenID = CSTI_Semicolon then break
+ else if FParser.CurrTokenId <> CSTI_Comma then
+ begin
+ MakeError('', ecSemicolonExpected, '');
+ Result := False;
+ {$IFNDEF PS_USESSUPPORT}
+ FUses.Free;
+ {$ENDIF}
+ exit;
+ end;
+ FParser.Next;
+ until False;
+ {$IFNDEF PS_USESSUPPORT}
+ FUses.Free;
+ {$ENDIF}
+ FParser.next;
+ Result := True;
+ end;
+
+var
+ Proc: TPSProcedure;
+ {$IFDEF PS_USESSUPPORT}
+ Block : TPSBlockInfo; //nvds
+ {$ENDIF}
+begin
+ Result := False;
+ FWithCount := -1;
+
+ {$IFDEF PS_USESSUPPORT}
+ if fInCompile=0 then
+ begin
+ {$ENDIF}
+ FUnitName := '';
+ FCurrUsedTypeNo := 0;
+ FIsUnit := False;
+ Clear;
+ FParserHadError := False;
+ FParser.SetText(s);
+ FAttributeTypes := TPSList.Create;
+ FProcs := TPSList.Create;
+ FConstants := TPSList.Create;
+ FVars := TPSList.Create;
+ FTypes := TPSList.Create;
+ FRegProcs := TPSList.Create;
+ FClasses := TPSList.Create;
+
+ {$IFDEF PS_USESSUPPORT}
+ FUnitInits := TPSList.Create; //nvds
+ FUnitFinits:= TPSList.Create; //nvds
+
+ FUses:=TIFStringList.Create;
+ FUnits:=TPSUnitList.Create;
+ {$ENDIF}
+ {$IFNDEF PS_NOINTERFACES} FInterfaces := TPSList.Create;{$ENDIF}
+
+ FGlobalBlock := TPSBlockInfo.Create(nil);
+ FGlobalBlock.SubType := tMainBegin;
+
+ FGlobalBlock.Proc := NewProc(PSMainProcNameOrg, PSMainProcName);
+ FGlobalBlock.ProcNo := FindProc(PSMainProcName);
+
+ {$IFDEF PS_USESSUPPORT}
+ OldFileName:=fModule;
+ fModule:='System';
+ FUses.Add('SYSTEM');
+ {$ENDIF}
+ {$IFNDEF PS_NOSTANDARDTYPES}
+ DefineStandardTypes;
+ DefineStandardProcedures;
+ {$ENDIF}
+ if @FOnUses <> nil then
+ begin
+ try
+ if not OnUses(Self, 'SYSTEM') then
+ begin
+ Cleanup;
+ exit;
+ end;
+ except
+ on e: Exception do
+ begin
+ MakeError('', ecCustomError, tbtstring(e.Message));
+ Cleanup;
+ exit;
+ end;
+ end;
+ end;
+ {$IFDEF PS_USESSUPPORT}
+ fModule:=OldFileName;
+ OldParser:=nil;
+ OldUnit:=nil;
+ OldIsUnit:=false; // defaults
+ end
+ else
+ begin
+ OldParser:=FParser;
+ OldIsUnit:=FIsUnit;
+ OldUnit:=fUnit;
+ FParser:=TPSPascalParser.Create;
+ FParser.SetText(s);
+ end;
+
+ fUnit:=fUnits.GetUnit(fModule);
+
+ inc(fInCompile);
+ {$ENDIF}
+
+ Position := csStart;
+ repeat
+ if FParser.CurrTokenId = CSTI_EOF then
+ begin
+ if FParserHadError then
+ begin
+ Cleanup;
+ exit;
+ end;
+ if FAllowNoEnd then
+ Break
+ else
+ begin
+ MakeError('', ecUnexpectedEndOfFile, '');
+ Cleanup;
+ exit;
+ end;
+ end;
+ if (FParser.CurrTokenId = CSTII_Program) and (Position = csStart) then
+ begin
+ {$IFDEF PS_USESSUPPORT}
+ if fInCompile>1 then
+ begin
+ MakeError('', ecNotAllowed, 'program');
+ Cleanup;
+ exit;
+ end;
+ {$ENDIF}
+ Position := csProgram;
+ FParser.Next;
+ if FParser.CurrTokenId <> CSTI_Identifier then
+ begin
+ MakeError('', ecIdentifierExpected, '');
+ Cleanup;
+ exit;
+ end;
+ FParser.Next;
+ if FParser.CurrTokenId <> CSTI_Semicolon then
+ begin
+ MakeError('', ecSemicolonExpected, '');
+ Cleanup;
+ exit;
+ end;
+ FParser.Next;
+ end else
+ if (Fparser.CurrTokenID = CSTII_Implementation) and ((Position = csinterface) or (position = csInterfaceUses)) then
+ begin
+ Position := csImplementation;
+ FParser.Next;
+ end else
+ if (Fparser.CurrTokenID = CSTII_Interface) and (Position = csUnit) then
+ begin
+ Position := csInterface;
+ FParser.Next;
+ end else
+ if (FParser.CurrTokenId = CSTII_Unit) and (Position = csStart) and (FAllowUnit) then
+ begin
+ Position := csUnit;
+ FIsUnit := True;
+ FParser.Next;
+ if FParser.CurrTokenId <> CSTI_Identifier then
+ begin
+ MakeError('', ecIdentifierExpected, '');
+ Cleanup;
+ exit;
+ end;
+ if fInCompile = 1 then
+ FUnitName := FParser.OriginalToken;
+ FParser.Next;
+ if FParser.CurrTokenId <> CSTI_Semicolon then
+ begin
+ MakeError('', ecSemicolonExpected, '');
+ Cleanup;
+ exit;
+ end;
+ FParser.Next;
+ end
+ else if (FParser.CurrTokenID = CSTII_Uses) and ((Position < csuses) or (Position = csInterface)) then
+ begin
+ if (Position = csInterface) or (Position =csInterfaceUses)
+ then Position := csInterfaceUses
+ else Position := csUses;
+ if not ProcessUses then
+ begin
+ Cleanup;
+ exit;
+ end;
+ end else if (FParser.CurrTokenId = CSTII_Procedure) or
+ (FParser.CurrTokenId = CSTII_Function) or (FParser.CurrTokenID = CSTI_OpenBlock) then
+ begin
+ if (Position = csInterface) or (position = csInterfaceUses) then
+ begin
+ if not ProcessFunction(True, nil) then
+ begin
+ Cleanup;
+ exit;
+ end;
+ end else begin
+ Position := csUses;
+ if not ProcessFunction(False, nil) then
+ begin
+ Cleanup;
+ exit;
+ end;
+ end;
+ end
+ else if (FParser.CurrTokenId = CSTII_Label) then
+ begin
+ if (Position = csInterface) or (Position =csInterfaceUses)
+ then Position := csInterfaceUses
+ else Position := csUses;
+ if not ProcessLabel(FGlobalBlock.Proc) then
+ begin
+ Cleanup;
+ exit;
+ end;
+ end
+ else if (FParser.CurrTokenId = CSTII_Var) then
+ begin
+ if (Position = csInterface) or (Position =csInterfaceUses)
+ then Position := csInterfaceUses
+ else Position := csUses;
+ if not DoVarBlock(nil) then
+ begin
+ Cleanup;
+ exit;
+ end;
+ end
+ else if (FParser.CurrTokenId = CSTII_Const) then
+ begin
+ if (Position = csInterface) or (Position =csInterfaceUses)
+ then Position := csInterfaceUses
+ else Position := csUses;
+ if not DoConstBlock then
+ begin
+ Cleanup;
+ exit;
+ end;
+ end
+ else if (FParser.CurrTokenId = CSTII_Type) then
+ begin
+ if (Position = csInterface) or (Position =csInterfaceUses)
+ then Position := csInterfaceUses
+ else Position := csUses;
+ if not DoTypeBlock(FParser) then
+ begin
+ Cleanup;
+ exit;
+ end;
+ end
+ else if (FParser.CurrTokenId = CSTII_Begin)
+ {$IFDEF PS_USESSUPPORT}
+ or ((FParser.CurrTokenID = CSTII_initialization) and FIsUnit) {$ENDIF} then //nvds
+ begin
+ {$IFDEF PS_USESSUPPORT}
+ if FIsUnit then
+ begin
+ Block := TPSBlockInfo.Create(nil); //nvds
+ Block.SubType := tUnitInit; //nvds
+ Block.Proc := NewProc(PSMainProcNameOrg+'_'+fModule, FastUpperCase(PSMainProcName+'_'+fModule)); //nvds
+ Block.ProcNo := FindProc(PSMainProcName+'_'+fModule); //nvds
+ Block.Proc.DeclareUnit:= fModule;
+ Block.Proc.DeclarePos := FParser.CurrTokenPos;
+ Block.Proc.DeclareRow := FParser.Row;
+ Block.Proc.DeclareCol := FParser.Col;
+ Block.Proc.Use;
+ FUnitInits.Add(Block);
+ if ProcessSub(Block) then
+ begin
+ if (Fparser.CurrTokenId = CSTI_EOF) THEN break;
+ end
+ else
+ begin
+ Cleanup;
+ exit;
+ end;
+ end
+ else
+ begin
+ FGlobalBlock.Proc.DeclareUnit:= fModule;
+ {$ENDIF}
+ FGlobalBlock.Proc.DeclarePos := FParser.CurrTokenPos;
+ FGlobalBlock.Proc.DeclareRow := FParser.Row;
+ FGlobalBlock.Proc.DeclareCol := FParser.Col;
+ if ProcessSub(FGlobalBlock) then
+ begin
+ break;
+ end
+ else
+ begin
+ Cleanup;
+ exit;
+ end;
+ {$IFDEF PS_USESSUPPORT}
+ end;
+ {$ENDIF}
+ end
+ {$IFDEF PS_USESSUPPORT}
+ else if ((FParser.CurrTokenID = CSTII_finalization) and FIsUnit) then //NvdS
+ begin
+ Block := TPSBlockInfo.Create(nil);
+ Block.SubType := tUnitFinish;
+ Block.Proc := NewProc('!Finish_'+fModule, '!FINISH_'+FastUppercase(fModule));
+ Block.ProcNo := FindProc('!FINISH_'+FastUppercase(fModule));
+ Block.Proc.DeclareUnit:= fModule;
+
+ Block.Proc.DeclarePos := FParser.CurrTokenPos;
+ Block.Proc.DeclareRow := FParser.Row;
+ Block.Proc.DeclareCol := FParser.Col;
+ Block.Proc.use;
+ FUnitFinits.Add(Block);
+ if ProcessSub(Block) then
+ begin
+ break;
+ end else begin
+ Cleanup;
+ Result := False; //Cleanup;
+ exit;
+ end;
+ end
+ {$endif}
+ else if (Fparser.CurrTokenId = CSTII_End) and (FAllowNoBegin or FIsUnit) then
+ begin
+ FParser.Next;
+ if FParser.CurrTokenID <> CSTI_Period then
+ begin
+ MakeError('', ecPeriodExpected, '');
+ Cleanup;
+ exit;
+ end;
+ break;
+ end else
+ begin
+ MakeError('', ecBeginExpected, '');
+ Cleanup;
+ exit;
+ end;
+ until False;
+
+ {$IFDEF PS_USESSUPPORT}
+ dec(fInCompile);
+ if fInCompile=0 then
+ begin
+ {$ENDIF}
+ if not ProcessLabelForwards(FGlobalBlock.Proc) then
+ begin
+ Cleanup;
+ exit;
+ end;
+ // NVDS: Do we need to check here also do a ProcessLabelForwards() for each Initialisation/finalization block?
+
+ for i := 0 to FProcs.Count -1 do
+ begin
+ Proc := FProcs[I];
+ if (Proc.ClassType = TPSInternalProcedure) and (TPSInternalProcedure(Proc).Forwarded) then
+ begin
+ with MakeError('', ecUnsatisfiedForward, TPSInternalProcedure(Proc).Name) do
+ begin
+ FPosition := TPSInternalProcedure(Proc).DeclarePos;
+ FRow := TPSInternalProcedure(Proc).DeclareRow;
+ FCol := TPSInternalProcedure(Proc).DeclareCol;
+ end;
+ Cleanup;
+ Exit;
+ end;
+ end;
+ if not CheckExports then
+ begin
+ Cleanup;
+ exit;
+ end;
+ for i := 0 to FVars.Count -1 do
+ begin
+ if not TPSVar(FVars[I]).Used then
+ begin
+ with MakeHint({$IFDEF PS_USESSUPPORT}TPSVar(FVars[I]).DeclareUnit{$ELSE}''{$ENDIF}, ehVariableNotUsed, TPSVar(FVars[I]).Name) do
+ begin
+ FPosition := TPSVar(FVars[I]).DeclarePos;
+ FRow := TPSVar(FVars[I]).DeclareRow;
+ FCol := TPSVar(FVars[I]).DeclareCol;
+ end;
+ end;
+ end;
+
+ Result := MakeOutput;
+ Cleanup;
+ {$IFDEF PS_USESSUPPORT}
+ end
+ else
+ begin
+ fParser.Free;
+ fParser:=OldParser;
+ fIsUnit:=OldIsUnit;
+ fUnit:=OldUnit;
+ result:=true;
+ end;
+ {$ENDIF}
+end;
+
+constructor TPSPascalCompiler.Create;
+begin
+ inherited Create;
+ FParser := TPSPascalParser.Create;
+ FParser.OnParserError := ParserError;
+ FAutoFreeList := TPSList.Create;
+ FOutput := '';
+ {$IFDEF PS_USESSUPPORT}
+ FAllowUnit := true;
+ {$ENDIF}
+ FMessages := TPSList.Create;
+end;
+
+destructor TPSPascalCompiler.Destroy;
+begin
+ Clear;
+ FAutoFreeList.Free;
+
+ FMessages.Free;
+ FParser.Free;
+ inherited Destroy;
+end;
+
+function TPSPascalCompiler.GetOutput(var s: tbtString): Boolean;
+begin
+ if Length(FOutput) <> 0 then
+ begin
+ s := FOutput;
+ Result := True;
+ end
+ else
+ Result := False;
+end;
+
+function TPSPascalCompiler.GetMsg(l: Longint): TPSPascalCompilerMessage;
+begin
+ Result := FMessages[l];
+end;
+
+function TPSPascalCompiler.GetMsgCount: Longint;
+begin
+ Result := FMessages.Count;
+end;
+
+procedure TPSPascalCompiler.DefineStandardTypes;
+var
+ i: Longint;
+begin
+ AddType('Byte', btU8);
+ FDefaultBoolType := AddTypeS('Boolean', '(False, True)');
+ FDefaultBoolType.ExportName := True;
+ with TPSEnumType(AddType('LongBool', btEnum)) do
+ begin
+ HighValue := 2147483647; // make sure it's gonna be a 4 byte var
+ end;
+ with TPSEnumType(AddType('WordBool', btEnum)) do
+ begin
+ HighValue := 65535; // make sure it's gonna be a 2 byte var
+ end;
+ with TPSEnumType(AddType('ByteBool', btEnum)) do
+ begin
+ HighValue := 255; // make sure it's gonna be a 1 byte var
+ end;
+ //following 2 IFDEFs should actually be UNICODE IFDEFs...
+ AddType({$IFDEF PS_PANSICHAR}'AnsiChar'{$ELSE}'Char'{$ENDIF}, btChar);
+ {$IFDEF PS_PANSICHAR}
+ AddType('Char', btWideChar);
+ {$ENDIF}
+ {$IFNDEF PS_NOWIDESTRING}
+ AddType('WideChar', btWideChar);
+ AddType('WideString', btWideString);
+ AddType('UnicodeString', btUnicodeString);
+ {$ENDIF}
+ AddType('AnsiString', btString);
+ {$IFDEF DELPHI2009UP}
+ AddType('String', btUnicodeString);
+ ADdType('NativeString', btUnicodeString);
+ {$ELSE}
+ AddType('String', btString);
+ AddType('NativeString', btString);
+ {$ENDIF}
+ FAnyString := AddType('AnyString', btString);
+ AddType('ShortInt', btS8);
+ AddType('Word', btU16);
+ AddType('SmallInt', btS16);
+ AddType('LongInt', btS32);
+ at2ut(AddType('___Pointer', btPointer));
+ AddType('LongWord', btU32);
+ AddTypeCopyN('Integer', 'LONGINT');
+ AddTypeCopyN('Cardinal', 'LONGWORD');
+ AddType('tbtString', btString);
+ {$IFNDEF PS_NOINT64}
+ AddType('Int64', btS64);
+ {$ENDIF}
+ AddType('Single', btSingle);
+ AddType('Double', btDouble);
+ AddType('Extended', btExtended);
+ AddType('Currency', btCurrency);
+ AddType({$IFDEF PS_PANSICHAR}'PAnsiChar'{$ELSE}'PChar'{$ENDIF}, btPChar);
+ AddType('Variant', btVariant);
+ AddType('!NotificationVariant', btNotificationVariant);
+ for i := FTypes.Count -1 downto 0 do AT2UT(FTypes[i]);
+ TPSArrayType(AddType('TVariantArray', btArray)).ArrayTypeNo := FindType('VARIANT');
+
+ with AddFunction('function Assigned(I: Longint): Boolean;') do
+ begin
+ Name := '!ASSIGNED';
+ end;
+
+ with AddFunction('procedure _T(Name: tbtString; v: Variant);') do
+ begin
+ Name := '!NOTIFICATIONVARIANTSET';
+ end;
+ with AddFunction('function _T(Name: tbtString): Variant;') do
+ begin
+ Name := '!NOTIFICATIONVARIANTGET';
+ end;
+end;
+
+
+function TPSPascalCompiler.FindType(const Name: tbtString): TPSType;
+var
+ i, n: Longint;
+ RName: tbtString;
+begin
+ if FProcs = nil then begin Result := nil; exit;end;
+ RName := Fastuppercase(Name);
+ n := makehash(rname);
+ for i := FTypes.Count - 1 downto 0 do
+ begin
+ Result := FTypes.Data[I];
+ if (Result.NameHash = n) and (Result.name = rname) then
+ begin
+ Result := GetTypeCopyLink(Result);
+ exit;
+ end;
+ end;
+ result := nil;
+end;
+
+function TPSPascalCompiler.AddConstant(const Name: tbtString; FType: TPSType): TPSConstant;
+var
+ pc: TPSConstant;
+ val: PIfRVariant;
+begin
+ if FProcs = nil then raise EPSCompilerException.Create(RPS_OnUseEventOnly);
+
+ FType := GetTypeCopyLink(FType);
+ if FType = nil then
+ Raise EPSCompilerException.CreateFmt(RPS_UnableToRegisterConst, [name]);
+ pc := TPSConstant.Create;
+ pc.OrgName := name;
+ pc.Name := FastUppercase(name);
+ pc.DeclarePos:=InvalidVal;
+ {$IFDEF PS_USESSUPPORT}
+ pc.DeclareUnit:=fModule;
+ {$ENDIF}
+ New(Val);
+ InitializeVariant(Val, FType);
+ pc.Value := Val;
+ FConstants.Add(pc);
+ result := pc;
+end;
+
+function TPSPascalCompiler.ReadAttributes(Dest: TPSAttributes): Boolean;
+var
+ Att: TPSAttributeType;
+ at: TPSAttribute;
+ varp: PIfRVariant;
+ h, i: Longint;
+ s: tbtString;
+begin
+ if FParser.CurrTokenID <> CSTI_OpenBlock then begin Result := true; exit; end;
+ FParser.Next;
+ if FParser.CurrTokenID <> CSTI_Identifier then
+ begin
+ MakeError('', ecIdentifierExpected, '');
+ Result := False;
+ exit;
+ end;
+ s := FParser.GetToken;
+ h := MakeHash(s);
+ att := nil;
+ for i := FAttributeTypes.count -1 downto 0 do
+ begin
+ att := FAttributeTypes[i];
+ if (att.FNameHash = h) and (att.FName = s) then
+ Break;
+ att := nil;
+ end;
+ if att = nil then
+ begin
+ MakeError('', ecUnknownIdentifier, '');
+ Result := False;
+ exit;
+ end;
+ FParser.Next;
+ i := 0;
+ at := Dest.Add(att);
+ while att.Fields[i].Hidden do
+ begin
+ at.AddValue(NewVariant(at2ut(att.Fields[i].FieldType)));
+ inc(i);
+ end;
+ if FParser.CurrTokenId <> CSTI_OpenRound then
+ begin
+ MakeError('', ecOpenRoundExpected, '');
+ Result := False;
+ exit;
+ end;
+ FParser.Next;
+ if i < Att.FieldCount then
+ begin
+ while i < att.FieldCount do
+ begin
+ varp := ReadConstant(FParser, CSTI_CloseRound);
+ if varp = nil then
+ begin
+ Result := False;
+ exit;
+ end;
+ at.AddValue(varp);
+ if not IsCompatibleType(varp.FType, Att.Fields[i].FieldType, False) then
+ begin
+ MakeError('', ecTypeMismatch, '');
+ Result := False;
+ exit;
+ end;
+ Inc(i);
+ while (i < Att.FieldCount) and (att.Fields[i].Hidden) do
+ begin
+ at.AddValue(NewVariant(at2ut(att.Fields[i].FieldType)));
+ inc(i);
+ end;
+ if i >= Att.FieldCount then
+ begin
+ break;
+ end else
+ begin
+ if FParser.CurrTokenID <> CSTI_Comma then
+ begin
+ MakeError('', ecCommaExpected, '');
+ Result := False;
+ exit;
+ end;
+ end;
+ FParser.Next;
+ end;
+ end;
+ if FParser.CurrTokenID <> CSTI_CloseRound then
+ begin
+ MakeError('', ecCloseRoundExpected, '');
+ Result := False;
+ exit;
+ end;
+ FParser.Next;
+ if FParser.CurrTokenID <> CSTI_CloseBlock then
+ begin
+ MakeError('', ecCloseBlockExpected, '');
+ Result := False;
+ exit;
+ end;
+ FParser.Next;
+ Result := True;
+end;
+
+type
+ TConstOperation = class(TObject)
+ private
+ FDeclPosition, FDeclRow, FDeclCol: Cardinal;
+ public
+ property DeclPosition: Cardinal read FDeclPosition write FDeclPosition;
+ property DeclRow: Cardinal read FDeclRow write FDeclRow;
+ property DeclCol: Cardinal read FDeclCol write FDeclCol;
+ procedure SetPos(Parser: TPSPascalParser);
+ end;
+
+ TUnConstOperation = class(TConstOperation)
+ private
+ FOpType: TPSUnOperatorType;
+ FVal1: TConstOperation;
+ public
+ property OpType: TPSUnOperatorType read FOpType write FOpType;
+ property Val1: TConstOperation read FVal1 write FVal1;
+
+ destructor Destroy; override;
+ end;
+
+ TBinConstOperation = class(TConstOperation)
+ private
+ FOpType: TPSBinOperatorType;
+ FVal2: TConstOperation;
+ FVal1: TConstOperation;
+ public
+ property OpType: TPSBinOperatorType read FOpType write FOpType;
+ property Val1: TConstOperation read FVal1 write FVal1;
+ property Val2: TConstOperation read FVal2 write FVal2;
+
+ destructor Destroy; override;
+ end;
+
+ TConstData = class(TConstOperation)
+ private
+ FData: PIfRVariant;
+ public
+ property Data: PIfRVariant read FData write FData;
+ destructor Destroy; override;
+ end;
+
+
+function TPSPascalCompiler.IsBoolean(aType: TPSType): Boolean;
+begin
+ Result := (AType = FDefaultBoolType)
+ or (AType.Name = 'LONGBOOL')
+ or (AType.Name = 'WORDBOOL')
+ or (AType.Name = 'BYTEBOOL');
+end;
+
+
+function TPSPascalCompiler.ReadConstant(FParser: TPSPascalParser; StopOn: TPSPasToken): PIfRVariant;
+
+ function ReadExpression: TConstOperation; forward;
+ function ReadTerm: TConstOperation; forward;
+ function ReadFactor: TConstOperation;
+ var
+ NewVar: TConstOperation;
+ NewVarU: TUnConstOperation;
+ function GetConstantIdentifier: PIfRVariant;
+ var
+ s: tbtString;
+ sh: Longint;
+ i: Longint;
+ p: TPSConstant;
+ begin
+ s := FParser.GetToken;
+ sh := MakeHash(s);
+ for i := FConstants.Count -1 downto 0 do
+ begin
+ p := FConstants[I];
+ if (p.NameHash = sh) and (p.Name = s) then
+ begin
+ New(Result);
+ InitializeVariant(Result, p.Value.FType);
+ CopyVariantContents(P.Value, Result);
+ FParser.Next;
+ exit;
+ end;
+ end;
+ MakeError('', ecUnknownIdentifier, '');
+ Result := nil;
+ end;
+ begin
+ case fParser.CurrTokenID of
+ CSTII_Not:
+ begin
+ FParser.Next;
+ NewVar := ReadFactor;
+ if NewVar = nil then
+ begin
+ Result := nil;
+ exit;
+ end;
+ NewVarU := TUnConstOperation.Create;
+ NewVarU.OpType := otNot;
+ NewVarU.Val1 := NewVar;
+ NewVar := NewVarU;
+ end;
+ CSTI_Minus:
+ begin
+ FParser.Next;
+ NewVar := ReadTerm;
+ if NewVar = nil then
+ begin
+ Result := nil;
+ exit;
+ end;
+ NewVarU := TUnConstOperation.Create;
+ NewVarU.OpType := otMinus;
+ NewVarU.Val1 := NewVar;
+ NewVar := NewVarU;
+ end;
+ CSTI_OpenRound:
+ begin
+ FParser.Next;
+ NewVar := ReadExpression;
+ if NewVar = nil then
+ begin
+ Result := nil;
+ exit;
+ end;
+ if FParser.CurrTokenId <> CSTI_CloseRound then
+ begin
+ NewVar.Free;
+ Result := nil;
+ MakeError('', ecCloseRoundExpected, '');
+ exit;
+ end;
+ FParser.Next;
+ end;
+ CSTI_Char, CSTI_String:
+ begin
+ NewVar := TConstData.Create;
+ NewVar.SetPos(FParser);
+ TConstData(NewVar).Data := ReadString;
+ end;
+ CSTI_HexInt, CSTI_Integer:
+ begin
+ NewVar := TConstData.Create;
+ NewVar.SetPos(FParser);
+ TConstData(NewVar).Data := ReadInteger(FParser.GetToken);
+ FParser.Next;
+ end;
+ CSTI_Real:
+ begin
+ NewVar := TConstData.Create;
+ NewVar.SetPos(FParser);
+ TConstData(NewVar).Data := ReadReal(FParser.GetToken);
+ FParser.Next;
+ end;
+ CSTI_Identifier:
+ begin
+ NewVar := TConstData.Create;
+ NewVar.SetPos(FParser);
+ TConstData(NewVar).Data := GetConstantIdentifier;
+ if TConstData(NewVar).Data = nil then
+ begin
+ NewVar.Free;
+ Result := nil;
+ exit;
+ end
+ end;
+ else
+ begin
+ MakeError('', ecSyntaxError, '');
+ Result := nil;
+ exit;
+ end;
+ end; {case}
+ Result := NewVar;
+ end; // ReadFactor
+
+ function ReadTerm: TConstOperation;
+ var
+ F1, F2: TConstOperation;
+ F: TBinConstOperation;
+ Token: TPSPasToken;
+ Op: TPSBinOperatorType;
+ begin
+ F1 := ReadFactor;
+ if F1 = nil then
+ begin
+ Result := nil;
+ exit;
+ end;
+ while FParser.CurrTokenID in [CSTI_Multiply, CSTI_Divide, CSTII_Div, CSTII_Mod, CSTII_And, CSTII_Shl, CSTII_Shr] do
+ begin
+ Token := FParser.CurrTokenID;
+ FParser.Next;
+ F2 := ReadFactor;
+ if f2 = nil then
+ begin
+ f1.Free;
+ Result := nil;
+ exit;
+ end;
+ case Token of
+ CSTI_Multiply: Op := otMul;
+ CSTI_Divide: Op := otDiv;
+ CSTII_Div: Op := otIntDiv;
+ CSTII_mod: Op := otMod;
+ CSTII_and: Op := otAnd;
+ CSTII_shl: Op := otShl;
+ CSTII_shr: Op := otShr;
+ else
+ Op := otAdd;
+ end;
+ F := TBinConstOperation.Create;
+ f.Val1 := F1;
+ f.Val2 := F2;
+ f.OpType := Op;
+ f1 := f;
+ end;
+ Result := F1;
+ end; // ReadTerm
+
+ function ReadSimpleExpression: TConstOperation;
+ var
+ F1, F2: TConstOperation;
+ F: TBinConstOperation;
+ Token: TPSPasToken;
+ Op: TPSBinOperatorType;
+ begin
+ F1 := ReadTerm;
+ if F1 = nil then
+ begin
+ Result := nil;
+ exit;
+ end;
+ while FParser.CurrTokenID in [CSTI_Plus, CSTI_Minus, CSTII_Or, CSTII_Xor] do
+ begin
+ Token := FParser.CurrTokenID;
+ FParser.Next;
+ F2 := ReadTerm;
+ if f2 = nil then
+ begin
+ f1.Free;
+ Result := nil;
+ exit;
+ end;
+ case Token of
+ CSTI_Plus: Op := otAdd;
+ CSTI_Minus: Op := otSub;
+ CSTII_or: Op := otOr;
+ CSTII_xor: Op := otXor;
+ else
+ Op := otAdd;
+ end;
+ F := TBinConstOperation.Create;
+ f.Val1 := F1;
+ f.Val2 := F2;
+ f.OpType := Op;
+ f1 := f;
+ end;
+ Result := F1;
+ end; // ReadSimpleExpression
+
+
+ function ReadExpression: TConstOperation;
+ var
+ F1, F2: TConstOperation;
+ F: TBinConstOperation;
+ Token: TPSPasToken;
+ Op: TPSBinOperatorType;
+ begin
+ F1 := ReadSimpleExpression;
+ if F1 = nil then
+ begin
+ Result := nil;
+ exit;
+ end;
+ while FParser.CurrTokenID in [ CSTI_GreaterEqual, CSTI_LessEqual, CSTI_Greater, CSTI_Less, CSTI_Equal, CSTI_NotEqual] do
+ begin
+ Token := FParser.CurrTokenID;
+ FParser.Next;
+ F2 := ReadSimpleExpression;
+ if f2 = nil then
+ begin
+ f1.Free;
+ Result := nil;
+ exit;
+ end;
+ case Token of
+ CSTI_GreaterEqual: Op := otGreaterEqual;
+ CSTI_LessEqual: Op := otLessEqual;
+ CSTI_Greater: Op := otGreater;
+ CSTI_Less: Op := otLess;
+ CSTI_Equal: Op := otEqual;
+ CSTI_NotEqual: Op := otNotEqual;
+ else
+ Op := otAdd;
+ end;
+ F := TBinConstOperation.Create;
+ f.Val1 := F1;
+ f.Val2 := F2;
+ f.OpType := Op;
+ f1 := f;
+ end;
+ Result := F1;
+ end; // ReadExpression
+
+
+ function EvalConst(P: TConstOperation): PIfRVariant;
+ var
+ p1, p2: PIfRVariant;
+ begin
+ if p is TBinConstOperation then
+ begin
+ p1 := EvalConst(TBinConstOperation(p).Val1);
+ if p1 = nil then begin Result := nil; exit; end;
+ p2 := EvalConst(TBinConstOperation(p).Val2);
+ if p2 = nil then begin DisposeVariant(p1); Result := nil; exit; end;
+ if not PreCalc(False, 0, p1, 0, p2, TBinConstOperation(p).OpType, p.DeclPosition, p.DeclRow, p.DeclCol) then
+ begin
+ DisposeVariant(p1);
+ DisposeVariant(p2);
+// MakeError('', ecTypeMismatch, '');
+ result := nil;
+ exit;
+ end;
+ DisposeVariant(p2);
+ Result := p1;
+ end else if p is TUnConstOperation then
+ begin
+ with TUnConstOperation(P) do
+ begin
+ p1 := EvalConst(Val1);
+ case OpType of
+ otNot:
+ case p1.FType.BaseType of
+ btU8: p1.tu8 := not p1.tu8;
+ btU16: p1.tu16 := not p1.tu16;
+ btU32: p1.tu32 := not p1.tu32;
+ bts8: p1.ts8 := not p1.ts8;
+ bts16: p1.ts16 := not p1.ts16;
+ bts32: p1.ts32 := not p1.ts32;
+ {$IFNDEF PS_NOINT64}
+ bts64: p1.ts64 := not p1.ts64;
+ {$ENDIF}
+ else
+ begin
+ MakeError('', ecTypeMismatch, '');
+ DisposeVariant(p1);
+ Result := nil;
+ exit;
+ end;
+ end;
+ otMinus:
+ case p1.FType.BaseType of
+ btU8: p1.tu8 := -p1.tu8;
+ btU16: p1.tu16 := -p1.tu16;
+ btU32: p1.tu32 := -p1.tu32;
+ bts8: p1.ts8 := -p1.ts8;
+ bts16: p1.ts16 := -p1.ts16;
+ bts32: p1.ts32 := -p1.ts32;
+ {$IFNDEF PS_NOINT64}
+ bts64: p1.ts64 := -p1.ts64;
+ {$ENDIF}
+ btDouble: p1.tdouble := - p1.tDouble;
+ btSingle: p1.tsingle := - p1.tsingle;
+ btCurrency: p1.tcurrency := - p1.tcurrency;
+ btExtended: p1.textended := - p1.textended;
+ else
+ begin
+ MakeError('', ecTypeMismatch, '');
+ DisposeVariant(p1);
+ Result := nil;
+ exit;
+ end;
+ end;
+ else
+ begin
+ DisposeVariant(p1);
+ Result := nil;
+ exit;
+ end;
+ end;
+ end;
+ Result := p1;
+ end else
+ begin
+ if ((p as TConstData).Data.FType.BaseType = btString)
+ and (length(tbtstring((p as TConstData).Data.tstring)) =1) then
+ begin
+ New(p1);
+ InitializeVariant(p1, FindBaseType(btChar));
+ p1.tchar := tbtstring((p as TConstData).Data.tstring)[1];
+ Result := p1;
+ end else begin
+ New(p1);
+ InitializeVariant(p1, (p as TConstData).Data.FType);
+ CopyVariantContents((p as TConstData).Data, p1);
+ Result := p1;
+ end;
+ end;
+ end;
+
+var
+ Val: TConstOperation;
+begin
+ Val := ReadExpression;
+ if val = nil then
+ begin
+ Result := nil;
+ exit;
+ end;
+ Result := EvalConst(Val);
+ Val.Free;
+end;
+
+procedure TPSPascalCompiler.WriteDebugData(const s: tbtString);
+begin
+ FDebugOutput := FDebugOutput + s;
+end;
+
+function TPSPascalCompiler.GetDebugOutput(var s: tbtString): Boolean;
+begin
+ if Length(FDebugOutput) <> 0 then
+ begin
+ s := FDebugOutput;
+ Result := True;
+ end
+ else
+ Result := False;
+end;
+
+function TPSPascalCompiler.AddUsedFunction(var Proc: TPSInternalProcedure): Cardinal;
+begin
+ if FProcs = nil then raise EPSCompilerException.Create(RPS_OnUseEventOnly);
+ Proc := TPSInternalProcedure.Create;
+ FProcs.Add(Proc);
+ Result := FProcs.Count - 1;
+end;
+
+{$IFNDEF PS_NOINTERFACES}
+const
+ IUnknown_Guid: TGuid = (D1: 0; d2: 0; d3: 0; d4: ($c0,00,00,00,00,00,00,$46));
+ IDispatch_Guid: Tguid = (D1: $20400; D2: $0; D3: $0; D4:($C0, $0, $0, $0, $0, $0, $0, $46));
+{$ENDIF}
+
+procedure TPSPascalCompiler.DefineStandardProcedures;
+var
+ p: TPSRegProc;
+begin
+ {$IFNDEF PS_NOINT64}
+ AddFunction('function IntToStr(i: Int64): String;');
+ {$ELSE}
+ AddFunction('function IntTostr(i: Integer): String;');
+ {$ENDIF}
+ AddFunction('function StrToInt(s: String): Longint;');
+ AddFunction('function StrToIntDef(s: String; def: Longint): Longint;');
+ AddFunction('function Copy(s: AnyString; iFrom, iCount: Longint): AnyString;');
+ AddFunction('function Pos(SubStr, S: AnyString): Longint;');
+ AddFunction('procedure Delete(var s: AnyString; ifrom, icount: Longint);');
+ AddFunction('procedure Insert(s: AnyString; var s2: AnyString; iPos: Longint);');
+ p := AddFunction('function GetArrayLength: integer;');
+ with P.Decl.AddParam do
+ begin
+ OrgName := 'arr';
+ Mode := pmInOut;
+ end;
+ p := AddFunction('procedure SetArrayLength;');
+ with P.Decl.AddParam do
+ begin
+ OrgName := 'arr';
+ Mode := pmInOut;
+ end;
+ with P.Decl.AddParam do
+ begin
+ OrgName := 'count';
+ aType := FindBaseType(btS32);
+ end;
+ AddFunction('Function StrGet(var S : String; I : Integer) : Char;');
+ AddFunction('Function StrGet2(S : String; I : Integer) : Char;');
+ AddFunction('procedure StrSet(c : Char; I : Integer; var s : String);');
+ {$IFNDEF PS_NOWIDESTRING}
+ AddFunction('Function WStrGet(var S : AnyString; I : Integer) : WideChar;');
+ AddFunction('procedure WStrSet(c : AnyString; I : Integer; var s : AnyString);');
+ {$ENDIF}
+ AddFunction('Function AnsiUppercase(s : String) : String;');
+ AddFunction('Function AnsiLowercase(s : String) : String;');
+ AddFunction('Function Uppercase(s : AnyString) : AnyString;');
+ AddFunction('Function Lowercase(s : AnyString) : AnyString;');
+ AddFunction('Function Trim(s : AnyString) : AnyString;');
+ AddFunction('function Length: Integer;').Decl.AddParam.OrgName:='s';
+ with AddFunction('procedure SetLength;').Decl do
+ begin
+ with AddParam do
+ begin
+ OrgName:='s';
+ Mode:=pmInOut;
+ end;
+ with AddParam do
+ begin
+ OrgName:='NewLength';
+ aType:=FindBaseType(btS32); //Integer
+ end;
+ end;
+ {$IFNDEF PS_NOINT64}
+ AddFunction('function Low: Int64;').Decl.AddParam.OrgName:='x';
+ AddFunction('function High: Int64;').Decl.AddParam.OrgName:='x';
+ {$ELSE}
+ AddFunction('function Low: Integer;').Decl.AddParam.OrgName:='x';
+ AddFunction('function High: Integer;').Decl.AddParam.OrgName:='x';
+ {$ENDIF}
+ with AddFunction('procedure Dec;').Decl do begin
+ with AddParam do
+ begin
+ OrgName:='x';
+ Mode:=pmInOut;
+ end;
+ end;
+ with AddFunction('procedure Inc;').Decl do begin
+ with AddParam do
+ begin
+ OrgName:='x';
+ Mode:=pmInOut;
+ end;
+ end;
+ AddFunction('Function Sin(e : Extended) : Extended;');
+ AddFunction('Function Cos(e : Extended) : Extended;');
+ AddFunction('Function Sqrt(e : Extended) : Extended;');
+ AddFunction('Function Round(e : Extended) : Longint;');
+ AddFunction('Function Trunc(e : Extended) : Longint;');
+ AddFunction('Function Int(e : Extended) : Extended;');
+ AddFunction('Function Pi : Extended;');
+ AddFunction('Function Abs(e : Extended) : Extended;');
+ AddFunction('function StrToFloat(s: String): Extended;');
+ AddFunction('Function FloatToStr(e : Extended) : String;');
+ AddFunction('Function Padl(s : AnyString;I : longInt) : AnyString;');
+ AddFunction('Function Padr(s : AnyString;I : longInt) : AnyString;');
+ AddFunction('Function Padz(s : AnyString;I : longInt) : AnyString;');
+ AddFunction('Function Replicate(c : char;I : longInt) : String;');
+ AddFunction('Function StringOfChar(c : char;I : longInt) : String;');
+ AddTypeS('TVarType', 'Word');
+ AddConstantN('varEmpty', 'Word').Value.tu16 := varempty;
+ AddConstantN('varNull', 'Word').Value.tu16 := varnull;
+ AddConstantN('varSmallInt', 'Word').Value.tu16 := varsmallint;
+ AddConstantN('varInteger', 'Word').Value.tu16 := varinteger;
+ AddConstantN('varSingle', 'Word').Value.tu16 := varsingle;
+ AddConstantN('varDouble', 'Word').Value.tu16 := vardouble;
+ AddConstantN('varCurrency', 'Word').Value.tu16 := varcurrency;
+ AddConstantN('varDate', 'Word').Value.tu16 := vardate;
+ AddConstantN('varOleStr', 'Word').Value.tu16 := varolestr;
+ AddConstantN('varDispatch', 'Word').Value.tu16 := vardispatch;
+ AddConstantN('varError', 'Word').Value.tu16 := varerror;
+ AddConstantN('varBoolean', 'Word').Value.tu16 := varboolean;
+ AddConstantN('varVariant', 'Word').Value.tu16 := varvariant;
+ AddConstantN('varUnknown', 'Word').Value.tu16 := varunknown;
+{$IFDEF DELPHI6UP}
+ AddConstantN('varShortInt', 'Word').Value.tu16 := varshortint;
+ AddConstantN('varByte', 'Word').Value.tu16 := varbyte;
+ AddConstantN('varWord', 'Word').Value.tu16 := varword;
+ AddConstantN('varLongWord', 'Word').Value.tu16 := varlongword;
+ AddConstantN('varInt64', 'Word').Value.tu16 := varint64;
+{$ENDIF}
+{$IFDEF DELPHI5UP}
+ AddConstantN('varStrArg', 'Word').Value.tu16 := varstrarg;
+ AddConstantN('varAny', 'Word').Value.tu16 := varany;
+{$ENDIF}
+ AddConstantN('varString', 'Word').Value.tu16 := varstring;
+ AddConstantN('varTypeMask', 'Word').Value.tu16 := vartypemask;
+ AddConstantN('varArray', 'Word').Value.tu16 := vararray;
+ AddConstantN('varByRef', 'Word').Value.tu16 := varByRef;
+{$IFDEF UNICODE}
+ AddConstantN('varUString', 'Word').Value.tu16 := varUString;
+{$ENDIF}
+ AddDelphiFunction('function Unassigned: Variant;');
+ AddDelphiFunction('function VarIsEmpty(const V: Variant): Boolean;');
+ AddDelphiFunction('function Null: Variant;');
+ AddDelphiFunction('function VarIsNull(const V: Variant): Boolean;');
+ AddDelphiFunction('function VarType(const V: Variant): TVarType;');
+ addTypeS('TIFException', '(ErNoError, erCannotImport, erInvalidType, ErInternalError, '+
+ 'erInvalidHeader, erInvalidOpcode, erInvalidOpcodeParameter, erNoMainProc, erOutOfGlobalVarsRange, '+
+ 'erOutOfProcRange, ErOutOfRange, erOutOfStackRange, ErTypeMismatch, erUnexpectedEof, '+
+ 'erVersionError, ErDivideByZero, ErMathError,erCouldNotCallProc, erOutofRecordRange, '+
+ 'erOutOfMemory, erException, erNullPointerException, erNullVariantError, erInterfaceNotSupported, erCustomError)');
+ AddFunction('procedure RaiseLastException;');
+ AddFunction('procedure RaiseException(Ex: TIFException; Param: String);');
+ AddFunction('function ExceptionType: TIFException;');
+ AddFunction('function ExceptionParam: String;');
+ AddFunction('function ExceptionProc: Cardinal;');
+ AddFunction('function ExceptionPos: Cardinal;');
+ AddFunction('function ExceptionToString(er: TIFException; Param: String): String;');
+ {$IFNDEF PS_NOINT64}
+ AddFunction('function StrToInt64(s: String): int64;');
+ AddFunction('function Int64ToStr(i: Int64): String;');
+ {$ENDIF}
+
+ with AddFunction('function SizeOf: Longint;').Decl.AddParam do
+ begin
+ OrgName := 'Data';
+ end;
+{$IFNDEF PS_NOINTERFACES}
+ with AddInterface(nil, IUnknown_Guid, 'IUnknown') do
+ begin
+ RegisterDummyMethod; // Query Interface
+ RegisterDummyMethod; // _AddRef
+ RegisterDummyMethod; // _Release
+ end;
+ with AddInterface(nil, IUnknown_Guid, 'IInterface') do
+ begin
+ RegisterDummyMethod; // Query Interface
+ RegisterDummyMethod; // _AddRef
+ RegisterDummyMethod; // _Release
+ end;
+
+ {$IFNDEF PS_NOIDISPATCH}
+ with AddInterface(FindInterface('IUnknown'), IDispatch_Guid, 'IDispatch') do
+ begin
+ RegisterDummyMethod; // GetTypeCount
+ RegisterDummyMethod; // GetTypeInfo
+ RegisterDummyMethod; // GetIdsOfName
+ RegisterDummyMethod; // Invoke
+ end;
+ with TPSInterfaceType(FindType('IDispatch')) do
+ begin
+ ExportName := True;
+ end;
+ AddDelphiFunction('function IDispatchInvoke(Self: IDispatch; PropertySet: Boolean; const Name: String; Par: array of variant): variant;');
+ {$ENDIF}
+{$ENDIF}
+end;
+
+function TPSPascalCompiler.GetTypeCount: Longint;
+begin
+ if FProcs = nil then raise EPSCompilerException.Create(RPS_OnUseEventOnly);
+ Result := FTypes.Count;
+end;
+
+function TPSPascalCompiler.GetType(I: Longint): TPSType;
+begin
+ if FProcs = nil then raise EPSCompilerException.Create(RPS_OnUseEventOnly);
+ Result := FTypes[I];
+end;
+
+function TPSPascalCompiler.GetVarCount: Longint;
+begin
+ if FProcs = nil then raise EPSCompilerException.Create(RPS_OnUseEventOnly);
+ Result := FVars.Count;
+end;
+
+function TPSPascalCompiler.GetVar(I: Longint): TPSVar;
+begin
+ if FProcs = nil then raise EPSCompilerException.Create(RPS_OnUseEventOnly);
+ Result := FVars[i];
+end;
+
+function TPSPascalCompiler.GetProcCount: Longint;
+begin
+ if FProcs = nil then raise EPSCompilerException.Create(RPS_OnUseEventOnly);
+ Result := FProcs.Count;
+end;
+
+function TPSPascalCompiler.GetProc(I: Longint): TPSProcedure;
+begin
+ if FProcs = nil then raise EPSCompilerException.Create(RPS_OnUseEventOnly);
+ Result := FProcs[i];
+end;
+
+
+
+
+function TPSPascalCompiler.AddUsedFunction2(var Proc: TPSExternalProcedure): Cardinal;
+begin
+ if FProcs = nil then raise EPSCompilerException.Create(RPS_OnUseEventOnly);
+ Proc := TPSExternalProcedure.Create;
+ FProcs.Add(Proc);
+ Result := FProcs.Count -1;
+end;
+
+function TPSPascalCompiler.AddVariable(const Name: tbtString; FType: TPSType): TPSVar;
+var
+ P: TPSVar;
+ s:tbtString;
+begin
+ if FProcs = nil then raise EPSCompilerException.Create(RPS_OnUseEventOnly);
+ if FType = nil then raise EPSCompilerException.CreateFmt(RPS_InvalidTypeForVar, [Name]);
+ s := Fastuppercase(Name);
+ if IsDuplicate(s,[dcVars]) then raise EPSCompilerException.CreateFmt(RPS_DuplicateIdent, [Name]);
+
+ p := TPSVar.Create;
+ p.OrgName := Name;
+ p.Name := s;
+ p.FType := AT2UT(FType);
+ p.exportname := p.Name;
+ FVars.Add(p);
+ Result := P;
+end;
+
+function TPSPascalCompiler.AddAttributeType: TPSAttributeType;
+begin
+ if FAttributeTypes = nil then Raise Exception.Create(RPS_OnUseEventOnly);
+ Result := TPSAttributeType.Create;
+ FAttributeTypes.Add(Result);
+end;
+
+function TPSPascalCompiler.FindAttributeType(const Name: tbtString): TPSAttributeType;
+var
+ h, i: Integer;
+ n: tbtString;
+begin
+ if FAttributeTypes = nil then Raise Exception.Create(RPS_OnUseEventOnly);
+ n := FastUpperCase(Name);
+ h := MakeHash(n);
+ for i := FAttributeTypes.Count -1 downto 0 do
+ begin
+ result := TPSAttributeType(FAttributeTypes[i]);
+ if (Result.NameHash = h) and (Result.Name = n) then
+ exit;
+ end;
+ result := nil;
+end;
+function TPSPascalCompiler.GetConstCount: Longint;
+begin
+ if FProcs = nil then raise EPSCompilerException.Create(RPS_OnUseEventOnly);
+ result := FConstants.Count;
+end;
+
+function TPSPascalCompiler.GetConst(I: Longint): TPSConstant;
+begin
+ if FProcs = nil then raise EPSCompilerException.Create(RPS_OnUseEventOnly);
+ Result := TPSConstant(FConstants[i]);
+end;
+
+function TPSPascalCompiler.GetRegProcCount: Longint;
+begin
+ if FProcs = nil then raise EPSCompilerException.Create(RPS_OnUseEventOnly);
+ Result := FRegProcs.Count;
+end;
+
+function TPSPascalCompiler.GetRegProc(I: Longint): TPSRegProc;
+begin
+ if FProcs = nil then raise EPSCompilerException.Create(RPS_OnUseEventOnly);
+ Result := TPSRegProc(FRegProcs[i]);
+end;
+
+
+procedure TPSPascalCompiler.AddToFreeList(Obj: TObject);
+begin
+ FAutoFreeList.Add(Obj);
+end;
+
+function TPSPascalCompiler.AddConstantN(const Name,
+ FType: tbtString): TPSConstant;
+begin
+ Result := AddConstant(Name, FindType(FType));
+end;
+
+function TPSPascalCompiler.AddTypeCopy(const Name: tbtString;
+ TypeNo: TPSType): TPSType;
+begin
+ if FProcs = nil then raise EPSCompilerException.Create(RPS_OnUseEventOnly);
+ TypeNo := GetTypeCopyLink(TypeNo);
+ if Typeno = nil then raise EPSCompilerException.Create(RPS_InvalidType);
+ Result := AddType(Name, BtTypeCopy);
+ TPSTypeLink(Result).LinkTypeNo := TypeNo;
+end;
+
+function TPSPascalCompiler.AddTypeCopyN(const Name,
+ FType: tbtString): TPSType;
+begin
+ Result := AddTypeCopy(Name, FindType(FType));
+end;
+
+
+function TPSPascalCompiler.AddUsedVariable(const Name: tbtString;
+ FType: TPSType): TPSVar;
+begin
+ Result := AddVariable(Name, FType);
+ if Result <> nil then
+ Result.Use;
+end;
+
+function TPSPascalCompiler.AddUsedVariableN(const Name,
+ FType: tbtString): TPSVar;
+begin
+ Result := AddVariable(Name, FindType(FType));
+ if Result <> nil then
+ Result.Use;
+end;
+
+function TPSPascalCompiler.AddVariableN(const Name,
+ FType: tbtString): TPSVar;
+begin
+ Result := AddVariable(Name, FindType(FType));
+end;
+
+function TPSPascalCompiler.AddUsedPtrVariable(const Name: tbtString; FType: TPSType): TPSVar;
+begin
+ Result := AddVariable(Name, FType);
+ if Result <> nil then
+ begin
+ result.SaveAsPointer := True;
+ Result.Use;
+ end;
+end;
+
+function TPSPascalCompiler.AddUsedPtrVariableN(const Name, FType: tbtString): TPSVar;
+begin
+ Result := AddVariable(Name, FindType(FType));
+ if Result <> nil then
+ begin
+ result.SaveAsPointer := True;
+ Result.Use;
+ end;
+end;
+
+function TPSPascalCompiler.AddTypeS(const Name, Decl: tbtString): TPSType;
+var
+ Parser: TPSPascalParser;
+begin
+ if FProcs = nil then raise EPSCompilerException.Create(RPS_OnUseEventOnly);
+ Parser := TPSPascalParser.Create;
+ Parser.SetText(Decl);
+ Result := ReadType(Name, Parser);
+ if Result<>nil then
+ begin
+ Result.DeclarePos:=InvalidVal;
+ {$IFDEF PS_USESSUPPORT}
+ Result.DeclareUnit:=fModule;
+ {$ENDIF}
+ Result.DeclareRow:=0;
+ Result.DeclareCol:=0;
+ end;
+ Parser.Free;
+ if result = nil then Raise EPSCompilerException.CreateFmt(RPS_UnableToRegisterType, [name]);
+end;
+
+
+function TPSPascalCompiler.CheckCompatProc(P: TPSType; ProcNo: Cardinal): Boolean;
+var
+ i: Longint;
+ s1, s2: TPSParametersDecl;
+begin
+ if p.BaseType <> btProcPtr then begin
+ Result := False;
+ Exit;
+ end;
+
+ S1 := TPSProceduralType(p).ProcDef;
+
+ if TPSProcedure(FProcs[ProcNo]).ClassType = TPSInternalProcedure then
+ s2 := TPSInternalProcedure(FProcs[ProcNo]).Decl
+ else
+ s2 := TPSExternalProcedure(FProcs[ProcNo]).RegProc.Decl;
+ if (s1.Result <> s2.Result) or (s1.ParamCount <> s2.ParamCount) then
+ begin
+ Result := False;
+ Exit;
+ end;
+ for i := 0 to s1.ParamCount -1 do
+ begin
+ if (s1.Params[i].Mode <> s2.Params[i].Mode) or (s1.Params[i].aType <> s2.Params[i].aType) then
+ begin
+ Result := False;
+ Exit;
+ end;
+ end;
+ Result := True;
+end;
+
+function TPSPascalCompiler.MakeExportDecl(decl: TPSParametersDecl): tbtString;
+var
+ i: Longint;
+begin
+ if Decl.Result = nil then result := '-1' else
+ result := IntToStr(Decl.Result.FinalTypeNo);
+
+ for i := 0 to decl.ParamCount -1 do
+ begin
+ if decl.GetParam(i).Mode = pmIn then
+ Result := Result + ' @'
+ else
+ Result := Result + ' !';
+ Result := Result + inttostr(decl.GetParam(i).aType.FinalTypeNo);
+ end;
+end;
+
+
+function TPSPascalCompiler.IsIntBoolType(aType: TPSType): Boolean;
+begin
+ if Isboolean(aType) then begin Result := True; exit;end;
+
+ case aType.BaseType of
+ btU8, btS8, btU16, btS16, btU32, btS32{$IFNDEF PS_NOINT64}, btS64{$ENDIF}: Result := True;
+ else
+ Result := False;
+ end;
+end;
+
+
+procedure TPSPascalCompiler.ParserError(Parser: TObject;
+ Kind: TPSParserErrorKind);
+begin
+ FParserHadError := True;
+ case Kind of
+ ICOMMENTERROR: MakeError('', ecCommentError, '');
+ ISTRINGERROR: MakeError('', ecStringError, '');
+ ICHARERROR: MakeError('', ecCharError, '');
+ else
+ MakeError('', ecSyntaxError, '');
+ end;
+end;
+
+
+function TPSPascalCompiler.AddDelphiFunction(const Decl: tbtString): TPSRegProc;
+var
+ p: TPSRegProc;
+ pDecl: TPSParametersDecl;
+ DOrgName: tbtString;
+ FT: TPMFuncType;
+ i: Longint;
+
+begin
+ pDecl := TPSParametersDecl.Create;
+ p := nil;
+ try
+ if not ParseMethod(Self, '', Decl, DOrgName, pDecl, FT) then
+ Raise EPSCompilerException.CreateFmt(RPS_UnableToRegisterFunction, [Decl]);
+
+ p := TPSRegProc.Create;
+ P.Name := FastUppercase(DOrgName);
+ p.OrgName := DOrgName;
+ p.ExportName := True;
+ p.Decl.Assign(pDecl);
+
+ FRegProcs.Add(p);
+
+ if pDecl.Result = nil then
+ begin
+ p.ImportDecl := p.ImportDecl + #0;
+ end else
+ p.ImportDecl := p.ImportDecl + #1;
+ for i := 0 to pDecl.ParamCount -1 do
+ begin
+ if pDecl.Params[i].Mode <> pmIn then
+ p.ImportDecl := p.ImportDecl + #1
+ else
+ p.ImportDecl := p.ImportDecl + #0;
+ end;
+ finally
+ pDecl.Free;
+ end;
+ Result := p;
+end;
+
+{$IFNDEF PS_NOINTERFACES}
+function TPSPascalCompiler.AddInterface(InheritedFrom: TPSInterface; Guid: TGuid; const Name: tbtString): TPSInterface;
+var
+ f: TPSType;
+begin
+ if FProcs = nil then raise EPSCompilerException.Create(RPS_OnUseEventOnly);
+ f := FindType(Name);
+ if (f <> nil) and (f is TPSInterfaceType) then
+ begin
+ result := TPSInterfaceType(f).Intf;
+ Result.Guid := Guid;
+ Result.InheritedFrom := InheritedFrom;
+ exit;
+ end;
+ f := AddType(Name, btInterface);
+ Result := TPSInterface.Create(Self, InheritedFrom, GUID, FastUppercase(Name), f);
+ FInterfaces.Add(Result);
+ TPSInterfaceType(f).Intf := Result;
+end;
+
+function TPSPascalCompiler.FindInterface(const Name: tbtString): TPSInterface;
+var
+ n: tbtString;
+ i, nh: Longint;
+begin
+ if FProcs = nil then raise EPSCompilerException.Create(RPS_OnUseEventOnly);
+ n := FastUpperCase(Name);
+ nh := MakeHash(n);
+ for i := FInterfaces.Count -1 downto 0 do
+ begin
+ Result := FInterfaces[i];
+ if (Result.NameHash = nh) and (Result.Name = N) then
+ exit;
+ end;
+ raise EPSCompilerException.CreateFmt(RPS_UnknownInterface, [Name]);
+end;
+{$ENDIF}
+function TPSPascalCompiler.AddClass(InheritsFrom: TPSCompileTimeClass; aClass: TClass): TPSCompileTimeClass;
+var
+ f: TPSType;
+begin
+ if FProcs = nil then raise EPSCompilerException.Create(RPS_OnUseEventOnly);
+ Result := FindClass(tbtstring(aClass.ClassName));
+ if Result <> nil then exit;
+ f := AddType(tbtstring(aClass.ClassName), btClass);
+ Result := TPSCompileTimeClass.CreateC(aClass, Self, f);
+ Result.FInheritsFrom := InheritsFrom;
+ FClasses.Add(Result);
+ TPSClassType(f).Cl := Result;
+ f.ExportName := True;
+end;
+
+function TPSPascalCompiler.AddClassN(InheritsFrom: TPSCompileTimeClass; const aClass: tbtString): TPSCompileTimeClass;
+var
+ f: TPSType;
+begin
+ if FProcs = nil then raise EPSCompilerException.Create(RPS_OnUseEventOnly);
+ Result := FindClass(aClass);
+ if Result <> nil then
+ begin
+ if InheritsFrom <> nil then
+ Result.FInheritsFrom := InheritsFrom;
+ exit;
+ end;
+ f := AddType(aClass, btClass);
+ Result := TPSCompileTimeClass.Create(FastUppercase(aClass), Self, f);
+ TPSClassType(f).Cl := Result;
+ Result.FInheritsFrom := InheritsFrom;
+ FClasses.Add(Result);
+ TPSClassType(f).Cl := Result;
+ f.ExportName := True;
+end;
+
+function TPSPascalCompiler.FindClass(const aClass: tbtString): TPSCompileTimeClass;
+var
+ i: Longint;
+ Cl: tbtString;
+ H: Longint;
+ x: TPSCompileTimeClass;
+begin
+ cl := FastUpperCase(aClass);
+ H := MakeHash(Cl);
+ for i :=0 to FClasses.Count -1 do
+ begin
+ x := FClasses[I];
+ if (X.FClassNameHash = H) and (X.FClassName = Cl) then
+ begin
+ Result := X;
+ Exit;
+ end;
+ end;
+ Result := nil;
+end;
+
+
+
+{ }
+
+function TransDoubleToStr(D: Double): tbtString;
+begin
+ SetLength(Result, SizeOf(Double));
+ Double((@Result[1])^) := D;
+end;
+
+function TransSingleToStr(D: Single): tbtString;
+begin
+ SetLength(Result, SizeOf(Single));
+ Single((@Result[1])^) := D;
+end;
+
+function TransExtendedToStr(D: Extended): tbtString;
+begin
+ SetLength(Result, SizeOf(Extended));
+ Extended((@Result[1])^) := D;
+end;
+
+function TransLongintToStr(D: Longint): tbtString;
+begin
+ SetLength(Result, SizeOf(Longint));
+ Longint((@Result[1])^) := D;
+end;
+
+function TransCardinalToStr(D: Cardinal): tbtString;
+begin
+ SetLength(Result, SizeOf(Cardinal));
+ Cardinal((@Result[1])^) := D;
+end;
+
+function TransWordToStr(D: Word): tbtString;
+begin
+ SetLength(Result, SizeOf(Word));
+ Word((@Result[1])^) := D;
+end;
+
+function TransSmallIntToStr(D: SmallInt): tbtString;
+begin
+ SetLength(Result, SizeOf(SmallInt));
+ SmallInt((@Result[1])^) := D;
+end;
+
+function TransByteToStr(D: Byte): tbtString;
+begin
+ SetLength(Result, SizeOf(Byte));
+ Byte((@Result[1])^) := D;
+end;
+
+function TransShortIntToStr(D: ShortInt): tbtString;
+begin
+ SetLength(Result, SizeOf(ShortInt));
+ ShortInt((@Result[1])^) := D;
+end;
+
+function TPSPascalCompiler.GetConstant(const Name: tbtString): TPSConstant;
+var
+ h, i: Longint;
+ n: tbtString;
+
+begin
+ n := FastUppercase(name);
+ h := MakeHash(n);
+ for i := 0 to FConstants.Count -1 do
+ begin
+ result := TPSConstant(FConstants[i]);
+ if (Result.NameHash = h) and (Result.Name = n) then exit;
+ end;
+ result := nil;
+end;
+
+{$IFDEF PS_USESSUPPORT}
+function TPSPascalCompiler.IsInLocalUnitList(s: tbtstring): Boolean;
+begin
+ s:=FastUpperCase(s);
+ if (s=FastUpperCase(fModule)) or (s='SYSTEM') then
+ begin
+ result:=true;
+ exit;
+ end;
+ result:=fUnit.HasUses(S);
+end;
+{$ENDIF}
+
+{ TPSType }
+
+constructor TPSType.Create;
+begin
+ inherited Create;
+ FAttributes := TPSAttributes.Create;
+ FFinalTypeNo := InvalidVal;
+end;
+
+destructor TPSType.Destroy;
+begin
+ FAttributes.Free;
+ inherited Destroy;
+end;
+
+procedure TPSType.SetName(const Value: tbtString);
+begin
+ FName := Value;
+ FNameHash := MakeHash(Value);
+end;
+
+procedure TPSType.Use;
+begin
+ FUsed := True;
+end;
+
+{ TPSRecordType }
+
+function TPSRecordType.AddRecVal: PIFPSRecordFieldTypeDef;
+begin
+ Result := TPSRecordFieldTypeDef.Create;
+ FRecordSubVals.Add(Result);
+end;
+
+constructor TPSRecordType.Create;
+begin
+ inherited Create;
+ FRecordSubVals := TPSList.Create;
+end;
+
+destructor TPSRecordType.Destroy;
+var
+ i: Longint;
+begin
+ for i := FRecordSubVals.Count -1 downto 0 do
+ TPSRecordFieldTypeDef(FRecordSubVals[I]).Free;
+ FRecordSubVals.Free;
+ inherited Destroy;
+end;
+
+function TPSRecordType.RecVal(I: Longint): PIFPSRecordFieldTypeDef;
+begin
+ Result := FRecordSubVals[I]
+end;
+
+function TPSRecordType.RecValCount: Longint;
+begin
+ Result := FRecordSubVals.Count;
+end;
+
+
+{ TPSRegProc }
+
+constructor TPSRegProc.Create;
+begin
+ inherited Create;
+ FDecl := TPSParametersDecl.Create;
+end;
+
+destructor TPSRegProc.Destroy;
+begin
+ FDecl.Free;
+ inherited Destroy;
+end;
+
+procedure TPSRegProc.SetName(const Value: tbtString);
+begin
+ FName := Value;
+ FNameHash := MakeHash(FName);
+end;
+
+{ TPSRecordFieldTypeDef }
+
+procedure TPSRecordFieldTypeDef.SetFieldOrgName(const Value: tbtString);
+begin
+ FFieldOrgName := Value;
+ FFieldName := FastUppercase(Value);
+ FFieldNameHash := MakeHash(FFieldName);
+end;
+
+{ TPSProcVar }
+
+procedure TPSProcVar.SetName(const Value: tbtString);
+begin
+ FName := Value;
+ FNameHash := MakeHash(FName);
+end;
+
+procedure TPSProcVar.Use;
+begin
+ FUsed := True;
+end;
+
+
+
+{ TPSInternalProcedure }
+
+constructor TPSInternalProcedure.Create;
+begin
+ inherited Create;
+ FProcVars := TPSList.Create;
+ FLabels := TIfStringList.Create;
+ FGotos := TIfStringList.Create;
+ FDecl := TPSParametersDecl.Create;
+end;
+
+destructor TPSInternalProcedure.Destroy;
+var
+ i: Longint;
+begin
+ FDecl.Free;
+ for i := FProcVars.Count -1 downto 0 do
+ TPSProcVar(FProcVars[I]).Free;
+ FProcVars.Free;
+ FGotos.Free;
+ FLabels.Free;
+ inherited Destroy;
+end;
+
+procedure TPSInternalProcedure.ResultUse;
+begin
+ FResultUsed := True;
+end;
+
+procedure TPSInternalProcedure.SetName(const Value: tbtString);
+begin
+ FName := Value;
+ FNameHash := MakeHash(FName);
+end;
+
+procedure TPSInternalProcedure.Use;
+begin
+ FUsed := True;
+end;
+
+{ TPSProcedure }
+constructor TPSProcedure.Create;
+begin
+ inherited Create;
+ FAttributes := TPSAttributes.Create;
+end;
+
+destructor TPSProcedure.Destroy;
+begin
+ FAttributes.Free;
+ inherited Destroy;
+end;
+
+{ TPSVar }
+
+procedure TPSVar.SetName(const Value: tbtString);
+begin
+ FName := Value;
+ FNameHash := MakeHash(Value);
+end;
+
+procedure TPSVar.Use;
+begin
+ FUsed := True;
+end;
+
+{ TPSConstant }
+
+destructor TPSConstant.Destroy;
+begin
+ DisposeVariant(Value);
+ inherited Destroy;
+end;
+
+procedure TPSConstant.SetChar(c: tbtChar);
+begin
+ if (FValue <> nil) then
+ begin
+ case FValue.FType.BaseType of
+ btChar: FValue.tchar := c;
+ btString: tbtString(FValue.tstring) := c;
+ {$IFNDEF PS_NOWIDESTRING}
+ btWideString: tbtwidestring(FValue.twidestring) := tbtWidestring(c);
+ btUnicodeString: tbtUnicodestring(FValue.twidestring) := tbtUnicodestring(c);
+ {$ENDIF}
+ else
+ raise EPSCompilerException.Create(RPS_ConstantValueMismatch);
+ end;
+ end else
+ raise EPSCompilerException.Create(RPS_ConstantValueNotAssigned)
+end;
+
+procedure TPSConstant.SetExtended(const Val: Extended);
+begin
+ if (FValue <> nil) then
+ begin
+ case FValue.FType.BaseType of
+ btSingle: FValue.tsingle := Val;
+ btDouble: FValue.tdouble := Val;
+ btExtended: FValue.textended := Val;
+ btCurrency: FValue.tcurrency := Val;
+ else
+ raise EPSCompilerException.Create(RPS_ConstantValueMismatch);
+ end;
+ end else
+ raise EPSCompilerException.Create(RPS_ConstantValueNotAssigned)
+end;
+
+procedure TPSConstant.SetInt(const Val: Longint);
+begin
+ if (FValue <> nil) then
+ begin
+ case FValue.FType.BaseType of
+ btEnum: FValue.tu32 := Val;
+ btU32, btS32: FValue.ts32 := Val;
+ btU16, btS16: FValue.ts16 := Val;
+ btU8, btS8: FValue.ts8 := Val;
+ btSingle: FValue.tsingle := Val;
+ btDouble: FValue.tdouble := Val;
+ btExtended: FValue.textended := Val;
+ btCurrency: FValue.tcurrency := Val;
+ {$IFNDEF PS_NOINT64}
+ bts64: FValue.ts64 := Val;
+ {$ENDIF}
+ else
+ raise EPSCompilerException.Create(RPS_ConstantValueMismatch);
+ end;
+ end else
+ raise EPSCompilerException.Create(RPS_ConstantValueNotAssigned)
+end;
+{$IFNDEF PS_NOINT64}
+procedure TPSConstant.SetInt64(const Val: Int64);
+begin
+ if (FValue <> nil) then
+ begin
+ case FValue.FType.BaseType of
+ btEnum: FValue.tu32 := Val;
+ btU32, btS32: FValue.ts32 := Val;
+ btU16, btS16: FValue.ts16 := Val;
+ btU8, btS8: FValue.ts8 := Val;
+ btSingle: FValue.tsingle := Val;
+ btDouble: FValue.tdouble := Val;
+ btExtended: FValue.textended := Val;
+ btCurrency: FValue.tcurrency := Val;
+ bts64: FValue.ts64 := Val;
+ else
+ raise EPSCompilerException.Create(RPS_ConstantValueMismatch);
+ end;
+ end else
+ raise EPSCompilerException.Create(RPS_ConstantValueNotAssigned)
+end;
+{$ENDIF}
+procedure TPSConstant.SetName(const Value: tbtString);
+begin
+ FName := Value;
+ FNameHash := MakeHash(Value);
+end;
+
+
+procedure TPSConstant.SetSet(const val);
+begin
+ if (FValue <> nil) then
+ begin
+ case FValue.FType.BaseType of
+ btSet:
+ begin
+ if length(tbtstring(FValue.tstring)) <> TPSSetType(FValue.FType).ByteSize then
+ SetLength(tbtstring(FValue.tstring), TPSSetType(FValue.FType).ByteSize);
+ Move(Val, FValue.tstring^, TPSSetType(FValue.FType).ByteSize);
+ end;
+ else
+ raise EPSCompilerException.Create(RPS_ConstantValueMismatch);
+ end;
+ end else
+ raise EPSCompilerException.Create(RPS_ConstantValueNotAssigned)
+end;
+
+procedure TPSConstant.SetString(const Val: tbtString);
+begin
+ if (FValue <> nil) then
+ begin
+ case FValue.FType.BaseType of
+ btChar: FValue.tchar := (Val+#0)[1];
+ btWideChar: FValue.twidechar := WideChar((Val+#0)[1]);
+ btString: tbtString(FValue.tstring) := val;
+ {$IFNDEF PS_NOWIDESTRING}
+ btWideString: tbtwidestring(FValue.twidestring) := tbtwidestring(val);
+ btUnicodeString: tbtunicodestring(FValue.tunistring) := tbtunicodestring(val);
+ {$ENDIF}
+ else
+ raise EPSCompilerException.Create(RPS_ConstantValueMismatch);
+ end;
+ end else
+ raise EPSCompilerException.Create(RPS_ConstantValueNotAssigned)
+end;
+
+procedure TPSConstant.SetUInt(const Val: Cardinal);
+begin
+ if (FValue <> nil) then
+ begin
+ case FValue.FType.BaseType of
+ btEnum: FValue.tu32 := Val;
+ btU32, btS32: FValue.tu32 := Val;
+ btU16, btS16: FValue.tu16 := Val;
+ btU8, btS8: FValue.tu8 := Val;
+ btSingle: FValue.tsingle := Val;
+ btDouble: FValue.tdouble := Val;
+ btExtended: FValue.textended := Val;
+ btCurrency: FValue.tcurrency := Val;
+ {$IFNDEF PS_NOINT64}
+ bts64: FValue.ts64 := Val;
+ {$ENDIF}
+ else
+ raise EPSCompilerException.Create(RPS_ConstantValueMismatch);
+ end;
+ end else
+ raise EPSCompilerException.Create(RPS_ConstantValueNotAssigned)
+end;
+
+{$IFNDEF PS_NOWIDESTRING}
+procedure TPSConstant.SetWideChar(const val: WideChar);
+begin
+ if (FValue <> nil) then
+ begin
+ case FValue.FType.BaseType of
+ btString: tbtString(FValue.tstring) := tbtstring(val);
+ btWideChar: FValue.twidechar := val;
+ btWideString: tbtwidestring(FValue.twidestring) := val;
+ btUnicodeString: tbtUnicodestring(FValue.tUniString) := val;
+ else
+ raise EPSCompilerException.Create(RPS_ConstantValueMismatch);
+ end;
+ end else
+ raise EPSCompilerException.Create(RPS_ConstantValueNotAssigned)
+end;
+
+procedure TPSConstant.SetWideString(const val: tbtwidestring);
+begin
+ if (FValue <> nil) then
+ begin
+ case FValue.FType.BaseType of
+ btString: tbtString(FValue.tstring) := tbtstring(val);
+ btWideString: tbtwidestring(FValue.twidestring) := val;
+ btUnicodeString: tbtunicodestring(FValue.tunistring) := val;
+ else
+ raise EPSCompilerException.Create(RPS_ConstantValueMismatch);
+ end;
+ end else
+ raise EPSCompilerException.Create(RPS_ConstantValueNotAssigned)
+end;
+procedure TPSConstant.SetUnicodeString(const val: tbtunicodestring);
+begin
+ if (FValue <> nil) then
+ begin
+ case FValue.FType.BaseType of
+ btString: tbtString(FValue.tstring) := tbtstring(val);
+ btWideString: tbtwidestring(FValue.twidestring) := val;
+ btUnicodeString: tbtunicodestring(FValue.tunistring) := val;
+ else
+ raise EPSCompilerException.Create(RPS_ConstantValueMismatch);
+ end;
+ end else
+ raise EPSCompilerException.Create(RPS_ConstantValueNotAssigned)
+end;
+{$ENDIF}
+{ TPSPascalCompilerError }
+
+function TPSPascalCompilerError.ErrorType: tbtString;
+begin
+ Result := tbtstring(RPS_Error);
+end;
+
+function TPSPascalCompilerError.ShortMessageToString: tbtString;
+begin
+ case Error of
+ ecUnknownIdentifier: Result := tbtstring(Format (RPS_UnknownIdentifier, [Param]));
+ ecIdentifierExpected: Result := tbtstring(RPS_IdentifierExpected);
+ ecCommentError: Result := tbtstring(RPS_CommentError);
+ ecStringError: Result := tbtstring(RPS_StringError);
+ ecCharError: Result := tbtstring(RPS_CharError);
+ ecSyntaxError: Result := tbtstring(RPS_SyntaxError);
+ ecUnexpectedEndOfFile: Result := tbtstring(RPS_EOF);
+ ecSemicolonExpected: Result := tbtstring(RPS_SemiColonExpected);
+ ecBeginExpected: Result := tbtstring(RPS_BeginExpected);
+ ecPeriodExpected: Result := tbtstring(RPS_PeriodExpected);
+ ecDuplicateIdentifier: Result := tbtstring(Format (RPS_DuplicateIdent, [Param]));
+ ecColonExpected: Result := tbtstring(RPS_ColonExpected);
+ ecUnknownType: Result := tbtstring(Format (RPS_UnknownType, [Param]));
+ ecCloseRoundExpected: Result := tbtstring(RPS_CloseRoundExpected);
+ ecTypeMismatch: Result := tbtstring(RPS_TypeMismatch);
+ ecInternalError: Result := tbtstring(Format (RPS_InternalError, [Param]));
+ ecAssignmentExpected: Result := tbtstring(RPS_AssignmentExpected);
+ ecThenExpected: Result := tbtstring(RPS_ThenExpected);
+ ecDoExpected: Result := tbtstring(RPS_DoExpected);
+ ecNoResult: Result := tbtstring(RPS_NoResult);
+ ecOpenRoundExpected: Result := tbtstring(RPS_OpenRoundExpected);
+ ecCommaExpected: Result := tbtstring(RPS_CommaExpected);
+ ecToExpected: Result := tbtstring(RPS_ToExpected);
+ ecIsExpected: Result := tbtstring(RPS_IsExpected);
+ ecOfExpected: Result := tbtstring(RPS_OfExpected);
+ ecCloseBlockExpected: Result := tbtstring(RPS_CloseBlockExpected);
+ ecVariableExpected: Result := tbtstring(RPS_VariableExpected);
+ ecStringExpected: result := tbtstring(RPS_StringExpected);
+ ecEndExpected: Result := tbtstring(RPS_EndExpected);
+ ecUnSetLabel: Result := tbtstring(Format (RPS_UnSetLabel, [Param]));
+ ecNotInLoop: Result := tbtstring(RPS_NotInLoop);
+ ecInvalidJump: Result := tbtstring(RPS_InvalidJump);
+ ecOpenBlockExpected: Result := tbtstring(RPS_OpenBlockExpected);
+ ecWriteOnlyProperty: Result := tbtstring(RPS_WriteOnlyProperty);
+ ecReadOnlyProperty: Result := tbtstring(RPS_ReadOnlyProperty);
+ ecClassTypeExpected: Result := tbtstring(RPS_ClassTypeExpected);
+ ecCustomError: Result := Param;
+ ecDivideByZero: Result := tbtstring(RPS_DivideByZero);
+ ecMathError: Result := tbtstring(RPS_MathError);
+ ecUnsatisfiedForward: Result := tbtstring(Format (RPS_UnsatisfiedForward, [Param]));
+ ecForwardParameterMismatch: Result := tbtstring(RPS_ForwardParameterMismatch);
+ ecInvalidnumberOfParameters: Result := tbtstring(RPS_InvalidNumberOfParameter);
+ {$IFDEF PS_USESSUPPORT}
+ ecNotAllowed : Result:=tbtstring(Format(RPS_NotAllowed,[Param]));
+ ecUnitNotFoundOrContainsErrors: Result:=tbtstring(Format(RPS_UnitNotFound,[Param]));
+ ecCrossReference: Result:=Format(RPS_CrossReference,[Param]);
+ {$ENDIF}
+ else
+ Result := tbtstring(RPS_UnknownError);
+ end;
+ Result := Result;
+end;
+
+
+{ TPSPascalCompilerHint }
+
+function TPSPascalCompilerHint.ErrorType: tbtString;
+begin
+ Result := tbtstring(RPS_Hint);
+end;
+
+function TPSPascalCompilerHint.ShortMessageToString: tbtString;
+begin
+ case Hint of
+ ehVariableNotUsed: Result := tbtstring(Format (RPS_VariableNotUsed, [Param]));
+ ehFunctionNotUsed: Result := tbtstring(Format (RPS_FunctionNotUsed, [Param]));
+ ehCustomHint: Result := Param;
+ else
+ Result := tbtstring(RPS_UnknownHint);
+ end;
+end;
+
+{ TPSPascalCompilerWarning }
+
+function TPSPascalCompilerWarning.ErrorType: tbtString;
+begin
+ Result := tbtstring(RPS_Warning);
+end;
+
+function TPSPascalCompilerWarning.ShortMessageToString: tbtString;
+begin
+ case Warning of
+ ewCustomWarning: Result := Param;
+ ewCalculationAlwaysEvaluatesTo: Result := tbtstring(Format (RPS_CalculationAlwaysEvaluatesTo, [Param]));
+ ewIsNotNeeded: Result := tbtstring(Format (RPS_IsNotNeeded, [Param]));
+ ewAbstractClass: Result := tbtstring(RPS_AbstractClass);
+ else
+ Result := tbtstring(RPS_UnknownWarning);
+ end;
+end;
+
+{ TPSPascalCompilerMessage }
+
+function TPSPascalCompilerMessage.MessageToString: tbtString;
+begin
+ Result := '['+ErrorType+'] '+FModuleName+'('+IntToStr(FRow)+':'+IntToStr(FCol)+'): '+ShortMessageToString;
+end;
+
+procedure TPSPascalCompilerMessage.SetParserPos(Parser: TPSPascalParser);
+begin
+ FPosition := Parser.CurrTokenPos;
+ FRow := Parser.Row;
+ FCol := Parser.Col;
+end;
+
+procedure TPSPascalCompilerMessage.SetCustomPos(Pos, Row, Col: Cardinal);
+begin
+ FPosition := Pos;
+ FRow := Row;
+ FCol := Col;
+end;
+
+{ TUnConstOperation }
+
+destructor TUnConstOperation.Destroy;
+begin
+ FVal1.Free;
+ inherited Destroy;
+end;
+
+
+{ TBinConstOperation }
+
+destructor TBinConstOperation.Destroy;
+begin
+ FVal1.Free;
+ FVal2.Free;
+ inherited Destroy;
+end;
+
+{ TConstData }
+
+destructor TConstData.Destroy;
+begin
+ DisposeVariant(FData);
+ inherited Destroy;
+end;
+
+
+{ TConstOperation }
+
+procedure TConstOperation.SetPos(Parser: TPSPascalParser);
+begin
+ FDeclPosition := Parser.CurrTokenPos;
+ FDeclRow := Parser.Row;
+ FDeclCol := Parser.Col;
+end;
+
+{ TPSValue }
+
+procedure TPSValue.SetParserPos(P: TPSPascalParser);
+begin
+ FPos := P.CurrTokenPos;
+ FRow := P.Row;
+ FCol := P.Col;
+end;
+
+{ TPSValueData }
+
+destructor TPSValueData.Destroy;
+begin
+ DisposeVariant(FData);
+ inherited Destroy;
+end;
+
+
+{ TPSValueReplace }
+
+constructor TPSValueReplace.Create;
+begin
+ FFreeNewValue := True;
+ FReplaceTimes := 1;
+end;
+
+destructor TPSValueReplace.Destroy;
+begin
+ if FFreeOldValue then
+ FOldValue.Free;
+ if FFreeNewValue then
+ FNewValue.Free;
+ inherited Destroy;
+end;
+
+
+
+{ TPSUnValueOp }
+
+destructor TPSUnValueOp.Destroy;
+begin
+ FVal1.Free;
+ inherited Destroy;
+end;
+
+{ TPSBinValueOp }
+
+destructor TPSBinValueOp.Destroy;
+begin
+ FVal1.Free;
+ FVal2.Free;
+ inherited Destroy;
+end;
+
+
+
+
+{ TPSSubValue }
+
+destructor TPSSubValue.Destroy;
+begin
+ FSubNo.Free;
+ inherited Destroy;
+end;
+
+{ TPSValueVar }
+
+constructor TPSValueVar.Create;
+begin
+ inherited Create;
+ FRecItems := TPSList.Create;
+end;
+
+destructor TPSValueVar.Destroy;
+var
+ i: Longint;
+begin
+ for i := 0 to FRecItems.Count -1 do
+ begin
+ TPSSubItem(FRecItems[I]).Free;
+ end;
+ FRecItems.Free;
+ inherited Destroy;
+end;
+
+function TPSValueVar.GetRecCount: Cardinal;
+begin
+ Result := FRecItems.Count;
+end;
+
+function TPSValueVar.GetRecItem(I: Cardinal): TPSSubItem;
+begin
+ Result := FRecItems[I];
+end;
+
+function TPSValueVar.RecAdd(Val: TPSSubItem): Cardinal;
+begin
+ Result := FRecItems.Add(Val);
+end;
+
+procedure TPSValueVar.RecDelete(I: Cardinal);
+var
+ rr :TPSSubItem;
+begin
+ rr := FRecItems[i];
+ FRecItems.Delete(I);
+ rr.Free;
+end;
+
+{ TPSValueProc }
+
+destructor TPSValueProc.Destroy;
+begin
+ FSelfPtr.Free;
+ FParameters.Free;
+end;
+{ TPSParameter }
+
+destructor TPSParameter.Destroy;
+begin
+ FTempVar.Free;
+ FValue.Free;
+ inherited Destroy;
+end;
+
+
+ { TPSParameters }
+
+function TPSParameters.Add: TPSParameter;
+begin
+ Result := TPSParameter.Create;
+ FItems.Add(Result);
+end;
+
+constructor TPSParameters.Create;
+begin
+ inherited Create;
+ FItems := TPSList.Create;
+end;
+
+procedure TPSParameters.Delete(I: Cardinal);
+var
+ p: TPSParameter;
+begin
+ p := FItems[I];
+ FItems.Delete(i);
+ p.Free;
+end;
+
+destructor TPSParameters.Destroy;
+var
+ i: Longint;
+begin
+ for i := FItems.Count -1 downto 0 do
+ begin
+ TPSParameter(FItems[I]).Free;
+ end;
+ FItems.Free;
+ inherited Destroy;
+end;
+
+function TPSParameters.GetCount: Cardinal;
+begin
+ Result := FItems.Count;
+end;
+
+function TPSParameters.GetItem(I: Longint): TPSParameter;
+begin
+ Result := FItems[I];
+end;
+
+
+{ TPSValueArray }
+
+function TPSValueArray.Add(Item: TPSValue): Cardinal;
+begin
+ Result := FItems.Add(Item);
+end;
+
+constructor TPSValueArray.Create;
+begin
+ inherited Create;
+ FItems := TPSList.Create;
+end;
+
+procedure TPSValueArray.Delete(I: Cardinal);
+begin
+ FItems.Delete(i);
+end;
+
+destructor TPSValueArray.Destroy;
+var
+ i: Longint;
+begin
+ for i := FItems.Count -1 downto 0 do
+ TPSValue(FItems[I]).Free;
+ FItems.Free;
+
+ inherited Destroy;
+end;
+
+function TPSValueArray.GetCount: Cardinal;
+begin
+ Result := FItems.Count;
+end;
+
+function TPSValueArray.GetItem(I: Cardinal): TPSValue;
+begin
+ Result := FItems[I];
+end;
+
+
+{ TPSValueAllocatedStackVar }
+
+destructor TPSValueAllocatedStackVar.Destroy;
+var
+ pv: TPSProcVar;
+begin
+ {$IFDEF DEBUG}
+ if Cardinal(LocalVarNo +1) <> proc.ProcVars.Count then
+ begin
+ Abort;
+ exit;
+ end;
+ {$ENDIF}
+ if Proc <> nil then
+ begin
+ pv := Proc.ProcVars[Proc.ProcVars.Count -1];
+ Proc.ProcVars.Delete(Proc.ProcVars.Count -1);
+ pv.Free;
+ Proc.Data := Proc.Data + tbtChar(CM_PO);
+ end;
+ inherited Destroy;
+end;
+
+
+
+
+function AddImportedClassVariable(Sender: TPSPascalCompiler; const VarName, VarType: tbtString): Boolean;
+var
+ P: TPSVar;
+begin
+ P := Sender.AddVariableN(VarName, VarType);
+ if p = nil then
+ begin
+ Result := False;
+ Exit;
+ end;
+ SetVarExportName(P, FastUppercase(VarName));
+ p.Use;
+ Result := True;
+end;
+
+
+{'class:'+CLASSNAME+'|'+FUNCNAME+'|'+chr(CallingConv)+chr(hasresult)+params
+
+For property write functions there is an '@' after the funcname.
+}
+
+const
+ ProcHDR = 'procedure a;';
+
+
+
+{ TPSCompileTimeClass }
+
+function TPSCompileTimeClass.CastToType(IntoType: TPSType;
+ var ProcNo: Cardinal): Boolean;
+var
+ P: TPSExternalProcedure;
+begin
+ if (IntoType <> nil) and (IntoType.BaseType <> btClass) and (IntoType.BaseType <> btInterface) then
+ begin
+ Result := False;
+ exit;
+ end;
+ if FCastProc <> InvalidVal then
+ begin
+ Procno := FCastProc;
+ Result := True;
+ exit;
+ end;
+ ProcNo := FOwner. AddUsedFunction2(P);
+ P.RegProc := FOwner.AddFunction(ProcHDR);
+ P.RegProc.Name := '';
+
+ with P.RegProc.Decl.AddParam do
+ begin
+ OrgName := 'Org';
+ aType := Self.FType;
+ end;
+ with P.RegProc.Decl.AddParam do
+ begin
+ OrgName := 'TypeNo';
+ aType := FOwner.at2ut(FOwner.FindBaseType(btU32));
+ end;
+ P.RegProc.Decl.Result := IntoType;
+ P.RegProc.ImportDecl := 'class:+';
+ FCastProc := ProcNo;
+ Result := True;
+end;
+
+
+function TPSCompileTimeClass.ClassFunc_Call(Index: IPointer;
+ var ProcNo: Cardinal): Boolean;
+var
+ C: TPSDelphiClassItemConstructor;
+ P: TPSExternalProcedure;
+ s: tbtString;
+ i: Longint;
+
+begin
+ if FIsAbstract then
+ FOwner.MakeWarning('', ewAbstractClass, '');
+ C := Pointer(Index);
+ if c.MethodNo = InvalidVal then
+ begin
+ ProcNo := FOwner.AddUsedFunction2(P);
+ P.RegProc := FOwner.AddFunction(ProcHDR);
+ P.RegProc.Name := '';
+ P.RegProc.Decl.Assign(c.Decl);
+ s := 'class:' + C.Owner.FClassName + '|' + C.Name + '|'+ chr(0);
+ if c.Decl.Result = nil then
+ s := s + #0
+ else
+ s := s + #1;
+ for i := 0 to C.Decl.ParamCount -1 do
+ begin
+ if c.Decl.Params[i].Mode <> pmIn then
+ s := s + #1
+ else
+ s := s + #0;
+ end;
+ P.RegProc.ImportDecl := s;
+ C.MethodNo := ProcNo;
+ end else begin
+ ProcNo := c.MethodNo;
+ end;
+ Result := True;
+end;
+
+function TPSCompileTimeClass.ClassFunc_Find(const Name: tbtString;
+ var Index: IPointer): Boolean;
+var
+ H: Longint;
+ I: Longint;
+ CurrClass: TPSCompileTimeClass;
+ C: TPSDelphiClassItem;
+begin
+ H := MakeHash(Name);
+ CurrClass := Self;
+ while CurrClass <> nil do
+ begin
+ for i := CurrClass.FClassItems.Count -1 downto 0 do
+ begin
+ C := CurrClass.FClassItems[I];
+ if (c is TPSDelphiClassItemConstructor) and (C.NameHash = H) and (C.Name = Name) then
+ begin
+ Index := Cardinal(C);
+ Result := True;
+ exit;
+ end;
+ end;
+ CurrClass := CurrClass.FInheritsFrom;
+ end;
+ Result := False;
+end;
+
+
+class function TPSCompileTimeClass.CreateC(FClass: TClass; aOwner: TPSPascalCompiler; aType: TPSType): TPSCompileTimeClass;
+begin
+ Result := TPSCompileTimeClass.Create(FastUpperCase(tbtstring(FClass.ClassName)), aOwner, aType);
+ Result.FClass := FClass;
+end;
+
+constructor TPSCompileTimeClass.Create(ClassName: tbtString; aOwner: TPSPascalCompiler; aType: TPSType);
+begin
+ inherited Create;
+ FType := aType;
+ FCastProc := InvalidVal;
+ FNilProc := InvalidVal;
+
+ FDefaultProperty := InvalidVal;
+ FClassName := Classname;
+ FClassNameHash := MakeHash(FClassName);
+ FClassItems := TPSList.Create;
+ FOwner := aOwner;
+end;
+
+destructor TPSCompileTimeClass.Destroy;
+var
+ I: Longint;
+begin
+ for i := FClassItems.Count -1 downto 0 do
+ TPSDelphiClassItem(FClassItems[I]).Free;
+ FClassItems.Free;
+ inherited Destroy;
+end;
+
+
+function TPSCompileTimeClass.Func_Call(Index: IPointer;
+ var ProcNo: Cardinal): Boolean;
+var
+ C: TPSDelphiClassItemMethod;
+ P: TPSExternalProcedure;
+ i: Longint;
+ s: tbtString;
+
+begin
+ C := Pointer(Index);
+ if c.MethodNo = InvalidVal then
+ begin
+ ProcNo := FOwner.AddUsedFunction2(P);
+ P.RegProc := FOwner.AddFunction(ProcHDR);
+ P.RegProc.Name := '';
+ p.RegProc.Decl.Assign(c.Decl);
+ s := 'class:' + C.Owner.FClassName + '|' + C.Name + '|'+ chr(0);
+ if c.Decl.Result = nil then
+ s := s + #0
+ else
+ s := s + #1;
+ for i := 0 to c.Decl.ParamCount -1 do
+ begin
+ if c.Decl.Params[i].Mode <> pmIn then
+ s := s + #1
+ else
+ s := s + #0;
+ end;
+ P.RegProc.ImportDecl := s;
+ C.MethodNo := ProcNo;
+ end else begin
+ ProcNo := c.MethodNo;
+ end;
+ Result := True;
+end;
+
+function TPSCompileTimeClass.Func_Find(const Name: tbtString;
+ var Index: IPointer): Boolean;
+var
+ H: Longint;
+ I: Longint;
+ CurrClass: TPSCompileTimeClass;
+ C: TPSDelphiClassItem;
+begin
+ H := MakeHash(Name);
+ CurrClass := Self;
+ while CurrClass <> nil do
+ begin
+ for i := CurrClass.FClassItems.Count -1 downto 0 do
+ begin
+ C := CurrClass.FClassItems[I];
+ if (c is TPSDelphiClassItemMethod) and (C.NameHash = H) and (C.Name = Name) then
+ begin
+ Index := Cardinal(C);
+ Result := True;
+ exit;
+ end;
+ end;
+ CurrClass := CurrClass.FInheritsFrom;
+ end;
+ Result := False;
+end;
+
+function TPSCompileTimeClass.GetCount: Longint;
+begin
+ Result := FClassItems.Count;
+end;
+
+function TPSCompileTimeClass.GetItem(i: Longint): TPSDelphiClassItem;
+begin
+ Result := FClassItems[i];
+end;
+
+function TPSCompileTimeClass.IsCompatibleWith(aType: TPSType): Boolean;
+var
+ Temp: TPSCompileTimeClass;
+begin
+ if (atype.BaseType <> btClass) then
+ begin
+ Result := False;
+ exit;
+ end;
+ temp := TPSClassType(aType).Cl;
+ while Temp <> nil do
+ begin
+ if Temp = Self then
+ begin
+ Result := True;
+ exit;
+ end;
+ Temp := Temp.FInheritsFrom;
+ end;
+ Result := False;
+end;
+
+function TPSCompileTimeClass.Property_Find(const Name: tbtString;
+ var Index: IPointer): Boolean;
+var
+ H: Longint;
+ I: Longint;
+ CurrClass: TPSCompileTimeClass;
+ C: TPSDelphiClassItem;
+begin
+ if Name = '' then
+ begin
+ CurrClass := Self;
+ while CurrClass <> nil do
+ begin
+ if CurrClass.FDefaultProperty <> InvalidVal then
+ begin
+ Index := Cardinal(CurrClass.FClassItems[Currclass.FDefaultProperty]);
+ result := True;
+ exit;
+ end;
+ CurrClass := CurrClass.FInheritsFrom;
+ end;
+ Result := False;
+ exit;
+ end;
+ H := MakeHash(Name);
+ CurrClass := Self;
+ while CurrClass <> nil do
+ begin
+ for i := CurrClass.FClassItems.Count -1 downto 0 do
+ begin
+ C := CurrClass.FClassItems[I];
+ if (c is TPSDelphiClassItemProperty) and (C.NameHash = H) and (C.Name = Name) then
+ begin
+ Index := Cardinal(C);
+ Result := True;
+ exit;
+ end;
+ end;
+ CurrClass := CurrClass.FInheritsFrom;
+ end;
+ Result := False;
+end;
+
+function TPSCompileTimeClass.Property_Get(Index: IPointer;
+ var ProcNo: Cardinal): Boolean;
+var
+ C: TPSDelphiClassItemProperty;
+ P: TPSExternalProcedure;
+ s: tbtString;
+
+begin
+ C := Pointer(Index);
+ if c.AccessType = iptW then
+ begin
+ Result := False;
+ exit;
+ end;
+ if c.ReadProcNo = InvalidVal then
+ begin
+ ProcNo := FOwner.AddUsedFunction2(P);
+ P.RegProc := FOwner.AddFunction(ProcHDR);
+ P.RegProc.Name := '';
+ P.RegProc.Decl.Result := C.Decl.Result;
+ s := 'class:' + C.Owner.FClassName + '|' + C.Name + '|'+#0#0#0#0;
+ Longint((@(s[length(s)-3]))^) := c.Decl.ParamCount +1;
+ P.RegProc.ImportDecl := s;
+ C.ReadProcNo := ProcNo;
+ end else begin
+ ProcNo := c.ReadProcNo;
+ end;
+ Result := True;
+end;
+
+function TPSCompileTimeClass.Property_GetHeader(Index: IPointer;
+ Dest: TPSParametersDecl): Boolean;
+var
+ c: TPSDelphiClassItemProperty;
+begin
+ C := Pointer(Index);
+ FOwner.UseProc(c.Decl);
+ Dest.Assign(c.Decl);
+ Result := True;
+end;
+
+function TPSCompileTimeClass.Property_Set(Index: IPointer;
+ var ProcNo: Cardinal): Boolean;
+var
+ C: TPSDelphiClassItemProperty;
+ P: TPSExternalProcedure;
+ s: tbtString;
+
+begin
+ C := Pointer(Index);
+ if c.AccessType = iptR then
+ begin
+ Result := False;
+ exit;
+ end;
+ if c.WriteProcNo = InvalidVal then
+ begin
+ ProcNo := FOwner.AddUsedFunction2(P);
+ P.RegProc := FOwner.AddFunction(ProcHDR);
+ P.RegProc.Name := '';
+ s := 'class:' + C.Owner.FClassName + '|' + C.Name + '@|'#0#0#0#0;
+ Longint((@(s[length(s)-3]))^) := C.Decl.ParamCount+1;
+ P.RegProc.ImportDecl := s;
+ C.WriteProcNo := ProcNo;
+ end else begin
+ ProcNo := c.WriteProcNo;
+ end;
+ Result := True;
+end;
+
+function TPSCompileTimeClass.RegisterMethod(const Decl: tbtString): Boolean;
+var
+ DOrgName: tbtString;
+ DDecl: TPSParametersDecl;
+ FT: TPMFuncType;
+ p: TPSDelphiClassItemMethod;
+begin
+ DDecl := TPSParametersDecl.Create;
+ try
+ if not ParseMethod(FOwner, FClassName, Decl, DOrgName, DDecl, FT) then
+ begin
+ Result := False;
+ {$IFDEF DEBUG} raise EPSCompilerException.CreateFmt(RPS_UnableToRegister, [Decl]); {$ENDIF}
+ exit;
+ end;
+ if ft = mftConstructor then
+ p := TPSDelphiClassItemConstructor.Create(Self)
+ else
+ p := TPSDelphiClassItemMethod.Create(self);
+ p.OrgName := DOrgName;
+ p.Decl.Assign(DDecl);
+ p.MethodNo := InvalidVal;
+ FClassItems.Add(p);
+ Result := True;
+ finally
+ DDecl.Free;
+ end;
+end;
+
+procedure TPSCompileTimeClass.RegisterProperty(const PropertyName,
+ PropertyType: tbtString; PropAC: TPSPropType);
+var
+ FType: TPSType;
+ Param: TPSParameterDecl;
+ p: TPSDelphiClassItemProperty;
+ PT: tbtString;
+begin
+ pt := PropertyType;
+ p := TPSDelphiClassItemProperty.Create(Self);
+ p.AccessType := PropAC;
+ p.ReadProcNo := InvalidVal;
+ p.WriteProcNo := InvalidVal;
+ p.OrgName := PropertyName;
+ repeat
+ FType := FOwner.FindType(FastUpperCase(grfw(pt)));
+ if FType = nil then
+ begin
+ p.Free;
+ Exit;
+ end;
+ if p.Decl.Result = nil then p.Decl.Result := FType else
+ begin
+ param := p.Decl.AddParam;
+ Param.OrgName := 'param'+IntToStr(p.Decl.ParamCount);
+ Param.aType := FType;
+ end;
+ until pt = '';
+ FClassItems.Add(p);
+end;
+
+
+procedure TPSCompileTimeClass.RegisterPublishedProperties;
+var
+ p: PPropList;
+ i, Count: Longint;
+ a: TPSPropType;
+begin
+ if (Fclass = nil) or (Fclass.ClassInfo = nil) then exit;
+ Count := GetTypeData(fclass.ClassInfo)^.PropCount;
+ GetMem(p, Count * SizeOf(Pointer));
+ GetPropInfos(fclass.ClassInfo, p);
+ for i := Count -1 downto 0 do
+ begin
+ if p^[i]^.PropType^.Kind in [tkLString, tkInteger, tkChar, tkEnumeration, tkFloat, tkString, tkSet, tkClass, tkMethod{$IFNDEF PS_NOWIDESTRING}, tkWString{$ENDIF}] then
+ begin
+ if (p^[i]^.GetProc <> nil) then
+ begin
+ if p^[i]^.SetProc = nil then
+ a := iptr
+ else
+ a := iptrw;
+ end else
+ begin
+ a := iptW;
+ if p^[i]^.SetProc = nil then continue;
+ end;
+ RegisterProperty(p^[i]^.Name, p^[i]^.PropType^.Name, a);
+ end;
+ end;
+ FreeMem(p);
+end;
+
+function TPSCompileTimeClass.RegisterPublishedProperty(const Name: tbtString): Boolean;
+var
+ p: PPropInfo;
+ a: TPSPropType;
+begin
+ if (Fclass = nil) or (Fclass.ClassInfo = nil) then begin Result := False; exit; end;
+ p := GetPropInfo(fclass.ClassInfo, string(Name));
+ if p = nil then begin Result := False; exit; end;
+ if (p^.GetProc <> nil) then
+ begin
+ if p^.SetProc = nil then
+ a := iptr
+ else
+ a := iptrw;
+ end else
+ begin
+ a := iptW;
+ if p^.SetProc = nil then begin result := False; exit; end;
+ end;
+ RegisterProperty(p^.Name, p^.PropType^.Name, a);
+ Result := True;
+end;
+
+
+procedure TPSCompileTimeClass.SetDefaultPropery(const Name: tbtString);
+var
+ i,h: Longint;
+ p: TPSDelphiClassItem;
+ s: tbtString;
+
+begin
+ s := FastUppercase(name);
+ h := MakeHash(s);
+ for i := FClassItems.Count -1 downto 0 do
+ begin
+ p := FClassItems[i];
+ if (p.NameHash = h) and (p.Name = s) then
+ begin
+ if p is TPSDelphiClassItemProperty then
+ begin
+ if p.Decl.ParamCount = 0 then
+ Raise EPSCompilerException.Create(RPS_NotArrayProperty);
+ FDefaultProperty := I;
+ exit;
+ end else Raise EPSCompilerException.Create(RPS_NotProperty);
+ end;
+ end;
+ raise EPSCompilerException.Create(RPS_UnknownProperty);
+end;
+
+function TPSCompileTimeClass.SetNil(var ProcNo: Cardinal): Boolean;
+var
+ P: TPSExternalProcedure;
+
+begin
+ if FNilProc <> InvalidVal then
+ begin
+ Procno := FNilProc;
+ Result := True;
+ exit;
+ end;
+ ProcNo := FOwner.AddUsedFunction2(P);
+ P.RegProc := FOwner.AddFunction(ProcHDR);
+ P.RegProc.Name := '';
+ with P.RegProc.Decl.AddParam do
+ begin
+ OrgName := 'VarNo';
+ aType := FOwner.at2ut(FType);
+ end;
+ P.RegProc.ImportDecl := 'class:-';
+ FNilProc := Procno;
+ Result := True;
+end;
+
+{ TPSSetType }
+
+function TPSSetType.GetBitSize: Longint;
+begin
+ case SetType.BaseType of
+ btEnum: begin Result := TPSEnumType(setType).HighValue+1; end;
+ btChar, btU8: Result := 256;
+ else
+ Result := 0;
+ end;
+end;
+
+function TPSSetType.GetByteSize: Longint;
+var
+ r: Longint;
+begin
+ r := BitSize;
+ if r mod 8 <> 0 then inc(r, 7);
+ Result := r div 8;
+end;
+
+
+{ TPSBlockInfo }
+
+procedure TPSBlockInfo.Clear;
+var
+ i: Longint;
+begin
+ for i := WithList.Count -1 downto 0 do
+ begin
+ TPSValue(WithList[i]).Free;
+ WithList.Delete(i);
+ end;
+end;
+
+constructor TPSBlockInfo.Create(Owner: TPSBlockInfo);
+begin
+ inherited Create;
+ FOwner := Owner;
+ FWithList := TPSList.Create;
+ if FOwner <> nil then
+ begin
+ FProcNo := FOwner.ProcNo;
+ FProc := FOwner.Proc;
+ end;
+end;
+
+destructor TPSBlockInfo.Destroy;
+begin
+ Clear;
+ FWithList.Free;
+ inherited Destroy;
+end;
+
+{ TPSAttributeTypeField }
+procedure TPSAttributeTypeField.SetFieldOrgName(const Value: tbtString);
+begin
+ FFieldOrgName := Value;
+ FFieldName := FastUpperCase(Value);
+ FFieldNameHash := MakeHash(FFieldName);
+end;
+
+constructor TPSAttributeTypeField.Create(AOwner: TPSAttributeType);
+begin
+ inherited Create;
+ FOwner := AOwner;
+end;
+
+{ TPSAttributeType }
+
+function TPSAttributeType.GetField(I: Longint): TPSAttributeTypeField;
+begin
+ Result := TPSAttributeTypeField(FFields[i]);
+end;
+
+function TPSAttributeType.GetFieldCount: Longint;
+begin
+ Result := FFields.Count;
+end;
+
+procedure TPSAttributeType.SetName(const s: tbtString);
+begin
+ FOrgname := s;
+ FName := FastUppercase(s);
+ FNameHash := MakeHash(FName);
+end;
+
+constructor TPSAttributeType.Create;
+begin
+ inherited Create;
+ FFields := TPSList.Create;
+end;
+
+destructor TPSAttributeType.Destroy;
+var
+ i: Longint;
+begin
+ for i := FFields.Count -1 downto 0 do
+ begin
+ TPSAttributeTypeField(FFields[i]).Free;
+ end;
+ FFields.Free;
+ inherited Destroy;
+end;
+
+function TPSAttributeType.AddField: TPSAttributeTypeField;
+begin
+ Result := TPSAttributeTypeField.Create(self);
+ FFields.Add(Result);
+end;
+
+procedure TPSAttributeType.DeleteField(I: Longint);
+var
+ Fld: TPSAttributeTypeField;
+begin
+ Fld := FFields[i];
+ FFields.Delete(i);
+ Fld.Free;
+end;
+
+{ TPSAttribute }
+function TPSAttribute.GetValueCount: Longint;
+begin
+ Result := FValues.Count;
+end;
+
+function TPSAttribute.GetValue(I: Longint): PIfRVariant;
+begin
+ Result := FValues[i];
+end;
+
+constructor TPSAttribute.Create(AttribType: TPSAttributeType);
+begin
+ inherited Create;
+ FValues := TPSList.Create;
+ FAttribType := AttribType;
+end;
+
+procedure TPSAttribute.DeleteValue(i: Longint);
+var
+ Val: PIfRVariant;
+begin
+ Val := FValues[i];
+ FValues.Delete(i);
+ DisposeVariant(Val);
+end;
+
+function TPSAttribute.AddValue(v: PIFRVariant): Longint;
+begin
+ Result := FValues.Add(v);
+end;
+
+
+destructor TPSAttribute.Destroy;
+var
+ i: Longint;
+begin
+ for i := FValues.Count -1 downto 0 do
+ begin
+ DisposeVariant(FValues[i]);
+ end;
+ FValues.Free;
+ inherited Destroy;
+end;
+
+
+procedure TPSAttribute.Assign(Item: TPSAttribute);
+var
+ i: Longint;
+ p: PIfRVariant;
+begin
+ for i := FValues.Count -1 downto 0 do
+ begin
+ DisposeVariant(FValues[i]);
+ end;
+ FValues.Clear;
+ FAttribType := Item.FAttribType;
+ for i := 0 to Item.FValues.Count -1 do
+ begin
+ p := DuplicateVariant(Item.FValues[i]);
+ FValues.Add(p);
+ end;
+end;
+
+{ TPSAttributes }
+
+function TPSAttributes.GetCount: Longint;
+begin
+ Result := FItems.Count;
+end;
+
+function TPSAttributes.GetItem(I: Longint): TPSAttribute;
+begin
+ Result := TPSAttribute(FItems[i]);
+end;
+
+procedure TPSAttributes.Delete(i: Longint);
+var
+ item: TPSAttribute;
+begin
+ item := TPSAttribute(FItems[i]);
+ FItems.Delete(i);
+ Item.Free;
+end;
+
+function TPSAttributes.Add(AttribType: TPSAttributeType): TPSAttribute;
+begin
+ Result := TPSAttribute.Create(AttribType);
+ FItems.Add(Result);
+end;
+
+constructor TPSAttributes.Create;
+begin
+ inherited Create;
+ FItems := TPSList.Create;
+end;
+
+destructor TPSAttributes.Destroy;
+var
+ i: Longint;
+begin
+ for i := FItems.Count -1 downto 0 do
+ begin
+ TPSAttribute(FItems[i]).Free;
+ end;
+ FItems.Free;
+ inherited Destroy;
+end;
+
+procedure TPSAttributes.Assign(attr: TPSAttributes; Move: Boolean);
+var
+ newitem, item: TPSAttribute;
+ i: Longint;
+begin
+ for i := ATtr.FItems.Count -1 downto 0 do
+ begin
+ Item := Attr.Fitems[i];
+ if Move then
+ begin
+ FItems.Add(Item);
+ Attr.FItems.Delete(i);
+ end else
+ begin
+ newitem := TPSAttribute.Create(Item.FAttribType );
+ newitem.Assign(item);
+ FItems.Add(NewItem);
+ end;
+ end;
+
+end;
+
+
+function TPSAttributes.FindAttribute(
+ const Name: tbtString): TPSAttribute;
+var
+ h, i: Longint;
+
+begin
+ h := MakeHash(name);
+ for i := FItems.Count -1 downto 0 do
+ begin
+ Result := FItems[i];
+ if (Result.FAttribType.NameHash = h) and (Result.FAttribType.Name = Name) then
+ exit;
+ end;
+ result := nil;
+end;
+
+{ TPSParameterDecl }
+procedure TPSParameterDecl.SetName(const s: tbtString);
+begin
+ FOrgName := s;
+ FName := FastUppercase(s);
+end;
+
+
+{ TPSParametersDecl }
+
+procedure TPSParametersDecl.Assign(Params: TPSParametersDecl);
+var
+ i: Longint;
+ np, orgp: TPSParameterDecl;
+begin
+ for i := FParams.Count -1 downto 0 do
+ begin
+ TPSParameterDecl(Fparams[i]).Free;
+ end;
+ FParams.Clear;
+ FResult := Params.Result;
+
+ for i := 0 to Params.FParams.count -1 do
+ begin
+ orgp := Params.FParams[i];
+ np := AddParam;
+ np.OrgName := orgp.OrgName;
+ np.Mode := orgp.Mode;
+ np.aType := orgp.aType;
+ np.DeclarePos:=orgp.DeclarePos;
+ np.DeclareRow:=orgp.DeclareRow;
+ np.DeclareCol:=orgp.DeclareCol;
+ end;
+end;
+
+
+function TPSParametersDecl.GetParam(I: Longint): TPSParameterDecl;
+begin
+ Result := FParams[i];
+end;
+
+function TPSParametersDecl.GetParamCount: Longint;
+begin
+ Result := FParams.Count;
+end;
+
+function TPSParametersDecl.AddParam: TPSParameterDecl;
+begin
+ Result := TPSParameterDecl.Create;
+ FParams.Add(Result);
+end;
+
+procedure TPSParametersDecl.DeleteParam(I: Longint);
+var
+ param: TPSParameterDecl;
+begin
+ param := FParams[i];
+ FParams.Delete(i);
+ Param.Free;
+end;
+
+constructor TPSParametersDecl.Create;
+begin
+ inherited Create;
+ FParams := TPSList.Create;
+end;
+
+destructor TPSParametersDecl.Destroy;
+var
+ i: Longint;
+begin
+ for i := FParams.Count -1 downto 0 do
+ begin
+ TPSParameterDecl(Fparams[i]).Free;
+ end;
+ FParams.Free;
+ inherited Destroy;
+end;
+
+function TPSParametersDecl.Same(d: TPSParametersDecl): boolean;
+var
+ i: Longint;
+begin
+ if (d = nil) or (d.ParamCount <> ParamCount) or (d.Result <> Self.Result) then
+ Result := False
+ else begin
+ for i := 0 to d.ParamCount -1 do
+ begin
+ if (d.Params[i].Mode <> Params[i].Mode) or (d.Params[i].aType <> Params[i].aType) then
+ begin
+ Result := False;
+ exit;
+ end;
+ end;
+ Result := True;
+ end;
+end;
+
+{ TPSProceduralType }
+
+constructor TPSProceduralType.Create;
+begin
+ inherited Create;
+ FProcDef := TPSParametersDecl.Create;
+
+end;
+
+destructor TPSProceduralType.Destroy;
+begin
+ FProcDef.Free;
+ inherited Destroy;
+end;
+
+{ TPSDelphiClassItem }
+
+procedure TPSDelphiClassItem.SetName(const s: tbtString);
+begin
+ FOrgName := s;
+ FName := FastUpperCase(s);
+ FNameHash := MakeHash(FName);
+end;
+
+constructor TPSDelphiClassItem.Create(Owner: TPSCompileTimeClass);
+begin
+ inherited Create;
+ FOwner := Owner;
+ FDecl := TPSParametersDecl.Create;
+end;
+
+destructor TPSDelphiClassItem.Destroy;
+begin
+ FDecl.Free;
+ inherited Destroy;
+end;
+
+{$IFNDEF PS_NOINTERFACES}
+{ TPSInterface }
+
+function TPSInterface.CastToType(IntoType: TPSType;
+ var ProcNo: Cardinal): Boolean;
+var
+ P: TPSExternalProcedure;
+begin
+ if (IntoType <> nil) and (IntoType.BaseType <> btInterface) then
+ begin
+ Result := False;
+ exit;
+ end;
+ if FCastProc <> InvalidVal then
+ begin
+ ProcNo := FCastProc;
+ Result := True;
+ exit;
+ end;
+ ProcNo := FOwner.AddUsedFunction2(P);
+ P.RegProc := FOwner.AddFunction(ProcHDR);
+ P.RegProc.Name := '';
+ with P.RegProc.Decl.AddParam do
+ begin
+ OrgName := 'Org';
+ aType := Self.FType;
+ end;
+ with P.RegProc.Decl.AddParam do
+ begin
+ OrgName := 'TypeNo';
+ aType := FOwner.at2ut(FOwner.FindBaseType(btU32));
+ end;
+ P.RegProc.Decl.Result := FOwner.at2ut(IntoType);
+
+ P.RegProc.ImportDecl := 'class:+';
+ FCastProc := ProcNo;
+ Result := True;
+end;
+
+constructor TPSInterface.Create(Owner: TPSPascalCompiler; InheritedFrom: TPSInterface; Guid: TGuid; const Name: tbtString; aType: TPSType);
+begin
+ inherited Create;
+ FCastProc := InvalidVal;
+ FNilProc := InvalidVal;
+
+ FType := aType;
+ FOWner := Owner;
+ FGuid := GUID;
+ Self.InheritedFrom := InheritedFrom;
+
+ FItems := TPSList.Create;
+ FName := Name;
+ FNameHash := MakeHash(Name);
+end;
+
+procedure TPSInterface.SetInheritedFrom(p: TPSInterface);
+begin
+ FInheritedFrom := p;
+end;
+
+destructor TPSInterface.Destroy;
+var
+ i: Longint;
+begin
+ for i := FItems.Count -1 downto 0 do
+ begin
+ TPSInterfaceMethod(FItems[i]).Free;
+ end;
+ FItems.Free;
+ inherited Destroy;
+end;
+
+function TPSInterface.Func_Call(Index: Cardinal;
+ var ProcNo: Cardinal): Boolean;
+var
+ c: TPSInterfaceMethod;
+ P: TPSExternalProcedure;
+ s: tbtString;
+ i: Longint;
+begin
+ c := TPSInterfaceMethod(Index);
+ if c.FScriptProcNo <> InvalidVal then
+ begin
+ Procno := c.FScriptProcNo;
+ Result := True;
+ exit;
+ end;
+ ProcNo := FOwner.AddUsedFunction2(P);
+ P.RegProc := FOwner.AddFunction(ProcHDR);
+ P.RegProc.Name := '';
+ FOwner.UseProc(C.Decl);
+ P.RegProc.Decl.Assign(c.Decl);
+ s := tbtstring('intf:.') + PS_mi2s(c.AbsoluteProcOffset) + tbtchar(ord(c.CC));
+ if c.Decl.Result = nil then
+ s := s + #0
+ else
+ s := s + #1;
+ for i := 0 to C.Decl.ParamCount -1 do
+ begin
+ if c.Decl.Params[i].Mode <> pmIn then
+ s := s + #1
+ else
+ s := s + #0;
+ end;
+ P.RegProc.ImportDecl := s;
+ C.FScriptProcNo := ProcNo;
+ Result := True;
+end;
+
+function TPSInterface.Func_Find(const Name: tbtString;
+ var Index: Cardinal): Boolean;
+var
+ H: Longint;
+ I: Longint;
+ CurrClass: TPSInterface;
+ C: TPSInterfaceMethod;
+begin
+ H := MakeHash(Name);
+ CurrClass := Self;
+ while CurrClass <> nil do
+ begin
+ for i := CurrClass.FItems.Count -1 downto 0 do
+ begin
+ C := CurrClass.FItems[I];
+ if (C.NameHash = H) and (C.Name = Name) then
+ begin
+ Index := Cardinal(c);
+ Result := True;
+ exit;
+ end;
+ end;
+ CurrClass := CurrClass.FInheritedFrom;
+ end;
+ Result := False;
+end;
+
+function TPSInterface.IsCompatibleWith(aType: TPSType): Boolean;
+var
+ Temp: TPSInterface;
+begin
+ if (atype.BaseType = btClass) then // just support it, we'll see what happens
+ begin
+ Result := true;
+ exit;
+ end;
+ if atype.BaseType <> btInterface then
+ begin
+ Result := False;
+ exit;
+ end;
+ temp := TPSInterfaceType(atype).FIntf;
+ while Temp <> nil do
+ begin
+ if Temp = Self then
+ begin
+ Result := True;
+ exit;
+ end;
+ Temp := Temp.FInheritedFrom;
+ end;
+ Result := False;
+end;
+
+procedure TPSInterface.RegisterDummyMethod;
+begin
+ FItems.Add(TPSInterfaceMethod.Create(self));
+end;
+
+function TPSInterface.RegisterMethod(const Declaration: tbtString;
+ const cc: TPSCallingConvention): Boolean;
+begin
+ Result := RegisterMethodEx(Declaration, cc, nil);
+end;
+
+function TPSInterface.RegisterMethodEx(const Declaration: tbtString;
+ const cc: TPSCallingConvention; const CustomParser: TPSPascalParser): Boolean;
+var
+ M: TPSInterfaceMethod;
+ DOrgName: tbtString;
+ Func: TPMFuncType;
+begin
+ M := TPSInterfaceMethod.Create(Self);
+ if not ParseMethodEx(FOwner, '', Declaration, DOrgname, m.Decl, Func, CustomParser) then
+ begin
+ FItems.Add(m); // in any case, add a dummy item
+ Result := False;
+ exit;
+ end;
+ m.FName := FastUppercase(DOrgName);
+ m.FOrgName := DOrgName;
+ m.FNameHash := MakeHash(m.FName);
+ m.FCC := CC;
+ m.FScriptProcNo := InvalidVal;
+ FItems.Add(M);
+ Result := True;
+end;
+
+
+function TPSInterface.SetNil(var ProcNo: Cardinal): Boolean;
+var
+ P: TPSExternalProcedure;
+
+begin
+ if FNilProc <> InvalidVal then
+ begin
+ Procno := FNilProc;
+ Result := True;
+ exit;
+ end;
+ ProcNo := FOwner.AddUsedFunction2(P);
+ P.RegProc := FOwner.AddFunction(ProcHDR);
+ P.RegProc.Name := '';
+ with p.RegProc.Decl.AddParam do
+ begin
+ Mode := pmInOut;
+ OrgName := 'VarNo';
+ aType := FOwner.at2ut(Self.FType);
+ end;
+ P.RegProc.ImportDecl := 'class:-';
+ FNilProc := Procno;
+ Result := True;
+end;
+
+{ TPSInterfaceMethod }
+
+constructor TPSInterfaceMethod.Create(Owner: TPSInterface);
+begin
+ inherited Create;
+ FDecl := TPSParametersDecl.Create;
+ FOwner := Owner;
+ FOffsetCache := InvalidVal;
+end;
+
+function TPSInterfaceMethod.GetAbsoluteProcOffset: Cardinal;
+var
+ ps: TPSInterface;
+begin
+ if FOffsetCache = InvalidVal then
+ begin
+ FOffsetCache := FOwner.FItems.IndexOf(Self);
+ ps := FOwner.FInheritedFrom;
+ while ps <> nil do
+ begin
+ FOffsetCache := FOffsetCache + ps.FItems.Count;
+ ps := ps.FInheritedFrom;
+ end;
+ end;
+ result := FOffsetCache;
+end;
+
+
+destructor TPSInterfaceMethod.Destroy;
+begin
+ FDecl.Free;
+ inherited Destroy;
+end;
+{$ENDIF}
+
+{ TPSVariantType }
+
+function TPSVariantType.GetDynInvokeParamType(Owner: TPSPascalCompiler) : TPSType;
+begin
+ Result := Owner.at2ut(FindAndAddType(owner, '!OPENARRAYOFVARIANT', 'array of variant'));
+end;
+
+function TPSVariantType.GetDynInvokeProcNo(Owner: TPSPascalCompiler; const Name: tbtString;
+ Params: TPSParameters): Cardinal;
+begin
+ Result := Owner.FindProc('IDISPATCHINVOKE');
+end;
+
+function TPSVariantType.GetDynIvokeResulType(
+ Owner: TPSPascalCompiler): TPSType;
+begin
+ Result := Owner.FindType('VARIANT');
+end;
+
+function TPSVariantType.GetDynIvokeSelfType(Owner: TPSPascalCompiler): TPSType;
+begin
+ Result := Owner.at2ut(Owner.FindType('IDISPATCH'));
+end;
+
+
+{ TPSExternalClass }
+function TPSExternalClass.SetNil(var ProcNo: Cardinal): Boolean;
+begin
+ Result := False;
+end;
+
+constructor TPSExternalClass.Create(Se: TIFPSPascalCompiler; TypeNo: TPSType);
+begin
+ inherited Create;
+ Self.SE := se;
+ Self.FTypeNo := TypeNo;
+end;
+
+function TPSExternalClass.Func_Call(Index: Cardinal;
+ var ProcNo: Cardinal): Boolean;
+begin
+ Result := False;
+end;
+
+function TPSExternalClass.Func_Find(const Name: tbtString;
+ var Index: Cardinal): Boolean;
+begin
+ Result := False;
+end;
+
+function TPSExternalClass.IsCompatibleWith(
+ Cl: TPSExternalClass): Boolean;
+begin
+ Result := False;
+end;
+
+function TPSExternalClass.SelfType: TPSType;
+begin
+ Result := nil;
+end;
+
+function TPSExternalClass.CastToType(IntoType: TPSType;
+ var ProcNo: Cardinal): Boolean;
+begin
+ Result := False;
+end;
+
+function TPSExternalClass.CompareClass(OtherTypeNo: TPSType;
+ var ProcNo: Cardinal): Boolean;
+begin
+ Result := false;
+end;
+
+function TPSExternalClass.ClassFunc_Find(const Name: tbtString; var Index: Cardinal): Boolean;
+begin
+ result := false;
+end;
+
+function TPSExternalClass.ClassFunc_Call(Index: Cardinal; var ProcNo: Cardinal): Boolean;
+begin
+ result := false;
+end;
+
+
+{ TPSValueProcVal }
+
+destructor TPSValueProcVal.Destroy;
+begin
+ FProcNo.Free;
+ inherited;
+end;
+
+
+{
+
+Internal error counter: 00020 (increase and then use)
+
+}
+end.
diff --git a/branches/script-component/Units/PascalScript/uPSComponent.pas b/branches/script-component/Units/PascalScript/uPSComponent.pas
new file mode 100644
index 0000000..44cfb54
--- /dev/null
+++ b/branches/script-component/Units/PascalScript/uPSComponent.pas
@@ -0,0 +1,1511 @@
+unit uPSComponent;
+{$I PascalScript.inc}
+interface
+
+uses
+ SysUtils, Classes, uPSRuntime, uPSDebugger, uPSUtils,
+ uPSCompiler, uPSC_dll, uPSR_dll, uPSPreProcessor;
+
+const
+ {alias to @link(ifps3.cdRegister)}
+ cdRegister = uPSRuntime.cdRegister;
+ {alias to @link(ifps3.cdPascal)}
+ cdPascal = uPSRuntime.cdPascal;
+
+ CdCdecl = uPSRuntime.CdCdecl;
+
+ CdStdCall = uPSRuntime.CdStdCall;
+
+type
+ TPSScript = class;
+
+ TDelphiCallingConvention = uPSRuntime.TPSCallingConvention;
+ {Alias to @link(ifps3.TPSRuntimeClassImporter)}
+ TPSRuntimeClassImporter = uPSRuntime.TPSRuntimeClassImporter;
+
+ TPSPlugin = class(TComponent)
+ public
+ procedure CompOnUses(CompExec: TPSScript); virtual;
+
+ procedure ExecOnUses(CompExec: TPSScript); virtual;
+
+ procedure CompileImport1(CompExec: TPSScript); virtual;
+
+ procedure CompileImport2(CompExec: TPSScript); virtual;
+
+ procedure ExecImport1(CompExec: TPSScript; const ri: TPSRuntimeClassImporter); virtual;
+
+ procedure ExecImport2(CompExec: TPSScript; const ri: TPSRuntimeClassImporter); virtual;
+ end;
+
+ TIFPS3Plugin = class(TPSPlugin);
+
+ TPSDllPlugin = class(TPSPlugin)
+ public
+ procedure CompOnUses(CompExec: TPSScript); override;
+ procedure ExecOnUses(CompExec: TPSScript); override;
+ end;
+
+ TIFPS3DllPlugin = class(TPSDllPlugin);
+
+
+ TPSPluginItem = class(TCollectionItem)
+ private
+ FPlugin: TPSPlugin;
+ procedure SetPlugin(const Value: TPSPlugin);
+ protected
+ function GetDisplayName: string; override;
+ public
+ procedure Assign(Source: TPersistent); override; //Birb
+ published
+ property Plugin: TPSPlugin read FPlugin write SetPlugin;
+ end;
+
+
+ TIFPS3CEPluginItem = class(TPSPluginItem);
+
+
+ TPSPlugins = class(TCollection)
+ private
+ FCompExec: TPSScript;
+ protected
+
+ function GetOwner: TPersistent; override;
+ public
+
+ constructor Create(CE: TPSScript);
+ end;
+
+ TIFPS3CEPlugins = class(TPSPlugins);
+
+
+ TPSOnGetNotVariant = function (Sender: TPSScript; const Name: tbtstring): Variant of object;
+ TPSOnSetNotVariant = procedure (Sender: TPSScript; const Name: tbtstring; V: Variant) of object;
+ TPSCompOptions = set of (icAllowNoBegin, icAllowUnit, icAllowNoEnd, icBooleanShortCircuit);
+
+ TPSVerifyProc = procedure (Sender: TPSScript; Proc: TPSInternalProcedure; const Decl: tbtstring; var Error: Boolean) of object;
+
+ TPSEvent = procedure (Sender: TPSScript) of object;
+
+ TPSOnCompImport = procedure (Sender: TObject; x: TPSPascalCompiler) of object;
+
+ TPSOnExecImport = procedure (Sender: TObject; se: TPSExec; x: TPSRuntimeClassImporter) of object;
+ {Script engine event function}
+ TPSOnNeedFile = function (Sender: TObject; const OrginFileName: tbtstring; var FileName, Output: tbtstring): Boolean of object;
+
+ TPSOnProcessDirective = procedure (
+ Sender: TPSPreProcessor;
+ Parser: TPSPascalPreProcessorParser;
+ const Active: Boolean;
+ const DirectiveName, DirectiveParam: tbtstring;
+ Var Continue: Boolean) of Object; // jgv
+
+ TPSScript = class(TComponent)
+ private
+ FOnGetNotificationVariant: TPSOnGetNotVariant;
+ FOnSetNotificationVariant: TPSOnSetNotVariant;
+ FCanAdd: Boolean;
+ FComp: TPSPascalCompiler;
+ FCompOptions: TPSCompOptions;
+ FExec: TPSDebugExec;
+ FSuppressLoadData: Boolean;
+ FScript: TStrings;
+ FOnLine: TNotifyEvent;
+ FUseDebugInfo: Boolean;
+ FOnAfterExecute, FOnCompile, FOnExecute: TPSEvent;
+ FOnCompImport: TPSOnCompImport;
+ FOnExecImport: TPSOnExecImport;
+ RI: TPSRuntimeClassImporter;
+ FPlugins: TPSPlugins;
+ FPP: TPSPreProcessor;
+ FMainFileName: tbtstring;
+ FOnNeedFile: TPSOnNeedFile;
+ FUsePreProcessor: Boolean;
+ FDefines: TStrings;
+ FOnVerifyProc: TPSVerifyProc;
+ FOnProcessDirective: TPSOnProcessDirective;
+ FOnProcessUnknowDirective: TPSOnProcessDirective;
+ FOnFindUnknownFile: TPSOnNeedFile;
+ function GetRunning: Boolean;
+ procedure SetScript(const Value: TStrings);
+ function GetCompMsg(i: Integer): TPSPascalCompilerMessage;
+ function GetCompMsgCount: Longint;
+ function GetAbout: tbtstring;
+ function ScriptUses(Sender: TPSPascalCompiler; const Name: tbtstring): Boolean;
+ function GetExecErrorByteCodePosition: Cardinal;
+ function GetExecErrorCode: TIFError;
+ function GetExecErrorParam: tbtstring;
+ function GetExecErrorProcNo: Cardinal;
+ function GetExecErrorString: tbtstring;
+ function GetExecErrorPosition: Cardinal;
+ function GetExecErrorCol: Cardinal;
+ function GetExecErrorRow: Cardinal;
+ function GetExecErrorFileName: tbtstring;
+ procedure SetDefines(const Value: TStrings);
+ protected
+ procedure Notification(AComponent: TComponent; Operation: TOperation); override;
+
+ protected
+ //jgv move where private before - not very usefull
+ procedure OnLineEvent; virtual;
+ procedure SetMainFileName(const Value: tbtstring); virtual;
+
+ //--jgv new
+ function DoOnNeedFile (Sender: TObject; const OrginFileName: tbtstring; var FileName, Output: tbtstring): Boolean; virtual;
+ function DoOnUnknowUses (Sender: TPSPascalCompiler; const Name: tbtstring): Boolean; virtual; // return true if processed
+ procedure DoOnCompImport; virtual;
+ procedure DoOnCompile; virtual;
+ function DoVerifyProc (Sender: TPSScript; Proc: TPSInternalProcedure; const Decl: tbtstring): Boolean; virtual;
+
+ procedure DoOnExecImport (RunTimeImporter: TPSRuntimeClassImporter); virtual;
+ procedure DoOnExecute (RunTimeImporter: TPSRuntimeClassImporter); virtual;
+ procedure DoAfterExecute; virtual;
+ function DoOnGetNotificationVariant (const Name: tbtstring): Variant; virtual;
+ procedure DoOnSetNotificationVariant (const Name: tbtstring; V: Variant); virtual;
+
+ procedure DoOnProcessDirective (Sender: TPSPreProcessor;
+ Parser: TPSPascalPreProcessorParser;
+ const Active: Boolean;
+ const DirectiveName, DirectiveParam: tbtstring;
+ Var Continue: Boolean); virtual;
+ procedure DoOnProcessUnknowDirective (Sender: TPSPreProcessor;
+ Parser: TPSPascalPreProcessorParser;
+ const Active: Boolean;
+ const DirectiveName, DirectiveParam: tbtstring;
+ Var Continue: Boolean); virtual;
+ public
+ property RuntimeImporter: TPSRuntimeClassImporter read RI;
+
+ function FindNamedType(const Name: tbtstring): TPSTypeRec;
+
+ function FindBaseType(Bt: TPSBaseType): TPSTypeRec;
+
+ property SuppressLoadData: Boolean read FSuppressLoadData write FSuppressLoadData;
+
+ function LoadExec: Boolean;
+
+ procedure Stop; virtual;
+
+ constructor Create(AOwner: TComponent); override;
+
+ destructor Destroy; override;
+
+ function Compile: Boolean; virtual;
+
+ function Execute: Boolean; virtual;
+
+ property Running: Boolean read GetRunning;
+
+ procedure GetCompiled(var data: tbtstring);
+
+ procedure SetCompiled(const Data: tbtstring);
+
+ property Comp: TPSPascalCompiler read FComp;
+
+ property Exec: TPSDebugExec read FExec;
+
+ property CompilerMessageCount: Longint read GetCompMsgCount;
+
+ property CompilerMessages[i: Longint]: TPSPascalCompilerMessage read GetCompMsg;
+
+ function CompilerErrorToStr(I: Longint): tbtstring;
+
+ property ExecErrorCode: TIFError read GetExecErrorCode;
+
+ property ExecErrorParam: tbtstring read GetExecErrorParam;
+
+ property ExecErrorToString: tbtstring read GetExecErrorString;
+
+ property ExecErrorProcNo: Cardinal read GetExecErrorProcNo;
+
+ property ExecErrorByteCodePosition: Cardinal read GetExecErrorByteCodePosition;
+
+ property ExecErrorPosition: Cardinal read GetExecErrorPosition;
+
+ property ExecErrorRow: Cardinal read GetExecErrorRow;
+
+ property ExecErrorCol: Cardinal read GetExecErrorCol;
+
+ property ExecErrorFileName: tbtstring read GetExecErrorFileName;
+
+ function AddFunctionEx(Ptr: Pointer; const Decl: tbtstring; CallingConv: TDelphiCallingConvention): Boolean;
+
+ function AddFunction(Ptr: Pointer; const Decl: tbtstring): Boolean;
+
+
+ function AddMethodEx(Slf, Ptr: Pointer; const Decl: tbtstring; CallingConv: TDelphiCallingConvention): Boolean;
+
+ function AddMethod(Slf, Ptr: Pointer; const Decl: tbtstring): Boolean;
+
+ function AddRegisteredVariable(const VarName, VarType: tbtstring): Boolean;
+ function AddNotificationVariant(const VarName: tbtstring): Boolean;
+
+ function AddRegisteredPTRVariable(const VarName, VarType: tbtstring): Boolean;
+
+ function GetVariable(const Name: tbtstring): PIFVariant;
+
+ function SetVarToInstance(const VarName: tbtstring; cl: TObject): Boolean;
+
+ procedure SetPointerToData(const VarName: tbtstring; Data: Pointer; aType: TIFTypeRec);
+
+ function TranslatePositionPos(Proc, Position: Cardinal; var Pos: Cardinal; var fn: tbtstring): Boolean;
+
+ function TranslatePositionRC(Proc, Position: Cardinal; var Row, Col: Cardinal; var fn: tbtstring): Boolean;
+
+ function GetProcMethod(const ProcName: tbtstring): TMethod;
+
+ function ExecuteFunction(const Params: array of Variant; const ProcName: tbtstring): Variant;
+ published
+
+ property About: tbtstring read GetAbout stored false;
+
+ property Script: TStrings read FScript write SetScript;
+
+ property CompilerOptions: TPSCompOptions read FCompOptions write FCompOptions;
+
+ property OnLine: TNotifyEvent read FOnLine write FOnLine;
+
+ property OnCompile: TPSEvent read FOnCompile write FOnCompile;
+
+ property OnExecute: TPSEvent read FOnExecute write FOnExecute;
+
+ property OnAfterExecute: TPSEvent read FOnAfterExecute write FOnAfterExecute;
+
+ property OnCompImport: TPSOnCompImport read FOnCompImport write FOnCompImport;
+
+ property OnExecImport: TPSOnExecImport read FOnExecImport write FOnExecImport;
+
+ property UseDebugInfo: Boolean read FUseDebugInfo write FUseDebugInfo default True;
+
+ property Plugins: TPSPlugins read FPlugins write FPlugins;
+
+ property MainFileName: tbtstring read FMainFileName write SetMainFileName;
+
+ property UsePreProcessor: Boolean read FUsePreProcessor write FUsePreProcessor;
+
+ property OnNeedFile: TPSOnNeedFile read FOnNeedFile write FOnNeedFile;
+
+ property Defines: TStrings read FDefines write SetDefines;
+
+ property OnVerifyProc: TPSVerifyProc read FOnVerifyProc write FOnVerifyProc;
+ property OnGetNotificationVariant: TPSOnGetNotVariant read FOnGetNotificationVariant write FOnGetNotificationVariant;
+ property OnSetNotificationVariant: TPSOnSetNotVariant read FOnSetNotificationVariant write FOnSetNotificationVariant;
+ property OnFindUnknownFile: TPSOnNeedFile read FOnFindUnknownFile write FOnFindUnknownFile;
+
+ published
+ //-- jgv
+ property OnProcessDirective: TPSOnProcessDirective read FOnProcessDirective write FOnProcessDirective;
+ property OnProcessUnknowDirective: TPSOnProcessDirective read FOnProcessUnknowDirective write FOnProcessUnknowDirective;
+ end;
+
+ TIFPS3CompExec = class(TPSScript);
+
+
+ TPSBreakPointInfo = class
+ private
+ FLine: Longint;
+ FFileNameHash: Longint;
+ FFileName: tbtstring;
+ procedure SetFileName(const Value: tbtstring);
+ public
+
+ property FileName: tbtstring read FFileName write SetFileName;
+
+ property FileNameHash: Longint read FFileNameHash;
+
+ property Line: Longint read FLine write FLine;
+ end;
+
+ TPSOnLineInfo = procedure (Sender: TObject; const FileName: tbtstring; Position, Row, Col: Cardinal) of object;
+
+ TPSScriptDebugger = class(TPSScript)
+ private
+ FOnIdle: TNotifyEvent;
+ FBreakPoints: TIFList;
+ FOnLineInfo: TPSOnLineInfo;
+ FLastRow: Cardinal;
+ FOnBreakpoint: TPSOnLineInfo;
+ function GetBreakPoint(I: Integer): TPSBreakPointInfo;
+ function GetBreakPointCount: Longint;
+ protected
+ procedure SetMainFileName(const Value: tbtstring); override;
+ public
+ constructor Create(AOwner: TComponent); override;
+ destructor Destroy; override;
+
+
+ procedure Pause; virtual;
+
+ procedure Resume; virtual;
+
+
+ procedure StepInto; virtual;
+
+ procedure StepOver; virtual;
+
+ procedure SetBreakPoint(const Fn: tbtstring; Line: Longint);
+
+ procedure ClearBreakPoint(const Fn: tbtstring; Line: Longint);
+
+ property BreakPointCount: Longint read GetBreakPointCount;
+
+ property BreakPoint[I: Longint]: TPSBreakPointInfo read GetBreakPoint;
+
+ function HasBreakPoint(const Fn: tbtstring; Line: Longint): Boolean;
+
+ procedure ClearBreakPoints;
+
+ function GetVarContents(const Name: tbtstring): tbtstring;
+ published
+
+ property OnIdle: TNotifyEvent read FOnIdle write FOnIdle;
+
+ property OnLineInfo: TPSOnLineInfo read FOnLineInfo write FOnLineInfo;
+
+ property OnBreakpoint: TPSOnLineInfo read FOnBreakpoint write FOnBreakpoint;
+ end;
+
+ TIFPS3DebugCompExec = class(TPSScriptDebugger);
+
+ TPSCustumPlugin = class(TPSPlugin)
+ private
+ FOnCompileImport2: TPSEvent;
+ FOnExecOnUses: TPSEvent;
+ FOnCompOnUses: TPSEvent;
+ FOnCompileImport1: TPSEvent;
+ FOnExecImport1: TPSOnExecImport;
+ FOnExecImport2: TPSOnExecImport;
+ public
+ procedure CompOnUses(CompExec: TPSScript); override;
+ procedure ExecOnUses(CompExec: TPSScript); override;
+ procedure CompileImport1(CompExec: TPSScript); override;
+ procedure CompileImport2(CompExec: TPSScript); override;
+ procedure ExecImport1(CompExec: TPSScript; const ri: TPSRuntimeClassImporter); override;
+
+ procedure ExecImport2(CompExec: TPSScript; const ri: TPSRuntimeClassImporter); override;
+ public
+ published
+ property OnCompOnUses : TPSEvent read FOnCompOnUses write FOnCompOnUses;
+ property OnExecOnUses: TPSEvent read FOnExecOnUses write FOnExecOnUses;
+ property OnCompileImport1: TPSEvent read FOnCompileImport1 write FOnCompileImport1;
+ property OnCompileImport2: TPSEvent read FOnCompileImport2 write FOnCompileImport2;
+ property OnExecImport1: TPSOnExecImport read FOnExecImport1 write FOnExecImport1;
+ property OnExecImport2: TPSOnExecImport read FOnExecImport2 write FOnExecImport2;
+ end;
+
+implementation
+
+
+{$IFDEF DELPHI3UP }
+resourceString
+{$ELSE }
+const
+{$ENDIF }
+
+ RPS_UnableToReadVariant = 'Unable to read variant';
+ RPS_UnableToWriteVariant = 'Unable to write variant';
+ RPS_ScripEngineAlreadyRunning = 'Script engine already running';
+ RPS_ScriptNotCompiled = 'Script is not compiled';
+ RPS_NotRunning = 'Not running';
+ RPS_UnableToFindVariable = 'Unable to find variable';
+ RPS_UnknownIdentifier = 'Unknown Identifier';
+ RPS_NoScript = 'No script';
+
+function MyGetVariant(Sender: TPSExec; const Name: tbtstring): Variant;
+begin
+ Result := TPSScript (Sender.Id).DoOnGetNotificationVariant(Name);
+end;
+
+procedure MySetVariant(Sender: TPSExec; const Name: tbtstring; V: Variant);
+begin
+ TPSScript (Sender.Id).DoOnSetNotificationVariant(Name, V);
+end;
+
+function CompScriptUses(Sender: TPSPascalCompiler; const Name: tbtstring): Boolean;
+begin
+ Result := TPSScript(Sender.ID).ScriptUses(Sender, Name);
+end;
+
+procedure ExecOnLine(Sender: TPSExec);
+begin
+ if assigned(TPSScript(Sender.ID).FOnLine) then
+ begin
+ TPSScript(Sender.ID).OnLineEvent;
+ end;
+end;
+
+function CompExportCheck(Sender: TPSPascalCompiler; Proc: TPSInternalProcedure; const ProcDecl: tbtstring): Boolean;
+begin
+ Result := TPSScript(Sender.ID).DoVerifyProc (Sender.ID, Proc, ProcDecl);
+end;
+
+
+procedure callObjectOnProcessDirective (
+ Sender: TPSPreProcessor;
+ Parser: TPSPascalPreProcessorParser;
+ const Active: Boolean;
+ const DirectiveName, DirectiveParam: tbtstring;
+ Var Continue: Boolean);
+begin
+ TPSScript (Sender.ID).DoOnProcessUnknowDirective(Sender, Parser, Active, DirectiveName, DirectiveParam, Continue);
+end;
+
+procedure callObjectOnProcessUnknowDirective (
+ Sender: TPSPreProcessor;
+ Parser: TPSPascalPreProcessorParser;
+ const Active: Boolean;
+ const DirectiveName, DirectiveParam: tbtstring;
+ Var Continue: Boolean);
+begin
+ TPSScript (Sender.ID).DoOnProcessDirective(Sender, Parser, Active, DirectiveName, DirectiveParam, Continue);
+end;
+
+
+{ TPSPlugin }
+procedure TPSPlugin.CompileImport1(CompExec: TPSScript);
+begin
+ // do nothing
+end;
+
+procedure TPSPlugin.CompileImport2(CompExec: TPSScript);
+begin
+ // do nothing
+end;
+
+procedure TPSPlugin.CompOnUses(CompExec: TPSScript);
+begin
+ // do nothing
+end;
+
+procedure TPSPlugin.ExecImport1(CompExec: TPSScript; const ri: TPSRuntimeClassImporter);
+begin
+ // do nothing
+end;
+
+procedure TPSPlugin.ExecImport2(CompExec: TPSScript; const ri: TPSRuntimeClassImporter);
+begin
+ // do nothing
+end;
+
+procedure TPSPlugin.ExecOnUses(CompExec: TPSScript);
+begin
+ // do nothing
+end;
+
+
+{ TPSScript }
+
+function TPSScript.AddFunction(Ptr: Pointer;
+ const Decl: tbtstring): Boolean;
+begin
+ Result := AddFunctionEx(Ptr, Decl, cdRegister);
+end;
+
+function TPSScript.AddFunctionEx(Ptr: Pointer; const Decl: tbtstring;
+ CallingConv: TDelphiCallingConvention): Boolean;
+var
+ P: TPSRegProc;
+begin
+ if not FCanAdd then begin Result := False; exit; end;
+ p := Comp.AddDelphiFunction(Decl);
+ if p <> nil then
+ begin
+ Exec.RegisterDelphiFunction(Ptr, p.Name, CallingConv);
+ Result := True;
+ end else Result := False;
+end;
+
+function TPSScript.AddRegisteredVariable(const VarName,
+ VarType: tbtstring): Boolean;
+var
+ FVar: TPSVar;
+begin
+ if not FCanAdd then begin Result := False; exit; end;
+ FVar := FComp.AddUsedVariableN(varname, vartype);
+ if fvar = nil then
+ result := False
+ else begin
+ fvar.exportname := fvar.Name;
+ Result := True;
+ end;
+end;
+
+function CENeedFile(Sender: TPSPreProcessor; const callingfilename: tbtstring; var FileName, Output: tbtstring): Boolean;
+begin
+ Result := TPSScript (Sender.ID).DoOnNeedFile(Sender.ID, CallingFileName, FileName, Output);
+end;
+
+procedure CompTranslateLineInfo(Sender: TPSPascalCompiler; var Pos, Row, Col: Cardinal; var Name: tbtstring);
+var
+ res: TPSLineInfoResults;
+begin
+ if TPSScript(Sender.ID).FPP.CurrentLineInfo.GetLineInfo(Name, Pos, Res) then
+ begin
+ Pos := Res.Pos;
+ Row := Res.Row;
+ Col := Res.Col;
+ Name := Res.Name;
+ end;
+end;
+
+function TPSScript.Compile: Boolean;
+var
+ i: Longint;
+ dta: tbtstring;
+begin
+ FExec.Clear;
+ FExec.CMD_Err(erNoError);
+ FExec.ClearspecialProcImports;
+ FExec.ClearFunctionList;
+ if ri <> nil then
+ begin
+ RI.Free;
+ RI := nil;
+ end;
+ RI := TPSRuntimeClassImporter.Create;
+ for i := 0 to FPlugins.Count -1 do
+ begin
+ if (TPSPluginItem(FPlugins.Items[i]) <> nil) and (TPSPluginItem(FPlugins.Items[i]).Plugin <> nil) then
+ TPSPluginItem(FPlugins.Items[i]).Plugin.ExecImport1(Self, ri);
+ end;
+
+ DoOnExecImport (RI);
+
+ for i := 0 to FPlugins.Count -1 do
+ begin
+ if (TPSPluginItem(FPlugins.Items[i]) <> nil)and (TPSPluginItem(FPlugins.Items[i]).Plugin <> nil) then
+ TPSPluginItem(FPlugins.Items[i]).Plugin.ExecImport2(Self, ri);
+ end;
+ RegisterClassLibraryRuntime(Exec, RI);
+ for i := 0 to FPlugins.Count -1 do
+ begin
+ if (TPSPluginItem(FPlugins.Items[i]) <> nil)and (TPSPluginItem(FPlugins.Items[i]).Plugin <> nil) then
+ TPSPluginItem(FPlugins.Items[i]).Plugin.ExecOnUses(Self);
+ end;
+ FCanAdd := True;
+ FComp.BooleanShortCircuit := icBooleanShortCircuit in FCompOptions;
+ FComp.AllowNoBegin := icAllowNoBegin in FCompOptions;
+ FComp.AllowUnit := icAllowUnit in FCompOptions;
+ FComp.AllowNoEnd := icAllowNoEnd in FCompOptions;
+ if FUsePreProcessor then
+ begin
+ FPP.Clear;
+ FPP.Defines.Assign(FDefines);
+ FComp.OnTranslateLineInfo := CompTranslateLineInfo;
+ Fpp.OnProcessDirective := callObjectOnProcessDirective;
+ Fpp.OnProcessUnknowDirective := callObjectOnProcessUnknowDirective;
+ Fpp.MainFile := FScript.Text;
+ Fpp.MainFileName := FMainFileName;
+ Fpp.PreProcess(FMainFileName, dta);
+ if FComp.Compile(dta) then
+ begin
+ FCanAdd := False;
+ if (not SuppressLoadData) and (not LoadExec) then
+ begin
+ Result := False;
+ end else
+ Result := True;
+ end else Result := False;
+ Fpp.AdjustMessages(Comp);
+ end else
+ begin
+ FComp.OnTranslateLineInfo := nil;
+ if FComp.Compile(FScript.Text) then
+ begin
+ FCanAdd := False;
+ if not LoadExec then
+ begin
+ Result := False;
+ end else
+ Result := True;
+ end else Result := False;
+ end;
+end;
+
+function TPSScript.CompilerErrorToStr(I: Integer): tbtstring;
+begin
+ Result := CompilerMessages[i].MessageToString;
+end;
+
+constructor TPSScript.Create(AOwner: TComponent);
+begin
+ inherited Create(AOwner);
+ FComp := TPSPascalCompiler.Create;
+ FExec := TPSDebugExec.Create;
+ FScript := TStringList.Create;
+ FPlugins := TPSPlugins.Create(self);
+
+ FComp.ID := Self;
+ FComp.OnUses := CompScriptUses;
+ FComp.OnExportCheck := CompExportCheck;
+ FExec.Id := Self;
+ FExec.OnRunLine:= ExecOnLine;
+ FExec.OnGetNVariant := MyGetVariant;
+ FExec.OnSetNVariant := MySetVariant;
+
+ FUseDebugInfo := True;
+
+ FPP := TPSPreProcessor.Create;
+ FPP.Id := Self;
+ FPP.OnNeedFile := CENeedFile;
+
+ FDefines := TStringList.Create;
+end;
+
+destructor TPSScript.Destroy;
+begin
+ FDefines.Free;
+
+ FPP.Free;
+ RI.Free;
+ FPlugins.Free;
+ FPlugins := nil;
+ FScript.Free;
+ FExec.Free;
+ FComp.Free;
+ inherited Destroy;
+end;
+
+function TPSScript.Execute: Boolean;
+begin
+ if Running then raise Exception.Create(RPS_ScripEngineAlreadyRunning);
+ if SuppressLoadData then
+ LoadExec;
+
+ DoOnExecute (RI);
+
+ FExec.DebugEnabled := FUseDebugInfo;
+ Result := FExec.RunScript and (FExec.ExceptionCode = erNoError) ;
+
+ DoAfterExecute;
+end;
+
+function TPSScript.GetAbout: tbtstring;
+begin
+ Result := TPSExec.About;
+end;
+
+procedure TPSScript.GetCompiled(var data: tbtstring);
+begin
+ if not FComp.GetOutput(Data) then
+ raise Exception.Create(RPS_ScriptNotCompiled);
+end;
+
+function TPSScript.GetCompMsg(i: Integer): TPSPascalCompilerMessage;
+begin
+ Result := FComp.Msg[i];
+end;
+
+function TPSScript.GetCompMsgCount: Longint;
+begin
+ Result := FComp.MsgCount;
+end;
+
+function TPSScript.GetExecErrorByteCodePosition: Cardinal;
+begin
+ Result := Exec.ExceptionPos;
+end;
+
+function TPSScript.GetExecErrorCode: TIFError;
+begin
+ Result := Exec.ExceptionCode;
+end;
+
+function TPSScript.GetExecErrorParam: tbtstring;
+begin
+ Result := Exec.ExceptionString;
+end;
+
+function TPSScript.GetExecErrorPosition: Cardinal;
+begin
+ Result := FExec.TranslatePosition(Exec.ExceptionProcNo, Exec.ExceptionPos);
+end;
+
+function TPSScript.GetExecErrorProcNo: Cardinal;
+begin
+ Result := Exec.ExceptionProcNo;
+end;
+
+function TPSScript.GetExecErrorString: tbtstring;
+begin
+ Result := TIFErrorToString(Exec.ExceptionCode, Exec.ExceptionString);
+end;
+
+function TPSScript.GetVariable(const Name: tbtstring): PIFVariant;
+begin
+ Result := FExec.GetVar2(name);
+end;
+
+function TPSScript.LoadExec: Boolean;
+var
+ s: tbtstring;
+begin
+ if (not FComp.GetOutput(s)) or (not FExec.LoadData(s)) then
+ begin
+ Result := False;
+ exit;
+ end;
+ if FUseDebugInfo then
+ begin
+ FComp.GetDebugOutput(s);
+ FExec.LoadDebugData(s);
+ end;
+ Result := True;
+end;
+
+function TPSScript.ScriptUses(Sender: TPSPascalCompiler;
+ const Name: tbtstring): Boolean;
+var
+ i: Longint;
+begin
+ if Name = 'SYSTEM' then
+ begin
+ for i := 0 to FPlugins.Count -1 do
+ begin
+ if (TPSPluginItem(FPlugins.Items[i]) <> nil)and (TPSPluginItem(FPlugins.Items[i]).Plugin <> nil) then
+ TPSPluginItem(FPlugins.Items[i]).Plugin.CompOnUses(Self);
+ end;
+ for i := 0 to FPlugins.Count -1 do
+ begin
+ if (TPSPluginItem(FPlugins.Items[i]) <> nil)and (TPSPluginItem(FPlugins.Items[i]).Plugin <> nil) then
+ TPSPluginItem(FPlugins.Items[i]).Plugin.CompileImport1(self);
+ end;
+
+ DoOnCompImport;
+
+ for i := 0 to FPlugins.Count -1 do
+ begin
+ if (TPSPluginItem(FPlugins.Items[i]) <> nil)and (TPSPluginItem(FPlugins.Items[i]).Plugin <> nil) then
+ TPSPluginItem(FPlugins.Items[i]).Plugin.CompileImport2(Self);
+ end;
+
+ DoOnCompile;
+
+ Result := true;
+ for i := 0 to Sender.MsgCount -1 do begin
+ if Sender.Msg[i] is TPSPascalCompilerError then Result := false;
+ end;
+ end
+ else begin
+ Result := DoOnUnknowUses (Sender, Name);
+{ If Not Result then
+ Sender.MakeError('', ecUnknownIdentifier, Name);}
+ end;
+end;
+
+procedure TPSScript.SetCompiled(const Data: tbtstring);
+var
+ i: Integer;
+begin
+ FExec.Clear;
+ FExec.ClearspecialProcImports;
+ FExec.ClearFunctionList;
+ if ri <> nil then
+ begin
+ RI.Free;
+ RI := nil;
+ end;
+ RI := TPSRuntimeClassImporter.Create;
+ for i := 0 to FPlugins.Count -1 do
+ begin
+ if (TPSPluginItem(FPlugins.Items[i]) <> nil)and (TPSPluginItem(FPlugins.Items[i]).Plugin <> nil) then
+ TPSPluginItem(FPlugins.Items[i]).Plugin.ExecImport1(Self, ri);
+ end;
+
+ DoOnExecImport(RI);
+
+ for i := 0 to FPlugins.Count -1 do
+ begin
+ if (TPSPluginItem(FPlugins.Items[i]) <> nil)and (TPSPluginItem(FPlugins.Items[i]).Plugin <> nil) then
+ TPSPluginItem(FPlugins.Items[i]).Plugin.ExecImport2(Self, ri);
+ end;
+ RegisterClassLibraryRuntime(Exec, RI);
+ for i := 0 to FPlugins.Count -1 do
+ begin
+ if (TPSPluginItem(FPlugins.Items[i]) <> nil)and (TPSPluginItem(FPlugins.Items[i]).Plugin <> nil) then
+ TPSPluginItem(FPlugins.Items[i]).Plugin.ExecOnUses(Self);
+ end;
+ if not FExec.LoadData(Data) then
+ raise Exception.Create(GetExecErrorString);
+end;
+
+function TPSScript.SetVarToInstance(const VarName: tbtstring; cl: TObject): Boolean;
+var
+ p: PIFVariant;
+begin
+ p := GetVariable(VarName);
+ if p <> nil then
+ begin
+ SetVariantToClass(p, cl);
+ result := true;
+ end else result := false;
+end;
+
+procedure TPSScript.SetScript(const Value: TStrings);
+begin
+ FScript.Assign(Value);
+end;
+
+
+function TPSScript.AddMethod(Slf, Ptr: Pointer;
+ const Decl: tbtstring): Boolean;
+begin
+ Result := AddMethodEx(Slf, Ptr, Decl, cdRegister);
+end;
+
+function TPSScript.AddMethodEx(Slf, Ptr: Pointer; const Decl: tbtstring;
+ CallingConv: TDelphiCallingConvention): Boolean;
+var
+ P: TPSRegProc;
+begin
+ if not FCanAdd then begin Result := False; exit; end;
+ p := Comp.AddDelphiFunction(Decl);
+ if p <> nil then
+ begin
+ Exec.RegisterDelphiMethod(Slf, Ptr, p.Name, CallingConv);
+ Result := True;
+ end else Result := False;
+end;
+
+procedure TPSScript.OnLineEvent;
+begin
+ if @FOnLine <> nil then FOnLine(Self);
+end;
+
+function TPSScript.GetRunning: Boolean;
+begin
+ Result := FExec.Status = isRunning;
+end;
+
+function TPSScript.GetExecErrorCol: Cardinal;
+var
+ s: tbtstring;
+ D1: Cardinal;
+begin
+ if not TranslatePositionRC(Exec.ExceptionProcNo, Exec.ExceptionPos, D1, Result, s) then
+ Result := 0;
+end;
+
+function TPSScript.TranslatePositionPos(Proc, Position: Cardinal;
+ var Pos: Cardinal; var fn: tbtstring): Boolean;
+var
+ D1, D2: Cardinal;
+begin
+ Result := Exec.TranslatePositionEx(Exec.ExceptionProcNo, Exec.ExceptionPos, Pos, D1, D2, fn);
+end;
+
+function TPSScript.TranslatePositionRC(Proc, Position: Cardinal;
+ var Row, Col: Cardinal; var fn: tbtstring): Boolean;
+var
+ d1: Cardinal;
+begin
+ Result := Exec.TranslatePositionEx(Proc, Position, d1, Row, Col, fn);
+end;
+
+
+function TPSScript.GetExecErrorRow: Cardinal;
+var
+ D1: Cardinal;
+ s: tbtstring;
+begin
+ if not TranslatePositionRC(Exec.ExceptionProcNo, Exec.ExceptionPos, Result, D1, s) then
+ Result := 0;
+end;
+
+procedure TPSScript.Stop;
+begin
+ if (FExec.Status = isRunning) or (Fexec.Status = isPaused) then
+ FExec.Stop
+ else
+ raise Exception.Create(RPS_NotRunning);
+end;
+
+function TPSScript.GetProcMethod(const ProcName: tbtstring): TMethod;
+begin
+ Result := FExec.GetProcAsMethodN(ProcName)
+end;
+
+procedure TPSScript.SetMainFileName(const Value: tbtstring);
+begin
+ FMainFileName := Value;
+end;
+
+function TPSScript.GetExecErrorFileName: tbtstring;
+var
+ D1, D2: Cardinal;
+begin
+ if not TranslatePositionRC(Exec.ExceptionProcNo, Exec.ExceptionPos, D1, D2, Result) then
+ Result := '';
+end;
+
+procedure TPSScript.SetPointerToData(const VarName: tbtstring;
+ Data: Pointer; aType: TIFTypeRec);
+var
+ v: PIFVariant;
+ t: TPSVariantIFC;
+begin
+ v := GetVariable(VarName);
+ if (Atype = nil) or (v = nil) then raise Exception.Create(RPS_UnableToFindVariable);
+ t.Dta := @PPSVariantData(v).Data;
+ t.aType := v.FType;
+ t.VarParam := false;
+ VNSetPointerTo(t, Data, aType);
+end;
+
+function TPSScript.AddRegisteredPTRVariable(const VarName,
+ VarType: tbtstring): Boolean;
+var
+ FVar: TPSVar;
+begin
+ if not FCanAdd then begin Result := False; exit; end;
+ FVar := FComp.AddUsedVariableN(varname, vartype);
+ if fvar = nil then
+ result := False
+ else begin
+ fvar.exportname := fvar.Name;
+ fvar.SaveAsPointer := true;
+ Result := True;
+ end;
+end;
+
+procedure TPSScript.SetDefines(const Value: TStrings);
+begin
+ FDefines.Assign(Value);
+end;
+
+function TPSScript.ExecuteFunction(const Params: array of Variant;
+ const ProcName: tbtstring): Variant;
+begin
+ if SuppressLoadData then
+ LoadExec;
+
+ DoOnExecute (RI);
+
+ FExec.DebugEnabled := FUseDebugInfo;
+
+ Result := Exec.RunProcPN(Params, ProcName);
+
+ DoAfterExecute;
+end;
+
+function TPSScript.FindBaseType(Bt: TPSBaseType): TPSTypeRec;
+begin
+ Result := Exec.FindType2(Bt);
+end;
+
+function TPSScript.FindNamedType(const Name: tbtstring): TPSTypeRec;
+begin
+ Result := Exec.GetTypeNo(Exec.GetType(Name));
+end;
+
+procedure TPSScript.Notification(AComponent: TComponent;
+ Operation: TOperation);
+var
+ i: Longint;
+begin
+ inherited Notification(AComponent, Operation);
+ if (Operation = opRemove) and (aComponent is TPSPlugin) then
+ begin
+ for i := Plugins.Count -1 downto 0 do
+ begin
+ if (Plugins.Items[i] as TPSPluginItem).Plugin = aComponent then
+ {$IFDEF FPC_COL_NODELETE}
+ TCollectionItem(Plugins.Items[i]).Free;
+ {$ELSE}
+ Plugins.Delete(i);
+ {$ENDIF}
+ end;
+ end;
+end;
+
+function TPSScript.AddNotificationVariant(const VarName: tbtstring): Boolean;
+begin
+ Result := AddRegisteredVariable(VarName, '!NOTIFICATIONVARIANT');
+end;
+
+procedure TPSScript.DoOnProcessDirective(Sender: TPSPreProcessor;
+ Parser: TPSPascalPreProcessorParser; const Active: Boolean;
+ const DirectiveName, DirectiveParam: tbtstring; var Continue: Boolean);
+begin
+ If Assigned (OnProcessDirective) then
+ OnProcessDirective (Sender, Parser, Active, DirectiveName, DirectiveParam, Continue);
+end;
+
+procedure TPSScript.DoOnProcessUnknowDirective(Sender: TPSPreProcessor;
+ Parser: TPSPascalPreProcessorParser; const Active: Boolean;
+ const DirectiveName, DirectiveParam: tbtstring; var Continue: Boolean);
+begin
+ If Assigned (OnProcessUnknowDirective) then
+ OnProcessUnknowDirective (Sender, Parser, Active, DirectiveName, DirectiveParam, Continue);
+end;
+
+function TPSScript.DoOnNeedFile(Sender: TObject;
+ const OrginFileName: tbtstring; var FileName, Output: tbtstring): Boolean;
+begin
+ If Assigned (OnNeedFile) then
+ Result := OnNeedFile(Sender, OrginFileName, FileName, Output)
+ else
+ Result := False;
+end;
+
+function TPSScript.DoOnUnknowUses(Sender: TPSPascalCompiler;
+ const Name: tbtstring): Boolean;
+var
+ lPrevAllowUnit: Boolean;
+ lData, lName: tbtstring;
+begin
+ if assigned(FOnFindUnknownFile) then begin
+ lName := Name;
+ if FOnFindUnknownFile(self, '', lName, lData) then begin
+ lPrevAllowUnit := FComp.AllowUnit;
+ FComp.AllowUnit := true;
+ if FUsePreProcessor then
+ begin
+ FPP.Defines.Assign(FDefines);
+ Fpp.MainFile := lData;
+ Fpp.MainFileName := lName;
+ Fpp.PreProcess(lName, lData);
+ Result := FComp.Compile(lData);
+ Fpp.AdjustMessages(FComp);
+ end else
+ begin
+ FComp.OnTranslateLineInfo := nil;
+ Result := FComp.Compile(lData);
+ end;
+ FComp.AllowUnit := lPrevAllowUnit;
+ end else begin
+ FComp.MakeError(FComp.UnitName, ecUnknownIdentifier, lName);
+ Result := false;
+ end;
+ end else begin
+ FComp.MakeError(FComp.UnitName, ecUnknownIdentifier, lName);
+ result := false;
+ end;
+end;
+
+procedure TPSScript.DoOnCompImport;
+begin
+ if assigned(OnCompImport) then
+ OnCompImport(Self, Comp);
+end;
+
+procedure TPSScript.DoOnCompile;
+begin
+ if assigned(OnCompile) then
+ OnCompile(Self);
+end;
+
+procedure TPSScript.DoOnExecute;
+begin
+ If Assigned (OnExecute) then
+ OnExecute (Self);
+end;
+
+procedure TPSScript.DoAfterExecute;
+begin
+ if Assigned (OnAfterExecute) then
+ OnAfterExecute(Self);
+end;
+
+function TPSScript.DoVerifyProc(Sender: TPSScript;
+ Proc: TPSInternalProcedure; const Decl: tbtstring): Boolean;
+begin
+ if Assigned(OnVerifyProc) then begin
+ Result := false;
+ OnVerifyProc(Sender, Proc, Decl, Result);
+ Result := not Result;
+ end
+ else
+ Result := True;
+end;
+
+procedure TPSScript.DoOnExecImport(
+ RunTimeImporter: TPSRuntimeClassImporter);
+begin
+ if assigned(OnExecImport) then
+ OnExecImport(Self, FExec, RunTimeImporter);
+end;
+
+function TPSScript.DoOnGetNotificationVariant(const Name: tbtstring): Variant;
+begin
+ if Not Assigned (OnGetNotificationVariant) then
+ raise Exception.Create(RPS_UnableToReadVariant);
+ Result := OnGetNotificationVariant(Self, Name);
+end;
+
+procedure TPSScript.DoOnSetNotificationVariant(const Name: tbtstring;
+ V: Variant);
+begin
+ if Not Assigned (OnSetNotificationVariant) then
+ raise Exception.Create(RPS_UnableToWriteVariant);
+ OnSetNotificationVariant(Self, Name, v);
+end;
+
+{ TPSDllPlugin }
+
+procedure TPSDllPlugin.CompOnUses;
+begin
+ CompExec.Comp.OnExternalProc := DllExternalProc;
+end;
+
+procedure TPSDllPlugin.ExecOnUses;
+begin
+ RegisterDLLRuntime(CompExec.Exec);
+end;
+
+
+
+{ TPS3DebugCompExec }
+
+procedure LineInfo(Sender: TPSDebugExec; const FileName: tbtstring; Position, Row, Col: Cardinal);
+var
+ Dc: TPSScriptDebugger;
+ h, i: Longint;
+ bi: TPSBreakPointInfo;
+ lFileName: tbtstring;
+begin
+ Dc := Sender.Id;
+ if FileName = '' then
+ lFileName := dc.MainFileName
+ else
+ lFileName := FileName;
+
+ if @dc.FOnLineInfo <> nil then dc.FOnLineInfo(dc, lFileName, Position, Row, Col);
+ if row = dc.FLastRow then exit;
+ dc.FLastRow := row;
+ h := MakeHash(lFileName);
+ bi := nil;
+ for i := DC.FBreakPoints.Count -1 downto 0 do
+ begin
+ bi := Dc.FBreakpoints[i];
+ if (h = bi.FileNameHash) and (lFileName = bi.FileName) and (Cardinal(bi.Line) = Row) then
+ begin
+ Break;
+ end;
+ Bi := nil;
+ end;
+ if bi <> nil then
+ begin
+ if @dc.FOnBreakpoint <> nil then dc.FOnBreakpoint(dc, lFileName, Position, Row, Col);
+ dc.Pause;
+ end;
+end;
+
+procedure IdleCall(Sender: TPSDebugExec);
+var
+ Dc: TPSScriptDebugger;
+begin
+ Dc := Sender.Id;
+ if @dc.FOnIdle <> nil then
+ dc.FOnIdle(DC)
+ else
+ dc.Exec.Run;
+end;
+
+procedure TPSScriptDebugger.ClearBreakPoint(const Fn: tbtstring; Line: Integer);
+var
+ h, i: Longint;
+ bi: TPSBreakPointInfo;
+begin
+ h := MakeHash(Fn);
+ for i := FBreakPoints.Count -1 downto 0 do
+ begin
+ bi := FBreakpoints[i];
+ if (h = bi.FileNameHash) and (Fn = bi.FileName) and (bi.Line = Line) then
+ begin
+ FBreakPoints.Delete(i);
+ bi.Free;
+ Break;
+ end;
+ end;
+end;
+
+procedure TPSScriptDebugger.ClearBreakPoints;
+var
+ i: Longint;
+begin
+ for i := FBreakPoints.Count -1 downto 0 do
+ TPSBreakPointInfo(FBreakPoints[i]).Free;
+ FBreakPoints.Clear;;
+end;
+
+constructor TPSScriptDebugger.Create(AOwner: TComponent);
+begin
+ inherited Create(AOwner);
+ FBreakPoints := TIFList.Create;
+ FExec.OnSourceLine := LineInfo;
+ FExec.OnIdleCall := IdleCall;
+end;
+
+destructor TPSScriptDebugger.Destroy;
+var
+ i: Longint;
+begin
+ for i := FBreakPoints.Count -1 downto 0 do
+ begin
+ TPSBreakPointInfo(FBreakPoints[i]).Free;
+ end;
+ FBreakPoints.Free;
+ inherited Destroy;
+end;
+
+function TPSScriptDebugger.GetBreakPoint(I: Integer): TPSBreakPointInfo;
+begin
+ Result := FBreakPoints[i];
+end;
+
+function TPSScriptDebugger.GetBreakPointCount: Longint;
+begin
+ Result := FBreakPoints.Count;
+end;
+
+function TPSScriptDebugger.GetVarContents(const Name: tbtstring): tbtstring;
+var
+ i: Longint;
+ pv: PIFVariant;
+ s1, s: tbtstring;
+begin
+ s := Uppercase(Name);
+ if pos('.', s) > 0 then
+ begin
+ s1 := copy(s,1,pos('.', s) -1);
+ delete(s,1,pos('.', Name));
+ end else begin
+ s1 := s;
+ s := '';
+ end;
+ pv := nil;
+ for i := 0 to Exec.CurrentProcVars.Count -1 do
+ begin
+ if Uppercase(Exec.CurrentProcVars[i]) = s1 then
+ begin
+ pv := Exec.GetProcVar(i);
+ break;
+ end;
+ end;
+ if pv = nil then
+ begin
+ for i := 0 to Exec.CurrentProcParams.Count -1 do
+ begin
+ if Uppercase(Exec.CurrentProcParams[i]) = s1 then
+ begin
+ pv := Exec.GetProcParam(i);
+ break;
+ end;
+ end;
+ end;
+ if pv = nil then
+ begin
+ for i := 0 to Exec.GlobalVarNames.Count -1 do
+ begin
+ if Uppercase(Exec.GlobalVarNames[i]) = s1 then
+ begin
+ pv := Exec.GetGlobalVar(i);
+ break;
+ end;
+ end;
+ end;
+ if pv = nil then
+ Result := RPS_UnknownIdentifier
+ else
+ Result := PSVariantToString(NewTPSVariantIFC(pv, False), s);
+end;
+
+function TPSScriptDebugger.HasBreakPoint(const Fn: tbtstring; Line: Integer): Boolean;
+var
+ h, i: Longint;
+ bi: TPSBreakPointInfo;
+begin
+ h := MakeHash(Fn);
+ for i := FBreakPoints.Count -1 downto 0 do
+ begin
+ bi := FBreakpoints[i];
+ if (h = bi.FileNameHash) and (Fn = bi.FileName) and (bi.Line = Line) then
+ begin
+ Result := true;
+ exit;
+ end;
+ end;
+ Result := False;
+end;
+
+procedure TPSScriptDebugger.Pause;
+begin
+ if FExec.Status = isRunning then
+ FExec.Pause
+ else
+ raise Exception.Create(RPS_NotRunning);
+end;
+
+procedure TPSScriptDebugger.Resume;
+begin
+ if FExec.Status = isRunning then
+ FExec.Run
+ else
+ raise Exception.Create(RPS_NotRunning);
+end;
+
+procedure TPSScriptDebugger.SetBreakPoint(const fn: tbtstring; Line: Integer);
+var
+ i, h: Longint;
+ BI: TPSBreakPointInfo;
+begin
+ h := MakeHash(fn);
+ for i := FBreakPoints.Count -1 downto 0 do
+ begin
+ bi := FBreakpoints[i];
+ if (h = bi.FileNameHash) and (fn = bi.FileName) and (bi.Line = Line) then
+ exit;
+ end;
+ bi := TPSBreakPointInfo.Create;
+ FBreakPoints.Add(bi);
+ bi.FileName := fn;
+ bi.Line := Line;
+end;
+
+procedure TPSScriptDebugger.SetMainFileName(const Value: tbtstring);
+var
+ OldFn: tbtstring;
+ h1, h2,i: Longint;
+ bi: TPSBreakPointInfo;
+begin
+ OldFn := FMainFileName;
+ inherited SetMainFileName(Value);
+ h1 := MakeHash(OldFn);
+ h2 := MakeHash(Value);
+ if OldFn <> Value then
+ begin
+ for i := FBreakPoints.Count -1 downto 0 do
+ begin
+ bi := FBreakPoints[i];
+ if (bi.FileNameHash = h1) and (bi.FileName = OldFn) then
+ begin
+ bi.FFileNameHash := h2;
+ bi.FFileName := Value;
+ end else if (bi.FileNameHash = h2) and (bi.FileName = Value) then
+ begin
+ // It's already the new filename, that can't be right, so remove all the breakpoints there
+ FBreakPoints.Delete(i);
+ bi.Free;
+ end;
+ end;
+ end;
+end;
+
+procedure TPSScriptDebugger.StepInto;
+begin
+ if (FExec.Status = isRunning) or (FExec.Status = isLoaded) then
+ FExec.StepInto
+ else
+ raise Exception.Create(RPS_NoScript);
+end;
+
+procedure TPSScriptDebugger.StepOver;
+begin
+ if (FExec.Status = isRunning) or (FExec.Status = isLoaded) then
+ FExec.StepOver
+ else
+ raise Exception.Create(RPS_NoScript);
+end;
+
+
+
+{ TPSPluginItem }
+
+procedure TPSPluginItem.Assign(Source: TPersistent); //Birb
+begin
+ if Source is TPSPluginItem then
+ plugin:=((source as TPSPluginItem).plugin)
+ else
+ inherited;
+end;
+
+function TPSPluginItem.GetDisplayName: string;
+begin
+ if FPlugin <> nil then
+ Result := string(FPlugin.Name)
+ else
+ Result := '';
+end;
+
+procedure TPSPluginItem.SetPlugin(const Value: TPSPlugin);
+begin
+ FPlugin := Value;
+ If Value <> nil then
+ Value.FreeNotification(TPSPlugins(Collection).FCompExec);
+ Changed(False);
+end;
+
+{ TPSPlugins }
+
+constructor TPSPlugins.Create(CE: TPSScript);
+begin
+ inherited Create(TPSPluginItem);
+ FCompExec := CE;
+end;
+
+function TPSPlugins.GetOwner: TPersistent;
+begin
+ Result := FCompExec;
+end;
+
+{ TPSBreakPointInfo }
+
+procedure TPSBreakPointInfo.SetFileName(const Value: tbtstring);
+begin
+ FFileName := Value;
+ FFileNameHash := MakeHash(Value);
+end;
+
+{ TPSCustomPlugin }
+procedure TPSCustumPlugin.CompileImport1(CompExec: TPSScript);
+begin
+ IF @FOnCompileImport1 <> nil then
+ FOnCompileImport1(CompExec)
+ else
+ inherited;
+end;
+
+procedure TPSCustumPlugin.CompileImport2(CompExec: TPSScript);
+begin
+ IF @FOnCompileImport2 <> nil then
+ FOnCompileImport2(CompExec)
+ else
+ inherited;
+end;
+
+procedure TPSCustumPlugin.CompOnUses(CompExec: TPSScript);
+begin
+ IF @FOnCompOnUses <> nil then
+ FOnCompOnUses(CompExec)
+ else
+ inherited;
+end;
+
+procedure TPSCustumPlugin.ExecImport1(CompExec: TPSScript;
+ const ri: TPSRuntimeClassImporter);
+begin
+ IF @FOnExecImport1 <> nil then
+ FOnExecImport1(CompExec, compExec.Exec, ri)
+ else
+ inherited;
+end;
+
+procedure TPSCustumPlugin.ExecImport2(CompExec: TPSScript;
+ const ri: TPSRuntimeClassImporter);
+begin
+ IF @FOnExecImport2 <> nil then
+ FOnExecImport1(CompExec, compExec.Exec, ri)
+ else
+ inherited;
+end;
+
+procedure TPSCustumPlugin.ExecOnUses(CompExec: TPSScript);
+begin
+ IF @FOnExecOnUses <> nil then
+ FOnExecOnUses(CompExec)
+ else
+ inherited;
+end;
+
+end.
diff --git a/branches/script-component/Units/PascalScript/uPSComponentExt.pas b/branches/script-component/Units/PascalScript/uPSComponentExt.pas
new file mode 100644
index 0000000..8dce07b
--- /dev/null
+++ b/branches/script-component/Units/PascalScript/uPSComponentExt.pas
@@ -0,0 +1,1010 @@
+{
+@abstract(Component wrapper for IFPS3 compiler and executer)
+A component wrapper for IFPS3, including debugging support.
+
+}
+{$I PascalScript.inc}
+
+unit uPSComponentExt;
+
+interface
+
+uses
+ {$IFNDEF LINUX} Windows, {$ENDIF} SysUtils, Classes, uPSRuntime, uPSDebugger, uPSUtils, uPSComponent,
+ contnrs, uPSCompiler, uPSC_dll, uPSR_dll, uPSPreProcessor, typInfo;
+
+const
+ {alias to @link(ifps3.cdRegister)}
+ cdRegister = uPSRuntime.cdRegister;
+ {alias to @link(ifps3.cdPascal)}
+ cdPascal = uPSRuntime.cdPascal;
+ { alias to ifps3.cdCdecl }
+ CdCdecl = uPSRuntime.CdCdecl;
+ {alias to @link(ifps3.cdStdcall)}
+ CdStdCall = uPSRuntime.CdStdCall;
+
+type
+ {Alias to @link(ifps3.TPSCallingConvention)}
+ TDelphiCallingConvention = uPSRuntime.TPSCallingConvention;
+ {Alias to @link(ifps3.TPSRuntimeClassImporter)}
+ TPSRuntimeClassImporter = uPSRuntime.TPSRuntimeClassImporter;
+
+ TPSScriptExtension = class;
+
+ {Base class for all plugins for the component}
+ TPSOnCompCleanup = Function (Sender: TObject; aComp: TPSPascalCompiler):Boolean of object;
+ TPSOnInsertProcedure = Procedure (Sender: TObject; aProc: tbtstring; OnTop: Boolean) of object;
+ TPSOnException = procedure (Sender: TPSExec; ExError: TPSError; const ExParam: tbtstring;
+ ExObject: TObject; ProcNo, Position: Cardinal) of object;
+
+ TMethodList = class;
+ TProcObj = Class
+ private
+ FName : tbtstring;
+ fOwner : TMethodList;
+ procedure SetName(const Value: tbtstring);
+ public
+ ProcType : TStringList;
+ Method : TMethod;
+ constructor create(aOwner: TMethodList);
+ destructor Destroy; override;
+ property Name: tbtstring read FName write SetName;
+ end;
+
+ TMethodObj = Class
+ Instance : TPersistent;
+ PropName : tbtstring;
+ ProcName : tbtstring;
+ end;
+
+ TMethodList = class
+ private
+ fOwner : TPSScriptExtension;
+ fProcList : TObjectList;
+ fEventList : TObjectList;
+ function GetObject(Index: Integer): TMethodObj; virtual;
+ function GetProcObj(Index: Integer): TProcObj;
+ function GetMethodName(Instance: TObject; PropName: tbtstring): tbtstring;
+ procedure SetMethodName(Instance: TObject; PropName: tbtstring; const Value: tbtstring);
+ procedure CreateProc(ProcName: tbtstring; aPropType: TTypeData);
+ public
+ constructor create(aOwner: TPSScriptExtension);
+ destructor Destroy; override;
+ function methodIndexOf(Instance: TObject; PropName: tbtstring):Integer;
+ Function ProcIndexOf(Name: tbtstring): Integer;
+ Procedure ListEventsName(EventType:tbtstring; List : TStrings);
+
+ Procedure AddProcedure(ProcName, ProcType:tbtstring);
+ procedure InsertMethod(NewProc: tbtstring; OnTop: Boolean = false);
+
+ Procedure FillMethods;
+ procedure ClearProcList;
+ Procedure ClearAll;
+ function ProcCount :Integer;
+ Function MethodCount :Integer;
+ property Procs[Index: Integer]: TProcObj read GetProcObj ;
+ property Methods[Index: Integer]: TMethodObj read GetObject;
+ property ProcName[Instance: TObject; PropName:tbtstring]: tbtstring read GetMethodName write SetMethodName;
+ end;
+
+ TPSScriptExtension = class(TPSScriptDebugger)
+ private
+ FOnBeforeCleanUp: TPSOnCompCleanup;
+ FMethodList : TMethodList;
+ FOnInsertMethod: TPSOnInsertProcedure;
+ FNeedCompiling :Boolean;
+ FOnScriptChance: TNotifyEvent;
+ FOnException: TPSOnException;
+
+ fItems, fInserts: TStrings;
+ fScriptPos : Cardinal;
+ fObjectNest: tbtstring;
+
+ Procedure GetCodeProps ;
+ function GetProcName(Instance: TObject; PropName: tbtstring): tbtstring;
+ procedure SetProcName(Instance: TObject; PropName: tbtstring; const Value: tbtstring);
+
+ protected
+ procedure Notification(AComponent: TComponent; Operation: TOperation); override;
+
+ procedure DoVerifyProc(Sender: TPSScript; Proc: TPSInternalProcedure;
+ const Decl: tbtstring; var Error: Boolean); reintroduce;
+ Function DoBeforeCleanup(Sender: TObject; aComp: TPSPascalCompiler):Boolean;
+ procedure DoScriptChance(sender:TObject);
+
+
+ public
+ {Create an instance of the CompExec component}
+ constructor Create(AOwner: TComponent); override;
+ {Destroy the CompExec component}
+ destructor Destroy; override;
+
+ function Compile: Boolean; Override;
+ function Execute: Boolean; Override;
+ { Create a list of all var's, const's, Type's and functions }
+ Procedure GetValueDefs(aItems, aInserts: TStrings; Const aObjectNest: tbtstring=''; aScriptPos: Integer = 0);
+
+ {Compile the source only when the source is modified}
+ procedure CompileIfNeeded;
+ {Is the source modified}
+ Property NeedCompiling : Boolean read FNeedCompiling;
+
+ {Fills all function in the script to there connected Events.
+ This is called automatic after a succesfull Compilition}
+ Procedure FillMethods;
+
+ {Removes all events from the Objects Fills all function in the script to there connected Events.
+ This function is automatic called before a Compilition}
+ procedure ClearProcList;
+ Procedure RemoveObjEvents(Obj: TObject);
+
+ {This property helps you set the events that must becalled from within the script
+ Instance is the object where the Propname must be set.
+ You need te create the function yopur self in the script.
+ When the new Procname dose not exists in the script, it is automatic created for you.}
+ property ProcName[Instance: TObject; PropName:tbtstring]: tbtstring read GetProcName write SetProcName;
+ property MethodList : TMethodList read FMethodList;
+
+ published
+
+ property OnBeforeCleanUp: TPSOnCompCleanup read FOnBeforeCleanUp write FOnBeforeCleanUp; //
+ property OnInsertMethod : TPSOnInsertProcedure read FOnInsertMethod write FOnInsertMethod;
+ Property OnScriptChance : TNotifyEvent read FOnScriptChance write fOnScriptChance;
+ property OnException : TPSOnException read FOnException write FOnException;
+ end;
+
+
+implementation
+
+resourcestring
+ sMissingEndStatment = 'Missing some ''End'' statments';
+
+
+function CompExportCheck(Sender: TPSPascalCompiler; Proc: TPSInternalProcedure; const ProcDecl: tbtstring): Boolean;
+begin
+ TPSScriptExtension(Sender.ID).DoVerifyProc(Sender.Id, Proc, ProcDecl, Result);
+ Result := not Result;
+end;
+
+Function BeforeCleanup(Sender: TPSPascalCompiler):Boolean;
+begin
+ result := TPSScriptExtension(Sender.ID).DoBeforeCleanUp(Sender.ID,Sender);
+end;
+
+procedure CEException(Sender: TPSExec; ExError: TIFError; const ExParam: tbtstring; ExObject: TObject; ProcNo, Position: Cardinal);
+begin
+ if @TPSScriptExtension(Sender.ID).FOnException <> nil then
+ TPSScriptExtension(Sender.ID).FOnException(Sender, ExError, ExParam, ExObject, ProcNo, Position);
+end;
+
+{ TPSScriptExtension }
+
+function TPSScriptExtension.Compile: Boolean;
+begin
+ ClearProcList;
+
+ result := inherited Compile;
+ if result then FillMethods;
+
+
+ FNeedCompiling := not result;
+end;
+
+constructor TPSScriptExtension.Create(AOwner: TComponent);
+begin
+ inherited Create(AOwner);
+ Comp.OnBeforeCleanup := BeforeCleanup;
+ Comp.OnExportCheck := CompExportCheck;
+ Exec.OnException := CEException;
+
+ TStringList(script).OnChange := DoScriptChance;
+ FMethodList := TMethodList.create(Self);
+ FNeedCompiling := True;
+end;
+
+destructor TPSScriptExtension.Destroy;
+begin
+ FMethodList.Free;
+ FMethodList := nil;
+ inherited Destroy;
+end;
+
+procedure TPSScriptExtension.DoVerifyProc(Sender: TPSScript;
+ Proc: TPSInternalProcedure; const Decl: tbtstring; var Error: Boolean);
+var
+ n{,m,p} : Integer;
+ tstType : TPSProceduralType;
+begin
+ Error := False;
+ for n := 0 to sender.comp.GetTypeCount -1 do begin
+ If comp.GetType(n) is TPSProceduralType then begin
+ tstType := comp.GetType(n) as TPSProceduralType;
+ If tstType.ProcDef.Same(Proc.Decl) then begin
+ MethodList.addprocedure(Proc.OriginalName, tstType.Name);
+// Proc. aExport := etExportDecl;
+ end;
+ end;
+ end;
+ if assigned(OnVerifyProc) then
+ begin
+ onVerifyProc(Sender, Proc, Decl, Error);
+ end;
+end;
+
+type
+ TMyPascalCompiler = class(TPSPascalCompiler);
+const
+ sIFPSParameterMode : array [pmIn..pmInOut] of tbtstring = ('','\style{+B}out\style{-B} ','\style{+B}Var\style{-B} ');
+
+Procedure TPSScriptExtension.GetCodeProps;
+
+ Function existsItem(aName:tbtstring):Boolean;
+ Begin
+ result := FInserts.indexof(aName)<> -1;
+ end;
+
+ Procedure addListItem(aType, aName:tbtstring; aDef:tbtstring='');
+ var
+ x : LongInt;
+ begin
+ If not ((aName ='') or (aName[1]='!')) then begin
+ x := FInserts.Add(aName);
+ fItems.Insert(x, format('%s \column{}\style{+B}%s\style{-B} %s',[aType, aName, aDef]));
+ end;
+ end;
+
+ procedure Getdecl(decl : TPSParametersDecl; var T,v :tbtstring);
+ var
+ m : Integer;
+ begin
+ v := '';
+ for m := 0 to Decl.ParamCount-1 do begin
+ v := V +';'+sIFPSParameterMode[Decl.Params[m].Mode]+
+ Decl.Params[m].OrgName;
+ if Decl.Params[m].aType <> nil then
+ v := v +':'+ Decl.Params[m].aType.OriginalName;
+ end;
+ delete(v,1,1);
+ If v <> '' then v := '('+ v +')';
+ if Decl.Result<>nil then begin
+ v := v +':'+ Decl.Result.OriginalName;
+ t := 'Function';
+ end else t := 'Procedure';
+
+ end;
+
+ Function getTypeDef(xr: TPSType; aZoek:tbtstring = ''):Boolean; forward;
+
+ Function getClassDef(xc: TPSCompileTimeClass; aZoek:tbtstring = ''):Boolean;
+ var
+ Show : Boolean;
+ Zoek,bZoek : tbtstring;
+ tci : TPSDelphiClassItem;
+ n : Integer;
+ T,v : tbtstring;
+
+ begin
+ Show := aZoek='';
+ Zoek := aZoek;
+ If Pos('.',aZoek)>0 then begin
+ Zoek := copy(aZoek, 1 ,Pos('.',aZoek)-1);
+ bZoek := copy(aZoek, Pos('.',aZoek)+1, 999);
+ end else bZoek := '';
+
+ result := (xc <> nil) and Show;
+ if XC<> nil then begin
+ For n := 0 to xc.Count-1 do begin
+ tci := xc.Items[n];
+ If (tci = nil) or existsItem(tci.OrgName) then continue;
+ if tci is TPSDelphiClassItemConstructor then begin
+ Getdecl(tci.decl, T, V);
+ If Show then addListItem('Constructor',tci.OrgName, v);
+ end else
+ if tci is TPSDelphiClassItemMethod then begin
+ If Show then begin
+ Getdecl(tci.decl, T, V);
+ addListItem(T,tci.OrgName, v)
+ end else
+ If (tci.decl.Result <> nil) and (tci.Name = Zoek) then
+ result := getTypeDef(tci.decl.Result, bZoek);
+ end else
+ if tci is TPSDelphiClassItemProperty then begin
+ If Show then begin
+ t := '';
+ If tci.Decl.Result<> nil then t := ': '+ tci.Decl.Result.OriginalName;
+ addListItem('Property',tci.OrgName, t);
+ end else
+ If (tci.decl.Result <> nil) and (tci.Name = Zoek) then
+ result := getTypeDef(tci.decl.Result, bZoek);
+ end;
+ If result and not show then exit;
+ end;
+ result := getClassDef(XC.ClassInheritsFrom, aZoek) or result;
+ end;
+ end;
+
+ Function getTypeDef(xr: TPSType; aZoek:tbtstring = ''):Boolean;
+ var
+ Show : Boolean;
+ Zoek : tbtstring;
+ xri : PIFPSRecordFieldTypeDef;
+ n : Integer;
+ begin
+ Show := aZoek='';
+ result := (xr <> nil) and Show;
+ if xr <> nil then begin
+ If xr is TPSRecordType then begin
+ Zoek := aZoek;
+ If Pos('.',aZoek)>0 then begin
+ Zoek := copy(aZoek, 1 ,Pos('.',aZoek)-1);
+ aZoek := copy(aZoek, Pos('.',aZoek)+1, 999);
+ end else aZoek := '';
+ for n := 0 to (xr as TPSRecordType).RecValCount-1 do begin
+ xri := (xr as TPSRecordType).RecVal(n);
+ If Show then begin
+ addListItem('Var',xri.FieldOrgName,xri.aType.OriginalName)
+ end else
+ If (xri.aType <> nil) and (xri.FieldName = Zoek) then
+ result := getTypeDef(xri.aType, aZoek);
+ end;
+ end else
+ If (xr is TPSClassType) then begin
+ result := getClassDef((xr as TPSClassType).Cl, aZoek)
+ end else
+ result := False;
+ end;
+ end;
+
+ Function FindVarProc(aVarName:tbtstring; aZoek : tbtstring= ''):Boolean;
+ var
+// cv : tbtstring;
+ hh, h, i : Longint;
+ proc : TPSProcedure;
+ ip : TPSInternalProcedure;
+ ipv : PIFPSProcVar;
+ ipp : TPSParameterDecl;
+// t : tbtstring;
+ begin
+ Hh := MakeHash(aVarName);
+ result := False;
+ If FScriptPos =0 then exit;
+ for i := Comp.GetProcCount -1 downto 0 do begin
+ Proc := Comp.GetProc(i);
+ If (Proc.ClassType = TPSInternalProcedure) and
+ ((Proc as TPSInternalProcedure).DeclarePos < FScriptPos) then begin
+ ip := Proc as TPSInternalProcedure;
+ for h := 0 to ip.ProcVars.Count-1 do begin
+ ipv := PIFPSProcVar(ip.ProcVars[h]);
+ If aVarName = '' then begin
+ addListItem('Var',ipv.OrgName, ': '+ipv.AType.OriginalName);
+ end else
+ If (ipv.NameHash = HH) and (ipv.Name = aVarName) then begin
+ result := getTypeDef(ipv.aType, aZoek);
+ exit;
+ end;
+ end;
+ for h := 0 to ip.Decl.ParamCount-1 do begin
+ ipp := TPSParameterDecl(ip.Decl.Params[h]);
+ If aVarName = '' then begin
+ addListItem('Var',ipp.OrgName, ': '+ipp.aType.OriginalName);
+ end else
+ If {(ipp.Hash = HH) and} (ipp.Name = aVarName) then begin
+ result := getTypeDef(ipp.aType, aZoek);
+ exit;
+ end;
+ end;
+ end;
+ end;
+ end;
+
+ Function FindVarFunctType(aProcName:tbtstring): Boolean;
+ var
+ cv : tbtstring;
+ h, i : Longint;
+ proc : TPSProcedure;
+ xr : TPSRegProc;
+// t : tbtstring;
+ begin
+ cv := aProcName;
+ If Pos('.',aProcName)>0 then begin
+ cv := copy(aProcName, 1 ,Pos('.',aProcName)-1);
+ aProcName := copy(aProcName, Pos('.',aProcName)+1, 999);
+ end else aProcName := '';
+ H := MakeHash(Cv);
+// Result := False;
+ for i :=0 to Comp.GetVarCount -1 do begin
+ if (Comp.GetVar(I).NameHash = H) and (Comp.GetVar(I).Name = CV) then begin
+ Result := getTypeDef(Comp.GetVar(I).aType, aProcName);
+ Exit;
+ end;
+ end;
+ for i :=0 to Comp.GetTypeCount -1 do begin
+ if (Comp.GetType(I).NameHash = H) and (Comp.GetType(I).Name = CV) then begin
+ Result := getTypeDef(Comp.GetType(I), aProcName);
+ Exit;
+ end;
+ end;
+ result := FindVarProc(cv, aProcName);
+ If result then exit;
+ for i :=0 to Comp.GetProcCount -1 do begin
+ Proc := Comp.GetProc(i);
+ If Proc.ClassType = TPSInternalProcedure then begin
+ if ((Proc as TPSInternalProcedure).NameHash = H) and
+ ((Proc as TPSInternalProcedure).Name = CV) then begin
+ Result := getTypeDef((Proc as TPSInternalProcedure).Decl.Result, aProcName);
+ exit;
+ end;
+ end;
+ end;
+ with TMyPascalCompiler(Comp) do begin
+ for i := 0 to FRegProcs.Count-1 do begin
+ xr := FRegProcs[i];
+ if (xr.NameHash = H) and (xr.Name = CV) then begin
+ result := getTypeDef(xr.Decl.Result, aProcName);
+ exit;
+ end;
+ end;
+ end;
+ end;
+
+Var
+ n : Integer;
+ s, t, v : tbtstring;
+ proc : TPSProcedure;
+ xr : TPSRegProc;
+
+begin
+ If (fItems = nil) or (fInserts = Nil) then exit;
+ fItems.BeginUpdate;
+ fInserts.BeginUpdate;
+ tStringList(fInserts).Sorted := true;
+ tStringList(fInserts).Duplicates := dupAccept;
+ try
+ fInserts.Clear;
+ fItems.Clear;
+
+ If (FObjectNest <> '') then begin
+ FindVarFunctType(FastUpperCase(FObjectNest));
+ exit;
+ end;
+
+ for n := 0 to Comp.GetTypeCount-1 do begin
+ addListItem('Type',Comp.GetType(n).OriginalName);
+ end;
+ for n := 0 to Comp.GetVarCount-1 do begin
+ addListItem('Var',Comp.GetVar(n).OrgName, ': '+Comp.Getvar(n).aType.OriginalName);
+ end;
+ with TMyPascalCompiler(Comp) do begin
+ for n := 0 to FConstants.Count-1 do begin
+ addListItem('Const', TPSConstant(FConstants[n]).OrgName );
+ end;
+ for n := 0 to FRegProcs.Count-1 do begin
+ xr := FRegProcs[n];
+ Getdecl(xr.decl, T, v);
+ addListItem(t,xr.OrgName, v );
+ end;
+ end;
+ FindVarProc('');
+ for n := 0 to Comp.GetProcCount-1 do begin
+ s := '';
+ proc := Comp.GetProc(n);
+ If Proc.ClassType = TPSInternalProcedure then begin
+ s := (Proc as TPSInternalProcedure).OriginalName;
+ Getdecl((Proc as TPSInternalProcedure).decl, T, v);
+ end;
+ If s <> '' then begin
+ addListItem(t,s, v );
+ end;
+ end;
+ Finally
+ fInserts.EndUpdate;
+ fItems.EndUpdate;
+ end;
+end;
+
+procedure TPSScriptExtension.GetValueDefs(aItems, aInserts: TStrings; const aObjectNest: tbtstring; aScriptPos: Integer);
+begin
+ fItems := aItems;
+ fInserts := aInserts;
+ FScriptPos := aScriptPos;
+ fObjectNest := aObjectNest;
+ Try
+ compile;
+ finally
+ fItems := Nil;
+ fInserts := Nil;
+ FScriptPos := 0;
+ fObjectNest := '';
+ end;
+end;
+
+function TPSScriptExtension.DoBeforeCleanup(Sender: TObject;
+ aComp: TPSPascalCompiler): Boolean;
+begin
+ result := true;
+ If fItems <> nil then GetCodeProps;
+ If @FOnBeforeCleanUp<> nil then
+ result := FOnBeforeCleanUp(Sender, aComp);
+end;
+
+function TPSScriptExtension.Execute: Boolean;
+begin
+ CompileIfNeeded;
+ MethodList.FillMethods;
+ result := inherited Execute;
+end;
+
+
+procedure TPSScriptExtension.DoScriptChance(sender: TObject);
+begin
+ FNeedCompiling := True;
+ self.ClearProcList;
+ If @FOnScriptChance <> NIL then
+ FOnScriptChance(sender);
+end;
+
+procedure TPSScriptExtension.CompileIfNeeded;
+begin
+ if FNeedCompiling then begin
+ Compile;
+ end;
+end;
+
+procedure TPSScriptExtension.Notification(AComponent: TComponent;
+ Operation: TOperation);
+begin
+ inherited;
+ If Operation = opRemove then begin
+ if MethodList <> nil then
+ MethodList.SetMethodName(aComponent,'','');
+ end;
+end;
+
+function TPSScriptExtension.GetProcName(Instance: TObject; PropName: tbtstring): tbtstring;
+begin
+ Result := MethodList.ProcName[Instance, Propname];
+end;
+
+procedure TPSScriptExtension.SetProcName(Instance: TObject; PropName: tbtstring; const Value: tbtstring);
+begin
+ MethodList.ProcName[Instance, Propname] := Value;
+end;
+
+procedure TPSScriptExtension.ClearProcList;
+begin
+ MethodList.ClearProcList;
+end;
+
+procedure TPSScriptExtension.RemoveObjEvents(Obj: TObject);
+begin
+ MethodList.SetMethodName(Obj, '', '');
+end;
+
+procedure TPSScriptExtension.FillMethods;
+begin
+ MethodList.FillMethods;
+end;
+
+{ TMethodList }
+
+procedure TMethodList.AddProcedure(ProcName, ProcType: tbtstring);
+var
+ po : TProcObj;
+ x,y : Integer;
+
+begin
+ ProcType := Uppercase(ProcType);
+ x := ProcIndexOf(ProcName);
+ if x <> -1 then begin
+ y := Procs[x].ProcType.IndexOf(ProcType);
+ If y = -1 then TProcObj(fProcList.Items[x]).ProcType.add(ProcType);
+ end else begin
+ po := TProcObj.create(self);
+ po.Name := ProcName;
+ po.ProcType.add(ProcType);
+ fProcList.add(po);
+ end
+end;
+
+procedure TMethodList.ClearProcList;
+begin
+ fProcList.Clear;
+end;
+
+constructor TMethodList.create(aOwner: TPSScriptExtension);
+begin
+ inherited create;
+ fOwner := aOwner;
+ fProcList := TObjectList.create(true);
+ fEventList := TObjectList.create(true);
+end;
+
+procedure TMethodList.CreateProc(ProcName:tbtstring; aPropType: TTypeData);
+var
+ newProc: tbtstring;
+ P: PByte;
+ i: Integer;
+ pf : TParamFlags;
+
+ {$IFDEF FPC}
+ // mh: TParamFlags(P^) doesn't compile in FPC, this function will "fix" it.
+ // yes it's ugly, but I don't know an other way to fix it
+ function GetParamFlags(P: Byte): TParamFlags;
+ begin
+ result := [];
+ if (Ord(pfVar) and P <> 0) then Include(result, pfVar);
+ if (Ord(pfConst) and P <> 0) then Include(result, pfConst);
+ if (Ord(pfArray) and P <> 0) then Include(result, pfArray);
+ if (Ord(pfAddress) and P <> 0) then Include(result, pfAddress);
+ if (Ord(pfReference) and P <> 0) then Include(result, pfReference);
+ if (Ord(pfOut) and P <> 0) then Include(result, pfOut);
+ end;
+ {$ENDIF}
+
+begin
+ WITH aPropType do begin
+ if MethodKind=mkProcedure then NewProc:='procedure '
+ else NewProc:='function ';
+ NewProc:=NewProc + ProcName+'(';
+ P:=PByte(@ParamList);
+ for i:=0 to Pred(ParamCount) do
+ begin
+ {$IFDEF FPC}
+ pf:=GetParamFlags(P^);
+ {$ELSE}
+ pf:=TParamFlags(P^);
+ {$ENDIF}
+ if pfVar in pf then NewProc:=NewProc+'var ';
+ if pfConst in pf then NewProc:=NewProc+'const ';
+ Inc(P);
+ NewProc:=NewProc +PShortString(P)^ +' : ';
+ Inc(P,Succ(P^));
+ if pfArray in pf then NewProc:=NewProc+'array of ';
+ NewProc := NewProc + PShortString(P)^;
+ Inc(P,Succ(P^));
+ If i < Pred(ParamCount) then NewProc := NewProc + '; ';
+ end;
+ NewProc := NewProc +')' ;
+ if (MethodKind=mkFunction) then
+ NewProc := NewProc +':'+ PShortString(P)^;
+ NewProc:=NewProc+';'^m^j
+ +'Begin'^m^j^m^j
+ +'End;'^m^j;
+ If @fowner.FOnInsertMethod <> nil then begin
+ fowner.FOnInsertMethod(fOwner, NewProc, false);
+ end else begin
+ InsertMethod(NewProc);
+ end;
+ fowner.CompileIfNeeded;
+ end;
+end;
+
+procedure TMethodList.InsertMethod(NewProc: tbtstring; OnTop: Boolean = false);
+var
+ x : Integer;
+ sl : TStringList;
+ nBegins : Integer;
+ nProcs : Integer;
+ line, test : tbtstring;
+
+
+ function IsItem(line,item:tbtstring; First :Boolean = false):Boolean;
+ var
+ nPos : Integer;
+ begin
+ repeat
+ nPos := pos(item,line);
+ result := ((npos>0) and ((length(Line)-nPos<= length(item)) or not(line[nPos+length(item)] in ['0'..'9','A'..'Z','_'])) And
+ ((Npos = 1) or ((not first) and not(line[nPos-1] in ['0'..'9','A'..'Z','_']))));
+ if nPos <> 0 then line := copy(line,nPos+Length(Item),Length(line));
+ until (Result) or (nPos = 0);
+ end;
+
+ function DelSpaces(AText: tbtstring): tbtstring;
+ var i: Integer;
+ begin
+ Result := '';
+ for i := 1 to Length(AText) do
+ if AText[i] <> ' ' then
+ Result := Result + AText[i];
+ end;
+
+ function IsProcDecl(AnOriginalProcDecl: tbtstring): Boolean;
+ var
+ bIsFunc: Boolean;
+ iLineNo: Integer;
+ sProcKey: tbtstring;
+ sProcDecl: tbtstring;
+ begin
+ Result := false;
+ sProcDecl := Line;
+ iLineNo := x;
+ bIsFunc := isItem(AnOriginalProcDecl,'FUNCTION',true);
+
+ if bIsFunc
+ then sProcKey := 'FUNCTION'
+ else sProcKey := 'PROCEDURE';
+
+ sProcDecl := copy(sProcDecl,Pos(sProcKey,sProcDecl),Length(sProcDecl));
+
+ while not IsItem(sProcDecl,'BEGIN') do
+ begin
+ inc(iLineNo);
+ if iLineNo > (fowner.script.Count - 1) then exit;
+ sProcDecl := sProcDecl + ' ' + uppercase(trim(fowner.script[iLineNo])) + ' ';
+ end;
+
+ sProcDecl := DelSpaces(sProcDecl);
+ AnOriginalProcDecl := DelSpaces(AnOriginalProcDecl);
+
+ sProcDecl := copy(sProcDecl,1,Length(AnOriginalProcDecl));
+
+ Result := sProcDecl = AnOriginalProcDecl;
+
+ end;
+begin
+ sl := TStringList.create;
+ Try
+ sl.Text := NewProc;
+ test := uppercase(trim(sl[0]));
+ finally
+ Sl.free;
+ end;
+ nProcs := 0;
+ nBegins := 0;
+ x := 0;
+ If Not Ontop Then begin
+ for x := 0 to fOwner.script.count -1 do begin
+ Line := fowner.script[x];
+ Line := uppercase(trim(line));
+ If IsItem(line,'PROCEDURE', true) or IsItem(line,'FUNCTION', true) then begin
+ If nBegins >0 then Raise exception.create('Missing some ''end'' statments');
+ If (nProcs = 0) and IsProcDecl(test) and
+ (not IsItem(line,'FORWARD')) and (not IsItem(line,'EXTERNAL')) then
+ Exit;
+ Inc(nProcs);
+ end;
+ if IsItem(line,'FORWARD') or IsItem(line,'EXTERNAL') then
+ dec(nProcs);
+ If Pos('END',line) < Pos('BEGIN',line) then begin
+ If IsItem(line,'END') then begin
+ If (nBegins = 0) and (nProcs=0) then Break;
+ Dec(nBegins);
+ If nBegins = 0 then Dec(nProcs);
+ end;
+ If IsItem(line,'BEGIN') or IsItem(line,'TRY') or IsItem(line,'CASE') then begin
+ If nProcs = 0 then Break;
+ Inc(nBegins);
+ end;
+ end else begin
+ If IsItem(line,'BEGIN') or IsItem(line,'TRY') or IsItem(line,'CASE') then begin
+ If nProcs = 0 then Break;
+ Inc(nBegins);
+ end;
+ If IsItem(line,'END') then begin
+ If (nBegins = 0) and (nProcs=0) then Break;
+ Dec(nBegins);
+ If nBegins = 0 then Dec(nProcs);
+ end;
+ end;
+ end;
+ end;
+ FOwner.script.BeginUpdate;
+ Try
+ If (nProcs <> 0) or (nBegins<>0) then
+ Raise exception.create(sMissingEndStatment);
+ If (Not Ontop) and (x>0) and (Trim(FOwner.script[x-1])<>'') then begin
+ FOwner.script.Insert(x,'');
+ inc(x);
+ end;
+ FOwner.script.Insert(x,NewProc);
+ FOwner.script.text := FOwner.script.text;
+ finally
+ FOwner.script.EndUpdate;
+ end;
+end;
+
+destructor TMethodList.Destroy;
+begin
+ fProcList.Free; {<< Needs Eventlist for removing Methods}
+ fEventList.Free;
+ inherited;
+end;
+
+procedure TMethodList.FillMethods;
+var
+ x, y : Integer;
+ m : TMethod;
+begin
+ for x := 0 to fEventList.Count-1 do begin
+ Y := ProcIndexOf(MethodS[x].ProcName);
+ If (Y >= 0) and assigned(Methods[x].Instance) then begin
+ m := Procs[Y].Method;
+ if m.Data = nil then begin
+ m := fOwner.Exec.GetProcAsMethodN(Procs[Y].name);
+ TProcObj(fProcList.Items[Y]).Method := m;
+ end;
+ SetMethodProp(Methods[x].Instance, Methods[x].propname, m );
+ end;
+ end;
+end;
+
+function TMethodList.GetMethodName(Instance: TObject; PropName: tbtstring): tbtstring;
+var
+ x : Integer;
+begin
+ fOwner.CompileIfNeeded;
+ x := methodIndexOf(Instance,PropName);
+ If x>=0 then result := Methods[x].ProcName
+ else result := '';
+end;
+
+function TMethodList.GetObject(Index: Integer): TMethodObj;
+begin
+ result := TMethodObj(fEventList.items[Index]);
+end;
+
+function TMethodList.GetProcObj(Index: Integer): TProcObj;
+begin
+ result := TProcObj(fProcList.items[Index]);
+end;
+
+procedure TMethodList.ListEventsName(EventType: tbtstring; List: TStrings);
+var
+ x : Integer;
+begin
+ If List = nil then exit;
+ EventType := Uppercase(EventType);
+ List.Clear;
+ fOwner.CompileIfNeeded;
+ for x := 0 to fProcList.count-1 do begin
+ If Procs[x].ProcType.indexof(EventType)<> -1 then
+ List.add(Procs[x].name);
+ end;
+end;
+
+function TMethodList.MethodCount: Integer;
+begin
+ result := fEventList.count;
+end;
+
+function TMethodList.methodIndexOf(Instance: TObject;
+ PropName: tbtstring): Integer;
+var x : integer;
+begin
+ Result := -1;
+ for x := 0 to fEventList.count-1 do begin
+ if (TMethodObj(fEventList.Items[x]).Instance = Instance) and
+ ((propName='') or(TMethodObj(fEventList.Items[x]).PropName = PropName)) then begin
+ Result := x;
+ exit;
+ end;
+ end;
+end;
+
+function TMethodList.ProcCount: Integer;
+begin
+ result := fProcList.count;
+end;
+
+function TMethodList.ProcIndexOf(Name: tbtstring): Integer;
+var x : integer;
+begin
+ result := -1;
+ Name := Uppercase(name);
+ For x := 0 to fProcList.count-1 do begin
+ If Uppercase(TProcObj(fProcList.Items[x]).name) = name then begin
+ Result := x;
+ exit;
+ end;
+ end;
+end;
+
+procedure TMethodList.SetMethodName(Instance: TObject; PropName: tbtstring;
+ const Value: tbtstring);
+var
+ x, y : Integer;
+ mo : TMethodObj;
+ function TypeData(Instance: TObject; const PropName: tbtstring):PTypeData;
+ var
+ PropInfo: PPropInfo;
+ begin
+ // assume failure
+ Result := Nil;
+ PropInfo := GetPropInfo(Instance, PropName);
+ if PropInfo <> nil then
+ begin
+ Result:= GetTypeData(PropInfo^.PropType{$IFNDEF FPC}^{$ENDIF});
+ end
+ end;
+
+begin
+ If PropName = '' then begin
+ x := 0;
+ While x < MethodCount do begin
+ If (Methods[x].Instance = Instance) or (Instance = nil) then
+ fEventList.Delete(x)
+ else Inc(x);
+ end;
+ end else begin
+ x := methodIndexOf(Instance, PropName);
+ if value = '' then begin
+ if x >= 0 then fEventList.Delete(x);
+ end else begin
+ fOwner.CompileIfNeeded;
+ y := ProcIndexOf(Value);
+ If (Y = -1) then begin
+ CreateProc(Value, TypeData(Instance,propName)^);
+ y := 0;
+ end;
+ If (x = -1) then begin
+ If (Y <> -1) then begin
+ mo := TMethodObj.create;
+ mo.Instance := TPersistent(Instance);
+ mo.ProPName := Propname;
+ mo.procName := Value;
+ If (methodIndexOf(Instance,'')<>-1) and Instance.InheritsFrom(TComponent) then
+ fOwner.FreeNotification(TComponent(Instance));
+ fEventList.add(mo);
+ end;
+ end else
+ begin
+ Methods[x].procname := Value;
+ end;
+ end;
+ end;
+end;
+
+procedure TMethodList.ClearAll;
+begin
+ fProclist.clear;
+ fEventList.Clear;
+end;
+
+{ TProcObj }
+
+constructor TProcObj.create(aOwner: TMethodList);
+begin
+ inherited create();
+ fOwner := aOwner;
+ ProcType := TStringList.Create;
+end;
+
+destructor TProcObj.Destroy;
+
+var x : Integer;
+ m :TMethod;
+begin
+ m.Code := nil;
+ m.Data := nil;
+ If ((Method.Data <> nil) or (method.Code<> nil)) and (fOwner<>nil) and assigned(fOwner) then begin
+ for x := 0 to fOwner.MethodCount-1 do begin
+ If (name = fOwner.Methods[x].ProcName) and assigned(fOwner.Methods[x].Instance) then begin
+ Try
+ SetMethodProp(fOwner.Methods[x].Instance, fOwner.Methods[x].PropName,m);
+ except; end;
+ end;
+ end;
+ end;
+ ProcType.free;
+ inherited;
+end;
+
+procedure TProcObj.SetName(const Value: tbtstring);
+var
+ x : Integer;
+begin
+ If FName <> Value then begin
+ If fName<>'' then begin
+ for x := 0 to fOwner.MethodCount-1 do begin
+ If Fname = fOwner.Methods[x].ProcName then begin
+ fOwner.Methods[x].ProcName := Value;
+ end;
+ end;
+ end;
+ FName := Value;
+ end;
+end;
+
+
+end.
diff --git a/branches/script-component/Units/PascalScript/uPSComponent_COM.pas b/branches/script-component/Units/PascalScript/uPSComponent_COM.pas
new file mode 100644
index 0000000..e601c87
--- /dev/null
+++ b/branches/script-component/Units/PascalScript/uPSComponent_COM.pas
@@ -0,0 +1,38 @@
+
+unit uPSComponent_COM;
+
+interface
+uses
+ SysUtils, Classes, uPSComponent, uPSCompiler, uPSRuntime;
+type
+
+ TPSImport_ComObj = class(TPSPlugin)
+ private
+ public
+ procedure CompileImport1(CompExec: TPSScript); override;
+ procedure ExecImport1(CompExec: TPSScript; const ri: TPSRuntimeClassImporter); override;
+ end;
+
+ TIFPS3CE_ComObj = class(TPSImport_ComObj);
+
+implementation
+uses
+ uPSC_comobj,
+ uPSR_comobj;
+
+
+{ TPSImport_ComObj }
+
+procedure TPSImport_ComObj.CompileImport1(CompExec: TPSScript);
+begin
+ SIRegister_ComObj(CompExec.Comp);
+end;
+
+
+procedure TPSImport_ComObj.ExecImport1(CompExec: TPSScript;
+ const ri: TPSRuntimeClassImporter);
+begin
+ RIRegister_ComObj(CompExec.Exec);
+end;
+
+end.
diff --git a/branches/script-component/Units/PascalScript/uPSComponent_Controls.pas b/branches/script-component/Units/PascalScript/uPSComponent_Controls.pas
new file mode 100644
index 0000000..5532b47
--- /dev/null
+++ b/branches/script-component/Units/PascalScript/uPSComponent_Controls.pas
@@ -0,0 +1,65 @@
+ unit uPSComponent_Controls;
+
+interface
+uses
+ SysUtils, Classes, uPSComponent, uPSCompiler, uPSRuntime;
+type
+
+ TPSImport_Controls = class(TPSPlugin)
+ private
+ FEnableStreams: Boolean;
+ FEnableGraphics: Boolean;
+ FEnableControls: Boolean;
+ public
+ procedure CompileImport1(CompExec: TPSScript); override;
+ procedure ExecImport1(CompExec: TPSScript; const ri: TPSRuntimeClassImporter); override;
+ public
+ constructor Create(AOwner: TComponent); override;
+ published
+
+ property EnableStreams: Boolean read FEnableStreams write FEnableStreams;
+
+ property EnableGraphics: Boolean read FEnableGraphics write FEnableGraphics;
+
+ property EnableControls: Boolean read FEnableControls write FEnableControls;
+ end;
+
+ TIFPS3CE_Controls = class(TPSImport_Controls);
+
+implementation
+uses
+ uPSC_graphics,
+ uPSC_controls,
+ uPSR_graphics,
+ uPSR_controls;
+
+
+{ TPSImport_Controls }
+
+procedure TPSImport_Controls.CompileImport1(CompExec: TPSScript);
+begin
+ if FEnableGraphics then
+ SIRegister_Graphics(CompExec.Comp, FEnableStreams);
+ if FEnableControls then
+ SIRegister_Controls(CompExec.Comp);
+end;
+
+constructor TPSImport_Controls.Create(AOwner: TComponent);
+begin
+ inherited Create(AOwner);
+ FEnableStreams := True;
+ FEnableGraphics := True;
+ FEnableControls := True;
+end;
+
+procedure TPSImport_Controls.ExecImport1(CompExec: TPSScript;
+ const ri: TPSRuntimeClassImporter);
+begin
+ if FEnableGraphics then
+ RIRegister_Graphics(ri, FEnableStreams);
+ if FEnableControls then
+ RIRegister_Controls(ri);
+end;
+
+
+end.
diff --git a/branches/script-component/Units/PascalScript/uPSComponent_DB.pas b/branches/script-component/Units/PascalScript/uPSComponent_DB.pas
new file mode 100644
index 0000000..1c42a14
--- /dev/null
+++ b/branches/script-component/Units/PascalScript/uPSComponent_DB.pas
@@ -0,0 +1,36 @@
+ unit uPSComponent_DB;
+
+interface
+{$I PascalScript.inc}
+uses
+ SysUtils, Classes, uPSComponent, uPSRuntime, uPSCompiler;
+type
+
+ TPSImport_DB = class(TPSPlugin)
+ public
+ procedure CompileImport1(CompExec: TPSScript); override;
+ procedure ExecImport1(CompExec: TPSScript; const ri: TPSRuntimeClassImporter); override;
+ public
+ end;
+
+ TIFPS3CE_DB = class(TPSImport_DB);
+
+implementation
+uses
+ uPSC_DB,
+ uPSR_DB;
+
+{ TPSImport_DB }
+
+procedure TPSImport_DB.CompileImport1(CompExec: TPSScript);
+begin
+ SIRegister_DB(CompExec.Comp);
+end;
+
+procedure TPSImport_DB.ExecImport1(CompExec: TPSScript;
+ const ri: TPSRuntimeClassImporter);
+begin
+ RIRegister_DB(RI);
+end;
+
+end.
diff --git a/branches/script-component/Units/PascalScript/uPSComponent_Default.pas b/branches/script-component/Units/PascalScript/uPSComponent_Default.pas
new file mode 100644
index 0000000..d50335b
--- /dev/null
+++ b/branches/script-component/Units/PascalScript/uPSComponent_Default.pas
@@ -0,0 +1,81 @@
+ unit uPSComponent_Default;
+{$I PascalScript.inc}
+interface
+uses
+ SysUtils, Classes, uPSComponent, uPSCompiler, uPSRuntime;
+
+type
+
+ TPSImport_DateUtils = class(TPSPlugin)
+ public
+ procedure CompOnUses(CompExec: TPSScript); override;
+ procedure ExecOnUses(CompExec: TPSScript); override;
+ end;
+
+ TPSImport_Classes = class(TPSPlugin)
+ private
+ FEnableStreams: Boolean;
+ FEnableClasses: Boolean;
+ public
+ procedure CompileImport1(CompExec: TPSScript); override;
+ procedure ExecImport1(CompExec: TPSScript; const ri: TPSRuntimeClassImporter); override;
+ public
+
+ constructor Create(AOwner: TComponent); override;
+ published
+
+ property EnableStreams: Boolean read FEnableStreams write FEnableStreams;
+
+ property EnableClasses: Boolean read FEnableClasses write FEnableClasses;
+ end;
+
+ TIFPS3CE_Std = class(TPSImport_Classes);
+
+ TIFPS3CE_DateUtils = class(TPSImport_DateUtils);
+
+implementation
+uses
+ uPSC_std,
+ uPSR_std,
+ uPSC_classes,
+ uPSR_classes,
+ uPSC_dateutils,
+ uPSR_dateutils;
+
+{ TPSImport_Classes }
+
+procedure TPSImport_Classes.CompileImport1(CompExec: TPSScript);
+begin
+ SIRegister_Std(CompExec.Comp);
+ if FEnableClasses then
+ SIRegister_Classes(CompExec.Comp, FEnableStreams);
+end;
+
+procedure TPSImport_Classes.ExecImport1(CompExec: TPSScript;
+ const ri: TPSRuntimeClassImporter);
+begin
+ RIRegister_Std(Ri);
+ if FEnableClasses then
+ RIRegister_Classes(ri, FEnableStreams);
+end;
+
+constructor TPSImport_Classes.Create(AOwner: TComponent);
+begin
+ inherited Create(AOwner);
+ FEnableStreams := True;
+ FEnableClasses := True;
+end;
+
+{ TPSImport_DateUtils }
+
+procedure TPSImport_DateUtils.CompOnUses(CompExec: TPSScript);
+begin
+ RegisterDateTimeLibrary_C(CompExec.Comp);
+end;
+
+procedure TPSImport_DateUtils.ExecOnUses(CompExec: TPSScript);
+begin
+ RegisterDateTimeLibrary_R(CompExec.Exec);
+end;
+
+end.
diff --git a/branches/script-component/Units/PascalScript/uPSComponent_Forms.pas b/branches/script-component/Units/PascalScript/uPSComponent_Forms.pas
new file mode 100644
index 0000000..ec23be4
--- /dev/null
+++ b/branches/script-component/Units/PascalScript/uPSComponent_Forms.pas
@@ -0,0 +1,65 @@
+
+unit uPSComponent_Forms;
+
+interface
+uses
+ SysUtils, Classes, uPSRuntime, uPSCompiler, uPSComponent;
+type
+
+ TPSImport_Forms = class(TPSPlugin)
+ private
+ FEnableForms: Boolean;
+ FEnableMenus: Boolean;
+ public
+ procedure CompileImport1(CompExec: TPSScript); override;
+ procedure ExecImport1(CompExec: TPSScript; const ri: TPSRuntimeClassImporter); override;
+ public
+ constructor Create(AOwner: TComponent); override;
+ published
+
+ property EnableForms: Boolean read FEnableForms write FEnableForms;
+
+ property EnableMenus: Boolean read FEnableMenus write FEnableMenus;
+ end;
+
+ TIFPS3CE_Forms = class(TPSImport_Forms);
+
+implementation
+uses
+ uPSC_forms,
+ uPSC_menus,
+ uPSR_forms,
+ uPSR_menus;
+
+{ TPSImport_Forms }
+
+procedure TPSImport_Forms.CompileImport1(CompExec: TPSScript);
+begin
+ if FEnableForms then
+ SIRegister_Forms(CompExec.comp);
+ if FEnableMenus then
+ SIRegister_Menus(CompExec.comp);
+end;
+
+constructor TPSImport_Forms.Create(AOwner: TComponent);
+begin
+ inherited Create(Aowner);
+ FEnableForms := True;
+ FEnableMenus := True;
+end;
+
+procedure TPSImport_Forms.ExecImport1(CompExec: TPSScript;
+ const ri: TPSRuntimeClassImporter);
+begin
+ if FEnableForms then
+ RIRegister_Forms(ri);
+
+ if FEnableMenus then
+ begin
+ RIRegister_Menus(ri);
+ RIRegister_Menus_Routines(compexec.Exec);
+ end;
+
+end;
+
+end.
diff --git a/branches/script-component/Units/PascalScript/uPSComponent_StdCtrls.pas b/branches/script-component/Units/PascalScript/uPSComponent_StdCtrls.pas
new file mode 100644
index 0000000..68a56d1
--- /dev/null
+++ b/branches/script-component/Units/PascalScript/uPSComponent_StdCtrls.pas
@@ -0,0 +1,65 @@
+
+unit uPSComponent_StdCtrls;
+
+interface
+uses
+ SysUtils, Classes, uPSComponent, uPSCompiler, uPSRuntime;
+type
+
+ TPSImport_StdCtrls = class(TPSPlugin)
+ private
+ FEnableButtons: Boolean;
+ FEnableExtCtrls: Boolean;
+ public
+ procedure CompileImport1(CompExec: TPSScript); override;
+ procedure ExecImport1(CompExec: TPSScript; const ri: TPSRuntimeClassImporter); override;
+ public
+ constructor Create(AOwner: TComponent); override;
+ published
+
+ property EnableExtCtrls: Boolean read FEnableExtCtrls write FEnableExtCtrls;
+
+ property EnableButtons: Boolean read FEnableButtons write FEnableButtons;
+ end;
+
+ TIFPS3CE_StdCtrls = class(TPSImport_StdCtrls);
+
+
+implementation
+uses
+ uPSC_buttons,
+ uPSC_stdctrls,
+ uPSC_extctrls,
+ uPSR_buttons,
+ uPSR_stdctrls,
+ uPSR_extctrls;
+
+{ TPSImport_StdCtrls }
+
+procedure TPSImport_StdCtrls.CompileImport1(CompExec: TPSScript);
+begin
+ SIRegister_stdctrls(CompExec.Comp);
+ if FEnableExtCtrls then
+ SIRegister_ExtCtrls(CompExec.Comp);
+ if FEnableButtons then
+ SIRegister_Buttons(CompExec.Comp);
+end;
+
+constructor TPSImport_StdCtrls.Create(AOwner: TComponent);
+begin
+ inherited Create(Aowner);
+ FEnableButtons := True;
+ FEnableExtCtrls := True;
+end;
+
+procedure TPSImport_StdCtrls.ExecImport1(CompExec: TPSScript;
+ const ri: TPSRuntimeClassImporter);
+begin
+ RIRegister_stdctrls(RI);
+ if FEnableExtCtrls then
+ RIRegister_ExtCtrls(RI);
+ if FEnableButtons then
+ RIRegister_Buttons(RI);
+end;
+
+end.
diff --git a/branches/script-component/Units/PascalScript/uPSDebugger.pas b/branches/script-component/Units/PascalScript/uPSDebugger.pas
new file mode 100644
index 0000000..386b021
--- /dev/null
+++ b/branches/script-component/Units/PascalScript/uPSDebugger.pas
@@ -0,0 +1,654 @@
+
+unit uPSDebugger;
+{$I PascalScript.inc}
+interface
+uses
+ SysUtils, uPSRuntime, uPSUtils;
+
+type
+
+ TDebugMode = (dmRun
+ , dmStepOver
+ , dmStepInto
+ , dmPaused
+ );
+
+ TPSCustomDebugExec = class(TPSExec)
+ protected
+ FDebugDataForProcs: TIfList;
+ FLastProc: TPSProcRec;
+ FCurrentDebugProc: Pointer;
+ FProcNames: TIFStringList;
+ FGlobalVarNames: TIfStringList;
+ FCurrentSourcePos, FCurrentRow, FCurrentCol: Cardinal;
+ FCurrentFile: tbtstring;
+
+ function GetCurrentProcParams: TIfStringList;
+
+ function GetCurrentProcVars: TIfStringList;
+ protected
+
+ procedure ClearDebug; virtual;
+ public
+
+ function GetCurrentProcNo: Cardinal;
+
+ function GetCurrentPosition: Cardinal;
+
+ function TranslatePosition(Proc, Position: Cardinal): Cardinal;
+
+ function TranslatePositionEx(Proc, Position: Cardinal; var Pos, Row, Col: Cardinal; var Fn: tbtstring): Boolean;
+
+ procedure LoadDebugData(const Data: tbtstring);
+
+ procedure Clear; override;
+
+ property GlobalVarNames: TIfStringList read FGlobalVarNames;
+
+ property ProcNames: TIfStringList read FProcNames;
+
+ property CurrentProcVars: TIfStringList read GetCurrentProcVars;
+
+ property CurrentProcParams: TIfStringList read GetCurrentProcParams;
+
+ function GetGlobalVar(I: Cardinal): PIfVariant;
+
+ function GetProcVar(I: Cardinal): PIfVariant;
+
+ function GetProcParam(I: Cardinal): PIfVariant;
+
+ constructor Create;
+
+ destructor Destroy; override;
+ end;
+ TPSDebugExec = class;
+
+ TOnSourceLine = procedure (Sender: TPSDebugExec; const Name: tbtstring; Position, Row, Col: Cardinal);
+
+ TOnIdleCall = procedure (Sender: TPSDebugExec);
+
+ TPSDebugExec = class(TPSCustomDebugExec)
+ private
+ FDebugMode: TDebugMode;
+ FStepOverProc: TPSInternalProcRec;
+ FStepOverStackBase: Cardinal;
+ FOnIdleCall: TOnIdleCall;
+ FOnSourceLine: TOnSourceLine;
+ FDebugEnabled: Boolean;
+ protected
+
+ procedure SourceChanged;
+ procedure ClearDebug; override;
+ procedure RunLine; override;
+ public
+ constructor Create;
+
+ function LoadData(const s: tbtstring): Boolean; override;
+
+ procedure Pause; override;
+
+ procedure Run;
+
+ procedure StepInto;
+
+ procedure StepOver;
+
+ procedure Stop; override;
+
+ property DebugMode: TDebugMode read FDebugMode;
+
+ property OnSourceLine: TOnSourceLine read FOnSourceLine write FOnSourceLine;
+
+ property OnIdleCall: TOnIdleCall read FOnIdleCall write FOnIdleCall;
+
+ property DebugEnabled: Boolean read FDebugEnabled write FDebugEnabled;
+ end;
+ TIFPSDebugExec = TPSDebugExec;
+
+implementation
+
+{$IFDEF DELPHI3UP }
+resourceString
+{$ELSE }
+const
+{$ENDIF }
+
+ RPS_ExpectedReturnAddressStackBase = 'Expected return address at stack base';
+
+type
+ PPositionData = ^TPositionData;
+ TPositionData = packed record
+ FileName: tbtstring;
+ Position,
+ Row,
+ Col,
+ SourcePosition: Cardinal;
+ end;
+ PFunctionInfo = ^TFunctionInfo;
+ TFunctionInfo = packed record
+ Func: TPSProcRec;
+ FParamNames: TIfStringList;
+ FVariableNames: TIfStringList;
+ FPositionTable: TIfList;
+ end;
+
+{ TPSCustomDebugExec }
+
+procedure TPSCustomDebugExec.Clear;
+begin
+ inherited Clear;
+ if FGlobalVarNames <> nil then ClearDebug;
+end;
+
+procedure TPSCustomDebugExec.ClearDebug;
+var
+ i, j: Longint;
+ p: PFunctionInfo;
+begin
+ FCurrentDebugProc := nil;
+ FLastProc := nil;
+ FProcNames.Clear;
+ FGlobalVarNames.Clear;
+ FCurrentSourcePos := 0;
+ FCurrentRow := 0;
+ FCurrentCol := 0;
+ FCurrentFile := '';
+ for i := 0 to FDebugDataForProcs.Count -1 do
+ begin
+ p := FDebugDataForProcs[I];
+ for j := 0 to p^.FPositionTable.Count -1 do
+ begin
+ Dispose(PPositionData(P^.FPositionTable[J]));
+ end;
+ p^.FPositionTable.Free;
+ p^.FParamNames.Free;
+ p^.FVariableNames.Free;
+ Dispose(p);
+ end;
+ FDebugDataForProcs.Clear;
+end;
+
+constructor TPSCustomDebugExec.Create;
+begin
+ inherited Create;
+ FCurrentSourcePos := 0;
+ FCurrentRow := 0;
+ FCurrentCol := 0;
+ FCurrentFile := '';
+ FDebugDataForProcs := TIfList.Create;
+ FLastProc := nil;
+ FCurrentDebugProc := nil;
+ FProcNames := TIFStringList.Create;
+ FGlobalVarNames := TIfStringList.Create;
+end;
+
+destructor TPSCustomDebugExec.Destroy;
+begin
+ Clear;
+ FDebugDataForProcs.Free;
+ FProcNames.Free;
+ FGlobalVarNames.Free;
+ FGlobalVarNames := nil;
+ inherited Destroy;
+end;
+
+function TPSCustomDebugExec.GetCurrentPosition: Cardinal;
+begin
+ Result := TranslatePosition(GetCurrentProcNo, 0);
+end;
+
+function TPSCustomDebugExec.GetCurrentProcNo: Cardinal;
+var
+ i: Longint;
+begin
+ for i := 0 to FProcs.Count -1 do
+ begin
+ if FProcs[i]= FCurrProc then
+ begin
+ Result := I;
+ Exit;
+ end;
+ end;
+ Result := Cardinal(-1);
+end;
+
+function TPSCustomDebugExec.GetCurrentProcParams: TIfStringList;
+begin
+ if FCurrentDebugProc <> nil then
+ begin
+ Result := PFunctionInfo(FCurrentDebugProc)^.FParamNames;
+ end else Result := nil;
+end;
+
+function TPSCustomDebugExec.GetCurrentProcVars: TIfStringList;
+begin
+ if FCurrentDebugProc <> nil then
+ begin
+ Result := PFunctionInfo(FCurrentDebugProc)^.FVariableNames;
+ end else Result := nil;
+end;
+
+function TPSCustomDebugExec.GetGlobalVar(I: Cardinal): PIfVariant;
+begin
+ Result := FGlobalVars[I];
+end;
+
+function TPSCustomDebugExec.GetProcParam(I: Cardinal): PIfVariant;
+begin
+ Result := FStack[Cardinal(Longint(FCurrStackBase) - Longint(I) - 1)];
+end;
+
+function TPSCustomDebugExec.GetProcVar(I: Cardinal): PIfVariant;
+begin
+ Result := FStack[Cardinal(Longint(FCurrStackBase) + Longint(I) + 1)];
+end;
+
+function GetProcDebugInfo(FProcs: TIFList; Proc: TPSProcRec): PFunctionInfo;
+var
+ i: Longint;
+ c: PFunctionInfo;
+begin
+ if Proc = nil then
+ begin
+ Result := nil;
+ exit;
+ end;
+ for i := FProcs.Count -1 downto 0 do
+ begin
+ c := FProcs.Data^[I];
+ if c^.Func = Proc then
+ begin
+ Result := c;
+ exit;
+ end;
+ end;
+ new(c);
+ c^.Func := Proc;
+ c^.FPositionTable := TIfList.Create;
+ c^.FVariableNames := TIfStringList.Create;
+ c^.FParamNames := TIfStringList.Create;
+ FProcs.Add(c);
+ REsult := c;
+end;
+
+procedure TPSCustomDebugExec.LoadDebugData(const Data: tbtstring);
+var
+ CP, I: Longint;
+ c: tbtchar;
+ CurrProcNo, LastProcNo: Cardinal;
+ LastProc: PFunctionInfo;
+ NewLoc: PPositionData;
+ s: tbtstring;
+begin
+ ClearDebug;
+ if FStatus = isNotLoaded then exit;
+ CP := 1;
+ LastProcNo := Cardinal(-1);
+ LastProc := nil;
+ while CP <= length(Data) do
+ begin
+ c := Data[CP];
+ inc(cp);
+ case c of
+ #0:
+ begin
+ i := cp;
+ if i > length(data) then exit;
+ while Data[i] <> #0 do
+ begin
+ if Data[i] = #1 then
+ begin
+ FProcNames.Add(Copy(Data, cp, i-cp));
+ cp := I + 1;
+ end;
+ inc(I);
+ if I > length(data) then exit;
+ end;
+ cp := i + 1;
+ end;
+ #1:
+ begin
+ i := cp;
+ if i > length(data) then exit;
+ while Data[i] <> #0 do
+ begin
+ if Data[i] = #1 then
+ begin
+ FGlobalVarNames.Add(Copy(Data, cp, i-cp));
+ cp := I + 1;
+ end;
+ inc(I);
+ if I > length(data) then exit;
+ end;
+ cp := i + 1;
+ end;
+ #2:
+ begin
+ if cp + 4 > Length(data) then exit;
+ CurrProcNo := Cardinal((@Data[cp])^);
+ if CurrProcNo = Cardinal(-1) then Exit;
+ if CurrProcNo <> LastProcNo then
+ begin
+ LastProcNo := CurrProcNo;
+ LastProc := GetProcDebugInfo(FDebugDataForProcs, FProcs[CurrProcNo]);
+ if LastProc = nil then exit;
+ end;
+ inc(cp, 4);
+
+ i := cp;
+ if i > length(data) then exit;
+ while Data[i] <> #0 do
+ begin
+ if Data[i] = #1 then
+ begin
+ LastProc^.FParamNames.Add(Copy(Data, cp, i-cp));
+ cp := I + 1;
+ end;
+ inc(I);
+ if I > length(data) then exit;
+ end;
+ cp := i + 1;
+ end;
+ #3:
+ begin
+ if cp + 4 > Length(data) then exit;
+ CurrProcNo := Cardinal((@Data[cp])^);
+ if CurrProcNo = Cardinal(-1) then Exit;
+ if CurrProcNo <> LastProcNo then
+ begin
+ LastProcNo := CurrProcNo;
+ LastProc := GetProcDebugInfo(FDebugDataForProcs, FProcs[CurrProcNo]);
+ if LastProc = nil then exit;
+ end;
+ inc(cp, 4);
+
+ i := cp;
+ if i > length(data) then exit;
+ while Data[i] <> #0 do
+ begin
+ if Data[i] = #1 then
+ begin
+ LastProc^.FVariableNames.Add(Copy(Data, cp, i-cp));
+ cp := I + 1;
+ end;
+ inc(I);
+ if I > length(data) then exit;
+ end;
+ cp := i + 1;
+ end;
+ #4:
+ begin
+ i := cp;
+ if i > length(data) then exit;
+ while Data[i] <> #0 do
+ begin
+ if Data[i] = #1 then
+ begin
+ s := Copy(Data, cp, i-cp);
+ cp := I + 1;
+ Break;
+ end;
+ inc(I);
+ if I > length(data) then exit;
+ end;
+ if cp + 4 > Length(data) then exit;
+ CurrProcNo := Cardinal((@Data[cp])^);
+ if CurrProcNo = Cardinal(-1) then Exit;
+ if CurrProcNo <> LastProcNo then
+ begin
+ LastProcNo := CurrProcNo;
+ LastProc := GetProcDebugInfo(FDebugDataForProcs, FProcs[CurrProcNo]);
+ if LastProc = nil then exit;
+ end;
+ inc(cp, 4);
+ if cp + 16 > Length(data) then exit;
+ new(NewLoc);
+ NewLoc^.Position := Cardinal((@Data[Cp])^);
+ NewLoc^.FileName := s;
+ NewLoc^.SourcePosition := Cardinal((@Data[Cp+4])^);
+ NewLoc^.Row := Cardinal((@Data[Cp+8])^);
+ NewLoc^.Col := Cardinal((@Data[Cp+12])^);
+ inc(cp, 16);
+ LastProc^.FPositionTable.Add(NewLoc);
+ end;
+ else
+ begin
+ ClearDebug;
+ Exit;
+ end;
+ end;
+
+ end;
+end;
+
+
+
+
+
+
+function TPSCustomDebugExec.TranslatePosition(Proc, Position: Cardinal): Cardinal;
+var
+ D1, D2: Cardinal;
+ s: tbtstring;
+begin
+ if not TranslatePositionEx(Proc, Position, Result, D1, D2, s) then
+ Result := 0;
+end;
+
+function TPSCustomDebugExec.TranslatePositionEx(Proc, Position: Cardinal;
+ var Pos, Row, Col: Cardinal; var Fn: tbtstring): Boolean;
+// Made by Martijn Laan (mlaan@wintax.nl)
+var
+ i: LongInt;
+ fi: PFunctionInfo;
+ pt: TIfList;
+ r: PPositionData;
+ lastfn: tbtstring;
+ LastPos, LastRow, LastCol: Cardinal;
+ pp: TPSProcRec;
+begin
+ fi := nil;
+ pp := FProcs[Proc];
+ for i := 0 to FDebugDataForProcs.Count -1 do
+ begin
+ fi := FDebugDataForProcs[i];
+ if fi^.Func = pp then
+ Break;
+ fi := nil;
+ end;
+ LastPos := 0;
+ LastRow := 0;
+ LastCol := 0;
+ if fi <> nil then begin
+ pt := fi^.FPositionTable;
+ for i := 0 to pt.Count -1 do
+ begin
+ r := pt[I];
+ if r^.Position >= Position then
+ begin
+ if r^.Position = Position then
+ begin
+ Pos := r^.SourcePosition;
+ Row := r^.Row;
+ Col := r^.Col;
+ Fn := r^.Filename;
+ end
+ else
+ begin
+ Pos := LastPos;
+ Row := LastRow;
+ Col := LastCol;
+ Fn := LastFn;
+ end;
+ Result := True;
+ exit;
+ end else
+ begin
+ LastPos := r^.SourcePosition;
+ LastRow := r^.Row;
+ LastCol := r^.Col;
+ LastFn := r^.FileName;
+ end;
+ end;
+ Pos := LastPos;
+ Row := LastRow;
+ Col := LastCol;
+ Result := True;
+ end else
+ begin
+ Result := False;
+ end;
+end;
+
+{ TPSDebugExec }
+procedure TPSDebugExec.ClearDebug;
+begin
+ inherited;
+ FDebugMode := dmRun;
+end;
+
+function TPSDebugExec.LoadData(const s: tbtstring): Boolean;
+begin
+ Result := inherited LoadData(s);
+ FDebugMode := dmRun;
+end;
+
+procedure TPSDebugExec.RunLine;
+var
+ i: Longint;
+ pt: TIfList;
+ r: PPositionData;
+begin
+ inherited RunLine;
+ if not DebugEnabled then exit;
+ if FCurrProc <> FLastProc then
+ begin
+ FLastProc := FCurrProc;
+ FCurrentDebugProc := nil;
+ for i := 0 to FDebugDataForProcs.Count -1 do
+ begin
+ if PFunctionInfo(FDebugDataForProcs[I])^.Func = FLastProc then
+ begin
+ FCurrentDebugProc := FDebugDataForProcs[I];
+ break;
+ end;
+ end;
+ end;
+ if FCurrentDebugProc <> nil then
+ begin
+ pt := PFunctionInfo(FCurrentDebugProc)^.FPositionTable;
+ for i := 0 to pt.Count -1 do
+ begin
+ r := pt[I];
+ if r^.Position = FCurrentPosition then
+ begin
+ FCurrentSourcePos := r^.SourcePosition;
+ FCurrentRow := r^.Row;
+ FCurrentCol := r^.Col;
+ FCurrentFile := r^.FileName;
+ SourceChanged;
+ break;
+ end;
+ end;
+ end else
+ begin
+ FCurrentSourcePos := 0;
+ FCurrentRow := 0;
+ FCurrentCol := 0;
+ FCurrentFile := '';
+ end;
+ while FDebugMode = dmPaused do
+ begin
+ if @FOnIdleCall <> nil then
+ begin
+ FOnIdleCall(Self);
+ end else break; // endless loop
+ end;
+end;
+
+
+procedure TPSDebugExec.SourceChanged;
+
+ function StepOverShouldPause: Boolean;
+ var
+ I: Cardinal;
+ V: PPSVariant;
+ begin
+ if (FCurrProc <> FStepOverProc) or (FCurrStackBase <> FStepOverStackBase) then
+ begin
+ { We're not inside the function being stepped, so scan the call stack to
+ see if we're inside a function called by the function being stepped }
+ I := FCurrStackBase;
+ while Longint(I) > Longint(FStepOverStackBase) do
+ begin
+ V := FStack.Items[I];
+ if (V = nil) or (V.FType <> FReturnAddressType) then
+ raise Exception.Create(RPS_ExpectedReturnAddressStackBase);
+ if (PPSVariantReturnAddress(V).Addr.ProcNo = FStepOverProc) and
+ (PPSVariantReturnAddress(V).Addr.StackBase = FStepOverStackBase) then
+ begin
+ { We are, so don't pause }
+ Result := False;
+ Exit;
+ end;
+ I := PPSVariantReturnAddress(V).Addr.StackBase;
+ end;
+ end;
+ Result := True;
+ end;
+
+begin
+ case FDebugMode of
+ dmStepInto:
+ begin
+ FDebugMode := dmPaused;
+ end;
+ dmStepOver:
+ begin
+ if StepOverShouldPause then
+ begin
+ FDebugMode := dmPaused;
+ end;
+ end;
+ end;
+ if @FOnSourceLine <> nil then
+ FOnSourceLine(Self, FCurrentFile, FCurrentSourcePos, FCurrentRow, FCurrentCol);
+end;
+
+
+procedure TPSDebugExec.Pause;
+begin
+ FDebugMode := dmPaused;
+end;
+
+procedure TPSDebugExec.Stop;
+begin
+ FDebugMode := dmRun;
+ inherited Stop;
+end;
+
+procedure TPSDebugExec.Run;
+begin
+ FDebugMode := dmRun;
+end;
+
+procedure TPSDebugExec.StepInto;
+begin
+ FDebugMode := dmStepInto;
+end;
+
+procedure TPSDebugExec.StepOver;
+begin
+ FStepOverProc := FCurrProc;
+ FStepOverStackBase := FCurrStackBase;
+ FDebugMode := dmStepOver;
+end;
+
+
+constructor TPSDebugExec.Create;
+begin
+ inherited Create;
+ FDebugEnabled := True;
+end;
+
+end.
diff --git a/branches/script-component/Units/PascalScript/uPSDisassembly.pas b/branches/script-component/Units/PascalScript/uPSDisassembly.pas
new file mode 100644
index 0000000..1f9ccac
--- /dev/null
+++ b/branches/script-component/Units/PascalScript/uPSDisassembly.pas
@@ -0,0 +1,499 @@
+
+
+unit uPSDisassembly;
+{$I PascalScript.inc}
+
+interface
+uses
+ uPSRuntime, uPSUtils, sysutils;
+
+function IFPS3DataToText(const Input: tbtstring; var Output: string): Boolean;
+implementation
+
+type
+ TMyPSExec = class(TPSExec)
+ function ImportProc(const Name: ShortString; proc: TIFExternalProcRec): Boolean; override;
+ end;
+
+function Debug2Str(const s: string): string;
+var
+ i: Integer;
+begin
+ result := '';
+ for i := 1 to length(s) do
+ begin
+ if (s[i] < #32) or (s[i] > #128) then
+ result := result + '\'+inttohex(ord(s[i]), 2)
+ else if s[i] = '\' then
+ result := result + '\\'
+ else
+ result := result + s[i];
+ end;
+
+end;
+
+function SpecImportProc(Sender: TObject; p: TIFExternalProcRec): Boolean; forward;
+
+function FloatToStr(Value: Extended): string;
+begin
+ try
+ Result := SysUtils.FloatToStr(Value);
+ except
+ Result := 'NaNa';
+ end;
+end;
+
+
+function IFPS3DataToText(const Input: tbtstring; var Output: string): Boolean;
+var
+ I: TMyPSExec;
+
+ procedure Writeln(const s: string);
+ begin
+ Output := Output + s + #13#10;
+ end;
+ function BT2S(P: PIFTypeRec): string;
+ var
+ i: Longint;
+ begin
+ case p.BaseType of
+ btU8: Result := 'U8';
+ btS8: Result := 'S8';
+ btU16: Result := 'U16';
+ btS16: Result := 'S16';
+ btU32: Result := 'U32';
+ btS32: Result := 'S32';
+ {$IFNDEF PS_NOINT64}bts64: Result := 'S64'; {$ENDIF}
+ btChar: Result := {$IFDEF UNICODE}'AnsiChar'{$ELSE}'Char'{$ENDIF};
+ {$IFNDEF PS_NOWIDESTRING}
+ btWideChar: Result := 'WideChar';
+ btWideString: Result := 'WideString';
+ {$ENDIF}
+ btSet: Result := 'Set';
+ btSingle: Result := 'Single';
+ btDouble: Result := 'Double';
+ btExtended: Result := 'Extended';
+ btString: Result := 'String';
+ btRecord:
+ begin
+ Result := 'Record(';
+ for i := 0 to TPSTypeRec_Record(p).FieldTypes.Count-1 do
+ begin
+ if i <> 0 then Result := Result+',';
+ Result := Result + BT2S(PIFTypeRec(TPSTypeRec_Record(p).FieldTypes[i]));
+ end;
+ Result := Result + ')';
+ end;
+ btArray: Result := 'Array of '+BT2S(TPSTypeRec_Array(p).ArrayType);
+ btResourcePointer: Result := 'ResourcePointer';
+ btPointer: Result := 'Pointer';
+ btVariant: Result := 'Variant';
+ btClass: Result := 'Class';
+ btProcPtr: Result := 'ProcPtr';
+ btStaticArray: Result := 'StaticArray['+inttostR(TPSTypeRec_StaticArray(p).Size)+'] of '+BT2S(TPSTypeRec_Array(p).ArrayType);
+ else
+ Result := 'Unknown '+inttostr(p.BaseType);
+ end;
+ end;
+ procedure WriteTypes;
+ var
+ T: Longint;
+ begin
+ Writeln('[TYPES]');
+ for T := 0 to i.FTypes.Count -1 do
+ begin
+ if PIFTypeRec(i.FTypes[t]).ExportName <> '' then
+ Writeln('Type ['+inttostr(t)+']: '+bt2s(PIFTypeRec(i.FTypes[t]))+' Export: '+PIFTypeRec(i.FTypes[t]).ExportName)
+ else
+ Writeln('Type ['+inttostr(t)+']: '+bt2s(PIFTypeRec(i.FTypes[t])));
+ end;
+ end;
+ procedure WriteVars;
+ var
+ T: Longint;
+ function FindType(p: Pointer): Cardinal;
+ var
+ T: Longint;
+ begin
+ Result := Cardinal(-1);
+ for T := 0 to i.FTypes.Count -1 do
+ begin
+ if p = i.FTypes[t] then begin
+ result := t;
+ exit;
+ end;
+ end;
+ end;
+ begin
+ Writeln('[VARS]');
+ for t := 0 to i.FGlobalVars.count -1 do
+ begin
+ Writeln('Var ['+inttostr(t)+']: '+ IntToStr(FindType(PIFVariant(i.FGlobalVars[t])^.FType)) + ' '+ bt2s(PIFVariant(i.FGlobalVars[t])^.Ftype) + ' '+ PIFVariant(i.FGlobalVars[t])^.Ftype.ExportName);
+ end;
+ end;
+
+ procedure WriteProcs;
+ var
+ t: Longint;
+ procedure WriteProc(proc: TPSProcRec);
+ var
+ sc, CP: Cardinal;
+ function ReadData(var Data; Len: Cardinal): Boolean;
+ begin
+ if CP + Len <= TPSInternalProcRec(PROC).Length then begin
+ Move(TPSInternalProcRec(Proc).Data[CP], Data, Len);
+ CP := CP + Len;
+ Result := True;
+ end else Result := False;
+ end;
+ function ReadByte(var B: Byte): Boolean;
+ begin
+ if CP < TPSInternalProcRec(Proc).Length then begin
+ b := TPSInternalProcRec(Proc).Data^[cp];
+ Inc(CP);
+ Result := True;
+ end else Result := False;
+ end;
+
+ function ReadLong(var B: Cardinal): Boolean;
+ begin
+ if CP + 3 < TPSInternalProcRec(Proc).Length then begin
+ b := Cardinal((@TPSInternalProcRec(Proc).Data[CP])^);
+ Inc(CP, 4);
+ Result := True;
+ end else Result := False;
+ end;
+ function ReadWriteVariable: string;
+ var
+ VarType: byte;
+ L1, L2: Cardinal;
+ function ReadVar(FType: Cardinal): string;
+ var
+ F: PIFTypeRec;
+ b: byte;
+ w: word;
+ l: Cardinal;
+ {$IFNDEF PS_NOINT64}ff: Int64;{$ENDIF}
+ e: extended;
+ ss: single;
+ d: double;
+ s: ansistring;
+ c: char;
+ {$IFNDEF PS_NOWIDESTRING}
+ wc: WideChar;
+ ws: WideString;
+ {$ENDIF}
+
+ begin
+ result := '';
+ F:= i.FTypes[Ftype];
+ if f = nil then exit;
+ case f.BaseType of
+ btProcPtr: begin if not ReadData(l, 4) then exit; Result := 'PROC: '+inttostr(l); end;
+ btU8: begin if not ReadData(b, 1) then exit; Result := IntToStr(tbtu8(B)); end;
+ btS8: begin if not ReadData(b, 1) then exit; Result := IntToStr(tbts8(B)); end;
+ btU16: begin if not ReadData(w, 2) then exit; Result := IntToStr(tbtu16(w)); end;
+ btS16: begin if not ReadData(w, 2) then exit; Result := IntToStr(tbts16(w)); end;
+ btU32: begin if not ReadData(l, 4) then exit; Result := IntToStr(tbtu32(l)); end;
+ btS32: begin if not ReadData(l, 4) then exit; Result := IntToStr(tbts32(l)); end;
+ {$IFNDEF PS_NOINT64}bts64: begin if not ReadData(ff, 8) then exit; Result := IntToStr(ff); end;{$ENDIF}
+ btSingle: begin if not ReadData(ss, Sizeof(tbtsingle)) then exit; Result := FloatToStr(ss); end;
+ btDouble: begin if not ReadData(d, Sizeof(tbtdouble)) then exit; Result := FloatToStr(d); end;
+ btExtended: begin if not ReadData(e, Sizeof(tbtextended)) then exit; Result := FloatToStr(e); end;
+ btPChar, btString: begin if not ReadData(l, 4) then exit; SetLength(s, l); if not readData(s[1], l) then exit; Result := MakeString(s); end;
+ btSet:
+ begin
+ SetLength(s, TPSTypeRec_Set(f).aByteSize);
+ if not ReadData(s[1], length(s)) then exit;
+ result := MakeString(s);
+
+ end;
+ btChar: begin if not ReadData(c, 1) then exit; Result := '#'+IntToStr(ord(c)); end;
+ {$IFNDEF PS_NOWIDESTRING}
+ btWideChar: begin if not ReadData(wc, 2) then exit; Result := '#'+IntToStr(ord(wc)); end;
+ btWideString: begin if not ReadData(l, 4) then exit; SetLength(ws, l); if not readData(ws[1], l*2) then exit; Result := MakeWString(ws); end;
+ {$ENDIF}
+ end;
+ end;
+ function AddressToStr(a: Cardinal): String;
+ begin
+ if a < PSAddrNegativeStackStart then
+ Result := 'GlobalVar['+inttostr(a)+']'
+ else
+ Result := 'Base['+inttostr(Longint(A-PSAddrStackStart))+']';
+ end;
+
+ begin
+ Result := '';
+ if not ReadByte(VarType) then Exit;
+ case VarType of
+ 0:
+ begin
+
+ if not ReadLong(L1) then Exit;
+ Result := AddressToStr(L1);
+ end;
+ 1:
+ begin
+ if not ReadLong(L1) then Exit;
+ Result := '['+ReadVar(l1)+']';
+ end;
+ 2:
+ begin
+ if not ReadLong(L1) then Exit;
+ if not ReadLong(L2) then Exit;
+ Result := AddressToStr(L1)+'.['+inttostr(l2)+']';
+ end;
+ 3:
+ begin
+ if not ReadLong(l1) then Exit;
+ if not ReadLong(l2) then Exit;
+ Result := AddressToStr(L1)+'.'+AddressToStr(l2);
+ end;
+ end;
+ end;
+
+ var
+ b: Byte;
+ s: string;
+ DP, D1, D2, d3, d4: Cardinal;
+
+ begin
+ CP := 0;
+ sc := 0;
+ while true do
+ begin
+ DP := cp;
+ if not ReadByte(b) then Exit;
+ case b of
+ CM_A:
+ begin
+ {$IFDEF FPC}
+ Output := Output + ' ['+inttostr(dp)+'] ASSIGN '+ ReadWriteVariable;
+ Output := Output + ', ' + ReadWriteVariable + #13#10;
+ {$ELSE}
+ Writeln(' ['+inttostr(dp)+'] ASSIGN '+ReadWriteVariable+ ', ' + ReadWriteVariable);
+ {$ENDIF}
+ end;
+ CM_CA:
+ begin
+ if not ReadByte(b) then exit;
+ case b of
+ 0: s:= '+';
+ 1: s := '-';
+ 2: s := '*';
+ 3: s:= '/';
+ 4: s:= 'MOD';
+ 5: s:= 'SHL';
+ 6: s:= 'SHR';
+ 7: s:= 'AND';
+ 8: s:= 'OR';
+ 9: s:= 'XOR';
+ else
+ exit;
+ end;
+ Writeln(' ['+inttostr(dp)+'] CALC '+ReadWriteVariable+ ' '+s+' ' + ReadWriteVariable);
+ end;
+ CM_P:
+ begin
+ Inc(sc);
+ Writeln(' ['+inttostr(dp)+'] PUSH '+ReadWriteVariable + ' // '+inttostr(sc));
+ end;
+ CM_PV:
+ begin
+ Inc(sc);
+ Writeln(' ['+inttostr(dp)+'] PUSHVAR '+ReadWriteVariable + ' // '+inttostr(sc));
+ end;
+ CM_PO:
+ begin
+ Dec(Sc);
+ Writeln(' ['+inttostr(dp)+'] POP // '+inttostr(sc));
+ end;
+ Cm_C:
+ begin
+ if not ReadLong(D1) then exit;
+ Writeln(' ['+inttostr(dp)+'] CALL '+inttostr(d1));
+ end;
+ Cm_PG:
+ begin
+ if not ReadLong(D1) then exit;
+ Writeln(' ['+inttostr(dp)+'] POP/GOTO currpos + '+IntToStr(d1)+' ['+IntToStr(CP+d1)+']');
+ end;
+ Cm_P2G:
+ begin
+ if not ReadLong(D1) then exit;
+ Writeln(' ['+inttostr(dp)+'] POP2/GOTO currpos + '+IntToStr(d1)+' ['+IntToStr(CP+d1)+']');
+ end;
+ Cm_G:
+ begin
+ if not ReadLong(D1) then exit;
+ Writeln(' ['+inttostr(dp)+'] GOTO currpos + '+IntToStr(d1)+' ['+IntToStr(CP+d1)+']');
+ end;
+ Cm_CG:
+ begin
+ if not ReadLong(D1) then exit;
+ Writeln(' ['+inttostr(dp)+'] COND_GOTO currpos + '+IntToStr(d1)+' '+ReadWriteVariable+' ['+IntToStr(CP+d1)+']');
+ end;
+ Cm_CNG:
+ begin
+ if not ReadLong(D1) then exit;
+ Writeln(' ['+inttostr(dp)+'] COND_NOT_GOTO currpos + '+IntToStr(d1)+' '+ReadWriteVariable+' ['+IntToStr(CP+d1)+']');
+ end;
+ Cm_R: Writeln(' ['+inttostr(dp)+'] RET');
+ Cm_ST:
+ begin
+ if not ReadLong(d1) or not readLong(d2) then exit;
+ Writeln(' ['+inttostr(dp)+'] SETSTACKTYPE Base['+inttostr(d1)+'] '+inttostr(d2));
+ end;
+ Cm_Pt:
+ begin
+ Inc(sc);
+ if not ReadLong(D1) then exit;
+ Writeln(' ['+inttostr(dp)+'] PUSHTYPE '+inttostr(d1) + '('+BT2S(TPSTypeRec(I.FTypes[d1]))+') // '+inttostr(sc));
+ end;
+ CM_CO:
+ begin
+ if not readByte(b) then exit;
+ case b of
+ 0: s := '>=';
+ 1: s := '<=';
+ 2: s := '>';
+ 3: s := '<';
+ 4: s := '<>';
+ 5: s := '=';
+ else exit;
+ end;
+ Writeln(' ['+inttostr(dp)+'] COMPARE into '+ReadWriteVariable+': '+ReadWriteVariable+' '+s+' '+ReadWriteVariable);
+ end;
+ Cm_cv:
+ begin
+ Writeln(' ['+inttostr(dp)+'] CALLVAR '+ReadWriteVariable);
+ end;
+ Cm_inc:
+ begin
+ Writeln(' ['+inttostr(dp)+'] INC '+ReadWriteVariable);
+ end;
+ Cm_dec:
+ begin
+ Writeln(' ['+inttostr(dp)+'] DEC '+ReadWriteVariable);
+ end;
+ cm_sp:
+ begin
+ Writeln(' ['+inttostr(dp)+'] SETPOINTER '+ReadWriteVariable+': '+ReadWriteVariable);
+ end;
+ cm_spc:
+ begin
+ Writeln(' ['+inttostr(dp)+'] SETCOPYPOINTER '+ReadWriteVariable+': '+ReadWriteVariable);
+ end;
+ cm_in:
+ begin
+ Writeln(' ['+inttostr(dp)+'] INOT '+ReadWriteVariable);
+ end;
+ cm_bn:
+ begin
+ Writeln(' ['+inttostr(dp)+'] BNOT '+ReadWriteVariable);
+ end;
+ cm_vm:
+ begin
+ Writeln(' ['+inttostr(dp)+'] MINUS '+ReadWriteVariable);
+ end;
+ cm_sf:
+ begin
+ s := ReadWriteVariable;
+ if not ReadByte(b) then exit;
+ if b = 0 then
+ Writeln(' ['+inttostr(dp)+'] SETFLAG '+s)
+ else
+ Writeln(' ['+inttostr(dp)+'] SETFLAG NOT '+s);
+ end;
+ cm_fg:
+ begin
+ if not ReadLong(D1) then exit;
+ Writeln(' ['+inttostr(dp)+'] FLAGGOTO currpos + '+IntToStr(d1)+' ['+IntToStr(CP+d1)+']');
+ end;
+ cm_puexh:
+ begin
+ if not ReadLong(D1) then exit;
+ if not ReadLong(D2) then exit;
+ if not ReadLong(D3) then exit;
+ if not ReadLong(D4) then exit;
+ Writeln(' ['+inttostr(dp)+'] PUSHEXCEPTION '+inttostr(d1)+' '+inttostr(d2)+' '+inttostr(d3)+' '+inttostr(d4));
+ end;
+ cm_poexh:
+ begin
+ if not ReadByte(b) then exit;
+ Writeln(' ['+inttostr(dp)+'] POPEXCEPTION '+inttostr(b));
+ end;
+ else
+ begin
+ Writeln(' Disasm Error');
+ Break;
+ end;
+ end;
+ end;
+ end;
+
+ begin
+ Writeln('[PROCS]');
+ for t := 0 to i.FProcs.Count -1 do
+ begin
+ if TPSProcRec(i.FProcs[t]).ClassType = TIFExternalProcRec then
+ begin
+ if TPSExternalProcRec(i.FProcs[t]). Decl = '' then
+ Writeln('Proc ['+inttostr(t)+']: External: '+TPSExternalProcRec(i.FProcs[t]).Name)
+ else
+ Writeln('Proc ['+inttostr(t)+']: External Decl: '+Debug2Str(TIFExternalProcRec(i.FProcs[t]).Decl) + ' ' + TIFExternalProcRec(i.FProcs[t]).Name);
+ end else begin
+ if TPSInternalProcRec(i.FProcs[t]).ExportName <> '' then
+ begin
+ Writeln('Proc ['+inttostr(t)+'] Export: '+TPSInternalProcRec(i.FProcs[t]).ExportName+' '+TPSInternalProcRec(i.FProcs[t]).ExportDecl);
+ end else
+ Writeln('Proc ['+inttostr(t)+']');
+ Writeproc(i.FProcs[t]);
+ end;
+ end;
+ end;
+
+begin
+ Result := False;
+ try
+ I := TMyPSExec.Create;
+ I.AddSpecialProcImport('', @SpecImportProc, nil);
+
+ if not I.LoadData(Input) then begin
+ I.Free;
+ Exit;
+ end;
+ Output := '';
+ WriteTypes;
+ WriteVars;
+ WriteProcs;
+ I.Free;
+ except
+ exit;
+ end;
+ result := true;
+end;
+
+{ TMyIFPSExec }
+
+function MyDummyProc(Caller: TPSExec; p: TIFExternalProcRec; Global, Stack: TPSStack): Boolean;
+begin
+ Result := False;
+end;
+
+
+function TMyPSExec.ImportProc(const Name: ShortString;
+ proc: TIFExternalProcRec): Boolean;
+begin
+ Proc.ProcPtr := MyDummyProc;
+ result := true;
+end;
+
+function SpecImportProc(Sender: TObject; p: TIFExternalProcRec): Boolean;
+begin
+ p.ProcPtr := MyDummyProc;
+ Result := True;
+end;
+
+end.
diff --git a/branches/script-component/Units/PascalScript/uPSI_Dialogs.pas b/branches/script-component/Units/PascalScript/uPSI_Dialogs.pas
new file mode 100644
index 0000000..3fe0b95
--- /dev/null
+++ b/branches/script-component/Units/PascalScript/uPSI_Dialogs.pas
@@ -0,0 +1,741 @@
+unit uPSI_Dialogs;
+{
+This file has been generated by UnitParser v0.5, written by M. Knight
+and updated by NP. v/d Spek.
+Source Code from Carlo Kok has been used to implement various sections of
+UnitParser. Components of ifps3 are used in the construction of UnitParser,
+code implementing the class wrapper is taken from Carlo Kok''s conv unility
+}
+interface
+
+uses
+ SysUtils, Classes, uPSComponent, uPSCompiler, uPSRuntime;
+
+type
+(*----------------------------------------------------------------------------*)
+ TPSImport_Dialogs = class(TPSPlugin)
+ protected
+ procedure CompOnUses(CompExec: TPSScript); override;
+ procedure ExecOnUses(CompExec: TPSScript); override;
+ procedure CompileImport1(CompExec: TPSScript); override;
+ procedure CompileImport2(CompExec: TPSScript); override;
+ procedure ExecImport1(CompExec: TPSScript; const ri: TPSRuntimeClassImporter); override;
+ procedure ExecImport2(CompExec: TPSScript; const ri: TPSRuntimeClassImporter); override;
+ end;
+
+implementation
+
+uses
+ Windows ,Messages ,CommDlg ,Graphics ,Controls ,Forms ,StdCtrls ,Dialogs;
+
+(* === compile-time registration functions === *)
+(*----------------------------------------------------------------------------*)
+procedure SIRegister_TReplaceDialog(CL: TPSPascalCompiler);
+begin
+ //with RegClassS(CL,'TFindDialog', 'TReplaceDialog') do
+ with CL.AddClassN(CL.FindClass('TFindDialog'),'TReplaceDialog') do
+ begin
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure SIRegister_TFindDialog(CL: TPSPascalCompiler);
+begin
+ //with RegClassS(CL,'TCommonDialog', 'TFindDialog') do
+ with CL.AddClassN(CL.FindClass('TCommonDialog'),'TFindDialog') do
+ begin
+ RegisterMethod('Procedure CloseDialog');
+ RegisterProperty('Left', 'Integer', iptrw);
+ RegisterProperty('Position', 'TPoint', iptrw);
+ RegisterProperty('Top', 'Integer', iptrw);
+ RegisterProperty('FindText', 'string', iptrw);
+ RegisterProperty('Options', 'TFindOptions', iptrw);
+ RegisterProperty('OnFind', 'TNotifyEvent', iptrw);
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure SIRegister_TPrintDialog(CL: TPSPascalCompiler);
+begin
+ //with RegClassS(CL,'TCommonDialog', 'TPrintDialog') do
+ with CL.AddClassN(CL.FindClass('TCommonDialog'),'TPrintDialog') do
+ begin
+ RegisterProperty('Collate', 'Boolean', iptrw);
+ RegisterProperty('Copies', 'Integer', iptrw);
+ RegisterProperty('FromPage', 'Integer', iptrw);
+ RegisterProperty('MinPage', 'Integer', iptrw);
+ RegisterProperty('MaxPage', 'Integer', iptrw);
+ RegisterProperty('Options', 'TPrintDialogOptions', iptrw);
+ RegisterProperty('PrintToFile', 'Boolean', iptrw);
+ RegisterProperty('PrintRange', 'TPrintRange', iptrw);
+ RegisterProperty('ToPage', 'Integer', iptrw);
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure SIRegister_TPrinterSetupDialog(CL: TPSPascalCompiler);
+begin
+ //with RegClassS(CL,'TCommonDialog', 'TPrinterSetupDialog') do
+ with CL.AddClassN(CL.FindClass('TCommonDialog'),'TPrinterSetupDialog') do
+ begin
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure SIRegister_TFontDialog(CL: TPSPascalCompiler);
+begin
+ //with RegClassS(CL,'TCommonDialog', 'TFontDialog') do
+ with CL.AddClassN(CL.FindClass('TCommonDialog'),'TFontDialog') do
+ begin
+ RegisterProperty('Font', 'TFont', iptrw);
+ RegisterProperty('Device', 'TFontDialogDevice', iptrw);
+ RegisterProperty('MinFontSize', 'Integer', iptrw);
+ RegisterProperty('MaxFontSize', 'Integer', iptrw);
+ RegisterProperty('Options', 'TFontDialogOptions', iptrw);
+ RegisterProperty('OnApply', 'TFDApplyEvent', iptrw);
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure SIRegister_TColorDialog(CL: TPSPascalCompiler);
+begin
+ //with RegClassS(CL,'TCommonDialog', 'TColorDialog') do
+ with CL.AddClassN(CL.FindClass('TCommonDialog'),'TColorDialog') do
+ begin
+ RegisterProperty('Color', 'TColor', iptrw);
+ RegisterProperty('CustomColors', 'TStrings', iptrw);
+ RegisterProperty('Options', 'TColorDialogOptions', iptrw);
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure SIRegister_TSaveDialog(CL: TPSPascalCompiler);
+begin
+ //with RegClassS(CL,'TOpenDialog', 'TSaveDialog') do
+ with CL.AddClassN(CL.FindClass('TOpenDialog'),'TSaveDialog') do
+ begin
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure SIRegister_TOpenDialog(CL: TPSPascalCompiler);
+begin
+ //with RegClassS(CL,'TCommonDialog', 'TOpenDialog') do
+ with CL.AddClassN(CL.FindClass('TCommonDialog'),'TOpenDialog') do
+ begin
+ RegisterProperty('FileEditStyle', 'TFileEditStyle', iptrw);
+ RegisterProperty('Files', 'TStrings', iptr);
+ RegisterProperty('HistoryList', 'TStrings', iptrw);
+ RegisterProperty('DefaultExt', 'string', iptrw);
+ RegisterProperty('FileName', 'TFileName', iptrw);
+ RegisterProperty('Filter', 'string', iptrw);
+ RegisterProperty('FilterIndex', 'Integer', iptrw);
+ RegisterProperty('InitialDir', 'string', iptrw);
+ RegisterProperty('Options', 'TOpenOptions', iptrw);
+ RegisterProperty('Title', 'string', iptrw);
+ RegisterProperty('OnCanClose', 'TCloseQueryEvent', iptrw);
+ RegisterProperty('OnFolderChange', 'TNotifyEvent', iptrw);
+ RegisterProperty('OnSelectionChange', 'TNotifyEvent', iptrw);
+ RegisterProperty('OnTypeChange', 'TNotifyEvent', iptrw);
+ RegisterProperty('OnIncludeItem', 'TIncludeItemEvent', iptrw);
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure SIRegister_TCommonDialog(CL: TPSPascalCompiler);
+begin
+ //with RegClassS(CL,'TComponent', 'TCommonDialog') do
+ with CL.AddClassN(CL.FindClass('TComponent'),'TCommonDialog') do
+ begin
+ RegisterProperty('Handle', 'HWnd', iptr);
+ RegisterProperty('Ctl3D', 'Boolean', iptrw);
+ RegisterProperty('HelpContext', 'THelpContext', iptrw);
+ RegisterProperty('OnClose', 'TNotifyEvent', iptrw);
+ RegisterProperty('OnShow', 'TNotifyEvent', iptrw);
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure SIRegister_Dialogs(CL: TPSPascalCompiler);
+begin
+ CL.AddConstantN('MaxCustomColors','LongInt').SetInt( 16);
+ SIRegister_TCommonDialog(CL);
+ CL.AddTypeS('TOpenOption', '( ofReadOnly, ofOverwritePrompt, ofHideReadOnly, '
+ +'ofNoChangeDir, ofShowHelp, ofNoValidate, ofAllowMultiSelect, ofExtensionDi'
+ +'fferent, ofPathMustExist, ofFileMustExist, ofCreatePrompt, ofShareAware, o'
+ +'fNoReadOnlyReturn, ofNoTestFileCreate, ofNoNetworkButton, ofNoLongNames, o'
+ +'fOldStyleDialog, ofNoDereferenceLinks, ofEnableIncludeNotify, ofEnableSizi'
+ +'ng )');
+ CL.AddTypeS('TOpenOptions', 'set of TOpenOption');
+ CL.AddTypeS('TFileEditStyle', '( fsEdit, fsComboBox )');
+ CL.AddTypeS('TIncludeItemEvent', 'Procedure ( const OFN : TOFNotifyEx; var In'
+ +'clude : Boolean)');
+ SIRegister_TOpenDialog(CL);
+ SIRegister_TSaveDialog(CL);
+ CL.AddTypeS('TColorDialogOption', '( cdFullOpen, cdPreventFullOpen, cdShowHel'
+ +'p, cdSolidColor, cdAnyColor )');
+ CL.AddTypeS('TColorDialogOptions', 'set of TColorDialogOption');
+ SIRegister_TColorDialog(CL);
+ CL.AddTypeS('TFontDialogOption', '( fdAnsiOnly, fdTrueTypeOnly, fdEffects, fd'
+ +'FixedPitchOnly, fdForceFontExist, fdNoFaceSel, fdNoOEMFonts, fdNoSimulatio'
+ +'ns, fdNoSizeSel, fdNoStyleSel, fdNoVectorFonts, fdShowHelp, fdWysiwyg, fdL'
+ +'imitSize, fdScalableOnly, fdApplyButton )');
+ CL.AddTypeS('TFontDialogOptions', 'set of TFontDialogOption');
+ CL.AddTypeS('TFontDialogDevice', '( fdScreen, fdPrinter, fdBoth )');
+ CL.AddTypeS('TFDApplyEvent', 'Procedure ( Sender : TObject; Wnd : HWND)');
+ SIRegister_TFontDialog(CL);
+ SIRegister_TPrinterSetupDialog(CL);
+ CL.AddTypeS('TPrintRange', '( prAllPages, prSelection, prPageNums )');
+ CL.AddTypeS('TPrintDialogOption', '( poPrintToFile, poPageNums, poSelection, '
+ +'poWarning, poHelp, poDisablePrintToFile )');
+ CL.AddTypeS('TPrintDialogOptions', 'set of TPrintDialogOption');
+ SIRegister_TPrintDialog(CL);
+ CL.AddTypeS('TFindOption', '( frDown, frFindNext, frHideMatchCase, frHideWhol'
+ +'eWord, frHideUpDown, frMatchCase, frDisableMatchCase, frDisableUpDown, frD'
+ +'isableWholeWord, frReplace, frReplaceAll, frWholeWord, frShowHelp )');
+ CL.AddTypeS('TFindOptions', 'set of TFindOption');
+ SIRegister_TFindDialog(CL);
+ SIRegister_TReplaceDialog(CL);
+ CL.AddTypeS('TMsgDlgType', '( mtWarning, mtError, mtInformation, mtConfirmati'
+ +'on, mtCustom )');
+ CL.AddTypeS('TMsgDlgBtn', '( mbYes, mbNo, mbOK, mbCancel, mbAbort, mbRetry, m'
+ +'bIgnore, mbAll, mbNoToAll, mbYesToAll, mbHelp )');
+ CL.AddTypeS('TMsgDlgButtons', 'set of TMsgDlgBtn');
+ CL.AddConstantN('mbYesNoCancel','LongInt').Value.ts32 := ord(mbYes) or ord(mbNo) or ord(mbCancel);
+ CL.AddConstantN('mbOKCancel','LongInt').Value.ts32 := ord(mbOK) or ord(mbCancel);
+ CL.AddConstantN('mbAbortRetryIgnore','LongInt').Value.ts32 := ord(mbAbort) or ord(mbRetry) or ord(mbIgnore);
+ CL.AddDelphiFunction('Function CreateMessageDialog( const Msg : string; DlgType : TMsgDlgType; Buttons : TMsgDlgButtons) : TForm');
+ CL.AddDelphiFunction('Function MessageDlg( const Msg : string; DlgType : TMsgDlgType; Buttons : TMsgDlgButtons; HelpCtx : Longint) : Integer');
+ CL.AddDelphiFunction('Function MessageDlgPos( const Msg : string; DlgType : TMsgDlgType; Buttons : TMsgDlgButtons; HelpCtx : Longint; X, Y : Integer) : Integer');
+ CL.AddDelphiFunction('Function MessageDlgPosHelp( const Msg : string; DlgType : TMsgDlgType; Buttons : TMsgDlgButtons; HelpCtx : Longint; X, Y : Integer; const HelpFileName : string) : Integer');
+ CL.AddDelphiFunction('Procedure ShowMessage( const Msg : string)');
+ CL.AddDelphiFunction('Procedure ShowMessagePos( const Msg : string; X, Y : Integer)');
+ CL.AddDelphiFunction('Function InputBox( const ACaption, APrompt, ADefault : string) : string');
+ CL.AddDelphiFunction('Function InputQuery( const ACaption, APrompt : string; var Value : string) : Boolean');
+end;
+
+(* === run-time registration functions === *)
+(*----------------------------------------------------------------------------*)
+procedure TFindDialogOnFind_W(Self: TFindDialog; const T: TNotifyEvent);
+begin Self.OnFind := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TFindDialogOnFind_R(Self: TFindDialog; var T: TNotifyEvent);
+begin T := Self.OnFind; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TFindDialogOptions_W(Self: TFindDialog; const T: TFindOptions);
+begin Self.Options := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TFindDialogOptions_R(Self: TFindDialog; var T: TFindOptions);
+begin T := Self.Options; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TFindDialogFindText_W(Self: TFindDialog; const T: string);
+begin Self.FindText := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TFindDialogFindText_R(Self: TFindDialog; var T: string);
+begin T := Self.FindText; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TFindDialogTop_W(Self: TFindDialog; const T: Integer);
+begin Self.Top := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TFindDialogTop_R(Self: TFindDialog; var T: Integer);
+begin T := Self.Top; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TFindDialogPosition_W(Self: TFindDialog; const T: TPoint);
+begin Self.Position := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TFindDialogPosition_R(Self: TFindDialog; var T: TPoint);
+begin T := Self.Position; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TFindDialogLeft_W(Self: TFindDialog; const T: Integer);
+begin Self.Left := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TFindDialogLeft_R(Self: TFindDialog; var T: Integer);
+begin T := Self.Left; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TPrintDialogToPage_W(Self: TPrintDialog; const T: Integer);
+begin Self.ToPage := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TPrintDialogToPage_R(Self: TPrintDialog; var T: Integer);
+begin T := Self.ToPage; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TPrintDialogPrintRange_W(Self: TPrintDialog; const T: TPrintRange);
+begin Self.PrintRange := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TPrintDialogPrintRange_R(Self: TPrintDialog; var T: TPrintRange);
+begin T := Self.PrintRange; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TPrintDialogPrintToFile_W(Self: TPrintDialog; const T: Boolean);
+begin Self.PrintToFile := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TPrintDialogPrintToFile_R(Self: TPrintDialog; var T: Boolean);
+begin T := Self.PrintToFile; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TPrintDialogOptions_W(Self: TPrintDialog; const T: TPrintDialogOptions);
+begin Self.Options := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TPrintDialogOptions_R(Self: TPrintDialog; var T: TPrintDialogOptions);
+begin T := Self.Options; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TPrintDialogMaxPage_W(Self: TPrintDialog; const T: Integer);
+begin Self.MaxPage := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TPrintDialogMaxPage_R(Self: TPrintDialog; var T: Integer);
+begin T := Self.MaxPage; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TPrintDialogMinPage_W(Self: TPrintDialog; const T: Integer);
+begin Self.MinPage := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TPrintDialogMinPage_R(Self: TPrintDialog; var T: Integer);
+begin T := Self.MinPage; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TPrintDialogFromPage_W(Self: TPrintDialog; const T: Integer);
+begin Self.FromPage := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TPrintDialogFromPage_R(Self: TPrintDialog; var T: Integer);
+begin T := Self.FromPage; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TPrintDialogCopies_W(Self: TPrintDialog; const T: Integer);
+begin Self.Copies := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TPrintDialogCopies_R(Self: TPrintDialog; var T: Integer);
+begin T := Self.Copies; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TPrintDialogCollate_W(Self: TPrintDialog; const T: Boolean);
+begin Self.Collate := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TPrintDialogCollate_R(Self: TPrintDialog; var T: Boolean);
+begin T := Self.Collate; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TFontDialogOnApply_W(Self: TFontDialog; const T: TFDApplyEvent);
+begin Self.OnApply := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TFontDialogOnApply_R(Self: TFontDialog; var T: TFDApplyEvent);
+begin T := Self.OnApply; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TFontDialogOptions_W(Self: TFontDialog; const T: TFontDialogOptions);
+begin Self.Options := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TFontDialogOptions_R(Self: TFontDialog; var T: TFontDialogOptions);
+begin T := Self.Options; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TFontDialogMaxFontSize_W(Self: TFontDialog; const T: Integer);
+begin Self.MaxFontSize := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TFontDialogMaxFontSize_R(Self: TFontDialog; var T: Integer);
+begin T := Self.MaxFontSize; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TFontDialogMinFontSize_W(Self: TFontDialog; const T: Integer);
+begin Self.MinFontSize := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TFontDialogMinFontSize_R(Self: TFontDialog; var T: Integer);
+begin T := Self.MinFontSize; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TFontDialogDevice_W(Self: TFontDialog; const T: TFontDialogDevice);
+begin Self.Device := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TFontDialogDevice_R(Self: TFontDialog; var T: TFontDialogDevice);
+begin T := Self.Device; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TFontDialogFont_W(Self: TFontDialog; const T: TFont);
+begin Self.Font := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TFontDialogFont_R(Self: TFontDialog; var T: TFont);
+begin T := Self.Font; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TColorDialogOptions_W(Self: TColorDialog; const T: TColorDialogOptions);
+begin Self.Options := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TColorDialogOptions_R(Self: TColorDialog; var T: TColorDialogOptions);
+begin T := Self.Options; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TColorDialogCustomColors_W(Self: TColorDialog; const T: TStrings);
+begin Self.CustomColors := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TColorDialogCustomColors_R(Self: TColorDialog; var T: TStrings);
+begin T := Self.CustomColors; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TColorDialogColor_W(Self: TColorDialog; const T: TColor);
+begin Self.Color := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TColorDialogColor_R(Self: TColorDialog; var T: TColor);
+begin T := Self.Color; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TOpenDialogOnIncludeItem_W(Self: TOpenDialog; const T: TIncludeItemEvent);
+begin Self.OnIncludeItem := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TOpenDialogOnIncludeItem_R(Self: TOpenDialog; var T: TIncludeItemEvent);
+begin T := Self.OnIncludeItem; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TOpenDialogOnTypeChange_W(Self: TOpenDialog; const T: TNotifyEvent);
+begin Self.OnTypeChange := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TOpenDialogOnTypeChange_R(Self: TOpenDialog; var T: TNotifyEvent);
+begin T := Self.OnTypeChange; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TOpenDialogOnSelectionChange_W(Self: TOpenDialog; const T: TNotifyEvent);
+begin Self.OnSelectionChange := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TOpenDialogOnSelectionChange_R(Self: TOpenDialog; var T: TNotifyEvent);
+begin T := Self.OnSelectionChange; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TOpenDialogOnFolderChange_W(Self: TOpenDialog; const T: TNotifyEvent);
+begin Self.OnFolderChange := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TOpenDialogOnFolderChange_R(Self: TOpenDialog; var T: TNotifyEvent);
+begin T := Self.OnFolderChange; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TOpenDialogOnCanClose_W(Self: TOpenDialog; const T: TCloseQueryEvent);
+begin Self.OnCanClose := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TOpenDialogOnCanClose_R(Self: TOpenDialog; var T: TCloseQueryEvent);
+begin T := Self.OnCanClose; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TOpenDialogTitle_W(Self: TOpenDialog; const T: string);
+begin Self.Title := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TOpenDialogTitle_R(Self: TOpenDialog; var T: string);
+begin T := Self.Title; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TOpenDialogOptions_W(Self: TOpenDialog; const T: TOpenOptions);
+begin Self.Options := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TOpenDialogOptions_R(Self: TOpenDialog; var T: TOpenOptions);
+begin T := Self.Options; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TOpenDialogInitialDir_W(Self: TOpenDialog; const T: string);
+begin Self.InitialDir := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TOpenDialogInitialDir_R(Self: TOpenDialog; var T: string);
+begin T := Self.InitialDir; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TOpenDialogFilterIndex_W(Self: TOpenDialog; const T: Integer);
+begin Self.FilterIndex := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TOpenDialogFilterIndex_R(Self: TOpenDialog; var T: Integer);
+begin T := Self.FilterIndex; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TOpenDialogFilter_W(Self: TOpenDialog; const T: string);
+begin Self.Filter := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TOpenDialogFilter_R(Self: TOpenDialog; var T: string);
+begin T := Self.Filter; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TOpenDialogFileName_W(Self: TOpenDialog; const T: TFileName);
+begin Self.FileName := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TOpenDialogFileName_R(Self: TOpenDialog; var T: TFileName);
+begin T := Self.FileName; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TOpenDialogDefaultExt_W(Self: TOpenDialog; const T: string);
+begin Self.DefaultExt := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TOpenDialogDefaultExt_R(Self: TOpenDialog; var T: string);
+begin T := Self.DefaultExt; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TOpenDialogHistoryList_W(Self: TOpenDialog; const T: TStrings);
+begin Self.HistoryList := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TOpenDialogHistoryList_R(Self: TOpenDialog; var T: TStrings);
+begin T := Self.HistoryList; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TOpenDialogFiles_R(Self: TOpenDialog; var T: TStrings);
+begin T := Self.Files; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TOpenDialogFileEditStyle_W(Self: TOpenDialog; const T: TFileEditStyle);
+begin Self.FileEditStyle := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TOpenDialogFileEditStyle_R(Self: TOpenDialog; var T: TFileEditStyle);
+begin T := Self.FileEditStyle; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TCommonDialogOnShow_W(Self: TCommonDialog; const T: TNotifyEvent);
+begin Self.OnShow := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TCommonDialogOnShow_R(Self: TCommonDialog; var T: TNotifyEvent);
+begin T := Self.OnShow; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TCommonDialogOnClose_W(Self: TCommonDialog; const T: TNotifyEvent);
+begin Self.OnClose := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TCommonDialogOnClose_R(Self: TCommonDialog; var T: TNotifyEvent);
+begin T := Self.OnClose; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TCommonDialogHelpContext_W(Self: TCommonDialog; const T: THelpContext);
+begin Self.HelpContext := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TCommonDialogHelpContext_R(Self: TCommonDialog; var T: THelpContext);
+begin T := Self.HelpContext; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TCommonDialogCtl3D_W(Self: TCommonDialog; const T: Boolean);
+begin Self.Ctl3D := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TCommonDialogCtl3D_R(Self: TCommonDialog; var T: Boolean);
+begin T := Self.Ctl3D; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TCommonDialogHandle_R(Self: TCommonDialog; var T: HWnd);
+begin T := Self.Handle; end;
+
+(*----------------------------------------------------------------------------*)
+procedure RIRegister_Dialogs_Routines(S: TPSExec);
+begin
+ S.RegisterDelphiFunction(@CreateMessageDialog, 'CreateMessageDialog', cdRegister);
+ S.RegisterDelphiFunction(@MessageDlg, 'MessageDlg', cdRegister);
+ S.RegisterDelphiFunction(@MessageDlgPos, 'MessageDlgPos', cdRegister);
+ S.RegisterDelphiFunction(@MessageDlgPosHelp, 'MessageDlgPosHelp', cdRegister);
+ S.RegisterDelphiFunction(@ShowMessage, 'ShowMessage', cdRegister);
+ S.RegisterDelphiFunction(@ShowMessagePos, 'ShowMessagePos', cdRegister);
+ S.RegisterDelphiFunction(@InputBox, 'InputBox', cdRegister);
+ S.RegisterDelphiFunction(@InputQuery, 'InputQuery', cdRegister);
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure RIRegister_TReplaceDialog(CL: TPSRuntimeClassImporter);
+begin
+ with CL.Add(TReplaceDialog) do
+ begin
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure RIRegister_TFindDialog(CL: TPSRuntimeClassImporter);
+begin
+ with CL.Add(TFindDialog) do
+ begin
+ RegisterMethod(@TFindDialog.CloseDialog, 'CloseDialog');
+ RegisterPropertyHelper(@TFindDialogLeft_R,@TFindDialogLeft_W,'Left');
+ RegisterPropertyHelper(@TFindDialogPosition_R,@TFindDialogPosition_W,'Position');
+ RegisterPropertyHelper(@TFindDialogTop_R,@TFindDialogTop_W,'Top');
+ RegisterPropertyHelper(@TFindDialogFindText_R,@TFindDialogFindText_W,'FindText');
+ RegisterPropertyHelper(@TFindDialogOptions_R,@TFindDialogOptions_W,'Options');
+ RegisterPropertyHelper(@TFindDialogOnFind_R,@TFindDialogOnFind_W,'OnFind');
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure RIRegister_TPrintDialog(CL: TPSRuntimeClassImporter);
+begin
+ with CL.Add(TPrintDialog) do
+ begin
+ RegisterPropertyHelper(@TPrintDialogCollate_R,@TPrintDialogCollate_W,'Collate');
+ RegisterPropertyHelper(@TPrintDialogCopies_R,@TPrintDialogCopies_W,'Copies');
+ RegisterPropertyHelper(@TPrintDialogFromPage_R,@TPrintDialogFromPage_W,'FromPage');
+ RegisterPropertyHelper(@TPrintDialogMinPage_R,@TPrintDialogMinPage_W,'MinPage');
+ RegisterPropertyHelper(@TPrintDialogMaxPage_R,@TPrintDialogMaxPage_W,'MaxPage');
+ RegisterPropertyHelper(@TPrintDialogOptions_R,@TPrintDialogOptions_W,'Options');
+ RegisterPropertyHelper(@TPrintDialogPrintToFile_R,@TPrintDialogPrintToFile_W,'PrintToFile');
+ RegisterPropertyHelper(@TPrintDialogPrintRange_R,@TPrintDialogPrintRange_W,'PrintRange');
+ RegisterPropertyHelper(@TPrintDialogToPage_R,@TPrintDialogToPage_W,'ToPage');
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure RIRegister_TPrinterSetupDialog(CL: TPSRuntimeClassImporter);
+begin
+ with CL.Add(TPrinterSetupDialog) do
+ begin
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure RIRegister_TFontDialog(CL: TPSRuntimeClassImporter);
+begin
+ with CL.Add(TFontDialog) do
+ begin
+ RegisterPropertyHelper(@TFontDialogFont_R,@TFontDialogFont_W,'Font');
+ RegisterPropertyHelper(@TFontDialogDevice_R,@TFontDialogDevice_W,'Device');
+ RegisterPropertyHelper(@TFontDialogMinFontSize_R,@TFontDialogMinFontSize_W,'MinFontSize');
+ RegisterPropertyHelper(@TFontDialogMaxFontSize_R,@TFontDialogMaxFontSize_W,'MaxFontSize');
+ RegisterPropertyHelper(@TFontDialogOptions_R,@TFontDialogOptions_W,'Options');
+ RegisterPropertyHelper(@TFontDialogOnApply_R,@TFontDialogOnApply_W,'OnApply');
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure RIRegister_TColorDialog(CL: TPSRuntimeClassImporter);
+begin
+ with CL.Add(TColorDialog) do
+ begin
+ RegisterPropertyHelper(@TColorDialogColor_R,@TColorDialogColor_W,'Color');
+ RegisterPropertyHelper(@TColorDialogCustomColors_R,@TColorDialogCustomColors_W,'CustomColors');
+ RegisterPropertyHelper(@TColorDialogOptions_R,@TColorDialogOptions_W,'Options');
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure RIRegister_TSaveDialog(CL: TPSRuntimeClassImporter);
+begin
+ with CL.Add(TSaveDialog) do
+ begin
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure RIRegister_TOpenDialog(CL: TPSRuntimeClassImporter);
+begin
+ with CL.Add(TOpenDialog) do
+ begin
+ RegisterPropertyHelper(@TOpenDialogFileEditStyle_R,@TOpenDialogFileEditStyle_W,'FileEditStyle');
+ RegisterPropertyHelper(@TOpenDialogFiles_R,nil,'Files');
+ RegisterPropertyHelper(@TOpenDialogHistoryList_R,@TOpenDialogHistoryList_W,'HistoryList');
+ RegisterPropertyHelper(@TOpenDialogDefaultExt_R,@TOpenDialogDefaultExt_W,'DefaultExt');
+ RegisterPropertyHelper(@TOpenDialogFileName_R,@TOpenDialogFileName_W,'FileName');
+ RegisterPropertyHelper(@TOpenDialogFilter_R,@TOpenDialogFilter_W,'Filter');
+ RegisterPropertyHelper(@TOpenDialogFilterIndex_R,@TOpenDialogFilterIndex_W,'FilterIndex');
+ RegisterPropertyHelper(@TOpenDialogInitialDir_R,@TOpenDialogInitialDir_W,'InitialDir');
+ RegisterPropertyHelper(@TOpenDialogOptions_R,@TOpenDialogOptions_W,'Options');
+ RegisterPropertyHelper(@TOpenDialogTitle_R,@TOpenDialogTitle_W,'Title');
+ RegisterPropertyHelper(@TOpenDialogOnCanClose_R,@TOpenDialogOnCanClose_W,'OnCanClose');
+ RegisterPropertyHelper(@TOpenDialogOnFolderChange_R,@TOpenDialogOnFolderChange_W,'OnFolderChange');
+ RegisterPropertyHelper(@TOpenDialogOnSelectionChange_R,@TOpenDialogOnSelectionChange_W,'OnSelectionChange');
+ RegisterPropertyHelper(@TOpenDialogOnTypeChange_R,@TOpenDialogOnTypeChange_W,'OnTypeChange');
+ RegisterPropertyHelper(@TOpenDialogOnIncludeItem_R,@TOpenDialogOnIncludeItem_W,'OnIncludeItem');
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure RIRegister_TCommonDialog(CL: TPSRuntimeClassImporter);
+begin
+ with CL.Add(TCommonDialog) do
+ begin
+ RegisterPropertyHelper(@TCommonDialogHandle_R,nil,'Handle');
+ RegisterPropertyHelper(@TCommonDialogCtl3D_R,@TCommonDialogCtl3D_W,'Ctl3D');
+ RegisterPropertyHelper(@TCommonDialogHelpContext_R,@TCommonDialogHelpContext_W,'HelpContext');
+ RegisterPropertyHelper(@TCommonDialogOnClose_R,@TCommonDialogOnClose_W,'OnClose');
+ RegisterPropertyHelper(@TCommonDialogOnShow_R,@TCommonDialogOnShow_W,'OnShow');
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure RIRegister_Dialogs(CL: TPSRuntimeClassImporter);
+begin
+ RIRegister_TCommonDialog(CL);
+ RIRegister_TOpenDialog(CL);
+ RIRegister_TSaveDialog(CL);
+ RIRegister_TColorDialog(CL);
+ RIRegister_TFontDialog(CL);
+ RIRegister_TPrinterSetupDialog(CL);
+ RIRegister_TPrintDialog(CL);
+ RIRegister_TFindDialog(CL);
+ RIRegister_TReplaceDialog(CL);
+end;
+
+
+
+{ TPSImport_Dialogs }
+(*----------------------------------------------------------------------------*)
+procedure TPSImport_Dialogs.CompOnUses(CompExec: TPSScript);
+begin
+ { nothing }
+end;
+(*----------------------------------------------------------------------------*)
+procedure TPSImport_Dialogs.ExecOnUses(CompExec: TPSScript);
+begin
+ { nothing }
+end;
+(*----------------------------------------------------------------------------*)
+procedure TPSImport_Dialogs.CompileImport1(CompExec: TPSScript);
+begin
+ SIRegister_Dialogs(CompExec.Comp);
+end;
+(*----------------------------------------------------------------------------*)
+procedure TPSImport_Dialogs.CompileImport2(CompExec: TPSScript);
+begin
+ { nothing }
+end;
+(*----------------------------------------------------------------------------*)
+procedure TPSImport_Dialogs.ExecImport1(CompExec: TPSScript; const ri: TPSRuntimeClassImporter);
+begin
+ RIRegister_Dialogs(ri);
+ RIRegister_Dialogs_Routines(CompExec.Exec); // comment it if no routines
+end;
+(*----------------------------------------------------------------------------*)
+procedure TPSImport_Dialogs.ExecImport2(CompExec: TPSScript; const ri: TPSRuntimeClassImporter);
+begin
+ { nothing }
+end;
+
+end.
diff --git a/branches/script-component/Units/PascalScript/uPSI_IBX.pas b/branches/script-component/Units/PascalScript/uPSI_IBX.pas
new file mode 100644
index 0000000..54046a3
--- /dev/null
+++ b/branches/script-component/Units/PascalScript/uPSI_IBX.pas
@@ -0,0 +1,2153 @@
+unit uPSI_IBX;
+{
+This file has been generated by UnitParser v0.4, written by M. Knight.
+Source Code from Carlo Kok has been used to implement various sections of
+UnitParser. Components of ifps3 are used in the construction of UnitParser,
+code implementing the class wrapper is taken from Carlo Kok''s conv unility
+}
+
+interface
+
+uses
+ SysUtils, Classes, uPSComponent, uPSCompiler, uPSRuntime;
+
+type
+ TPSImport_IBX = class(TPSPlugin)
+ protected
+ procedure CompOnUses(CompExec: TPSScript); override;
+ procedure ExecOnUses(CompExec: TPSScript); override;
+ procedure CompileImport1(CompExec: TPSScript); override;
+ procedure CompileImport2(CompExec: TPSScript); override;
+ procedure ExecImport1(CompExec: TPSScript; const ri: TPSRuntimeClassImporter); override;
+ procedure ExecImport2(CompExec: TPSScript; const ri: TPSRuntimeClassImporter); override;
+ end;
+
+
+
+implementation
+
+
+uses
+ WINDOWS
+ ,CONTROLS
+ ,IBEXTERNALS
+ ,IB
+ ,IBDatabase
+ ,IBHEADER
+ ,STDVCL
+ ,IBSQL
+ ,DB
+ ,IBUTILS
+ ,IBBLOB
+ ,IBCustomDataSet
+ ,IBTable
+ ,IBQuery
+ ;
+
+(* === compile-time registration functions === *)
+(*----------------------------------------------------------------------------*)
+procedure SIRegister_TIBDATASET(CL: TPSPascalCompiler);
+begin
+ //with RegClassS(CL,'TIBCUSTOMDATASET', 'TIBDATASET') do
+ with CL.AddClassN(CL.FindClass('TIBCUSTOMDATASET'),'TIBDATASET') do
+ begin
+ RegisterMethod('Procedure PREPARE');
+ RegisterMethod('Procedure UNPREPARE');
+ RegisterMethod('Procedure BATCHINPUT( INPUTOBJECT : TIBBATCHINPUT)');
+ RegisterMethod('Procedure BATCHOUTPUT( OUTPUTOBJECT : TIBBATCHOUTPUT)');
+ RegisterMethod('Procedure EXECSQL');
+ RegisterMethod('Function PARAMBYNAME( IDX : STRING) : TIBXSQLVAR');
+ RegisterProperty('PREPARED', 'BOOLEAN', iptr);
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure SIRegister_TIBCUSTOMDATASET(CL: TPSPascalCompiler);
+begin
+ //with RegClassS(CL,'TDATASET', 'TIBCUSTOMDATASET') do
+ with CL.AddClassN(CL.FindClass('TDATASET'),'TIBCUSTOMDATASET') do
+ begin
+ RegisterMethod('Procedure APPLYUPDATES');
+ RegisterMethod('Function CACHEDUPDATESTATUS : TCACHEDUPDATESTATUS');
+ RegisterMethod('Procedure CANCELUPDATES');
+ RegisterMethod('Procedure FETCHALL');
+ RegisterMethod('Function LOCATENEXT( const KEYFIELDS : STRING; const KEYVALUES : VARIANT; OPTIONS : TLOCATEOPTIONS) : BOOLEAN');
+// RegisterMethod('Function LOCATE( const KEYFIELDS : STRING; const KEYVALUES : VARIANT; OPTIONS : TLOCATEOPTIONS) : BOOLEAN');
+ RegisterMethod('Procedure RECORDMODIFIED( VALUE : BOOLEAN)');
+ RegisterMethod('Procedure REVERTRECORD');
+ RegisterMethod('Procedure UNDELETE');
+ RegisterMethod('Function CURRENT : TIBXSQLDA');
+ RegisterMethod('Function SQLTYPE : TIBSQLTYPES');
+ RegisterProperty('DBHANDLE', 'PISC_DB_HANDLE', iptr);
+ RegisterProperty('TRHANDLE', 'PISC_TR_HANDLE', iptr);
+ RegisterProperty('UPDATEOBJECT', 'TIBDATASETUPDATEOBJECT', iptrw);
+ RegisterProperty('UPDATESPENDING', 'BOOLEAN', iptr);
+ RegisterProperty('UPDATERECORDTYPES', 'TIBUPDATERECORDTYPES', iptrw);
+ RegisterProperty('ROWSAFFECTED', 'INTEGER', iptr);
+ RegisterProperty('PLAN', 'STRING', iptr);
+ RegisterProperty('DATABASE', 'TIBDATABASE', iptrw);
+ RegisterProperty('TRANSACTION', 'TIBTRANSACTION', iptrw);
+ RegisterProperty('FORCEDREFRESH', 'BOOLEAN', iptrw);
+ RegisterProperty('ONUPDATEERROR', 'TIBUPDATEERROREVENT', iptrw);
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure SIRegister_TIBGENERATORFIELD(CL: TPSPascalCompiler);
+begin
+ //with RegClassS(CL,'TPERSISTENT', 'TIBGENERATORFIELD') do
+ with CL.AddClassN(CL.FindClass('TPERSISTENT'),'TIBGENERATORFIELD') do
+ begin
+ RegisterMethod('Constructor CREATE( ADATASET : TIBCUSTOMDATASET)');
+ RegisterMethod('Function VALUENAME : STRING');
+ RegisterMethod('Procedure APPLY');
+ RegisterProperty('FIELD', 'STRING', iptrw);
+ RegisterProperty('GENERATOR', 'STRING', iptrw);
+ RegisterProperty('INCREMENTBY', 'INTEGER', iptrw);
+ RegisterProperty('APPLYEVENT', 'TIBGENERATORAPPLYEVENT', iptrw);
+ end;
+end;
+
+(* === compile-time registration functions === *)
+(*----------------------------------------------------------------------------*)
+procedure SIRegister_TIBBASE(CL: TPSPascalCompiler);
+begin
+ //with RegClassS(CL,'TOBJECT', 'TIBBASE') do
+ with CL.AddClassN(CL.FindClass('TOBJECT'),'TIBBASE') do
+ begin
+ RegisterMethod('Constructor CREATE( AOWNER : TOBJECT)');
+ RegisterMethod('Procedure CHECKDATABASE');
+ RegisterMethod('Procedure CHECKTRANSACTION');
+ RegisterProperty('BEFOREDATABASEDISCONNECT', 'TNOTIFYEVENT', iptrw);
+ RegisterProperty('AFTERDATABASEDISCONNECT', 'TNOTIFYEVENT', iptrw);
+ RegisterProperty('ONDATABASEFREE', 'TNOTIFYEVENT', iptrw);
+ RegisterProperty('BEFORETRANSACTIONEND', 'TNOTIFYEVENT', iptrw);
+ RegisterProperty('AFTERTRANSACTIONEND', 'TNOTIFYEVENT', iptrw);
+ RegisterProperty('ONTRANSACTIONFREE', 'TNOTIFYEVENT', iptrw);
+ RegisterProperty('DATABASE', 'TIBDATABASE', iptrw);
+ RegisterProperty('DBHANDLE', 'PISC_DB_HANDLE', iptr);
+ RegisterProperty('OWNER', 'TOBJECT', iptr);
+ RegisterProperty('TRHANDLE', 'PISC_TR_HANDLE', iptr);
+ RegisterProperty('TRANSACTION', 'TIBTRANSACTION', iptrw);
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure SIRegister_TIBTRANSACTION(CL: TPSPascalCompiler);
+begin
+ //with RegClassS(CL,'TCOMPONENT', 'TIBTRANSACTION') do
+ with CL.AddClassN(CL.FindClass('TCOMPONENT'),'TIBTRANSACTION') do
+ begin
+ RegisterMethod('Function CALL( ERRCODE : ISC_STATUS; RAISEERROR : BOOLEAN) : ISC_STATUS');
+ RegisterMethod('Procedure COMMIT');
+ RegisterMethod('Procedure COMMITRETAINING');
+ RegisterMethod('Procedure ROLLBACK');
+ RegisterMethod('Procedure ROLLBACKRETAINING');
+ RegisterMethod('Procedure STARTTRANSACTION');
+ RegisterMethod('Procedure CHECKINTRANSACTION');
+ RegisterMethod('Procedure CHECKNOTINTRANSACTION');
+ RegisterMethod('Procedure CHECKAUTOSTOP');
+ RegisterMethod('Function ADDDATABASE( DB : TIBDATABASE) : INTEGER');
+ RegisterMethod('Function FINDDATABASE( DB : TIBDATABASE) : INTEGER');
+ RegisterMethod('Function FINDDEFAULTDATABASE : TIBDATABASE');
+ RegisterMethod('Procedure REMOVEDATABASE( IDX : INTEGER)');
+ RegisterMethod('Procedure REMOVEDATABASES');
+ RegisterMethod('Procedure CHECKDATABASESINLIST');
+ RegisterProperty('DATABASECOUNT', 'INTEGER', iptr);
+ RegisterProperty('DATABASES', 'TIBDATABASE INTEGER', iptr);
+ RegisterProperty('SQLOBJECTCOUNT', 'INTEGER', iptr);
+ RegisterProperty('SQLOBJECTS', 'TIBBASE INTEGER', iptr);
+ RegisterProperty('HANDLE', 'TISC_TR_HANDLE', iptr);
+ RegisterProperty('HANDLEISSHARED', 'BOOLEAN', iptr);
+ RegisterProperty('INTRANSACTION', 'BOOLEAN', iptr);
+ RegisterProperty('TPB', 'PCHAR', iptr);
+ RegisterProperty('TPBLENGTH', 'SHORT', iptr);
+ RegisterProperty('ACTIVE', 'BOOLEAN', iptrw);
+ RegisterProperty('DEFAULTDATABASE', 'TIBDATABASE', iptrw);
+ RegisterProperty('IDLETIMER', 'INTEGER', iptrw);
+ RegisterProperty('DEFAULTACTION', 'TTRANSACTIONACTION', iptrw);
+ RegisterProperty('PARAMS', 'TSTRINGS', iptrw);
+ RegisterProperty('AUTOSTOPACTION', 'TAUTOSTOPACTION', iptrw);
+ RegisterProperty('ONIDLETIMER', 'TNOTIFYEVENT', iptrw);
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure SIRegister_TIBDATABASE(CL: TPSPascalCompiler);
+begin
+ //with RegClassS(CL,'TCUSTOMCONNECTION', 'TIBDATABASE') do
+ with CL.AddClassN(CL.FindClass('TCUSTOMCONNECTION'),'TIBDATABASE') do
+ begin
+ RegisterMethod('Procedure ADDEVENTNOTIFIER( NOTIFIER : IIBEVENTNOTIFIER)');
+ RegisterMethod('Procedure REMOVEEVENTNOTIFIER( NOTIFIER : IIBEVENTNOTIFIER)');
+ RegisterMethod('Procedure APPLYUPDATES( const DATASETS : array of TDATASET)');
+ RegisterMethod('Procedure CLOSEDATASETS');
+ RegisterMethod('Procedure CHECKACTIVE');
+ RegisterMethod('Procedure CHECKINACTIVE');
+ RegisterMethod('Procedure CREATEDATABASE');
+ RegisterMethod('Procedure DROPDATABASE');
+ RegisterMethod('Procedure FORCECLOSE');
+ RegisterMethod('Procedure GETFIELDNAMES( const TABLENAME : STRING; LIST : TSTRINGS)');
+ RegisterMethod('Procedure GETTABLENAMES( LIST : TSTRINGS; SYSTEMTABLES : BOOLEAN)');
+ RegisterMethod('Function INDEXOFDBCONST( ST : STRING) : INTEGER');
+ RegisterMethod('Function TESTCONNECTED : BOOLEAN');
+ RegisterMethod('Procedure CHECKDATABASENAME');
+ RegisterMethod('Function CALL( ERRCODE : ISC_STATUS; RAISEERROR : BOOLEAN) : ISC_STATUS');
+ RegisterMethod('Function ADDTRANSACTION( TR : TIBTRANSACTION) : INTEGER');
+ RegisterMethod('Function FINDTRANSACTION( TR : TIBTRANSACTION) : INTEGER');
+ RegisterMethod('Function FINDDEFAULTTRANSACTION( ) : TIBTRANSACTION');
+ RegisterMethod('Procedure REMOVETRANSACTION( IDX : INTEGER)');
+ RegisterMethod('Procedure REMOVETRANSACTIONS');
+ RegisterMethod('Procedure SETHANDLE( VALUE : TISC_DB_HANDLE)');
+ RegisterMethod('procedure Open');
+ RegisterMethod('procedure Close');
+ RegisterProperty('Connected','BOOLEAN',iptrw);
+ RegisterProperty('HANDLE', 'TISC_DB_HANDLE', iptr);
+ RegisterProperty('ISREADONLY', 'BOOLEAN', iptr);
+ RegisterProperty('DBPARAMBYDPB', 'STRING INTEGER', iptrw);
+ RegisterProperty('SQLOBJECTCOUNT', 'INTEGER', iptr);
+ RegisterProperty('SQLOBJECTS', 'TIBBASE INTEGER', iptr);
+ RegisterProperty('HANDLEISSHARED', 'BOOLEAN', iptr);
+ RegisterProperty('TRANSACTIONCOUNT', 'INTEGER', iptr);
+ RegisterProperty('TRANSACTIONS', 'TIBTRANSACTION INTEGER', iptr);
+ RegisterProperty('INTERNALTRANSACTION', 'TIBTRANSACTION', iptr);
+ RegisterMethod('Function HAS_DEFAULT_VALUE( RELATION, FIELD : STRING) : BOOLEAN');
+ RegisterMethod('Function HAS_COMPUTED_BLR( RELATION, FIELD : STRING) : BOOLEAN');
+ RegisterMethod('Procedure FLUSHSCHEMA');
+ RegisterProperty('DATABASENAME', 'TIBFILENAME', iptrw);
+ RegisterProperty('PARAMS', 'TSTRINGS', iptrw);
+ RegisterProperty('DEFAULTTRANSACTION', 'TIBTRANSACTION', iptrw);
+ RegisterProperty('IDLETIMER', 'INTEGER', iptrw);
+ RegisterProperty('SQLDIALECT', 'INTEGER', iptrw);
+ RegisterProperty('DBSQLDIALECT', 'INTEGER', iptr);
+ RegisterProperty('TRACEFLAGS', 'TTRACEFLAGS', iptrw);
+ RegisterProperty('ALLOWSTREAMEDCONNECTED', 'BOOLEAN', iptrw);
+ RegisterProperty('ONLOGIN', 'TIBDATABASELOGINEVENT', iptrw);
+ RegisterProperty('ONIDLETIMER', 'TNOTIFYEVENT', iptrw);
+ RegisterProperty('ONDIALECTDOWNGRADEWARNING', 'TNOTIFYEVENT', iptrw);
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure SIRegister_TIBSCHEMA(CL: TPSPascalCompiler);
+begin
+ //with RegClassS(CL,'TOBJECT', 'TIBSCHEMA') do
+ with CL.AddClassN(CL.FindClass('TOBJECT'),'TIBSCHEMA') do
+ begin
+ RegisterMethod('Procedure FREENODES');
+ RegisterMethod('Function HAS_DEFAULT_VALUE( RELATION, FIELD : STRING) : BOOLEAN');
+ RegisterMethod('Function HAS_COMPUTED_BLR( RELATION, FIELD : STRING) : BOOLEAN');
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure SIRegister_IBDatabase(CL: TPSPascalCompiler);
+begin
+ CL.AddClassN(CL.FindClass('TOBJECT'),'TIBDATABASE');
+ CL.AddClassN(CL.FindClass('TOBJECT'),'TIBTRANSACTION');
+ CL.AddClassN(CL.FindClass('TOBJECT'),'TIBBASE');
+ CL.AddTypeS('TIBDATABASELOGINEVENT', 'Procedure ( DATABASE : TIBDATABASE; LOG'
+ +'INPARAMS : TSTRINGS)');
+ SIRegister_TIBSCHEMA(CL);
+ CL.AddTypeS('TIBFILENAME', 'STRING');
+ SIRegister_TIBDATABASE(CL);
+ CL.AddTypeS('TTRANSACTIONACTION', '( TAROLLBACK, TACOMMIT, TAROLLBACKRETAININ'
+ +'G, TACOMMITRETAINING )');
+ CL.AddTypeS('TAUTOSTOPACTION', '( SANONE, SAROLLBACK, SACOMMIT, SAROLLBACKRET'
+ +'AINING, SACOMMITRETAINING )');
+ SIRegister_TIBTRANSACTION(CL);
+ SIRegister_TIBBASE(CL);
+end;
+
+(* === run-time registration functions === *)
+(*----------------------------------------------------------------------------*)
+procedure TIBBASETRANSACTION_W(Self: TIBBASE; const T: TIBTRANSACTION);
+begin Self.TRANSACTION := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBBASETRANSACTION_R(Self: TIBBASE; var T: TIBTRANSACTION);
+begin T := Self.TRANSACTION; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBBASETRHANDLE_R(Self: TIBBASE; var T: PISC_TR_HANDLE);
+begin T := Self.TRHANDLE; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBBASEOWNER_R(Self: TIBBASE; var T: TOBJECT);
+begin T := Self.OWNER; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBBASEDBHANDLE_R(Self: TIBBASE; var T: PISC_DB_HANDLE);
+begin T := Self.DBHANDLE; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBBASEDATABASE_W(Self: TIBBASE; const T: TIBDATABASE);
+begin Self.DATABASE := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBBASEDATABASE_R(Self: TIBBASE; var T: TIBDATABASE);
+begin T := Self.DATABASE; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBBASEONTRANSACTIONFREE_W(Self: TIBBASE; const T: TNOTIFYEVENT);
+begin Self.ONTRANSACTIONFREE := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBBASEONTRANSACTIONFREE_R(Self: TIBBASE; var T: TNOTIFYEVENT);
+begin T := Self.ONTRANSACTIONFREE; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBBASEAFTERTRANSACTIONEND_W(Self: TIBBASE; const T: TNOTIFYEVENT);
+begin Self.AFTERTRANSACTIONEND := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBBASEAFTERTRANSACTIONEND_R(Self: TIBBASE; var T: TNOTIFYEVENT);
+begin T := Self.AFTERTRANSACTIONEND; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBBASEBEFORETRANSACTIONEND_W(Self: TIBBASE; const T: TNOTIFYEVENT);
+begin Self.BEFORETRANSACTIONEND := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBBASEBEFORETRANSACTIONEND_R(Self: TIBBASE; var T: TNOTIFYEVENT);
+begin T := Self.BEFORETRANSACTIONEND; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBBASEONDATABASEFREE_W(Self: TIBBASE; const T: TNOTIFYEVENT);
+begin Self.ONDATABASEFREE := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBBASEONDATABASEFREE_R(Self: TIBBASE; var T: TNOTIFYEVENT);
+begin T := Self.ONDATABASEFREE; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBBASEAFTERDATABASEDISCONNECT_W(Self: TIBBASE; const T: TNOTIFYEVENT);
+begin Self.AFTERDATABASEDISCONNECT := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBBASEAFTERDATABASEDISCONNECT_R(Self: TIBBASE; var T: TNOTIFYEVENT);
+begin T := Self.AFTERDATABASEDISCONNECT; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBBASEBEFOREDATABASEDISCONNECT_W(Self: TIBBASE; const T: TNOTIFYEVENT);
+begin Self.BEFOREDATABASEDISCONNECT := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBBASEBEFOREDATABASEDISCONNECT_R(Self: TIBBASE; var T: TNOTIFYEVENT);
+begin T := Self.BEFOREDATABASEDISCONNECT; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBTRANSACTIONONIDLETIMER_W(Self: TIBTRANSACTION; const T: TNOTIFYEVENT);
+begin Self.ONIDLETIMER := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBTRANSACTIONONIDLETIMER_R(Self: TIBTRANSACTION; var T: TNOTIFYEVENT);
+begin T := Self.ONIDLETIMER; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBTRANSACTIONAUTOSTOPACTION_W(Self: TIBTRANSACTION; const T: TAUTOSTOPACTION);
+begin Self.AUTOSTOPACTION := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBTRANSACTIONAUTOSTOPACTION_R(Self: TIBTRANSACTION; var T: TAUTOSTOPACTION);
+begin T := Self.AUTOSTOPACTION; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBTRANSACTIONPARAMS_W(Self: TIBTRANSACTION; const T: TSTRINGS);
+begin Self.PARAMS := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBTRANSACTIONPARAMS_R(Self: TIBTRANSACTION; var T: TSTRINGS);
+begin T := Self.PARAMS; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBTRANSACTIONDEFAULTACTION_W(Self: TIBTRANSACTION; const T: TTRANSACTIONACTION);
+begin Self.DEFAULTACTION := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBTRANSACTIONDEFAULTACTION_R(Self: TIBTRANSACTION; var T: TTRANSACTIONACTION);
+begin T := Self.DEFAULTACTION; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBTRANSACTIONIDLETIMER_W(Self: TIBTRANSACTION; const T: INTEGER);
+begin Self.IDLETIMER := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBTRANSACTIONIDLETIMER_R(Self: TIBTRANSACTION; var T: INTEGER);
+begin T := Self.IDLETIMER; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBTRANSACTIONDEFAULTDATABASE_W(Self: TIBTRANSACTION; const T: TIBDATABASE);
+begin Self.DEFAULTDATABASE := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBTRANSACTIONDEFAULTDATABASE_R(Self: TIBTRANSACTION; var T: TIBDATABASE);
+begin T := Self.DEFAULTDATABASE; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBTRANSACTIONACTIVE_W(Self: TIBTRANSACTION; const T: BOOLEAN);
+begin Self.ACTIVE := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBTRANSACTIONACTIVE_R(Self: TIBTRANSACTION; var T: BOOLEAN);
+begin T := Self.ACTIVE; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBTRANSACTIONTPBLENGTH_R(Self: TIBTRANSACTION; var T: SHORT);
+begin T := Self.TPBLENGTH; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBTRANSACTIONTPB_R(Self: TIBTRANSACTION; var T: PCHAR);
+begin T := Self.TPB; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBTRANSACTIONINTRANSACTION_R(Self: TIBTRANSACTION; var T: BOOLEAN);
+begin T := Self.INTRANSACTION; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBTRANSACTIONHANDLEISSHARED_R(Self: TIBTRANSACTION; var T: BOOLEAN);
+begin T := Self.HANDLEISSHARED; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBTRANSACTIONHANDLE_R(Self: TIBTRANSACTION; var T: TISC_TR_HANDLE);
+begin T := Self.HANDLE; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBTRANSACTIONSQLOBJECTS_R(Self: TIBTRANSACTION; var T: TIBBASE; const t1: INTEGER);
+begin T := Self.SQLOBJECTS[t1]; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBTRANSACTIONSQLOBJECTCOUNT_R(Self: TIBTRANSACTION; var T: INTEGER);
+begin T := Self.SQLOBJECTCOUNT; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBTRANSACTIONDATABASES_R(Self: TIBTRANSACTION; var T: TIBDATABASE; const t1: INTEGER);
+begin T := Self.DATABASES[t1]; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBTRANSACTIONDATABASECOUNT_R(Self: TIBTRANSACTION; var T: INTEGER);
+begin T := Self.DATABASECOUNT; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBDATABASEONDIALECTDOWNGRADEWARNING_W(Self: TIBDATABASE; const T: TNOTIFYEVENT);
+begin Self.ONDIALECTDOWNGRADEWARNING := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBDATABASEONDIALECTDOWNGRADEWARNING_R(Self: TIBDATABASE; var T: TNOTIFYEVENT);
+begin T := Self.ONDIALECTDOWNGRADEWARNING; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBDATABASEONIDLETIMER_W(Self: TIBDATABASE; const T: TNOTIFYEVENT);
+begin Self.ONIDLETIMER := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBDATABASEONIDLETIMER_R(Self: TIBDATABASE; var T: TNOTIFYEVENT);
+begin T := Self.ONIDLETIMER; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBDATABASEONLOGIN_W(Self: TIBDATABASE; const T: TIBDATABASELOGINEVENT);
+begin Self.ONLOGIN := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBDATABASEONLOGIN_R(Self: TIBDATABASE; var T: TIBDATABASELOGINEVENT);
+begin T := Self.ONLOGIN; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBDATABASECONNECTED_W(Self: TIBDATABASE; const T: Boolean);
+begin Self.Connected := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBDATABASECONNECTED_R(Self: TIBDATABASE; var T: Boolean);
+begin T := Self.Connected; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBDATABASEALLOWSTREAMEDCONNECTED_W(Self: TIBDATABASE; const T: BOOLEAN);
+begin Self.ALLOWSTREAMEDCONNECTED := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBDATABASEALLOWSTREAMEDCONNECTED_R(Self: TIBDATABASE; var T: BOOLEAN);
+begin T := Self.ALLOWSTREAMEDCONNECTED; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBDATABASETRACEFLAGS_W(Self: TIBDATABASE; const T: TTRACEFLAGS);
+begin Self.TRACEFLAGS := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBDATABASETRACEFLAGS_R(Self: TIBDATABASE; var T: TTRACEFLAGS);
+begin T := Self.TRACEFLAGS; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBDATABASEDBSQLDIALECT_R(Self: TIBDATABASE; var T: INTEGER);
+begin T := Self.DBSQLDIALECT; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBDATABASESQLDIALECT_W(Self: TIBDATABASE; const T: INTEGER);
+begin Self.SQLDIALECT := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBDATABASESQLDIALECT_R(Self: TIBDATABASE; var T: INTEGER);
+begin T := Self.SQLDIALECT; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBDATABASEIDLETIMER_W(Self: TIBDATABASE; const T: INTEGER);
+begin Self.IDLETIMER := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBDATABASEIDLETIMER_R(Self: TIBDATABASE; var T: INTEGER);
+begin T := Self.IDLETIMER; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBDATABASEDEFAULTTRANSACTION_W(Self: TIBDATABASE; const T: TIBTRANSACTION);
+begin Self.DEFAULTTRANSACTION := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBDATABASEDEFAULTTRANSACTION_R(Self: TIBDATABASE; var T: TIBTRANSACTION);
+begin T := Self.DEFAULTTRANSACTION; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBDATABASEPARAMS_W(Self: TIBDATABASE; const T: TSTRINGS);
+begin Self.PARAMS := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBDATABASEPARAMS_R(Self: TIBDATABASE; var T: TSTRINGS);
+begin T := Self.PARAMS; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBDATABASEDATABASENAME_W(Self: TIBDATABASE; const T: TIBFILENAME);
+begin Self.DATABASENAME := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBDATABASEDATABASENAME_R(Self: TIBDATABASE; var T: TIBFILENAME);
+begin T := Self.DATABASENAME; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBDATABASEINTERNALTRANSACTION_R(Self: TIBDATABASE; var T: TIBTRANSACTION);
+begin T := Self.INTERNALTRANSACTION; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBDATABASETRANSACTIONS_R(Self: TIBDATABASE; var T: TIBTRANSACTION; const t1: INTEGER);
+begin T := Self.TRANSACTIONS[t1]; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBDATABASETRANSACTIONCOUNT_R(Self: TIBDATABASE; var T: INTEGER);
+begin T := Self.TRANSACTIONCOUNT; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBDATABASEHANDLEISSHARED_R(Self: TIBDATABASE; var T: BOOLEAN);
+begin T := Self.HANDLEISSHARED; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBDATABASESQLOBJECTS_R(Self: TIBDATABASE; var T: TIBBASE; const t1: INTEGER);
+begin T := Self.SQLOBJECTS[t1]; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBDATABASESQLOBJECTCOUNT_R(Self: TIBDATABASE; var T: INTEGER);
+begin T := Self.SQLOBJECTCOUNT; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBDATABASEDBPARAMBYDPB_W(Self: TIBDATABASE; const T: STRING; const t1: INTEGER);
+begin Self.DBPARAMBYDPB[t1] := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBDATABASEDBPARAMBYDPB_R(Self: TIBDATABASE; var T: STRING; const t1: INTEGER);
+begin T := Self.DBPARAMBYDPB[t1]; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBDATABASEISREADONLY_R(Self: TIBDATABASE; var T: BOOLEAN);
+begin T := Self.ISREADONLY; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBDATABASEHANDLE_R(Self: TIBDATABASE; var T: TISC_DB_HANDLE);
+begin T := Self.HANDLE; end;
+
+(*----------------------------------------------------------------------------*)
+procedure SIRegister_TIBDATALINK(CL: TPSPascalCompiler);
+begin
+ //with RegClassS(CL,'TDETAILDATALINK', 'TIBDATALINK') do
+ with CL.AddClassN(CL.FindClass('TDETAILDATALINK'),'TIBDATALINK') do
+ begin
+ RegisterMethod('Constructor CREATE( ADATASET : TIBCUSTOMDATASET)');
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure SIRegister_TIBBCDFIELD(CL: TPSPascalCompiler);
+begin
+ //with RegClassS(CL,'TBCDFIELD', 'TIBBCDFIELD') do
+ with CL.AddClassN(CL.FindClass('TBCDFIELD'),'TIBBCDFIELD') do
+ begin
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure SIRegister_TIBSTRINGFIELD(CL: TPSPascalCompiler);
+begin
+ //with RegClassS(CL,'TSTRINGFIELD', 'TIBSTRINGFIELD') do
+ with CL.AddClassN(CL.FindClass('TSTRINGFIELD'),'TIBSTRINGFIELD') do
+ begin
+ RegisterMethod('Function GETVALUE( var VALUE : STRING) : BOOLEAN');
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure SIRegister_TIBDATASETUPDATEOBJECT(CL: TPSPascalCompiler);
+begin
+ //with RegClassS(CL,'TCOMPONENT', 'TIBDATASETUPDATEOBJECT') do
+ with CL.AddClassN(CL.FindClass('TCOMPONENT'),'TIBDATASETUPDATEOBJECT') do
+ begin
+ RegisterProperty('REFRESHSQL', 'TSTRINGS', iptrw);
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure SIRegister_IBCustomDataSet(CL: TPSPascalCompiler);
+begin
+ CL.AddConstantN('BUFFERCACHESIZE','LONGINT').SetInt( 1000);
+ CL.AddConstantN('UNICACHE','LONGINT').SetInt( 2);
+ CL.AddClassN(CL.FindClass('TOBJECT'),'TIBCUSTOMDATASET');
+ CL.AddClassN(CL.FindClass('TOBJECT'),'TIBDATASET');
+ SIRegister_TIBDATASETUPDATEOBJECT(CL);
+ CL.AddTypeS('TCACHEDUPDATESTATUS', '( CUSUNMODIFIED, CUSMODIFIED, CUSINSERTED'
+ +', CUSDELETED, CUSUNINSERTED )');
+ SIRegister_TIBSTRINGFIELD(CL);
+ SIRegister_TIBBCDFIELD(CL);
+ SIRegister_TIBDATALINK(CL);
+ CL.AddTypeS('TIBGENERATORAPPLYEVENT', '( GAMONNEWRECORD, GAMONPOST, GAMONSERV'
+ +'ER )');
+ SIRegister_TIBGENERATORFIELD(CL);
+ CL.AddTypeS('TIBUPDATEACTION', '( UAFAIL, UAABORT, UASKIP, UARETRY, UAAPPLY, '
+ +'UAAPPLIED )');
+ CL.AddTypeS('TIBUPDATERECORDTYPES', 'set of TCACHEDUPDATESTATUS');
+ CL.AddTypeS('TLIVEMODE', '( LMINSERT, LMMODIFY, LMDELETE, LMREFRESH )');
+ CL.AddTypeS('TLIVEMODES', 'set of TLIVEMODE');
+ SIRegister_TIBCUSTOMDATASET(CL);
+ SIRegister_TIBDATASET(CL);
+end;
+
+(* === run-time registration functions === *)
+(*----------------------------------------------------------------------------*)
+procedure TIBDATASETPREPARED_R(Self: TIBDATASET; var T: BOOLEAN);
+begin T := Self.PREPARED; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBCUSTOMDATASETFORCEDREFRESH_W(Self: TIBCUSTOMDATASET; const T: BOOLEAN);
+begin Self.FORCEDREFRESH := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBCUSTOMDATASETFORCEDREFRESH_R(Self: TIBCUSTOMDATASET; var T: BOOLEAN);
+begin T := Self.FORCEDREFRESH; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBCUSTOMDATASETTRANSACTION_W(Self: TIBCUSTOMDATASET; const T: TIBTRANSACTION);
+begin Self.TRANSACTION := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBCUSTOMDATASETTRANSACTION_R(Self: TIBCUSTOMDATASET; var T: TIBTRANSACTION);
+begin T := Self.TRANSACTION; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBCUSTOMDATASETDATABASE_W(Self: TIBCUSTOMDATASET; const T: TIBDATABASE);
+begin Self.DATABASE := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBCUSTOMDATASETDATABASE_R(Self: TIBCUSTOMDATASET; var T: TIBDATABASE);
+begin T := Self.DATABASE; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBCUSTOMDATASETPLAN_R(Self: TIBCUSTOMDATASET; var T: STRING);
+begin T := Self.PLAN; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBCUSTOMDATASETROWSAFFECTED_R(Self: TIBCUSTOMDATASET; var T: INTEGER);
+begin T := Self.ROWSAFFECTED; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBCUSTOMDATASETUPDATERECORDTYPES_W(Self: TIBCUSTOMDATASET; const T: TIBUPDATERECORDTYPES);
+begin Self.UPDATERECORDTYPES := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBCUSTOMDATASETUPDATERECORDTYPES_R(Self: TIBCUSTOMDATASET; var T: TIBUPDATERECORDTYPES);
+begin T := Self.UPDATERECORDTYPES; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBCUSTOMDATASETUPDATESPENDING_R(Self: TIBCUSTOMDATASET; var T: BOOLEAN);
+begin T := Self.UPDATESPENDING; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBCUSTOMDATASETUPDATEOBJECT_W(Self: TIBCUSTOMDATASET; const T: TIBDATASETUPDATEOBJECT);
+begin Self.UPDATEOBJECT := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBCUSTOMDATASETUPDATEOBJECT_R(Self: TIBCUSTOMDATASET; var T: TIBDATASETUPDATEOBJECT);
+begin T := Self.UPDATEOBJECT; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBCUSTOMDATASETTRHANDLE_R(Self: TIBCUSTOMDATASET; var T: PISC_TR_HANDLE);
+begin T := Self.TRHANDLE; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBCUSTOMDATASETDBHANDLE_R(Self: TIBCUSTOMDATASET; var T: PISC_DB_HANDLE);
+begin T := Self.DBHANDLE; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBGENERATORFIELDAPPLYEVENT_W(Self: TIBGENERATORFIELD; const T: TIBGENERATORAPPLYEVENT);
+begin Self.APPLYEVENT := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBGENERATORFIELDAPPLYEVENT_R(Self: TIBGENERATORFIELD; var T: TIBGENERATORAPPLYEVENT);
+begin T := Self.APPLYEVENT; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBGENERATORFIELDINCREMENTBY_W(Self: TIBGENERATORFIELD; const T: INTEGER);
+begin Self.INCREMENTBY := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBGENERATORFIELDINCREMENTBY_R(Self: TIBGENERATORFIELD; var T: INTEGER);
+begin T := Self.INCREMENTBY; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBGENERATORFIELDGENERATOR_W(Self: TIBGENERATORFIELD; const T: STRING);
+begin Self.GENERATOR := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBGENERATORFIELDGENERATOR_R(Self: TIBGENERATORFIELD; var T: STRING);
+begin T := Self.GENERATOR; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBGENERATORFIELDFIELD_W(Self: TIBGENERATORFIELD; const T: STRING);
+begin Self.FIELD := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBGENERATORFIELDFIELD_R(Self: TIBGENERATORFIELD; var T: STRING);
+begin T := Self.FIELD; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBDATASETUPDATEOBJECTREFRESHSQL_W(Self: TIBDATASETUPDATEOBJECT; const T: TSTRINGS);
+begin Self.REFRESHSQL := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBDATASETUPDATEOBJECTREFRESHSQL_R(Self: TIBDATASETUPDATEOBJECT; var T: TSTRINGS);
+begin T := Self.REFRESHSQL; end;
+
+(*----------------------------------------------------------------------------*)
+procedure RIRegister_TIBDATASET(CL: TPSRuntimeClassImporter);
+begin
+ with CL.Add(TIBDATASET) do
+ begin
+ RegisterMethod(@TIBDATASET.PREPARE, 'PREPARE');
+ RegisterMethod(@TIBDATASET.UNPREPARE, 'UNPREPARE');
+ RegisterMethod(@TIBDATASET.BATCHINPUT, 'BATCHINPUT');
+ RegisterMethod(@TIBDATASET.BATCHOUTPUT, 'BATCHOUTPUT');
+ RegisterMethod(@TIBDATASET.EXECSQL, 'EXECSQL');
+ RegisterMethod(@TIBDATASET.PARAMBYNAME, 'PARAMBYNAME');
+ RegisterPropertyHelper(@TIBDATASETPREPARED_R,nil,'PREPARED');
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure RIRegister_TIBCUSTOMDATASET(CL: TPSRuntimeClassImporter);
+begin
+ with CL.Add(TIBCUSTOMDATASET) do
+ begin
+ RegisterMethod(@TIBCUSTOMDATASET.APPLYUPDATES, 'APPLYUPDATES');
+ RegisterMethod(@TIBCUSTOMDATASET.CACHEDUPDATESTATUS, 'CACHEDUPDATESTATUS');
+ RegisterMethod(@TIBCUSTOMDATASET.CANCELUPDATES, 'CANCELUPDATES');
+ RegisterMethod(@TIBCUSTOMDATASET.FETCHALL, 'FETCHALL');
+ RegisterMethod(@TIBCUSTOMDATASET.LOCATENEXT, 'LOCATENEXT');
+// RegisterMethod(@TIBCUSTOMDATASET.LOCATE, 'LOCATE');
+ RegisterMethod(@TIBCUSTOMDATASET.RECORDMODIFIED, 'RECORDMODIFIED');
+ RegisterMethod(@TIBCUSTOMDATASET.REVERTRECORD, 'REVERTRECORD');
+ RegisterMethod(@TIBCUSTOMDATASET.UNDELETE, 'UNDELETE');
+ RegisterMethod(@TIBCUSTOMDATASET.CURRENT, 'CURRENT');
+ RegisterMethod(@TIBCUSTOMDATASET.SQLTYPE, 'SQLTYPE');
+ RegisterPropertyHelper(@TIBCUSTOMDATASETDBHANDLE_R,nil,'DBHANDLE');
+ RegisterPropertyHelper(@TIBCUSTOMDATASETTRHANDLE_R,nil,'TRHANDLE');
+ RegisterPropertyHelper(@TIBCUSTOMDATASETUPDATEOBJECT_R,@TIBCUSTOMDATASETUPDATEOBJECT_W,'UPDATEOBJECT');
+ RegisterPropertyHelper(@TIBCUSTOMDATASETUPDATESPENDING_R,nil,'UPDATESPENDING');
+ RegisterPropertyHelper(@TIBCUSTOMDATASETUPDATERECORDTYPES_R,@TIBCUSTOMDATASETUPDATERECORDTYPES_W,'UPDATERECORDTYPES');
+ RegisterPropertyHelper(@TIBCUSTOMDATASETROWSAFFECTED_R,nil,'ROWSAFFECTED');
+ RegisterPropertyHelper(@TIBCUSTOMDATASETPLAN_R,nil,'PLAN');
+ RegisterPropertyHelper(@TIBCUSTOMDATASETDATABASE_R,@TIBCUSTOMDATASETDATABASE_W,'DATABASE');
+ RegisterPropertyHelper(@TIBCUSTOMDATASETTRANSACTION_R,@TIBCUSTOMDATASETTRANSACTION_W,'TRANSACTION');
+ RegisterPropertyHelper(@TIBCUSTOMDATASETFORCEDREFRESH_R,@TIBCUSTOMDATASETFORCEDREFRESH_W,'FORCEDREFRESH');
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure RIRegister_TIBGENERATORFIELD(CL: TPSRuntimeClassImporter);
+begin
+ with CL.Add(TIBGENERATORFIELD) do
+ begin
+ RegisterConstructor(@TIBGENERATORFIELD.CREATE, 'CREATE');
+ RegisterMethod(@TIBGENERATORFIELD.VALUENAME, 'VALUENAME');
+ RegisterMethod(@TIBGENERATORFIELD.APPLY, 'APPLY');
+ RegisterPropertyHelper(@TIBGENERATORFIELDFIELD_R,@TIBGENERATORFIELDFIELD_W,'FIELD');
+ RegisterPropertyHelper(@TIBGENERATORFIELDGENERATOR_R,@TIBGENERATORFIELDGENERATOR_W,'GENERATOR');
+ RegisterPropertyHelper(@TIBGENERATORFIELDINCREMENTBY_R,@TIBGENERATORFIELDINCREMENTBY_W,'INCREMENTBY');
+ RegisterPropertyHelper(@TIBGENERATORFIELDAPPLYEVENT_R,@TIBGENERATORFIELDAPPLYEVENT_W,'APPLYEVENT');
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure RIRegister_TIBDATALINK(CL: TPSRuntimeClassImporter);
+begin
+ with CL.Add(TIBDATALINK) do
+ begin
+ RegisterConstructor(@TIBDATALINK.CREATE, 'CREATE');
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure RIRegister_TIBBCDFIELD(CL: TPSRuntimeClassImporter);
+begin
+ with CL.Add(TIBBCDFIELD) do
+ begin
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure RIRegister_TIBSTRINGFIELD(CL: TPSRuntimeClassImporter);
+begin
+ with CL.Add(TIBSTRINGFIELD) do
+ begin
+ RegisterMethod(@TIBSTRINGFIELD.GETVALUE, 'GETVALUE');
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure RIRegister_TIBDATASETUPDATEOBJECT(CL: TPSRuntimeClassImporter);
+begin
+ with CL.Add(TIBDATASETUPDATEOBJECT) do
+ begin
+ RegisterPropertyHelper(@TIBDATASETUPDATEOBJECTREFRESHSQL_R,@TIBDATASETUPDATEOBJECTREFRESHSQL_W,'REFRESHSQL');
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure RIRegister_IBCustomDataSet(CL: TPSRuntimeClassImporter);
+begin
+ with CL.Add(TIBCUSTOMDATASET) do
+ with CL.Add(TIBDATASET) do
+ RIRegister_TIBDATASETUPDATEOBJECT(CL);
+ RIRegister_TIBSTRINGFIELD(CL);
+ RIRegister_TIBBCDFIELD(CL);
+ RIRegister_TIBDATALINK(CL);
+ RIRegister_TIBGENERATORFIELD(CL);
+ RIRegister_TIBCUSTOMDATASET(CL);
+ RIRegister_TIBDATASET(CL);
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure RIRegister_TIBBASE(CL: TPSRuntimeClassImporter);
+begin
+ with CL.Add(TIBBASE) do
+ begin
+ RegisterConstructor(@TIBBASE.CREATE, 'CREATE');
+ RegisterVirtualMethod(@TIBBASE.CHECKDATABASE, 'CHECKDATABASE');
+ RegisterVirtualMethod(@TIBBASE.CHECKTRANSACTION, 'CHECKTRANSACTION');
+ RegisterPropertyHelper(@TIBBASEBEFOREDATABASEDISCONNECT_R,@TIBBASEBEFOREDATABASEDISCONNECT_W,'BEFOREDATABASEDISCONNECT');
+ RegisterPropertyHelper(@TIBBASEAFTERDATABASEDISCONNECT_R,@TIBBASEAFTERDATABASEDISCONNECT_W,'AFTERDATABASEDISCONNECT');
+ RegisterEventPropertyHelper(@TIBBASEONDATABASEFREE_R,@TIBBASEONDATABASEFREE_W,'ONDATABASEFREE');
+ RegisterPropertyHelper(@TIBBASEBEFORETRANSACTIONEND_R,@TIBBASEBEFORETRANSACTIONEND_W,'BEFORETRANSACTIONEND');
+ RegisterPropertyHelper(@TIBBASEAFTERTRANSACTIONEND_R,@TIBBASEAFTERTRANSACTIONEND_W,'AFTERTRANSACTIONEND');
+ RegisterEventPropertyHelper(@TIBBASEONTRANSACTIONFREE_R,@TIBBASEONTRANSACTIONFREE_W,'ONTRANSACTIONFREE');
+ RegisterPropertyHelper(@TIBBASEDATABASE_R,@TIBBASEDATABASE_W,'DATABASE');
+ RegisterPropertyHelper(@TIBBASEDBHANDLE_R,nil,'DBHANDLE');
+ RegisterPropertyHelper(@TIBBASEOWNER_R,nil,'OWNER');
+ RegisterPropertyHelper(@TIBBASETRHANDLE_R,nil,'TRHANDLE');
+ RegisterPropertyHelper(@TIBBASETRANSACTION_R,@TIBBASETRANSACTION_W,'TRANSACTION');
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure RIRegister_TIBTRANSACTION(CL: TPSRuntimeClassImporter);
+begin
+ with CL.Add(TIBTRANSACTION) do
+ begin
+ RegisterMethod(@TIBTRANSACTION.CALL, 'CALL');
+ RegisterMethod(@TIBTRANSACTION.COMMIT, 'COMMIT');
+ RegisterMethod(@TIBTRANSACTION.COMMITRETAINING, 'COMMITRETAINING');
+ RegisterMethod(@TIBTRANSACTION.ROLLBACK, 'ROLLBACK');
+ RegisterMethod(@TIBTRANSACTION.ROLLBACKRETAINING, 'ROLLBACKRETAINING');
+ RegisterMethod(@TIBTRANSACTION.STARTTRANSACTION, 'STARTTRANSACTION');
+ RegisterMethod(@TIBTRANSACTION.CHECKINTRANSACTION, 'CHECKINTRANSACTION');
+ RegisterMethod(@TIBTRANSACTION.CHECKNOTINTRANSACTION, 'CHECKNOTINTRANSACTION');
+ RegisterMethod(@TIBTRANSACTION.CHECKAUTOSTOP, 'CHECKAUTOSTOP');
+ RegisterMethod(@TIBTRANSACTION.ADDDATABASE, 'ADDDATABASE');
+ RegisterMethod(@TIBTRANSACTION.FINDDATABASE, 'FINDDATABASE');
+ RegisterMethod(@TIBTRANSACTION.FINDDEFAULTDATABASE, 'FINDDEFAULTDATABASE');
+ RegisterMethod(@TIBTRANSACTION.REMOVEDATABASE, 'REMOVEDATABASE');
+ RegisterMethod(@TIBTRANSACTION.REMOVEDATABASES, 'REMOVEDATABASES');
+ RegisterMethod(@TIBTRANSACTION.CHECKDATABASESINLIST, 'CHECKDATABASESINLIST');
+ RegisterPropertyHelper(@TIBTRANSACTIONDATABASECOUNT_R,nil,'DATABASECOUNT');
+ RegisterPropertyHelper(@TIBTRANSACTIONDATABASES_R,nil,'DATABASES');
+ RegisterPropertyHelper(@TIBTRANSACTIONSQLOBJECTCOUNT_R,nil,'SQLOBJECTCOUNT');
+ RegisterPropertyHelper(@TIBTRANSACTIONSQLOBJECTS_R,nil,'SQLOBJECTS');
+ RegisterPropertyHelper(@TIBTRANSACTIONHANDLE_R,nil,'HANDLE');
+ RegisterPropertyHelper(@TIBTRANSACTIONHANDLEISSHARED_R,nil,'HANDLEISSHARED');
+ RegisterPropertyHelper(@TIBTRANSACTIONINTRANSACTION_R,nil,'INTRANSACTION');
+ RegisterPropertyHelper(@TIBTRANSACTIONTPB_R,nil,'TPB');
+ RegisterPropertyHelper(@TIBTRANSACTIONTPBLENGTH_R,nil,'TPBLENGTH');
+ RegisterPropertyHelper(@TIBTRANSACTIONACTIVE_R,@TIBTRANSACTIONACTIVE_W,'ACTIVE');
+ RegisterPropertyHelper(@TIBTRANSACTIONDEFAULTDATABASE_R,@TIBTRANSACTIONDEFAULTDATABASE_W,'DEFAULTDATABASE');
+ RegisterPropertyHelper(@TIBTRANSACTIONIDLETIMER_R,@TIBTRANSACTIONIDLETIMER_W,'IDLETIMER');
+ RegisterPropertyHelper(@TIBTRANSACTIONDEFAULTACTION_R,@TIBTRANSACTIONDEFAULTACTION_W,'DEFAULTACTION');
+ RegisterPropertyHelper(@TIBTRANSACTIONPARAMS_R,@TIBTRANSACTIONPARAMS_W,'PARAMS');
+ RegisterPropertyHelper(@TIBTRANSACTIONAUTOSTOPACTION_R,@TIBTRANSACTIONAUTOSTOPACTION_W,'AUTOSTOPACTION');
+ RegisterEventPropertyHelper(@TIBTRANSACTIONONIDLETIMER_R,@TIBTRANSACTIONONIDLETIMER_W,'ONIDLETIMER');
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure RIRegister_TIBDATABASE(CL: TPSRuntimeClassImporter);
+begin
+ with CL.Add(TIBDATABASE) do
+ begin
+ RegisterMethod(@TIBDATABASE.ADDEVENTNOTIFIER, 'ADDEVENTNOTIFIER');
+ RegisterMethod(@TIBDATABASE.REMOVEEVENTNOTIFIER, 'REMOVEEVENTNOTIFIER');
+ RegisterMethod(@TIBDATABASE.APPLYUPDATES, 'APPLYUPDATES');
+ RegisterMethod(@TIBDATABASE.CLOSEDATASETS, 'CLOSEDATASETS');
+ RegisterMethod(@TIBDATABASE.CHECKACTIVE, 'CHECKACTIVE');
+ RegisterMethod(@TIBDATABASE.CHECKINACTIVE, 'CHECKINACTIVE');
+ RegisterMethod(@TIBDATABASE.CREATEDATABASE, 'CREATEDATABASE');
+ RegisterMethod(@TIBDATABASE.DROPDATABASE, 'DROPDATABASE');
+ RegisterMethod(@TIBDATABASE.FORCECLOSE, 'FORCECLOSE');
+ RegisterMethod(@TIBDATABASE.GETFIELDNAMES, 'GETFIELDNAMES');
+ RegisterMethod(@TIBDATABASE.GETTABLENAMES, 'GETTABLENAMES');
+ RegisterMethod(@TIBDATABASE.INDEXOFDBCONST, 'INDEXOFDBCONST');
+ RegisterMethod(@TIBDATABASE.TESTCONNECTED, 'TESTCONNECTED');
+ RegisterMethod(@TIBDATABASE.CHECKDATABASENAME, 'CHECKDATABASENAME');
+ RegisterMethod(@TIBDATABASE.CALL, 'CALL');
+ RegisterMethod(@TIBDATABASE.Open, 'OPEN');
+ RegisterMethod(@TIBDATABASE.Close, 'CLOSE');
+ RegisterMethod(@TIBDATABASE.ADDTRANSACTION, 'ADDTRANSACTION');
+ RegisterMethod(@TIBDATABASE.FINDTRANSACTION, 'FINDTRANSACTION');
+ RegisterMethod(@TIBDATABASE.FINDDEFAULTTRANSACTION, 'FINDDEFAULTTRANSACTION');
+ RegisterMethod(@TIBDATABASE.REMOVETRANSACTION, 'REMOVETRANSACTION');
+ RegisterMethod(@TIBDATABASE.REMOVETRANSACTIONS, 'REMOVETRANSACTIONS');
+ RegisterMethod(@TIBDATABASE.SETHANDLE, 'SETHANDLE');
+ RegisterPropertyHelper(@TIBDATABASEHANDLE_R,nil,'HANDLE');
+ RegisterPropertyHelper(@TIBDATABASEISREADONLY_R,nil,'ISREADONLY');
+ RegisterPropertyHelper(@TIBDATABASEDBPARAMBYDPB_R,@TIBDATABASEDBPARAMBYDPB_W,'DBPARAMBYDPB');
+ RegisterPropertyHelper(@TIBDATABASESQLOBJECTCOUNT_R,nil,'SQLOBJECTCOUNT');
+ RegisterPropertyHelper(@TIBDATABASESQLOBJECTS_R,nil,'SQLOBJECTS');
+ RegisterPropertyHelper(@TIBDATABASEHANDLEISSHARED_R,nil,'HANDLEISSHARED');
+ RegisterPropertyHelper(@TIBDATABASETRANSACTIONCOUNT_R,nil,'TRANSACTIONCOUNT');
+ RegisterPropertyHelper(@TIBDATABASETRANSACTIONS_R,nil,'TRANSACTIONS');
+ RegisterPropertyHelper(@TIBDATABASEINTERNALTRANSACTION_R,nil,'INTERNALTRANSACTION');
+ RegisterMethod(@TIBDATABASE.HAS_DEFAULT_VALUE, 'HAS_DEFAULT_VALUE');
+ RegisterMethod(@TIBDATABASE.HAS_COMPUTED_BLR, 'HAS_COMPUTED_BLR');
+ RegisterMethod(@TIBDATABASE.FLUSHSCHEMA, 'FLUSHSCHEMA');
+ RegisterPropertyHelper(@TIBDATABASEDATABASENAME_R,@TIBDATABASEDATABASENAME_W,'DATABASENAME');
+ RegisterPropertyHelper(@TIBDATABASECONNECTED_R,@TIBDATABASECONNECTED_W,'CONNECTED');
+ RegisterPropertyHelper(@TIBDATABASEPARAMS_R,@TIBDATABASEPARAMS_W,'PARAMS');
+ RegisterPropertyHelper(@TIBDATABASEDEFAULTTRANSACTION_R,@TIBDATABASEDEFAULTTRANSACTION_W,'DEFAULTTRANSACTION');
+ RegisterPropertyHelper(@TIBDATABASEIDLETIMER_R,@TIBDATABASEIDLETIMER_W,'IDLETIMER');
+ RegisterPropertyHelper(@TIBDATABASESQLDIALECT_R,@TIBDATABASESQLDIALECT_W,'SQLDIALECT');
+ RegisterPropertyHelper(@TIBDATABASEDBSQLDIALECT_R,nil,'DBSQLDIALECT');
+ RegisterPropertyHelper(@TIBDATABASETRACEFLAGS_R,@TIBDATABASETRACEFLAGS_W,'TRACEFLAGS');
+ RegisterPropertyHelper(@TIBDATABASEALLOWSTREAMEDCONNECTED_R,@TIBDATABASEALLOWSTREAMEDCONNECTED_W,'ALLOWSTREAMEDCONNECTED');
+ RegisterEventPropertyHelper(@TIBDATABASEONLOGIN_R,@TIBDATABASEONLOGIN_W,'ONLOGIN');
+ RegisterEventPropertyHelper(@TIBDATABASEONIDLETIMER_R,@TIBDATABASEONIDLETIMER_W,'ONIDLETIMER');
+ RegisterEventPropertyHelper(@TIBDATABASEONDIALECTDOWNGRADEWARNING_R,@TIBDATABASEONDIALECTDOWNGRADEWARNING_W,'ONDIALECTDOWNGRADEWARNING');
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure RIRegister_IBDatabase(CL: TPSRuntimeClassImporter);
+begin
+ with CL.Add(TIBDATABASE) do
+ with CL.Add(TIBTRANSACTION) do
+ with CL.Add(TIBBASE) do
+ RIRegister_TIBDATABASE(CL);
+ RIRegister_TIBTRANSACTION(CL);
+ RIRegister_TIBBASE(CL);
+end;
+
+(* === compile-time registration functions === *)
+(*----------------------------------------------------------------------------*)
+procedure SIRegister_TIBTABLE(CL: TPSPascalCompiler);
+begin
+ //with RegClassS(CL,'TIBCUSTOMDATASET', 'TIBTABLE') do
+ with CL.AddClassN(CL.FindClass('TIBCUSTOMDATASET'),'TIBTABLE') do
+ begin
+ RegisterMethod('Procedure ADDINDEX( const NAME, FIELDS : STRING; OPTIONS : TINDEXOPTIONS; const DESCFIELDS : STRING)');
+ RegisterMethod('Procedure CREATETABLE');
+ RegisterMethod('Procedure DELETEINDEX( const NAME : STRING)');
+ RegisterMethod('Procedure DELETETABLE');
+ RegisterMethod('Procedure EMPTYTABLE');
+ RegisterMethod('Procedure GETINDEXNAMES( LIST : TSTRINGS)');
+ RegisterMethod('Procedure GOTOCURRENT( TABLE : TIBTABLE)');
+ RegisterProperty('CURRENTDBKEY', 'TIBDBKEY', iptr);
+ RegisterProperty('EXISTS', 'BOOLEAN', iptr);
+ RegisterProperty('INDEXFIELDCOUNT', 'INTEGER', iptr);
+ RegisterProperty('INDEXFIELDS', 'TFIELD INTEGER', iptrw);
+ RegisterProperty('TABLENAMES', 'TSTRINGS', iptr);
+ RegisterProperty('DEFAULTINDEX', 'BOOLEAN', iptrw);
+ RegisterProperty('INDEXDEFS', 'TINDEXDEFS', iptrw);
+ RegisterProperty('INDEXFIELDNAMES', 'STRING', iptrw);
+ RegisterProperty('INDEXNAME', 'STRING', iptrw);
+ RegisterProperty('MASTERFIELDS', 'STRING', iptrw);
+ RegisterProperty('MASTERSOURCE', 'TDATASOURCE', iptrw);
+ RegisterProperty('READONLY', 'BOOLEAN', iptrw);
+ RegisterProperty('STOREDEFS', 'BOOLEAN', iptrw);
+ RegisterProperty('TABLENAME', 'STRING', iptrw);
+ RegisterProperty('TABLETYPES', 'TIBTABLETYPES', iptrw);
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure SIRegister_IBTable(CL: TPSPascalCompiler);
+begin
+ CL.AddTypeS('TIBTABLETYPE', '( TTSYSTEM, TTVIEW )');
+ CL.AddTypeS('TIBTABLETYPES', 'set of TIBTABLETYPE');
+ CL.AddTypeS('TINDEXNAME', 'STRING');
+ CL.AddClassN(CL.FindClass('TOBJECT'),'TIBTABLE');
+ SIRegister_TIBTABLE(CL);
+end;
+
+(* === run-time registration functions === *)
+(*----------------------------------------------------------------------------*)
+procedure TIBTABLETABLETYPES_W(Self: TIBTABLE; const T: TIBTABLETYPES);
+begin Self.TABLETYPES := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBTABLETABLETYPES_R(Self: TIBTABLE; var T: TIBTABLETYPES);
+begin T := Self.TABLETYPES; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBTABLETABLENAME_W(Self: TIBTABLE; const T: STRING);
+begin Self.TABLENAME := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBTABLETABLENAME_R(Self: TIBTABLE; var T: STRING);
+begin T := Self.TABLENAME; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBTABLESTOREDEFS_W(Self: TIBTABLE; const T: BOOLEAN);
+begin Self.STOREDEFS := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBTABLESTOREDEFS_R(Self: TIBTABLE; var T: BOOLEAN);
+begin T := Self.STOREDEFS; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBTABLEREADONLY_W(Self: TIBTABLE; const T: BOOLEAN);
+begin Self.READONLY := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBTABLEREADONLY_R(Self: TIBTABLE; var T: BOOLEAN);
+begin T := Self.READONLY; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBTABLEMASTERSOURCE_W(Self: TIBTABLE; const T: TDATASOURCE);
+begin Self.MASTERSOURCE := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBTABLEMASTERSOURCE_R(Self: TIBTABLE; var T: TDATASOURCE);
+begin T := Self.MASTERSOURCE; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBTABLEMASTERFIELDS_W(Self: TIBTABLE; const T: STRING);
+begin Self.MASTERFIELDS := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBTABLEMASTERFIELDS_R(Self: TIBTABLE; var T: STRING);
+begin T := Self.MASTERFIELDS; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBTABLEINDEXNAME_W(Self: TIBTABLE; const T: STRING);
+begin Self.INDEXNAME := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBTABLEINDEXNAME_R(Self: TIBTABLE; var T: STRING);
+begin T := Self.INDEXNAME; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBTABLEINDEXFIELDNAMES_W(Self: TIBTABLE; const T: STRING);
+begin Self.INDEXFIELDNAMES := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBTABLEINDEXFIELDNAMES_R(Self: TIBTABLE; var T: STRING);
+begin T := Self.INDEXFIELDNAMES; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBTABLEINDEXDEFS_W(Self: TIBTABLE; const T: TINDEXDEFS);
+begin Self.INDEXDEFS := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBTABLEINDEXDEFS_R(Self: TIBTABLE; var T: TINDEXDEFS);
+begin T := Self.INDEXDEFS; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBTABLEDEFAULTINDEX_W(Self: TIBTABLE; const T: BOOLEAN);
+begin Self.DEFAULTINDEX := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBTABLEDEFAULTINDEX_R(Self: TIBTABLE; var T: BOOLEAN);
+begin T := Self.DEFAULTINDEX; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBTABLETABLENAMES_R(Self: TIBTABLE; var T: TSTRINGS);
+begin T := Self.TABLENAMES; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBTABLEINDEXFIELDS_W(Self: TIBTABLE; const T: TFIELD; const t1: INTEGER);
+begin Self.INDEXFIELDS[t1] := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBTABLEINDEXFIELDS_R(Self: TIBTABLE; var T: TFIELD; const t1: INTEGER);
+begin T := Self.INDEXFIELDS[t1]; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBTABLEINDEXFIELDCOUNT_R(Self: TIBTABLE; var T: INTEGER);
+begin T := Self.INDEXFIELDCOUNT; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBTABLEEXISTS_R(Self: TIBTABLE; var T: BOOLEAN);
+begin T := Self.EXISTS; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBTABLECURRENTDBKEY_R(Self: TIBTABLE; var T: TIBDBKEY);
+begin T := Self.CURRENTDBKEY; end;
+
+(*----------------------------------------------------------------------------*)
+procedure RIRegister_TIBTABLE(CL: TPSRuntimeClassImporter);
+begin
+ with CL.Add(TIBTABLE) do
+ begin
+ RegisterMethod(@TIBTABLE.ADDINDEX, 'ADDINDEX');
+ RegisterMethod(@TIBTABLE.CREATETABLE, 'CREATETABLE');
+ RegisterMethod(@TIBTABLE.DELETEINDEX, 'DELETEINDEX');
+ RegisterMethod(@TIBTABLE.DELETETABLE, 'DELETETABLE');
+ RegisterMethod(@TIBTABLE.EMPTYTABLE, 'EMPTYTABLE');
+ RegisterMethod(@TIBTABLE.GETINDEXNAMES, 'GETINDEXNAMES');
+ RegisterMethod(@TIBTABLE.GOTOCURRENT, 'GOTOCURRENT');
+ RegisterPropertyHelper(@TIBTABLECURRENTDBKEY_R,nil,'CURRENTDBKEY');
+ RegisterPropertyHelper(@TIBTABLEEXISTS_R,nil,'EXISTS');
+ RegisterPropertyHelper(@TIBTABLEINDEXFIELDCOUNT_R,nil,'INDEXFIELDCOUNT');
+ RegisterPropertyHelper(@TIBTABLEINDEXFIELDS_R,@TIBTABLEINDEXFIELDS_W,'INDEXFIELDS');
+ RegisterPropertyHelper(@TIBTABLETABLENAMES_R,nil,'TABLENAMES');
+ RegisterPropertyHelper(@TIBTABLEDEFAULTINDEX_R,@TIBTABLEDEFAULTINDEX_W,'DEFAULTINDEX');
+ RegisterPropertyHelper(@TIBTABLEINDEXDEFS_R,@TIBTABLEINDEXDEFS_W,'INDEXDEFS');
+ RegisterPropertyHelper(@TIBTABLEINDEXFIELDNAMES_R,@TIBTABLEINDEXFIELDNAMES_W,'INDEXFIELDNAMES');
+ RegisterPropertyHelper(@TIBTABLEINDEXNAME_R,@TIBTABLEINDEXNAME_W,'INDEXNAME');
+ RegisterPropertyHelper(@TIBTABLEMASTERFIELDS_R,@TIBTABLEMASTERFIELDS_W,'MASTERFIELDS');
+ RegisterPropertyHelper(@TIBTABLEMASTERSOURCE_R,@TIBTABLEMASTERSOURCE_W,'MASTERSOURCE');
+ RegisterPropertyHelper(@TIBTABLEREADONLY_R,@TIBTABLEREADONLY_W,'READONLY');
+ RegisterPropertyHelper(@TIBTABLESTOREDEFS_R,@TIBTABLESTOREDEFS_W,'STOREDEFS');
+ RegisterPropertyHelper(@TIBTABLETABLENAME_R,@TIBTABLETABLENAME_W,'TABLENAME');
+ RegisterPropertyHelper(@TIBTABLETABLETYPES_R,@TIBTABLETABLETYPES_W,'TABLETYPES');
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure RIRegister_IBTable(CL: TPSRuntimeClassImporter);
+begin
+ with CL.Add(TIBTABLE) do
+ RIRegister_TIBTABLE(CL);
+end;
+
+(* === compile-time registration functions === *)
+(*----------------------------------------------------------------------------*)
+procedure SIRegister_TIBSQL(CL: TPSPascalCompiler);
+begin
+ //with RegClassS(CL,'TCOMPONENT', 'TIBSQL') do
+ with CL.AddClassN(CL.FindClass('TCOMPONENT'),'TIBSQL') do
+ begin
+ RegisterMethod('Procedure BATCHINPUT( INPUTOBJECT : TIBBATCHINPUT)');
+ RegisterMethod('Procedure BATCHOUTPUT( OUTPUTOBJECT : TIBBATCHOUTPUT)');
+ RegisterMethod('Function CALL( ERRCODE : ISC_STATUS; RAISEERROR : BOOLEAN) : ISC_STATUS');
+ RegisterMethod('Procedure CHECKCLOSED');
+ RegisterMethod('Procedure CHECKOPEN');
+ RegisterMethod('Procedure CHECKVALIDSTATEMENT');
+ RegisterMethod('Procedure CLOSE');
+ RegisterMethod('Function CURRENT : TIBXSQLDA');
+ RegisterMethod('Procedure EXECQUERY');
+ RegisterMethod('Function FIELDBYNAME( FIELDNAME : STRING) : TIBXSQLVAR');
+ RegisterMethod('Procedure FREEHANDLE');
+ RegisterMethod('Function NEXT : TIBXSQLDA');
+ RegisterMethod('Procedure PREPARE');
+ RegisterMethod('Function GETUNIQUERELATIONNAME : STRING');
+ RegisterMethod('Function PARAMBYNAME( IDX : STRING) : TIBXSQLVAR');
+ RegisterProperty('BOF', 'BOOLEAN', iptr);
+ RegisterProperty('DBHANDLE', 'PISC_DB_HANDLE', iptr);
+ RegisterProperty('EOF', 'BOOLEAN', iptr);
+ RegisterProperty('FIELDS', 'TIBXSQLVAR INTEGER', iptr);
+ RegisterProperty('FIELDINDEX', 'INTEGER STRING', iptr);
+ RegisterProperty('OPEN', 'BOOLEAN', iptr);
+ RegisterProperty('PARAMS', 'TIBXSQLDA', iptr);
+ RegisterProperty('PLAN', 'STRING', iptr);
+ RegisterProperty('PREPARED', 'BOOLEAN', iptr);
+ RegisterProperty('RECORDCOUNT', 'INTEGER', iptr);
+ RegisterProperty('ROWSAFFECTED', 'INTEGER', iptr);
+ RegisterProperty('SQLTYPE', 'TIBSQLTYPES', iptr);
+ RegisterProperty('TRHANDLE', 'PISC_TR_HANDLE', iptr);
+ RegisterProperty('HANDLE', 'TISC_STMT_HANDLE', iptr);
+ RegisterProperty('GENERATEPARAMNAMES', 'BOOLEAN', iptrw);
+ RegisterProperty('UNIQUERELATIONNAME', 'STRING', iptr);
+ RegisterProperty('DATABASE', 'TIBDATABASE', iptrw);
+ RegisterProperty('GOTOFIRSTRECORDONEXECUTE', 'BOOLEAN', iptrw);
+ RegisterProperty('PARAMCHECK', 'BOOLEAN', iptrw);
+ RegisterProperty('SQL', 'TSTRINGS', iptrw);
+ RegisterProperty('TRANSACTION', 'TIBTRANSACTION', iptrw);
+ RegisterProperty('ONSQLCHANGING', 'TNOTIFYEVENT', iptrw);
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure SIRegister_TIBOUTPUTXML(CL: TPSPascalCompiler);
+begin
+ //with RegClassS(CL,'TOBJECT', 'TIBOUTPUTXML') do
+ with CL.AddClassN(CL.FindClass('TOBJECT'),'TIBOUTPUTXML') do
+ begin
+ RegisterMethod('Procedure WRITEXML( SQL : TIBSQL)');
+ RegisterProperty('HEADERTAG', 'STRING', iptrw);
+ RegisterProperty('DATABASETAG', 'STRING', iptrw);
+ RegisterProperty('STREAM', 'TSTREAM', iptrw);
+ RegisterProperty('TABLETAG', 'STRING', iptrw);
+ RegisterProperty('ROWTAG', 'STRING', iptrw);
+ RegisterProperty('FLAGS', 'TIBXMLFLAGS', iptrw);
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure SIRegister_TIBINPUTRAWFILE(CL: TPSPascalCompiler);
+begin
+ //with RegClassS(CL,'TIBBATCHINPUT', 'TIBINPUTRAWFILE') do
+ with CL.AddClassN(CL.FindClass('TIBBATCHINPUT'),'TIBINPUTRAWFILE') do
+ begin
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure SIRegister_TIBOUTPUTRAWFILE(CL: TPSPascalCompiler);
+begin
+ //with RegClassS(CL,'TIBBATCHOUTPUT', 'TIBOUTPUTRAWFILE') do
+ with CL.AddClassN(CL.FindClass('TIBBATCHOUTPUT'),'TIBOUTPUTRAWFILE') do
+ begin
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure SIRegister_TIBINPUTDELIMITEDFILE(CL: TPSPascalCompiler);
+begin
+ //with RegClassS(CL,'TIBBATCHINPUT', 'TIBINPUTDELIMITEDFILE') do
+ with CL.AddClassN(CL.FindClass('TIBBATCHINPUT'),'TIBINPUTDELIMITEDFILE') do
+ begin
+ RegisterMethod('Function GETCOLUMN( var COL : STRING) : INTEGER');
+ RegisterProperty('COLDELIMITER', 'STRING', iptrw);
+ RegisterProperty('READBLANKSASNULL', 'BOOLEAN', iptrw);
+ RegisterProperty('ROWDELIMITER', 'STRING', iptrw);
+ RegisterProperty('SKIPTITLES', 'BOOLEAN', iptrw);
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure SIRegister_TIBOUTPUTDELIMITEDFILE(CL: TPSPascalCompiler);
+begin
+ //with RegClassS(CL,'TIBBATCHOUTPUT', 'TIBOUTPUTDELIMITEDFILE') do
+ with CL.AddClassN(CL.FindClass('TIBBATCHOUTPUT'),'TIBOUTPUTDELIMITEDFILE') do
+ begin
+ RegisterProperty('COLDELIMITER', 'STRING', iptrw);
+ RegisterProperty('OUTPUTTITLES', 'BOOLEAN', iptrw);
+ RegisterProperty('ROWDELIMITER', 'STRING', iptrw);
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure SIRegister_TIBBATCHOUTPUT(CL: TPSPascalCompiler);
+begin
+ //with RegClassS(CL,'TIBBATCH', 'TIBBATCHOUTPUT') do
+ with CL.AddClassN(CL.FindClass('TIBBATCH'),'TIBBATCHOUTPUT') do
+ begin
+ RegisterMethod('Function WRITECOLUMNS : BOOLEAN');
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure SIRegister_TIBBATCHINPUT(CL: TPSPascalCompiler);
+begin
+ //with RegClassS(CL,'TIBBATCH', 'TIBBATCHINPUT') do
+ with CL.AddClassN(CL.FindClass('TIBBATCH'),'TIBBATCHINPUT') do
+ begin
+ RegisterMethod('Function READPARAMETERS : BOOLEAN');
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure SIRegister_TIBBATCH(CL: TPSPascalCompiler);
+begin
+ //with RegClassS(CL,'TOBJECT', 'TIBBATCH') do
+ with CL.AddClassN(CL.FindClass('TOBJECT'),'TIBBATCH') do
+ begin
+ RegisterMethod('Procedure READYFILE');
+ RegisterProperty('COLUMNS', 'TIBXSQLDA', iptrw);
+ RegisterProperty('FILENAME', 'STRING', iptrw);
+ RegisterProperty('PARAMS', 'TIBXSQLDA', iptrw);
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure SIRegister_TIBXSQLDA(CL: TPSPascalCompiler);
+begin
+ //with RegClassS(CL,'TOBJECT', 'TIBXSQLDA') do
+ with CL.AddClassN(CL.FindClass('TOBJECT'),'TIBXSQLDA') do
+ begin
+ RegisterMethod('Constructor CREATE( QUERY : TIBSQL)');
+ RegisterMethod('Procedure ADDNAME( FIELDNAME : STRING; IDX : INTEGER)');
+ RegisterMethod('Function BYNAME( IDX : STRING) : TIBXSQLVAR');
+ RegisterProperty('ASXSQLDA', 'PXSQLDA', iptr);
+ RegisterProperty('COUNT', 'INTEGER', iptrw);
+ RegisterProperty('MODIFIED', 'BOOLEAN', iptr);
+ RegisterProperty('NAMES', 'STRING', iptr);
+ RegisterProperty('RECORDSIZE', 'INTEGER', iptr);
+ RegisterProperty('VARS', 'TIBXSQLVAR INTEGER', iptr);
+ SetDefaultPropery('VARS');
+ RegisterProperty('UNIQUERELATIONNAME', 'STRING', iptr);
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure SIRegister_TIBXSQLVAR(CL: TPSPascalCompiler);
+begin
+ //with RegClassS(CL,'TOBJECT', 'TIBXSQLVAR') do
+ with CL.AddClassN(CL.FindClass('TOBJECT'),'TIBXSQLVAR') do
+ begin
+ RegisterMethod('Constructor CREATE( PARENT : TIBXSQLDA; QUERY : TIBSQL)');
+ RegisterMethod('Procedure ASSIGN( SOURCE : TIBXSQLVAR)');
+ RegisterMethod('Procedure LOADFROMFILE( const FILENAME : STRING)');
+ RegisterMethod('Procedure LOADFROMSTREAM( STREAM : TSTREAM)');
+ RegisterMethod('Procedure SAVETOFILE( const FILENAME : STRING)');
+ RegisterMethod('Procedure SAVETOSTREAM( STREAM : TSTREAM)');
+ RegisterMethod('Procedure CLEAR');
+ RegisterProperty('ASDATE', 'TDATETIME', iptrw);
+ RegisterProperty('ASTIME', 'TDATETIME', iptrw);
+ RegisterProperty('ASDATETIME', 'TDATETIME', iptrw);
+ RegisterProperty('ASDOUBLE', 'DOUBLE', iptrw);
+ RegisterProperty('ASFLOAT', 'FLOAT', iptrw);
+ RegisterProperty('ASCURRENCY', 'CURRENCY', iptrw);
+ RegisterProperty('ASINT64', 'INT64', iptrw);
+ RegisterProperty('ASINTEGER', 'INTEGER', iptrw);
+ RegisterProperty('ASLONG', 'LONG', iptrw);
+ RegisterProperty('ASPOINTER', 'POINTER', iptrw);
+ RegisterProperty('ASQUAD', 'TISC_QUAD', iptrw);
+ RegisterProperty('ASSHORT', 'SHORT', iptrw);
+ RegisterProperty('ASSTRING', 'STRING', iptrw);
+ RegisterProperty('ASTRIMSTRING', 'STRING', iptrw);
+ RegisterProperty('ASVARIANT', 'VARIANT', iptrw);
+ RegisterProperty('ASXSQLVAR', 'PXSQLVAR', iptrw);
+ RegisterProperty('DATA', 'PXSQLVAR', iptrw);
+ RegisterProperty('ISNULL', 'BOOLEAN', iptrw);
+ RegisterProperty('ISNULLABLE', 'BOOLEAN', iptrw);
+ RegisterProperty('INDEX', 'INTEGER', iptr);
+ RegisterProperty('MODIFIED', 'BOOLEAN', iptrw);
+ RegisterProperty('NAME', 'STRING', iptr);
+ RegisterProperty('SIZE', 'INTEGER', iptr);
+ RegisterProperty('SQLTYPE', 'INTEGER', iptr);
+ RegisterProperty('VALUE', 'VARIANT', iptrw);
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure SIRegister_IBSQL(CL: TPSPascalCompiler);
+begin
+ CL.AddClassN(CL.FindClass('TOBJECT'),'TIBSQL');
+ CL.AddClassN(CL.FindClass('TOBJECT'),'TIBXSQLDA');
+ SIRegister_TIBXSQLVAR(CL);
+ CL.AddTypeS('TIBXSQLVARARRAY', 'array of TIBXSQLVAR');
+ SIRegister_TIBXSQLDA(CL);
+ SIRegister_TIBBATCH(CL);
+ SIRegister_TIBBATCHINPUT(CL);
+ SIRegister_TIBBATCHOUTPUT(CL);
+ SIRegister_TIBOUTPUTDELIMITEDFILE(CL);
+ SIRegister_TIBINPUTDELIMITEDFILE(CL);
+ SIRegister_TIBOUTPUTRAWFILE(CL);
+ SIRegister_TIBINPUTRAWFILE(CL);
+ CL.AddTypeS('TIBXMLFLAG', '( XMLATTRIBUTE, XMLDISPLAYNULL, XMLNOHEADER )');
+ CL.AddTypeS('TIBXMLFLAGS', 'set of TIBXMLFLAG');
+ SIRegister_TIBOUTPUTXML(CL);
+ CL.AddTypeS('TIBSQLTYPES', '( SQLUNKNOWN, SQLSELECT, SQLINSERT, SQLUPDATE, SQ'
+ +'LDELETE, SQLDDL, SQLGETSEGMENT, SQLPUTSEGMENT, SQLEXECPROCEDURE, SQLSTARTT'
+ +'RANSACTION, SQLCOMMIT, SQLROLLBACK, SQLSELECTFORUPDATE, SQLSETGENERATOR )');
+ SIRegister_TIBSQL(CL);
+ CL.AddDelphiFunction('Procedure OUTPUTXML( SQLOBJECT : TIBSQL; OUTPUTOBJECT : TIBOUTPUTXML)');
+end;
+
+(* === run-time registration functions === *)
+(*----------------------------------------------------------------------------*)
+procedure TIBSQLONSQLCHANGING_W(Self: TIBSQL; const T: TNOTIFYEVENT);
+begin Self.ONSQLCHANGING := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBSQLONSQLCHANGING_R(Self: TIBSQL; var T: TNOTIFYEVENT);
+begin T := Self.ONSQLCHANGING; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBSQLTRANSACTION_W(Self: TIBSQL; const T: TIBTRANSACTION);
+begin Self.TRANSACTION := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBSQLTRANSACTION_R(Self: TIBSQL; var T: TIBTRANSACTION);
+begin T := Self.TRANSACTION; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBSQLSQL_W(Self: TIBSQL; const T: TSTRINGS);
+begin Self.SQL := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBSQLSQL_R(Self: TIBSQL; var T: TSTRINGS);
+begin T := Self.SQL; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBSQLPARAMCHECK_W(Self: TIBSQL; const T: BOOLEAN);
+begin Self.PARAMCHECK := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBSQLPARAMCHECK_R(Self: TIBSQL; var T: BOOLEAN);
+begin T := Self.PARAMCHECK; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBSQLGOTOFIRSTRECORDONEXECUTE_W(Self: TIBSQL; const T: BOOLEAN);
+begin Self.GOTOFIRSTRECORDONEXECUTE := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBSQLGOTOFIRSTRECORDONEXECUTE_R(Self: TIBSQL; var T: BOOLEAN);
+begin T := Self.GOTOFIRSTRECORDONEXECUTE; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBSQLDATABASE_W(Self: TIBSQL; const T: TIBDATABASE);
+begin Self.DATABASE := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBSQLDATABASE_R(Self: TIBSQL; var T: TIBDATABASE);
+begin T := Self.DATABASE; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBSQLUNIQUERELATIONNAME_R(Self: TIBSQL; var T: STRING);
+begin T := Self.UNIQUERELATIONNAME; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBSQLGENERATEPARAMNAMES_W(Self: TIBSQL; const T: BOOLEAN);
+begin Self.GENERATEPARAMNAMES := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBSQLGENERATEPARAMNAMES_R(Self: TIBSQL; var T: BOOLEAN);
+begin T := Self.GENERATEPARAMNAMES; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBSQLHANDLE_R(Self: TIBSQL; var T: TISC_STMT_HANDLE);
+begin T := Self.HANDLE; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBSQLTRHANDLE_R(Self: TIBSQL; var T: PISC_TR_HANDLE);
+begin T := Self.TRHANDLE; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBSQLSQLTYPE_R(Self: TIBSQL; var T: TIBSQLTYPES);
+begin T := Self.SQLTYPE; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBSQLROWSAFFECTED_R(Self: TIBSQL; var T: INTEGER);
+begin T := Self.ROWSAFFECTED; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBSQLRECORDCOUNT_R(Self: TIBSQL; var T: INTEGER);
+begin T := Self.RECORDCOUNT; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBSQLPREPARED_R(Self: TIBSQL; var T: BOOLEAN);
+begin T := Self.PREPARED; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBSQLPLAN_R(Self: TIBSQL; var T: STRING);
+begin T := Self.PLAN; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBSQLPARAMS_R(Self: TIBSQL; var T: TIBXSQLDA);
+begin T := Self.PARAMS; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBSQLOPEN_R(Self: TIBSQL; var T: BOOLEAN);
+begin T := Self.OPEN; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBSQLFIELDINDEX_R(Self: TIBSQL; var T: INTEGER; const t1: STRING);
+begin T := Self.FIELDINDEX[t1]; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBSQLFIELDS_R(Self: TIBSQL; var T: TIBXSQLVAR; const t1: INTEGER);
+begin T := Self.FIELDS[t1]; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBSQLEOF_R(Self: TIBSQL; var T: BOOLEAN);
+begin T := Self.EOF; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBSQLDBHANDLE_R(Self: TIBSQL; var T: PISC_DB_HANDLE);
+begin T := Self.DBHANDLE; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBSQLBOF_R(Self: TIBSQL; var T: BOOLEAN);
+begin T := Self.BOF; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBOUTPUTXMLFLAGS_W(Self: TIBOUTPUTXML; const T: TIBXMLFLAGS);
+begin Self.FLAGS := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBOUTPUTXMLFLAGS_R(Self: TIBOUTPUTXML; var T: TIBXMLFLAGS);
+begin T := Self.FLAGS; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBOUTPUTXMLROWTAG_W(Self: TIBOUTPUTXML; const T: STRING);
+begin Self.ROWTAG := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBOUTPUTXMLROWTAG_R(Self: TIBOUTPUTXML; var T: STRING);
+begin T := Self.ROWTAG; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBOUTPUTXMLTABLETAG_W(Self: TIBOUTPUTXML; const T: STRING);
+begin Self.TABLETAG := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBOUTPUTXMLTABLETAG_R(Self: TIBOUTPUTXML; var T: STRING);
+begin T := Self.TABLETAG; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBOUTPUTXMLSTREAM_W(Self: TIBOUTPUTXML; const T: TSTREAM);
+begin Self.STREAM := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBOUTPUTXMLSTREAM_R(Self: TIBOUTPUTXML; var T: TSTREAM);
+begin T := Self.STREAM; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBOUTPUTXMLDATABASETAG_W(Self: TIBOUTPUTXML; const T: STRING);
+begin Self.DATABASETAG := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBOUTPUTXMLDATABASETAG_R(Self: TIBOUTPUTXML; var T: STRING);
+begin T := Self.DATABASETAG; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBOUTPUTXMLHEADERTAG_W(Self: TIBOUTPUTXML; const T: STRING);
+begin Self.HEADERTAG := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBOUTPUTXMLHEADERTAG_R(Self: TIBOUTPUTXML; var T: STRING);
+begin T := Self.HEADERTAG; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBINPUTDELIMITEDFILESKIPTITLES_W(Self: TIBINPUTDELIMITEDFILE; const T: BOOLEAN);
+begin Self.SKIPTITLES := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBINPUTDELIMITEDFILESKIPTITLES_R(Self: TIBINPUTDELIMITEDFILE; var T: BOOLEAN);
+begin T := Self.SKIPTITLES; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBINPUTDELIMITEDFILEROWDELIMITER_W(Self: TIBINPUTDELIMITEDFILE; const T: STRING);
+begin Self.ROWDELIMITER := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBINPUTDELIMITEDFILEROWDELIMITER_R(Self: TIBINPUTDELIMITEDFILE; var T: STRING);
+begin T := Self.ROWDELIMITER; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBINPUTDELIMITEDFILEREADBLANKSASNULL_W(Self: TIBINPUTDELIMITEDFILE; const T: BOOLEAN);
+begin Self.READBLANKSASNULL := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBINPUTDELIMITEDFILEREADBLANKSASNULL_R(Self: TIBINPUTDELIMITEDFILE; var T: BOOLEAN);
+begin T := Self.READBLANKSASNULL; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBINPUTDELIMITEDFILECOLDELIMITER_W(Self: TIBINPUTDELIMITEDFILE; const T: STRING);
+begin Self.COLDELIMITER := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBINPUTDELIMITEDFILECOLDELIMITER_R(Self: TIBINPUTDELIMITEDFILE; var T: STRING);
+begin T := Self.COLDELIMITER; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBOUTPUTDELIMITEDFILEROWDELIMITER_W(Self: TIBOUTPUTDELIMITEDFILE; const T: STRING);
+begin Self.ROWDELIMITER := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBOUTPUTDELIMITEDFILEROWDELIMITER_R(Self: TIBOUTPUTDELIMITEDFILE; var T: STRING);
+begin T := Self.ROWDELIMITER; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBOUTPUTDELIMITEDFILEOUTPUTTITLES_W(Self: TIBOUTPUTDELIMITEDFILE; const T: BOOLEAN);
+begin Self.OUTPUTTITLES := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBOUTPUTDELIMITEDFILEOUTPUTTITLES_R(Self: TIBOUTPUTDELIMITEDFILE; var T: BOOLEAN);
+begin T := Self.OUTPUTTITLES; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBOUTPUTDELIMITEDFILECOLDELIMITER_W(Self: TIBOUTPUTDELIMITEDFILE; const T: STRING);
+begin Self.COLDELIMITER := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBOUTPUTDELIMITEDFILECOLDELIMITER_R(Self: TIBOUTPUTDELIMITEDFILE; var T: STRING);
+begin T := Self.COLDELIMITER; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBXSQLDAUNIQUERELATIONNAME_R(Self: TIBXSQLDA; var T: STRING);
+begin T := Self.UNIQUERELATIONNAME; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBXSQLDAVARS_R(Self: TIBXSQLDA; var T: TIBXSQLVAR; const t1: INTEGER);
+begin T := Self.VARS[t1]; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBXSQLDARECORDSIZE_R(Self: TIBXSQLDA; var T: INTEGER);
+begin T := Self.RECORDSIZE; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBXSQLDANAMES_R(Self: TIBXSQLDA; var T: STRING);
+begin T := Self.NAMES; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBXSQLDAMODIFIED_R(Self: TIBXSQLDA; var T: BOOLEAN);
+begin T := Self.MODIFIED; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBXSQLDACOUNT_W(Self: TIBXSQLDA; const T: INTEGER);
+begin Self.COUNT := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBXSQLDACOUNT_R(Self: TIBXSQLDA; var T: INTEGER);
+begin T := Self.COUNT; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBXSQLDAASXSQLDA_R(Self: TIBXSQLDA; var T: PXSQLDA);
+begin T := Self.ASXSQLDA; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBXSQLVARVALUE_W(Self: TIBXSQLVAR; const T: VARIANT);
+begin Self.VALUE := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBXSQLVARVALUE_R(Self: TIBXSQLVAR; var T: VARIANT);
+begin T := Self.VALUE; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBXSQLVARSQLTYPE_R(Self: TIBXSQLVAR; var T: INTEGER);
+begin T := Self.SQLTYPE; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBXSQLVARSIZE_R(Self: TIBXSQLVAR; var T: INTEGER);
+begin T := Self.SIZE; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBXSQLVARNAME_R(Self: TIBXSQLVAR; var T: STRING);
+begin T := Self.NAME; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBXSQLVARMODIFIED_W(Self: TIBXSQLVAR; const T: BOOLEAN);
+begin Self.MODIFIED := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBXSQLVARMODIFIED_R(Self: TIBXSQLVAR; var T: BOOLEAN);
+begin T := Self.MODIFIED; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBXSQLVARINDEX_R(Self: TIBXSQLVAR; var T: INTEGER);
+begin T := Self.INDEX; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBXSQLVARISNULLABLE_W(Self: TIBXSQLVAR; const T: BOOLEAN);
+begin Self.ISNULLABLE := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBXSQLVARISNULLABLE_R(Self: TIBXSQLVAR; var T: BOOLEAN);
+begin T := Self.ISNULLABLE; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBXSQLVARISNULL_W(Self: TIBXSQLVAR; const T: BOOLEAN);
+begin Self.ISNULL := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBXSQLVARISNULL_R(Self: TIBXSQLVAR; var T: BOOLEAN);
+begin T := Self.ISNULL; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBXSQLVARDATA_W(Self: TIBXSQLVAR; const T: PXSQLVAR);
+begin Self.DATA := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBXSQLVARDATA_R(Self: TIBXSQLVAR; var T: PXSQLVAR);
+begin T := Self.DATA; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBXSQLVARASXSQLVAR_W(Self: TIBXSQLVAR; const T: PXSQLVAR);
+begin Self.ASXSQLVAR := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBXSQLVARASXSQLVAR_R(Self: TIBXSQLVAR; var T: PXSQLVAR);
+begin T := Self.ASXSQLVAR; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBXSQLVARASVARIANT_W(Self: TIBXSQLVAR; const T: VARIANT);
+begin Self.ASVARIANT := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBXSQLVARASVARIANT_R(Self: TIBXSQLVAR; var T: VARIANT);
+begin T := Self.ASVARIANT; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBXSQLVARASTRIMSTRING_W(Self: TIBXSQLVAR; const T: STRING);
+begin Self.ASTRIMSTRING := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBXSQLVARASTRIMSTRING_R(Self: TIBXSQLVAR; var T: STRING);
+begin T := Self.ASTRIMSTRING; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBXSQLVARASSTRING_W(Self: TIBXSQLVAR; const T: STRING);
+begin Self.ASSTRING := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBXSQLVARASSTRING_R(Self: TIBXSQLVAR; var T: STRING);
+begin T := Self.ASSTRING; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBXSQLVARASSHORT_W(Self: TIBXSQLVAR; const T: SHORT);
+begin Self.ASSHORT := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBXSQLVARASSHORT_R(Self: TIBXSQLVAR; var T: SHORT);
+begin T := Self.ASSHORT; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBXSQLVARASQUAD_W(Self: TIBXSQLVAR; const T: TISC_QUAD);
+begin Self.ASQUAD := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBXSQLVARASQUAD_R(Self: TIBXSQLVAR; var T: TISC_QUAD);
+begin T := Self.ASQUAD; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBXSQLVARASPOINTER_W(Self: TIBXSQLVAR; const T: POINTER);
+begin Self.ASPOINTER := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBXSQLVARASPOINTER_R(Self: TIBXSQLVAR; var T: POINTER);
+begin T := Self.ASPOINTER; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBXSQLVARASLONG_W(Self: TIBXSQLVAR; const T: LONG);
+begin Self.ASLONG := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBXSQLVARASLONG_R(Self: TIBXSQLVAR; var T: LONG);
+begin T := Self.ASLONG; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBXSQLVARASINTEGER_W(Self: TIBXSQLVAR; const T: INTEGER);
+begin Self.ASINTEGER := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBXSQLVARASINTEGER_R(Self: TIBXSQLVAR; var T: INTEGER);
+begin T := Self.ASINTEGER; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBXSQLVARASINT64_W(Self: TIBXSQLVAR; const T: INT64);
+begin Self.ASINT64 := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBXSQLVARASINT64_R(Self: TIBXSQLVAR; var T: INT64);
+begin T := Self.ASINT64; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBXSQLVARASCURRENCY_W(Self: TIBXSQLVAR; const T: CURRENCY);
+begin Self.ASCURRENCY := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBXSQLVARASCURRENCY_R(Self: TIBXSQLVAR; var T: CURRENCY);
+begin T := Self.ASCURRENCY; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBXSQLVARASFLOAT_W(Self: TIBXSQLVAR; const T: FLOAT);
+begin Self.ASFLOAT := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBXSQLVARASFLOAT_R(Self: TIBXSQLVAR; var T: FLOAT);
+begin T := Self.ASFLOAT; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBXSQLVARASDOUBLE_W(Self: TIBXSQLVAR; const T: DOUBLE);
+begin Self.ASDOUBLE := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBXSQLVARASDOUBLE_R(Self: TIBXSQLVAR; var T: DOUBLE);
+begin T := Self.ASDOUBLE; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBXSQLVARASDATETIME_W(Self: TIBXSQLVAR; const T: TDATETIME);
+begin Self.ASDATETIME := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBXSQLVARASDATETIME_R(Self: TIBXSQLVAR; var T: TDATETIME);
+begin T := Self.ASDATETIME; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBXSQLVARASTIME_W(Self: TIBXSQLVAR; const T: TDATETIME);
+begin Self.ASTIME := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBXSQLVARASTIME_R(Self: TIBXSQLVAR; var T: TDATETIME);
+begin T := Self.ASTIME; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBXSQLVARASDATE_W(Self: TIBXSQLVAR; const T: TDATETIME);
+begin Self.ASDATE := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBXSQLVARASDATE_R(Self: TIBXSQLVAR; var T: TDATETIME);
+begin T := Self.ASDATE; end;
+
+(*----------------------------------------------------------------------------*)
+procedure RIRegister_IBSQL_Routines(S: TIFPSExec);
+begin
+ S.RegisterDelphiFunction(@OUTPUTXML, 'OUTPUTXML', cdRegister);
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure RIRegister_TIBSQL(CL: TPSRuntimeClassImporter);
+begin
+ with CL.Add(TIBSQL) do
+ begin
+ RegisterMethod(@TIBSQL.BATCHINPUT, 'BATCHINPUT');
+ RegisterMethod(@TIBSQL.BATCHOUTPUT, 'BATCHOUTPUT');
+ RegisterMethod(@TIBSQL.CALL, 'CALL');
+ RegisterMethod(@TIBSQL.CHECKCLOSED, 'CHECKCLOSED');
+ RegisterMethod(@TIBSQL.CHECKOPEN, 'CHECKOPEN');
+ RegisterMethod(@TIBSQL.CHECKVALIDSTATEMENT, 'CHECKVALIDSTATEMENT');
+ RegisterMethod(@TIBSQL.CLOSE, 'CLOSE');
+ RegisterMethod(@TIBSQL.CURRENT, 'CURRENT');
+ RegisterMethod(@TIBSQL.EXECQUERY, 'EXECQUERY');
+ RegisterMethod(@TIBSQL.FIELDBYNAME, 'FIELDBYNAME');
+ RegisterMethod(@TIBSQL.FREEHANDLE, 'FREEHANDLE');
+ RegisterMethod(@TIBSQL.NEXT, 'NEXT');
+ RegisterMethod(@TIBSQL.PREPARE, 'PREPARE');
+ RegisterMethod(@TIBSQL.GETUNIQUERELATIONNAME, 'GETUNIQUERELATIONNAME');
+ RegisterMethod(@TIBSQL.PARAMBYNAME, 'PARAMBYNAME');
+ RegisterPropertyHelper(@TIBSQLBOF_R,nil,'BOF');
+ RegisterPropertyHelper(@TIBSQLDBHANDLE_R,nil,'DBHANDLE');
+ RegisterPropertyHelper(@TIBSQLEOF_R,nil,'EOF');
+ RegisterPropertyHelper(@TIBSQLFIELDS_R,nil,'FIELDS');
+ RegisterPropertyHelper(@TIBSQLFIELDINDEX_R,nil,'FIELDINDEX');
+ RegisterPropertyHelper(@TIBSQLOPEN_R,nil,'OPEN');
+ RegisterPropertyHelper(@TIBSQLPARAMS_R,nil,'PARAMS');
+ RegisterPropertyHelper(@TIBSQLPLAN_R,nil,'PLAN');
+ RegisterPropertyHelper(@TIBSQLPREPARED_R,nil,'PREPARED');
+ RegisterPropertyHelper(@TIBSQLRECORDCOUNT_R,nil,'RECORDCOUNT');
+ RegisterPropertyHelper(@TIBSQLROWSAFFECTED_R,nil,'ROWSAFFECTED');
+ RegisterPropertyHelper(@TIBSQLSQLTYPE_R,nil,'SQLTYPE');
+ RegisterPropertyHelper(@TIBSQLTRHANDLE_R,nil,'TRHANDLE');
+ RegisterPropertyHelper(@TIBSQLHANDLE_R,nil,'HANDLE');
+ RegisterPropertyHelper(@TIBSQLGENERATEPARAMNAMES_R,@TIBSQLGENERATEPARAMNAMES_W,'GENERATEPARAMNAMES');
+ RegisterPropertyHelper(@TIBSQLUNIQUERELATIONNAME_R,nil,'UNIQUERELATIONNAME');
+ RegisterPropertyHelper(@TIBSQLDATABASE_R,@TIBSQLDATABASE_W,'DATABASE');
+ RegisterPropertyHelper(@TIBSQLGOTOFIRSTRECORDONEXECUTE_R,@TIBSQLGOTOFIRSTRECORDONEXECUTE_W,'GOTOFIRSTRECORDONEXECUTE');
+ RegisterPropertyHelper(@TIBSQLPARAMCHECK_R,@TIBSQLPARAMCHECK_W,'PARAMCHECK');
+ RegisterPropertyHelper(@TIBSQLSQL_R,@TIBSQLSQL_W,'SQL');
+ RegisterPropertyHelper(@TIBSQLTRANSACTION_R,@TIBSQLTRANSACTION_W,'TRANSACTION');
+ RegisterEventPropertyHelper(@TIBSQLONSQLCHANGING_R,@TIBSQLONSQLCHANGING_W,'ONSQLCHANGING');
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure RIRegister_TIBOUTPUTXML(CL: TPSRuntimeClassImporter);
+begin
+ with CL.Add(TIBOUTPUTXML) do
+ begin
+ RegisterMethod(@TIBOUTPUTXML.WRITEXML, 'WRITEXML');
+ RegisterPropertyHelper(@TIBOUTPUTXMLHEADERTAG_R,@TIBOUTPUTXMLHEADERTAG_W,'HEADERTAG');
+ RegisterPropertyHelper(@TIBOUTPUTXMLDATABASETAG_R,@TIBOUTPUTXMLDATABASETAG_W,'DATABASETAG');
+ RegisterPropertyHelper(@TIBOUTPUTXMLSTREAM_R,@TIBOUTPUTXMLSTREAM_W,'STREAM');
+ RegisterPropertyHelper(@TIBOUTPUTXMLTABLETAG_R,@TIBOUTPUTXMLTABLETAG_W,'TABLETAG');
+ RegisterPropertyHelper(@TIBOUTPUTXMLROWTAG_R,@TIBOUTPUTXMLROWTAG_W,'ROWTAG');
+ RegisterPropertyHelper(@TIBOUTPUTXMLFLAGS_R,@TIBOUTPUTXMLFLAGS_W,'FLAGS');
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure RIRegister_TIBINPUTRAWFILE(CL: TPSRuntimeClassImporter);
+begin
+ with CL.Add(TIBINPUTRAWFILE) do
+ begin
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure RIRegister_TIBOUTPUTRAWFILE(CL: TPSRuntimeClassImporter);
+begin
+ with CL.Add(TIBOUTPUTRAWFILE) do
+ begin
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure RIRegister_TIBINPUTDELIMITEDFILE(CL: TPSRuntimeClassImporter);
+begin
+ with CL.Add(TIBINPUTDELIMITEDFILE) do
+ begin
+ RegisterMethod(@TIBINPUTDELIMITEDFILE.GETCOLUMN, 'GETCOLUMN');
+ RegisterPropertyHelper(@TIBINPUTDELIMITEDFILECOLDELIMITER_R,@TIBINPUTDELIMITEDFILECOLDELIMITER_W,'COLDELIMITER');
+ RegisterPropertyHelper(@TIBINPUTDELIMITEDFILEREADBLANKSASNULL_R,@TIBINPUTDELIMITEDFILEREADBLANKSASNULL_W,'READBLANKSASNULL');
+ RegisterPropertyHelper(@TIBINPUTDELIMITEDFILEROWDELIMITER_R,@TIBINPUTDELIMITEDFILEROWDELIMITER_W,'ROWDELIMITER');
+ RegisterPropertyHelper(@TIBINPUTDELIMITEDFILESKIPTITLES_R,@TIBINPUTDELIMITEDFILESKIPTITLES_W,'SKIPTITLES');
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure RIRegister_TIBOUTPUTDELIMITEDFILE(CL: TPSRuntimeClassImporter);
+begin
+ with CL.Add(TIBOUTPUTDELIMITEDFILE) do
+ begin
+ RegisterPropertyHelper(@TIBOUTPUTDELIMITEDFILECOLDELIMITER_R,@TIBOUTPUTDELIMITEDFILECOLDELIMITER_W,'COLDELIMITER');
+ RegisterPropertyHelper(@TIBOUTPUTDELIMITEDFILEOUTPUTTITLES_R,@TIBOUTPUTDELIMITEDFILEOUTPUTTITLES_W,'OUTPUTTITLES');
+ RegisterPropertyHelper(@TIBOUTPUTDELIMITEDFILEROWDELIMITER_R,@TIBOUTPUTDELIMITEDFILEROWDELIMITER_W,'ROWDELIMITER');
+ end;
+end;
+
+
+(*----------------------------------------------------------------------------*)
+procedure RIRegister_TIBXSQLDA(CL: TPSRuntimeClassImporter);
+begin
+ with CL.Add(TIBXSQLDA) do
+ begin
+ RegisterConstructor(@TIBXSQLDA.CREATE, 'CREATE');
+ RegisterMethod(@TIBXSQLDA.ADDNAME, 'ADDNAME');
+ RegisterMethod(@TIBXSQLDA.BYNAME, 'BYNAME');
+ RegisterPropertyHelper(@TIBXSQLDAASXSQLDA_R,nil,'ASXSQLDA');
+ RegisterPropertyHelper(@TIBXSQLDACOUNT_R,@TIBXSQLDACOUNT_W,'COUNT');
+ RegisterPropertyHelper(@TIBXSQLDAMODIFIED_R,nil,'MODIFIED');
+ RegisterPropertyHelper(@TIBXSQLDANAMES_R,nil,'NAMES');
+ RegisterPropertyHelper(@TIBXSQLDARECORDSIZE_R,nil,'RECORDSIZE');
+ RegisterPropertyHelper(@TIBXSQLDAVARS_R,nil,'VARS');
+ RegisterPropertyHelper(@TIBXSQLDAUNIQUERELATIONNAME_R,nil,'UNIQUERELATIONNAME');
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure RIRegister_TIBXSQLVAR(CL: TPSRuntimeClassImporter);
+begin
+ with CL.Add(TIBXSQLVAR) do
+ begin
+ RegisterConstructor(@TIBXSQLVAR.CREATE, 'CREATE');
+ RegisterMethod(@TIBXSQLVAR.ASSIGN, 'ASSIGN');
+ RegisterMethod(@TIBXSQLVAR.LOADFROMFILE, 'LOADFROMFILE');
+ RegisterMethod(@TIBXSQLVAR.LOADFROMSTREAM, 'LOADFROMSTREAM');
+ RegisterMethod(@TIBXSQLVAR.SAVETOFILE, 'SAVETOFILE');
+ RegisterMethod(@TIBXSQLVAR.SAVETOSTREAM, 'SAVETOSTREAM');
+ RegisterMethod(@TIBXSQLVAR.CLEAR, 'CLEAR');
+ RegisterPropertyHelper(@TIBXSQLVARASDATE_R,@TIBXSQLVARASDATE_W,'ASDATE');
+ RegisterPropertyHelper(@TIBXSQLVARASTIME_R,@TIBXSQLVARASTIME_W,'ASTIME');
+ RegisterPropertyHelper(@TIBXSQLVARASDATETIME_R,@TIBXSQLVARASDATETIME_W,'ASDATETIME');
+ RegisterPropertyHelper(@TIBXSQLVARASDOUBLE_R,@TIBXSQLVARASDOUBLE_W,'ASDOUBLE');
+ RegisterPropertyHelper(@TIBXSQLVARASFLOAT_R,@TIBXSQLVARASFLOAT_W,'ASFLOAT');
+ RegisterPropertyHelper(@TIBXSQLVARASCURRENCY_R,@TIBXSQLVARASCURRENCY_W,'ASCURRENCY');
+ RegisterPropertyHelper(@TIBXSQLVARASINT64_R,@TIBXSQLVARASINT64_W,'ASINT64');
+ RegisterPropertyHelper(@TIBXSQLVARASINTEGER_R,@TIBXSQLVARASINTEGER_W,'ASINTEGER');
+ RegisterPropertyHelper(@TIBXSQLVARASLONG_R,@TIBXSQLVARASLONG_W,'ASLONG');
+ RegisterPropertyHelper(@TIBXSQLVARASPOINTER_R,@TIBXSQLVARASPOINTER_W,'ASPOINTER');
+ RegisterPropertyHelper(@TIBXSQLVARASQUAD_R,@TIBXSQLVARASQUAD_W,'ASQUAD');
+ RegisterPropertyHelper(@TIBXSQLVARASSHORT_R,@TIBXSQLVARASSHORT_W,'ASSHORT');
+ RegisterPropertyHelper(@TIBXSQLVARASSTRING_R,@TIBXSQLVARASSTRING_W,'ASSTRING');
+ RegisterPropertyHelper(@TIBXSQLVARASTRIMSTRING_R,@TIBXSQLVARASTRIMSTRING_W,'ASTRIMSTRING');
+ RegisterPropertyHelper(@TIBXSQLVARASVARIANT_R,@TIBXSQLVARASVARIANT_W,'ASVARIANT');
+ RegisterPropertyHelper(@TIBXSQLVARASXSQLVAR_R,@TIBXSQLVARASXSQLVAR_W,'ASXSQLVAR');
+ RegisterPropertyHelper(@TIBXSQLVARDATA_R,@TIBXSQLVARDATA_W,'DATA');
+ RegisterPropertyHelper(@TIBXSQLVARISNULL_R,@TIBXSQLVARISNULL_W,'ISNULL');
+ RegisterPropertyHelper(@TIBXSQLVARISNULLABLE_R,@TIBXSQLVARISNULLABLE_W,'ISNULLABLE');
+ RegisterPropertyHelper(@TIBXSQLVARINDEX_R,nil,'INDEX');
+ RegisterPropertyHelper(@TIBXSQLVARMODIFIED_R,@TIBXSQLVARMODIFIED_W,'MODIFIED');
+ RegisterPropertyHelper(@TIBXSQLVARNAME_R,nil,'NAME');
+ RegisterPropertyHelper(@TIBXSQLVARSIZE_R,nil,'SIZE');
+ RegisterPropertyHelper(@TIBXSQLVARSQLTYPE_R,nil,'SQLTYPE');
+ RegisterPropertyHelper(@TIBXSQLVARVALUE_R,@TIBXSQLVARVALUE_W,'VALUE');
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure RIRegister_IBSQL(CL: TPSRuntimeClassImporter);
+begin
+ with CL.Add(TIBSQL) do
+ with CL.Add(TIBXSQLDA) do
+ RIRegister_TIBXSQLVAR(CL);
+ RIRegister_TIBXSQLDA(CL);
+ RIRegister_TIBOUTPUTDELIMITEDFILE(CL);
+ RIRegister_TIBINPUTDELIMITEDFILE(CL);
+ RIRegister_TIBOUTPUTRAWFILE(CL);
+ RIRegister_TIBINPUTRAWFILE(CL);
+ RIRegister_TIBOUTPUTXML(CL);
+ RIRegister_TIBSQL(CL);
+end;
+
+(* === compile-time registration functions === *)
+(*----------------------------------------------------------------------------*)
+procedure SIRegister_TIBQuery(CL: TPSPascalCompiler);
+begin
+ //with RegClassS(CL,'TIBCustomDataSet', 'TIBQuery') do
+ with CL.AddClassN(CL.FindClass('TIBCustomDataSet'),'TIBQuery') do
+ begin
+ RegisterMethod('Procedure BatchInput( InputObject : TIBBatchInput)');
+ RegisterMethod('Procedure BatchOutput( OutputObject : TIBBatchOutput)');
+ RegisterMethod('Procedure ExecSQL');
+ RegisterMethod('Function ParamByName( const Value : string) : TParam');
+ RegisterMethod('Procedure Prepare');
+ RegisterMethod('Procedure UnPrepare');
+ RegisterProperty('Prepared', 'Boolean', iptrw);
+ RegisterProperty('ParamCount', 'Word', iptr);
+ RegisterProperty('StmtHandle', 'TISC_STMT_HANDLE', iptr);
+ RegisterProperty('Text', 'string', iptr);
+ RegisterProperty('RowsAffected', 'Integer', iptr);
+ RegisterProperty('GenerateParamNames', 'Boolean', iptrw);
+ RegisterProperty('DataSource', 'TDatasource', iptrw);
+ RegisterProperty('SQL', 'TStrings', iptrw);
+ RegisterProperty('Params', 'TParams', iptrw);
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure SIRegister_IBQuery(CL: TPSPascalCompiler);
+begin
+ SIRegister_TIBQuery(CL);
+end;
+
+(* === run-time registration functions === *)
+(*----------------------------------------------------------------------------*)
+procedure TIBQueryParams_W(Self: TIBQuery; const T: TParams);
+begin Self.Params := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBQueryParams_R(Self: TIBQuery; var T: TParams);
+begin T := Self.Params; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBQuerySQL_W(Self: TIBQuery; const T: TStrings);
+begin Self.SQL := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBQuerySQL_R(Self: TIBQuery; var T: TStrings);
+begin T := Self.SQL; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBQueryDataSource_W(Self: TIBQuery; const T: TDatasource);
+begin Self.DataSource := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBQueryDataSource_R(Self: TIBQuery; var T: TDatasource);
+begin T := Self.DataSource; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBQueryGenerateParamNames_W(Self: TIBQuery; const T: Boolean);
+begin Self.GenerateParamNames := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBQueryGenerateParamNames_R(Self: TIBQuery; var T: Boolean);
+begin T := Self.GenerateParamNames; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBQueryRowsAffected_R(Self: TIBQuery; var T: Integer);
+begin T := Self.RowsAffected; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBQueryText_R(Self: TIBQuery; var T: string);
+begin T := Self.Text; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBQueryStmtHandle_R(Self: TIBQuery; var T: TISC_STMT_HANDLE);
+begin T := Self.StmtHandle; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBQueryParamCount_R(Self: TIBQuery; var T: Word);
+begin T := Self.ParamCount; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBQueryPrepared_W(Self: TIBQuery; const T: Boolean);
+begin Self.Prepared := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TIBQueryPrepared_R(Self: TIBQuery; var T: Boolean);
+begin T := Self.Prepared; end;
+
+(*----------------------------------------------------------------------------*)
+procedure RIRegister_TIBQuery(CL: TPSRuntimeClassImporter);
+begin
+ with CL.Add(TIBQuery) do
+ begin
+ RegisterMethod(@TIBQuery.BatchInput, 'BatchInput');
+ RegisterMethod(@TIBQuery.BatchOutput, 'BatchOutput');
+ RegisterMethod(@TIBQuery.ExecSQL, 'ExecSQL');
+ RegisterMethod(@TIBQuery.ParamByName, 'ParamByName');
+ RegisterMethod(@TIBQuery.Prepare, 'Prepare');
+ RegisterMethod(@TIBQuery.UnPrepare, 'UnPrepare');
+ RegisterPropertyHelper(@TIBQueryPrepared_R,@TIBQueryPrepared_W,'Prepared');
+ RegisterPropertyHelper(@TIBQueryParamCount_R,nil,'ParamCount');
+ RegisterPropertyHelper(@TIBQueryStmtHandle_R,nil,'StmtHandle');
+ RegisterPropertyHelper(@TIBQueryText_R,nil,'Text');
+ RegisterPropertyHelper(@TIBQueryRowsAffected_R,nil,'RowsAffected');
+ RegisterPropertyHelper(@TIBQueryGenerateParamNames_R,@TIBQueryGenerateParamNames_W,'GenerateParamNames');
+ RegisterPropertyHelper(@TIBQueryDataSource_R,@TIBQueryDataSource_W,'DataSource');
+ RegisterPropertyHelper(@TIBQuerySQL_R,@TIBQuerySQL_W,'SQL');
+ RegisterPropertyHelper(@TIBQueryParams_R,@TIBQueryParams_W,'Params');
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure RIRegister_IBQuery(CL: TPSRuntimeClassImporter);
+begin
+ RIRegister_TIBQuery(CL);
+end;
+
+
+
+{ TIFPS3CE_IBCustomDataSet }
+(*----------------------------------------------------------------------------*)
+procedure TPSImport_IBX.CompOnUses(CompExec: TPSScript);
+begin
+ { nothing }
+end;
+(*----------------------------------------------------------------------------*)
+procedure TPSImport_IBX.ExecOnUses(CompExec: TPSScript);
+begin
+ { nothing }
+end;
+(*----------------------------------------------------------------------------*)
+procedure TPSImport_IBX.CompileImport1(CompExec: TPSScript);
+begin
+ SIRegister_IBDatabase(CompExec.Comp);
+ SIRegister_IBSQL(CompExec.Comp);
+ SIRegister_IBCustomDataSet(CompExec.Comp);
+ SIRegister_IBTable(CompExec.Comp);
+ SIRegister_IBQuery(CompExec.Comp);
+end;
+(*----------------------------------------------------------------------------*)
+procedure TPSImport_IBX.CompileImport2(CompExec: TPSScript);
+begin
+ { nothing }
+end;
+(*----------------------------------------------------------------------------*)
+procedure TPSImport_IBX.ExecImport1(CompExec: TPSScript; const ri: TPSRuntimeClassImporter);
+begin
+ RIRegister_IBDatabase(ri);
+ RIRegister_IBSQL(ri);
+ RIRegister_IBCustomDataSet(ri);
+ RIRegister_IBTable(ri);
+ RIRegister_IBQuery(ri);
+end;
+(*----------------------------------------------------------------------------*)
+procedure TPSImport_IBX.ExecImport2(CompExec: TPSScript; const ri: TPSRuntimeClassImporter);
+begin
+ { nothing }
+end;
+
+end.
diff --git a/branches/script-component/Units/PascalScript/uPSI_JvMail.pas b/branches/script-component/Units/PascalScript/uPSI_JvMail.pas
new file mode 100644
index 0000000..a74b3ce
--- /dev/null
+++ b/branches/script-component/Units/PascalScript/uPSI_JvMail.pas
@@ -0,0 +1,373 @@
+unit uPSI_JvMail;
+{
+This file has been generated by UnitParser v0.4b, written by M. Knight
+and updated by NP. v/d Spek.
+Source Code from Carlo Kok has been used to implement various sections of
+UnitParser. Components of ifps3 are used in the construction of UnitParser,
+code implementing the class wrapper is taken from Carlo Kok''s conv unility
+}
+interface
+
+uses
+ SysUtils, Classes, uPSComponent, uPSCompiler, uPSRuntime;
+
+type
+(*----------------------------------------------------------------------------*)
+ TPSImport_JvMail = class(TPSPlugin)
+ protected
+ procedure CompOnUses(CompExec: TPSScript); override;
+ procedure ExecOnUses(CompExec: TPSScript); override;
+ procedure CompileImport1(CompExec: TPSScript); override;
+ procedure CompileImport2(CompExec: TPSScript); override;
+ procedure ExecImport1(CompExec: TPSScript; const ri: TPSRuntimeClassImporter); override;
+ procedure ExecImport2(CompExec: TPSScript; const ri: TPSRuntimeClassImporter); override;
+ end;
+
+implementation
+
+
+uses
+ Windows
+ ,Controls
+ ,Forms
+ ,Mapi
+ ,JclBase
+ ,JclMapi
+ ,JvComponent
+ ,JvMail
+ ;
+
+(* === compile-time registration functions === *)
+(*----------------------------------------------------------------------------*)
+procedure SIRegister_TJvMail(CL: TPSPascalCompiler);
+begin
+ //with RegClassS(CL,'TJvComponent', 'TJvMail') do
+ with CL.AddClassN(CL.FindClass('TComponent'),'TJvMail') do
+ begin
+ RegisterMethod('Function Address( const Caption : string; EditFields : Integer) : Boolean');
+ RegisterMethod('Procedure Clear');
+ RegisterMethod('Function ErrorCheck( Res : DWORD) : DWORD');
+ RegisterMethod('Function FindFirstMail : Boolean');
+ RegisterMethod('Function FindNextMail : Boolean');
+ RegisterMethod('Procedure FreeSimpleMapi');
+ RegisterMethod('Procedure LogOff');
+ RegisterMethod('Procedure LogOn');
+ RegisterMethod('Procedure ReadMail');
+ RegisterMethod('Function ResolveName( const Name : string) : string');
+ RegisterMethod('Function SaveMail( const MessageID : string) : string');
+ RegisterMethod('Procedure SendMail( ShowDialog : Boolean)');
+ RegisterProperty('ReadedMail', 'TJvMailReadedData', iptr);
+ RegisterProperty('SeedMessageID', 'string', iptrw);
+ RegisterProperty('SessionHandle', 'THandle', iptr);
+ RegisterProperty('SimpleMAPI', 'TJclSimpleMapi', iptr);
+ RegisterProperty('UserLogged', 'Boolean', iptr);
+ RegisterProperty('Attachment', 'TStrings', iptrw);
+ RegisterProperty('BlindCopy', 'TJvMailRecipients', iptrw);
+ RegisterProperty('Body', 'TStrings', iptrw);
+ RegisterProperty('CarbonCopy', 'TJvMailRecipients', iptrw);
+ RegisterProperty('LogonOptions', 'TJvMailLogonOptions', iptrw);
+ RegisterProperty('LongMsgId', 'Boolean', iptrw);
+ RegisterProperty('Password', 'string', iptrw);
+ RegisterProperty('ProfileName', 'string', iptrw);
+ RegisterProperty('ReadOptions', 'TJvMailReadOptions', iptrw);
+ RegisterProperty('Recipient', 'TJvMailRecipients', iptrw);
+ RegisterProperty('Subject', 'string', iptrw);
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure SIRegister_TJvMailRecipients(CL: TPSPascalCompiler);
+begin
+ //with RegClassS(CL,'TCollection', 'TJvMailRecipients') do
+ with CL.AddClassN(CL.FindClass('TCollection'),'TJvMailRecipients') do
+ begin
+ RegisterMethod('Constructor Create( AOwner : TJvMail; ARecipientClass : DWORD)');
+ RegisterMethod('Function Add : TJvMailRecipient');
+ RegisterMethod('Function AddRecipient( const Address : string; const Name : string) : Integer');
+ RegisterProperty('Items', 'TJvMailRecipient Integer', iptrw);
+ SetDefaultPropery('Items');
+ RegisterProperty('RecipientClass', 'DWORD', iptr);
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure SIRegister_TJvMailRecipient(CL: TPSPascalCompiler);
+begin
+ //with RegClassS(CL,'TCollectionItem', 'TJvMailRecipient') do
+ with CL.AddClassN(CL.FindClass('TCollectionItem'),'TJvMailRecipient') do
+ begin
+ RegisterProperty('AddressAndName', 'string', iptr);
+ RegisterProperty('Address', 'string', iptrw);
+ RegisterProperty('Name', 'string', iptrw);
+ RegisterProperty('Valid', 'Boolean', iptr);
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure SIRegister_JvMail(CL: TPSPascalCompiler);
+begin
+ CL.AddClassN(CL.FindClass('TOBJECT'),'TJvMail');
+ SIRegister_TJvMailRecipient(CL);
+ SIRegister_TJvMailRecipients(CL);
+ CL.AddTypeS('TJvMailLogonOption', '( loLogonUI, loNewSession )');
+ CL.AddTypeS('TJvMailReadOption', '( roUnreadOnly, roFifo, roPeek, roHeaderOnl'
+ +'y, roAttachments )');
+ CL.AddTypeS('TJvMailLogonOptions', 'set of TJvMailLogonOption');
+ CL.AddTypeS('TJvMailReadOptions', 'set of TJvMailReadOption');
+ CL.AddTypeS('TJvMailReadedData', 'record RecipientAddress : string; Recipient'
+ +'Name : string; ConversationID : string; DateReceived : TDateTime; end');
+ SIRegister_TJvMail(CL);
+end;
+
+(* === run-time registration functions === *)
+(*----------------------------------------------------------------------------*)
+procedure TJvMailSubject_W(Self: TJvMail; const T: string);
+begin Self.Subject := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TJvMailSubject_R(Self: TJvMail; var T: string);
+begin T := Self.Subject; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TJvMailRecipient_W(Self: TJvMail; const T: TJvMailRecipients);
+begin Self.Recipient := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TJvMailRecipient_R(Self: TJvMail; var T: TJvMailRecipients);
+begin T := Self.Recipient; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TJvMailReadOptions_W(Self: TJvMail; const T: TJvMailReadOptions);
+begin Self.ReadOptions := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TJvMailReadOptions_R(Self: TJvMail; var T: TJvMailReadOptions);
+begin T := Self.ReadOptions; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TJvMailProfileName_W(Self: TJvMail; const T: string);
+begin Self.ProfileName := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TJvMailProfileName_R(Self: TJvMail; var T: string);
+begin T := Self.ProfileName; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TJvMailPassword_W(Self: TJvMail; const T: string);
+begin Self.Password := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TJvMailPassword_R(Self: TJvMail; var T: string);
+begin T := Self.Password; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TJvMailLongMsgId_W(Self: TJvMail; const T: Boolean);
+begin Self.LongMsgId := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TJvMailLongMsgId_R(Self: TJvMail; var T: Boolean);
+begin T := Self.LongMsgId; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TJvMailLogonOptions_W(Self: TJvMail; const T: TJvMailLogonOptions);
+begin Self.LogonOptions := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TJvMailLogonOptions_R(Self: TJvMail; var T: TJvMailLogonOptions);
+begin T := Self.LogonOptions; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TJvMailCarbonCopy_W(Self: TJvMail; const T: TJvMailRecipients);
+begin Self.CarbonCopy := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TJvMailCarbonCopy_R(Self: TJvMail; var T: TJvMailRecipients);
+begin T := Self.CarbonCopy; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TJvMailBody_W(Self: TJvMail; const T: TStrings);
+begin Self.Body := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TJvMailBody_R(Self: TJvMail; var T: TStrings);
+begin T := Self.Body; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TJvMailBlindCopy_W(Self: TJvMail; const T: TJvMailRecipients);
+begin Self.BlindCopy := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TJvMailBlindCopy_R(Self: TJvMail; var T: TJvMailRecipients);
+begin T := Self.BlindCopy; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TJvMailAttachment_W(Self: TJvMail; const T: TStrings);
+begin Self.Attachment := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TJvMailAttachment_R(Self: TJvMail; var T: TStrings);
+begin T := Self.Attachment; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TJvMailUserLogged_R(Self: TJvMail; var T: Boolean);
+begin T := Self.UserLogged; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TJvMailSimpleMAPI_R(Self: TJvMail; var T: TJclSimpleMapi);
+begin T := Self.SimpleMAPI; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TJvMailSessionHandle_R(Self: TJvMail; var T: THandle);
+begin T := Self.SessionHandle; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TJvMailSeedMessageID_W(Self: TJvMail; const T: string);
+begin Self.SeedMessageID := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TJvMailSeedMessageID_R(Self: TJvMail; var T: string);
+begin T := Self.SeedMessageID; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TJvMailReadedMail_R(Self: TJvMail; var T: TJvMailReadedData);
+begin T := Self.ReadedMail; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TJvMailRecipientsRecipientClass_R(Self: TJvMailRecipients; var T: DWORD);
+begin T := Self.RecipientClass; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TJvMailRecipientsItems_W(Self: TJvMailRecipients; const T: TJvMailRecipient; const t1: Integer);
+begin Self.Items[t1] := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TJvMailRecipientsItems_R(Self: TJvMailRecipients; var T: TJvMailRecipient; const t1: Integer);
+begin T := Self.Items[t1]; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TJvMailRecipientValid_R(Self: TJvMailRecipient; var T: Boolean);
+begin T := Self.Valid; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TJvMailRecipientName_W(Self: TJvMailRecipient; const T: string);
+begin Self.Name := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TJvMailRecipientName_R(Self: TJvMailRecipient; var T: string);
+begin T := Self.Name; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TJvMailRecipientAddress_W(Self: TJvMailRecipient; const T: string);
+begin Self.Address := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TJvMailRecipientAddress_R(Self: TJvMailRecipient; var T: string);
+begin T := Self.Address; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TJvMailRecipientAddressAndName_R(Self: TJvMailRecipient; var T: string);
+begin T := Self.AddressAndName; end;
+
+(*----------------------------------------------------------------------------*)
+procedure RIRegister_TJvMail(CL: TPSRuntimeClassImporter);
+begin
+ with CL.Add(TJvMail) do
+ begin
+ RegisterMethod(@TJvMail.Address, 'Address');
+ RegisterMethod(@TJvMail.Clear, 'Clear');
+ RegisterMethod(@TJvMail.ErrorCheck, 'ErrorCheck');
+ RegisterMethod(@TJvMail.FindFirstMail, 'FindFirstMail');
+ RegisterMethod(@TJvMail.FindNextMail, 'FindNextMail');
+ RegisterMethod(@TJvMail.FreeSimpleMapi, 'FreeSimpleMapi');
+ RegisterMethod(@TJvMail.LogOff, 'LogOff');
+ RegisterMethod(@TJvMail.LogOn, 'LogOn');
+ RegisterMethod(@TJvMail.ReadMail, 'ReadMail');
+ RegisterMethod(@TJvMail.ResolveName, 'ResolveName');
+ RegisterMethod(@TJvMail.SaveMail, 'SaveMail');
+ RegisterMethod(@TJvMail.SendMail, 'SendMail');
+ RegisterPropertyHelper(@TJvMailReadedMail_R,nil,'ReadedMail');
+ RegisterPropertyHelper(@TJvMailSeedMessageID_R,@TJvMailSeedMessageID_W,'SeedMessageID');
+ RegisterPropertyHelper(@TJvMailSessionHandle_R,nil,'SessionHandle');
+ RegisterPropertyHelper(@TJvMailSimpleMAPI_R,nil,'SimpleMAPI');
+ RegisterPropertyHelper(@TJvMailUserLogged_R,nil,'UserLogged');
+ RegisterPropertyHelper(@TJvMailAttachment_R,@TJvMailAttachment_W,'Attachment');
+ RegisterPropertyHelper(@TJvMailBlindCopy_R,@TJvMailBlindCopy_W,'BlindCopy');
+ RegisterPropertyHelper(@TJvMailBody_R,@TJvMailBody_W,'Body');
+ RegisterPropertyHelper(@TJvMailCarbonCopy_R,@TJvMailCarbonCopy_W,'CarbonCopy');
+ RegisterPropertyHelper(@TJvMailLogonOptions_R,@TJvMailLogonOptions_W,'LogonOptions');
+ RegisterPropertyHelper(@TJvMailLongMsgId_R,@TJvMailLongMsgId_W,'LongMsgId');
+ RegisterPropertyHelper(@TJvMailPassword_R,@TJvMailPassword_W,'Password');
+ RegisterPropertyHelper(@TJvMailProfileName_R,@TJvMailProfileName_W,'ProfileName');
+ RegisterPropertyHelper(@TJvMailReadOptions_R,@TJvMailReadOptions_W,'ReadOptions');
+ RegisterPropertyHelper(@TJvMailRecipient_R,@TJvMailRecipient_W,'Recipient');
+ RegisterPropertyHelper(@TJvMailSubject_R,@TJvMailSubject_W,'Subject');
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure RIRegister_TJvMailRecipients(CL: TPSRuntimeClassImporter);
+begin
+ with CL.Add(TJvMailRecipients) do
+ begin
+ RegisterConstructor(@TJvMailRecipients.Create, 'Create');
+ RegisterMethod(@TJvMailRecipients.Add, 'Add');
+ RegisterMethod(@TJvMailRecipients.AddRecipient, 'AddRecipient');
+ RegisterPropertyHelper(@TJvMailRecipientsItems_R,@TJvMailRecipientsItems_W,'Items');
+ RegisterPropertyHelper(@TJvMailRecipientsRecipientClass_R,nil,'RecipientClass');
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure RIRegister_TJvMailRecipient(CL: TPSRuntimeClassImporter);
+begin
+ with CL.Add(TJvMailRecipient) do
+ begin
+ RegisterPropertyHelper(@TJvMailRecipientAddressAndName_R,nil,'AddressAndName');
+ RegisterPropertyHelper(@TJvMailRecipientAddress_R,@TJvMailRecipientAddress_W,'Address');
+ RegisterPropertyHelper(@TJvMailRecipientName_R,@TJvMailRecipientName_W,'Name');
+ RegisterPropertyHelper(@TJvMailRecipientValid_R,nil,'Valid');
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure RIRegister_JvMail(CL: TPSRuntimeClassImporter);
+begin
+ with CL.Add(TJvMail) do
+ RIRegister_TJvMailRecipient(CL);
+ RIRegister_TJvMailRecipients(CL);
+ RIRegister_TJvMail(CL);
+end;
+
+{ TPSImport_JvMail }
+(*----------------------------------------------------------------------------*)
+procedure TPSImport_JvMail.CompOnUses(CompExec: TPSScript);
+begin
+ { nothing }
+end;
+(*----------------------------------------------------------------------------*)
+procedure TPSImport_JvMail.ExecOnUses(CompExec: TPSScript);
+begin
+ { nothing }
+end;
+(*----------------------------------------------------------------------------*)
+procedure TPSImport_JvMail.CompileImport1(CompExec: TPSScript);
+begin
+ SIRegister_JvMail(CompExec.Comp);
+end;
+(*----------------------------------------------------------------------------*)
+procedure TPSImport_JvMail.CompileImport2(CompExec: TPSScript);
+begin
+ { nothing }
+end;
+(*----------------------------------------------------------------------------*)
+procedure TPSImport_JvMail.ExecImport1(CompExec: TPSScript; const ri: TPSRuntimeClassImporter);
+begin
+ RIRegister_JvMail(ri);
+end;
+(*----------------------------------------------------------------------------*)
+procedure TPSImport_JvMail.ExecImport2(CompExec: TPSScript; const ri: TPSRuntimeClassImporter);
+begin
+ { nothing }
+end;
+
+end.
diff --git a/branches/script-component/Units/PascalScript/uPSI_Mask.pas b/branches/script-component/Units/PascalScript/uPSI_Mask.pas
new file mode 100644
index 0000000..7cfe29a
--- /dev/null
+++ b/branches/script-component/Units/PascalScript/uPSI_Mask.pas
@@ -0,0 +1,187 @@
+unit uPSI_Mask;
+{
+This file has been generated by UnitParser v0.5, written by M. Knight
+and updated by NP. v/d Spek.
+Source Code from Carlo Kok has been used to implement various sections of
+UnitParser. Components of ifps3 are used in the construction of UnitParser,
+code implementing the class wrapper is taken from Carlo Kok''s conv unility
+}
+interface
+
+uses
+ SysUtils, Classes, uPSComponent, uPSCompiler, uPSRuntime;
+
+type
+(*----------------------------------------------------------------------------*)
+ TPSImport_Mask = class(TPSPlugin)
+ protected
+ procedure CompOnUses(CompExec: TPSScript); override;
+ procedure ExecOnUses(CompExec: TPSScript); override;
+ procedure CompileImport1(CompExec: TPSScript); override;
+ procedure CompileImport2(CompExec: TPSScript); override;
+ procedure ExecImport1(CompExec: TPSScript; const ri: TPSRuntimeClassImporter); override;
+ procedure ExecImport2(CompExec: TPSScript; const ri: TPSRuntimeClassImporter); override;
+ end;
+
+implementation
+
+
+uses
+ Windows ,StdCtrls ,Controls ,Messages ,Forms ,Graphics ,Menus ,Mask;
+
+(* === compile-time registration functions === *)
+(*----------------------------------------------------------------------------*)
+procedure SIRegister_TMaskEdit(CL: TPSPascalCompiler);
+begin
+ //with RegClassS(CL,'TCustomMaskEdit', 'TMaskEdit') do
+ with CL.AddClassN(CL.FindClass('TCustomMaskEdit'),'TMaskEdit') do
+ begin
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure SIRegister_TCustomMaskEdit(CL: TPSPascalCompiler);
+begin
+ //with RegClassS(CL,'TCustomEdit', 'TCustomMaskEdit') do
+ with CL.AddClassN(CL.FindClass('TCustomEdit'),'TCustomMaskEdit') do
+ begin
+ RegisterMethod('Procedure ValidateEdit');
+ RegisterMethod('Function GetTextLen : Integer');
+ RegisterProperty('IsMasked', 'Boolean', iptr);
+ RegisterProperty('EditText', 'string', iptrw);
+ RegisterProperty('Text', 'string', iptrw);
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure SIRegister_Mask(CL: TPSPascalCompiler);
+begin
+ CL.AddConstantN('DefaultBlank','Char').SetString( '_');
+ CL.AddConstantN('MaskFieldSeparator','Char').SetString( ';');
+ CL.AddConstantN('MaskNoSave','Char').SetString( '0');
+ CL.AddConstantN('mDirReverse','String').SetString( '!');
+ CL.AddConstantN('mDirUpperCase','String').SetString( '>');
+ CL.AddConstantN('mDirLowerCase','String').SetString( '<');
+ CL.AddConstantN('mDirLiteral','String').SetString( '\');
+ CL.AddConstantN('mMskAlpha','String').SetString( 'L');
+ CL.AddConstantN('mMskAlphaOpt','String').SetString( 'l');
+ CL.AddConstantN('mMskAlphaNum','String').SetString( 'A');
+ CL.AddConstantN('mMskAlphaNumOpt','String').SetString( 'a');
+ CL.AddConstantN('mMskAscii','String').SetString( 'C');
+ CL.AddConstantN('mMskAsciiOpt','String').SetString( 'c');
+ CL.AddConstantN('mMskNumeric','String').SetString( '0');
+ CL.AddConstantN('mMskNumericOpt','String').SetString( '9');
+ CL.AddConstantN('mMskNumSymOpt','String').SetString( '#');
+ CL.AddConstantN('mMskTimeSeparator','String').SetString( ':');
+ CL.AddConstantN('mMskDateSeparator','String').SetString( '/');
+ CL.AddTypeS('TMaskCharType', '( mcNone, mcLiteral, mcIntlLiteral, mcDirective'
+ +', mcMask, mcMaskOpt, mcFieldSeparator, mcField )');
+ CL.AddTypeS('TMaskDirective', '( mdReverseDir, mdUpperCase, mdLowerCa'
+ +'se, mdLiteralChar )');
+ CL.AddTypeS('TMaskDirectives', 'set of TMaskDirective');
+ CL.AddClassN(CL.FindClass('TOBJECT'),'EDBEditError');
+ CL.AddTypeS('TMaskedStatex', '( msMasked, msReEnter, msDBSetText )');
+ CL.AddTypeS('TMaskedState', 'set of TMaskedStatex');
+ SIRegister_TCustomMaskEdit(CL);
+ SIRegister_TMaskEdit(CL);
+ CL.AddDelphiFunction('Function FormatMaskText( const EditMask : string; const Value : string) : string');
+ CL.AddDelphiFunction('Function MaskGetMaskSave( const EditMask : string) : Boolean');
+ CL.AddDelphiFunction('Function MaskGetMaskBlank( const EditMask : string) : Char');
+ CL.AddDelphiFunction('Function MaskGetFldSeparator( const EditMask : string) : Integer');
+end;
+
+(* === run-time registration functions === *)
+(*----------------------------------------------------------------------------*)
+procedure TCustomMaskEditText_W(Self: TCustomMaskEdit; const T: string);
+begin Self.Text := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TCustomMaskEditText_R(Self: TCustomMaskEdit; var T: string);
+begin T := Self.Text; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TCustomMaskEditEditText_W(Self: TCustomMaskEdit; const T: string);
+begin Self.EditText := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TCustomMaskEditEditText_R(Self: TCustomMaskEdit; var T: string);
+begin T := Self.EditText; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TCustomMaskEditIsMasked_R(Self: TCustomMaskEdit; var T: Boolean);
+begin T := Self.IsMasked; end;
+
+(*----------------------------------------------------------------------------*)
+procedure RIRegister_Mask_Routines(S: TPSExec);
+begin
+ S.RegisterDelphiFunction(@FormatMaskText, 'FormatMaskText', cdRegister);
+ S.RegisterDelphiFunction(@MaskGetMaskSave, 'MaskGetMaskSave', cdRegister);
+ S.RegisterDelphiFunction(@MaskGetMaskBlank, 'MaskGetMaskBlank', cdRegister);
+ S.RegisterDelphiFunction(@MaskGetFldSeparator, 'MaskGetFldSeparator', cdRegister);
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure RIRegister_TMaskEdit(CL: TPSRuntimeClassImporter);
+begin
+ with CL.Add(TMaskEdit) do
+ begin
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure RIRegister_TCustomMaskEdit(CL: TPSRuntimeClassImporter);
+begin
+ with CL.Add(TCustomMaskEdit) do
+ begin
+ RegisterVirtualMethod(@TCustomMaskEdit.ValidateEdit, 'ValidateEdit');
+ RegisterMethod(@TCustomMaskEdit.GetTextLen, 'GetTextLen');
+ RegisterPropertyHelper(@TCustomMaskEditIsMasked_R,nil,'IsMasked');
+ RegisterPropertyHelper(@TCustomMaskEditEditText_R,@TCustomMaskEditEditText_W,'EditText');
+ RegisterPropertyHelper(@TCustomMaskEditText_R,@TCustomMaskEditText_W,'Text');
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure RIRegister_Mask(CL: TPSRuntimeClassImporter);
+begin
+ with CL.Add(EDBEditError) do
+ RIRegister_TCustomMaskEdit(CL);
+ RIRegister_TMaskEdit(CL);
+end;
+
+
+
+{ TPSImport_Mask }
+(*----------------------------------------------------------------------------*)
+procedure TPSImport_Mask.CompOnUses(CompExec: TPSScript);
+begin
+ { nothing }
+end;
+(*----------------------------------------------------------------------------*)
+procedure TPSImport_Mask.ExecOnUses(CompExec: TPSScript);
+begin
+ { nothing }
+end;
+(*----------------------------------------------------------------------------*)
+procedure TPSImport_Mask.CompileImport1(CompExec: TPSScript);
+begin
+ SIRegister_Mask(CompExec.Comp);
+end;
+(*----------------------------------------------------------------------------*)
+procedure TPSImport_Mask.CompileImport2(CompExec: TPSScript);
+begin
+ { nothing }
+end;
+(*----------------------------------------------------------------------------*)
+procedure TPSImport_Mask.ExecImport1(CompExec: TPSScript; const ri: TPSRuntimeClassImporter);
+begin
+ RIRegister_Mask(ri);
+ RIRegister_Mask_Routines(CompExec.Exec); // comment it if no routines
+end;
+(*----------------------------------------------------------------------------*)
+procedure TPSImport_Mask.ExecImport2(CompExec: TPSScript; const ri: TPSRuntimeClassImporter);
+begin
+ { nothing }
+end;
+
+end.
diff --git a/branches/script-component/Units/PascalScript/uPSI_Registry.pas b/branches/script-component/Units/PascalScript/uPSI_Registry.pas
new file mode 100644
index 0000000..2bc5283
--- /dev/null
+++ b/branches/script-component/Units/PascalScript/uPSI_Registry.pas
@@ -0,0 +1,478 @@
+unit uPSI_Registry;
+{
+This file has been generated by UnitParser v0.4b, written by M. Knight
+and updated by NP. v/d Spek.
+Source Code from Carlo Kok has been used to implement various sections of
+UnitParser. Components of ifps3 are used in the construction of UnitParser,
+code implementing the class wrapper is taken from Carlo Kok''s conv unility
+}
+
+interface
+
+uses
+ SysUtils, Classes, uPSComponent, uPSCompiler, uPSRuntime;
+
+type
+(*----------------------------------------------------------------------------*)
+ TPSImport_Registry = class(TPSPlugin)
+ protected
+ procedure CompOnUses(CompExec: TPSScript); override;
+ procedure ExecOnUses(CompExec: TPSScript); override;
+ procedure CompileImport1(CompExec: TPSScript); override;
+ procedure CompileImport2(CompExec: TPSScript); override;
+ procedure ExecImport1(CompExec: TPSScript; const ri: TPSRuntimeClassImporter); override;
+ procedure ExecImport2(CompExec: TPSScript; const ri: TPSRuntimeClassImporter); override;
+ end;
+
+implementation
+
+
+uses
+ Windows ,IniFiles ,Registry ;
+
+(* === compile-time registration functions === *)
+(*----------------------------------------------------------------------------*)
+procedure SIRegister_TRegistryIniFile(CL: TPSPascalCompiler);
+begin
+ //with RegClassS(CL,'TCustomIniFile', 'TRegistryIniFile') do
+ with CL.AddClassN(CL.FindClass('TCustomIniFile'),'TRegistryIniFile') do
+ begin
+ RegisterMethod('Constructor Create( const FileName : string);');
+ RegisterMethod('Constructor CreateA( const FileName : string; AAccess : LongWord);');
+ RegisterProperty('RegIniFile', 'TRegIniFile', iptr);
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure SIRegister_TRegIniFile(CL: TPSPascalCompiler);
+begin
+ //with RegClassS(CL,'TRegistry', 'TRegIniFile') do
+ with CL.AddClassN(CL.FindClass('TRegistry'),'TRegIniFile') do
+ begin
+ RegisterMethod('Constructor Create( const FileName : string);');
+ RegisterMethod('Constructor CreateA( const FileName : string; AAccess : LongWord);');
+ RegisterMethod('Function ReadString( const Section, Ident, Default : string) : string');
+ RegisterMethod('Function ReadInteger( const Section, Ident : string; Default : Longint) : Longint');
+ RegisterMethod('Procedure WriteInteger( const Section, Ident : string; Value : Longint)');
+ RegisterMethod('Procedure WriteString( const Section, Ident, Value : String)');
+ RegisterMethod('Function ReadBool( const Section, Ident : string; Default : Boolean) : Boolean');
+ RegisterMethod('Procedure WriteBool( const Section, Ident : string; Value : Boolean)');
+ RegisterMethod('Procedure ReadSection( const Section : string; Strings : TStrings)');
+ RegisterMethod('Procedure ReadSections( Strings : TStrings)');
+ RegisterMethod('Procedure ReadSectionValues( const Section : string; Strings : TStrings)');
+ RegisterMethod('Procedure EraseSection( const Section : string)');
+ RegisterMethod('Procedure DeleteKey( const Section, Ident : String)');
+ RegisterProperty('FileName', 'string', iptr);
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure SIRegister_TRegistry(CL: TPSPascalCompiler);
+begin
+ //with RegClassS(CL,'TObject', 'TRegistry') do
+ with CL.AddClassN(CL.FindClass('TObject'),'TRegistry') do
+ begin
+ RegisterMethod('Constructor Create;');
+ RegisterMethod('Constructor CreateA( AAccess : LongWord);');
+ RegisterMethod('Procedure CloseKey');
+ RegisterMethod('Function CreateKey( const Key : string) : Boolean');
+ RegisterMethod('Function DeleteKey( const Key : string) : Boolean');
+ RegisterMethod('Function DeleteValue( const Name : string) : Boolean');
+ RegisterMethod('Function GetDataInfo( const ValueName : string; var Value : TRegDataInfo) : Boolean');
+ RegisterMethod('Function GetDataSize( const ValueName : string) : Integer');
+ RegisterMethod('Function GetDataType( const ValueName : string) : TRegDataType');
+ RegisterMethod('Function GetKeyInfo( var Value : TRegKeyInfo) : Boolean');
+ RegisterMethod('Procedure GetKeyNames( Strings : TStrings)');
+ RegisterMethod('Procedure GetValueNames( Strings : TStrings)');
+ RegisterMethod('Function HasSubKeys : Boolean');
+ RegisterMethod('Function KeyExists( const Key : string) : Boolean');
+ RegisterMethod('Function LoadKey( const Key, FileName : string) : Boolean');
+ RegisterMethod('Procedure MoveKey( const OldName, NewName : string; Delete : Boolean)');
+ RegisterMethod('Function OpenKey( const Key : string; CanCreate : Boolean) : Boolean');
+ RegisterMethod('Function OpenKeyReadOnly( const Key : String) : Boolean');
+ RegisterMethod('Function ReadCurrency( const Name : string) : Currency');
+ RegisterMethod('Function ReadBool( const Name : string) : Boolean');
+ RegisterMethod('Function ReadDate( const Name : string) : TDateTime');
+ RegisterMethod('Function ReadDateTime( const Name : string) : TDateTime');
+ RegisterMethod('Function ReadFloat( const Name : string) : Double');
+ RegisterMethod('Function ReadInteger( const Name : string) : Integer');
+ RegisterMethod('Function ReadString( const Name : string) : string');
+ RegisterMethod('Function ReadTime( const Name : string) : TDateTime');
+ RegisterMethod('Function RegistryConnect( const UNCName : string) : Boolean');
+ RegisterMethod('Procedure RenameValue( const OldName, NewName : string)');
+ RegisterMethod('Function ReplaceKey( const Key, FileName, BackUpFileName : string) : Boolean');
+ RegisterMethod('Function RestoreKey( const Key, FileName : string) : Boolean');
+ RegisterMethod('Function SaveKey( const Key, FileName : string) : Boolean');
+ RegisterMethod('Function UnLoadKey( const Key : string) : Boolean');
+ RegisterMethod('Function ValueExists( const Name : string) : Boolean');
+ RegisterMethod('Procedure WriteCurrency( const Name : string; Value : Currency)');
+ RegisterMethod('Procedure WriteBool( const Name : string; Value : Boolean)');
+ RegisterMethod('Procedure WriteDate( const Name : string; Value : TDateTime)');
+ RegisterMethod('Procedure WriteDateTime( const Name : string; Value : TDateTime)');
+ RegisterMethod('Procedure WriteFloat( const Name : string; Value : Double)');
+ RegisterMethod('Procedure WriteInteger( const Name : string; Value : Integer)');
+ RegisterMethod('Procedure WriteString( const Name, Value : string)');
+ RegisterMethod('Procedure WriteExpandString( const Name, Value : string)');
+ RegisterMethod('Procedure WriteTime( const Name : string; Value : TDateTime)');
+ RegisterProperty('CurrentKey', 'HKEY', iptr);
+ RegisterProperty('CurrentPath', 'string', iptr);
+ RegisterProperty('LazyWrite', 'Boolean', iptrw);
+ RegisterProperty('RootKey', 'HKEY', iptrw);
+ RegisterProperty('Access', 'LongWord', iptrw);
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure SIRegister_Registry(CL: TPSPascalCompiler);
+begin
+ CL.AddClassN(CL.FindClass('TOBJECT'),'ERegistryException');
+ SIRegister_TRegistry(CL);
+ SIRegister_TRegIniFile(CL);
+ SIRegister_TRegistryIniFile(CL);
+end;
+
+(* === run-time registration functions === *)
+(*----------------------------------------------------------------------------*)
+procedure TRegistryIniFileRegIniFile_R(Self: TRegistryIniFile; var T: TRegIniFile);
+begin T := Self.RegIniFile; end;
+
+(*----------------------------------------------------------------------------*)
+Function TRegistryIniFileCreateA_P(Self: TClass; CreateNewInstance: Boolean; const FileName : string; AAccess : LongWord):TObject;
+Begin Result := TRegistryIniFile.Create(FileName, AAccess); END;
+
+(*----------------------------------------------------------------------------*)
+Function TRegistryIniFileCreate_P(Self: TClass; CreateNewInstance: Boolean; const FileName : string):TObject;
+Begin Result := TRegistryIniFile.Create(FileName); END;
+
+(*----------------------------------------------------------------------------*)
+procedure TRegIniFileFileName_R(Self: TRegIniFile; var T: string);
+begin T := Self.FileName; end;
+
+(*----------------------------------------------------------------------------*)
+Function TRegIniFileCreateA_P(Self: TClass; CreateNewInstance: Boolean; const FileName : string; AAccess : LongWord):TObject;
+Begin Result := TRegIniFile.Create(FileName, AAccess); END;
+
+(*----------------------------------------------------------------------------*)
+Function TRegIniFileCreate_P(Self: TClass; CreateNewInstance: Boolean; const FileName : string):TObject;
+Begin Result := TRegIniFile.Create(FileName); END;
+
+(*----------------------------------------------------------------------------*)
+procedure TRegistryAccess_W(Self: TRegistry; const T: LongWord);
+begin Self.Access := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TRegistryAccess_R(Self: TRegistry; var T: LongWord);
+begin T := Self.Access; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TRegistryRootKey_W(Self: TRegistry; const T: HKEY);
+begin Self.RootKey := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TRegistryRootKey_R(Self: TRegistry; var T: HKEY);
+begin T := Self.RootKey; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TRegistryLazyWrite_W(Self: TRegistry; const T: Boolean);
+begin Self.LazyWrite := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TRegistryLazyWrite_R(Self: TRegistry; var T: Boolean);
+begin T := Self.LazyWrite; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TRegistryCurrentPath_R(Self: TRegistry; var T: string);
+begin T := Self.CurrentPath; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TRegistryCurrentKey_R(Self: TRegistry; var T: HKEY);
+begin T := Self.CurrentKey; end;
+
+(*----------------------------------------------------------------------------*)
+Function TRegistryCreateA_P(Self: TClass; CreateNewInstance: Boolean; AAccess : LongWord):TObject;
+Begin Result := TRegistry.Create(AAccess); END;
+
+(*----------------------------------------------------------------------------*)
+Function TRegistryCreate_P(Self: TClass; CreateNewInstance: Boolean):TObject;
+Begin Result := TRegistry.Create; END;
+
+(*----------------------------------------------------------------------------*)
+procedure RIRegister_TRegistryIniFile(CL: TPSRuntimeClassImporter);
+begin
+ with CL.Add(TRegistryIniFile) do
+ begin
+ RegisterConstructor(@TRegistryIniFileCreate_P, 'Create');
+ RegisterConstructor(@TRegistryIniFileCreateA_P, 'CreateA');
+ RegisterPropertyHelper(@TRegistryIniFileRegIniFile_R,nil,'RegIniFile');
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure RIRegister_TRegIniFile(CL: TPSRuntimeClassImporter);
+begin
+ with CL.Add(TRegIniFile) do
+ begin
+ RegisterConstructor(@TRegIniFileCreate_P, 'Create');
+ RegisterConstructor(@TRegIniFileCreateA_P, 'CreateA');
+ RegisterMethod(@TRegIniFile.ReadString, 'ReadString');
+ RegisterMethod(@TRegIniFile.ReadInteger, 'ReadInteger');
+ RegisterMethod(@TRegIniFile.WriteInteger, 'WriteInteger');
+ RegisterMethod(@TRegIniFile.WriteString, 'WriteString');
+ RegisterMethod(@TRegIniFile.ReadBool, 'ReadBool');
+ RegisterMethod(@TRegIniFile.WriteBool, 'WriteBool');
+ RegisterMethod(@TRegIniFile.ReadSection, 'ReadSection');
+ RegisterMethod(@TRegIniFile.ReadSections, 'ReadSections');
+ RegisterMethod(@TRegIniFile.ReadSectionValues, 'ReadSectionValues');
+ RegisterMethod(@TRegIniFile.EraseSection, 'EraseSection');
+ RegisterMethod(@TRegIniFile.DeleteKey, 'DeleteKey');
+ RegisterPropertyHelper(@TRegIniFileFileName_R,nil,'FileName');
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure RIRegister_TRegistry(CL: TPSRuntimeClassImporter);
+begin
+ with CL.Add(TRegistry) do
+ begin
+ RegisterConstructor(@TRegistryCreateA_P, 'CreateA');
+ RegisterConstructor(@TRegistryCreate_P, 'Create');
+ RegisterMethod(@TRegistry.CloseKey, 'CloseKey');
+ RegisterMethod(@TRegistry.CreateKey, 'CreateKey');
+ RegisterMethod(@TRegistry.DeleteKey, 'DeleteKey');
+ RegisterMethod(@TRegistry.DeleteValue, 'DeleteValue');
+ RegisterMethod(@TRegistry.GetDataInfo, 'GetDataInfo');
+ RegisterMethod(@TRegistry.GetDataSize, 'GetDataSize');
+ RegisterMethod(@TRegistry.GetDataType, 'GetDataType');
+ RegisterMethod(@TRegistry.GetKeyInfo, 'GetKeyInfo');
+ RegisterMethod(@TRegistry.GetKeyNames, 'GetKeyNames');
+ RegisterMethod(@TRegistry.GetValueNames, 'GetValueNames');
+ RegisterMethod(@TRegistry.HasSubKeys, 'HasSubKeys');
+ RegisterMethod(@TRegistry.KeyExists, 'KeyExists');
+ RegisterMethod(@TRegistry.LoadKey, 'LoadKey');
+ RegisterMethod(@TRegistry.MoveKey, 'MoveKey');
+ RegisterMethod(@TRegistry.OpenKey, 'OpenKey');
+ RegisterMethod(@TRegistry.OpenKeyReadOnly, 'OpenKeyReadOnly');
+ RegisterMethod(@TRegistry.ReadCurrency, 'ReadCurrency');
+ RegisterMethod(@TRegistry.ReadBool, 'ReadBool');
+ RegisterMethod(@TRegistry.ReadDate, 'ReadDate');
+ RegisterMethod(@TRegistry.ReadDateTime, 'ReadDateTime');
+ RegisterMethod(@TRegistry.ReadFloat, 'ReadFloat');
+ RegisterMethod(@TRegistry.ReadInteger, 'ReadInteger');
+ RegisterMethod(@TRegistry.ReadString, 'ReadString');
+ RegisterMethod(@TRegistry.ReadTime, 'ReadTime');
+ RegisterMethod(@TRegistry.RegistryConnect, 'RegistryConnect');
+ RegisterMethod(@TRegistry.RenameValue, 'RenameValue');
+ RegisterMethod(@TRegistry.ReplaceKey, 'ReplaceKey');
+ RegisterMethod(@TRegistry.RestoreKey, 'RestoreKey');
+ RegisterMethod(@TRegistry.SaveKey, 'SaveKey');
+ RegisterMethod(@TRegistry.UnLoadKey, 'UnLoadKey');
+ RegisterMethod(@TRegistry.ValueExists, 'ValueExists');
+ RegisterMethod(@TRegistry.WriteCurrency, 'WriteCurrency');
+ RegisterMethod(@TRegistry.WriteBool, 'WriteBool');
+ RegisterMethod(@TRegistry.WriteDate, 'WriteDate');
+ RegisterMethod(@TRegistry.WriteDateTime, 'WriteDateTime');
+ RegisterMethod(@TRegistry.WriteFloat, 'WriteFloat');
+ RegisterMethod(@TRegistry.WriteInteger, 'WriteInteger');
+ RegisterMethod(@TRegistry.WriteString, 'WriteString');
+ RegisterMethod(@TRegistry.WriteExpandString, 'WriteExpandString');
+ RegisterMethod(@TRegistry.WriteTime, 'WriteTime');
+ RegisterPropertyHelper(@TRegistryCurrentKey_R,nil,'CurrentKey');
+ RegisterPropertyHelper(@TRegistryCurrentPath_R,nil,'CurrentPath');
+ RegisterPropertyHelper(@TRegistryLazyWrite_R,@TRegistryLazyWrite_W,'LazyWrite');
+ RegisterPropertyHelper(@TRegistryRootKey_R,@TRegistryRootKey_W,'RootKey');
+ RegisterPropertyHelper(@TRegistryAccess_R,@TRegistryAccess_W,'Access');
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure RIRegister_Registry(CL: TPSRuntimeClassImporter);
+begin
+ with CL.Add(ERegistryException) do
+ RIRegister_TRegistry(CL);
+ RIRegister_TRegIniFile(CL);
+ RIRegister_TRegistryIniFile(CL);
+end;
+
+(* === compile-time registration functions === *)
+(*----------------------------------------------------------------------------*)
+procedure SIRegister_TMemIniFile(CL: TPSPascalCompiler);
+begin
+ //with RegClassS(CL,'TCustomIniFile', 'TMemIniFile') do
+ with CL.AddClassN(CL.FindClass('TCustomIniFile'),'TMemIniFile') do
+ begin
+ RegisterMethod('Constructor Create( const FileName : string)');
+ RegisterMethod('Procedure Clear');
+ RegisterMethod('Procedure GetStrings( List : TStrings)');
+ RegisterMethod('Procedure Rename( const FileName : string; Reload : Boolean)');
+ RegisterMethod('Procedure SetStrings( List : TStrings)');
+ end;
+end;
+
+
+(*----------------------------------------------------------------------------*)
+procedure SIRegister_TIniFile(CL: TPSPascalCompiler);
+begin
+ //with RegClassS(CL,'TCustomIniFile', 'TIniFile') do
+ with CL.AddClassN(CL.FindClass('TCustomIniFile'),'TIniFile') do
+ begin
+ RegisterMethod('Function ReadString( const Section, Ident, Default : string) : string');
+ RegisterMethod('Procedure WriteString( const Section, Ident, Value : String)');
+ RegisterMethod('Procedure ReadSection( const Section : string; Strings : TStrings)');
+ RegisterMethod('Procedure ReadSections( Strings : TStrings)');
+ RegisterMethod('Procedure ReadSectionValues( const Section : string; Strings : TStrings)');
+ RegisterMethod('Procedure EraseSection( const Section : string)');
+ RegisterMethod('Procedure DeleteKey( const Section, Ident : String)');
+ RegisterMethod('Procedure UpdateFile');
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure SIRegister_TCustomIniFile(CL: TPSPascalCompiler);
+begin
+ //with RegClassS(CL,'TObject', 'TCustomIniFile') do
+ with CL.AddClassN(CL.FindClass('TObject'),'TCustomIniFile') do
+ begin
+ RegisterMethod('Constructor Create( const FileName : string)');
+ RegisterMethod('Function SectionExists( const Section : string) : Boolean');
+// RegisterMethod('Function ReadString( const Section, Ident, Default : string) : string');
+// RegisterMethod('Procedure WriteString( const Section, Ident, Value : String)');
+ RegisterMethod('Function ReadInteger( const Section, Ident : string; Default : Longint) : Longint');
+ RegisterMethod('Procedure WriteInteger( const Section, Ident : string; Value : Longint)');
+ RegisterMethod('Function ReadBool( const Section, Ident : string; Default : Boolean) : Boolean');
+ RegisterMethod('Procedure WriteBool( const Section, Ident : string; Value : Boolean)');
+ RegisterMethod('Function ReadDate( const Section, Name : string; Default : TDateTime) : TDateTime');
+ RegisterMethod('Function ReadDateTime( const Section, Name : string; Default : TDateTime) : TDateTime');
+ RegisterMethod('Function ReadFloat( const Section, Name : string; Default : Double) : Double');
+ RegisterMethod('Function ReadTime( const Section, Name : string; Default : TDateTime) : TDateTime');
+ RegisterMethod('Procedure WriteDate( const Section, Name : string; Value : TDateTime)');
+ RegisterMethod('Procedure WriteDateTime( const Section, Name : string; Value : TDateTime)');
+ RegisterMethod('Procedure WriteFloat( const Section, Name : string; Value : Double)');
+ RegisterMethod('Procedure WriteTime( const Section, Name : string; Value : TDateTime)');
+// RegisterMethod('Procedure ReadSection( const Section : string; Strings : TStrings)');
+// RegisterMethod('Procedure ReadSections( Strings : TStrings)');
+// RegisterMethod('Procedure ReadSectionValues( const Section : string; Strings : TStrings)');
+// RegisterMethod('Procedure EraseSection( const Section : string)');
+// RegisterMethod('Procedure DeleteKey( const Section, Ident : String)');
+// RegisterMethod('Procedure UpdateFile');
+ RegisterMethod('Function ValueExists( const Section, Ident : string) : Boolean');
+ RegisterProperty('FileName', 'string', iptr);
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure SIRegister_IniFiles(CL: TPSPascalCompiler);
+begin
+ SIRegister_TCustomIniFile(CL);
+ SIRegister_TIniFile(CL);
+ SIRegister_TMemIniFile(CL);
+end;
+
+(* === run-time registration functions === *)
+(*----------------------------------------------------------------------------*)
+procedure TCustomIniFileFileName_R(Self: TCustomIniFile; var T: string);
+begin T := Self.FileName; end;
+
+(*----------------------------------------------------------------------------*)
+procedure RIRegister_TMemIniFile(CL: TPSRuntimeClassImporter);
+begin
+ with CL.Add(TMemIniFile) do
+ begin
+ RegisterConstructor(@TMemIniFile.Create, 'Create');
+ RegisterMethod(@TMemIniFile.Clear, 'Clear');
+ RegisterMethod(@TMemIniFile.GetStrings, 'GetStrings');
+ RegisterMethod(@TMemIniFile.Rename, 'Rename');
+ RegisterMethod(@TMemIniFile.SetStrings, 'SetStrings');
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure RIRegister_TIniFile(CL: TPSRuntimeClassImporter);
+begin
+ with CL.Add(TIniFile) do
+ begin
+ RegisterMethod(@TIniFile.ReadString, 'ReadString');
+ RegisterMethod(@TIniFile.WriteString, 'WriteString');
+ RegisterMethod(@TIniFile.ReadSection, 'ReadSection');
+ RegisterMethod(@TIniFile.ReadSections, 'ReadSections');
+ RegisterMethod(@TIniFile.ReadSectionValues, 'ReadSectionValues');
+ RegisterMethod(@TIniFile.EraseSection, 'EraseSection');
+ RegisterMethod(@TIniFile.DeleteKey, 'DeleteKey');
+ RegisterMethod(@TIniFile.UpdateFile, 'UpdateFile');
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure RIRegister_TCustomIniFile(CL: TPSRuntimeClassImporter);
+begin
+ with CL.Add(TCustomIniFile) do
+ begin
+ RegisterConstructor(@TCustomIniFile.Create, 'Create');
+ RegisterMethod(@TCustomIniFile.SectionExists, 'SectionExists');
+// RegisterVirtualAbstractMethod(@TCustomIniFile, @!.ReadString, 'ReadString');
+// RegisterVirtualAbstractMethod(@TCustomIniFile, @!.WriteString, 'WriteString');
+ RegisterVirtualMethod(@TCustomIniFile.ReadInteger, 'ReadInteger');
+ RegisterVirtualMethod(@TCustomIniFile.WriteInteger, 'WriteInteger');
+ RegisterVirtualMethod(@TCustomIniFile.ReadBool, 'ReadBool');
+ RegisterVirtualMethod(@TCustomIniFile.WriteBool, 'WriteBool');
+ RegisterVirtualMethod(@TCustomIniFile.ReadDate, 'ReadDate');
+ RegisterVirtualMethod(@TCustomIniFile.ReadDateTime, 'ReadDateTime');
+ RegisterVirtualMethod(@TCustomIniFile.ReadFloat, 'ReadFloat');
+ RegisterVirtualMethod(@TCustomIniFile.ReadTime, 'ReadTime');
+ RegisterVirtualMethod(@TCustomIniFile.WriteDate, 'WriteDate');
+ RegisterVirtualMethod(@TCustomIniFile.WriteDateTime, 'WriteDateTime');
+ RegisterVirtualMethod(@TCustomIniFile.WriteFloat, 'WriteFloat');
+ RegisterVirtualMethod(@TCustomIniFile.WriteTime, 'WriteTime');
+// RegisterVirtualAbstractMethod(@TCustomIniFile, @!.ReadSection, 'ReadSection');
+// RegisterVirtualAbstractMethod(@TCustomIniFile, @!.ReadSections, 'ReadSections');
+// RegisterVirtualAbstractMethod(@TCustomIniFile, @!.ReadSectionValues, 'ReadSectionValues');
+// RegisterVirtualAbstractMethod(@TCustomIniFile, @!.EraseSection, 'EraseSection');
+// RegisterVirtualAbstractMethod(@TCustomIniFile, @!.DeleteKey, 'DeleteKey');
+// RegisterVirtualAbstractMethod(@TCustomIniFile, @!.UpdateFile, 'UpdateFile');
+ RegisterMethod(@TCustomIniFile.ValueExists, 'ValueExists');
+ RegisterPropertyHelper(@TCustomIniFileFileName_R,nil,'FileName');
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure RIRegister_IniFiles(CL: TPSRuntimeClassImporter);
+begin
+ RIRegister_TCustomIniFile(CL);
+ RIRegister_TIniFile(CL);
+ RIRegister_TMemIniFile(CL);
+end;
+
+{ TPSImport_Registry }
+(*----------------------------------------------------------------------------*)
+procedure TPSImport_Registry.CompOnUses(CompExec: TPSScript);
+begin
+ { nothing }
+end;
+(*----------------------------------------------------------------------------*)
+procedure TPSImport_Registry.ExecOnUses(CompExec: TPSScript);
+begin
+ { nothing }
+end;
+(*----------------------------------------------------------------------------*)
+procedure TPSImport_Registry.CompileImport1(CompExec: TPSScript);
+begin
+ SIRegister_Registry(CompExec.Comp);
+ SIRegister_IniFiles(CompExec.Comp);
+end;
+(*----------------------------------------------------------------------------*)
+procedure TPSImport_Registry.CompileImport2(CompExec: TPSScript);
+begin
+ { nothing }
+end;
+(*----------------------------------------------------------------------------*)
+procedure TPSImport_Registry.ExecImport1(CompExec: TPSScript; const ri: TPSRuntimeClassImporter);
+begin
+ RIRegister_Registry(ri);
+ RIRegister_IniFiles(ri);
+end;
+(*----------------------------------------------------------------------------*)
+procedure TPSImport_Registry.ExecImport2(CompExec: TPSScript; const ri: TPSRuntimeClassImporter);
+begin
+ { nothing }
+end;
+
+end.
diff --git a/branches/script-component/Units/PascalScript/uPSPreProcessor.pas b/branches/script-component/Units/PascalScript/uPSPreProcessor.pas
new file mode 100644
index 0000000..6be2689
--- /dev/null
+++ b/branches/script-component/Units/PascalScript/uPSPreProcessor.pas
@@ -0,0 +1,800 @@
+
+unit uPSPreProcessor;
+{$I PascalScript.inc}
+
+interface
+uses
+ Classes, SysUtils, uPSCompiler, uPSUtils;
+
+
+
+type
+ EPSPreProcessor = class(Exception); //- jgv
+ TPSPreProcessor = class;
+ TPSPascalPreProcessorParser = class;
+
+ TPSOnNeedFile = function (Sender: TPSPreProcessor; const callingfilename: tbtstring; var FileName, Output: tbtstring): Boolean;
+ TPSOnProcessDirective = procedure (
+ Sender: TPSPreProcessor;
+ Parser: TPSPascalPreProcessorParser;
+ const Active: Boolean;
+ const DirectiveName, DirectiveParam: tbtString;
+ Var Continue: Boolean); //- jgv - application set continue to false to stop the normal directive processing
+
+ TPSLineInfo = class(TObject)
+ private
+ function GetLineOffset(I: Integer): Cardinal;
+ function GetLineOffsetCount: Longint;
+ protected
+ FEndPos: Cardinal;
+ FStartPos: Cardinal;
+ FFileName: tbtstring;
+ FLineOffsets: TIfList;
+ public
+
+ property FileName: tbtstring read FFileName;
+
+ property StartPos: Cardinal read FStartPos;
+
+ property EndPos: Cardinal read FEndPos;
+
+ property LineOffsetCount: Longint read GetLineOffsetCount;
+
+ property LineOffset[I: Longint]: Cardinal read GetLineOffset;
+
+
+ constructor Create;
+
+ destructor Destroy; override;
+ end;
+
+ TPSLineInfoResults = record
+
+ Row,
+ Col,
+ Pos: Cardinal;
+
+ Name: tbtstring;
+ end;
+
+ TPSLineInfoList = class(TObject)
+ private
+ FItems: TIfList;
+ FCurrent: Longint;
+ function GetCount: Longint;
+ function GetItem(I: Integer): TPSLineInfo;
+ protected
+
+ function Add: TPSLineInfo;
+ public
+
+ property Count: Longint read GetCount;
+
+ property Items[I: Longint]: TPSLineInfo read GetItem; default;
+
+ procedure Clear;
+
+ function GetLineInfo(const ModuleName: tbtstring; Pos: Cardinal; var Res: TPSLineInfoResults): Boolean;
+
+ property Current: Longint read FCurrent write FCurrent;
+
+
+ constructor Create;
+
+ destructor Destroy; override;
+ end;
+ TPSDefineStates = class;
+
+ TPSPreProcessor = class(TObject)
+ private
+ FID: Pointer;
+ FCurrentDefines, FDefines: TStringList;
+ FCurrentLineInfo: TPSLineInfoList;
+ FOnNeedFile: TPSOnNeedFile;
+ FAddedPosition: Cardinal;
+ FDefineState: TPSDefineStates;
+ FMaxLevel: Longint;
+ FMainFileName: tbtstring;
+ FMainFile: tbtstring;
+ FOnProcessDirective: TPSOnProcessDirective;
+ FOnProcessUnknowDirective: TPSOnProcessDirective;
+ procedure ParserNewLine(Sender: TPSPascalPreProcessorParser; Row, Col, Pos: Cardinal);
+ procedure IntPreProcess(Level: Integer; const OrgFileName: tbtstring; FileName: tbtstring; Dest: TStream);
+ protected
+ procedure doAddStdPredefines; virtual; // jgv
+ public
+ {The maximum number of levels deep the parser will go, defaults to 20}
+ property MaxLevel: Longint read FMaxLevel write FMaxLevel;
+ property CurrentLineInfo: TPSLineInfoList read FCurrentLineInfo;
+
+ property OnNeedFile: TPSOnNeedFile read FOnNeedFile write FOnNeedFile;
+
+ property Defines: TStringList read FDefines write FDefines;
+
+ property MainFile: tbtstring read FMainFile write FMainFile;
+
+ property MainFileName: tbtstring read FMainFileName write FMainFileName;
+
+ property ID: Pointer read FID write FID;
+
+ procedure AdjustMessages(Comp: TPSPascalCompiler);
+ procedure AdjustMessage(Msg: TPSPascalCompilerMessage); //-jgv
+
+ procedure PreProcess(const Filename: tbtstring; var Output: tbtstring);
+
+ procedure Clear;
+
+
+ constructor Create;
+
+ destructor Destroy; override;
+
+ property OnProcessDirective: TPSOnProcessDirective read fOnProcessDirective write fOnProcessDirective;
+ property OnProcessUnknowDirective: TPSOnProcessDirective read fOnProcessUnknowDirective write fOnProcessUnknowDirective;
+ end;
+
+ TPSPascalPreProcessorType = (ptEOF, ptOther, ptDefine);
+
+ TPSOnNewLine = procedure (Sender: TPSPascalPreProcessorParser; Row, Col, Pos: Cardinal) of object;
+
+ TPSPascalPreProcessorParser = class(TObject)
+ private
+ FData: tbtstring;
+ FText: PAnsichar;
+ FToken: tbtstring;
+ FTokenId: TPSPascalPreProcessorType;
+ FLastEnterPos, FLen, FRow, FCol, FPos: Cardinal;
+ FOnNewLine: TPSOnNewLine;
+ public
+
+ procedure SetText(const dta: tbtstring);
+
+ procedure Next;
+
+ property Token: tbtstring read FToken;
+
+ property TokenId: TPSPascalPreProcessorType read FTokenId;
+
+ property Row: Cardinal read FRow;
+
+ property Col: Cardinal read FCol;
+
+ property Pos: Cardinal read FPos;
+
+ property OnNewLine: TPSOnNewLine read FOnNewLine write FOnNewLine;
+ end;
+
+ TPSDefineState = class(TObject)
+ private
+ FInElse: Boolean;
+ FDoWrite: Boolean;
+ public
+
+ property InElse: Boolean read FInElse write FInElse;
+
+ property DoWrite: Boolean read FDoWrite write FDoWrite;
+ end;
+
+ TPSDefineStates = class(TObject)
+ private
+ FItems: TIfList;
+ function GetCount: Longint;
+ function GetItem(I: Integer): TPSDefineState;
+ function GetWrite: Boolean;
+ function GetPrevWrite: Boolean; //JeromeWelsh - nesting fix
+ public
+
+ property Count: Longint read GetCount;
+
+ property Item[I: Longint]: TPSDefineState read GetItem; default;
+
+ function Add: TPSDefineState;
+
+ procedure Delete(I: Longint);
+
+
+ constructor Create;
+
+ destructor Destroy; override;
+
+ procedure Clear;
+
+ property DoWrite: Boolean read GetWrite;
+ property DoPrevWrite: Boolean read GetPrevWrite; //JeromeWelsh - nesting fix
+ end;
+
+implementation
+
+{$IFDEF DELPHI3UP }
+resourceString
+{$ELSE }
+const
+{$ENDIF }
+
+ RPS_TooManyNestedInclude = 'Too many nested include files while processing ''%s'' from ''%s''';
+ RPS_IncludeNotFound = 'Unable to find file ''%s'' used from ''%s''';
+ RPS_DefineTooManyParameters = 'Too many parameters at %d:%d';
+ RPS_NoIfdefForEndif = 'No IFDEF for ENDIF at %d:%d';
+ RPS_NoIfdefForElse = 'No IFDEF for ELSE at %d:%d';
+ RPS_ElseTwice = 'Can''t use ELSE twice at %d:%d';
+ RPS_UnknownCompilerDirective = 'Unknown compiler directives at %d:%d';
+ RPs_DefineNotClosed = 'Define not closed';
+
+{ TPSLineInfoList }
+
+function TPSLineInfoList.Add: TPSLineInfo;
+begin
+ Result := TPSLineInfo.Create;
+ FItems.Add(Result);
+end;
+
+procedure TPSLineInfoList.Clear;
+var
+ i: Longint;
+begin
+ for i := FItems.count -1 downto 0 do
+ TPSLineInfo(FItems[i]).Free;
+ FItems.Clear;
+end;
+
+constructor TPSLineInfoList.Create;
+begin
+ inherited Create;
+ FItems := TIfList.Create;
+end;
+
+destructor TPSLineInfoList.Destroy;
+begin
+ Clear;
+ FItems.Free;
+ inherited Destroy;
+end;
+
+function TPSLineInfoList.GetCount: Longint;
+begin
+ Result := FItems.Count;
+end;
+
+function TPSLineInfoList.GetItem(I: Integer): TPSLineInfo;
+begin
+ Result := TPSLineInfo(FItems[i]);
+end;
+
+function TPSLineInfoList.GetLineInfo(const ModuleName: tbtstring; Pos: Cardinal; var Res: TPSLineInfoResults): Boolean;
+var
+ i,j: Longint;
+ linepos: Cardinal;
+ Item: TPSLineInfo;
+ lModuleName: tbtstring;
+begin
+ lModuleName := FastUpperCase(ModuleName);
+
+ for i := FItems.Count -1 downto 0 do
+ begin
+ Item := FItems[i];
+ if (Pos >= Item.StartPos) and (Pos < Item.EndPos) and
+ (lModuleName = '') or (lModuleName = Item.FileName) then
+ begin
+ Res.Name := Item.FileName;
+ Pos := Pos - Item.StartPos;
+ Res.Pos := Pos;
+ Res.Col := 1;
+ Res.Row := 1;
+ LinePos := 0;
+ for j := 0 to Item.LineOffsetCount -1 do
+ begin
+ if Pos >= Item.LineOffset[j] then
+ begin
+ linepos := Item.LineOffset[j];
+ end else
+ begin
+ Res.Row := j; // j -1, but line counting starts at 1
+ Res.Col := pos - linepos + 1;
+ Break;
+ end;
+ end;
+ Result := True;
+ exit;
+ end;
+ end;
+ Result := False;
+end;
+
+{ TPSLineInfo }
+
+constructor TPSLineInfo.Create;
+begin
+ inherited Create;
+ FLineOffsets := TIfList.Create;
+end;
+
+destructor TPSLineInfo.Destroy;
+begin
+ FLineOffsets.Free;
+ inherited Destroy;
+end;
+
+
+function TPSLineInfo.GetLineOffset(I: Integer): Cardinal;
+begin
+ Result := Longint(FLineOffsets[I]);
+end;
+
+function TPSLineInfo.GetLineOffsetCount: Longint;
+begin
+ result := FLineOffsets.Count;
+end;
+
+{ TPSPascalPreProcessorParser }
+
+procedure TPSPascalPreProcessorParser.Next;
+var
+ ci: Cardinal;
+
+begin
+ FPos := FPos + FLen;
+ case FText[FPos] of
+ #0:
+ begin
+ FLen := 0;
+ FTokenId := ptEof;
+ end;
+ '''':
+ begin
+ ci := FPos;
+ while (FText[ci] <> #0) do
+ begin
+ Inc(ci);
+ while FText[ci] = '''' do
+ begin
+ if FText[ci+1] <> '''' then Break;
+ inc(ci);
+ inc(ci);
+ end;
+ if FText[ci] = '''' then Break;
+ if FText[ci] = #13 then
+ begin
+ inc(FRow);
+ if FText[ci] = #10 then
+ inc(ci);
+ FLastEnterPos := ci -1;
+ if @FOnNewLine <> nil then FOnNewLine(Self, FRow, FPos - FLastEnterPos + 1, ci+1);
+ end else if FText[ci] = #10 then
+ begin
+ inc(FRow);
+ FLastEnterPos := ci -1;
+ if @FOnNewLine <> nil then FOnNewLine(Self, FRow, FPos - FLastEnterPos + 1, ci+1);
+ end;
+ end;
+ FLen := ci - FPos + 1;
+ FTokenId := ptOther;
+ end;
+ '(':
+ begin
+ if FText[FPos + 1] = '*' then
+ begin
+ ci := FPos + 1;
+ while (FText[ci] <> #0) do begin
+ if (FText[ci] = '*') and (FText[ci + 1] = ')') then
+ Break;
+ if FText[ci] = #13 then
+ begin
+ inc(FRow);
+ if FText[ci+1] = #10 then
+ inc(ci);
+ FLastEnterPos := ci -1;
+ if @FOnNewLine <> nil then FOnNewLine(Self, FRow, FPos - FLastEnterPos + 1, ci+1);
+ end else if FText[ci] = #10 then
+ begin
+ inc(FRow);
+ FLastEnterPos := ci -1;
+ if @FOnNewLine <> nil then FOnNewLine(Self, FRow, FPos - FLastEnterPos + 1, ci+1);
+ end;
+ Inc(ci);
+ end;
+ FTokenId := ptOther;
+ if (FText[ci] <> #0) then
+ Inc(ci, 2);
+ FLen := ci - FPos;
+ end
+ else
+ begin
+ FTokenId := ptOther;
+ FLen := 1;
+ end;
+ end;
+ '/':
+ begin
+ if FText[FPos + 1] = '/' then
+ begin
+ ci := FPos + 1;
+ while (FText[ci] <> #0) and (FText[ci] <> #13) and
+ (FText[ci] <> #10) do begin
+ Inc(ci);
+ end;
+ FTokenId := ptOther;
+ FLen := ci - FPos;
+ end else
+ begin
+ FTokenId := ptOther;
+ FLen := 1;
+ end;
+ end;
+ '{':
+ begin
+ ci := FPos + 1;
+ while (FText[ci] <> #0) and (FText[ci] <> '}') do begin
+ if FText[ci] = #13 then
+ begin
+ inc(FRow);
+ if FText[ci+1] = #10 then
+ inc(ci);
+ FLastEnterPos := ci - 1;
+ if @FOnNewLine <> nil then FOnNewLine(Self, FRow, FPos - FLastEnterPos + 1, ci+1);
+ end else if FText[ci] = #10 then
+ begin
+ inc(FRow);
+ FLastEnterPos := ci - 1;
+ if @FOnNewLine <> nil then FOnNewLine(Self, FRow, FPos - FLastEnterPos + 1, ci+1);
+ end;
+ Inc(ci);
+ end;
+ if (FText[FPos + 1] = '$') or (FText[FPos + 1] = '.') then
+ FTokenId := ptDefine
+ else
+ FTokenId := ptOther;
+
+ FLen := ci - FPos + 1;
+ end;
+ else
+ begin
+ ci := FPos + 1;
+ while not (FText[ci] in [#0,'{', '(', '''', '/']) do
+ begin
+ if FText[ci] = #13 then
+ begin
+ inc(FRow);
+ if FText[ci+1] = #10 then
+ inc(ci);
+ FLastEnterPos := ci - 1;
+ if @FOnNewLine <> nil then FOnNewLine(Self, FRow, FPos - FLastEnterPos + 1, ci+1);
+ end else if FText[ci] = #10 then
+ begin
+ inc(FRow);
+ FLastEnterPos := ci -1 ;
+ if @FOnNewLine <> nil then FOnNewLine(Self, FRow, FPos - FLastEnterPos + 1, ci+1);
+ end;
+ Inc(Ci);
+ end;
+ FTokenId := ptOther;
+ FLen := ci - FPos;
+ end;
+ end;
+ FCol := FPos - FLastEnterPos + 1;
+ FToken := Copy(FData, FPos +1, FLen);
+end;
+
+procedure TPSPascalPreProcessorParser.SetText(const dta: tbtstring);
+begin
+ FData := dta;
+ FText := pAnsichar(FData);
+ FLen := 0;
+ FPos := 0;
+ FCol := 1;
+ FLastEnterPos := 0;
+ FRow := 1;
+ if @FOnNewLine <> nil then FOnNewLine(Self, 1, 1, 0);
+ Next;
+end;
+
+{ TPSPreProcessor }
+
+procedure TPSPreProcessor.AdjustMessage(Msg: TPSPascalCompilerMessage);
+var
+ Res: TPSLineInfoResults;
+begin
+ if CurrentLineInfo.GetLineInfo(Msg.ModuleName, Msg.Pos, Res) then
+ begin
+ Msg.SetCustomPos(res.Pos, Res.Row, Res.Col);
+ Msg.ModuleName := Res.Name;
+ end;
+end;
+
+procedure TPSPreProcessor.AdjustMessages(Comp: TPSPascalCompiler);
+var
+ i: Longint;
+begin
+ for i := 0 to Comp.MsgCount -1 do
+ AdjustMessage (Comp.Msg[i]);
+end;
+
+procedure TPSPreProcessor.Clear;
+begin
+ FDefineState.Clear;
+ FDefines.Clear;
+ FCurrentDefines.Clear;
+ FCurrentLineInfo.Clear;
+ FMainFile := '';
+end;
+
+constructor TPSPreProcessor.Create;
+begin
+ inherited Create;
+ FDefines := TStringList.Create;
+ FCurrentLineInfo := TPSLineInfoList.Create;
+ FCurrentDefines := TStringList.Create;
+ FDefines.Duplicates := dupIgnore;
+ FCurrentDefines.Duplicates := dupIgnore;
+ FDefineState := TPSDefineStates.Create;
+ FMaxLevel := 20;
+
+ doAddStdPredefines;
+end;
+
+destructor TPSPreProcessor.Destroy;
+begin
+ FDefineState.Free;
+ FCurrentDefines.Free;
+ FDefines.Free;
+ FCurrentLineInfo.Free;
+ inherited Destroy;
+end;
+
+procedure TPSPreProcessor.doAddStdPredefines;
+begin
+ //--- 20050708_jgv
+ FCurrentDefines.Add (Format ('VER%d', [PSCurrentBuildNo]));
+ {$IFDEF CPU386 }
+ FCurrentDefines.Add ('CPU386');
+ {$ENDIF }
+ {$IFDEF MSWINDOWS }
+ FCurrentDefines.Add ('MSWINDOWS');
+ FCurrentDefines.Add ('WIN32');
+ {$ENDIF }
+ {$IFDEF LINUX }
+ FCurrentDefines.Add ('LINUX');
+ {$ENDIF }
+end;
+
+procedure TPSPreProcessor.IntPreProcess(Level: Integer; const OrgFileName: tbtstring; FileName: tbtstring; Dest: TStream);
+var
+ Parser: TPSPascalPreProcessorParser;
+ dta: tbtstring;
+ item: TPSLineInfo;
+ s, name: tbtstring;
+ current, i: Longint;
+ ds: TPSDefineState;
+ AppContinue: Boolean;
+begin
+ if Level > MaxLevel then raise EPSPreProcessor.CreateFmt(RPS_TooManyNestedInclude, [FileName, OrgFileName]);
+ Parser := TPSPascalPreProcessorParser.Create;
+ try
+ Parser.OnNewLine := ParserNewLine;
+ if FileName = MainFileName then
+ begin
+ dta := MainFile;
+ end else
+ if (@OnNeedFile = nil) or (not OnNeedFile(Self, OrgFileName, FileName, dta)) then
+ raise EPSPreProcessor.CreateFmt(RPS_IncludeNotFound, [FileName, OrgFileName]);
+ Item := FCurrentLineInfo.Add;
+ current := FCurrentLineInfo.Count -1;
+ FCurrentLineInfo.Current := current;
+ Item.FStartPos := Dest.Position;
+ Item.FFileName := FileName;
+ Parser.SetText(dta);
+ while Parser.TokenId <> ptEOF do
+ begin
+ s := Parser.Token;
+ if Parser.TokenId = ptDefine then
+ begin
+ Delete(s,1,2); // delete the {$
+ Delete(s,length(s), 1); // delete the }
+
+ //-- 20050707_jgv trim right
+ i := length (s);
+ while (i > 0) and (s[i] = ' ') do begin
+ Delete (s, i, 1);
+ Dec (i);
+ end;
+ //-- end_jgv
+
+ if pos(tbtChar(' '), s) = 0 then
+ begin
+ name := uppercase(s);
+ s := '';
+ end else
+ begin
+ Name := uppercase(copy(s,1,pos(' ', s)-1));
+ Delete(s, 1, pos(' ', s));
+ end;
+
+ //-- 20050707_jgv - ask the application
+ AppContinue := True;
+ If @OnProcessDirective <> Nil then OnProcessDirective (Self, Parser, FDefineState.DoWrite, name, s, AppContinue);
+
+ If AppContinue then
+ //-- end jgv
+
+ if (Name = 'I') or (Name = 'INCLUDE') or (Name = '.INCLUDE') then
+ begin
+ if FDefineState.DoWrite then
+ begin
+ FAddedPosition := 0;
+ IntPreProcess(Level +1, FileName, s, Dest);
+ FCurrentLineInfo.Current := current;
+ FAddedPosition := Cardinal(Dest.Position) - Item.StartPos - Parser.Pos;
+ end;
+ end else if (Name = 'DEFINE') then
+ begin
+ if FDefineState.DoWrite then
+ begin
+ if pos(' ', s) <> 0 then raise EPSPreProcessor.CreateFmt(RPS_DefineTooManyParameters, [Parser.Row, Parser.Col]);
+ FCurrentDefines.Add(Uppercase(S));
+ end;
+ end else if (Name = 'UNDEF') then
+ begin
+ if FDefineState.DoWrite then
+ begin
+ if pos(' ', s) <> 0 then raise EPSPreProcessor.CreateFmt(RPS_DefineTooManyParameters, [Parser.Row, Parser.Col]);
+ i := FCurrentDefines.IndexOf(Uppercase(s));
+ if i <> -1 then
+ FCurrentDefines.Delete(i);
+ end;
+ end else if (Name = 'IFDEF') then
+ begin
+ if pos(' ', s) <> 0 then raise EPSPreProcessor.CreateFmt(RPS_DefineTooManyParameters, [Parser.Row, Parser.Col]);
+ //JeromeWelsh - nesting fix
+ if (FDefineState.DoWrite and (FCurrentDefines.IndexOf(Uppercase(s)) <> -1)) then
+ FDefineState.Add.DoWrite := True
+ else
+ FDefineState.Add.DoWrite := False;
+ end else if (Name = 'IFNDEF') then
+ begin
+ if pos(' ', s) <> 0 then raise EPSPreProcessor.CreateFmt(RPS_DefineTooManyParameters, [Parser.Row, Parser.Col]);
+ //JeromeWelsh - nesting fix
+ if (FCurrentDefines.IndexOf(Uppercase(s)) = -1) and FDefineState.DoWrite then
+ FDefineState.Add.DoWrite := True
+ else
+ FDefineState.Add.DoWrite := False;
+ end else if (Name = 'ENDIF') then
+ begin
+ //- jgv remove - borland use it (sysutils.pas)
+ //- if s <> '' then raise EPSPreProcessor.CreateFmt(RPS_DefineTooManyParameters, [Parser.Row, Parser.Col]);
+ if FDefineState.Count = 0 then
+ raise EPSPreProcessor.CreateFmt(RPS_NoIfdefForEndif, [Parser.Row, Parser.Col]);
+ FDefineState.Delete(FDefineState.Count -1); // remove define from list
+ end else if (Name = 'ELSE') then
+ begin
+ if s<> '' then raise EPSPreProcessor.CreateFmt(RPS_DefineTooManyParameters, [Parser.Row, Parser.Col]);
+ if FDefineState.Count = 0 then
+ raise EPSPreProcessor.CreateFmt(RPS_NoIfdefForElse, [Parser.Row, Parser.Col]);
+ ds := FDefineState[FDefineState.Count -1];
+ if ds.InElse then
+ raise EPSPreProcessor.CreateFmt(RPS_ElseTwice, [Parser.Row, Parser.Col]);
+ ds.FInElse := True;
+ //JeromeWelsh - nesting fix
+ ds.DoWrite := not ds.DoWrite and FDefineState.DoPrevWrite;
+ end
+
+ //-- 20050710_jgv custom application error process
+ else if Parser.Token[2] <> '.' then begin
+ If @OnProcessUnknowDirective <> Nil then begin
+ OnProcessUnknowDirective (Self, Parser, FDefineState.DoWrite, name, s, AppContinue);
+ end;
+ If AppContinue then
+ //-- end jgv
+
+ raise EPSPreProcessor.CreateFmt(RPS_UnknownCompilerDirective, [Parser.Row, Parser.Col]);
+ end;
+ end;
+
+ if (not FDefineState.DoWrite) or (Parser.TokenId = ptDefine) then
+ begin
+ SetLength(s, Length(Parser.Token));
+ for i := length(s) downto 1 do
+ s[i] := #32; // space
+ end;
+ Dest.Write(s[1], length(s));
+ Parser.Next;
+ end;
+ Item.FEndPos := Dest.Position;
+ finally
+ Parser.Free;
+ end;
+end;
+
+procedure TPSPreProcessor.ParserNewLine(Sender: TPSPascalPreProcessorParser; Row, Col, Pos: Cardinal);
+begin
+ if FCurrentLineInfo.Current >= FCurrentLineInfo.Count then exit; //errr ???
+ with FCurrentLineInfo.Items[FCurrentLineInfo.Current] do
+ begin
+ Pos := Pos + FAddedPosition;
+ FLineOffsets.Add(Pointer(Pos));
+ end;
+end;
+
+procedure TPSPreProcessor.PreProcess(const Filename: tbtstring; var Output: tbtstring);
+var
+ Stream: TMemoryStream;
+begin
+ FAddedPosition := 0;
+ FCurrentDefines.Assign(FDefines);
+ Stream := TMemoryStream.Create;
+ try
+ IntPreProcess(0, '', FileName, Stream);
+ Stream.Position := 0;
+ SetLength(Output, Stream.Size);
+ Stream.Read(Output[1], Length(Output));
+ finally
+ Stream.Free;
+ end;
+ if FDefineState.Count <> 0 then
+ raise EPSPreProcessor.Create(RPs_DefineNotClosed);
+end;
+
+{ TPSDefineStates }
+
+function TPSDefineStates.Add: TPSDefineState;
+begin
+ Result := TPSDefineState.Create;
+ FItems.Add(Result);
+end;
+
+procedure TPSDefineStates.Clear;
+var
+ i: Longint;
+begin
+ for i := Longint(FItems.Count) -1 downto 0 do
+ TPSDefineState(FItems[i]).Free;
+ FItems.Clear;
+end;
+
+constructor TPSDefineStates.Create;
+begin
+ inherited Create;
+ FItems := TIfList.Create;
+end;
+
+procedure TPSDefineStates.Delete(I: Integer);
+begin
+ TPSDefineState(FItems[i]).Free;
+ FItems.Delete(i);
+end;
+
+destructor TPSDefineStates.Destroy;
+var
+ i: Longint;
+begin
+ for i := Longint(FItems.Count) -1 downto 0 do
+ TPSDefineState(FItems[i]).Free;
+ FItems.Free;
+ inherited Destroy;
+end;
+
+function TPSDefineStates.GetCount: Longint;
+begin
+ Result := FItems.Count;
+end;
+
+function TPSDefineStates.GetItem(I: Integer): TPSDefineState;
+begin
+ Result := FItems[i];
+end;
+
+function TPSDefineStates.GetWrite: Boolean;
+begin
+ if FItems.Count = 0 then
+ result := true
+ else Result := TPSDefineState(FItems[FItems.Count -1]).DoWrite;
+end;
+
+//JeromeWelsh - nesting fix
+function TPSDefineStates.GetPrevWrite: Boolean;
+begin
+ if FItems.Count < 2 then
+ result := true
+ else Result := TPSDefineState(FItems[FItems.Count -2]).DoWrite;
+end;
+
+end.
+
diff --git a/branches/script-component/Units/PascalScript/uPSR_DB.pas b/branches/script-component/Units/PascalScript/uPSR_DB.pas
new file mode 100644
index 0000000..9d9350c
--- /dev/null
+++ b/branches/script-component/Units/PascalScript/uPSR_DB.pas
@@ -0,0 +1,2094 @@
+{runtime DB support}
+Unit uPSR_DB;
+{$I PascalScript.inc}
+Interface
+Uses uPSRuntime, uPSUtils, SysUtils;
+
+procedure RIRegisterTDATASET(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTPARAMS(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTPARAM(Cl: TPSRuntimeClassImporter);
+
+{$IFNDEF FPC}
+procedure RIRegisterTGUIDFIELD(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTVARIANTFIELD(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTREFERENCEFIELD(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTDATASETFIELD(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTARRAYFIELD(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTADTFIELD(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTOBJECTFIELD(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTWIDESTRINGFIELD(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTFIELDLIST(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTFIELDDEFLIST(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTFLATLIST(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTDEFCOLLECTION(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTNAMEDITEM(Cl: TPSRuntimeClassImporter);
+
+{$IFDEF DELPHI6UP}
+procedure RIRegisterTFMTBCDFIELD(Cl: TPSRuntimeClassImporter);
+{$ENDIF}
+procedure RIRegisterTBCDFIELD(Cl: TPSRuntimeClassImporter);
+
+{$ENDIF}
+
+procedure RIRegisterTGRAPHICFIELD(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTMEMOFIELD(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTBLOBFIELD(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTVARBYTESFIELD(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTBYTESFIELD(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTBINARYFIELD(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTTIMEFIELD(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTDATEFIELD(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTDATETIMEFIELD(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTBOOLEANFIELD(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTCURRENCYFIELD(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTFLOATFIELD(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTAUTOINCFIELD(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTWORDFIELD(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTLARGEINTFIELD(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTSMALLINTFIELD(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTINTEGERFIELD(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTNUMERICFIELD(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTSTRINGFIELD(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTFIELD(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTLOOKUPLIST(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTFIELDS(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTINDEXDEFS(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTINDEXDEF(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTFIELDDEFS(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTFIELDDEF(Cl: TPSRuntimeClassImporter);
+procedure RIRegister_DB(CL: TPSRuntimeClassImporter);
+
+implementation
+Uses DB, {$IFDEF DELPHI6UP}{$IFNDEF FPC}FMTBcd, MaskUtils,{$ENDIF}{$ENDIF}Classes;
+
+procedure TDATASETONPOSTERROR_W(Self: TDATASET; const T: TDATASETERROREVENT);
+begin Self.ONPOSTERROR := T; end;
+
+procedure TDATASETONPOSTERROR_R(Self: TDATASET; var T: TDATASETERROREVENT);
+begin T := Self.ONPOSTERROR; end;
+
+procedure TDATASETONNEWRECORD_W(Self: TDATASET; const T: TDATASETNOTIFYEVENT);
+begin Self.ONNEWRECORD := T; end;
+
+procedure TDATASETONNEWRECORD_R(Self: TDATASET; var T: TDATASETNOTIFYEVENT);
+begin T := Self.ONNEWRECORD; end;
+
+procedure TDATASETONFILTERRECORD_W(Self: TDATASET; const T: TFILTERRECORDEVENT);
+begin Self.ONFILTERRECORD := T; end;
+
+procedure TDATASETONFILTERRECORD_R(Self: TDATASET; var T: TFILTERRECORDEVENT);
+begin T := Self.ONFILTERRECORD; end;
+
+procedure TDATASETONEDITERROR_W(Self: TDATASET; const T: TDATASETERROREVENT);
+begin Self.ONEDITERROR := T; end;
+
+procedure TDATASETONEDITERROR_R(Self: TDATASET; var T: TDATASETERROREVENT);
+begin T := Self.ONEDITERROR; end;
+
+procedure TDATASETONDELETEERROR_W(Self: TDATASET; const T: TDATASETERROREVENT);
+begin Self.ONDELETEERROR := T; end;
+
+procedure TDATASETONDELETEERROR_R(Self: TDATASET; var T: TDATASETERROREVENT);
+begin T := Self.ONDELETEERROR; end;
+
+procedure TDATASETONCALCFIELDS_W(Self: TDATASET; const T: TDATASETNOTIFYEVENT);
+begin Self.ONCALCFIELDS := T; end;
+
+procedure TDATASETONCALCFIELDS_R(Self: TDATASET; var T: TDATASETNOTIFYEVENT);
+begin T := Self.ONCALCFIELDS; end;
+
+{$IFNDEF FPC}
+procedure TDATASETAFTERREFRESH_W(Self: TDATASET; const T: TDATASETNOTIFYEVENT);
+begin Self.AFTERREFRESH := T; end;
+
+procedure TDATASETAFTERREFRESH_R(Self: TDATASET; var T: TDATASETNOTIFYEVENT);
+begin T := Self.AFTERREFRESH; end;
+
+procedure TDATASETBEFOREREFRESH_W(Self: TDATASET; const T: TDATASETNOTIFYEVENT);
+begin Self.BEFOREREFRESH := T; end;
+
+procedure TDATASETBEFOREREFRESH_R(Self: TDATASET; var T: TDATASETNOTIFYEVENT);
+begin T := Self.BEFOREREFRESH; end;
+
+{$ENDIF}
+
+procedure TDATASETAFTERSCROLL_W(Self: TDATASET; const T: TDATASETNOTIFYEVENT);
+begin Self.AFTERSCROLL := T; end;
+
+procedure TDATASETAFTERSCROLL_R(Self: TDATASET; var T: TDATASETNOTIFYEVENT);
+begin T := Self.AFTERSCROLL; end;
+
+procedure TDATASETBEFORESCROLL_W(Self: TDATASET; const T: TDATASETNOTIFYEVENT);
+begin Self.BEFORESCROLL := T; end;
+
+procedure TDATASETBEFORESCROLL_R(Self: TDATASET; var T: TDATASETNOTIFYEVENT);
+begin T := Self.BEFORESCROLL; end;
+
+procedure TDATASETAFTERDELETE_W(Self: TDATASET; const T: TDATASETNOTIFYEVENT);
+begin Self.AFTERDELETE := T; end;
+
+procedure TDATASETAFTERDELETE_R(Self: TDATASET; var T: TDATASETNOTIFYEVENT);
+begin T := Self.AFTERDELETE; end;
+
+procedure TDATASETBEFOREDELETE_W(Self: TDATASET; const T: TDATASETNOTIFYEVENT);
+begin Self.BEFOREDELETE := T; end;
+
+procedure TDATASETBEFOREDELETE_R(Self: TDATASET; var T: TDATASETNOTIFYEVENT);
+begin T := Self.BEFOREDELETE; end;
+
+procedure TDATASETAFTERCANCEL_W(Self: TDATASET; const T: TDATASETNOTIFYEVENT);
+begin Self.AFTERCANCEL := T; end;
+
+procedure TDATASETAFTERCANCEL_R(Self: TDATASET; var T: TDATASETNOTIFYEVENT);
+begin T := Self.AFTERCANCEL; end;
+
+procedure TDATASETBEFORECANCEL_W(Self: TDATASET; const T: TDATASETNOTIFYEVENT);
+begin Self.BEFORECANCEL := T; end;
+
+procedure TDATASETBEFORECANCEL_R(Self: TDATASET; var T: TDATASETNOTIFYEVENT);
+begin T := Self.BEFORECANCEL; end;
+
+procedure TDATASETAFTERPOST_W(Self: TDATASET; const T: TDATASETNOTIFYEVENT);
+begin Self.AFTERPOST := T; end;
+
+procedure TDATASETAFTERPOST_R(Self: TDATASET; var T: TDATASETNOTIFYEVENT);
+begin T := Self.AFTERPOST; end;
+
+procedure TDATASETBEFOREPOST_W(Self: TDATASET; const T: TDATASETNOTIFYEVENT);
+begin Self.BEFOREPOST := T; end;
+
+procedure TDATASETBEFOREPOST_R(Self: TDATASET; var T: TDATASETNOTIFYEVENT);
+begin T := Self.BEFOREPOST; end;
+
+procedure TDATASETAFTEREDIT_W(Self: TDATASET; const T: TDATASETNOTIFYEVENT);
+begin Self.AFTEREDIT := T; end;
+
+procedure TDATASETAFTEREDIT_R(Self: TDATASET; var T: TDATASETNOTIFYEVENT);
+begin T := Self.AFTEREDIT; end;
+
+procedure TDATASETBEFOREEDIT_W(Self: TDATASET; const T: TDATASETNOTIFYEVENT);
+begin Self.BEFOREEDIT := T; end;
+
+procedure TDATASETBEFOREEDIT_R(Self: TDATASET; var T: TDATASETNOTIFYEVENT);
+begin T := Self.BEFOREEDIT; end;
+
+procedure TDATASETAFTERINSERT_W(Self: TDATASET; const T: TDATASETNOTIFYEVENT);
+begin Self.AFTERINSERT := T; end;
+
+procedure TDATASETAFTERINSERT_R(Self: TDATASET; var T: TDATASETNOTIFYEVENT);
+begin T := Self.AFTERINSERT; end;
+
+procedure TDATASETBEFOREINSERT_W(Self: TDATASET; const T: TDATASETNOTIFYEVENT);
+begin Self.BEFOREINSERT := T; end;
+
+procedure TDATASETBEFOREINSERT_R(Self: TDATASET; var T: TDATASETNOTIFYEVENT);
+begin T := Self.BEFOREINSERT; end;
+
+procedure TDATASETAFTERCLOSE_W(Self: TDATASET; const T: TDATASETNOTIFYEVENT);
+begin Self.AFTERCLOSE := T; end;
+
+procedure TDATASETAFTERCLOSE_R(Self: TDATASET; var T: TDATASETNOTIFYEVENT);
+begin T := Self.AFTERCLOSE; end;
+
+procedure TDATASETBEFORECLOSE_W(Self: TDATASET; const T: TDATASETNOTIFYEVENT);
+begin Self.BEFORECLOSE := T; end;
+
+procedure TDATASETBEFORECLOSE_R(Self: TDATASET; var T: TDATASETNOTIFYEVENT);
+begin T := Self.BEFORECLOSE; end;
+
+procedure TDATASETAFTEROPEN_W(Self: TDATASET; const T: TDATASETNOTIFYEVENT);
+begin Self.AFTEROPEN := T; end;
+
+procedure TDATASETAFTEROPEN_R(Self: TDATASET; var T: TDATASETNOTIFYEVENT);
+begin T := Self.AFTEROPEN; end;
+
+procedure TDATASETBEFOREOPEN_W(Self: TDATASET; const T: TDATASETNOTIFYEVENT);
+begin Self.BEFOREOPEN := T; end;
+
+procedure TDATASETBEFOREOPEN_R(Self: TDATASET; var T: TDATASETNOTIFYEVENT);
+begin T := Self.BEFOREOPEN; end;
+
+procedure TDATASETAUTOCALCFIELDS_W(Self: TDATASET; const T: BOOLEAN);
+begin Self.AUTOCALCFIELDS := T; end;
+
+procedure TDATASETAUTOCALCFIELDS_R(Self: TDATASET; var T: BOOLEAN);
+begin T := Self.AUTOCALCFIELDS; end;
+
+procedure TDATASETACTIVE_W(Self: TDATASET; const T: BOOLEAN);
+begin Self.ACTIVE := T; end;
+
+procedure TDATASETACTIVE_R(Self: TDATASET; var T: BOOLEAN);
+begin T := Self.ACTIVE; end;
+
+procedure TDATASETFILTEROPTIONS_W(Self: TDATASET; const T: TFILTEROPTIONS);
+begin Self.FILTEROPTIONS := T; end;
+
+procedure TDATASETFILTEROPTIONS_R(Self: TDATASET; var T: TFILTEROPTIONS);
+begin T := Self.FILTEROPTIONS; end;
+
+procedure TDATASETFILTERED_W(Self: TDATASET; const T: BOOLEAN);
+begin Self.FILTERED := T; end;
+
+procedure TDATASETFILTERED_R(Self: TDATASET; var T: BOOLEAN);
+begin T := Self.FILTERED; end;
+
+procedure TDATASETFILTER_W(Self: TDATASET; const T: String);
+begin Self.FILTER := T; end;
+
+procedure TDATASETFILTER_R(Self: TDATASET; var T: String);
+begin T := Self.FILTER; end;
+
+procedure TDATASETSTATE_R(Self: TDATASET; var T: TDATASETSTATE);
+begin T := Self.STATE; end;
+
+{$IFNDEF FPC}
+procedure TDATASETSPARSEARRAYS_W(Self: TDATASET; const T: BOOLEAN);
+begin Self.SPARSEARRAYS := T; end;
+
+procedure TDATASETSPARSEARRAYS_R(Self: TDATASET; var T: BOOLEAN);
+begin T := Self.SPARSEARRAYS; end;
+{$ENDIF}
+
+procedure TDATASETRECORDSIZE_R(Self: TDATASET; var T: WORD);
+begin T := Self.RECORDSIZE; end;
+
+procedure TDATASETRECNO_W(Self: TDATASET; const T: INTEGER);
+begin Self.RECNO := T; end;
+
+procedure TDATASETRECNO_R(Self: TDATASET; var T: INTEGER);
+begin T := Self.RECNO; end;
+
+procedure TDATASETRECORDCOUNT_R(Self: TDATASET; var T: INTEGER);
+begin T := Self.RECORDCOUNT; end;
+
+{$IFNDEF FPC}
+procedure TDATASETOBJECTVIEW_W(Self: TDATASET; const T: BOOLEAN);
+begin Self.OBJECTVIEW := T; end;
+
+procedure TDATASETOBJECTVIEW_R(Self: TDATASET; var T: BOOLEAN);
+begin T := Self.OBJECTVIEW; end;
+{$ENDIF}
+
+procedure TDATASETMODIFIED_R(Self: TDATASET; var T: BOOLEAN);
+begin T := Self.MODIFIED; end;
+
+{$IFDEF DELPHI6UP}
+procedure TDATASETISUNIDIRECTIONAL_R(Self: TDATASET; var T: BOOLEAN);
+begin T := Self.ISUNIDIRECTIONAL; end;
+{$ENDIF}
+
+procedure TDATASETFOUND_R(Self: TDATASET; var T: BOOLEAN);
+begin T := Self.FOUND; end;
+
+procedure TDATASETFIELDVALUES_W(Self: TDATASET; const T: VARIANT; const t1: String);
+begin Self.FIELDVALUES[t1] := T; end;
+
+procedure TDATASETFIELDVALUES_R(Self: TDATASET; var T: VARIANT; const t1: String);
+begin T := Self.FIELDVALUES[t1]; end;
+
+procedure TDATASETFIELDS_R(Self: TDATASET; var T: TFIELDS);
+begin T := Self.FIELDS; end;
+
+{$IFNDEF FPC}
+
+procedure TDATASETFIELDLIST_R(Self: TDATASET; var T: TFIELDLIST);
+begin T := Self.FIELDLIST; end;
+
+
+procedure TDATASETFIELDDEFLIST_R(Self: TDATASET; var T: TFIELDDEFLIST);
+begin T := Self.FIELDDEFLIST; end;
+
+procedure TDATASETFIELDDEFS_W(Self: TDATASET; const T: TFIELDDEFS);
+begin Self.FIELDDEFS := T; end;
+
+procedure TDATASETFIELDDEFS_R(Self: TDATASET; var T: TFIELDDEFS);
+begin T := Self.FIELDDEFS; end;
+
+procedure TDATASETBLOCKREADSIZE_W(Self: TDATASET; const T: INTEGER);
+begin Self.BLOCKREADSIZE := T; end;
+
+procedure TDATASETBLOCKREADSIZE_R(Self: TDATASET; var T: INTEGER);
+begin T := Self.BLOCKREADSIZE; end;
+
+procedure TDATASETDESIGNER_R(Self: TDATASET; var T: TDATASETDESIGNER);
+begin T := Self.DESIGNER; end;
+
+
+procedure TDATASETDATASETFIELD_W(Self: TDATASET; const T: TDATASETFIELD);
+begin Self.DATASETFIELD := T; end;
+
+
+
+procedure TDATASETDATASETFIELD_R(Self: TDATASET; var T: TDATASETFIELD);
+begin T := Self.DATASETFIELD; end;
+
+
+procedure TDATASETAGGFIELDS_R(Self: TDATASET; var T: TFIELDS);
+begin T := Self.AGGFIELDS; end;
+
+
+
+{$ENDIF}
+
+procedure TDATASETFIELDCOUNT_R(Self: TDATASET; var T: INTEGER);
+begin T := Self.FIELDCOUNT; end;
+
+
+procedure TDATASETEOF_R(Self: TDATASET; var T: BOOLEAN);
+begin T := Self.EOF; end;
+
+procedure TDATASETDEFAULTFIELDS_R(Self: TDATASET; var T: BOOLEAN);
+begin T := Self.DEFAULTFIELDS; end;
+
+procedure TDATASETDATASOURCE_R(Self: TDATASET; var T: TDATASOURCE);
+begin T := Self.DATASOURCE; end;
+
+
+
+procedure TDATASETCANMODIFY_R(Self: TDATASET; var T: BOOLEAN);
+begin T := Self.CANMODIFY; end;
+
+//procedure TDATASETBOOKMARK_W(Self: TDATASET; const T: TBOOKMARKSTR);
+//begin Self.BOOKMARK := T; end;
+
+//procedure TDATASETBOOKMARK_R(Self: TDATASET; var T: TBOOKMARKSTR);
+//begin T := Self.BOOKMARK; end;
+
+procedure TDATASETBOF_R(Self: TDATASET; var T: BOOLEAN);
+begin T := Self.BOF; end;
+
+procedure TPARAMSPARAMVALUES_W(Self: TPARAMS; const T: VARIANT; const t1: String);
+begin Self.PARAMVALUES[t1] := T; end;
+
+procedure TPARAMSPARAMVALUES_R(Self: TPARAMS; var T: VARIANT; const t1: String);
+begin T := Self.PARAMVALUES[t1]; end;
+
+procedure TPARAMSITEMS_W(Self: TPARAMS; const T: TPARAM; const t1: INTEGER);
+begin Self.ITEMS[t1] := T; end;
+
+procedure TPARAMSITEMS_R(Self: TPARAMS; var T: TPARAM; const t1: INTEGER);
+begin T := Self.ITEMS[t1]; end;
+
+procedure TPARAMVALUE_W(Self: TPARAM; const T: VARIANT);
+begin Self.VALUE := T; end;
+
+procedure TPARAMVALUE_R(Self: TPARAM; var T: VARIANT);
+begin T := Self.VALUE; end;
+
+
+{$IFDEF DELPHI6UP}
+procedure TPARAMSIZE_W(Self: TPARAM; const T: INTEGER);
+begin Self.SIZE := T; end;
+
+procedure TPARAMSIZE_R(Self: TPARAM; var T: INTEGER);
+begin T := Self.SIZE; end;
+{$ENDIF}
+
+procedure TPARAMPARAMTYPE_W(Self: TPARAM; const T: TPARAMTYPE);
+begin Self.PARAMTYPE := T; end;
+
+procedure TPARAMPARAMTYPE_R(Self: TPARAM; var T: TPARAMTYPE);
+begin T := Self.PARAMTYPE; end;
+
+procedure TPARAMNAME_W(Self: TPARAM; const T: String);
+begin Self.NAME := T; end;
+
+procedure TPARAMNAME_R(Self: TPARAM; var T: String);
+begin T := Self.NAME; end;
+
+{$IFDEF DELPHI6UP}
+procedure TPARAMNUMERICSCALE_W(Self: TPARAM; const T: INTEGER);
+begin Self.NUMERICSCALE := T; end;
+
+procedure TPARAMNUMERICSCALE_R(Self: TPARAM; var T: INTEGER);
+begin T := Self.NUMERICSCALE; end;
+{$ENDIF}
+{$IFDEF DELPHI6UP}
+
+procedure TPARAMPRECISION_W(Self: TPARAM; const T: INTEGER);
+begin Self.PRECISION := T; end;
+
+procedure TPARAMPRECISION_R(Self: TPARAM; var T: INTEGER);
+begin T := Self.PRECISION; end;
+{$ENDIF}
+procedure TPARAMDATATYPE_W(Self: TPARAM; const T: TFIELDTYPE);
+begin Self.DATATYPE := T; end;
+
+procedure TPARAMDATATYPE_R(Self: TPARAM; var T: TFIELDTYPE);
+begin T := Self.DATATYPE; end;
+
+procedure TPARAMTEXT_W(Self: TPARAM; const T: String);
+begin Self.TEXT := T; end;
+
+procedure TPARAMTEXT_R(Self: TPARAM; var T: String);
+begin T := Self.TEXT; end;
+
+procedure TPARAMNATIVESTR_W(Self: TPARAM; const T: String);
+begin Self.NATIVESTR := T; end;
+
+procedure TPARAMNATIVESTR_R(Self: TPARAM; var T: String);
+begin T := Self.NATIVESTR; end;
+
+procedure TPARAMISNULL_R(Self: TPARAM; var T: BOOLEAN);
+begin T := Self.ISNULL; end;
+
+procedure TPARAMBOUND_W(Self: TPARAM; const T: BOOLEAN);
+begin Self.BOUND := T; end;
+
+procedure TPARAMBOUND_R(Self: TPARAM; var T: BOOLEAN);
+begin T := Self.BOUND; end;
+
+procedure TPARAMASWORD_W(Self: TPARAM; const T: LONGINT);
+begin Self.ASWORD := T; end;
+
+procedure TPARAMASWORD_R(Self: TPARAM; var T: LONGINT);
+begin T := Self.ASWORD; end;
+
+procedure TPARAMASTIME_W(Self: TPARAM; const T: TDATETIME);
+begin Self.ASTIME := T; end;
+
+procedure TPARAMASTIME_R(Self: TPARAM; var T: TDATETIME);
+begin T := Self.ASTIME; end;
+
+procedure TPARAMASSTRING_W(Self: TPARAM; const T: String);
+begin Self.ASSTRING := T; end;
+
+procedure TPARAMASSTRING_R(Self: TPARAM; var T: String);
+begin T := Self.ASSTRING; end;
+
+procedure TPARAMASMEMO_W(Self: TPARAM; const T: String);
+begin Self.ASMEMO := T; end;
+
+procedure TPARAMASMEMO_R(Self: TPARAM; var T: String);
+begin T := Self.ASMEMO; end;
+
+procedure TPARAMASSMALLINT_W(Self: TPARAM; const T: LONGINT);
+begin Self.ASSMALLINT := T; end;
+
+procedure TPARAMASSMALLINT_R(Self: TPARAM; var T: LONGINT);
+begin T := Self.ASSMALLINT; end;
+
+procedure TPARAMASINTEGER_W(Self: TPARAM; const T: LONGINT);
+begin Self.ASINTEGER := T; end;
+
+procedure TPARAMASINTEGER_R(Self: TPARAM; var T: LONGINT);
+begin T := Self.ASINTEGER; end;
+
+procedure TPARAMASFLOAT_W(Self: TPARAM; const T: DOUBLE);
+begin Self.ASFLOAT := T; end;
+
+procedure TPARAMASFLOAT_R(Self: TPARAM; var T: DOUBLE);
+begin T := Self.ASFLOAT; end;
+
+procedure TPARAMASDATETIME_W(Self: TPARAM; const T: TDATETIME);
+begin Self.ASDATETIME := T; end;
+
+procedure TPARAMASDATETIME_R(Self: TPARAM; var T: TDATETIME);
+begin T := Self.ASDATETIME; end;
+
+procedure TPARAMASDATE_W(Self: TPARAM; const T: TDATETIME);
+begin Self.ASDATE := T; end;
+
+procedure TPARAMASDATE_R(Self: TPARAM; var T: TDATETIME);
+begin T := Self.ASDATE; end;
+
+procedure TPARAMASCURRENCY_W(Self: TPARAM; const T: CURRENCY);
+begin Self.ASCURRENCY := T; end;
+
+procedure TPARAMASCURRENCY_R(Self: TPARAM; var T: CURRENCY);
+begin T := Self.ASCURRENCY; end;
+
+procedure TPARAMASBOOLEAN_W(Self: TPARAM; const T: BOOLEAN);
+begin Self.ASBOOLEAN := T; end;
+
+procedure TPARAMASBOOLEAN_R(Self: TPARAM; var T: BOOLEAN);
+begin T := Self.ASBOOLEAN; end;
+
+procedure TPARAMASBLOB_W(Self: TPARAM; const T: TBLOBDATA);
+begin Self.ASBLOB := T; end;
+
+procedure TPARAMASBLOB_R(Self: TPARAM; var T: TBLOBDATA);
+begin T := Self.ASBLOB; end;
+
+{$IFNDEF FPC}
+
+{$IFDEF DELPHI6UP}
+procedure TPARAMASFMTBCD_W(Self: TPARAM; const T: TBCD);
+begin Self.ASFMTBCD := T; end;
+
+procedure TPARAMASFMTBCD_R(Self: TPARAM; var T: TBCD);
+begin T := Self.ASFMTBCD; end;
+{$ENDIF}
+procedure TPARAMASBCD_W(Self: TPARAM; const T: CURRENCY);
+begin Self.ASBCD := T; end;
+
+procedure TPARAMASBCD_R(Self: TPARAM; var T: CURRENCY);
+begin T := Self.ASBCD; end;
+
+procedure TREFERENCEFIELDREFERENCETABLENAME_W(Self: TREFERENCEFIELD; const T: String);
+begin Self.REFERENCETABLENAME := T; end;
+
+procedure TREFERENCEFIELDREFERENCETABLENAME_R(Self: TREFERENCEFIELD; var T: String);
+begin T := Self.REFERENCETABLENAME; end;
+
+
+procedure TDATASETFIELDINCLUDEOBJECTFIELD_W(Self: TDATASETFIELD; const T: BOOLEAN);
+begin Self.INCLUDEOBJECTFIELD := T; end;
+
+procedure TDATASETFIELDINCLUDEOBJECTFIELD_R(Self: TDATASETFIELD; var T: BOOLEAN);
+begin T := Self.INCLUDEOBJECTFIELD; end;
+
+procedure TDATASETFIELDNESTEDDATASET_R(Self: TDATASETFIELD; var T: TDATASET);
+begin T := Self.NESTEDDATASET; end;
+
+procedure TOBJECTFIELDOBJECTTYPE_W(Self: TOBJECTFIELD; const T: String);
+begin Self.OBJECTTYPE := T; end;
+
+procedure TOBJECTFIELDOBJECTTYPE_R(Self: TOBJECTFIELD; var T: String);
+begin T := Self.OBJECTTYPE; end;
+
+procedure TOBJECTFIELDUNNAMED_R(Self: TOBJECTFIELD; var T: BOOLEAN);
+begin T := Self.UNNAMED; end;
+
+procedure TOBJECTFIELDFIELDVALUES_W(Self: TOBJECTFIELD; const T: VARIANT; const t1: INTEGER);
+begin Self.FIELDVALUES[t1] := T; end;
+
+procedure TOBJECTFIELDFIELDVALUES_R(Self: TOBJECTFIELD; var T: VARIANT; const t1: INTEGER);
+begin T := Self.FIELDVALUES[t1]; end;
+
+procedure TOBJECTFIELDFIELDS_R(Self: TOBJECTFIELD; var T: TFIELDS);
+begin T := Self.FIELDS; end;
+
+procedure TOBJECTFIELDFIELDCOUNT_R(Self: TOBJECTFIELD; var T: INTEGER);
+begin T := Self.FIELDCOUNT; end;
+{$ENDIF}
+
+
+{$IFNDEF FPC}
+{$IFDEF DELPHI6UP}
+procedure TBLOBFIELDGRAPHICHEADER_W(Self: TBLOBFIELD; const T: BOOLEAN);
+begin Self.GRAPHICHEADER := T; end;
+
+procedure TBLOBFIELDGRAPHICHEADER_R(Self: TBLOBFIELD; var T: BOOLEAN);
+begin T := Self.GRAPHICHEADER; end;
+{$ENDIF}
+{$ENDIF}
+
+procedure TBLOBFIELDBLOBTYPE_W(Self: TBLOBFIELD; const T: TBLOBTYPE);
+begin Self.BLOBTYPE := T; end;
+
+procedure TBLOBFIELDBLOBTYPE_R(Self: TBLOBFIELD; var T: TBLOBTYPE);
+begin T := Self.BLOBTYPE; end;
+
+procedure TBLOBFIELDTRANSLITERATE_W(Self: TBLOBFIELD; const T: BOOLEAN);
+begin Self.TRANSLITERATE := T; end;
+
+procedure TBLOBFIELDTRANSLITERATE_R(Self: TBLOBFIELD; var T: BOOLEAN);
+begin T := Self.TRANSLITERATE; end;
+
+procedure TBLOBFIELDVALUE_W(Self: TBLOBFIELD; const T: String);
+{$IFDEF DELPHI2009UP}
+var
+ b: TBytes;
+begin
+ setLEngth(b, Length(T));
+ Move(T[1], b[0], Length(T));
+ self.Value := b;
+ {$ELSE}
+begin
+ Self.VALUE := T;
+ {$ENDIF}
+end;
+
+procedure TBLOBFIELDVALUE_R(Self: TBLOBFIELD; var T: String);
+begin
+{$IFDEF DELPHI2009UP}
+ SetLength(t, Length(SElf.Value));
+ Move(Self.Value[0], t[1], LEngth(T));
+{$ELSE}
+ T := Self.VALUE;
+{$ENDIF}
+end;
+
+procedure TBLOBFIELDMODIFIED_W(Self: TBLOBFIELD; const T: BOOLEAN);
+begin Self.MODIFIED := T; end;
+
+procedure TBLOBFIELDMODIFIED_R(Self: TBLOBFIELD; var T: BOOLEAN);
+begin T := Self.MODIFIED; end;
+
+procedure TBLOBFIELDBLOBSIZE_R(Self: TBLOBFIELD; var T: INTEGER);
+begin T := Self.BLOBSIZE; end;
+
+{$IFNDEF FPC}
+{$IFDEF DELPHI6UP}
+procedure TFMTBCDFIELDPRECISION_W(Self: TFMTBCDFIELD; const T: INTEGER);
+begin Self.PRECISION := T; end;
+
+procedure TFMTBCDFIELDPRECISION_R(Self: TFMTBCDFIELD; var T: INTEGER);
+begin T := Self.PRECISION; end;
+
+procedure TFMTBCDFIELDMINVALUE_W(Self: TFMTBCDFIELD; const T: String);
+begin Self.MINVALUE := T; end;
+
+procedure TFMTBCDFIELDMINVALUE_R(Self: TFMTBCDFIELD; var T: String);
+begin T := Self.MINVALUE; end;
+
+procedure TFMTBCDFIELDMAXVALUE_W(Self: TFMTBCDFIELD; const T: String);
+begin Self.MAXVALUE := T; end;
+
+procedure TFMTBCDFIELDMAXVALUE_R(Self: TFMTBCDFIELD; var T: String);
+begin T := Self.MAXVALUE; end;
+
+procedure TFMTBCDFIELDCURRENCY_W(Self: TFMTBCDFIELD; const T: BOOLEAN);
+begin Self.CURRENCY := T; end;
+
+procedure TFMTBCDFIELDCURRENCY_R(Self: TFMTBCDFIELD; var T: BOOLEAN);
+begin T := Self.CURRENCY; end;
+
+procedure TFMTBCDFIELDVALUE_W(Self: TFMTBCDFIELD; const T: TBCD);
+begin Self.VALUE := T; end;
+
+procedure TFMTBCDFIELDVALUE_R(Self: TFMTBCDFIELD; var T: TBCD);
+begin T := Self.VALUE; end;
+{$ENDIF}
+
+procedure TBCDFIELDPRECISION_W(Self: TBCDFIELD; const T: INTEGER);
+begin Self.PRECISION := T; end;
+
+procedure TBCDFIELDPRECISION_R(Self: TBCDFIELD; var T: INTEGER);
+begin T := Self.PRECISION; end;
+
+procedure TBCDFIELDMINVALUE_W(Self: TBCDFIELD; const T: CURRENCY);
+begin Self.MINVALUE := T; end;
+
+procedure TBCDFIELDMINVALUE_R(Self: TBCDFIELD; var T: CURRENCY);
+begin T := Self.MINVALUE; end;
+
+procedure TBCDFIELDMAXVALUE_W(Self: TBCDFIELD; const T: CURRENCY);
+begin Self.MAXVALUE := T; end;
+
+procedure TBCDFIELDMAXVALUE_R(Self: TBCDFIELD; var T: CURRENCY);
+begin T := Self.MAXVALUE; end;
+
+procedure TBCDFIELDCURRENCY_W(Self: TBCDFIELD; const T: BOOLEAN);
+begin Self.CURRENCY := T; end;
+
+procedure TBCDFIELDCURRENCY_R(Self: TBCDFIELD; var T: BOOLEAN);
+begin T := Self.CURRENCY; end;
+
+procedure TBCDFIELDVALUE_W(Self: TBCDFIELD; const T: CURRENCY);
+begin Self.VALUE := T; end;
+
+procedure TBCDFIELDVALUE_R(Self: TBCDFIELD; var T: CURRENCY);
+begin T := Self.VALUE; end;
+{$ENDIF}
+
+
+procedure TDATETIMEFIELDDISPLAYFORMAT_W(Self: TDATETIMEFIELD; const T: String);
+begin Self.DISPLAYFORMAT := T; end;
+
+procedure TDATETIMEFIELDDISPLAYFORMAT_R(Self: TDATETIMEFIELD; var T: String);
+begin T := Self.DISPLAYFORMAT; end;
+
+procedure TDATETIMEFIELDVALUE_W(Self: TDATETIMEFIELD; const T: TDATETIME);
+begin Self.VALUE := T; end;
+
+procedure TDATETIMEFIELDVALUE_R(Self: TDATETIMEFIELD; var T: TDATETIME);
+begin T := Self.VALUE; end;
+
+procedure TBOOLEANFIELDDISPLAYVALUES_W(Self: TBOOLEANFIELD; const T: String);
+begin Self.DISPLAYVALUES := T; end;
+
+procedure TBOOLEANFIELDDISPLAYVALUES_R(Self: TBOOLEANFIELD; var T: String);
+begin T := Self.DISPLAYVALUES; end;
+
+procedure TBOOLEANFIELDVALUE_W(Self: TBOOLEANFIELD; const T: BOOLEAN);
+begin Self.VALUE := T; end;
+
+procedure TBOOLEANFIELDVALUE_R(Self: TBOOLEANFIELD; var T: BOOLEAN);
+begin T := Self.VALUE; end;
+
+procedure TFLOATFIELDPRECISION_W(Self: TFLOATFIELD; const T: INTEGER);
+begin Self.PRECISION := T; end;
+
+procedure TFLOATFIELDPRECISION_R(Self: TFLOATFIELD; var T: INTEGER);
+begin T := Self.PRECISION; end;
+
+procedure TFLOATFIELDMINVALUE_W(Self: TFLOATFIELD; const T: DOUBLE);
+begin Self.MINVALUE := T; end;
+
+procedure TFLOATFIELDMINVALUE_R(Self: TFLOATFIELD; var T: DOUBLE);
+begin T := Self.MINVALUE; end;
+
+procedure TFLOATFIELDMAXVALUE_W(Self: TFLOATFIELD; const T: DOUBLE);
+begin Self.MAXVALUE := T; end;
+
+procedure TFLOATFIELDMAXVALUE_R(Self: TFLOATFIELD; var T: DOUBLE);
+begin T := Self.MAXVALUE; end;
+
+{$IFNDEF FPC}
+procedure TFLOATFIELDCURRENCY_W(Self: TFLOATFIELD; const T: BOOLEAN);
+begin Self.CURRENCY := T; end;
+
+procedure TFLOATFIELDCURRENCY_R(Self: TFLOATFIELD; var T: BOOLEAN);
+begin T := Self.CURRENCY; end;
+{$ENDIF}
+
+procedure TFLOATFIELDVALUE_W(Self: TFLOATFIELD; const T: DOUBLE);
+begin Self.VALUE := T; end;
+
+procedure TFLOATFIELDVALUE_R(Self: TFLOATFIELD; var T: DOUBLE);
+begin T := Self.VALUE; end;
+
+procedure TLARGEINTFIELDMINVALUE_W(Self: TLARGEINTFIELD; const T: LARGEINT);
+begin Self.MINVALUE := T; end;
+
+procedure TLARGEINTFIELDMINVALUE_R(Self: TLARGEINTFIELD; var T: LARGEINT);
+begin T := Self.MINVALUE; end;
+
+procedure TLARGEINTFIELDMAXVALUE_W(Self: TLARGEINTFIELD; const T: LARGEINT);
+begin Self.MAXVALUE := T; end;
+
+procedure TLARGEINTFIELDMAXVALUE_R(Self: TLARGEINTFIELD; var T: LARGEINT);
+begin T := Self.MAXVALUE; end;
+
+procedure TLARGEINTFIELDVALUE_W(Self: TLARGEINTFIELD; const T: LARGEINT);
+begin Self.VALUE := T; end;
+
+procedure TLARGEINTFIELDVALUE_R(Self: TLARGEINTFIELD; var T: LARGEINT);
+begin T := Self.VALUE; end;
+
+procedure TLARGEINTFIELDASLARGEINT_W(Self: TLARGEINTFIELD; const T: LARGEINT);
+begin Self.ASLARGEINT := T; end;
+
+procedure TLARGEINTFIELDASLARGEINT_R(Self: TLARGEINTFIELD; var T: LARGEINT);
+begin T := Self.ASLARGEINT; end;
+
+procedure TINTEGERFIELDMINVALUE_W(Self: TINTEGERFIELD; const T: LONGINT);
+begin Self.MINVALUE := T; end;
+
+procedure TINTEGERFIELDMINVALUE_R(Self: TINTEGERFIELD; var T: LONGINT);
+begin T := Self.MINVALUE; end;
+
+procedure TINTEGERFIELDMAXVALUE_W(Self: TINTEGERFIELD; const T: LONGINT);
+begin Self.MAXVALUE := T; end;
+
+procedure TINTEGERFIELDMAXVALUE_R(Self: TINTEGERFIELD; var T: LONGINT);
+begin T := Self.MAXVALUE; end;
+
+procedure TINTEGERFIELDVALUE_W(Self: TINTEGERFIELD; const T: LONGINT);
+begin Self.VALUE := T; end;
+
+procedure TINTEGERFIELDVALUE_R(Self: TINTEGERFIELD; var T: LONGINT);
+begin T := Self.VALUE; end;
+
+procedure TNUMERICFIELDEDITFORMAT_W(Self: TNUMERICFIELD; const T: String);
+begin Self.EDITFORMAT := T; end;
+
+procedure TNUMERICFIELDEDITFORMAT_R(Self: TNUMERICFIELD; var T: String);
+begin T := Self.EDITFORMAT; end;
+
+procedure TNUMERICFIELDDISPLAYFORMAT_W(Self: TNUMERICFIELD; const T: String);
+begin Self.DISPLAYFORMAT := T; end;
+
+procedure TNUMERICFIELDDISPLAYFORMAT_R(Self: TNUMERICFIELD; var T: String);
+begin T := Self.DISPLAYFORMAT; end;
+
+{$IFNDEF FPC}
+procedure TWIDESTRINGFIELDVALUE_W(Self: TWIDESTRINGFIELD; const T: WIDESTRING);
+begin Self.VALUE := T; end;
+
+procedure TWIDESTRINGFIELDVALUE_R(Self: TWIDESTRINGFIELD; var T: WIDESTRING);
+begin T := Self.VALUE; end;
+
+procedure TSTRINGFIELDTRANSLITERATE_W(Self: TSTRINGFIELD; const T: BOOLEAN);
+begin Self.TRANSLITERATE := T; end;
+
+procedure TSTRINGFIELDTRANSLITERATE_R(Self: TSTRINGFIELD; var T: BOOLEAN);
+begin T := Self.TRANSLITERATE; end;
+
+procedure TSTRINGFIELDFIXEDCHAR_W(Self: TSTRINGFIELD; const T: BOOLEAN);
+begin Self.FIXEDCHAR := T; end;
+
+procedure TSTRINGFIELDFIXEDCHAR_R(Self: TSTRINGFIELD; var T: BOOLEAN);
+begin T := Self.FIXEDCHAR; end;
+{$ENDIF}
+
+
+procedure TSTRINGFIELDVALUE_W(Self: TSTRINGFIELD; const T: String);
+begin Self.VALUE := T; end;
+
+procedure TSTRINGFIELDVALUE_R(Self: TSTRINGFIELD; var T: String);
+begin T := Self.VALUE; end;
+
+procedure TFIELDONVALIDATE_W(Self: TFIELD; const T: TFIELDNOTIFYEVENT);
+begin Self.ONVALIDATE := T; end;
+
+procedure TFIELDONVALIDATE_R(Self: TFIELD; var T: TFIELDNOTIFYEVENT);
+begin T := Self.ONVALIDATE; end;
+
+procedure TFIELDONSETTEXT_W(Self: TFIELD; const T: TFIELDSETTEXTEVENT);
+begin Self.ONSETTEXT := T; end;
+
+procedure TFIELDONSETTEXT_R(Self: TFIELD; var T: TFIELDSETTEXTEVENT);
+begin T := Self.ONSETTEXT; end;
+
+procedure TFIELDONGETTEXT_W(Self: TFIELD; const T: TFIELDGETTEXTEVENT);
+begin Self.ONGETTEXT := T; end;
+
+procedure TFIELDONGETTEXT_R(Self: TFIELD; var T: TFIELDGETTEXTEVENT);
+begin T := Self.ONGETTEXT; end;
+
+procedure TFIELDONCHANGE_W(Self: TFIELD; const T: TFIELDNOTIFYEVENT);
+begin Self.ONCHANGE := T; end;
+
+procedure TFIELDONCHANGE_R(Self: TFIELD; var T: TFIELDNOTIFYEVENT);
+begin T := Self.ONCHANGE; end;
+
+procedure TFIELDVISIBLE_W(Self: TFIELD; const T: BOOLEAN);
+begin Self.VISIBLE := T; end;
+
+procedure TFIELDVISIBLE_R(Self: TFIELD; var T: BOOLEAN);
+begin T := Self.VISIBLE; end;
+
+procedure TFIELDREQUIRED_W(Self: TFIELD; const T: BOOLEAN);
+begin Self.REQUIRED := T; end;
+
+procedure TFIELDREQUIRED_R(Self: TFIELD; var T: BOOLEAN);
+begin T := Self.REQUIRED; end;
+
+procedure TFIELDREADONLY_W(Self: TFIELD; const T: BOOLEAN);
+begin Self.READONLY := T; end;
+
+procedure TFIELDREADONLY_R(Self: TFIELD; var T: BOOLEAN);
+begin T := Self.READONLY; end;
+
+procedure TFIELDPROVIDERFLAGS_W(Self: TFIELD; const T: TPROVIDERFLAGS);
+begin Self.PROVIDERFLAGS := T; end;
+
+procedure TFIELDPROVIDERFLAGS_R(Self: TFIELD; var T: TPROVIDERFLAGS);
+begin T := Self.PROVIDERFLAGS; end;
+
+procedure TFIELDORIGIN_W(Self: TFIELD; const T: String);
+begin Self.ORIGIN := T; end;
+
+procedure TFIELDORIGIN_R(Self: TFIELD; var T: String);
+begin T := Self.ORIGIN; end;
+
+procedure TFIELDLOOKUPCACHE_W(Self: TFIELD; const T: BOOLEAN);
+begin Self.LOOKUPCACHE := T; end;
+
+procedure TFIELDLOOKUPCACHE_R(Self: TFIELD; var T: BOOLEAN);
+begin T := Self.LOOKUPCACHE; end;
+
+procedure TFIELDKEYFIELDS_W(Self: TFIELD; const T: String);
+begin Self.KEYFIELDS := T; end;
+
+procedure TFIELDKEYFIELDS_R(Self: TFIELD; var T: String);
+begin T := Self.KEYFIELDS; end;
+
+procedure TFIELDLOOKUPRESULTFIELD_W(Self: TFIELD; const T: String);
+begin Self.LOOKUPRESULTFIELD := T; end;
+
+procedure TFIELDLOOKUPRESULTFIELD_R(Self: TFIELD; var T: String);
+begin T := Self.LOOKUPRESULTFIELD; end;
+
+procedure TFIELDLOOKUPKEYFIELDS_W(Self: TFIELD; const T: String);
+begin Self.LOOKUPKEYFIELDS := T; end;
+
+procedure TFIELDLOOKUPKEYFIELDS_R(Self: TFIELD; var T: String);
+begin T := Self.LOOKUPKEYFIELDS; end;
+
+procedure TFIELDLOOKUPDATASET_W(Self: TFIELD; const T: TDATASET);
+begin Self.LOOKUPDATASET := T; end;
+
+procedure TFIELDLOOKUPDATASET_R(Self: TFIELD; var T: TDATASET);
+begin T := Self.LOOKUPDATASET; end;
+
+procedure TFIELDIMPORTEDCONSTRAINT_W(Self: TFIELD; const T: String);
+begin Self.IMPORTEDCONSTRAINT := T; end;
+
+procedure TFIELDIMPORTEDCONSTRAINT_R(Self: TFIELD; var T: String);
+begin T := Self.IMPORTEDCONSTRAINT; end;
+
+procedure TFIELDINDEX_W(Self: TFIELD; const T: INTEGER);
+begin Self.INDEX := T; end;
+
+procedure TFIELDINDEX_R(Self: TFIELD; var T: INTEGER);
+begin T := Self.INDEX; end;
+
+procedure TFIELDHASCONSTRAINTS_R(Self: TFIELD; var T: BOOLEAN);
+begin T := Self.HASCONSTRAINTS; end;
+
+procedure TFIELDFIELDNAME_W(Self: TFIELD; const T: String);
+begin Self.FIELDNAME := T; end;
+
+procedure TFIELDFIELDNAME_R(Self: TFIELD; var T: String);
+begin T := Self.FIELDNAME; end;
+
+procedure TFIELDFIELDKIND_W(Self: TFIELD; const T: TFIELDKIND);
+begin Self.FIELDKIND := T; end;
+
+procedure TFIELDFIELDKIND_R(Self: TFIELD; var T: TFIELDKIND);
+begin T := Self.FIELDKIND; end;
+
+procedure TFIELDDISPLAYWIDTH_W(Self: TFIELD; const T: INTEGER);
+begin Self.DISPLAYWIDTH := T; end;
+
+procedure TFIELDDISPLAYWIDTH_R(Self: TFIELD; var T: INTEGER);
+begin T := Self.DISPLAYWIDTH; end;
+
+procedure TFIELDDISPLAYLABEL_W(Self: TFIELD; const T: String);
+begin Self.DISPLAYLABEL := T; end;
+
+procedure TFIELDDISPLAYLABEL_R(Self: TFIELD; var T: String);
+begin T := Self.DISPLAYLABEL; end;
+
+procedure TFIELDDEFAULTEXPRESSION_W(Self: TFIELD; const T: String);
+begin Self.DEFAULTEXPRESSION := T; end;
+
+procedure TFIELDDEFAULTEXPRESSION_R(Self: TFIELD; var T: String);
+begin T := Self.DEFAULTEXPRESSION; end;
+
+procedure TFIELDCONSTRAINTERRORMESSAGE_W(Self: TFIELD; const T: String);
+begin Self.CONSTRAINTERRORMESSAGE := T; end;
+
+procedure TFIELDCONSTRAINTERRORMESSAGE_R(Self: TFIELD; var T: String);
+begin T := Self.CONSTRAINTERRORMESSAGE; end;
+
+procedure TFIELDCUSTOMCONSTRAINT_W(Self: TFIELD; const T: String);
+begin Self.CUSTOMCONSTRAINT := T; end;
+
+procedure TFIELDCUSTOMCONSTRAINT_R(Self: TFIELD; var T: String);
+begin T := Self.CUSTOMCONSTRAINT; end;
+
+{$IFNDEF FPC}
+procedure TFIELDAUTOGENERATEVALUE_W(Self: TFIELD; const T: TAUTOREFRESHFLAG);
+begin Self.AUTOGENERATEVALUE := T; end;
+
+procedure TFIELDAUTOGENERATEVALUE_R(Self: TFIELD; var T: TAUTOREFRESHFLAG);
+begin T := Self.AUTOGENERATEVALUE; end;
+
+procedure TFIELDVALIDCHARS_W(Self: TFIELD; const T: TFIELDCHARS);
+begin Self.VALIDCHARS := T; end;
+
+procedure TFIELDVALIDCHARS_R(Self: TFIELD; var T: TFIELDCHARS);
+begin T := Self.VALIDCHARS; end;
+
+
+procedure TFIELDPARENTFIELD_W(Self: TFIELD; const T: TOBJECTFIELD);
+begin Self.PARENTFIELD := T; end;
+
+procedure TFIELDPARENTFIELD_R(Self: TFIELD; var T: TOBJECTFIELD);
+begin T := Self.PARENTFIELD; end;
+
+
+
+{$ENDIF}
+
+procedure TFIELDALIGNMENT_W(Self: TFIELD; const T: TALIGNMENT);
+begin Self.ALIGNMENT := T; end;
+
+procedure TFIELDALIGNMENT_R(Self: TFIELD; var T: TALIGNMENT);
+begin T := Self.ALIGNMENT; end;
+
+procedure TFIELDVALUE_W(Self: TFIELD; const T: VARIANT);
+begin Self.VALUE := T; end;
+
+procedure TFIELDVALUE_R(Self: TFIELD; var T: VARIANT);
+begin T := Self.VALUE; end;
+
+procedure TFIELDTEXT_W(Self: TFIELD; const T: String);
+begin Self.TEXT := T; end;
+
+procedure TFIELDTEXT_R(Self: TFIELD; var T: String);
+begin T := Self.TEXT; end;
+
+procedure TFIELDSIZE_W(Self: TFIELD; const T: INTEGER);
+begin Self.SIZE := T; end;
+
+procedure TFIELDSIZE_R(Self: TFIELD; var T: INTEGER);
+begin T := Self.SIZE; end;
+
+procedure TFIELDOLDVALUE_R(Self: TFIELD; var T: VARIANT);
+begin T := Self.OLDVALUE; end;
+
+procedure TFIELDOFFSET_R(Self: TFIELD; var T: INTEGER);
+begin T := Self.OFFSET; end;
+
+procedure TFIELDNEWVALUE_W(Self: TFIELD; const T: VARIANT);
+begin Self.NEWVALUE := T; end;
+
+procedure TFIELDNEWVALUE_R(Self: TFIELD; var T: VARIANT);
+begin T := Self.NEWVALUE; end;
+
+procedure TFIELDLOOKUPLIST_R(Self: TFIELD; var T: TLOOKUPLIST);
+begin T := Self.LOOKUPLIST; end;
+
+{$IFNDEF FPC}
+procedure TFIELDLOOKUP_W(Self: TFIELD; const T: BOOLEAN);
+begin Self.LOOKUP := T; end;
+
+procedure TFIELDLOOKUP_R(Self: TFIELD; var T: BOOLEAN);
+begin T := Self.LOOKUP; end;
+
+procedure TFIELDFULLNAME_R(Self: TFIELD; var T: String);
+begin T := Self.FULLNAME; end;
+
+
+procedure TFIELDEDITMASKPTR_R(Self: TFIELD; var T: String);
+begin T := Self.EDITMASKPTR; end;
+
+procedure TFIELDEDITMASK_W(Self: TFIELD; const T: String);
+begin Self.EDITMASK := T; end;
+
+procedure TFIELDEDITMASK_R(Self: TFIELD; var T: String);
+begin T := Self.EDITMASK; end;
+
+{$ENDIF}
+
+procedure TFIELDISNULL_R(Self: TFIELD; var T: BOOLEAN);
+begin T := Self.ISNULL; end;
+
+procedure TFIELDISINDEXFIELD_R(Self: TFIELD; var T: BOOLEAN);
+begin T := Self.ISINDEXFIELD; end;
+
+procedure TFIELDFIELDNO_R(Self: TFIELD; var T: INTEGER);
+begin T := Self.FIELDNO; end;
+
+
+
+procedure TFIELDDISPLAYTEXT_R(Self: TFIELD; var T: String);
+begin T := Self.DISPLAYTEXT; end;
+
+procedure TFIELDDISPLAYNAME_R(Self: TFIELD; var T: String);
+begin T := Self.DISPLAYNAME; end;
+
+procedure TFIELDDATATYPE_R(Self: TFIELD; var T: TFIELDTYPE);
+begin T := Self.DATATYPE; end;
+
+procedure TFIELDDATASIZE_R(Self: TFIELD; var T: INTEGER);
+begin T := Self.DATASIZE; end;
+
+procedure TFIELDDATASET_W(Self: TFIELD; const T: TDATASET);
+begin Self.DATASET := T; end;
+
+procedure TFIELDDATASET_R(Self: TFIELD; var T: TDATASET);
+begin T := Self.DATASET; end;
+
+procedure TFIELDCURVALUE_R(Self: TFIELD; var T: VARIANT);
+begin T := Self.CURVALUE; end;
+
+procedure TFIELDCANMODIFY_R(Self: TFIELD; var T: BOOLEAN);
+begin T := Self.CANMODIFY; end;
+
+procedure TFIELDCALCULATED_W(Self: TFIELD; const T: BOOLEAN);
+begin Self.CALCULATED := T; end;
+
+procedure TFIELDCALCULATED_R(Self: TFIELD; var T: BOOLEAN);
+begin T := Self.CALCULATED; end;
+
+procedure TFIELDATTRIBUTESET_W(Self: TFIELD; const T: String);
+begin Self.ATTRIBUTESET := T; end;
+
+procedure TFIELDATTRIBUTESET_R(Self: TFIELD; var T: String);
+begin T := Self.ATTRIBUTESET; end;
+
+procedure TFIELDASVARIANT_W(Self: TFIELD; const T: VARIANT);
+begin Self.ASVARIANT := T; end;
+
+procedure TFIELDASVARIANT_R(Self: TFIELD; var T: VARIANT);
+begin T := Self.ASVARIANT; end;
+
+procedure TFIELDASSTRING_W(Self: TFIELD; const T: String);
+begin Self.ASSTRING := T; end;
+
+procedure TFIELDASSTRING_R(Self: TFIELD; var T: String);
+begin T := Self.ASSTRING; end;
+
+procedure TFIELDASINTEGER_W(Self: TFIELD; const T: LONGINT);
+begin Self.ASINTEGER := T; end;
+
+procedure TFIELDASINTEGER_R(Self: TFIELD; var T: LONGINT);
+begin T := Self.ASINTEGER; end;
+
+procedure TFIELDASFLOAT_W(Self: TFIELD; const T: DOUBLE);
+begin Self.ASFLOAT := T; end;
+
+procedure TFIELDASFLOAT_R(Self: TFIELD; var T: DOUBLE);
+begin T := Self.ASFLOAT; end;
+
+procedure TFIELDASDATETIME_W(Self: TFIELD; const T: TDATETIME);
+begin Self.ASDATETIME := T; end;
+
+procedure TFIELDASDATETIME_R(Self: TFIELD; var T: TDATETIME);
+begin T := Self.ASDATETIME; end;
+
+procedure TFIELDASCURRENCY_W(Self: TFIELD; const T: CURRENCY);
+begin Self.ASCURRENCY := T; end;
+
+procedure TFIELDASCURRENCY_R(Self: TFIELD; var T: CURRENCY);
+begin T := Self.ASCURRENCY; end;
+
+procedure TFIELDASBOOLEAN_W(Self: TFIELD; const T: BOOLEAN);
+begin Self.ASBOOLEAN := T; end;
+
+procedure TFIELDASBOOLEAN_R(Self: TFIELD; var T: BOOLEAN);
+begin T := Self.ASBOOLEAN; end;
+
+{$IFNDEF FPC}
+{$IFDEF DELPHI6UP}
+procedure TFIELDASBCD_W(Self: TFIELD; const T: TBCD);
+begin Self.ASBCD := T; end;
+
+procedure TFIELDASBCD_R(Self: TFIELD; var T: TBCD);
+begin T := Self.ASBCD; end;
+{$ENDIF}
+
+procedure TFIELDLISTFIELDS_R(Self: TFIELDLIST; var T: TFIELD; const t1: INTEGER);
+begin T := Self.FIELDS[t1]; end;
+
+procedure TFIELDDEFLISTFIELDDEFS_R(Self: TFIELDDEFLIST; var T: TFIELDDEF; const t1: INTEGER);
+begin T := Self.FIELDDEFS[t1]; end;
+
+procedure TFLATLISTDATASET_R(Self: TFLATLIST; var T: TDATASET);
+begin T := Self.DATASET; end;
+
+procedure TINDEXDEFGROUPINGLEVEL_W(Self: TINDEXDEF; const T: INTEGER);
+begin Self.GROUPINGLEVEL := T; end;
+
+procedure TINDEXDEFGROUPINGLEVEL_R(Self: TINDEXDEF; var T: INTEGER);
+begin T := Self.GROUPINGLEVEL; end;
+
+
+
+{$ENDIF}
+
+procedure TFIELDSFIELDS_W(Self: TFIELDS; const T: TFIELD; const t1: INTEGER);
+begin Self.FIELDS[t1] := T; end;
+
+procedure TFIELDSFIELDS_R(Self: TFIELDS; var T: TFIELD; const t1: INTEGER);
+begin T := Self.FIELDS[t1]; end;
+
+procedure TFIELDSDATASET_R(Self: TFIELDS; var T: TDATASET);
+begin T := Self.DATASET; end;
+
+procedure TFIELDSCOUNT_R(Self: TFIELDS; var T: INTEGER);
+begin T := Self.COUNT; end;
+
+procedure TINDEXDEFSITEMS_W(Self: TINDEXDEFS; const T: TINDEXDEF; const t1: INTEGER);
+begin Self.ITEMS[t1] := T; end;
+
+procedure TINDEXDEFSITEMS_R(Self: TINDEXDEFS; var T: TINDEXDEF; const t1: INTEGER);
+begin T := Self.ITEMS[t1]; end;
+
+procedure TINDEXDEFSOURCE_W(Self: TINDEXDEF; const T: String);
+begin Self.SOURCE := T; end;
+
+procedure TINDEXDEFSOURCE_R(Self: TINDEXDEF; var T: String);
+begin T := Self.SOURCE; end;
+
+procedure TINDEXDEFOPTIONS_W(Self: TINDEXDEF; const T: TINDEXOPTIONS);
+begin Self.OPTIONS := T; end;
+
+procedure TINDEXDEFOPTIONS_R(Self: TINDEXDEF; var T: TINDEXOPTIONS);
+begin T := Self.OPTIONS; end;
+
+procedure TINDEXDEFFIELDS_W(Self: TINDEXDEF; const T: String);
+begin Self.FIELDS := T; end;
+
+procedure TINDEXDEFFIELDS_R(Self: TINDEXDEF; var T: String);
+begin T := Self.FIELDS; end;
+
+procedure TINDEXDEFEXPRESSION_W(Self: TINDEXDEF; const T: String);
+begin {$IFNDEF FPC}Self.EXPRESSION := T; {$ENDIF}end;
+
+procedure TINDEXDEFEXPRESSION_R(Self: TINDEXDEF; var T: String);
+begin T := Self.EXPRESSION; end;
+
+{$IFNDEF FPC}
+procedure TINDEXDEFDESCFIELDS_W(Self: TINDEXDEF; const T: String);
+begin Self.DESCFIELDS := T; end;
+
+procedure TINDEXDEFDESCFIELDS_R(Self: TINDEXDEF; var T: String);
+begin T := Self.DESCFIELDS; end;
+
+procedure TINDEXDEFCASEINSFIELDS_W(Self: TINDEXDEF; const T: String);
+begin Self.CASEINSFIELDS := T; end;
+
+procedure TINDEXDEFCASEINSFIELDS_R(Self: TINDEXDEF; var T: String);
+begin T := Self.CASEINSFIELDS; end;
+
+
+procedure TINDEXDEFFIELDEXPRESSION_R(Self: TINDEXDEF; var T: String);
+begin T := Self.FIELDEXPRESSION; end;
+
+procedure TFIELDDEFSPARENTDEF_R(Self: TFIELDDEFS; var T: TFIELDDEF);
+begin T := Self.PARENTDEF; end;
+
+{$ENDIF}
+
+procedure TFIELDDEFSITEMS_W(Self: TFIELDDEFS; const T: TFIELDDEF; const t1: INTEGER);
+begin Self.ITEMS[t1] := T; end;
+
+procedure TFIELDDEFSITEMS_R(Self: TFIELDDEFS; var T: TFIELDDEF; const t1: INTEGER);
+begin T := Self.ITEMS[t1]; end;
+
+procedure TFIELDDEFSHIDDENFIELDS_W(Self: TFIELDDEFS; const T: BOOLEAN);
+begin Self.HIDDENFIELDS := T; end;
+
+procedure TFIELDDEFSHIDDENFIELDS_R(Self: TFIELDDEFS; var T: BOOLEAN);
+begin T := Self.HIDDENFIELDS; end;
+
+procedure TFIELDDEFSIZE_W(Self: TFIELDDEF; const T: INTEGER);
+begin Self.SIZE := T; end;
+
+procedure TFIELDDEFSIZE_R(Self: TFIELDDEF; var T: INTEGER);
+begin T := Self.SIZE; end;
+
+procedure TFIELDDEFPRECISION_W(Self: TFIELDDEF; const T: INTEGER);
+begin Self.PRECISION := T; end;
+
+procedure TFIELDDEFPRECISION_R(Self: TFIELDDEF; var T: INTEGER);
+begin T := Self.PRECISION; end;
+
+procedure TFIELDDEFDATATYPE_W(Self: TFIELDDEF; const T: TFIELDTYPE);
+begin Self.DATATYPE := T; end;
+
+procedure TFIELDDEFDATATYPE_R(Self: TFIELDDEF; var T: TFIELDTYPE);
+begin T := Self.DATATYPE; end;
+
+{$IFNDEF FPC}
+procedure TFIELDDEFCHILDDEFS_W(Self: TFIELDDEF; const T: TFIELDDEFS);
+begin Self.CHILDDEFS := T; end;
+
+procedure TFIELDDEFCHILDDEFS_R(Self: TFIELDDEF; var T: TFIELDDEFS);
+begin T := Self.CHILDDEFS; end;
+
+procedure TFIELDDEFREQUIRED_W(Self: TFIELDDEF; const T: BOOLEAN);
+begin Self.REQUIRED := T;end;
+
+procedure TFIELDDEFPARENTDEF_R(Self: TFIELDDEF; var T: TFIELDDEF);
+begin T := Self.PARENTDEF; end;
+
+{$ENDIF}
+
+procedure TFIELDDEFATTRIBUTES_W(Self: TFIELDDEF; const T: TFIELDATTRIBUTES);
+begin Self.ATTRIBUTES := T; end;
+
+procedure TFIELDDEFATTRIBUTES_R(Self: TFIELDDEF; var T: TFIELDATTRIBUTES);
+begin T := Self.ATTRIBUTES; end;
+
+procedure TFIELDDEFREQUIRED_R(Self: TFIELDDEF; var T: BOOLEAN);
+begin T := Self.REQUIRED; end;
+
+procedure TFIELDDEFINTERNALCALCFIELD_W(Self: TFIELDDEF; const T: BOOLEAN);
+begin Self.INTERNALCALCFIELD := T; end;
+
+procedure TFIELDDEFINTERNALCALCFIELD_R(Self: TFIELDDEF; var T: BOOLEAN);
+begin T := Self.INTERNALCALCFIELD; end;
+
+{$IFNDEF FPC}
+procedure TFIELDDEFFIELDNO_W(Self: TFIELDDEF; const T: INTEGER);
+begin Self.FIELDNO := T; end;
+
+procedure TDEFCOLLECTIONUPDATED_W(Self: TDEFCOLLECTION; const T: BOOLEAN);
+begin Self.UPDATED := T; end;
+
+procedure TDEFCOLLECTIONUPDATED_R(Self: TDEFCOLLECTION; var T: BOOLEAN);
+begin T := Self.UPDATED; end;
+
+procedure TDEFCOLLECTIONDATASET_R(Self: TDEFCOLLECTION; var T: TDATASET);
+begin T := Self.DATASET; end;
+
+procedure TNAMEDITEMNAME_W(Self: TNAMEDITEM; const T: String);
+begin Self.NAME := T; end;
+
+procedure TNAMEDITEMNAME_R(Self: TNAMEDITEM; var T: String);
+begin T := Self.NAME; end;
+
+
+{$ENDIF}
+
+procedure TFIELDDEFFIELDNO_R(Self: TFIELDDEF; var T: INTEGER);
+begin T := Self.FIELDNO; end;
+
+procedure TFIELDDEFFIELDCLASS_R(Self: TFIELDDEF; var T: TFIELDCLASS);
+begin T := Self.FIELDCLASS; end;
+
+procedure RIRegisterTDATASET(Cl: TPSRuntimeClassImporter);
+Begin
+with Cl.Add(TDATASET) do
+ begin
+ RegisterMethod(@TDATASET.ACTIVEBUFFER, 'ACTIVEBUFFER');
+ RegisterMethod(@TDATASET.APPEND, 'APPEND');
+ RegisterMethod(@TDATASET.APPENDRECORD, 'APPENDRECORD');
+// RegisterVirtualMethod(@TDATASET.BOOKMARKVALID, 'BOOKMARKVALID');
+ RegisterVirtualMethod(@TDATASET.CANCEL, 'CANCEL');
+ RegisterMethod(@TDATASET.CHECKBROWSEMODE, 'CHECKBROWSEMODE');
+ RegisterMethod(@TDATASET.CLEARFIELDS, 'CLEARFIELDS');
+ RegisterMethod(@TDATASET.CLOSE, 'CLOSE');
+ RegisterMethod(@TDATASET.CONTROLSDISABLED, 'CONTROLSDISABLED');
+// RegisterVirtualMethod(@TDATASET.COMPAREBOOKMARKS, 'COMPAREBOOKMARKS');
+ RegisterVirtualMethod(@TDATASET.CREATEBLOBSTREAM, 'CREATEBLOBSTREAM');
+ RegisterMethod(@TDATASET.CURSORPOSCHANGED, 'CURSORPOSCHANGED');
+ RegisterMethod(@TDATASET.DELETE, 'DELETE');
+ RegisterMethod(@TDATASET.DISABLECONTROLS, 'DISABLECONTROLS');
+ RegisterMethod(@TDATASET.EDIT, 'EDIT');
+ RegisterMethod(@TDATASET.ENABLECONTROLS, 'ENABLECONTROLS');
+ RegisterMethod(@TDATASET.FIELDBYNAME, 'FIELDBYNAME');
+ RegisterMethod(@TDATASET.FINDFIELD, 'FINDFIELD');
+ RegisterMethod(@TDATASET.FINDFIRST, 'FINDFIRST');
+ RegisterMethod(@TDATASET.FINDLAST, 'FINDLAST');
+ RegisterMethod(@TDATASET.FINDNEXT, 'FINDNEXT');
+ RegisterMethod(@TDATASET.FINDPRIOR, 'FINDPRIOR');
+ RegisterMethod(@TDATASET.FIRST, 'FIRST');
+// RegisterVirtualMethod(@TDATASET.FREEBOOKMARK, 'FREEBOOKMARK');
+// RegisterVirtualMethod(@TDATASET.GETBOOKMARK, 'GETBOOKMARK');
+ RegisterVirtualMethod(@TDATASET.GETCURRENTRECORD, 'GETCURRENTRECORD');
+// RegisterVirtualMethod(@TDATASET.GETDETAILDATASETS, 'GETDETAILDATASETS');
+// RegisterVirtualMethod(@TDATASET.GETDETAILLINKFIELDS, 'GETDETAILLINKFIELDS');
+// RegisterVirtualMethod(@TDATASET.GETBLOBFIELDDATA, 'GETBLOBFIELDDATA');
+// RegisterMethod(@TDATASET.GETFIELDLIST, 'GETFIELDLIST');
+ RegisterMethod(@TDATASET.GETFIELDNAMES, 'GETFIELDNAMES');
+// RegisterMethod(@TDATASET.GOTOBOOKMARK, 'GOTOBOOKMARK');
+ RegisterMethod(@TDATASET.INSERT, 'INSERT');
+ RegisterMethod(@TDATASET.INSERTRECORD, 'INSERTRECORD');
+ RegisterMethod(@TDATASET.ISEMPTY, 'ISEMPTY');
+ RegisterMethod(@TDATASET.ISLINKEDTO, 'ISLINKEDTO');
+ RegisterVirtualMethod(@TDATASET.ISSEQUENCED, 'ISSEQUENCED');
+ RegisterMethod(@TDATASET.LAST, 'LAST');
+ RegisterVirtualMethod(@TDATASET.LOCATE, 'LOCATE');
+ RegisterVirtualMethod(@TDATASET.LOOKUP, 'LOOKUP');
+ RegisterMethod(@TDATASET.MOVEBY, 'MOVEBY');
+ RegisterMethod(@TDATASET.NEXT, 'NEXT');
+ RegisterMethod(@TDATASET.OPEN, 'OPEN');
+ RegisterVirtualMethod(@TDATASET.POST, 'POST');
+ RegisterMethod(@TDATASET.PRIOR, 'PRIOR');
+ RegisterMethod(@TDATASET.REFRESH, 'REFRESH');
+// RegisterVirtualMethod(@TDATASET.RESYNC, 'RESYNC');
+ RegisterMethod(@TDATASET.SETFIELDS, 'SETFIELDS');
+ RegisterVirtualMethod(@TDATASET.TRANSLATE, 'TRANSLATE');
+ RegisterMethod(@TDATASET.UPDATECURSORPOS, 'UPDATECURSORPOS');
+ RegisterMethod(@TDATASET.UPDATERECORD, 'UPDATERECORD');
+ RegisterVirtualMethod(@TDATASET.UPDATESTATUS, 'UPDATESTATUS');
+ RegisterPropertyHelper(@TDATASETBOF_R,nil,'BOF');
+// RegisterPropertyHelper(@TDATASETBOOKMARK_R,@TDATASETBOOKMARK_W,'BOOKMARK');
+ RegisterPropertyHelper(@TDATASETCANMODIFY_R,nil,'CANMODIFY');
+ RegisterPropertyHelper(@TDATASETDATASOURCE_R,nil,'DATASOURCE');
+ RegisterPropertyHelper(@TDATASETDEFAULTFIELDS_R,nil,'DEFAULTFIELDS');
+ RegisterPropertyHelper(@TDATASETEOF_R,nil,'EOF');
+ RegisterPropertyHelper(@TDATASETFIELDCOUNT_R,nil,'FIELDCOUNT');
+ RegisterPropertyHelper(@TDATASETFIELDS_R,nil,'FIELDS');
+ RegisterPropertyHelper(@TDATASETFIELDVALUES_R,@TDATASETFIELDVALUES_W,'FIELDVALUES');
+ RegisterPropertyHelper(@TDATASETFOUND_R,nil,'FOUND');
+{$IFDEF DELPHI6UP}
+ RegisterPropertyHelper(@TDATASETISUNIDIRECTIONAL_R,nil,'ISUNIDIRECTIONAL');
+{$ENDIF}
+ RegisterPropertyHelper(@TDATASETMODIFIED_R,nil,'MODIFIED');
+ RegisterPropertyHelper(@TDATASETRECORDCOUNT_R,nil,'RECORDCOUNT');
+ RegisterPropertyHelper(@TDATASETRECNO_R,@TDATASETRECNO_W,'RECNO');
+ RegisterPropertyHelper(@TDATASETRECORDSIZE_R,nil,'RECORDSIZE');
+ RegisterPropertyHelper(@TDATASETSTATE_R,nil,'STATE');
+ RegisterPropertyHelper(@TDATASETFILTER_R,@TDATASETFILTER_W,'FILTER');
+ RegisterPropertyHelper(@TDATASETFILTERED_R,@TDATASETFILTERED_W,'FILTERED');
+ RegisterPropertyHelper(@TDATASETFILTEROPTIONS_R,@TDATASETFILTEROPTIONS_W,'FILTEROPTIONS');
+ RegisterPropertyHelper(@TDATASETACTIVE_R,@TDATASETACTIVE_W,'ACTIVE');
+ RegisterPropertyHelper(@TDATASETAUTOCALCFIELDS_R,@TDATASETAUTOCALCFIELDS_W,'AUTOCALCFIELDS');
+ RegisterPropertyHelper(@TDATASETBEFOREOPEN_R,@TDATASETBEFOREOPEN_W,'BEFOREOPEN');
+ RegisterPropertyHelper(@TDATASETAFTEROPEN_R,@TDATASETAFTEROPEN_W,'AFTEROPEN');
+ RegisterPropertyHelper(@TDATASETBEFORECLOSE_R,@TDATASETBEFORECLOSE_W,'BEFORECLOSE');
+ RegisterPropertyHelper(@TDATASETAFTERCLOSE_R,@TDATASETAFTERCLOSE_W,'AFTERCLOSE');
+ RegisterPropertyHelper(@TDATASETBEFOREINSERT_R,@TDATASETBEFOREINSERT_W,'BEFOREINSERT');
+ RegisterPropertyHelper(@TDATASETAFTERINSERT_R,@TDATASETAFTERINSERT_W,'AFTERINSERT');
+ RegisterPropertyHelper(@TDATASETBEFOREEDIT_R,@TDATASETBEFOREEDIT_W,'BEFOREEDIT');
+ RegisterPropertyHelper(@TDATASETAFTEREDIT_R,@TDATASETAFTEREDIT_W,'AFTEREDIT');
+ RegisterPropertyHelper(@TDATASETBEFOREPOST_R,@TDATASETBEFOREPOST_W,'BEFOREPOST');
+ RegisterPropertyHelper(@TDATASETAFTERPOST_R,@TDATASETAFTERPOST_W,'AFTERPOST');
+ RegisterPropertyHelper(@TDATASETBEFORECANCEL_R,@TDATASETBEFORECANCEL_W,'BEFORECANCEL');
+ RegisterPropertyHelper(@TDATASETAFTERCANCEL_R,@TDATASETAFTERCANCEL_W,'AFTERCANCEL');
+ RegisterPropertyHelper(@TDATASETBEFOREDELETE_R,@TDATASETBEFOREDELETE_W,'BEFOREDELETE');
+ RegisterPropertyHelper(@TDATASETAFTERDELETE_R,@TDATASETAFTERDELETE_W,'AFTERDELETE');
+ RegisterPropertyHelper(@TDATASETBEFORESCROLL_R,@TDATASETBEFORESCROLL_W,'BEFORESCROLL');
+ RegisterPropertyHelper(@TDATASETAFTERSCROLL_R,@TDATASETAFTERSCROLL_W,'AFTERSCROLL');
+ {$IFNDEF FPC}
+ RegisterPropertyHelper(@TDATASETFIELDLIST_R,nil,'FIELDLIST');
+ RegisterPropertyHelper(@TDATASETDESIGNER_R,nil,'DESIGNER');
+ RegisterPropertyHelper(@TDATASETBLOCKREADSIZE_R,@TDATASETBLOCKREADSIZE_W,'BLOCKREADSIZE');
+ RegisterPropertyHelper(@TDATASETBEFOREREFRESH_R,@TDATASETBEFOREREFRESH_W,'BEFOREREFRESH');
+ RegisterPropertyHelper(@TDATASETAFTERREFRESH_R,@TDATASETAFTERREFRESH_W,'AFTERREFRESH');
+ RegisterPropertyHelper(@TDATASETAGGFIELDS_R,nil,'AGGFIELDS');
+ RegisterPropertyHelper(@TDATASETDATASETFIELD_R,@TDATASETDATASETFIELD_W,'DATASETFIELD');
+ RegisterPropertyHelper(@TDATASETOBJECTVIEW_R,@TDATASETOBJECTVIEW_W,'OBJECTVIEW');
+ RegisterPropertyHelper(@TDATASETSPARSEARRAYS_R,@TDATASETSPARSEARRAYS_W,'SPARSEARRAYS');
+ RegisterPropertyHelper(@TDATASETFIELDDEFS_R,@TDATASETFIELDDEFS_W,'FIELDDEFS');
+ RegisterPropertyHelper(@TDATASETFIELDDEFLIST_R,nil,'FIELDDEFLIST');
+
+ {$ENDIF}
+ RegisterEventPropertyHelper(@TDATASETONCALCFIELDS_R,@TDATASETONCALCFIELDS_W,'ONCALCFIELDS');
+ RegisterEventPropertyHelper(@TDATASETONDELETEERROR_R,@TDATASETONDELETEERROR_W,'ONDELETEERROR');
+ RegisterEventPropertyHelper(@TDATASETONEDITERROR_R,@TDATASETONEDITERROR_W,'ONEDITERROR');
+ RegisterEventPropertyHelper(@TDATASETONFILTERRECORD_R,@TDATASETONFILTERRECORD_W,'ONFILTERRECORD');
+ RegisterEventPropertyHelper(@TDATASETONNEWRECORD_R,@TDATASETONNEWRECORD_W,'ONNEWRECORD');
+ RegisterEventPropertyHelper(@TDATASETONPOSTERROR_R,@TDATASETONPOSTERROR_W,'ONPOSTERROR');
+ end;
+end;
+
+procedure RIRegisterTPARAMS(Cl: TPSRuntimeClassImporter);
+Begin
+with Cl.Add(TPARAMS) do
+ begin
+// RegisterMethod(@TPARAMS.ASSIGNVALUES, 'ASSIGNVALUES');
+ RegisterMethod(@TPARAMS.ADDPARAM, 'ADDPARAM');
+ RegisterMethod(@TPARAMS.REMOVEPARAM, 'REMOVEPARAM');
+ RegisterMethod(@TPARAMS.CREATEPARAM, 'CREATEPARAM');
+ RegisterMethod(@TPARAMS.GETPARAMLIST, 'GETPARAMLIST');
+ RegisterMethod(@TPARAMS.ISEQUAL, 'ISEQUAL');
+ RegisterMethod(@TPARAMS.PARSESQL, 'PARSESQL');
+ RegisterMethod(@TPARAMS.PARAMBYNAME, 'PARAMBYNAME');
+ RegisterMethod(@TPARAMS.FINDPARAM, 'FINDPARAM');
+ RegisterPropertyHelper(@TPARAMSITEMS_R,@TPARAMSITEMS_W,'ITEMS');
+ RegisterPropertyHelper(@TPARAMSPARAMVALUES_R,@TPARAMSPARAMVALUES_W,'PARAMVALUES');
+ end;
+end;
+
+procedure RIRegisterTPARAM(Cl: TPSRuntimeClassImporter);
+Begin
+with Cl.Add(TPARAM) do
+ begin
+ RegisterMethod(@TPARAM.ASSIGNFIELD, 'ASSIGNFIELD');
+ RegisterMethod(@TPARAM.ASSIGNFIELDVALUE, 'ASSIGNFIELDVALUE');
+ RegisterMethod(@TPARAM.CLEAR, 'CLEAR');
+// RegisterMethod(@TPARAM.GETDATA, 'GETDATA');
+ RegisterMethod(@TPARAM.GETDATASIZE, 'GETDATASIZE');
+ RegisterMethod(@TPARAM.LOADFROMFILE, 'LOADFROMFILE');
+ RegisterMethod(@TPARAM.LOADFROMSTREAM, 'LOADFROMSTREAM');
+// RegisterMethod(@TPARAM.SETBLOBDATA, 'SETBLOBDATA');
+// RegisterMethod(@TPARAM.SETDATA, 'SETDATA');
+ {$IFNDEF FPC}
+ RegisterPropertyHelper(@TPARAMASBCD_R,@TPARAMASBCD_W,'ASBCD');
+{$IFDEF DELPHI6UP}
+ RegisterPropertyHelper(@TPARAMASFMTBCD_R,@TPARAMASFMTBCD_W,'ASFMTBCD');
+{$ENDIF}
+ {$ENDIF}
+ RegisterPropertyHelper(@TPARAMASBLOB_R,@TPARAMASBLOB_W,'ASBLOB');
+ RegisterPropertyHelper(@TPARAMASBOOLEAN_R,@TPARAMASBOOLEAN_W,'ASBOOLEAN');
+ RegisterPropertyHelper(@TPARAMASCURRENCY_R,@TPARAMASCURRENCY_W,'ASCURRENCY');
+ RegisterPropertyHelper(@TPARAMASDATE_R,@TPARAMASDATE_W,'ASDATE');
+ RegisterPropertyHelper(@TPARAMASDATETIME_R,@TPARAMASDATETIME_W,'ASDATETIME');
+ RegisterPropertyHelper(@TPARAMASFLOAT_R,@TPARAMASFLOAT_W,'ASFLOAT');
+ RegisterPropertyHelper(@TPARAMASINTEGER_R,@TPARAMASINTEGER_W,'ASINTEGER');
+ RegisterPropertyHelper(@TPARAMASSMALLINT_R,@TPARAMASSMALLINT_W,'ASSMALLINT');
+ RegisterPropertyHelper(@TPARAMASMEMO_R,@TPARAMASMEMO_W,'ASMEMO');
+ RegisterPropertyHelper(@TPARAMASSTRING_R,@TPARAMASSTRING_W,'ASSTRING');
+ RegisterPropertyHelper(@TPARAMASTIME_R,@TPARAMASTIME_W,'ASTIME');
+ RegisterPropertyHelper(@TPARAMASWORD_R,@TPARAMASWORD_W,'ASWORD');
+ RegisterPropertyHelper(@TPARAMBOUND_R,@TPARAMBOUND_W,'BOUND');
+ RegisterPropertyHelper(@TPARAMISNULL_R,nil,'ISNULL');
+ RegisterPropertyHelper(@TPARAMNATIVESTR_R,@TPARAMNATIVESTR_W,'NATIVESTR');
+ RegisterPropertyHelper(@TPARAMTEXT_R,@TPARAMTEXT_W,'TEXT');
+ RegisterPropertyHelper(@TPARAMDATATYPE_R,@TPARAMDATATYPE_W,'DATATYPE');
+{$IFDEF DELPHI6UP}
+ RegisterPropertyHelper(@TPARAMPRECISION_R,@TPARAMPRECISION_W,'PRECISION');
+ RegisterPropertyHelper(@TPARAMNUMERICSCALE_R,@TPARAMNUMERICSCALE_W,'NUMERICSCALE');
+ RegisterPropertyHelper(@TPARAMSIZE_R,@TPARAMSIZE_W,'SIZE');
+{$ENDIF}
+ RegisterPropertyHelper(@TPARAMNAME_R,@TPARAMNAME_W,'NAME');
+ RegisterPropertyHelper(@TPARAMPARAMTYPE_R,@TPARAMPARAMTYPE_W,'PARAMTYPE');
+ RegisterPropertyHelper(@TPARAMVALUE_R,@TPARAMVALUE_W,'VALUE');
+ end;
+end;
+
+{$IFNDEF FPC}
+procedure RIRegisterTGUIDFIELD(Cl: TPSRuntimeClassImporter);
+Begin
+with Cl.Add(TGUIDFIELD) do
+ begin
+ end;
+end;
+
+procedure RIRegisterTVARIANTFIELD(Cl: TPSRuntimeClassImporter);
+Begin
+with Cl.Add(TVARIANTFIELD) do
+ begin
+ end;
+end;
+
+procedure RIRegisterTREFERENCEFIELD(Cl: TPSRuntimeClassImporter);
+Begin
+with Cl.Add(TREFERENCEFIELD) do
+ begin
+ RegisterPropertyHelper(@TREFERENCEFIELDREFERENCETABLENAME_R,@TREFERENCEFIELDREFERENCETABLENAME_W,'REFERENCETABLENAME');
+ end;
+end;
+
+
+procedure RIRegisterTDATASETFIELD(Cl: TPSRuntimeClassImporter);
+Begin
+with Cl.Add(TDATASETFIELD) do
+ begin
+ RegisterPropertyHelper(@TDATASETFIELDNESTEDDATASET_R,nil,'NESTEDDATASET');
+ RegisterPropertyHelper(@TDATASETFIELDINCLUDEOBJECTFIELD_R,@TDATASETFIELDINCLUDEOBJECTFIELD_W,'INCLUDEOBJECTFIELD');
+ end;
+end;
+
+
+procedure RIRegisterTARRAYFIELD(Cl: TPSRuntimeClassImporter);
+Begin
+with Cl.Add(TARRAYFIELD) do
+ begin
+ end;
+end;
+
+
+procedure RIRegisterTADTFIELD(Cl: TPSRuntimeClassImporter);
+Begin
+with Cl.Add(TADTFIELD) do
+ begin
+ end;
+end;
+
+
+procedure RIRegisterTOBJECTFIELD(Cl: TPSRuntimeClassImporter);
+Begin
+with Cl.Add(TOBJECTFIELD) do
+ begin
+ RegisterPropertyHelper(@TOBJECTFIELDFIELDCOUNT_R,nil,'FIELDCOUNT');
+ RegisterPropertyHelper(@TOBJECTFIELDFIELDS_R,nil,'FIELDS');
+ RegisterPropertyHelper(@TOBJECTFIELDFIELDVALUES_R,@TOBJECTFIELDFIELDVALUES_W,'FIELDVALUES');
+ RegisterPropertyHelper(@TOBJECTFIELDUNNAMED_R,nil,'UNNAMED');
+ RegisterPropertyHelper(@TOBJECTFIELDOBJECTTYPE_R,@TOBJECTFIELDOBJECTTYPE_W,'OBJECTTYPE');
+ end;
+end;
+{$ENDIF}
+
+
+procedure RIRegisterTGRAPHICFIELD(Cl: TPSRuntimeClassImporter);
+Begin
+with Cl.Add(TGRAPHICFIELD) do
+ begin
+ end;
+end;
+
+procedure RIRegisterTMEMOFIELD(Cl: TPSRuntimeClassImporter);
+Begin
+with Cl.Add(TMEMOFIELD) do
+ begin
+ end;
+end;
+
+procedure RIRegisterTBLOBFIELD(Cl: TPSRuntimeClassImporter);
+Begin
+with Cl.Add(TBLOBFIELD) do
+ begin
+ RegisterMethod(@TBLOBFIELD.LOADFROMFILE, 'LOADFROMFILE');
+ RegisterMethod(@TBLOBFIELD.LOADFROMSTREAM, 'LOADFROMSTREAM');
+ RegisterMethod(@TBLOBFIELD.SAVETOFILE, 'SAVETOFILE');
+ RegisterMethod(@TBLOBFIELD.SAVETOSTREAM, 'SAVETOSTREAM');
+ RegisterPropertyHelper(@TBLOBFIELDBLOBSIZE_R,nil,'BLOBSIZE');
+ RegisterPropertyHelper(@TBLOBFIELDMODIFIED_R,@TBLOBFIELDMODIFIED_W,'MODIFIED');
+ RegisterPropertyHelper(@TBLOBFIELDVALUE_R,@TBLOBFIELDVALUE_W,'VALUE');
+ RegisterPropertyHelper(@TBLOBFIELDTRANSLITERATE_R,@TBLOBFIELDTRANSLITERATE_W,'TRANSLITERATE');
+ RegisterPropertyHelper(@TBLOBFIELDBLOBTYPE_R,@TBLOBFIELDBLOBTYPE_W,'BLOBTYPE');
+{$IFNDEF FPC}
+{$IFDEF DELPHI6UP}
+ RegisterPropertyHelper(@TBLOBFIELDGRAPHICHEADER_R,@TBLOBFIELDGRAPHICHEADER_W,'GRAPHICHEADER');
+{$ENDIF}
+{$ENDIF}
+ end;
+end;
+
+
+{$IFNDEF FPC}
+{$IFDEF DELPHI6UP}
+
+procedure RIRegisterTFMTBCDFIELD(Cl: TPSRuntimeClassImporter);
+Begin
+with Cl.Add(TFMTBCDFIELD) do
+ begin
+ RegisterPropertyHelper(@TFMTBCDFIELDVALUE_R,@TFMTBCDFIELDVALUE_W,'VALUE');
+ RegisterPropertyHelper(@TFMTBCDFIELDCURRENCY_R,@TFMTBCDFIELDCURRENCY_W,'CURRENCY');
+ RegisterPropertyHelper(@TFMTBCDFIELDMAXVALUE_R,@TFMTBCDFIELDMAXVALUE_W,'MAXVALUE');
+ RegisterPropertyHelper(@TFMTBCDFIELDMINVALUE_R,@TFMTBCDFIELDMINVALUE_W,'MINVALUE');
+ RegisterPropertyHelper(@TFMTBCDFIELDPRECISION_R,@TFMTBCDFIELDPRECISION_W,'PRECISION');
+ end;
+end;
+{$ENDIF}
+procedure RIRegisterTBCDFIELD(Cl: TPSRuntimeClassImporter);
+Begin
+with Cl.Add(TBCDFIELD) do
+ begin
+ RegisterPropertyHelper(@TBCDFIELDVALUE_R,@TBCDFIELDVALUE_W,'VALUE');
+ RegisterPropertyHelper(@TBCDFIELDCURRENCY_R,@TBCDFIELDCURRENCY_W,'CURRENCY');
+ RegisterPropertyHelper(@TBCDFIELDMAXVALUE_R,@TBCDFIELDMAXVALUE_W,'MAXVALUE');
+ RegisterPropertyHelper(@TBCDFIELDMINVALUE_R,@TBCDFIELDMINVALUE_W,'MINVALUE');
+ RegisterPropertyHelper(@TBCDFIELDPRECISION_R,@TBCDFIELDPRECISION_W,'PRECISION');
+ end;
+end;
+{$ENDIF}
+
+procedure RIRegisterTVARBYTESFIELD(Cl: TPSRuntimeClassImporter);
+Begin
+with Cl.Add(TVARBYTESFIELD) do
+ begin
+ end;
+end;
+
+procedure RIRegisterTBYTESFIELD(Cl: TPSRuntimeClassImporter);
+Begin
+with Cl.Add(TBYTESFIELD) do
+ begin
+ end;
+end;
+
+procedure RIRegisterTBINARYFIELD(Cl: TPSRuntimeClassImporter);
+Begin
+with Cl.Add(TBINARYFIELD) do
+ begin
+ end;
+end;
+
+procedure RIRegisterTTIMEFIELD(Cl: TPSRuntimeClassImporter);
+Begin
+with Cl.Add(TTIMEFIELD) do
+ begin
+ end;
+end;
+
+procedure RIRegisterTDATEFIELD(Cl: TPSRuntimeClassImporter);
+Begin
+with Cl.Add(TDATEFIELD) do
+ begin
+ end;
+end;
+
+procedure RIRegisterTDATETIMEFIELD(Cl: TPSRuntimeClassImporter);
+Begin
+with Cl.Add(TDATETIMEFIELD) do
+ begin
+ RegisterPropertyHelper(@TDATETIMEFIELDVALUE_R,@TDATETIMEFIELDVALUE_W,'VALUE');
+ RegisterPropertyHelper(@TDATETIMEFIELDDISPLAYFORMAT_R,@TDATETIMEFIELDDISPLAYFORMAT_W,'DISPLAYFORMAT');
+ end;
+end;
+
+procedure RIRegisterTBOOLEANFIELD(Cl: TPSRuntimeClassImporter);
+Begin
+with Cl.Add(TBOOLEANFIELD) do
+ begin
+ RegisterPropertyHelper(@TBOOLEANFIELDVALUE_R,@TBOOLEANFIELDVALUE_W,'VALUE');
+ RegisterPropertyHelper(@TBOOLEANFIELDDISPLAYVALUES_R,@TBOOLEANFIELDDISPLAYVALUES_W,'DISPLAYVALUES');
+ end;
+end;
+
+procedure RIRegisterTCURRENCYFIELD(Cl: TPSRuntimeClassImporter);
+Begin
+with Cl.Add(TCURRENCYFIELD) do
+ begin
+ end;
+end;
+
+procedure RIRegisterTFLOATFIELD(Cl: TPSRuntimeClassImporter);
+Begin
+with Cl.Add(TFLOATFIELD) do
+ begin
+ {$IFNDEF FPC}
+ RegisterPropertyHelper(@TFLOATFIELDCURRENCY_R,@TFLOATFIELDCURRENCY_W,'CURRENCY');
+ {$ENDIF}
+ RegisterPropertyHelper(@TFLOATFIELDVALUE_R,@TFLOATFIELDVALUE_W,'VALUE');
+ RegisterPropertyHelper(@TFLOATFIELDMAXVALUE_R,@TFLOATFIELDMAXVALUE_W,'MAXVALUE');
+ RegisterPropertyHelper(@TFLOATFIELDMINVALUE_R,@TFLOATFIELDMINVALUE_W,'MINVALUE');
+ RegisterPropertyHelper(@TFLOATFIELDPRECISION_R,@TFLOATFIELDPRECISION_W,'PRECISION');
+ end;
+end;
+
+procedure RIRegisterTAUTOINCFIELD(Cl: TPSRuntimeClassImporter);
+Begin
+with Cl.Add(TAUTOINCFIELD) do
+ begin
+ end;
+end;
+
+procedure RIRegisterTWORDFIELD(Cl: TPSRuntimeClassImporter);
+Begin
+with Cl.Add(TWORDFIELD) do
+ begin
+ end;
+end;
+
+procedure RIRegisterTLARGEINTFIELD(Cl: TPSRuntimeClassImporter);
+Begin
+with Cl.Add(TLARGEINTFIELD) do
+ begin
+ RegisterPropertyHelper(@TLARGEINTFIELDASLARGEINT_R,@TLARGEINTFIELDASLARGEINT_W,'ASLARGEINT');
+ RegisterPropertyHelper(@TLARGEINTFIELDVALUE_R,@TLARGEINTFIELDVALUE_W,'VALUE');
+ RegisterPropertyHelper(@TLARGEINTFIELDMAXVALUE_R,@TLARGEINTFIELDMAXVALUE_W,'MAXVALUE');
+ RegisterPropertyHelper(@TLARGEINTFIELDMINVALUE_R,@TLARGEINTFIELDMINVALUE_W,'MINVALUE');
+ end;
+end;
+
+procedure RIRegisterTSMALLINTFIELD(Cl: TPSRuntimeClassImporter);
+Begin
+with Cl.Add(TSMALLINTFIELD) do
+ begin
+ end;
+end;
+
+procedure RIRegisterTINTEGERFIELD(Cl: TPSRuntimeClassImporter);
+Begin
+with Cl.Add(TINTEGERFIELD) do
+ begin
+ RegisterPropertyHelper(@TINTEGERFIELDVALUE_R,@TINTEGERFIELDVALUE_W,'VALUE');
+ RegisterPropertyHelper(@TINTEGERFIELDMAXVALUE_R,@TINTEGERFIELDMAXVALUE_W,'MAXVALUE');
+ RegisterPropertyHelper(@TINTEGERFIELDMINVALUE_R,@TINTEGERFIELDMINVALUE_W,'MINVALUE');
+ end;
+end;
+
+procedure RIRegisterTNUMERICFIELD(Cl: TPSRuntimeClassImporter);
+Begin
+with Cl.Add(TNUMERICFIELD) do
+ begin
+ RegisterPropertyHelper(@TNUMERICFIELDDISPLAYFORMAT_R,@TNUMERICFIELDDISPLAYFORMAT_W,'DISPLAYFORMAT');
+ RegisterPropertyHelper(@TNUMERICFIELDEDITFORMAT_R,@TNUMERICFIELDEDITFORMAT_W,'EDITFORMAT');
+ end;
+end;
+
+{$IFNDEF FPC}
+procedure RIRegisterTWIDESTRINGFIELD(Cl: TPSRuntimeClassImporter);
+Begin
+with Cl.Add(TWIDESTRINGFIELD) do
+ begin
+ RegisterPropertyHelper(@TWIDESTRINGFIELDVALUE_R,@TWIDESTRINGFIELDVALUE_W,'VALUE');
+ end;
+end;
+{$ENDIF}
+
+procedure RIRegisterTSTRINGFIELD(Cl: TPSRuntimeClassImporter);
+Begin
+with Cl.Add(TSTRINGFIELD) do
+ begin
+ RegisterPropertyHelper(@TSTRINGFIELDVALUE_R,@TSTRINGFIELDVALUE_W,'VALUE');
+ {$IFNDEF FPC}
+ RegisterPropertyHelper(@TSTRINGFIELDFIXEDCHAR_R,@TSTRINGFIELDFIXEDCHAR_W,'FIXEDCHAR');
+ RegisterPropertyHelper(@TSTRINGFIELDTRANSLITERATE_R,@TSTRINGFIELDTRANSLITERATE_W,'TRANSLITERATE');
+ {$ENDIF}
+ end;
+end;
+
+procedure RIRegisterTFIELD(Cl: TPSRuntimeClassImporter);
+Begin
+with Cl.Add(TFIELD) do
+ begin
+ RegisterMethod(@TFIELD.ASSIGNVALUE, 'ASSIGNVALUE');
+ RegisterVirtualMethod(@TFIELD.CLEAR, 'CLEAR');
+ RegisterMethod(@TFIELD.FOCUSCONTROL, 'FOCUSCONTROL');
+// RegisterMethod(@TFIELD.GETDATA, 'GETDATA');
+ RegisterVirtualMethod(@TFIELD.ISVALIDCHAR, 'ISVALIDCHAR');
+ RegisterMethod(@TFIELD.REFRESHLOOKUPLIST, 'REFRESHLOOKUPLIST');
+// RegisterMethod(@TFIELD.SETDATA, 'SETDATA');
+ RegisterVirtualMethod(@TFIELD.SETFIELDTYPE, 'SETFIELDTYPE');
+// RegisterMethod(@TFIELD.VALIDATE, 'VALIDATE');
+{$IFNDEF FPC}
+
+ RegisterPropertyHelper(@TFIELDEDITMASK_R,@TFIELDEDITMASK_W,'EDITMASK');
+ RegisterPropertyHelper(@TFIELDEDITMASKPTR_R,nil,'EDITMASKPTR');
+ RegisterPropertyHelper(@TFIELDEDITMASK_R,@TFIELDEDITMASK_W,'EDITMASK');
+ RegisterPropertyHelper(@TFIELDEDITMASKPTR_R,nil,'EDITMASKPTR');
+ RegisterPropertyHelper(@TFIELDFULLNAME_R,nil,'FULLNAME');
+ RegisterPropertyHelper(@TFIELDLOOKUP_R,@TFIELDLOOKUP_W,'LOOKUP');
+ RegisterPropertyHelper(@TFIELDPARENTFIELD_R,@TFIELDPARENTFIELD_W,'PARENTFIELD');
+ RegisterPropertyHelper(@TFIELDVALIDCHARS_R,@TFIELDVALIDCHARS_W,'VALIDCHARS');
+ RegisterPropertyHelper(@TFIELDAUTOGENERATEVALUE_R,@TFIELDAUTOGENERATEVALUE_W,'AUTOGENERATEVALUE');
+
+{$IFDEF DELPHI6UP}
+ RegisterPropertyHelper(@TFIELDASBCD_R,@TFIELDASBCD_W,'ASBCD');
+{$ENDIF}
+{$ENDIF}
+ RegisterPropertyHelper(@TFIELDASBOOLEAN_R,@TFIELDASBOOLEAN_W,'ASBOOLEAN');
+ RegisterPropertyHelper(@TFIELDASCURRENCY_R,@TFIELDASCURRENCY_W,'ASCURRENCY');
+ RegisterPropertyHelper(@TFIELDASDATETIME_R,@TFIELDASDATETIME_W,'ASDATETIME');
+ RegisterPropertyHelper(@TFIELDASFLOAT_R,@TFIELDASFLOAT_W,'ASFLOAT');
+ RegisterPropertyHelper(@TFIELDASINTEGER_R,@TFIELDASINTEGER_W,'ASINTEGER');
+ RegisterPropertyHelper(@TFIELDASSTRING_R,@TFIELDASSTRING_W,'ASSTRING');
+ RegisterPropertyHelper(@TFIELDASVARIANT_R,@TFIELDASVARIANT_W,'ASVARIANT');
+ RegisterPropertyHelper(@TFIELDATTRIBUTESET_R,@TFIELDATTRIBUTESET_W,'ATTRIBUTESET');
+ RegisterPropertyHelper(@TFIELDCALCULATED_R,@TFIELDCALCULATED_W,'CALCULATED');
+ RegisterPropertyHelper(@TFIELDCANMODIFY_R,nil,'CANMODIFY');
+ RegisterPropertyHelper(@TFIELDCURVALUE_R,nil,'CURVALUE');
+ RegisterPropertyHelper(@TFIELDDATASET_R,@TFIELDDATASET_W,'DATASET');
+ RegisterPropertyHelper(@TFIELDDATASIZE_R,nil,'DATASIZE');
+ RegisterPropertyHelper(@TFIELDDATATYPE_R,nil,'DATATYPE');
+ RegisterPropertyHelper(@TFIELDDISPLAYNAME_R,nil,'DISPLAYNAME');
+ RegisterPropertyHelper(@TFIELDDISPLAYTEXT_R,nil,'DISPLAYTEXT');
+ RegisterPropertyHelper(@TFIELDFIELDNO_R,nil,'FIELDNO');
+ RegisterPropertyHelper(@TFIELDISINDEXFIELD_R,nil,'ISINDEXFIELD');
+ RegisterPropertyHelper(@TFIELDISNULL_R,nil,'ISNULL');
+ RegisterPropertyHelper(@TFIELDLOOKUPLIST_R,nil,'LOOKUPLIST');
+ RegisterPropertyHelper(@TFIELDNEWVALUE_R,@TFIELDNEWVALUE_W,'NEWVALUE');
+ RegisterPropertyHelper(@TFIELDOFFSET_R,nil,'OFFSET');
+ RegisterPropertyHelper(@TFIELDOLDVALUE_R,nil,'OLDVALUE');
+ RegisterPropertyHelper(@TFIELDSIZE_R,@TFIELDSIZE_W,'SIZE');
+ RegisterPropertyHelper(@TFIELDTEXT_R,@TFIELDTEXT_W,'TEXT');
+ RegisterPropertyHelper(@TFIELDVALUE_R,@TFIELDVALUE_W,'VALUE');
+ RegisterPropertyHelper(@TFIELDALIGNMENT_R,@TFIELDALIGNMENT_W,'ALIGNMENT');
+ RegisterPropertyHelper(@TFIELDCUSTOMCONSTRAINT_R,@TFIELDCUSTOMCONSTRAINT_W,'CUSTOMCONSTRAINT');
+ RegisterPropertyHelper(@TFIELDCONSTRAINTERRORMESSAGE_R,@TFIELDCONSTRAINTERRORMESSAGE_W,'CONSTRAINTERRORMESSAGE');
+ RegisterPropertyHelper(@TFIELDDEFAULTEXPRESSION_R,@TFIELDDEFAULTEXPRESSION_W,'DEFAULTEXPRESSION');
+ RegisterPropertyHelper(@TFIELDDISPLAYLABEL_R,@TFIELDDISPLAYLABEL_W,'DISPLAYLABEL');
+ RegisterPropertyHelper(@TFIELDDISPLAYWIDTH_R,@TFIELDDISPLAYWIDTH_W,'DISPLAYWIDTH');
+ RegisterPropertyHelper(@TFIELDFIELDKIND_R,@TFIELDFIELDKIND_W,'FIELDKIND');
+ RegisterPropertyHelper(@TFIELDFIELDNAME_R,@TFIELDFIELDNAME_W,'FIELDNAME');
+ RegisterPropertyHelper(@TFIELDHASCONSTRAINTS_R,nil,'HASCONSTRAINTS');
+ RegisterPropertyHelper(@TFIELDINDEX_R,@TFIELDINDEX_W,'INDEX');
+ RegisterPropertyHelper(@TFIELDIMPORTEDCONSTRAINT_R,@TFIELDIMPORTEDCONSTRAINT_W,'IMPORTEDCONSTRAINT');
+ RegisterPropertyHelper(@TFIELDLOOKUPDATASET_R,@TFIELDLOOKUPDATASET_W,'LOOKUPDATASET');
+ RegisterPropertyHelper(@TFIELDLOOKUPKEYFIELDS_R,@TFIELDLOOKUPKEYFIELDS_W,'LOOKUPKEYFIELDS');
+ RegisterPropertyHelper(@TFIELDLOOKUPRESULTFIELD_R,@TFIELDLOOKUPRESULTFIELD_W,'LOOKUPRESULTFIELD');
+ RegisterPropertyHelper(@TFIELDKEYFIELDS_R,@TFIELDKEYFIELDS_W,'KEYFIELDS');
+ RegisterPropertyHelper(@TFIELDLOOKUPCACHE_R,@TFIELDLOOKUPCACHE_W,'LOOKUPCACHE');
+ RegisterPropertyHelper(@TFIELDORIGIN_R,@TFIELDORIGIN_W,'ORIGIN');
+ RegisterPropertyHelper(@TFIELDPROVIDERFLAGS_R,@TFIELDPROVIDERFLAGS_W,'PROVIDERFLAGS');
+ RegisterPropertyHelper(@TFIELDREADONLY_R,@TFIELDREADONLY_W,'READONLY');
+ RegisterPropertyHelper(@TFIELDREQUIRED_R,@TFIELDREQUIRED_W,'REQUIRED');
+ RegisterPropertyHelper(@TFIELDVISIBLE_R,@TFIELDVISIBLE_W,'VISIBLE');
+ RegisterEventPropertyHelper(@TFIELDONCHANGE_R,@TFIELDONCHANGE_W,'ONCHANGE');
+ RegisterEventPropertyHelper(@TFIELDONGETTEXT_R,@TFIELDONGETTEXT_W,'ONGETTEXT');
+ RegisterEventPropertyHelper(@TFIELDONSETTEXT_R,@TFIELDONSETTEXT_W,'ONSETTEXT');
+ RegisterEventPropertyHelper(@TFIELDONVALIDATE_R,@TFIELDONVALIDATE_W,'ONVALIDATE');
+ end;
+end;
+
+procedure RIRegisterTLOOKUPLIST(Cl: TPSRuntimeClassImporter);
+Begin
+with Cl.Add(TLOOKUPLIST) do
+ begin
+ RegisterConstructor(@TLOOKUPLIST.CREATE, 'CREATE');
+ {$IFDEF DELPHI2009UP}
+ RegisterVirtualAbstractMethod(TDefaultLookupList, @TDefaultLookupList.ADD, 'ADD');
+ RegisterVirtualAbstractMethod(TDefaultLookupList, @TDefaultLookupList.CLEAR, 'CLEAR');
+ RegisterVirtualAbstractMethod(TDefaultLookupList, @TDefaultLookupList.VALUEOFKEY, 'VALUEOFKEY');
+ {$ELSE}
+ RegisterMethod(@TLOOKUPLIST.ADD, 'ADD');
+ RegisterMethod(@TLOOKUPLIST.CLEAR, 'CLEAR');
+ RegisterMethod(@TLOOKUPLIST.VALUEOFKEY, 'VALUEOFKEY');
+ {$ENDIF}
+ end;
+end;
+
+procedure RIRegisterTFIELDS(Cl: TPSRuntimeClassImporter);
+Begin
+with Cl.Add(TFIELDS) do
+ begin
+ RegisterConstructor(@TFIELDS.CREATE, 'CREATE');
+ RegisterMethod(@TFIELDS.ADD, 'ADD');
+ RegisterMethod(@TFIELDS.CHECKFIELDNAME, 'CHECKFIELDNAME');
+ RegisterMethod(@TFIELDS.CHECKFIELDNAMES, 'CHECKFIELDNAMES');
+ RegisterMethod(@TFIELDS.CLEAR, 'CLEAR');
+ RegisterMethod(@TFIELDS.FINDFIELD, 'FINDFIELD');
+ RegisterMethod(@TFIELDS.FIELDBYNAME, 'FIELDBYNAME');
+ RegisterMethod(@TFIELDS.FIELDBYNUMBER, 'FIELDBYNUMBER');
+ RegisterMethod(@TFIELDS.GETFIELDNAMES, 'GETFIELDNAMES');
+ RegisterMethod(@TFIELDS.INDEXOF, 'INDEXOF');
+ RegisterMethod(@TFIELDS.REMOVE, 'REMOVE');
+ RegisterPropertyHelper(@TFIELDSCOUNT_R,nil,'COUNT');
+ RegisterPropertyHelper(@TFIELDSDATASET_R,nil,'DATASET');
+ RegisterPropertyHelper(@TFIELDSFIELDS_R,@TFIELDSFIELDS_W,'FIELDS');
+ end;
+end;
+
+{$IFNDEF FPC}
+procedure RIRegisterTFIELDLIST(Cl: TPSRuntimeClassImporter);
+Begin
+with Cl.Add(TFIELDLIST) do
+ begin
+ RegisterMethod(@TFIELDLIST.FIELDBYNAME, 'FIELDBYNAME');
+ RegisterMethod(@TFIELDLIST.FIND, 'FIND');
+ RegisterPropertyHelper(@TFIELDLISTFIELDS_R,nil,'FIELDS');
+ end;
+end;
+
+procedure RIRegisterTFIELDDEFLIST(Cl: TPSRuntimeClassImporter);
+Begin
+with Cl.Add(TFIELDDEFLIST) do
+ begin
+ RegisterMethod(@TFIELDDEFLIST.FIELDBYNAME, 'FIELDBYNAME');
+ RegisterMethod(@TFIELDDEFLIST.FIND, 'FIND');
+ RegisterPropertyHelper(@TFIELDDEFLISTFIELDDEFS_R,nil,'FIELDDEFS');
+ end;
+end;
+
+
+procedure RIRegisterTFLATLIST(Cl: TPSRuntimeClassImporter);
+Begin
+with Cl.Add(TFLATLIST) do
+ begin
+ RegisterConstructor(@TFLATLIST.CREATE, 'CREATE');
+ RegisterMethod(@TFLATLIST.UPDATE, 'UPDATE');
+ RegisterPropertyHelper(@TFLATLISTDATASET_R,nil,'DATASET');
+ end;
+end;
+{$ENDIF}
+
+
+procedure RIRegisterTINDEXDEFS(Cl: TPSRuntimeClassImporter);
+Begin
+with Cl.Add(TINDEXDEFS) do
+ begin
+ RegisterConstructor(@TINDEXDEFS.CREATE, 'CREATE');
+ RegisterMethod(@TINDEXDEFS.ADDINDEXDEF, 'ADDINDEXDEF');
+ RegisterMethod(@TINDEXDEFS.FIND, 'FIND');
+ RegisterMethod(@TINDEXDEFS.UPDATE, 'UPDATE');
+ RegisterMethod(@TINDEXDEFS.FINDINDEXFORFIELDS, 'FINDINDEXFORFIELDS');
+ RegisterMethod(@TINDEXDEFS.GETINDEXFORFIELDS, 'GETINDEXFORFIELDS');
+ RegisterMethod(@TINDEXDEFS.ADD, 'ADD');
+ RegisterPropertyHelper(@TINDEXDEFSITEMS_R,@TINDEXDEFSITEMS_W,'ITEMS');
+ end;
+end;
+
+procedure RIRegisterTINDEXDEF(Cl: TPSRuntimeClassImporter);
+Begin
+with Cl.Add(TINDEXDEF) do
+ begin
+ RegisterConstructor(@TINDEXDEF.CREATE, 'CREATE');
+{$IFNDEF FPC}
+ RegisterPropertyHelper(@TINDEXDEFFIELDEXPRESSION_R,nil,'FIELDEXPRESSION');
+ RegisterPropertyHelper(@TINDEXDEFCASEINSFIELDS_R,@TINDEXDEFCASEINSFIELDS_W,'CASEINSFIELDS');
+ RegisterPropertyHelper(@TINDEXDEFGROUPINGLEVEL_R,@TINDEXDEFGROUPINGLEVEL_W,'GROUPINGLEVEL');
+ RegisterPropertyHelper(@TINDEXDEFDESCFIELDS_R,@TINDEXDEFDESCFIELDS_W,'DESCFIELDS');
+
+{$ENDIF}
+ RegisterPropertyHelper(@TINDEXDEFEXPRESSION_R,@TINDEXDEFEXPRESSION_W,'EXPRESSION');
+ RegisterPropertyHelper(@TINDEXDEFFIELDS_R,@TINDEXDEFFIELDS_W,'FIELDS');
+ RegisterPropertyHelper(@TINDEXDEFOPTIONS_R,@TINDEXDEFOPTIONS_W,'OPTIONS');
+ RegisterPropertyHelper(@TINDEXDEFSOURCE_R,@TINDEXDEFSOURCE_W,'SOURCE');
+ end;
+end;
+
+procedure RIRegisterTFIELDDEFS(Cl: TPSRuntimeClassImporter);
+Begin
+with Cl.Add(TFIELDDEFS) do
+ begin
+ RegisterConstructor(@TFIELDDEFS.CREATE, 'CREATE');
+ RegisterMethod(@TFIELDDEFS.ADDFIELDDEF, 'ADDFIELDDEF');
+ RegisterMethod(@TFIELDDEFS.FIND, 'FIND');
+ RegisterMethod(@TFIELDDEFS.UPDATE, 'UPDATE');
+{$IFNDEF FPC}
+ RegisterMethod(@TFIELDDEFS.ADD, 'ADD');
+ RegisterPropertyHelper(@TFIELDDEFSPARENTDEF_R,nil,'PARENTDEF');
+
+{$ENDIF}
+ RegisterPropertyHelper(@TFIELDDEFSHIDDENFIELDS_R,@TFIELDDEFSHIDDENFIELDS_W,'HIDDENFIELDS');
+ RegisterPropertyHelper(@TFIELDDEFSITEMS_R,@TFIELDDEFSITEMS_W,'ITEMS');
+ end;
+end;
+
+procedure RIRegisterTFIELDDEF(Cl: TPSRuntimeClassImporter);
+Begin
+with Cl.Add(TFIELDDEF) do
+ begin
+// RegisterConstructor(@TFIELDDEF.CREATE, 'CREATE');
+{$IFNDEF FPC}
+ RegisterMethod(@TFIELDDEF.ADDCHILD, 'ADDCHILD');
+ RegisterMethod(@TFIELDDEF.HASCHILDDEFS, 'HASCHILDDEFS');
+
+{$ENDIF}
+ RegisterMethod(@TFIELDDEF.CREATEFIELD, 'CREATEFIELD');
+{$IFNDEF FPC}
+ RegisterPropertyHelper(@TFIELDDEFFIELDNO_R,@TFIELDDEFFIELDNO_W,'FIELDNO');
+ RegisterPropertyHelper(@TFIELDDEFPARENTDEF_R,nil,'PARENTDEF');
+ RegisterPropertyHelper(@TFIELDDEFCHILDDEFS_R,@TFIELDDEFCHILDDEFS_W,'CHILDDEFS');
+ RegisterPropertyHelper(@TFIELDDEFREQUIRED_R,@TFIELDDEFREQUIRED_W,'REQUIRED');
+
+{$ENDIF}
+ RegisterPropertyHelper(@TFIELDDEFFIELDCLASS_R,nil,'FIELDCLASS');
+ RegisterPropertyHelper(@TFIELDDEFINTERNALCALCFIELD_R,@TFIELDDEFINTERNALCALCFIELD_W,'INTERNALCALCFIELD');
+ RegisterPropertyHelper(@TFIELDDEFATTRIBUTES_R,@TFIELDDEFATTRIBUTES_W,'ATTRIBUTES');
+ RegisterPropertyHelper(@TFIELDDEFDATATYPE_R,@TFIELDDEFDATATYPE_W,'DATATYPE');
+ RegisterPropertyHelper(@TFIELDDEFPRECISION_R,@TFIELDDEFPRECISION_W,'PRECISION');
+ RegisterPropertyHelper(@TFIELDDEFSIZE_R,@TFIELDDEFSIZE_W,'SIZE');
+ end;
+end;
+
+{$IFNDEF FPC}
+procedure RIRegisterTDEFCOLLECTION(Cl: TPSRuntimeClassImporter);
+Begin
+with Cl.Add(TDEFCOLLECTION) do
+ begin
+ RegisterConstructor(@TDEFCOLLECTION.CREATE, 'CREATE');
+ RegisterMethod(@TDEFCOLLECTION.FIND, 'FIND');
+ RegisterMethod(@TDEFCOLLECTION.GETITEMNAMES, 'GETITEMNAMES');
+ RegisterMethod(@TDEFCOLLECTION.INDEXOF, 'INDEXOF');
+ RegisterPropertyHelper(@TDEFCOLLECTIONDATASET_R,nil,'DATASET');
+ RegisterPropertyHelper(@TDEFCOLLECTIONUPDATED_R,@TDEFCOLLECTIONUPDATED_W,'UPDATED');
+ end;
+end;
+
+procedure RIRegisterTNAMEDITEM(Cl: TPSRuntimeClassImporter);
+Begin
+with Cl.Add(TNAMEDITEM) do
+ begin
+ RegisterPropertyHelper(@TNAMEDITEMNAME_R,@TNAMEDITEMNAME_W,'NAME');
+ end;
+end;
+{$ENDIF}
+
+
+procedure RIRegister_DB(CL: TPSRuntimeClassImporter);
+Begin
+RIRegisterTFIELDDEF(Cl);
+RIRegisterTFIELDDEFS(Cl);
+RIRegisterTINDEXDEF(Cl);
+RIRegisterTINDEXDEFS(Cl);
+RIRegisterTFIELDS(Cl);
+RIRegisterTLOOKUPLIST(Cl);
+RIRegisterTFIELD(Cl);
+RIRegisterTSTRINGFIELD(Cl);
+RIRegisterTNUMERICFIELD(Cl);
+RIRegisterTINTEGERFIELD(Cl);
+RIRegisterTSMALLINTFIELD(Cl);
+RIRegisterTLARGEINTFIELD(Cl);
+RIRegisterTWORDFIELD(Cl);
+RIRegisterTAUTOINCFIELD(Cl);
+RIRegisterTFLOATFIELD(Cl);
+RIRegisterTCURRENCYFIELD(Cl);
+RIRegisterTBOOLEANFIELD(Cl);
+RIRegisterTDATETIMEFIELD(Cl);
+RIRegisterTDATEFIELD(Cl);
+RIRegisterTTIMEFIELD(Cl);
+RIRegisterTBINARYFIELD(Cl);
+RIRegisterTBYTESFIELD(Cl);
+RIRegisterTVARBYTESFIELD(Cl);
+{$IFNDEF FPC}
+RIRegisterTNAMEDITEM(Cl);
+RIRegisterTDEFCOLLECTION(Cl);
+RIRegisterTWIDESTRINGFIELD(Cl);
+RIRegisterTFLATLIST(Cl);
+RIRegisterTFIELDDEFLIST(Cl);
+RIRegisterTFIELDLIST(Cl);
+RIRegisterTBCDFIELD(Cl);
+{$IFDEF DELPHI6UP}
+RIRegisterTFMTBCDFIELD(Cl);
+{$ENDIF}
+{$ENDIF}
+
+RIRegisterTBLOBFIELD(Cl);
+RIRegisterTMEMOFIELD(Cl);
+RIRegisterTGRAPHICFIELD(Cl);
+{$IFNDEF FPC}
+RIRegisterTOBJECTFIELD(Cl);
+RIRegisterTADTFIELD(Cl);
+RIRegisterTARRAYFIELD(Cl);
+RIRegisterTDATASETFIELD(Cl);
+RIRegisterTREFERENCEFIELD(Cl);
+RIRegisterTVARIANTFIELD(Cl);
+RIRegisterTGUIDFIELD(Cl);
+{$ENDIF}
+RIRegisterTPARAM(Cl);
+RIRegisterTPARAMS(Cl);
+RIRegisterTDATASET(Cl);
+end;
+
+{$IFDEF USEIMPORTER}
+initialization
+RIImporter.Invoke(RIRegister_DB);
+{$ENDIF}
+end.
diff --git a/branches/script-component/Units/PascalScript/uPSR_buttons.pas b/branches/script-component/Units/PascalScript/uPSR_buttons.pas
new file mode 100644
index 0000000..ea4454c
--- /dev/null
+++ b/branches/script-component/Units/PascalScript/uPSR_buttons.pas
@@ -0,0 +1,38 @@
+
+unit uPSR_buttons;
+{$I PascalScript.inc}
+interface
+uses
+ uPSRuntime, uPSUtils;
+
+
+procedure RIRegisterTSPEEDBUTTON(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTBITBTN(Cl: TPSRuntimeClassImporter);
+
+procedure RIRegister_Buttons(Cl: TPSRuntimeClassImporter);
+
+implementation
+uses
+ Classes{$IFDEF CLX}, QControls, QButtons{$ELSE}, Controls, Buttons{$ENDIF};
+
+procedure RIRegisterTSPEEDBUTTON(Cl: TPSRuntimeClassImporter);
+begin
+ Cl.Add(TSPEEDBUTTON);
+end;
+
+
+procedure RIRegisterTBITBTN(Cl: TPSRuntimeClassImporter);
+begin
+ Cl.Add(TBITBTN);
+end;
+
+procedure RIRegister_Buttons(Cl: TPSRuntimeClassImporter);
+begin
+ RIRegisterTSPEEDBUTTON(cl);
+ RIRegisterTBITBTN(cl);
+end;
+
+// PS_MINIVCL changes by Martijn Laan (mlaan at wintax _dot_ nl)
+
+
+end.
diff --git a/branches/script-component/Units/PascalScript/uPSR_classes.pas b/branches/script-component/Units/PascalScript/uPSR_classes.pas
new file mode 100644
index 0000000..7729d49
--- /dev/null
+++ b/branches/script-component/Units/PascalScript/uPSR_classes.pas
@@ -0,0 +1,383 @@
+
+unit uPSR_classes;
+
+{$I PascalScript.inc}
+interface
+uses
+ uPSRuntime, uPSUtils;
+
+
+procedure RIRegisterTStrings(cl: TPSRuntimeClassImporter; Streams: Boolean);
+procedure RIRegisterTStringList(cl: TPSRuntimeClassImporter);
+{$IFNDEF PS_MINIVCL}
+procedure RIRegisterTBITS(Cl: TPSRuntimeClassImporter);
+{$ENDIF}
+procedure RIRegisterTSTREAM(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTHANDLESTREAM(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTFILESTREAM(Cl: TPSRuntimeClassImporter);
+{$IFNDEF PS_MINIVCL}
+procedure RIRegisterTCUSTOMMEMORYSTREAM(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTMEMORYSTREAM(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTRESOURCESTREAM(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTPARSER(Cl: TPSRuntimeClassImporter);
+{$IFDEF DELPHI3UP}
+procedure RIRegisterTOWNEDCOLLECTION(Cl: TPSRuntimeClassImporter);
+{$ENDIF}
+procedure RIRegisterTCOLLECTION(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTCOLLECTIONITEM(Cl: TPSRuntimeClassImporter);
+{$ENDIF}
+
+procedure RIRegister_Classes(Cl: TPSRuntimeClassImporter; Streams: Boolean{$IFDEF D4PLUS}=True{$ENDIF});
+
+implementation
+uses
+ Classes;
+
+procedure TStringsCountR(Self: TStrings; var T: Longint); begin T := Self.Count; end;
+
+procedure TStringsTextR(Self: TStrings; var T: string); begin T := Self.Text; end;
+procedure TStringsTextW(Self: TStrings; T: string); begin Self.Text:= T; end;
+
+procedure TStringsCommaTextR(Self: TStrings; var T: string); begin T := Self.CommaText; end;
+procedure TStringsCommaTextW(Self: TStrings; T: string); begin Self.CommaText:= T; end;
+
+procedure TStringsObjectsR(Self: TStrings; var T: TObject; I: Longint);
+begin
+T := Self.Objects[I];
+end;
+procedure TStringsObjectsW(Self: TStrings; const T: TObject; I: Longint);
+begin
+ Self.Objects[I]:= T;
+end;
+
+procedure TStringsStringsR(Self: TStrings; var T: string; I: Longint);
+begin
+T := Self.Strings[I];
+end;
+procedure TStringsStringsW(Self: TStrings; const T: string; I: Longint);
+begin
+ Self.Strings[I]:= T;
+end;
+
+procedure TStringsNamesR(Self: TStrings; var T: string; I: Longint);
+begin
+T := Self.Names[I];
+end;
+procedure TStringsValuesR(Self: TStrings; var T: string; const I: string);
+begin
+T := Self.Values[I];
+end;
+procedure TStringsValuesW(Self: TStrings; Const T, I: String);
+begin
+ Self.Values[I]:= T;
+end;
+
+procedure RIRegisterTStrings(cl: TPSRuntimeClassImporter; Streams: Boolean); // requires TPersistent
+begin
+ with Cl.Add(TStrings) do
+ begin
+ RegisterVirtualMethod(@TStrings.Add, 'ADD');
+ RegisterMethod(@TStrings.Append, 'APPEND');
+ RegisterVirtualMethod(@TStrings.AddStrings, 'ADDSTRINGS');
+ RegisterVirtualAbstractMethod(TStringList, @TStringList.Clear, 'CLEAR');
+ RegisterVirtualAbstractMethod(TStringList, @TStringList.Delete, 'DELETE');
+ RegisterVirtualMethod(@TStrings.IndexOf, 'INDEXOF');
+ RegisterVirtualAbstractMethod(TStringList, @TStringList.Insert, 'INSERT');
+ RegisterPropertyHelper(@TStringsCountR, nil, 'COUNT');
+ RegisterPropertyHelper(@TStringsTextR, @TStringsTextW, 'TEXT');
+ RegisterPropertyHelper(@TStringsCommaTextR, @TStringsCommatextW, 'COMMATEXT');
+ if Streams then
+ begin
+ RegisterVirtualMethod(@TStrings.LoadFromFile, 'LOADFROMFILE');
+ RegisterVirtualMethod(@TStrings.SaveToFile, 'SAVETOFILE');
+ end;
+ RegisterPropertyHelper(@TStringsStringsR, @TStringsStringsW, 'STRINGS');
+ RegisterPropertyHelper(@TStringsObjectsR, @TStringsObjectsW, 'OBJECTS');
+
+ {$IFNDEF PS_MINIVCL}
+ RegisterMethod(@TStrings.BeginUpdate, 'BEGINUPDATE');
+ RegisterMethod(@TStrings.EndUpdate, 'ENDUPDATE');
+ RegisterMethod(@TStrings.Equals, 'EQUALS');
+ RegisterVirtualMethod(@TStrings.Exchange, 'EXCHANGE');
+ RegisterMethod(@TStrings.IndexOfName, 'INDEXOFNAME');
+ if Streams then
+ RegisterVirtualMethod(@TStrings.LoadFromStream, 'LOADFROMSTREAM');
+ RegisterVirtualMethod(@TStrings.Move, 'MOVE');
+ if Streams then
+ RegisterVirtualMethod(@TStrings.SaveToStream, 'SAVETOSTREAM');
+ RegisterVirtualMethod(@TStrings.SetText, 'SETTEXT');
+ RegisterPropertyHelper(@TStringsNamesR, nil, 'NAMES');
+ RegisterPropertyHelper(@TStringsValuesR, @TStringsValuesW, 'VALUES');
+ RegisterVirtualMethod(@TSTRINGS.ADDOBJECT, 'ADDOBJECT');
+ RegisterVirtualMethod(@TSTRINGS.GETTEXT, 'GETTEXT');
+ RegisterMethod(@TSTRINGS.INDEXOFOBJECT, 'INDEXOFOBJECT');
+ RegisterMethod(@TSTRINGS.INSERTOBJECT, 'INSERTOBJECT');
+ {$ENDIF}
+ end;
+end;
+
+procedure TSTRINGLISTDUPLICATES_R(Self: TSTRINGLIST; var T: TDUPLICATES); begin T := Self.DUPLICATES; end;
+procedure TSTRINGLISTDUPLICATES_W(Self: TSTRINGLIST; const T: TDUPLICATES); begin Self.DUPLICATES := T; end;
+procedure TSTRINGLISTSORTED_R(Self: TSTRINGLIST; var T: BOOLEAN); begin T := Self.SORTED; end;
+procedure TSTRINGLISTSORTED_W(Self: TSTRINGLIST; const T: BOOLEAN); begin Self.SORTED := T; end;
+procedure TSTRINGLISTONCHANGE_R(Self: TSTRINGLIST; var T: TNOTIFYEVENT);
+begin
+T := Self.ONCHANGE; end;
+procedure TSTRINGLISTONCHANGE_W(Self: TSTRINGLIST; const T: TNOTIFYEVENT);
+begin
+Self.ONCHANGE := T; end;
+procedure TSTRINGLISTONCHANGING_R(Self: TSTRINGLIST; var T: TNOTIFYEVENT); begin T := Self.ONCHANGING; end;
+procedure TSTRINGLISTONCHANGING_W(Self: TSTRINGLIST; const T: TNOTIFYEVENT); begin Self.ONCHANGING := T; end;
+procedure RIRegisterTSTRINGLIST(Cl: TPSRuntimeClassImporter);
+begin
+ with Cl.Add(TSTRINGLIST) do
+ begin
+ RegisterVirtualMethod(@TSTRINGLIST.FIND, 'FIND');
+ RegisterVirtualMethod(@TSTRINGLIST.SORT, 'SORT');
+ RegisterPropertyHelper(@TSTRINGLISTDUPLICATES_R, @TSTRINGLISTDUPLICATES_W, 'DUPLICATES');
+ RegisterPropertyHelper(@TSTRINGLISTSORTED_R, @TSTRINGLISTSORTED_W, 'SORTED');
+ RegisterEventPropertyHelper(@TSTRINGLISTONCHANGE_R, @TSTRINGLISTONCHANGE_W, 'ONCHANGE');
+ RegisterEventPropertyHelper(@TSTRINGLISTONCHANGING_R, @TSTRINGLISTONCHANGING_W, 'ONCHANGING');
+ end;
+end;
+
+{$IFNDEF PS_MINIVCL}
+procedure TBITSBITS_W(Self: TBITS; T: BOOLEAN; t1: INTEGER); begin Self.BITS[t1] := T; end;
+procedure TBITSBITS_R(Self: TBITS; var T: BOOLEAN; t1: INTEGER); begin T := Self.Bits[t1]; end;
+procedure TBITSSIZE_R(Self: TBITS; T: INTEGER); begin Self.SIZE := T; end;
+procedure TBITSSIZE_W(Self: TBITS; var T: INTEGER); begin T := Self.SIZE; end;
+
+procedure RIRegisterTBITS(Cl: TPSRuntimeClassImporter);
+begin
+ with Cl.Add(TBITS) do
+ begin
+ RegisterMethod(@TBITS.OPENBIT, 'OPENBIT');
+ RegisterPropertyHelper(@TBITSBITS_R, @TBITSBITS_W, 'BITS');
+ RegisterPropertyHelper(@TBITSSIZE_R, @TBITSSIZE_W, 'SIZE');
+ end;
+end;
+{$ENDIF}
+
+procedure TSTREAMPOSITION_R(Self: TSTREAM; var T: LONGINT); begin t := Self.POSITION; end;
+procedure TSTREAMPOSITION_W(Self: TSTREAM; T: LONGINT); begin Self.POSITION := t; end;
+procedure TSTREAMSIZE_R(Self: TSTREAM; var T: LONGINT); begin t := Self.SIZE; end;
+{$IFDEF DELPHI3UP}
+procedure TSTREAMSIZE_W(Self: TSTREAM; T: LONGINT); begin Self.SIZE := t; end;
+{$ENDIF}
+
+procedure RIRegisterTSTREAM(Cl: TPSRuntimeClassImporter);
+begin
+ with Cl.Add(TSTREAM) do
+ begin
+ RegisterVirtualAbstractMethod(TMemoryStream, @TMemoryStream.READ, 'READ');
+ RegisterVirtualAbstractMethod(TMemoryStream, @TMemoryStream.WRITE, 'WRITE');
+ RegisterVirtualAbstractMethod(TMemoryStream, @TMemoryStream.SEEK, 'SEEK');
+ RegisterMethod(@TSTREAM.READBUFFER, 'READBUFFER');
+ RegisterMethod(@TSTREAM.WRITEBUFFER, 'WRITEBUFFER');
+ RegisterMethod(@TSTREAM.COPYFROM, 'COPYFROM');
+ RegisterPropertyHelper(@TSTREAMPOSITION_R, @TSTREAMPOSITION_W, 'POSITION');
+ RegisterPropertyHelper(@TSTREAMSIZE_R, {$IFDEF DELPHI3UP}@TSTREAMSIZE_W, {$ELSE}nil, {$ENDIF}'SIZE');
+ end;
+end;
+
+procedure THANDLESTREAMHANDLE_R(Self: THANDLESTREAM; var T: INTEGER); begin T := Self.HANDLE; end;
+
+procedure RIRegisterTHANDLESTREAM(Cl: TPSRuntimeClassImporter);
+begin
+ with Cl.Add(THANDLESTREAM) do
+ begin
+ RegisterConstructor(@THANDLESTREAM.CREATE, 'CREATE');
+ RegisterPropertyHelper(@THANDLESTREAMHANDLE_R, nil, 'HANDLE');
+ end;
+end;
+
+{$IFDEF FPC}
+// mh: because FPC doesn't handle pointers to overloaded functions
+function TFileStreamCreate(filename: string; mode: word): TFileStream;
+begin
+ result := TFilestream.Create(filename, mode);
+end;
+{$ENDIF}
+
+procedure RIRegisterTFILESTREAM(Cl: TPSRuntimeClassImporter);
+begin
+ with Cl.Add(TFILESTREAM) do
+ begin
+ {$IFDEF FPC}
+ RegisterConstructor(@TFileStreamCreate, 'CREATE');
+ {$ELSE}
+ RegisterConstructor(@TFILESTREAM.CREATE, 'CREATE');
+ {$ENDIF}
+ end;
+end;
+
+{$IFNDEF PS_MINIVCL}
+procedure RIRegisterTCUSTOMMEMORYSTREAM(Cl: TPSRuntimeClassImporter);
+begin
+ with Cl.Add(TCUSTOMMEMORYSTREAM) do
+ begin
+ RegisterMethod(@TCUSTOMMEMORYSTREAM.SAVETOSTREAM, 'SAVETOSTREAM');
+ RegisterMethod(@TCUSTOMMEMORYSTREAM.SAVETOFILE, 'SAVETOFILE');
+ end;
+end;
+
+procedure RIRegisterTMEMORYSTREAM(Cl: TPSRuntimeClassImporter);
+begin
+ with Cl.Add(TMEMORYSTREAM) do
+ begin
+ RegisterMethod(@TMEMORYSTREAM.CLEAR, 'CLEAR');
+ RegisterMethod(@TMEMORYSTREAM.LOADFROMSTREAM, 'LOADFROMSTREAM');
+ RegisterMethod(@TMEMORYSTREAM.LOADFROMFILE, 'LOADFROMFILE');
+ RegisterMethod(@TMEMORYSTREAM.SETSIZE, 'SETSIZE');
+ end;
+end;
+
+procedure RIRegisterTRESOURCESTREAM(Cl: TPSRuntimeClassImporter);
+begin
+ with Cl.Add(TRESOURCESTREAM) do
+ begin
+ RegisterConstructor(@TRESOURCESTREAM.CREATE, 'CREATE');
+ RegisterConstructor(@TRESOURCESTREAM.CREATEFROMID, 'CREATEFROMID');
+ end;
+end;
+
+procedure TPARSERSOURCELINE_R(Self: TPARSER; var T: INTEGER); begin T := Self.SOURCELINE; end;
+procedure TPARSERTOKEN_R(Self: TPARSER; var T: CHAR); begin T := Self.TOKEN; end;
+
+procedure RIRegisterTPARSER(Cl: TPSRuntimeClassImporter);
+begin
+ with Cl.Add(TPARSER) do
+ begin
+ RegisterConstructor(@TPARSER.CREATE, 'CREATE');
+ RegisterMethod(@TPARSER.CHECKTOKEN, 'CHECKTOKEN');
+ RegisterMethod(@TPARSER.CHECKTOKENSYMBOL, 'CHECKTOKENSYMBOL');
+ RegisterMethod(@TPARSER.ERROR, 'ERROR');
+ RegisterMethod(@TPARSER.ERRORSTR, 'ERRORSTR');
+ RegisterMethod(@TPARSER.HEXTOBINARY, 'HEXTOBINARY');
+ RegisterMethod(@TPARSER.NEXTTOKEN, 'NEXTTOKEN');
+ RegisterMethod(@TPARSER.SOURCEPOS, 'SOURCEPOS');
+ RegisterMethod(@TPARSER.TOKENCOMPONENTIDENT, 'TOKENCOMPONENTIDENT');
+ RegisterMethod(@TPARSER.TOKENFLOAT, 'TOKENFLOAT');
+ RegisterMethod(@TPARSER.TOKENINT, 'TOKENINT');
+ RegisterMethod(@TPARSER.TOKENSTRING, 'TOKENSTRING');
+ RegisterMethod(@TPARSER.TOKENSYMBOLIS, 'TOKENSYMBOLIS');
+ RegisterPropertyHelper(@TPARSERSOURCELINE_R, nil, 'SOURCELINE');
+ RegisterPropertyHelper(@TPARSERTOKEN_R, nil, 'TOKEN');
+ end;
+end;
+
+procedure TCOLLECTIONITEMS_W(Self: TCOLLECTION; const T: TCOLLECTIONITEM; const t1: INTEGER);
+begin Self.ITEMS[t1] := T; end;
+
+procedure TCOLLECTIONITEMS_R(Self: TCOLLECTION; var T: TCOLLECTIONITEM; const t1: INTEGER);
+begin T := Self.ITEMS[t1]; end;
+
+{$IFDEF DELPHI3UP}
+procedure TCOLLECTIONITEMCLASS_R(Self: TCOLLECTION; var T: TCOLLECTIONITEMCLASS);
+begin T := Self.ITEMCLASS; end;
+{$ENDIF}
+
+procedure TCOLLECTIONCOUNT_R(Self: TCOLLECTION; var T: INTEGER);
+begin T := Self.COUNT; end;
+
+{$IFDEF DELPHI3UP}
+procedure TCOLLECTIONITEMDISPLAYNAME_W(Self: TCOLLECTIONITEM; const T: STRING);
+begin Self.DISPLAYNAME := T; end;
+{$ENDIF}
+
+{$IFDEF DELPHI3UP}
+procedure TCOLLECTIONITEMDISPLAYNAME_R(Self: TCOLLECTIONITEM; var T: STRING);
+begin T := Self.DISPLAYNAME; end;
+{$ENDIF}
+
+procedure TCOLLECTIONITEMINDEX_W(Self: TCOLLECTIONITEM; const T: INTEGER);
+begin Self.INDEX := T; end;
+
+procedure TCOLLECTIONITEMINDEX_R(Self: TCOLLECTIONITEM; var T: INTEGER);
+begin T := Self.INDEX; end;
+
+{$IFDEF DELPHI3UP}
+procedure TCOLLECTIONITEMID_R(Self: TCOLLECTIONITEM; var T: INTEGER);
+begin T := Self.ID; end;
+{$ENDIF}
+
+procedure TCOLLECTIONITEMCOLLECTION_W(Self: TCOLLECTIONITEM; const T: TCOLLECTION);
+begin Self.COLLECTION := T; end;
+
+procedure TCOLLECTIONITEMCOLLECTION_R(Self: TCOLLECTIONITEM; var T: TCOLLECTION);
+begin T := Self.COLLECTION; end;
+
+{$IFDEF DELPHI3UP}
+procedure RIRegisterTOWNEDCOLLECTION(Cl: TPSRuntimeClassImporter);
+Begin
+with Cl.Add(TOWNEDCOLLECTION) do
+ begin
+ RegisterConstructor(@TOWNEDCOLLECTION.CREATE, 'CREATE');
+ end;
+end;
+{$ENDIF}
+
+procedure RIRegisterTCOLLECTION(Cl: TPSRuntimeClassImporter);
+Begin
+with Cl.Add(TCOLLECTION) do
+ begin
+ RegisterConstructor(@TCOLLECTION.CREATE, 'CREATE');
+{$IFDEF DELPHI6UP} {$IFNDEF FPC} RegisterMethod(@TCOLLECTION.OWNER, 'OWNER'); {$ENDIF} {$ENDIF} // no owner in FPC
+ RegisterMethod(@TCOLLECTION.ADD, 'ADD');
+ RegisterVirtualMethod(@TCOLLECTION.BEGINUPDATE, 'BEGINUPDATE');
+ RegisterMethod(@TCOLLECTION.CLEAR, 'CLEAR');
+{$IFDEF DELPHI5UP} RegisterMethod(@TCOLLECTION.DELETE, 'DELETE'); {$ENDIF}
+ RegisterVirtualMethod(@TCOLLECTION.ENDUPDATE, 'ENDUPDATE');
+{$IFDEF DELPHI3UP} RegisterMethod(@TCOLLECTION.FINDITEMID, 'FINDITEMID'); {$ENDIF}
+{$IFDEF DELPHI3UP} RegisterMethod(@TCOLLECTION.INSERT, 'INSERT'); {$ENDIF}
+ RegisterPropertyHelper(@TCOLLECTIONCOUNT_R,nil,'COUNT');
+{$IFDEF DELPHI3UP} RegisterPropertyHelper(@TCOLLECTIONITEMCLASS_R,nil,'ITEMCLASS'); {$ENDIF}
+ RegisterPropertyHelper(@TCOLLECTIONITEMS_R,@TCOLLECTIONITEMS_W,'ITEMS');
+ end;
+end;
+
+procedure RIRegisterTCOLLECTIONITEM(Cl: TPSRuntimeClassImporter);
+Begin
+with Cl.Add(TCOLLECTIONITEM) do
+ begin
+ RegisterVirtualConstructor(@TCOLLECTIONITEM.CREATE, 'CREATE');
+ RegisterPropertyHelper(@TCOLLECTIONITEMCOLLECTION_R,@TCOLLECTIONITEMCOLLECTION_W,'COLLECTION');
+{$IFDEF DELPHI3UP} RegisterPropertyHelper(@TCOLLECTIONITEMID_R,nil,'ID'); {$ENDIF}
+ RegisterPropertyHelper(@TCOLLECTIONITEMINDEX_R,@TCOLLECTIONITEMINDEX_W,'INDEX');
+{$IFDEF DELPHI3UP} RegisterPropertyHelper(@TCOLLECTIONITEMDISPLAYNAME_R,@TCOLLECTIONITEMDISPLAYNAME_W,'DISPLAYNAME'); {$ENDIF}
+ end;
+end;
+{$ENDIF}
+
+procedure RIRegister_Classes(Cl: TPSRuntimeClassImporter; Streams: Boolean);
+begin
+ if Streams then
+ RIRegisterTSTREAM(Cl);
+ RIRegisterTStrings(cl, Streams);
+ RIRegisterTStringList(cl);
+ {$IFNDEF PS_MINIVCL}
+ RIRegisterTBITS(cl);
+ {$ENDIF}
+ if Streams then
+ begin
+ RIRegisterTHANDLESTREAM(Cl);
+ RIRegisterTFILESTREAM(Cl);
+ {$IFNDEF PS_MINIVCL}
+ RIRegisterTCUSTOMMEMORYSTREAM(Cl);
+ RIRegisterTMEMORYSTREAM(Cl);
+ RIRegisterTRESOURCESTREAM(Cl);
+ {$ENDIF}
+ end;
+ {$IFNDEF PS_MINIVCL}
+ RIRegisterTPARSER(Cl);
+ RIRegisterTCOLLECTIONITEM(Cl);
+ RIRegisterTCOLLECTION(Cl);
+ {$IFDEF DELPHI3UP}
+ RIRegisterTOWNEDCOLLECTION(Cl);
+ {$ENDIF}
+ {$ENDIF}
+end;
+
+// PS_MINIVCL changes by Martijn Laan (mlaan at wintax _dot_ nl)
+
+end.
diff --git a/branches/script-component/Units/PascalScript/uPSR_comobj.pas b/branches/script-component/Units/PascalScript/uPSR_comobj.pas
new file mode 100644
index 0000000..5e8c9a9
--- /dev/null
+++ b/branches/script-component/Units/PascalScript/uPSR_comobj.pas
@@ -0,0 +1,96 @@
+
+
+unit uPSR_comobj;
+
+{$I PascalScript.inc}
+interface
+uses
+ uPSRuntime, uPSUtils;
+
+
+procedure RIRegister_ComObj(cl: TPSExec);
+
+implementation
+uses
+{$IFDEF DELPHI3UP}
+ ComObj;
+{$ELSE}
+ SysUtils, Ole2;
+{$ENDIF}
+{$IFNDEF DELPHI3UP}
+
+{$IFDEF DELPHI3UP }
+resourceString
+{$ELSE }
+const
+{$ENDIF }
+
+ RPS_OLEError = 'OLE error %.8x';
+function OleErrorMessage(ErrorCode: HResult): String;
+begin
+ Result := SysErrorMessage(ErrorCode);
+ if Result = '' then
+ Result := Format(RPS_OLEError, [ErrorCode]);
+end;
+
+procedure OleError(ErrorCode: HResult);
+begin
+ raise Exception.Create(OleErrorMessage(ErrorCode));
+end;
+
+procedure OleCheck(Result: HResult);
+begin
+ if Result < 0 then OleError(Result);
+end;
+
+procedure CreateOleObject(const ClassName: string; var Disp: IDispatch);
+var
+ OldDisp: IDispatch;
+ ClassID: TCLSID;
+ WideCharBuf: array[0..127] of WideChar;
+begin
+ StringToWideChar(ClassName, WideCharBuf, SizeOf(WideCharBuf) div SizeOf(WideCharBuf[0]));
+ OleCheck(CLSIDFromProgID(WideCharBuf, ClassID));
+ if Disp <> nil then
+ begin
+ OldDisp := Disp;
+ Disp := nil;
+ OldDisp.Release;
+ end;
+ OleCheck(CoCreateInstance(ClassID, nil, CLSCTX_INPROC_SERVER or
+ CLSCTX_LOCAL_SERVER, IID_IDispatch, Disp));
+end;
+
+procedure GetActiveOleObject(const ClassName: string; var Disp: IDispatch);
+var
+ Unknown: IUnknown;
+ OldDisp: IDispatch;
+ ClassID: TCLSID;
+ WideCharBuf: array[0..127] of WideChar;
+begin
+ StringToWideChar(ClassName, WideCharBuf, SizeOf(WideCharBuf) div SizeOf(WideCharBuf[0]));
+ OleCheck(CLSIDFromProgID(WideCharBuf, ClassID));
+ OleCheck(GetActiveObject(ClassID, nil, Unknown));
+ try
+ if Disp <> nil then
+ begin
+ OldDisp := Disp;
+ Disp := nil;
+ OldDisp.Release;
+ end;
+ OleCheck(Unknown.QueryInterface(IID_IDispatch, Disp));
+ finally
+ Unknown.Release;
+ end;
+end;
+
+{$ENDIF}
+
+
+procedure RIRegister_ComObj(cl: TPSExec);
+begin
+ cl.RegisterDelphiFunction(@CreateOleObject, 'CREATEOLEOBJECT', cdRegister);
+ cl.RegisterDelphiFunction(@GetActiveOleObject, 'GETACTIVEOLEOBJECT', cdRegister);
+end;
+
+end.
diff --git a/branches/script-component/Units/PascalScript/uPSR_controls.pas b/branches/script-component/Units/PascalScript/uPSR_controls.pas
new file mode 100644
index 0000000..72d9490
--- /dev/null
+++ b/branches/script-component/Units/PascalScript/uPSR_controls.pas
@@ -0,0 +1,249 @@
+
+unit uPSR_controls;
+
+{$I PascalScript.inc}
+interface
+uses
+ uPSRuntime, uPSUtils;
+
+
+
+
+procedure RIRegisterTControl(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTWinControl(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTGraphicControl(cl: TPSRuntimeClassImporter);
+procedure RIRegisterTCustomControl(cl: TPSRuntimeClassImporter);
+procedure RIRegister_TDragObject(CL: TPSRuntimeClassImporter);
+
+procedure RIRegister_Controls(Cl: TPSRuntimeClassImporter);
+
+implementation
+{$IFNDEF FPC}
+uses
+ Classes{$IFDEF CLX}, QControls, QGraphics{$ELSE}, Controls, Graphics, Windows{$ENDIF};
+{$ELSE}
+uses
+ Classes, Controls, Graphics;
+{$ENDIF}
+
+procedure TControlAlignR(Self: TControl; var T: Byte); begin T := Byte(Self.Align); end;
+procedure TControlAlignW(Self: TControl; T: Byte); begin Self.Align:= TAlign(T); end;
+
+procedure TControlClientHeightR(Self: TControl; var T: Longint); begin T := Self.ClientHeight; end;
+procedure TControlClientHeightW(Self: TControl; T: Longint); begin Self.ClientHeight := T; end;
+
+procedure TControlClientWidthR(Self: TControl; var T: Longint); begin T := Self.ClientWidth; end;
+procedure TControlClientWidthW(Self: TControl; T: Longint); begin Self.ClientWidth:= T; end;
+
+procedure TControlShowHintR(Self: TControl; var T: Boolean); begin T := Self.ShowHint; end;
+procedure TControlShowHintW(Self: TControl; T: Boolean); begin Self.ShowHint:= T; end;
+
+procedure TControlVisibleR(Self: TControl; var T: Boolean); begin T := Self.Visible; end;
+procedure TControlVisibleW(Self: TControl; T: Boolean); begin Self.Visible:= T; end;
+
+procedure TControlParentR(Self: TControl; var T: TWinControl); begin T := Self.Parent; end;
+procedure TControlParentW(Self: TControl; T: TWinControl); begin Self.Parent:= T; end;
+
+
+procedure TCONTROLSHOWHINT_W(Self: TCONTROL; T: BOOLEAN); begin Self.SHOWHINT := T; end;
+procedure TCONTROLSHOWHINT_R(Self: TCONTROL; var T: BOOLEAN); begin T := Self.SHOWHINT; end;
+procedure TCONTROLENABLED_W(Self: TCONTROL; T: BOOLEAN); begin Self.ENABLED := T; end;
+procedure TCONTROLENABLED_R(Self: TCONTROL; var T: BOOLEAN); begin T := Self.ENABLED; end;
+
+procedure RIRegisterTControl(Cl: TPSRuntimeClassImporter);
+begin
+ with Cl.Add(TControl) do
+ begin
+ RegisterVirtualConstructor(@TControl.Create, 'CREATE');
+ RegisterMethod(@TControl.BRingToFront, 'BRINGTOFRONT');
+ RegisterMethod(@TControl.Hide, 'HIDE');
+ RegisterVirtualMethod(@TControl.Invalidate, 'INVALIDATE');
+ RegisterMethod(@TControl.Refresh, 'REFRESH');
+ RegisterVirtualMethod(@TControl.Repaint, 'REPAINT');
+ RegisterMethod(@TControl.SendToBack, 'SENDTOBACK');
+ RegisterMethod(@TControl.Show, 'SHOW');
+ RegisterVirtualMethod(@TControl.Update, 'UPDATE');
+ RegisterVirtualMethod(@TControl.SetBounds, 'SETBOUNDS');
+
+ RegisterPropertyHelper(@TControlShowHintR, @TControlShowHintW, 'SHOWHINT');
+ RegisterPropertyHelper(@TControlAlignR, @TControlAlignW, 'ALIGN');
+ RegisterPropertyHelper(@TControlClientHeightR, @TControlClientHeightW, 'CLIENTHEIGHT');
+ RegisterPropertyHelper(@TControlClientWidthR, @TControlClientWidthW, 'CLIENTWIDTH');
+ RegisterPropertyHelper(@TControlVisibleR, @TControlVisibleW, 'VISIBLE');
+ RegisterPropertyHelper(@TCONTROLENABLED_R, @TCONTROLENABLED_W, 'ENABLED');
+
+ RegisterPropertyHelper(@TControlParentR, @TControlParentW, 'PARENT');
+
+ {$IFNDEF PS_MINIVCL}
+ RegisterMethod(@TControl.Dragging, 'DRAGGING');
+ RegisterMethod(@TControl.HasParent, 'HASPARENT');
+ RegisterMethod(@TCONTROL.CLIENTTOSCREEN, 'CLIENTTOSCREEN');
+ RegisterMethod(@TCONTROL.DRAGGING, 'DRAGGING');
+ {$IFNDEF FPC}
+ RegisterMethod(@TCONTROL.BEGINDRAG, 'BEGINDRAG');
+ RegisterMethod(@TCONTROL.ENDDRAG, 'ENDDRAG');
+ {$ENDIF}
+ {$IFNDEF CLX}
+ RegisterMethod(@TCONTROL.GETTEXTBUF, 'GETTEXTBUF');
+ RegisterMethod(@TCONTROL.GETTEXTLEN, 'GETTEXTLEN');
+ RegisterMethod(@TCONTROL.PERFORM, 'PERFORM');
+ RegisterMethod(@TCONTROL.SETTEXTBUF, 'SETTEXTBUF');
+ {$ENDIF}
+ RegisterMethod(@TCONTROL.SCREENTOCLIENT, 'SCREENTOCLIENT');
+ {$ENDIF}
+ end;
+end;
+{$IFNDEF CLX}
+procedure TWinControlHandleR(Self: TWinControl; var T: Longint); begin T := Self.Handle; end;
+{$ENDIF}
+procedure TWinControlShowingR(Self: TWinControl; var T: Boolean); begin T := Self.Showing; end;
+
+
+procedure TWinControlTabOrderR(Self: TWinControl; var T: Longint); begin T := Self.TabOrder; end;
+procedure TWinControlTabOrderW(Self: TWinControl; T: Longint); begin Self.TabOrder:= T; end;
+
+procedure TWinControlTabStopR(Self: TWinControl; var T: Boolean); begin T := Self.TabStop; end;
+procedure TWinControlTabStopW(Self: TWinControl; T: Boolean); begin Self.TabStop:= T; end;
+procedure TWINCONTROLBRUSH_R(Self: TWINCONTROL; var T: TBRUSH); begin T := Self.BRUSH; end;
+procedure TWINCONTROLCONTROLS_R(Self: TWINCONTROL; var T: TCONTROL; t1: INTEGER); begin t := Self.CONTROLS[t1]; end;
+procedure TWINCONTROLCONTROLCOUNT_R(Self: TWINCONTROL; var T: INTEGER); begin t := Self.CONTROLCOUNT; end;
+
+procedure RIRegisterTWinControl(Cl: TPSRuntimeClassImporter); // requires TControl
+begin
+ with Cl.Add(TWinControl) do
+ begin
+ {$IFNDEF CLX}
+ RegisterPropertyHelper(@TWinControlHandleR, nil, 'HANDLE');
+ {$ENDIF}
+ RegisterPropertyHelper(@TWinControlShowingR, nil, 'SHOWING');
+ RegisterPropertyHelper(@TWinControlTabOrderR, @TWinControlTabOrderW, 'TABORDER');
+ RegisterPropertyHelper(@TWinControlTabStopR, @TWinControlTabStopW, 'TABSTOP');
+ RegisterMethod(@TWINCONTROL.CANFOCUS, 'CANFOCUS');
+ RegisterMethod(@TWINCONTROL.FOCUSED, 'FOCUSED');
+ RegisterPropertyHelper(@TWINCONTROLCONTROLS_R, nil, 'CONTROLS');
+ RegisterPropertyHelper(@TWINCONTROLCONTROLCOUNT_R, nil, 'CONTROLCOUNT');
+ {$IFNDEF PS_MINIVCL}
+ RegisterMethod(@TWinControl.HandleAllocated, 'HANDLEALLOCATED');
+ RegisterMethod(@TWinControl.HandleNeeded, 'HANDLENEEDED');
+ RegisterMethod(@TWinControl.EnableAlign, 'ENABLEALIGN');
+ RegisterMethod(@TWinControl.RemoveControl, 'REMOVECONTROL');
+ {$IFNDEF FPC}
+ RegisterMethod(@TWinControl.InsertControl, 'INSERTCONTROL');
+ RegisterMethod(@TWinControl.ScaleBy, 'SCALEBY');
+ RegisterMethod(@TWinControl.ScrollBy, 'SCROLLBY');
+ {$IFNDEF CLX}
+ RegisterMethod(@TWINCONTROL.PAINTTO, 'PAINTTO');
+ {$ENDIF}
+ {$ENDIF}{FPC}
+ RegisterMethod(@TWinControl.Realign, 'REALIGN');
+ RegisterVirtualMethod(@TWinControl.SetFocus, 'SETFOCUS');
+ RegisterMethod(@TWINCONTROL.CONTAINSCONTROL, 'CONTAINSCONTROL');
+ RegisterMethod(@TWINCONTROL.DISABLEALIGN, 'DISABLEALIGN');
+ RegisterMethod(@TWINCONTROL.UPDATECONTROLSTATE, 'UPDATECONTROLSTATE');
+ RegisterPropertyHelper(@TWINCONTROLBRUSH_R, nil, 'BRUSH');
+ {$ENDIF}
+ end;
+end;
+
+procedure RIRegisterTGraphicControl(cl: TPSRuntimeClassImporter); // requires TControl
+begin
+ Cl.Add(TGraphicControl);
+end;
+procedure RIRegisterTCustomControl(cl: TPSRuntimeClassImporter); // requires TControl
+begin
+ Cl.Add(TCustomControl);
+end;
+
+{$IFDEF DELPHI4UP}
+(* === run-time registration functions === *)
+(*----------------------------------------------------------------------------*)
+procedure TDragObjectMouseDeltaY_R(Self: TDragObject; var T: Double);
+begin T := Self.MouseDeltaY; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TDragObjectMouseDeltaX_R(Self: TDragObject; var T: Double);
+begin T := Self.MouseDeltaX; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TDragObjectDragTarget_W(Self: TDragObject; const T: Pointer);
+begin Self.DragTarget := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TDragObjectDragTarget_R(Self: TDragObject; var T: Pointer);
+begin T := Self.DragTarget; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TDragObjectDragTargetPos_W(Self: TDragObject; const T: TPoint);
+begin Self.DragTargetPos := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TDragObjectDragTargetPos_R(Self: TDragObject; var T: TPoint);
+begin T := Self.DragTargetPos; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TDragObjectDragPos_W(Self: TDragObject; const T: TPoint);
+begin Self.DragPos := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TDragObjectDragPos_R(Self: TDragObject; var T: TPoint);
+begin T := Self.DragPos; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TDragObjectDragHandle_W(Self: TDragObject; const T: HWND);
+begin Self.DragHandle := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TDragObjectDragHandle_R(Self: TDragObject; var T: HWND);
+begin T := Self.DragHandle; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TDragObjectCancelling_W(Self: TDragObject; const T: Boolean);
+begin Self.Cancelling := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TDragObjectCancelling_R(Self: TDragObject; var T: Boolean);
+begin T := Self.Cancelling; end;
+{$ENDIF}
+(*----------------------------------------------------------------------------*)
+procedure RIRegister_TDragObject(CL: TPSRuntimeClassImporter);
+begin
+ with CL.Add(TDragObject) do
+ begin
+{$IFNDEF PS_MINIVCL}
+{$IFDEF DELPHI4UP}
+ RegisterVirtualMethod(@TDragObject.Assign, 'Assign');
+{$ENDIF}
+{$IFNDEF FPC}
+ RegisterVirtualMethod(@TDragObject.GetName, 'GetName');
+ RegisterVirtualMethod(@TDragObject.Instance, 'Instance');
+{$ENDIF}
+ RegisterVirtualMethod(@TDragObject.HideDragImage, 'HideDragImage');
+ RegisterVirtualMethod(@TDragObject.ShowDragImage, 'ShowDragImage');
+{$IFDEF DELPHI4UP}
+ RegisterPropertyHelper(@TDragObjectCancelling_R,@TDragObjectCancelling_W,'Cancelling');
+ RegisterPropertyHelper(@TDragObjectDragHandle_R,@TDragObjectDragHandle_W,'DragHandle');
+ RegisterPropertyHelper(@TDragObjectDragPos_R,@TDragObjectDragPos_W,'DragPos');
+ RegisterPropertyHelper(@TDragObjectDragTargetPos_R,@TDragObjectDragTargetPos_W,'DragTargetPos');
+ RegisterPropertyHelper(@TDragObjectDragTarget_R,@TDragObjectDragTarget_W,'DragTarget');
+ RegisterPropertyHelper(@TDragObjectMouseDeltaX_R,nil,'MouseDeltaX');
+ RegisterPropertyHelper(@TDragObjectMouseDeltaY_R,nil,'MouseDeltaY');
+{$ENDIF}
+{$ENDIF}
+ end;
+end;
+
+
+procedure RIRegister_Controls(Cl: TPSRuntimeClassImporter);
+begin
+ RIRegisterTControl(Cl);
+ RIRegisterTWinControl(Cl);
+ RIRegisterTGraphicControl(cl);
+ RIRegisterTCustomControl(cl);
+ RIRegister_TDragObject(cl);
+
+end;
+
+// PS_MINIVCL changes by Martijn Laan (mlaan at wintax _dot_ nl)
+
+
+end.
diff --git a/branches/script-component/Units/PascalScript/uPSR_dateutils.pas b/branches/script-component/Units/PascalScript/uPSR_dateutils.pas
new file mode 100644
index 0000000..cff7469
--- /dev/null
+++ b/branches/script-component/Units/PascalScript/uPSR_dateutils.pas
@@ -0,0 +1,63 @@
+
+unit uPSR_dateutils;
+{$I PascalScript.inc}
+interface
+uses
+ SysUtils, uPSRuntime;
+
+
+
+procedure RegisterDateTimeLibrary_R(S: TPSExec);
+
+implementation
+
+function TryEncodeDate(Year, Month, Day: Word; var Date: TDateTime): Boolean;
+begin
+ try
+ Date := EncodeDate(Year, Month, Day);
+ Result := true;
+ except
+ Result := false;
+ end;
+end;
+
+function TryEncodeTime(Hour, Min, Sec, MSec: Word; var Time: TDateTime): Boolean;
+begin
+ try
+ Time := EncodeTime(hour, Min, Sec, MSec);
+ Result := true;
+ except
+ Result := false;
+ end;
+end;
+
+function DateTimeToUnix(D: TDateTime): Int64;
+begin
+ Result := Round((D - 25569) * 86400);
+end;
+
+function UnixToDateTime(U: Int64): TDateTime;
+begin
+ Result := U / 86400 + 25569;
+end;
+
+procedure RegisterDateTimeLibrary_R(S: TPSExec);
+begin
+ S.RegisterDelphiFunction(@EncodeDate, 'ENCODEDATE', cdRegister);
+ S.RegisterDelphiFunction(@EncodeTime, 'ENCODETIME', cdRegister);
+ S.RegisterDelphiFunction(@TryEncodeDate, 'TRYENCODEDATE', cdRegister);
+ S.RegisterDelphiFunction(@TryEncodeTime, 'TRYENCODETIME', cdRegister);
+ S.RegisterDelphiFunction(@DecodeDate, 'DECODEDATE', cdRegister);
+ S.RegisterDelphiFunction(@DecodeTime, 'DECODETIME', cdRegister);
+ S.RegisterDelphiFunction(@DayOfWeek, 'DAYOFWEEK', cdRegister);
+ S.RegisterDelphiFunction(@Date, 'DATE', cdRegister);
+ S.RegisterDelphiFunction(@Time, 'TIME', cdRegister);
+ S.RegisterDelphiFunction(@Now, 'NOW', cdRegister);
+ S.RegisterDelphiFunction(@DateTimeToUnix, 'DATETIMETOUNIX', cdRegister);
+ S.RegisterDelphiFunction(@UnixToDateTime, 'UNIXTODATETIME', cdRegister);
+ S.RegisterDelphiFunction(@DateToStr, 'DATETOSTR', cdRegister);
+ S.RegisterDelphiFunction(@FormatDateTime, 'FORMATDATETIME', cdRegister);
+ S.RegisterDelphiFunction(@StrToDate, 'STRTODATE', cdRegister);
+end;
+
+end.
diff --git a/branches/script-component/Units/PascalScript/uPSR_dll.pas b/branches/script-component/Units/PascalScript/uPSR_dll.pas
new file mode 100644
index 0000000..00dd22c
--- /dev/null
+++ b/branches/script-component/Units/PascalScript/uPSR_dll.pas
@@ -0,0 +1,283 @@
+unit uPSR_dll;
+
+{$I PascalScript.inc}
+interface
+uses
+ uPSRuntime, uPSUtils;
+
+procedure RegisterDLLRuntime(Caller: TPSExec);
+procedure RegisterDLLRuntimeEx(Caller: TPSExec; AddDllProcImport: Boolean);
+
+function ProcessDllImport(Caller: TPSExec; P: TPSExternalProcRec): Boolean;
+function ProcessDllImportEx(Caller: TPSExec; P: TPSExternalProcRec; ForceDelayLoad: Boolean): Boolean;
+function UnloadProc(Caller: TPSExec; p: TPSExternalProcRec; Global, Stack: TPSStack): Boolean;
+
+implementation
+uses
+ {$IFDEF UNIX}
+ LCLIntf, Unix, baseunix, dynlibs, termio, sockets;
+ {$ELSE}
+ Windows;
+ {$ENDIF}
+
+{
+p^.Ext1 contains the pointer to the Proc function
+p^.ExportDecl:
+ 'dll:'+DllName+#0+FunctionName+#0+chr(Cc)+Chr(DelayLoad)+Chr(AlternateSearchPath)+VarParams
+}
+
+type
+ PLoadedDll = ^TLoadedDll;
+ TLoadedDll = record
+ dllnamehash: Longint;
+ dllname: tbtstring;
+ dllhandle: THandle;
+ end;
+ TMyExec = class(TPSExec);
+ PInteger = ^Integer;
+
+procedure LAstErrorFree(Sender: TPSExec; P: PInteger);
+begin
+ dispose(p);
+end;
+
+procedure DLLSetLastError(Sender: TPSExec; P: Integer);
+var
+ pz: PInteger;
+begin
+ pz := Sender.FindProcResource(@LastErrorFree);
+ if pz = nil then
+ begin
+ new(pz);
+ Sender.AddResource(@LastErrorFree, PZ);
+ end;
+ pz^ := p;
+end;
+
+function DLLGetLastError(Sender: TPSExec): Integer;
+var
+ pz: PInteger;
+begin
+ pz := Sender.FindProcResource(@LastErrorFree);
+ if pz = nil then
+ result := 0
+ else
+ result := pz^;
+end;
+
+
+procedure DllFree(Sender: TPSExec; P: PLoadedDll);
+begin
+ FreeLibrary(p^.dllhandle);
+ Dispose(p);
+end;
+
+function LoadDll(Caller: TPSExec; P: TPSExternalProcRec): Boolean;
+var
+ s, s2, s3: tbtstring;
+ h, i: Longint;
+ ph: PLoadedDll;
+ dllhandle: THandle;
+ loadwithalteredsearchpath: Boolean;
+begin
+ s := p.Decl;
+ Delete(s, 1, 4);
+ s2 := copy(s, 1, pos(tbtchar(#0), s)-1);
+ delete(s, 1, length(s2)+1);
+ h := makehash(s2);
+ s3 := copy(s, 1, pos(tbtchar(#0), s)-1);
+ delete(s, 1, length(s3)+1);
+ loadwithalteredsearchpath := bytebool(s[3]);
+ i := 2147483647; // maxint
+ dllhandle := 0;
+ repeat
+ ph := Caller.FindProcResource2(@dllFree, i);
+ if (ph = nil) then
+ begin
+ if s2 = '' then
+ begin
+ // don't pass an empty filename to LoadLibrary, just treat it as uncallable
+ p.Ext2 := Pointer(1);
+ Result := False;
+ exit;
+ end;
+ {$IFDEF UNIX}
+ dllhandle := LoadLibrary(PChar(s2));
+ {$ELSE}
+ if loadwithalteredsearchpath then
+ dllhandle := LoadLibraryExA(PAnsiChar(AnsiString(s2)), 0, LOAD_WITH_ALTERED_SEARCH_PATH)
+ else
+ dllhandle := LoadLibraryA(PAnsiChar(AnsiString(s2)));
+ {$ENDIF}
+ if dllhandle = 0 then
+ begin
+ p.Ext2 := Pointer(1);
+ Result := False;
+ exit;
+ end;
+ new(ph);
+ ph^.dllnamehash := h;
+ ph^.dllname := s2;
+ ph^.dllhandle := dllhandle;
+ Caller.AddResource(@DllFree, ph);
+ end;
+ if (ph^.dllnamehash = h) and (ph^.dllname = s2) then
+ begin
+ dllhandle := ph^.dllhandle;
+ end;
+ until dllhandle <> 0;
+ p.Ext1 := GetProcAddress(dllhandle, pansichar(s3));
+ if p.Ext1 = nil then
+ begin
+ p.Ext2 := Pointer(1);
+ Result := false;
+ exit;
+ end;
+ Result := True;
+end;
+
+
+function DllProc(Caller: TPSExec; p: TPSExternalProcRec; Global, Stack: TPSStack): Boolean;
+
+var
+ i: Longint;
+ MyList: TIfList;
+ n: PPSVariantIFC;
+ CurrStack: Cardinal;
+ cc: TPSCallingConvention;
+ s: tbtstring;
+begin
+ if p.Ext2 <> nil then // error
+ begin
+ Result := false;
+ exit;
+ end;
+ if p.Ext1 = nil then
+ begin
+ if not LoadDll(Caller, P) then
+ begin
+ Result := false;
+ exit;
+ end;
+ end;
+ s := p.Decl;
+ delete(S, 1, pos(tbtchar(#0), s));
+ delete(S, 1, pos(tbtchar(#0), s));
+ if length(S) < 2 then
+ begin
+ Result := False;
+ exit;
+ end;
+ cc := TPSCallingConvention(s[1]);
+ delete(s, 1, 3); // cc + delayload + alternatesearchpath (delayload might also be forced!)
+ CurrStack := Cardinal(Stack.Count) - Cardinal(length(s));
+ if s[1] = #0 then inc(CurrStack);
+ MyList := tIfList.Create;
+ for i := 2 to length(s) do
+ begin
+ MyList.Add(nil);
+ end;
+ for i := length(s) downto 2 do
+ begin
+ MyList[i - 2] := NewPPSVariantIFC(Stack[CurrStack], s[i] <> #0);
+ inc(CurrStack);
+ end;
+ if s[1] <> #0 then
+ begin
+ n := NewPPSVariantIFC(Stack[CurrStack], true);
+ end else n := nil;
+ try
+ TMYExec(Caller).InnerfuseCall(nil, p.Ext1, cc, MyList, n);
+ {$IFNDEF LINUX}
+ DLLSetLastError(Caller, GetLastError);
+ {$ENDIF}
+ finally
+ DisposePPSvariantIFC(n);
+ DisposePPSVariantIFCList(MyList);
+ end;
+ result := true;
+end;
+
+function ProcessDllImport(Caller: TPSExec; P: TPSExternalProcRec): Boolean;
+begin
+ Result := ProcessDllImportEx(Caller, P, False);
+end;
+
+function ProcessDllImportEx(Caller: TPSExec; P: TPSExternalProcRec; ForceDelayLoad: Boolean): Boolean;
+var
+ DelayLoad: Boolean;
+ s: tbtstring;
+begin
+ if not ForceDelayLoad then begin
+ s := p.Decl;
+ Delete(s,1,pos(tbtchar(#0), s));
+ Delete(s,1,pos(tbtchar(#0), s));
+ DelayLoad := bytebool(s[2]);
+ end else
+ DelayLoad := True;
+
+ if DelayLoad then begin
+ p.ProcPtr := DllProc;
+ Result := True;
+ end else begin
+ p.ProcPtr := DllProc;
+ Result := LoadDll(Caller, p);
+ end;
+end;
+
+
+function GetLastErrorProc(Caller: TPSExec; p: TPSExternalProcRec; Global, Stack: TPSStack): Boolean;
+begin
+ Stack.SetInt(-1, DLLGetLastError(Caller));
+ Result := true;
+end;
+
+function UnloadProc(Caller: TPSExec; p: TPSExternalProcRec; Global, Stack: TPSStack): Boolean;
+var
+ h, i: Longint;
+ pv: TPSProcRec;
+ ph: PLoadedDll;
+ sname, s: tbtstring;
+begin
+ sname := Stack.GetAnsiString(-1);
+ for i := Caller.GetProcCount -1 downto 0 do
+ begin
+ pv := Caller.GetProcNo(i);
+ if not (pv is TPSExternalProcRec) then continue;
+ if @TPSExternalProcRec(pv).ProcPtr <> @DllProc then continue;
+ s := (TPSExternalProcRec(pv).Decl);
+ delete(s,1,4);
+ if copy(s,1,pos(tbtchar(#0),s)-1) = sname then
+ begin
+ TPSExternalProcRec(pv).Ext1 := nil;
+ end;
+ end;
+ h := MakeHash(sname);
+ i := 2147483647; // maxint
+ repeat
+ ph := Caller.FindProcResource2(@dllFree, i);
+ if (ph = nil) then break;
+ if (ph.dllnamehash = h) and (ph.dllname = sname) then
+ begin
+ FreeLibrary(ph^.dllhandle);
+ Caller.DeleteResource(ph);
+ dispose(ph);
+ end;
+ until false;
+ result := true;
+end;
+
+procedure RegisterDLLRuntime(Caller: TPSExec);
+begin
+ RegisterDLLRuntimeEx(Caller, True);
+end;
+
+procedure RegisterDLLRuntimeEx(Caller: TPSExec; AddDllProcImport: Boolean);
+begin
+ if AddDllProcImport then
+ Caller.AddSpecialProcImport('dll', @ProcessDllImport, nil);
+ Caller.RegisterFunctionName('UNLOADDLL', UnloadProc, nil, nil);
+ Caller.RegisterFunctionName('DLLGETLASTERROR', GetLastErrorProc, nil, nil);
+end;
+
+end.
diff --git a/branches/script-component/Units/PascalScript/uPSR_extctrls.pas b/branches/script-component/Units/PascalScript/uPSR_extctrls.pas
new file mode 100644
index 0000000..b9c059a
--- /dev/null
+++ b/branches/script-component/Units/PascalScript/uPSR_extctrls.pas
@@ -0,0 +1,150 @@
+
+unit uPSR_extctrls;
+
+{$I PascalScript.inc}
+interface
+uses
+ uPSRuntime, uPSUtils;
+
+
+procedure RIRegister_ExtCtrls(cl: TPSRuntimeClassImporter);
+
+procedure RIRegisterTSHAPE(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTIMAGE(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTPAINTBOX(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTBEVEL(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTTIMER(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTCUSTOMPANEL(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTPANEL(Cl: TPSRuntimeClassImporter);
+{$IFNDEF CLX}
+procedure RIRegisterTPAGE(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTNOTEBOOK(Cl: TPSRuntimeClassImporter);
+{$IFNDEF FPC}procedure RIRegisterTHEADER(Cl: TPSRuntimeClassImporter);{$ENDIF}
+{$ENDIF}
+procedure RIRegisterTCUSTOMRADIOGROUP(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTRADIOGROUP(Cl: TPSRuntimeClassImporter);
+
+implementation
+
+uses
+ {$IFDEF CLX}
+ QExtCtrls, QGraphics;
+ {$ELSE}
+ ExtCtrls, Graphics;
+ {$ENDIF}
+
+procedure RIRegisterTSHAPE(Cl: TPSRuntimeClassImporter);
+begin
+ with Cl.Add(TSHAPE) do
+ begin
+ {$IFNDEF PS_MINIVCL}
+ RegisterMethod(@TSHAPE.STYLECHANGED, 'STYLECHANGED');
+ {$ENDIF}
+ end;
+end;
+
+procedure TIMAGECANVAS_R(Self: TIMAGE; var T: TCANVAS); begin T := Self.CANVAS; end;
+
+procedure RIRegisterTIMAGE(Cl: TPSRuntimeClassImporter);
+begin
+ with Cl.Add(TIMAGE) do
+ begin
+ RegisterPropertyHelper(@TIMAGECANVAS_R, nil, 'CANVAS');
+ end;
+end;
+
+procedure TPAINTBOXCANVAS_R(Self: TPAINTBOX; var T: TCanvas); begin T := Self.CANVAS; end;
+
+procedure RIRegisterTPAINTBOX(Cl: TPSRuntimeClassImporter);
+begin
+ with Cl.Add(TPAINTBOX) do
+ begin
+ RegisterPropertyHelper(@TPAINTBOXCANVAS_R, nil, 'CANVAS');
+ end;
+end;
+
+procedure RIRegisterTBEVEL(Cl: TPSRuntimeClassImporter);
+begin
+ Cl.Add(TBEVEL);
+end;
+
+procedure RIRegisterTTIMER(Cl: TPSRuntimeClassImporter);
+begin
+ Cl.Add(TTIMER);
+end;
+
+procedure RIRegisterTCUSTOMPANEL(Cl: TPSRuntimeClassImporter);
+begin
+ Cl.Add(TCUSTOMPANEL);
+end;
+
+procedure RIRegisterTPANEL(Cl: TPSRuntimeClassImporter);
+begin
+ Cl.Add(TPANEL);
+end;
+{$IFNDEF CLX}
+procedure RIRegisterTPAGE(Cl: TPSRuntimeClassImporter);
+begin
+ Cl.Add(TPAGE);
+end;
+
+procedure RIRegisterTNOTEBOOK(Cl: TPSRuntimeClassImporter);
+begin
+ Cl.Add(TNOTEBOOK);
+end;
+
+{$IFNDEF FPC}
+procedure THEADERSECTIONWIDTH_R(Self: THEADER; var T: INTEGER; t1: INTEGER); begin T := Self.SECTIONWIDTH[t1]; end;
+procedure THEADERSECTIONWIDTH_W(Self: THEADER; T: INTEGER; t1: INTEGER); begin Self.SECTIONWIDTH[t1] := T; end;
+
+procedure RIRegisterTHEADER(Cl: TPSRuntimeClassImporter);
+begin
+ with Cl.Add(THEADER) do
+ begin
+ RegisterPropertyHelper(@THEADERSECTIONWIDTH_R, @THEADERSECTIONWIDTH_W, 'SECTIONWIDTH');
+ end;
+end;
+{$ENDIF}
+{$ENDIF}
+
+procedure RIRegisterTCUSTOMRADIOGROUP(Cl: TPSRuntimeClassImporter);
+begin
+ Cl.Add(TCUSTOMRADIOGROUP);
+end;
+
+procedure RIRegisterTRADIOGROUP(Cl: TPSRuntimeClassImporter);
+begin
+ Cl.Add(TRADIOGROUP);
+end;
+
+procedure RIRegister_ExtCtrls(cl: TPSRuntimeClassImporter);
+begin
+ {$IFNDEF PS_MINIVCL}
+ RIRegisterTSHAPE(Cl);
+ RIRegisterTIMAGE(Cl);
+ RIRegisterTPAINTBOX(Cl);
+ {$ENDIF}
+ RIRegisterTBEVEL(Cl);
+ {$IFNDEF PS_MINIVCL}
+ RIRegisterTTIMER(Cl);
+ {$ENDIF}
+ RIRegisterTCUSTOMPANEL(Cl);
+{$IFNDEF CLX}
+ RIRegisterTPANEL(Cl);
+{$ENDIF}
+ {$IFNDEF PS_MINIVCL}
+{$IFNDEF CLX}
+ RIRegisterTPAGE(Cl);
+ RIRegisterTNOTEBOOK(Cl);
+ {$IFNDEF FPC}
+ RIRegisterTHEADER(Cl);
+ {$ENDIF}{FPC}
+{$ENDIF}
+ RIRegisterTCUSTOMRADIOGROUP(Cl);
+ RIRegisterTRADIOGROUP(Cl);
+ {$ENDIF}
+end;
+
+end.
+
+
diff --git a/branches/script-component/Units/PascalScript/uPSR_forms.pas b/branches/script-component/Units/PascalScript/uPSR_forms.pas
new file mode 100644
index 0000000..91f5db4
--- /dev/null
+++ b/branches/script-component/Units/PascalScript/uPSR_forms.pas
@@ -0,0 +1,264 @@
+
+unit uPSR_forms;
+
+{$I PascalScript.inc}
+interface
+uses
+ uPSRuntime, uPSUtils;
+
+procedure RIRegisterTCONTROLSCROLLBAR(Cl: TPSRuntimeClassImporter);
+{$IFNDEF FPC} procedure RIRegisterTSCROLLINGWINCONTROL(Cl: TPSRuntimeClassImporter);{$ENDIF}
+procedure RIRegisterTSCROLLBOX(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTFORM(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTAPPLICATION(Cl: TPSRuntimeClassImporter);
+
+procedure RIRegister_Forms(Cl: TPSRuntimeClassImporter);
+
+implementation
+uses
+ sysutils, classes, {$IFDEF CLX}QControls, QForms, QGraphics{$ELSE}Controls, Forms, Graphics{$ENDIF};
+
+procedure TCONTROLSCROLLBARKIND_R(Self: TCONTROLSCROLLBAR; var T: TSCROLLBARKIND); begin T := Self.KIND; end;
+procedure TCONTROLSCROLLBARSCROLLPOS_R(Self: TCONTROLSCROLLBAR; var T: INTEGER); begin t := Self.SCROLLPOS; end;
+
+procedure RIRegisterTCONTROLSCROLLBAR(Cl: TPSRuntimeClassImporter);
+begin
+ with Cl.Add(TCONTROLSCROLLBAR) do
+ begin
+ RegisterPropertyHelper(@TCONTROLSCROLLBARKIND_R, nil, 'KIND');
+ RegisterPropertyHelper(@TCONTROLSCROLLBARSCROLLPOS_R, nil, 'SCROLLPOS');
+ end;
+end;
+
+{$IFNDEF FPC}
+procedure RIRegisterTSCROLLINGWINCONTROL(Cl: TPSRuntimeClassImporter);
+begin
+ with Cl.Add(TSCROLLINGWINCONTROL) do
+ begin
+ RegisterMethod(@TSCROLLINGWINCONTROL.SCROLLINVIEW, 'SCROLLINVIEW');
+ end;
+end;
+{$ENDIF}
+
+procedure RIRegisterTSCROLLBOX(Cl: TPSRuntimeClassImporter);
+begin
+ Cl.Add(TSCROLLBOX);
+end;
+{$IFNDEF FPC}
+{$IFNDEF CLX}
+procedure TFORMACTIVEOLECONTROL_W(Self: TFORM; T: TWINCONTROL); begin Self.ACTIVEOLECONTROL := T; end;
+procedure TFORMACTIVEOLECONTROL_R(Self: TFORM; var T: TWINCONTROL); begin T := Self.ACTIVEOLECONTROL;
+end;
+procedure TFORMTILEMODE_W(Self: TFORM; T: TTILEMODE); begin Self.TILEMODE := T; end;
+procedure TFORMTILEMODE_R(Self: TFORM; var T: TTILEMODE); begin T := Self.TILEMODE; end;
+{$ENDIF}{CLX}
+procedure TFORMACTIVEMDICHILD_R(Self: TFORM; var T: TFORM); begin T := Self.ACTIVEMDICHILD; end;
+procedure TFORMDROPTARGET_W(Self: TFORM; T: BOOLEAN); begin Self.DROPTARGET := T; end;
+procedure TFORMDROPTARGET_R(Self: TFORM; var T: BOOLEAN); begin T := Self.DROPTARGET; end;
+procedure TFORMMDICHILDCOUNT_R(Self: TFORM; var T: INTEGER); begin T := Self.MDICHILDCOUNT; end;
+procedure TFORMMDICHILDREN_R(Self: TFORM; var T: TFORM; t1: INTEGER); begin T := Self.MDICHILDREN[T1];
+end;
+{$ENDIF}{FPC}
+
+procedure TFORMMODALRESULT_W(Self: TFORM; T: TMODALRESULT); begin Self.MODALRESULT := T; end;
+procedure TFORMMODALRESULT_R(Self: TFORM; var T: TMODALRESULT); begin T := Self.MODALRESULT; end;
+procedure TFORMACTIVE_R(Self: TFORM; var T: BOOLEAN); begin T := Self.ACTIVE; end;
+procedure TFORMCANVAS_R(Self: TFORM; var T: TCANVAS); begin T := Self.CANVAS; end;
+{$IFNDEF CLX}
+procedure TFORMCLIENTHANDLE_R(Self: TFORM; var T: Longint); begin T := Self.CLIENTHANDLE; end;
+{$ENDIF}
+
+{ Innerfuse Pascal Script Class Import Utility (runtime) }
+
+procedure RIRegisterTFORM(Cl: TPSRuntimeClassImporter);
+begin
+ with Cl.Add(TFORM) do
+ begin
+ {$IFDEF DELPHI4UP}
+ RegisterVirtualConstructor(@TFORM.CREATENEW, 'CREATENEW');
+ {$ELSE}
+ RegisterConstructor(@TFORM.CREATENEW, 'CREATENEW');
+ {$ENDIF}
+ RegisterMethod(@TFORM.CLOSE, 'CLOSE');
+ RegisterMethod(@TFORM.HIDE, 'HIDE');
+ RegisterMethod(@TFORM.SHOW, 'SHOW');
+ RegisterMethod(@TFORM.SHOWMODAL, 'SHOWMODAL');
+ RegisterMethod(@TFORM.RELEASE, 'RELEASE');
+ RegisterPropertyHelper(@TFORMACTIVE_R, nil, 'ACTIVE');
+
+ {$IFNDEF PS_MINIVCL}
+ {$IFNDEF FPC}
+{$IFNDEF CLX}
+ RegisterMethod(@TFORM.ARRANGEICONS, 'ARRANGEICONS');
+ RegisterMethod(@TFORM.GETFORMIMAGE, 'GETFORMIMAGE');
+ RegisterMethod(@TFORM.PRINT, 'PRINT');
+ RegisterMethod(@TFORM.SENDCANCELMODE, 'SENDCANCELMODE');
+ RegisterPropertyHelper(@TFORMACTIVEOLECONTROL_R, @TFORMACTIVEOLECONTROL_W, 'ACTIVEOLECONTROL');
+ RegisterPropertyHelper(@TFORMCLIENTHANDLE_R, nil, 'CLIENTHANDLE');
+ RegisterPropertyHelper(@TFORMTILEMODE_R, @TFORMTILEMODE_W, 'TILEMODE');
+{$ENDIF}{CLX}
+ RegisterMethod(@TFORM.CASCADE, 'CASCADE');
+ RegisterMethod(@TFORM.NEXT, 'NEXT');
+ RegisterMethod(@TFORM.PREVIOUS, 'PREVIOUS');
+ RegisterMethod(@TFORM.TILE, 'TILE');
+ RegisterPropertyHelper(@TFORMACTIVEMDICHILD_R, nil, 'ACTIVEMDICHILD');
+ RegisterPropertyHelper(@TFORMDROPTARGET_R, @TFORMDROPTARGET_W, 'DROPTARGET');
+ RegisterPropertyHelper(@TFORMMDICHILDCOUNT_R, nil, 'MDICHILDCOUNT');
+ RegisterPropertyHelper(@TFORMMDICHILDREN_R, nil, 'MDICHILDREN');
+ {$ENDIF}{FPC}
+ RegisterMethod(@TFORM.CLOSEQUERY, 'CLOSEQUERY');
+ RegisterMethod(@TFORM.DEFOCUSCONTROL, 'DEFOCUSCONTROL');
+ RegisterMethod(@TFORM.FOCUSCONTROL, 'FOCUSCONTROL');
+ RegisterMethod(@TFORM.SETFOCUSEDCONTROL, 'SETFOCUSEDCONTROL');
+ RegisterPropertyHelper(@TFORMCANVAS_R, nil, 'CANVAS');
+ RegisterPropertyHelper(@TFORMMODALRESULT_R, @TFORMMODALRESULT_W, 'MODALRESULT');
+ {$ENDIF}{PS_MINIVCL}
+ end;
+end;
+
+ {$IFNDEF FPC}
+procedure TAPPLICATIONACTIVE_R(Self: TAPPLICATION; var T: BOOLEAN); begin T := Self.ACTIVE; end;
+{$IFNDEF CLX}
+procedure TAPPLICATIONDIALOGHANDLE_R(Self: TAPPLICATION; var T: Longint); begin T := Self.DIALOGHANDLE; end;
+procedure TAPPLICATIONDIALOGHANDLE_W(Self: TAPPLICATION; T: Longint); begin Self.DIALOGHANDLE := T; end;
+procedure TAPPLICATIONHANDLE_R(Self: TAPPLICATION; var T: Longint); begin T := Self.HANDLE; end;
+procedure TAPPLICATIONHANDLE_W(Self: TAPPLICATION; T: Longint); begin Self.HANDLE := T; end;
+procedure TAPPLICATIONUPDATEFORMATSETTINGS_R(Self: TAPPLICATION; var T: BOOLEAN); begin T := Self.UPDATEFORMATSETTINGS; end;
+procedure TAPPLICATIONUPDATEFORMATSETTINGS_W(Self: TAPPLICATION; T: BOOLEAN); begin Self.UPDATEFORMATSETTINGS := T; end;
+{$ENDIF}
+{$ENDIF}{FPC}
+
+
+procedure TAPPLICATIONEXENAME_R(Self: TAPPLICATION; var T: STRING); begin T := Self.EXENAME; end;
+procedure TAPPLICATIONHELPFILE_R(Self: TAPPLICATION; var T: STRING); begin T := Self.HELPFILE; end;
+procedure TAPPLICATIONHELPFILE_W(Self: TAPPLICATION; T: STRING); begin Self.HELPFILE := T; end;
+procedure TAPPLICATIONHINT_R(Self: TAPPLICATION; var T: STRING); begin T := Self.HINT; end;
+procedure TAPPLICATIONHINT_W(Self: TAPPLICATION; T: STRING); begin Self.HINT := T; end;
+procedure TAPPLICATIONHINTCOLOR_R(Self: TAPPLICATION; var T: TCOLOR); begin T := Self.HINTCOLOR; end;
+procedure TAPPLICATIONHINTCOLOR_W(Self: TAPPLICATION; T: TCOLOR); begin Self.HINTCOLOR := T; end;
+procedure TAPPLICATIONHINTPAUSE_R(Self: TAPPLICATION; var T: INTEGER); begin T := Self.HINTPAUSE; end;
+procedure TAPPLICATIONHINTPAUSE_W(Self: TAPPLICATION; T: INTEGER); begin Self.HINTPAUSE := T; end;
+procedure TAPPLICATIONHINTSHORTPAUSE_R(Self: TAPPLICATION; var T: INTEGER); begin T := Self.HINTSHORTPAUSE; end;
+procedure TAPPLICATIONHINTSHORTPAUSE_W(Self: TAPPLICATION; T: INTEGER); begin Self.HINTSHORTPAUSE := T; end;
+procedure TAPPLICATIONHINTHIDEPAUSE_R(Self: TAPPLICATION; var T: INTEGER); begin T := Self.HINTHIDEPAUSE; end;
+procedure TAPPLICATIONHINTHIDEPAUSE_W(Self: TAPPLICATION; T: INTEGER); begin Self.HINTHIDEPAUSE := T; end;
+procedure TAPPLICATIONMAINFORM_R(Self: TAPPLICATION; var T: {$IFDEF DELPHI3UP}TCustomForm{$ELSE}TFORM{$ENDIF}); begin T := Self.MAINFORM; end;
+procedure TAPPLICATIONSHOWHINT_R(Self: TAPPLICATION; var T: BOOLEAN); begin T := Self.SHOWHINT; end;
+procedure TAPPLICATIONSHOWHINT_W(Self: TAPPLICATION; T: BOOLEAN); begin Self.SHOWHINT := T; end;
+procedure TAPPLICATIONSHOWMAINFORM_R(Self: TAPPLICATION; var T: BOOLEAN); begin T := Self.SHOWMAINFORM; end;
+procedure TAPPLICATIONSHOWMAINFORM_W(Self: TAPPLICATION; T: BOOLEAN); begin Self.SHOWMAINFORM := T; end;
+procedure TAPPLICATIONTERMINATED_R(Self: TAPPLICATION; var T: BOOLEAN); begin T := Self.TERMINATED; end;
+procedure TAPPLICATIONTITLE_R(Self: TAPPLICATION; var T: STRING); begin T := Self.TITLE; end;
+procedure TAPPLICATIONTITLE_W(Self: TAPPLICATION; T: STRING); begin Self.TITLE := T; end;
+
+{$IFNDEF FPC}
+procedure TAPPLICATIONONACTIVATE_R(Self: TAPPLICATION; var T: TNOTIFYEVENT); begin T := Self.ONACTIVATE; end;
+procedure TAPPLICATIONONACTIVATE_W(Self: TAPPLICATION; T: TNOTIFYEVENT); begin Self.ONACTIVATE := T; end;
+procedure TAPPLICATIONONDEACTIVATE_R(Self: TAPPLICATION; var T: TNOTIFYEVENT); begin T := Self.ONDEACTIVATE; end;
+procedure TAPPLICATIONONDEACTIVATE_W(Self: TAPPLICATION; T: TNOTIFYEVENT); begin Self.ONDEACTIVATE := T; end;
+{$ENDIF}
+
+procedure TAPPLICATIONONIDLE_R(Self: TAPPLICATION; var T: TIDLEEVENT); begin T := Self.ONIDLE; end;
+procedure TAPPLICATIONONIDLE_W(Self: TAPPLICATION; T: TIDLEEVENT); begin Self.ONIDLE := T; end;
+procedure TAPPLICATIONONHELP_R(Self: TAPPLICATION; var T: THELPEVENT); begin T := Self.ONHELP; end;
+procedure TAPPLICATIONONHELP_W(Self: TAPPLICATION; T: THELPEVENT); begin Self.ONHELP := T; end;
+procedure TAPPLICATIONONHINT_R(Self: TAPPLICATION; var T: TNOTIFYEVENT); begin T := Self.ONHINT; end;
+procedure TAPPLICATIONONHINT_W(Self: TAPPLICATION; T: TNOTIFYEVENT); begin Self.ONHINT := T; end;
+
+{$IFNDEF FPC}
+procedure TAPPLICATIONONMINIMIZE_R(Self: TAPPLICATION; var T: TNOTIFYEVENT); begin T := Self.ONMINIMIZE; end;
+procedure TAPPLICATIONONMINIMIZE_W(Self: TAPPLICATION; T: TNOTIFYEVENT); begin Self.ONMINIMIZE := T; end;
+
+procedure TAPPLICATIONONRESTORE_R(Self: TAPPLICATION; var T: TNOTIFYEVENT); begin T := Self.ONRESTORE; end;
+procedure TAPPLICATIONONRESTORE_W(Self: TAPPLICATION; T: TNOTIFYEVENT); begin Self.ONRESTORE := T; end;
+{$ENDIF}
+
+procedure RIRegisterTAPPLICATION(Cl: TPSRuntimeClassImporter);
+begin
+ with Cl.Add(TAPPLICATION) do
+ begin
+ {$IFNDEF FPC}
+ RegisterMethod(@TAPPLICATION.MINIMIZE, 'MINIMIZE');
+ RegisterMethod(@TAPPLICATION.RESTORE, 'RESTORE');
+ RegisterPropertyHelper(@TAPPLICATIONACTIVE_R, nil, 'ACTIVE');
+ RegisterPropertyHelper(@TAPPLICATIONONACTIVATE_R, @TAPPLICATIONONACTIVATE_W, 'ONACTIVATE');
+ RegisterPropertyHelper(@TAPPLICATIONONDEACTIVATE_R, @TAPPLICATIONONDEACTIVATE_W, 'ONDEACTIVATE');
+ RegisterPropertyHelper(@TAPPLICATIONONMINIMIZE_R, @TAPPLICATIONONMINIMIZE_W, 'ONMINIMIZE');
+ RegisterPropertyHelper(@TAPPLICATIONONRESTORE_R, @TAPPLICATIONONRESTORE_W, 'ONRESTORE');
+ RegisterPropertyHelper(@TAPPLICATIONDIALOGHANDLE_R, @TAPPLICATIONDIALOGHANDLE_W, 'DIALOGHANDLE');
+ RegisterMethod(@TAPPLICATION.CREATEHANDLE, 'CREATEHANDLE');
+ RegisterMethod(@TAPPLICATION.NORMALIZETOPMOSTS, 'NORMALIZETOPMOSTS');
+ RegisterMethod(@TAPPLICATION.RESTORETOPMOSTS, 'RESTORETOPMOSTS');
+ {$IFNDEF CLX}
+ RegisterPropertyHelper(@TAPPLICATIONHANDLE_R, @TAPPLICATIONHANDLE_W, 'HANDLE');
+ RegisterPropertyHelper(@TAPPLICATIONUPDATEFORMATSETTINGS_R, @TAPPLICATIONUPDATEFORMATSETTINGS_W, 'UPDATEFORMATSETTINGS');
+ {$ENDIF}
+ {$ENDIF}
+ RegisterMethod(@TAPPLICATION.BRINGTOFRONT, 'BRINGTOFRONT');
+ RegisterMethod(@TAPPLICATION.MESSAGEBOX, 'MESSAGEBOX');
+ RegisterMethod(@TAPPLICATION.PROCESSMESSAGES, 'PROCESSMESSAGES');
+ RegisterMethod(@TAPPLICATION.TERMINATE, 'TERMINATE');
+ RegisterPropertyHelper(@TAPPLICATIONEXENAME_R, nil, 'EXENAME');
+ RegisterPropertyHelper(@TAPPLICATIONHINT_R, @TAPPLICATIONHINT_W, 'HINT');
+ RegisterPropertyHelper(@TAPPLICATIONMAINFORM_R, nil, 'MAINFORM');
+ RegisterPropertyHelper(@TAPPLICATIONSHOWHINT_R, @TAPPLICATIONSHOWHINT_W, 'SHOWHINT');
+ RegisterPropertyHelper(@TAPPLICATIONSHOWMAINFORM_R, @TAPPLICATIONSHOWMAINFORM_W, 'SHOWMAINFORM');
+ RegisterPropertyHelper(@TAPPLICATIONTERMINATED_R, nil, 'TERMINATED');
+ RegisterPropertyHelper(@TAPPLICATIONTITLE_R, @TAPPLICATIONTITLE_W, 'TITLE');
+ RegisterPropertyHelper(@TAPPLICATIONONIDLE_R, @TAPPLICATIONONIDLE_W, 'ONIDLE');
+ RegisterPropertyHelper(@TAPPLICATIONONHINT_R, @TAPPLICATIONONHINT_W, 'ONHINT');
+ {$IFNDEF PS_MINIVCL}
+ RegisterMethod(@TAPPLICATION.CONTROLDESTROYED, 'CONTROLDESTROYED');
+ RegisterMethod(@TAPPLICATION.CANCELHINT, 'CANCELHINT');
+ {$IFNDEF CLX}
+ {$IFNDEF FPC}
+ RegisterMethod(@TAPPLICATION.HELPCOMMAND, 'HELPCOMMAND');
+ {$ENDIF}
+ RegisterMethod(@TAPPLICATION.HELPCONTEXT, 'HELPCONTEXT');
+ {$IFNDEF FPC}
+ RegisterMethod(@TAPPLICATION.HELPJUMP, 'HELPJUMP');
+ {$ENDIF}
+ {$ENDIF}
+// RegisterMethod(@TAPPLICATION.HANDLEEXCEPTION, 'HANDLEEXCEPTION');
+// RegisterMethod(@TAPPLICATION.HOOKMAINWINDOW, 'HOOKMAINWINDOW');
+// RegisterMethod(@TAPPLICATION.UNHOOKMAINWINDOW, 'UNHOOKMAINWINDOW');
+
+ RegisterMethod(@TAPPLICATION.HANDLEMESSAGE, 'HANDLEMESSAGE');
+ RegisterMethod(@TAPPLICATION.HIDEHINT, 'HIDEHINT');
+ RegisterMethod(@TAPPLICATION.HINTMOUSEMESSAGE, 'HINTMOUSEMESSAGE');
+ RegisterMethod(@TAPPLICATION.INITIALIZE, 'INITIALIZE');
+ RegisterMethod(@TAPPLICATION.RUN, 'RUN');
+// RegisterMethod(@TAPPLICATION.SHOWEXCEPTION, 'SHOWEXCEPTION');
+ RegisterPropertyHelper(@TAPPLICATIONHELPFILE_R, @TAPPLICATIONHELPFILE_W, 'HELPFILE');
+ RegisterPropertyHelper(@TAPPLICATIONHINTCOLOR_R, @TAPPLICATIONHINTCOLOR_W, 'HINTCOLOR');
+ RegisterPropertyHelper(@TAPPLICATIONHINTPAUSE_R, @TAPPLICATIONHINTPAUSE_W, 'HINTPAUSE');
+ RegisterPropertyHelper(@TAPPLICATIONHINTSHORTPAUSE_R, @TAPPLICATIONHINTSHORTPAUSE_W, 'HINTSHORTPAUSE');
+ RegisterPropertyHelper(@TAPPLICATIONHINTHIDEPAUSE_R, @TAPPLICATIONHINTHIDEPAUSE_W, 'HINTHIDEPAUSE');
+ RegisterPropertyHelper(@TAPPLICATIONONHELP_R, @TAPPLICATIONONHELP_W, 'ONHELP');
+ {$ENDIF}
+ end;
+end;
+
+procedure RIRegister_Forms(Cl: TPSRuntimeClassImporter);
+begin
+ {$IFNDEF PS_MINIVCL}
+ RIRegisterTCONTROLSCROLLBAR(cl);
+ RIRegisterTSCROLLBOX(cl);
+ {$ENDIF}
+{$IFNDEF FPC} RIRegisterTScrollingWinControl(cl);{$ENDIF}
+ RIRegisterTForm(Cl);
+ {$IFNDEF PS_MINIVCL}
+ RIRegisterTApplication(Cl);
+ {$ENDIF}
+end;
+
+
+// PS_MINIVCL changes by Martijn Laan (mlaan at wintax _dot_ nl)
+// FPC changes by Boguslaw brandys (brandys at o2 _dot_ pl)
+
+end.
+
+
+
+
+
diff --git a/branches/script-component/Units/PascalScript/uPSR_graphics.pas b/branches/script-component/Units/PascalScript/uPSR_graphics.pas
new file mode 100644
index 0000000..45e6054
--- /dev/null
+++ b/branches/script-component/Units/PascalScript/uPSR_graphics.pas
@@ -0,0 +1,218 @@
+
+unit uPSR_graphics;
+{$I PascalScript.inc}
+interface
+uses
+ uPSRuntime, uPSUtils;
+
+
+
+procedure RIRegisterTGRAPHICSOBJECT(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTFont(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTPEN(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTBRUSH(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTCanvas(cl: TPSRuntimeClassImporter);
+procedure RIRegisterTGraphic(CL: TPSRuntimeClassImporter);
+procedure RIRegisterTBitmap(CL: TPSRuntimeClassImporter; Streams: Boolean);
+
+procedure RIRegister_Graphics(Cl: TPSRuntimeClassImporter; Streams: Boolean);
+
+implementation
+{$IFNDEF FPC}
+uses
+ Classes{$IFDEF CLX}, QGraphics{$ELSE}, Windows, Graphics{$ENDIF};
+{$ELSE}
+uses
+ Classes, Graphics,LCLType;
+{$ENDIF}
+
+{$IFNDEF CLX}
+procedure TFontHandleR(Self: TFont; var T: Longint); begin T := Self.Handle; end;
+procedure TFontHandleW(Self: TFont; T: Longint); begin Self.Handle := T; end;
+{$ENDIF}
+procedure TFontPixelsPerInchR(Self: TFont; var T: Longint); begin T := Self.PixelsPerInch; end;
+procedure TFontPixelsPerInchW(Self: TFont; T: Longint); begin {$IFNDEF FPC} Self.PixelsPerInch := T;{$ENDIF} end;
+procedure TFontStyleR(Self: TFont; var T: TFontStyles); begin T := Self.Style; end;
+procedure TFontStyleW(Self: TFont; T: TFontStyles); begin Self.Style:= T; end;
+
+procedure RIRegisterTFont(Cl: TPSRuntimeClassImporter);
+begin
+ with Cl.Add(TFont) do
+ begin
+ RegisterConstructor(@TFont.Create, 'CREATE');
+{$IFNDEF CLX}
+ RegisterPropertyHelper(@TFontHandleR, @TFontHandleW, 'HANDLE');
+{$ENDIF}
+ RegisterPropertyHelper(@TFontPixelsPerInchR, @TFontPixelsPerInchW, 'PIXELSPERINCH');
+ RegisterPropertyHelper(@TFontStyleR, @TFontStyleW, 'STYLE');
+ end;
+end;
+{$IFNDEF CLX}
+procedure TCanvasHandleR(Self: TCanvas; var T: Longint); begin T := Self.Handle; end;
+procedure TCanvasHandleW(Self: TCanvas; T: Longint); begin Self.Handle:= T; end;
+{$ENDIF}
+
+procedure TCanvasPixelsR(Self: TCanvas; var T: Longint; X,Y: Longint); begin T := Self.Pixels[X,Y]; end;
+procedure TCanvasPixelsW(Self: TCanvas; T, X, Y: Longint); begin Self.Pixels[X,Y]:= T; end;
+
+procedure RIRegisterTCanvas(cl: TPSRuntimeClassImporter); // requires TPersistent
+begin
+ with Cl.Add(TCanvas) do
+ begin
+{$IFNDEF FPC}
+ RegisterMethod(@TCanvas.Arc, 'ARC');
+ RegisterMethod(@TCanvas.Chord, 'CHORD');
+ RegisterMethod(@TCanvas.Rectangle, 'RECTANGLE');
+ RegisterMethod(@TCanvas.RoundRect, 'ROUNDRECT');
+ RegisterMethod(@TCanvas.Ellipse, 'ELLIPSE');
+ RegisterMethod(@TCanvas.FillRect, 'FILLRECT');
+{$ENDIF}
+ RegisterMethod(@TCanvas.Draw, 'DRAW');
+{$IFNDEF CLX}
+ RegisterMethod(@TCanvas.FloodFill, 'FLOODFILL');
+{$ENDIF}
+ RegisterMethod(@TCanvas.Lineto, 'LINETO');
+ RegisterMethod(@TCanvas.Moveto, 'MOVETO');
+ RegisterMethod(@TCanvas.Pie, 'PIE');
+ RegisterMethod(@TCanvas.Refresh, 'REFRESH');
+ RegisterMethod(@TCanvas.TextHeight, 'TEXTHEIGHT');
+ RegisterMethod(@TCanvas.TextOut, 'TEXTOUT');
+ RegisterMethod(@TCanvas.TextWidth, 'TEXTWIDTH');
+{$IFNDEF CLX}
+ RegisterPropertyHelper(@TCanvasHandleR, @TCanvasHandleW, 'HANDLE');
+{$ENDIF}
+ RegisterPropertyHelper(@TCanvasPixelsR, @TCanvasPixelsW, 'PIXELS');
+ end;
+end;
+
+
+procedure TGRAPHICSOBJECTONCHANGE_W(Self: TGraphicsObject; T: TNotifyEvent); begin Self.OnChange := t; end;
+procedure TGRAPHICSOBJECTONCHANGE_R(Self: TGraphicsObject; var T: TNotifyEvent); begin T :=Self.OnChange; end;
+
+
+procedure RIRegisterTGRAPHICSOBJECT(Cl: TPSRuntimeClassImporter);
+begin
+ with Cl.Add(TGRAPHICSOBJECT) do
+ begin
+ RegisterPropertyHelper(@TGRAPHICSOBJECTONCHANGE_R, @TGRAPHICSOBJECTONCHANGE_W, 'ONCHANGE');
+ end;
+end;
+
+procedure RIRegisterTPEN(Cl: TPSRuntimeClassImporter);
+begin
+ with Cl.Add(TPEN) do
+ begin
+ RegisterConstructor(@TPEN.CREATE, 'CREATE');
+ end;
+end;
+
+procedure RIRegisterTBRUSH(Cl: TPSRuntimeClassImporter);
+begin
+ with Cl.Add(TBRUSH) do
+ begin
+ RegisterConstructor(@TBRUSH.CREATE, 'CREATE');
+ end;
+end;
+
+procedure TGraphicOnChange_W(Self: TGraphic; const T: TNotifyEvent); begin Self.OnChange := T; end;
+procedure TGraphicOnChange_R(Self: TGraphic; var T: TNotifyEvent); begin T := Self.OnChange; end;
+procedure TGraphicWidth_W(Self: TGraphic; const T: Integer); begin Self.Width := T; end;
+procedure TGraphicWidth_R(Self: TGraphic; var T: Integer); begin T := Self.Width; end;
+procedure TGraphicModified_W(Self: TGraphic; const T: Boolean); begin Self.Modified := T; end;
+procedure TGraphicModified_R(Self: TGraphic; var T: Boolean); begin T := Self.Modified; end;
+procedure TGraphicHeight_W(Self: TGraphic; const T: Integer); begin Self.Height := T; end;
+procedure TGraphicHeight_R(Self: TGraphic; var T: Integer); begin T := Self.Height; end;
+procedure TGraphicEmpty_R(Self: TGraphic; var T: Boolean); begin T := Self.Empty; end;
+
+procedure RIRegisterTGraphic(CL: TPSRuntimeClassImporter);
+begin
+ with CL.Add(TGraphic) do
+ begin
+ RegisterVirtualConstructor(@TGraphic.Create, 'Create');
+ RegisterVirtualMethod(@TGraphic.LoadFromFile, 'LoadFromFile');
+ RegisterVirtualMethod(@TGraphic.SaveToFile, 'SaveToFile');
+ RegisterPropertyHelper(@TGraphicEmpty_R,nil,'Empty');
+ RegisterPropertyHelper(@TGraphicHeight_R,@TGraphicHeight_W,'Height');
+ RegisterPropertyHelper(@TGraphicWidth_R,@TGraphicWidth_W,'Width');
+ RegisterPropertyHelper(@TGraphicOnChange_R,@TGraphicOnChange_W,'OnChange');
+
+ {$IFNDEF PS_MINIVCL}
+ RegisterPropertyHelper(@TGraphicModified_R,@TGraphicModified_W,'Modified');
+ {$ENDIF}
+ end;
+end;
+
+procedure TBitmapTransparentColor_R(Self: TBitmap; var T: TColor); begin T := Self.TransparentColor; end;
+{$IFNDEF CLX}
+{$IFNDEF FPC}
+procedure TBitmapIgnorePalette_W(Self: TBitmap; const T: Boolean); begin Self.IgnorePalette := T; end;
+procedure TBitmapIgnorePalette_R(Self: TBitmap; var T: Boolean); begin T := Self.IgnorePalette; end;
+{$ENDIF}
+procedure TBitmapPalette_W(Self: TBitmap; const T: HPALETTE); begin Self.Palette := T; end;
+procedure TBitmapPalette_R(Self: TBitmap; var T: HPALETTE); begin T := Self.Palette; end;
+{$ENDIF}
+procedure TBitmapMonochrome_W(Self: TBitmap; const T: Boolean); begin Self.Monochrome := T; end;
+procedure TBitmapMonochrome_R(Self: TBitmap; var T: Boolean); begin T := Self.Monochrome; end;
+{$IFNDEF CLX}
+procedure TBitmapHandle_W(Self: TBitmap; const T: HBITMAP); begin Self.Handle := T; end;
+procedure TBitmapHandle_R(Self: TBitmap; var T: HBITMAP); begin T := Self.Handle; end;
+{$ENDIF}
+procedure TBitmapCanvas_R(Self: TBitmap; var T: TCanvas); begin T := Self.Canvas; end;
+
+procedure RIRegisterTBitmap(CL: TPSRuntimeClassImporter; Streams: Boolean);
+begin
+ with CL.Add(TBitmap) do
+ begin
+ if Streams then begin
+ RegisterMethod(@TBitmap.LoadFromStream, 'LoadFromStream');
+ RegisterMethod(@TBitmap.SaveToStream, 'SaveToStream');
+ end;
+ RegisterPropertyHelper(@TBitmapCanvas_R,nil,'Canvas');
+{$IFNDEF CLX}
+ RegisterPropertyHelper(@TBitmapHandle_R,@TBitmapHandle_W,'Handle');
+{$ENDIF}
+
+ {$IFNDEF PS_MINIVCL}
+{$IFNDEF FPC}
+ RegisterMethod(@TBitmap.Dormant, 'Dormant');
+{$ENDIF}
+ RegisterMethod(@TBitmap.FreeImage, 'FreeImage');
+{$IFNDEF CLX}
+ RegisterMethod(@TBitmap.LoadFromClipboardFormat, 'LoadFromClipboardFormat');
+{$ENDIF}
+ RegisterMethod(@TBitmap.LoadFromResourceName, 'LoadFromResourceName');
+ RegisterMethod(@TBitmap.LoadFromResourceID, 'LoadFromResourceID');
+{$IFNDEF CLX}
+ RegisterMethod(@TBitmap.ReleaseHandle, 'ReleaseHandle');
+ RegisterMethod(@TBitmap.ReleasePalette, 'ReleasePalette');
+ RegisterMethod(@TBitmap.SaveToClipboardFormat, 'SaveToClipboardFormat');
+ RegisterPropertyHelper(@TBitmapMonochrome_R,@TBitmapMonochrome_W,'Monochrome');
+ RegisterPropertyHelper(@TBitmapPalette_R,@TBitmapPalette_W,'Palette');
+{$IFNDEF FPC}
+ RegisterPropertyHelper(@TBitmapIgnorePalette_R,@TBitmapIgnorePalette_W,'IgnorePalette');
+{$ENDIF}
+{$ENDIF}
+ RegisterPropertyHelper(@TBitmapTransparentColor_R,nil,'TransparentColor');
+ {$ENDIF}
+ end;
+end;
+
+procedure RIRegister_Graphics(Cl: TPSRuntimeClassImporter; Streams: Boolean);
+begin
+ RIRegisterTGRAPHICSOBJECT(cl);
+ RIRegisterTFont(Cl);
+ RIRegisterTCanvas(cl);
+ RIRegisterTPEN(cl);
+ RIRegisterTBRUSH(cl);
+ RIRegisterTGraphic(CL);
+ RIRegisterTBitmap(CL, Streams);
+end;
+
+// PS_MINIVCL changes by Martijn Laan (mlaan at wintax _dot_ nl)
+
+end.
+
+
+
+
+
diff --git a/branches/script-component/Units/PascalScript/uPSR_menus.pas b/branches/script-component/Units/PascalScript/uPSR_menus.pas
new file mode 100644
index 0000000..6e2600a
--- /dev/null
+++ b/branches/script-component/Units/PascalScript/uPSR_menus.pas
@@ -0,0 +1,460 @@
+
+Unit uPSR_menus;
+{$I PascalScript.inc}
+Interface
+Uses uPSRuntime;
+
+procedure RIRegister_Menus_Routines(S: TPSExec);
+{$IFNDEF FPC}
+procedure RIRegisterTMENUITEMSTACK(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTPOPUPLIST(Cl: TPSRuntimeClassImporter);
+{$ENDIF}
+procedure RIRegisterTPOPUPMENU(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTMAINMENU(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTMENU(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTMENUITEM(Cl: TPSRuntimeClassImporter);
+procedure RIRegister_Menus(CL: TPSRuntimeClassImporter);
+
+implementation
+{$IFDEF LINUX}
+{$IFNDEF FPC}
+Uses
+ Libc, SysUtils, Classes, QControls, QMenus, QGraphics;
+{$ELSE}
+Uses
+ Libc, SysUtils, Classes, Controls, Menus, Graphics, LCLType, ImgList;
+{$ENDIF}
+{$ELSE}
+Uses {$IFNDEF FPC}WINDOWS,{$ELSE} LCLType,{$ENDIF} SYSUTILS, CLASSES, CONTNRS, MESSAGES, GRAPHICS, IMGLIST, ACTNLIST, Menus;
+{$ENDIF}
+
+
+{$IFNDEF FPC}
+procedure TPOPUPLISTWINDOW_R(Self: TPOPUPLIST; var T: HWND);
+begin T := Self.WINDOW; end;
+{$ENDIF}
+
+procedure TPOPUPMENUONPOPUP_W(Self: TPOPUPMENU; const T: TNOTIFYEVENT);
+begin Self.ONPOPUP := T; end;
+
+procedure TPOPUPMENUONPOPUP_R(Self: TPOPUPMENU; var T: TNOTIFYEVENT);
+begin T := Self.ONPOPUP; end;
+
+{$IFNDEF FPC}
+procedure TPOPUPMENUTRACKBUTTON_W(Self: TPOPUPMENU; const T: TTRACKBUTTON);
+begin Self.TRACKBUTTON := T; end;
+
+procedure TPOPUPMENUTRACKBUTTON_R(Self: TPOPUPMENU; var T: TTRACKBUTTON);
+begin T := Self.TRACKBUTTON; end;
+
+
+procedure TPOPUPMENUMENUANIMATION_W(Self: TPOPUPMENU; const T: TMENUANIMATION);
+begin Self.MENUANIMATION := T; end;
+
+procedure TPOPUPMENUMENUANIMATION_R(Self: TPOPUPMENU; var T: TMENUANIMATION);
+begin T := Self.MENUANIMATION; end;
+
+procedure TPOPUPMENUHELPCONTEXT_W(Self: TPOPUPMENU; const T: THELPCONTEXT);
+begin Self.HELPCONTEXT := T; end;
+
+procedure TPOPUPMENUHELPCONTEXT_R(Self: TPOPUPMENU; var T: THELPCONTEXT);
+begin T := Self.HELPCONTEXT; end;
+{$ENDIF}
+
+procedure TPOPUPMENUAUTOPOPUP_W(Self: TPOPUPMENU; const T: BOOLEAN);
+begin Self.AUTOPOPUP := T; end;
+
+procedure TPOPUPMENUAUTOPOPUP_R(Self: TPOPUPMENU; var T: BOOLEAN);
+begin T := Self.AUTOPOPUP; end;
+
+{$IFNDEF FPC}
+procedure TPOPUPMENUALIGNMENT_W(Self: TPOPUPMENU; const T: TPOPUPALIGNMENT);
+begin Self.ALIGNMENT := T; end;
+
+procedure TPOPUPMENUALIGNMENT_R(Self: TPOPUPMENU; var T: TPOPUPALIGNMENT);
+begin T := Self.ALIGNMENT; end;
+{$ENDIF}
+
+procedure TPOPUPMENUPOPUPCOMPONENT_W(Self: TPOPUPMENU; const T: TCOMPONENT);
+begin Self.POPUPCOMPONENT := T; end;
+
+procedure TPOPUPMENUPOPUPCOMPONENT_R(Self: TPOPUPMENU; var T: TCOMPONENT);
+begin T := Self.POPUPCOMPONENT; end;
+
+{$IFNDEF FPC}
+procedure TMAINMENUAUTOMERGE_W(Self: TMAINMENU; const T: BOOLEAN);
+begin Self.AUTOMERGE := T; end;
+
+procedure TMAINMENUAUTOMERGE_R(Self: TMAINMENU; var T: BOOLEAN);
+begin T := Self.AUTOMERGE; end;
+{$ENDIF}
+
+procedure TMENUITEMS_R(Self: TMENU; var T: TMENUITEM);
+begin T := Self.ITEMS; end;
+
+
+{$IFNDEF FPC}
+procedure TMENUWINDOWHANDLE_W(Self: TMENU; const T: HWND);
+begin Self.WINDOWHANDLE := T; end;
+
+procedure TMENUWINDOWHANDLE_R(Self: TMENU; var T: HWND);
+begin T := Self.WINDOWHANDLE; end;
+
+procedure TMENUPARENTBIDIMODE_W(Self: TMENU; const T: BOOLEAN);
+begin Self.PARENTBIDIMODE := T; end;
+
+procedure TMENUPARENTBIDIMODE_R(Self: TMENU; var T: BOOLEAN);
+begin T := Self.PARENTBIDIMODE; end;
+
+procedure TMENUOWNERDRAW_W(Self: TMENU; const T: BOOLEAN);
+begin Self.OWNERDRAW := T; end;
+
+procedure TMENUOWNERDRAW_R(Self: TMENU; var T: BOOLEAN);
+begin T := Self.OWNERDRAW; end;
+
+procedure TMENUBIDIMODE_W(Self: TMENU; const T: TBIDIMODE);
+begin Self.BIDIMODE := T; end;
+
+procedure TMENUBIDIMODE_R(Self: TMENU; var T: TBIDIMODE);
+begin T := Self.BIDIMODE; end;
+
+procedure TMENUAUTOLINEREDUCTION_W(Self: TMENU; const T: TMENUAUTOFLAG);
+begin Self.AUTOLINEREDUCTION := T; end;
+
+procedure TMENUAUTOLINEREDUCTION_R(Self: TMENU; var T: TMENUAUTOFLAG);
+begin T := Self.AUTOLINEREDUCTION; end;
+
+procedure TMENUAUTOHOTKEYS_W(Self: TMENU; const T: TMENUAUTOFLAG);
+begin Self.AUTOHOTKEYS := T; end;
+
+procedure TMENUAUTOHOTKEYS_R(Self: TMENU; var T: TMENUAUTOFLAG);
+begin T := Self.AUTOHOTKEYS; end;
+
+{$ENDIF}
+
+
+procedure TMENUHANDLE_R(Self: TMENU; var T: HMENU);
+begin T := Self.HANDLE; end;
+
+
+
+
+procedure TMENUIMAGES_W(Self: TMENU; const T: TCUSTOMIMAGELIST);
+begin Self.IMAGES := T; end;
+
+procedure TMENUIMAGES_R(Self: TMENU; var T: TCUSTOMIMAGELIST);
+begin T := Self.IMAGES; end;
+
+{$IFNDEF FPC}
+procedure TMENUITEMONMEASUREITEM_W(Self: TMENUITEM; const T: TMENUMEASUREITEMEVENT);
+begin Self.ONMEASUREITEM := T; end;
+
+procedure TMENUITEMONMEASUREITEM_R(Self: TMENUITEM; var T: TMENUMEASUREITEMEVENT);
+begin T := Self.ONMEASUREITEM; end;
+
+procedure TMENUITEMONADVANCEDDRAWITEM_W(Self: TMENUITEM; const T: TADVANCEDMENUDRAWITEMEVENT);
+begin Self.ONADVANCEDDRAWITEM := T; end;
+
+procedure TMENUITEMONADVANCEDDRAWITEM_R(Self: TMENUITEM; var T: TADVANCEDMENUDRAWITEMEVENT);
+begin T := Self.ONADVANCEDDRAWITEM; end;
+
+procedure TMENUITEMONDRAWITEM_W(Self: TMENUITEM; const T: TMENUDRAWITEMEVENT);
+begin Self.ONDRAWITEM := T; end;
+
+procedure TMENUITEMONDRAWITEM_R(Self: TMENUITEM; var T: TMENUDRAWITEMEVENT);
+begin T := Self.ONDRAWITEM; end;
+{$ENDIF}
+
+procedure TMENUITEMONCLICK_W(Self: TMENUITEM; const T: TNOTIFYEVENT);
+begin Self.ONCLICK := T; end;
+
+procedure TMENUITEMONCLICK_R(Self: TMENUITEM; var T: TNOTIFYEVENT);
+begin T := Self.ONCLICK; end;
+
+procedure TMENUITEMVISIBLE_W(Self: TMENUITEM; const T: BOOLEAN);
+begin Self.VISIBLE := T; end;
+
+procedure TMENUITEMVISIBLE_R(Self: TMENUITEM; var T: BOOLEAN);
+begin T := Self.VISIBLE; end;
+
+procedure TMENUITEMSHORTCUT_W(Self: TMENUITEM; const T: TSHORTCUT);
+begin Self.SHORTCUT := T; end;
+
+procedure TMENUITEMSHORTCUT_R(Self: TMENUITEM; var T: TSHORTCUT);
+begin T := Self.SHORTCUT; end;
+
+procedure TMENUITEMRADIOITEM_W(Self: TMENUITEM; const T: BOOLEAN);
+begin Self.RADIOITEM := T; end;
+
+procedure TMENUITEMRADIOITEM_R(Self: TMENUITEM; var T: BOOLEAN);
+begin T := Self.RADIOITEM; end;
+
+procedure TMENUITEMIMAGEINDEX_W(Self: TMENUITEM; const T: TIMAGEINDEX);
+begin Self.IMAGEINDEX := T; end;
+
+procedure TMENUITEMIMAGEINDEX_R(Self: TMENUITEM; var T: TIMAGEINDEX);
+begin T := Self.IMAGEINDEX; end;
+
+procedure TMENUITEMHINT_W(Self: TMENUITEM; const T: STRING);
+begin Self.HINT := T; end;
+
+procedure TMENUITEMHINT_R(Self: TMENUITEM; var T: STRING);
+begin T := Self.HINT; end;
+
+procedure TMENUITEMHELPCONTEXT_W(Self: TMENUITEM; const T: THELPCONTEXT);
+begin Self.HELPCONTEXT := T; end;
+
+procedure TMENUITEMHELPCONTEXT_R(Self: TMENUITEM; var T: THELPCONTEXT);
+begin T := Self.HELPCONTEXT; end;
+
+procedure TMENUITEMGROUPINDEX_W(Self: TMENUITEM; const T: BYTE);
+begin Self.GROUPINDEX := T; end;
+
+procedure TMENUITEMGROUPINDEX_R(Self: TMENUITEM; var T: BYTE);
+begin T := Self.GROUPINDEX; end;
+
+procedure TMENUITEMENABLED_W(Self: TMENUITEM; const T: BOOLEAN);
+begin Self.ENABLED := T; end;
+
+procedure TMENUITEMENABLED_R(Self: TMENUITEM; var T: BOOLEAN);
+begin T := Self.ENABLED; end;
+
+procedure TMENUITEMDEFAULT_W(Self: TMENUITEM; const T: BOOLEAN);
+begin Self.DEFAULT := T; end;
+
+procedure TMENUITEMDEFAULT_R(Self: TMENUITEM; var T: BOOLEAN);
+begin T := Self.DEFAULT; end;
+
+procedure TMENUITEMSUBMENUIMAGES_W(Self: TMENUITEM; const T: TCUSTOMIMAGELIST);
+begin Self.SUBMENUIMAGES := T; end;
+
+procedure TMENUITEMSUBMENUIMAGES_R(Self: TMENUITEM; var T: TCUSTOMIMAGELIST);
+begin T := Self.SUBMENUIMAGES; end;
+
+procedure TMENUITEMCHECKED_W(Self: TMENUITEM; const T: BOOLEAN);
+begin Self.CHECKED := T; end;
+
+procedure TMENUITEMCHECKED_R(Self: TMENUITEM; var T: BOOLEAN);
+begin T := Self.CHECKED; end;
+
+procedure TMENUITEMCAPTION_W(Self: TMENUITEM; const T: STRING);
+begin Self.CAPTION := T; end;
+
+procedure TMENUITEMCAPTION_R(Self: TMENUITEM; var T: STRING);
+begin T := Self.CAPTION; end;
+
+procedure TMENUITEMBITMAP_W(Self: TMENUITEM; const T: TBITMAP);
+begin Self.BITMAP := T; end;
+
+procedure TMENUITEMBITMAP_R(Self: TMENUITEM; var T: TBITMAP);
+begin T := Self.BITMAP; end;
+
+{$IFNDEF FPC}
+procedure TMENUITEMAUTOLINEREDUCTION_W(Self: TMENUITEM; const T: TMENUITEMAUTOFLAG);
+begin Self.AUTOLINEREDUCTION := T; end;
+
+procedure TMENUITEMAUTOLINEREDUCTION_R(Self: TMENUITEM; var T: TMENUITEMAUTOFLAG);
+begin T := Self.AUTOLINEREDUCTION; end;
+
+procedure TMENUITEMAUTOHOTKEYS_W(Self: TMENUITEM; const T: TMENUITEMAUTOFLAG);
+begin Self.AUTOHOTKEYS := T; end;
+
+procedure TMENUITEMAUTOHOTKEYS_R(Self: TMENUITEM; var T: TMENUITEMAUTOFLAG);
+begin T := Self.AUTOHOTKEYS; end;
+{$ENDIF}
+
+procedure TMENUITEMACTION_W(Self: TMENUITEM; const T: TBASICACTION);
+begin Self.ACTION := T; end;
+
+procedure TMENUITEMACTION_R(Self: TMENUITEM; var T: TBASICACTION);
+begin T := Self.ACTION; end;
+
+procedure TMENUITEMPARENT_R(Self: TMENUITEM; var T: TMENUITEM);
+begin T := Self.PARENT; end;
+
+procedure TMENUITEMMENUINDEX_W(Self: TMENUITEM; const T: INTEGER);
+begin Self.MENUINDEX := T; end;
+
+procedure TMENUITEMMENUINDEX_R(Self: TMENUITEM; var T: INTEGER);
+begin T := Self.MENUINDEX; end;
+
+procedure TMENUITEMITEMS_R(Self: TMENUITEM; var T: TMENUITEM; const t1: INTEGER);
+begin T := Self.ITEMS[t1]; end;
+
+procedure TMENUITEMCOUNT_R(Self: TMENUITEM; var T: INTEGER);
+begin T := Self.COUNT; end;
+
+procedure TMENUITEMHANDLE_R(Self: TMENUITEM; var T: HMENU);
+begin T := Self.HANDLE; end;
+
+procedure TMENUITEMCOMMAND_R(Self: TMENUITEM; var T: WORD);
+begin T := Self.COMMAND; end;
+
+procedure RIRegister_Menus_Routines(S: TPSExec);
+begin
+ S.RegisterDelphiFunction(@SHORTCUT, 'SHORTCUT', cdRegister);
+ S.RegisterDelphiFunction(@SHORTCUTTOKEY, 'SHORTCUTTOKEY', cdRegister);
+{$IFNDEF FPC}
+ S.RegisterDelphiFunction(@SHORTCUTTOTEXT, 'SHORTCUTTOTEXT', cdRegister);
+ S.RegisterDelphiFunction(@TEXTTOSHORTCUT, 'TEXTTOSHORTCUT', cdRegister);
+ S.RegisterDelphiFunction(@NEWMENU, 'NEWMENU', cdRegister);
+ S.RegisterDelphiFunction(@NEWPOPUPMENU, 'NEWPOPUPMENU', cdRegister);
+ S.RegisterDelphiFunction(@NEWSUBMENU, 'NEWSUBMENU', cdRegister);
+ S.RegisterDelphiFunction(@NEWITEM, 'NEWITEM', cdRegister);
+ S.RegisterDelphiFunction(@NEWLINE, 'NEWLINE', cdRegister);
+ S.RegisterDelphiFunction(@DRAWMENUITEM, 'DRAWMENUITEM', cdRegister);
+{$ENDIF}
+end;
+
+{$IFNDEF FPC}
+procedure RIRegisterTMENUITEMSTACK(Cl: TPSRuntimeClassImporter);
+begin
+ with Cl.Add(TMENUITEMSTACK) do
+ begin
+ RegisterMethod(@TMENUITEMSTACK.CLEARITEM, 'CLEARITEM');
+ end;
+end;
+
+procedure RIRegisterTPOPUPLIST(Cl: TPSRuntimeClassImporter);
+begin
+ with Cl.Add(TPOPUPLIST) do
+ begin
+ RegisterPropertyHelper(@TPOPUPLISTWINDOW_R,nil,'WINDOW');
+ RegisterMethod(@TPOPUPLIST.ADD, 'ADD');
+ RegisterMethod(@TPOPUPLIST.REMOVE, 'REMOVE');
+ end;
+end;
+{$ENDIF}
+
+
+procedure RIRegisterTPOPUPMENU(Cl: TPSRuntimeClassImporter);
+begin
+ with Cl.Add(TPOPUPMENU) do
+ begin
+ RegisterConstructor(@TPOPUPMENU.CREATE, 'CREATE');
+ RegisterVirtualMethod(@TPOPUPMENU.POPUP, 'POPUP');
+ RegisterPropertyHelper(@TPOPUPMENUPOPUPCOMPONENT_R,@TPOPUPMENUPOPUPCOMPONENT_W,'POPUPCOMPONENT');
+ RegisterEventPropertyHelper(@TPOPUPMENUONPOPUP_R,@TPOPUPMENUONPOPUP_W,'ONPOPUP');
+{$IFNDEF FPC}
+ RegisterPropertyHelper(@TPOPUPMENUALIGNMENT_R,@TPOPUPMENUALIGNMENT_W,'ALIGNMENT');
+ RegisterPropertyHelper(@TPOPUPMENUAUTOPOPUP_R,@TPOPUPMENUAUTOPOPUP_W,'AUTOPOPUP');
+ RegisterPropertyHelper(@TPOPUPMENUHELPCONTEXT_R,@TPOPUPMENUHELPCONTEXT_W,'HELPCONTEXT');
+ RegisterPropertyHelper(@TPOPUPMENUMENUANIMATION_R,@TPOPUPMENUMENUANIMATION_W,'MENUANIMATION');
+ RegisterPropertyHelper(@TPOPUPMENUTRACKBUTTON_R,@TPOPUPMENUTRACKBUTTON_W,'TRACKBUTTON');
+{$ENDIF}
+ end;
+end;
+
+procedure RIRegisterTMAINMENU(Cl: TPSRuntimeClassImporter);
+begin
+ with Cl.Add(TMAINMENU) do
+ begin
+{$IFNDEF FPC}
+ RegisterMethod(@TMAINMENU.MERGE, 'MERGE');
+ RegisterMethod(@TMAINMENU.UNMERGE, 'UNMERGE');
+ RegisterMethod(@TMAINMENU.POPULATEOLE2MENU, 'POPULATEOLE2MENU');
+ RegisterMethod(@TMAINMENU.GETOLE2ACCELERATORTABLE, 'GETOLE2ACCELERATORTABLE');
+ RegisterMethod(@TMAINMENU.SETOLE2MENUHANDLE, 'SETOLE2MENUHANDLE');
+ RegisterPropertyHelper(@TMAINMENUAUTOMERGE_R,@TMAINMENUAUTOMERGE_W,'AUTOMERGE');
+{$ENDIF}
+ end;
+end;
+
+
+procedure RIRegisterTMENU(Cl: TPSRuntimeClassImporter);
+begin
+ with Cl.Add(TMENU) do
+ begin
+ RegisterConstructor(@TMENU.CREATE, 'CREATE');
+ RegisterMethod(@TMENU.DISPATCHCOMMAND, 'DISPATCHCOMMAND');
+ RegisterMethod(@TMENU.FINDITEM, 'FINDITEM');
+ RegisterPropertyHelper(@TMENUIMAGES_R,@TMENUIMAGES_W,'IMAGES');
+ RegisterMethod(@TMENU.ISRIGHTTOLEFT, 'ISRIGHTTOLEFT');
+ RegisterPropertyHelper(@TMENUHANDLE_R,nil,'HANDLE');
+ RegisterPropertyHelper(@TMENUITEMS_R,nil,'ITEMS');
+{$IFNDEF FPC}
+ RegisterMethod(@TMENU.DISPATCHPOPUP, 'DISPATCHPOPUP');
+ RegisterMethod(@TMENU.PARENTBIDIMODECHANGED, 'PARENTBIDIMODECHANGED');
+ RegisterMethod(@TMENU.PROCESSMENUCHAR, 'PROCESSMENUCHAR');
+ RegisterPropertyHelper(@TMENUAUTOHOTKEYS_R,@TMENUAUTOHOTKEYS_W,'AUTOHOTKEYS');
+ RegisterPropertyHelper(@TMENUAUTOLINEREDUCTION_R,@TMENUAUTOLINEREDUCTION_W,'AUTOLINEREDUCTION');
+ RegisterPropertyHelper(@TMENUBIDIMODE_R,@TMENUBIDIMODE_W,'BIDIMODE');
+ RegisterMethod(@TMENU.GETHELPCONTEXT, 'GETHELPCONTEXT');
+ RegisterPropertyHelper(@TMENUOWNERDRAW_R,@TMENUOWNERDRAW_W,'OWNERDRAW');
+ RegisterPropertyHelper(@TMENUPARENTBIDIMODE_R,@TMENUPARENTBIDIMODE_W,'PARENTBIDIMODE');
+ RegisterPropertyHelper(@TMENUWINDOWHANDLE_R,@TMENUWINDOWHANDLE_W,'WINDOWHANDLE');
+{$ENDIF}
+ end;
+end;
+
+procedure RIRegisterTMENUITEM(Cl: TPSRuntimeClassImporter);
+begin
+ with Cl.Add(TMENUITEM) do
+ begin
+ RegisterConstructor(@TMENUITEM.CREATE, 'CREATE');
+ RegisterVirtualMethod(@TMENUITEM.INITIATEACTION, 'INITIATEACTION');
+ RegisterMethod(@TMENUITEM.INSERT, 'INSERT');
+ RegisterMethod(@TMENUITEM.DELETE, 'DELETE');
+ RegisterMethod(@TMENUITEM.CLEAR, 'CLEAR');
+ RegisterVirtualMethod(@TMENUITEM.CLICK, 'CLICK');
+{$IFNDEF FPC}
+ RegisterMethod(@TMENUITEM.FIND, 'FIND');
+ RegisterMethod(@TMENUITEM.NEWTOPLINE, 'NEWTOPLINE');
+ RegisterMethod(@TMENUITEM.NEWBOTTOMLINE, 'NEWBOTTOMLINE');
+ RegisterMethod(@TMENUITEM.INSERTNEWLINEBEFORE, 'INSERTNEWLINEBEFORE');
+ RegisterMethod(@TMENUITEM.INSERTNEWLINEAFTER, 'INSERTNEWLINEAFTER');
+ RegisterMethod(@TMENUITEM.RETHINKHOTKEYS, 'RETHINKHOTKEYS');
+ RegisterMethod(@TMENUITEM.RETHINKLINES, 'RETHINKLINES');
+ RegisterMethod(@TMENUITEM.ISLINE, 'ISLINE');
+{$ENDIF}
+ RegisterMethod(@TMENUITEM.INDEXOF, 'INDEXOF');
+ RegisterMethod(@TMENUITEM.GETIMAGELIST, 'GETIMAGELIST');
+ RegisterMethod(@TMENUITEM.GETPARENTCOMPONENT, 'GETPARENTCOMPONENT');
+ RegisterMethod(@TMENUITEM.GETPARENTMENU, 'GETPARENTMENU');
+ RegisterMethod(@TMENUITEM.HASPARENT, 'HASPARENT');
+ RegisterMethod(@TMENUITEM.ADD, 'ADD');
+ RegisterMethod(@TMENUITEM.REMOVE, 'REMOVE');
+{$IFNDEF FPC}
+ RegisterPropertyHelper(@TMENUITEMAUTOHOTKEYS_R,@TMENUITEMAUTOHOTKEYS_W,'AUTOHOTKEYS');
+ RegisterPropertyHelper(@TMENUITEMAUTOLINEREDUCTION_R,@TMENUITEMAUTOLINEREDUCTION_W,'AUTOLINEREDUCTION');
+ RegisterEventPropertyHelper(@TMENUITEMONDRAWITEM_R,@TMENUITEMONDRAWITEM_W,'ONDRAWITEM');
+ RegisterEventPropertyHelper(@TMENUITEMONADVANCEDDRAWITEM_R,@TMENUITEMONADVANCEDDRAWITEM_W,'ONADVANCEDDRAWITEM');
+ RegisterEventPropertyHelper(@TMENUITEMONMEASUREITEM_R,@TMENUITEMONMEASUREITEM_W,'ONMEASUREITEM');
+{$ENDIF}
+ RegisterPropertyHelper(@TMENUITEMCOMMAND_R,nil,'COMMAND');
+ RegisterPropertyHelper(@TMENUITEMHANDLE_R,nil,'HANDLE');
+ RegisterPropertyHelper(@TMENUITEMCOUNT_R,nil,'COUNT');
+ RegisterPropertyHelper(@TMENUITEMITEMS_R,nil,'ITEMS');
+ RegisterPropertyHelper(@TMENUITEMMENUINDEX_R,@TMENUITEMMENUINDEX_W,'MENUINDEX');
+ RegisterPropertyHelper(@TMENUITEMPARENT_R,nil,'PARENT');
+ RegisterPropertyHelper(@TMENUITEMACTION_R,@TMENUITEMACTION_W,'ACTION');
+ RegisterPropertyHelper(@TMENUITEMBITMAP_R,@TMENUITEMBITMAP_W,'BITMAP');
+ RegisterPropertyHelper(@TMENUITEMCAPTION_R,@TMENUITEMCAPTION_W,'CAPTION');
+ RegisterPropertyHelper(@TMENUITEMCHECKED_R,@TMENUITEMCHECKED_W,'CHECKED');
+ RegisterPropertyHelper(@TMENUITEMSUBMENUIMAGES_R,@TMENUITEMSUBMENUIMAGES_W,'SUBMENUIMAGES');
+ RegisterPropertyHelper(@TMENUITEMDEFAULT_R,@TMENUITEMDEFAULT_W,'DEFAULT');
+ RegisterPropertyHelper(@TMENUITEMENABLED_R,@TMENUITEMENABLED_W,'ENABLED');
+ RegisterPropertyHelper(@TMENUITEMGROUPINDEX_R,@TMENUITEMGROUPINDEX_W,'GROUPINDEX');
+ RegisterPropertyHelper(@TMENUITEMHELPCONTEXT_R,@TMENUITEMHELPCONTEXT_W,'HELPCONTEXT');
+ RegisterPropertyHelper(@TMENUITEMHINT_R,@TMENUITEMHINT_W,'HINT');
+ RegisterPropertyHelper(@TMENUITEMIMAGEINDEX_R,@TMENUITEMIMAGEINDEX_W,'IMAGEINDEX');
+ RegisterPropertyHelper(@TMENUITEMRADIOITEM_R,@TMENUITEMRADIOITEM_W,'RADIOITEM');
+ RegisterPropertyHelper(@TMENUITEMSHORTCUT_R,@TMENUITEMSHORTCUT_W,'SHORTCUT');
+ RegisterPropertyHelper(@TMENUITEMVISIBLE_R,@TMENUITEMVISIBLE_W,'VISIBLE');
+ RegisterEventPropertyHelper(@TMENUITEMONCLICK_R,@TMENUITEMONCLICK_W,'ONCLICK');
+ end;
+end;
+
+procedure RIRegister_Menus(CL: TPSRuntimeClassImporter);
+begin
+ RIRegisterTMENUITEM(Cl);
+ RIRegisterTMENU(Cl);
+ RIRegisterTPOPUPMENU(Cl);
+ RIRegisterTMAINMENU(Cl);
+ {$IFNDEF FPC}
+ RIRegisterTPOPUPLIST(Cl);
+ RIRegisterTMENUITEMSTACK(Cl);
+ {$ENDIF}
+end;
+
+end.
diff --git a/branches/script-component/Units/PascalScript/uPSR_std.pas b/branches/script-component/Units/PascalScript/uPSR_std.pas
new file mode 100644
index 0000000..a9b20ad
--- /dev/null
+++ b/branches/script-component/Units/PascalScript/uPSR_std.pas
@@ -0,0 +1,85 @@
+
+unit uPSR_std;
+{$I PascalScript.inc}
+interface
+uses
+ uPSRuntime, uPSUtils;
+
+
+procedure RIRegisterTObject(CL: TPSRuntimeClassImporter);
+procedure RIRegisterTPersistent(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTComponent(Cl: TPSRuntimeClassImporter);
+procedure RIRegister_Std(Cl: TPSRuntimeClassImporter);
+
+implementation
+uses
+ Classes;
+
+
+
+procedure RIRegisterTObject(CL: TPSRuntimeClassImporter);
+begin
+ with cl.Add(TObject) do
+ begin
+ RegisterConstructor(@TObject.Create, 'CREATE');
+ RegisterMethod(@TObject.Free, 'FREE');
+ end;
+end;
+
+procedure RIRegisterTPersistent(Cl: TPSRuntimeClassImporter);
+begin
+ with Cl.Add(TPersistent) do
+ begin
+ RegisterVirtualMethod(@TPersistent.Assign, 'ASSIGN');
+ end;
+end;
+
+procedure TComponentOwnerR(Self: TComponent; var T: TComponent); begin T := Self.Owner; end;
+
+
+procedure TCOMPONENTCOMPONENTS_R(Self: TCOMPONENT; var T: TCOMPONENT; t1: INTEGER); begin T := Self.COMPONENTS[t1]; end;
+procedure TCOMPONENTCOMPONENTCOUNT_R(Self: TCOMPONENT; var T: INTEGER); begin t := Self.COMPONENTCOUNT; end;
+procedure TCOMPONENTCOMPONENTINDEX_R(Self: TCOMPONENT; var T: INTEGER); begin t := Self.COMPONENTINDEX; end;
+procedure TCOMPONENTCOMPONENTINDEX_W(Self: TCOMPONENT; T: INTEGER); begin Self.COMPONENTINDEX := t; end;
+procedure TCOMPONENTCOMPONENTSTATE_R(Self: TCOMPONENT; var T: TCOMPONENTSTATE); begin t := Self.COMPONENTSTATE; end;
+procedure TCOMPONENTDESIGNINFO_R(Self: TCOMPONENT; var T: LONGINT); begin t := Self.DESIGNINFO; end;
+procedure TCOMPONENTDESIGNINFO_W(Self: TCOMPONENT; T: LONGINT); begin Self.DESIGNINFO := t; end;
+
+
+procedure RIRegisterTComponent(Cl: TPSRuntimeClassImporter);
+begin
+ with Cl.Add(TComponent) do
+ begin
+ RegisterMethod(@TComponent.FindComponent, 'FINDCOMPONENT');
+ RegisterVirtualConstructor(@TComponent.Create, 'CREATE');
+ RegisterPropertyHelper(@TComponentOwnerR, nil, 'OWNER');
+
+ RegisterMethod(@TCOMPONENT.DESTROYCOMPONENTS, 'DESTROYCOMPONENTS');
+ RegisterPropertyHelper(@TCOMPONENTCOMPONENTS_R, nil, 'COMPONENTS');
+ RegisterPropertyHelper(@TCOMPONENTCOMPONENTCOUNT_R, nil, 'COMPONENTCOUNT');
+ RegisterPropertyHelper(@TCOMPONENTCOMPONENTINDEX_R, @TCOMPONENTCOMPONENTINDEX_W, 'COMPONENTINDEX');
+ RegisterPropertyHelper(@TCOMPONENTCOMPONENTSTATE_R, nil, 'COMPONENTSTATE');
+ RegisterPropertyHelper(@TCOMPONENTDESIGNINFO_R, @TCOMPONENTDESIGNINFO_W, 'DESIGNINFO');
+ end;
+end;
+
+
+
+
+
+
+
+procedure RIRegister_Std(Cl: TPSRuntimeClassImporter);
+begin
+ RIRegisterTObject(CL);
+ RIRegisterTPersistent(Cl);
+ RIRegisterTComponent(Cl);
+end;
+// PS_MINIVCL changes by Martijn Laan (mlaan at wintax _dot_ nl)
+
+end.
+
+
+
+
+
diff --git a/branches/script-component/Units/PascalScript/uPSR_stdctrls.pas b/branches/script-component/Units/PascalScript/uPSR_stdctrls.pas
new file mode 100644
index 0000000..8610e96
--- /dev/null
+++ b/branches/script-component/Units/PascalScript/uPSR_stdctrls.pas
@@ -0,0 +1,287 @@
+{ STDCtrls import unit }
+unit uPSR_stdctrls;
+
+{$I PascalScript.inc}
+interface
+uses
+ uPSRuntime, uPSUtils;
+
+
+procedure RIRegisterTCUSTOMGROUPBOX(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTGROUPBOX(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTCUSTOMLABEL(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTLABEL(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTCUSTOMEDIT(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTEDIT(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTCUSTOMMEMO(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTMEMO(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTCUSTOMCOMBOBOX(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTCOMBOBOX(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTBUTTONCONTROL(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTBUTTON(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTCUSTOMCHECKBOX(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTCHECKBOX(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTRADIOBUTTON(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTCUSTOMLISTBOX(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTLISTBOX(Cl: TPSRuntimeClassImporter);
+procedure RIRegisterTSCROLLBAR(Cl: TPSRuntimeClassImporter);
+
+procedure RIRegister_stdctrls(cl: TPSRuntimeClassImporter);
+
+implementation
+uses
+ sysutils, classes{$IFDEF CLX}, QControls, QStdCtrls, QGraphics{$ELSE}, controls, stdctrls, Graphics{$ENDIF}{$IFDEF FPC},buttons{$ENDIF};
+
+procedure RIRegisterTCUSTOMGROUPBOX(Cl: TPSRuntimeClassImporter);
+begin
+ Cl.Add(TCUSTOMGROUPBOX);
+end;
+
+
+procedure RIRegisterTGROUPBOX(Cl: TPSRuntimeClassImporter);
+begin
+ Cl.Add(TGROUPBOX);
+end;
+{$IFNDEF CLX}
+procedure TCUSTOMLABELCANVAS_R(Self: TCUSTOMLABEL; var T: TCanvas); begin T := Self.CANVAS; end;
+{$ENDIF}
+
+procedure RIRegisterTCUSTOMLABEL(Cl: TPSRuntimeClassImporter);
+begin
+ with Cl.Add(TCUSTOMLABEL) do
+ begin
+ {$IFNDEF PS_MINIVCL}
+{$IFNDEF CLX}
+ RegisterPropertyHelper(@TCUSTOMLABELCANVAS_R, nil, 'CANVAS');
+{$ENDIF}
+ {$ENDIF}
+ end;
+end;
+
+procedure RIRegisterTLABEL(Cl: TPSRuntimeClassImporter);
+begin
+ Cl.Add(TLABEL);
+end;
+procedure TCUSTOMEDITMODIFIED_R(Self: TCUSTOMEDIT; var T: BOOLEAN); begin T := Self.MODIFIED; end;
+procedure TCUSTOMEDITMODIFIED_W(Self: TCUSTOMEDIT; T: BOOLEAN); begin Self.MODIFIED := T; end;
+procedure TCUSTOMEDITSELLENGTH_R(Self: TCUSTOMEDIT; var T: INTEGER); begin T := Self.SELLENGTH; end;
+procedure TCUSTOMEDITSELLENGTH_W(Self: TCUSTOMEDIT; T: INTEGER); begin Self.SELLENGTH := T; end;
+procedure TCUSTOMEDITSELSTART_R(Self: TCUSTOMEDIT; var T: INTEGER); begin T := Self.SELSTART; end;
+procedure TCUSTOMEDITSELSTART_W(Self: TCUSTOMEDIT; T: INTEGER); begin Self.SELSTART := T; end;
+procedure TCUSTOMEDITSELTEXT_R(Self: TCUSTOMEDIT; var T: STRING); begin T := Self.SELTEXT; end;
+procedure TCUSTOMEDITSELTEXT_W(Self: TCUSTOMEDIT; T: STRING); begin Self.SELTEXT := T; end;
+procedure TCUSTOMEDITTEXT_R(Self: TCUSTOMEDIT; var T: string); begin T := Self.TEXT; end;
+procedure TCUSTOMEDITTEXT_W(Self: TCUSTOMEDIT; T: string); begin Self.TEXT := T; end;
+
+
+procedure RIRegisterTCUSTOMEDIT(Cl: TPSRuntimeClassImporter);
+begin
+ with Cl.Add(TCUSTOMEDIT) do
+ begin
+ RegisterMethod(@TCUSTOMEDIT.CLEAR, 'CLEAR');
+ RegisterMethod(@TCUSTOMEDIT.CLEARSELECTION, 'CLEARSELECTION');
+ RegisterMethod(@TCUSTOMEDIT.SELECTALL, 'SELECTALL');
+ RegisterPropertyHelper(@TCUSTOMEDITMODIFIED_R, @TCUSTOMEDITMODIFIED_W, 'MODIFIED');
+ RegisterPropertyHelper(@TCUSTOMEDITSELLENGTH_R, @TCUSTOMEDITSELLENGTH_W, 'SELLENGTH');
+ RegisterPropertyHelper(@TCUSTOMEDITSELSTART_R, @TCUSTOMEDITSELSTART_W, 'SELSTART');
+ RegisterPropertyHelper(@TCUSTOMEDITSELTEXT_R, @TCUSTOMEDITSELTEXT_W, 'SELTEXT');
+ RegisterPropertyHelper(@TCUSTOMEDITTEXT_R, @TCUSTOMEDITTEXT_W, 'TEXT');
+
+ {$IFNDEF PS_MINIVCL}
+ RegisterMethod(@TCUSTOMEDIT.COPYTOCLIPBOARD, 'COPYTOCLIPBOARD');
+ RegisterMethod(@TCUSTOMEDIT.CUTTOCLIPBOARD, 'CUTTOCLIPBOARD');
+ RegisterMethod(@TCUSTOMEDIT.PASTEFROMCLIPBOARD, 'PASTEFROMCLIPBOARD');
+ {$IFNDEF FPC}
+ RegisterMethod(@TCUSTOMEDIT.GETSELTEXTBUF, 'GETSELTEXTBUF');
+ RegisterMethod(@TCUSTOMEDIT.SETSELTEXTBUF, 'SETSELTEXTBUF');
+ {$ENDIF}{FPC}
+ {$ENDIF}
+ end;
+end;
+
+procedure RIRegisterTEDIT(Cl: TPSRuntimeClassImporter);
+begin
+ Cl.Add(TEDIT);
+end;
+
+
+procedure TCUSTOMMEMOLINES_R(Self: {$IFDEF CLX}TMemo{$ELSE}TCUSTOMMEMO{$ENDIF}; var T: TSTRINGS); begin T := Self.LINES; end;
+procedure TCUSTOMMEMOLINES_W(Self: {$IFDEF CLX}TMemo{$ELSE}TCUSTOMMEMO{$ENDIF}; T: TSTRINGS); begin Self.LINES := T; end;
+
+
+procedure RIRegisterTCUSTOMMEMO(Cl: TPSRuntimeClassImporter);
+begin
+ with Cl.Add(TCUSTOMMEMO) do
+ begin
+ {$IFNDEF CLX}
+ RegisterPropertyHelper(@TCUSTOMMEMOLINES_R, @TCUSTOMMEMOLINES_W, 'LINES');
+ {$ENDIF}
+ end;
+end;
+
+
+procedure RIRegisterTMEMO(Cl: TPSRuntimeClassImporter);
+begin
+ with Cl.Add(TMEMO) do
+ begin
+ {$IFDEF CLX}
+ RegisterPropertyHelper(@TCUSTOMMEMOLINES_R, @TCUSTOMMEMOLINES_W, 'LINES');
+ {$ENDIF}
+ end;
+end;
+
+
+procedure TCUSTOMCOMBOBOXCANVAS_R(Self: TCUSTOMCOMBOBOX; var T: TCANVAS); begin T := Self.CANVAS; end;
+procedure TCUSTOMCOMBOBOXDROPPEDDOWN_R(Self: TCUSTOMCOMBOBOX; var T: BOOLEAN); begin T := Self.DROPPEDDOWN; end;
+procedure TCUSTOMCOMBOBOXDROPPEDDOWN_W(Self: TCUSTOMCOMBOBOX; T: BOOLEAN); begin Self.DROPPEDDOWN := T; end;
+procedure TCUSTOMCOMBOBOXITEMS_R(Self: TCUSTOMCOMBOBOX; var T: TSTRINGS); begin T := Self.ITEMS; end;
+procedure TCUSTOMCOMBOBOXITEMS_W(Self: TCUSTOMCOMBOBOX; T: TSTRINGS); begin Self.ITEMS := T; end;
+procedure TCUSTOMCOMBOBOXITEMINDEX_R(Self: TCUSTOMCOMBOBOX; var T: INTEGER); begin T := Self.ITEMINDEX; end;
+procedure TCUSTOMCOMBOBOXITEMINDEX_W(Self: TCUSTOMCOMBOBOX; T: INTEGER); begin Self.ITEMINDEX := T; end;
+procedure TCUSTOMCOMBOBOXSELLENGTH_R(Self: TCUSTOMCOMBOBOX; var T: INTEGER); begin T := Self.SELLENGTH; end;
+procedure TCUSTOMCOMBOBOXSELLENGTH_W(Self: TCUSTOMCOMBOBOX; T: INTEGER); begin Self.SELLENGTH := T; end;
+procedure TCUSTOMCOMBOBOXSELSTART_R(Self: TCUSTOMCOMBOBOX; var T: INTEGER); begin T := Self.SELSTART; end;
+procedure TCUSTOMCOMBOBOXSELSTART_W(Self: TCUSTOMCOMBOBOX; T: INTEGER); begin Self.SELSTART := T; end;
+procedure TCUSTOMCOMBOBOXSELTEXT_R(Self: TCUSTOMCOMBOBOX; var T: STRING); begin T := Self.SELTEXT; end;
+procedure TCUSTOMCOMBOBOXSELTEXT_W(Self: TCUSTOMCOMBOBOX; T: STRING); begin Self.SELTEXT := T; end;
+
+
+procedure RIRegisterTCUSTOMCOMBOBOX(Cl: TPSRuntimeClassImporter);
+begin
+ with Cl.Add(TCUSTOMCOMBOBOX) do
+ begin
+ RegisterPropertyHelper(@TCUSTOMCOMBOBOXDROPPEDDOWN_R, @TCUSTOMCOMBOBOXDROPPEDDOWN_W, 'DROPPEDDOWN');
+ RegisterPropertyHelper(@TCUSTOMCOMBOBOXITEMS_R, @TCUSTOMCOMBOBOXITEMS_W, 'ITEMS');
+ RegisterPropertyHelper(@TCUSTOMCOMBOBOXITEMINDEX_R, @TCUSTOMCOMBOBOXITEMINDEX_W, 'ITEMINDEX');
+
+ {$IFNDEF PS_MINIVCL}
+ RegisterMethod(@TCUSTOMCOMBOBOX.CLEAR, 'CLEAR');
+ RegisterMethod(@TCUSTOMCOMBOBOX.SELECTALL, 'SELECTALL');
+ RegisterPropertyHelper(@TCUSTOMCOMBOBOXCANVAS_R, nil, 'CANVAS');
+ RegisterPropertyHelper(@TCUSTOMCOMBOBOXSELLENGTH_R, @TCUSTOMCOMBOBOXSELLENGTH_W, 'SELLENGTH');
+ RegisterPropertyHelper(@TCUSTOMCOMBOBOXSELSTART_R, @TCUSTOMCOMBOBOXSELSTART_W, 'SELSTART');
+ RegisterPropertyHelper(@TCUSTOMCOMBOBOXSELTEXT_R, @TCUSTOMCOMBOBOXSELTEXT_W, 'SELTEXT');
+ {$ENDIF}
+ end;
+end;
+
+
+
+
+procedure RIRegisterTCOMBOBOX(Cl: TPSRuntimeClassImporter);
+begin
+ Cl.Add(TCOMBOBOX);
+end;
+
+
+
+procedure RIRegisterTBUTTONCONTROL(Cl: TPSRuntimeClassImporter);
+begin
+ Cl.Add(TBUTTONCONTROL);
+end;
+
+
+
+procedure RIRegisterTBUTTON(Cl: TPSRuntimeClassImporter);
+begin
+ Cl.Add(TBUTTON);
+end;
+
+
+
+
+procedure RIRegisterTCUSTOMCHECKBOX(Cl: TPSRuntimeClassImporter);
+begin
+ Cl.Add(TCUSTOMCHECKBOX);
+end;
+
+
+procedure RIRegisterTCHECKBOX(Cl: TPSRuntimeClassImporter);
+begin
+ Cl.Add(TCHECKBOX);
+end;
+
+
+procedure RIRegisterTRADIOBUTTON(Cl: TPSRuntimeClassImporter);
+begin
+ Cl.Add(TRADIOBUTTON);
+end;
+
+procedure TCUSTOMLISTBOXCANVAS_R(Self: TCUSTOMLISTBOX; var T: TCANVAS); begin T := Self.CANVAS; end;
+procedure TCUSTOMLISTBOXITEMS_R(Self: TCUSTOMLISTBOX; var T: TSTRINGS); begin T := Self.ITEMS; end;
+procedure TCUSTOMLISTBOXITEMS_W(Self: TCUSTOMLISTBOX; T: TSTRINGS); begin Self.ITEMS := T; end;
+procedure TCUSTOMLISTBOXITEMINDEX_R(Self: TCUSTOMLISTBOX; var T: INTEGER); begin T := Self.ITEMINDEX; end;
+procedure TCUSTOMLISTBOXITEMINDEX_W(Self: TCUSTOMLISTBOX; T: INTEGER); begin Self.ITEMINDEX := T; end;
+procedure TCUSTOMLISTBOXSELCOUNT_R(Self: TCUSTOMLISTBOX; var T: INTEGER); begin T := Self.SELCOUNT; end;
+procedure TCUSTOMLISTBOXSELECTED_R(Self: TCUSTOMLISTBOX; var T: BOOLEAN; t1: INTEGER); begin T := Self.SELECTED[t1]; end;
+procedure TCUSTOMLISTBOXSELECTED_W(Self: TCUSTOMLISTBOX; T: BOOLEAN; t1: INTEGER); begin Self.SELECTED[t1] := T; end;
+procedure TCUSTOMLISTBOXTOPINDEX_R(Self: TCUSTOMLISTBOX; var T: INTEGER); begin T := Self.TOPINDEX; end;
+procedure TCUSTOMLISTBOXTOPINDEX_W(Self: TCUSTOMLISTBOX; T: INTEGER); begin Self.TOPINDEX := T; end;
+
+
+procedure RIRegisterTCUSTOMLISTBOX(Cl: TPSRuntimeClassImporter);
+begin
+ with Cl.Add(TCUSTOMLISTBOX) do
+ begin
+ RegisterPropertyHelper(@TCUSTOMLISTBOXITEMS_R, @TCUSTOMLISTBOXITEMS_W, 'ITEMS');
+ RegisterPropertyHelper(@TCUSTOMLISTBOXITEMINDEX_R, @TCUSTOMLISTBOXITEMINDEX_W, 'ITEMINDEX');
+ RegisterPropertyHelper(@TCUSTOMLISTBOXSELCOUNT_R, nil, 'SELCOUNT');
+ RegisterPropertyHelper(@TCUSTOMLISTBOXSELECTED_R, @TCUSTOMLISTBOXSELECTED_W, 'SELECTED');
+
+ {$IFNDEF PS_MINIVCL}
+ RegisterMethod(@TCUSTOMLISTBOX.CLEAR, 'CLEAR');
+ RegisterMethod(@TCUSTOMLISTBOX.ITEMATPOS, 'ITEMATPOS');
+ RegisterMethod(@TCUSTOMLISTBOX.ITEMRECT, 'ITEMRECT');
+ RegisterPropertyHelper(@TCUSTOMLISTBOXCANVAS_R, nil, 'CANVAS');
+ RegisterPropertyHelper(@TCUSTOMLISTBOXTOPINDEX_R, @TCUSTOMLISTBOXTOPINDEX_W, 'TOPINDEX');
+ {$ENDIF}
+ end;
+end;
+
+
+procedure RIRegisterTLISTBOX(Cl: TPSRuntimeClassImporter);
+begin
+ Cl.Add(TLISTBOX);
+end;
+
+
+procedure RIRegisterTSCROLLBAR(Cl: TPSRuntimeClassImporter);
+begin
+ with Cl.Add(TSCROLLBAR) do
+ begin
+ RegisterMethod(@TSCROLLBAR.SETPARAMS, 'SETPARAMS');
+ end;
+end;
+
+
+procedure RIRegister_stdctrls(cl: TPSRuntimeClassImporter);
+begin
+ {$IFNDEF PS_MINIVCL}
+ RIRegisterTCUSTOMGROUPBOX(Cl);
+ RIRegisterTGROUPBOX(Cl);
+ {$ENDIF}
+ RIRegisterTCUSTOMLABEL(Cl);
+ RIRegisterTLABEL(Cl);
+ RIRegisterTCUSTOMEDIT(Cl);
+ RIRegisterTEDIT(Cl);
+ RIRegisterTCUSTOMMEMO(Cl);
+ RIRegisterTMEMO(Cl);
+ RIRegisterTCUSTOMCOMBOBOX(Cl);
+ RIRegisterTCOMBOBOX(Cl);
+ RIRegisterTBUTTONCONTROL(Cl);
+ RIRegisterTBUTTON(Cl);
+ RIRegisterTCUSTOMCHECKBOX(Cl);
+ RIRegisterTCHECKBOX(Cl);
+ RIRegisterTRADIOBUTTON(Cl);
+ RIRegisterTCUSTOMLISTBOX(Cl);
+ RIRegisterTLISTBOX(Cl);
+ {$IFNDEF PS_MINIVCL}
+ RIRegisterTSCROLLBAR(Cl);
+ {$ENDIF}
+end;
+
+// PS_MINIVCL changes by Martijn Laan (mlaan at wintax _dot_ nl)
+
+end.
+
+
diff --git a/branches/script-component/Units/PascalScript/uPSRuntime.pas b/branches/script-component/Units/PascalScript/uPSRuntime.pas
new file mode 100644
index 0000000..01e5097
--- /dev/null
+++ b/branches/script-component/Units/PascalScript/uPSRuntime.pas
@@ -0,0 +1,12472 @@
+unit uPSRuntime;
+
+{$I PascalScript.inc}
+{
+
+RemObjects Pascal Script III
+Copyright (C) 2000-2009 by Carlo Kok (ck@carlo-kok.com)
+
+}
+interface
+uses
+ SysUtils, uPSUtils{$IFDEF DELPHI6UP}, variants{$ENDIF}{$IFNDEF PS_NOIDISPATCH}{$IFDEF DELPHI3UP}, ActiveX, Windows{$ELSE}, Ole2{$ENDIF}{$ENDIF};
+
+
+type
+ TPSExec = class;
+ TPSStack = class;
+ TPSRuntimeAttributes = class;
+ TPSRuntimeAttribute = class;
+
+ TPSError = (ErNoError, erCannotImport, erInvalidType, ErInternalError,
+ erInvalidHeader, erInvalidOpcode, erInvalidOpcodeParameter, erNoMainProc,
+ erOutOfGlobalVarsRange, erOutOfProcRange, ErOutOfRange, erOutOfStackRange,
+ ErTypeMismatch, erUnexpectedEof, erVersionError, ErDivideByZero, ErMathError,
+ erCouldNotCallProc, erOutofRecordRange, erOutOfMemory, erException,
+ erNullPointerException, erNullVariantError, erInterfaceNotSupported, erCustomError);
+
+ TPSStatus = (isNotLoaded, isLoaded, isRunning, isPaused);
+
+ PByteArray = ^TByteArray;
+
+ TByteArray = array[0..1023] of Byte;
+
+ PDWordArray = ^TDWordArray;
+
+ TDWordArray = array[0..1023] of Cardinal;
+{@link(TPSProcRec)
+ PIFProcRec is a pointer to a TIProcRec record}
+ TPSProcRec = class;
+ TIFProcRec = TPSProcRec;
+ TPSExternalProcRec = class;
+ TIFPSExternalProcRec = TPSExternalProcRec;
+ TIFExternalProcRec = TPSExternalProcRec;
+ PIFProcRec = TPSProcRec;
+ PProcRec = ^TProcRec;
+
+ TPSProcPtr = function(Caller: TPSExec; p: TPSExternalProcRec; Global, Stack: TPSStack): Boolean;
+
+ TPSFreeProc = procedure (Caller: TPSExec; p: PProcRec);
+
+ TPSProcRec = class
+ private
+ FAttributes: TPSRuntimeAttributes;
+ public
+
+ constructor Create(Owner: TPSExec);
+
+ destructor Destroy; override;
+
+
+ property Attributes: TPSRuntimeAttributes read FAttributes;
+ end;
+
+ TPSExternalProcRec = class(TPSProcRec)
+ private
+ FExt1: Pointer;
+ FExt2: Pointer;
+ FName: tbtstring;
+ FProcPtr: TPSProcPtr;
+ FDecl: tbtstring;
+ public
+
+ property Name: tbtstring read FName write FName;
+
+ property Decl: tbtstring read FDecl write FDecl;
+
+ property Ext1: Pointer read FExt1 write FExt1;
+
+ property Ext2: Pointer read FExt2 write FExt2;
+
+ property ProcPtr: TPSProcPtr read FProcPtr write FProcPtr;
+ end;
+
+ TPSInternalProcRec = class(TPSProcRec)
+ private
+ FData: PByteArray;
+ FLength: Cardinal;
+ FExportNameHash: Longint;
+ FExportDecl: tbtstring;
+ FExportName: tbtstring;
+ public
+
+ property Data: PByteArray read FData;
+
+ property Length: Cardinal read FLength;
+
+ property ExportNameHash: Longint read FExportNameHash;
+
+ property ExportName: tbtstring read FExportName write FExportName;
+
+ property ExportDecl: tbtstring read FExportDecl write FExportDecl;
+
+
+ destructor Destroy; override;
+ end;
+
+ TProcRec = record
+
+ Name: ShortString;
+
+ Hash: Longint;
+
+ ProcPtr: TPSProcPtr;
+
+ FreeProc: TPSFreeProc;
+
+ Ext1, Ext2: Pointer;
+ end;
+
+ PBTReturnAddress = ^TBTReturnAddress;
+
+ TBTReturnAddress = packed record
+
+ ProcNo: TPSInternalProcRec;
+
+ Position, StackBase: Cardinal;
+ end;
+
+ TPSTypeRec = class
+ private
+ FExportNameHash: Longint;
+ FExportName: tbtstring;
+ FBaseType: TPSBaseType;
+ FAttributes: TPSRuntimeAttributes;
+ protected
+ FRealSize: Cardinal;
+ public
+
+ property RealSize: Cardinal read FRealSize;
+
+ property BaseType: TPSBaseType read FBaseType write FBaseType;
+
+ property ExportName: tbtstring read FExportName write FExportName;
+
+ property ExportNameHash: Longint read FExportNameHash write FExportNameHash;
+
+ property Attributes: TPSRuntimeAttributes read FAttributes write FAttributes;
+
+ procedure CalcSize; virtual;
+
+ constructor Create(Owner: TPSExec);
+ destructor Destroy; override;
+ end;
+
+ TPSTypeRec_ProcPtr = class(TPSTypeRec)
+ private
+ FParamInfo: tbtstring;
+ public
+
+ property ParamInfo: tbtstring read FParamInfo write FParamInfo;
+ procedure CalcSize; override;
+ end;
+ PIFTypeRec = TPSTypeRec;
+
+ TPSTypeRec_Class = class(TPSTypeRec)
+ private
+ FCN: tbtstring;
+ public
+
+ property CN: tbtstring read FCN write FCN;
+ end;
+{$IFNDEF PS_NOINTERFACES}
+
+ TPSTypeRec_Interface = class(TPSTypeRec)
+ private
+ FGuid: TGUID;
+ public
+
+ property Guid: TGUID read FGuid write FGuid;
+ end;
+{$ENDIF}
+
+ TPSTypeRec_Array = class(TPSTypeRec)
+ private
+ FArrayType: TPSTypeRec;
+ public
+
+ property ArrayType: TPSTypeRec read FArrayType write FArrayType;
+ procedure CalcSize; override;
+ end;
+
+ TPSTypeRec_StaticArray = class(TPSTypeRec_Array)
+ private
+ FSize: Longint;
+ FStartOffset: LongInt;
+ public
+
+ property Size: Longint read FSize write FSize;
+ property StartOffset: LongInt read FStartOffset write FStartOffset;
+
+ procedure CalcSize; override;
+ end;
+
+ TPSTypeRec_Set = class(TPSTypeRec)
+ private
+ FBitSize: Longint;
+ FByteSize: Longint;
+ public
+ {The number of bytes this would require (same as realsize)}
+ property aByteSize: Longint read FByteSize write FByteSize;
+ property aBitSize: Longint read FBitSize write FBitSize;
+ procedure CalcSize; override;
+ end;
+
+ TPSTypeRec_Record = class(TPSTypeRec)
+ private
+ FFieldTypes: TPSList;
+ FRealFieldOffsets: TPSList;
+ public
+
+ property FieldTypes: TPSList read FFieldTypes;
+
+ property RealFieldOffsets: TPSList read FRealFieldOffsets;
+
+ procedure CalcSize; override;
+
+ constructor Create(Owner: TPSExec);
+ destructor Destroy; override;
+ end;
+
+ PPSVariant = ^TPSVariant;
+
+ PIFVariant = PPSVariant;
+
+ TPSVariant = packed record
+ FType: TPSTypeRec;
+ end;
+
+ PPSVariantData = ^TPSVariantData;
+
+ TPSVariantData = packed record
+ VI: TPSVariant;
+ Data: array[0..0] of Byte;
+ end;
+
+ PPSVariantU8 = ^TPSVariantU8;
+
+ TPSVariantU8 = packed record
+ VI: TPSVariant;
+ Data: tbtU8;
+ end;
+
+
+ PPSVariantS8 = ^TPSVariantS8;
+
+ TPSVariantS8 = packed record
+ VI: TPSVariant;
+ Data: tbts8;
+ end;
+
+
+ PPSVariantU16 = ^TPSVariantU16;
+
+ TPSVariantU16 = packed record
+ VI: TPSVariant;
+ Data: tbtU16;
+ end;
+
+
+ PPSVariantS16 = ^TPSVariantS16;
+
+ TPSVariantS16 = packed record
+ VI: TPSVariant;
+ Data: tbts16;
+ end;
+
+
+ PPSVariantU32 = ^TPSVariantU32;
+
+ TPSVariantU32 = packed record
+ VI: TPSVariant;
+ Data: tbtU32;
+ end;
+
+
+ PPSVariantS32 = ^TPSVariantS32;
+
+ TPSVariantS32 = packed record
+ VI: TPSVariant;
+ Data: tbts32;
+ end;
+{$IFNDEF PS_NOINT64}
+
+ PPSVariantS64 = ^TPSVariantS64;
+
+ TPSVariantS64 = packed record
+ VI: TPSVariant;
+ Data: tbts64;
+ end;
+{$ENDIF}
+
+ PPSVariantAChar = ^TPSVariantAChar;
+
+ TPSVariantAChar = packed record
+ VI: TPSVariant;
+ Data: tbtChar;
+ end;
+
+{$IFNDEF PS_NOWIDESTRING}
+
+ PPSVariantWChar = ^TPSVariantWChar;
+
+ TPSVariantWChar = packed record
+ VI: TPSVariant;
+ Data: tbtWideChar;
+ end;
+{$ENDIF}
+
+ PPSVariantAString = ^TPSVariantAString;
+
+ TPSVariantAString = packed record
+ VI: TPSVariant;
+ Data: tbtString;
+ end;
+
+{$IFNDEF PS_NOWIDESTRING}
+
+ PPSVariantWString = ^TPSVariantWString;
+
+ TPSVariantWString = {$IFNDEF DELPHI2009UP}packed {$ENDIF}record
+ VI: TPSVariant;
+ Data: tbtWideString;
+ end;
+
+ PPSVariantUString = ^TPSVariantUString;
+
+ TPSVariantUString = {$IFNDEF DELPHI2009UP}packed {$ENDIF}record
+ VI: TPSVariant;
+ Data: tbtunicodestring;
+ end;
+
+{$ENDIF}
+
+
+ PPSVariantSingle = ^TPSVariantSingle;
+
+ TPSVariantSingle = packed record
+ VI: TPSVariant;
+ Data: tbtsingle;
+ end;
+
+
+ PPSVariantDouble = ^TPSVariantDouble;
+
+ TPSVariantDouble = packed record
+ VI: TPSVariant;
+ Data: tbtDouble;
+ end;
+
+
+ PPSVariantExtended = ^TPSVariantExtended;
+
+ TPSVariantExtended = packed record
+ VI: TPSVariant;
+ Data: tbtExtended;
+ end;
+
+
+ PPSVariantCurrency = ^TPSVariantCurrency;
+
+ TPSVariantCurrency = packed record
+ VI: TPSVariant;
+ Data: tbtCurrency;
+ end;
+
+ PPSVariantSet = ^TPSVariantSet;
+
+ TPSVariantSet = packed record
+ VI: TPSVariant;
+ Data: array[0..0] of Byte;
+ end;
+
+{$IFNDEF PS_NOINTERFACES}
+
+ PPSVariantInterface = ^TPSVariantInterface;
+
+ TPSVariantInterface = packed record
+ VI: TPSVariant;
+ Data: IUnknown;
+ end;
+{$ENDIF}
+
+ PPSVariantClass = ^TPSVariantClass;
+
+ TPSVariantClass = packed record
+ VI: TPSVariant;
+ Data: TObject;
+ end;
+
+
+ PPSVariantRecord = ^TPSVariantRecord;
+
+ TPSVariantRecord = packed record
+ VI: TPSVariant;
+ data: array[0..0] of byte;
+ end;
+
+
+ PPSVariantDynamicArray = ^TPSVariantDynamicArray;
+
+ TPSVariantDynamicArray = packed record
+ VI: TPSVariant;
+ Data: Pointer;
+ end;
+
+
+ PPSVariantStaticArray = ^TPSVariantStaticArray;
+
+ TPSVariantStaticArray = packed record
+ VI: TPSVariant;
+ data: array[0..0] of byte;
+ end;
+
+
+ PPSVariantPointer = ^TPSVariantPointer;
+
+ TPSVariantPointer = packed record
+ VI: TPSVariant;
+ DataDest: Pointer;
+ DestType: TPSTypeRec;
+ FreeIt: LongBool;
+ end;
+
+
+ PPSVariantReturnAddress = ^TPSVariantReturnAddress;
+
+ TPSVariantReturnAddress = packed record
+ VI: TPSVariant;
+ Addr: TBTReturnAddress;
+ end;
+
+
+ PPSVariantVariant = ^TPSVariantVariant;
+
+ TPSVariantVariant = packed record
+ VI: TPSVariant;
+ Data: Variant;
+ end;
+
+ PPSVariantProcPtr = ^TPSVariantProcPtr;
+ TPSVariantProcPtr = packed record
+ VI: TPSVariant;
+ ProcNo: Cardinal;
+ Self: Pointer;
+ Ptr: Pointer;
+ {
+ ProcNo = 0 means Self/Ptr become active (Ptr = nil means it's nil)
+ }
+ end;
+
+
+ TPSVarFreeType = (
+ vtNone,
+ vtTempVar
+ );
+
+ TPSResultData = packed record
+ P: Pointer;
+ aType: TPSTypeRec;
+ FreeType: TPSVarFreeType;
+ end;
+
+
+ PPSResource = ^TPSResource;
+
+ TPSResource = record
+ Proc: Pointer;
+ P: Pointer;
+ end;
+
+ TPSAttributeUseProc = function (Sender: TPSExec; const AttribType: tbtstring; Attr: TPSRuntimeAttribute): Boolean;
+
+ TPSAttributeType = class
+ private
+ FTypeName: tbtstring;
+ FUseProc: TPSAttributeUseProc;
+ FTypeNameHash: Longint;
+ public
+
+ property UseProc: TPSAttributeUseProc read FUseProc write FUseProc;
+
+ property TypeName: tbtstring read FTypeName write FTypeName;
+
+ property TypeNameHash: Longint read FTypeNameHash write FTypeNameHash;
+ end;
+
+ PClassItem = ^TClassItem;
+
+ TClassItem = record
+
+ FName: tbtstring;
+
+ FNameHash: Longint;
+
+ b: byte;
+ case byte of
+ 0: (Ptr: Pointer);
+ 1: (PointerInList: Pointer);
+ 3: (FReadFunc, FWriteFunc: Pointer); {Property Helper}
+ 4: (Ptr2: Pointer);
+ 5: (PointerInList2: Pointer);
+ 6: (); {Property helper, like 3}
+ 7: (); {Property helper that will pass it's name}
+ end;
+
+
+ PPSVariantIFC = ^TPSVariantIFC;
+ {Temporary variant into record}
+ TPSVariantIFC = packed record
+ Dta: Pointer;
+ aType: TPSTypeRec;
+ VarParam: Boolean;
+ end;
+ PIFPSVariantIFC = PPSVariantIFC;
+ TIFPSVariantIFC = TPSVariantIFC;
+
+ TPSRuntimeAttribute = class(TObject)
+ private
+ FValues: TPSStack;
+ FAttribType: tbtstring;
+ FOwner: TPSRuntimeAttributes;
+ FAttribTypeHash: Longint;
+ function GetValue(I: Longint): PIFVariant;
+ function GetValueCount: Longint;
+ public
+
+ property Owner: TPSRuntimeAttributes read FOwner;
+
+ property AttribType: tbtstring read FAttribType write FAttribType;
+
+ property AttribTypeHash: Longint read FAttribTypeHash write FAttribTypeHash;
+
+ property ValueCount: Longint read GetValueCount;
+
+ property Value[I: Longint]: PIFVariant read GetValue;
+
+ function AddValue(aType: TPSTypeRec): PPSVariant;
+
+ procedure DeleteValue(i: Longint);
+
+ procedure AdjustSize;
+
+
+ constructor Create(Owner: TPSRuntimeAttributes);
+
+ destructor Destroy; override;
+ end;
+
+ TPSRuntimeAttributes = class(TObject)
+ private
+ FAttributes: TPSList;
+ FOwner: TPSExec;
+ function GetCount: Longint;
+ function GetItem(I: Longint): TPSRuntimeAttribute;
+ public
+
+ property Owner: TPSExec read FOwner;
+
+ property Count: Longint read GetCount;
+
+ property Items[I: Longint]: TPSRuntimeAttribute read GetItem; default;
+
+ procedure Delete(I: Longint);
+
+ function Add: TPSRuntimeAttribute;
+
+ function FindAttribute(const Name: tbtstring): TPSRuntimeAttribute;
+
+
+ constructor Create(AOwner: TPSExec);
+
+ destructor Destroy; override;
+ end;
+ TPSOnGetNVariant = function (Sender: TPSExec; const Name: tbtstring): Variant;
+ TPSOnSetNVariant = procedure (Sender: TPSExec; const Name: tbtstring; V: Variant);
+
+ TPSOnLineEvent = procedure(Sender: TPSExec);
+
+ TPSOnSpecialProcImport = function (Sender: TPSExec; p: TPSExternalProcRec; Tag: Pointer): Boolean;
+
+ TPSOnException = procedure (Sender: TPSExec; ExError: TPSError; const ExParam: tbtstring; ExObject: TObject; ProcNo, Position: Cardinal);
+
+ TPSExec = class(TObject)
+ Private
+ FOnGetNVariant: TPSOnGetNVariant;
+ FOnSetNVariant: TPSOnSetNVariant;
+ FId: Pointer;
+ FJumpFlag: Boolean;
+ FCallCleanup: Boolean;
+ FOnException: TPSOnException;
+ function ReadData(var Data; Len: Cardinal): Boolean;
+ function ReadLong(var b: Cardinal): Boolean;
+ function DoCalc(var1, Var2: Pointer; var1Type, var2type: TPSTypeRec; CalcType: Cardinal): Boolean;
+ function DoBooleanCalc(var1, Var2, into: Pointer; var1Type, var2type, intotype: TPSTypeRec; Cmd: Cardinal): Boolean;
+ function SetVariantValue(dest, Src: Pointer; desttype, srctype: TPSTypeRec): Boolean;
+ function ReadVariable(var Dest: TPSResultData; UsePointer: Boolean): Boolean;
+ function DoBooleanNot(Dta: Pointer; aType: TPSTypeRec): Boolean;
+ function DoMinus(Dta: Pointer; aType: TPSTypeRec): Boolean;
+ function DoIntegerNot(Dta: Pointer; aType: TPSTypeRec): Boolean;
+ procedure RegisterStandardProcs;
+ Protected
+
+ FReturnAddressType: TPSTypeRec;
+
+ FVariantType: TPSTypeRec;
+
+ FVariantArrayType: TPSTypeRec;
+
+ FAttributeTypes: TPSList;
+
+ FExceptionStack: TPSList;
+
+ FResources: TPSList;
+
+ FExportedVars: TPSList;
+
+ FTypes: TPSList;
+
+ FProcs: TPSList;
+
+ FGlobalVars: TPSStack;
+
+ FTempVars: TPSStack;
+
+ FStack: TPSStack;
+
+ FMainProc: Cardinal;
+
+ FStatus: TPSStatus;
+
+ FCurrProc: TPSInternalProcRec;
+
+ FData: PByteArray;
+
+ FDataLength: Cardinal;
+
+ FCurrentPosition: Cardinal;
+
+ FCurrStackBase: Cardinal;
+
+ FOnRunLine: TPSOnLineEvent;
+
+ FSpecialProcList: TPSList;
+
+ FRegProcs: TPSList;
+
+ ExObject: TObject;
+
+ ExProc: Cardinal;
+
+ ExPos: Cardinal;
+
+ ExEx: TPSError;
+
+ ExParam: tbtstring;
+
+ function InvokeExternalMethod(At: TPSTypeRec_ProcPtr; Slf, Ptr: Pointer): Boolean;
+
+ function InnerfuseCall(_Self, Address: Pointer; CallingConv: TPSCallingConvention; Params: TPSList; res: PPSVariantIFC): Boolean;
+
+ procedure RunLine; virtual;
+
+ function ImportProc(const Name: ShortString; proc: TPSExternalProcRec): Boolean; Virtual;
+
+ procedure ExceptionProc(proc, Position: Cardinal; Ex: TPSError; const s: tbtstring; NewObject: TObject); Virtual;
+
+ function FindSpecialProcImport(P: TPSOnSpecialProcImport): pointer;
+ Public
+ function LastEx: TPSError;
+ function LastExParam: tbtstring;
+ function LastExProc: Integer;
+ function LastExPos: Integer;
+ procedure CMD_Err(EC: TPSError);
+
+ procedure CMD_Err2(EC: TPSError; const Param: tbtstring);
+
+ procedure CMD_Err3(EC: TPSError; const Param: tbtstring; ExObject: TObject);
+
+ property Id: Pointer read FID write FID;
+
+ class function About: tbtstring;
+
+ function RunProc(Params: TPSList; ProcNo: Cardinal): Boolean;
+
+ function RunProcP(const Params: array of Variant; const Procno: Cardinal): Variant;
+ function RunProcPVar(var Params: array of Variant; const Procno: Cardinal): Variant;
+
+ function RunProcPN(const Params: array of Variant; const ProcName: tbtstring): Variant;
+
+ function FindType(StartAt: Cardinal; BaseType: TPSBaseType; var l: Cardinal): PIFTypeRec;
+
+ function FindType2(BaseType: TPSBaseType): PIFTypeRec;
+
+ function GetTypeNo(l: Cardinal): PIFTypeRec;
+
+ function GetType(const Name: tbtstring): Cardinal;
+
+ function GetProc(const Name: tbtstring): Cardinal;
+
+ function GetVar(const Name: tbtstring): Cardinal;
+
+ function GetVar2(const Name: tbtstring): PIFVariant;
+
+ function GetVarNo(C: Cardinal): PIFVariant;
+
+ function GetProcNo(C: Cardinal): PIFProcRec;
+
+ function GetProcCount: Cardinal;
+
+ function GetVarCount: Longint;
+
+ function GetTypeCount: Longint;
+
+
+ constructor Create;
+
+ destructor Destroy; Override;
+
+
+ function RunScript: Boolean;
+
+
+ function LoadData(const s: tbtstring): Boolean; virtual;
+
+ procedure Clear; Virtual;
+
+ procedure Cleanup; Virtual;
+
+ procedure Stop; Virtual;
+
+ procedure Pause; Virtual;
+
+ property CallCleanup: Boolean read FCallCleanup write FCallCleanup;
+
+ property Status: TPSStatus Read FStatus;
+
+ property OnRunLine: TPSOnLineEvent Read FOnRunLine Write FOnRunLine;
+
+ procedure ClearspecialProcImports;
+
+ procedure AddSpecialProcImport(const FName: tbtstring; P: TPSOnSpecialProcImport; Tag: Pointer);
+
+ function RegisterFunctionName(const Name: tbtstring; ProcPtr: TPSProcPtr;
+ Ext1, Ext2: Pointer): PProcRec;
+
+ procedure RegisterDelphiFunction(ProcPtr: Pointer; const Name: tbtstring; CC: TPSCallingConvention);
+
+ procedure RegisterDelphiMethod(Slf, ProcPtr: Pointer; const Name: tbtstring; CC: TPSCallingConvention);
+
+ function GetProcAsMethod(const ProcNo: Cardinal): TMethod;
+
+ function GetProcAsMethodN(const ProcName: tbtstring): TMethod;
+
+ procedure RegisterAttributeType(useproc: TPSAttributeUseProc; const TypeName: tbtstring);
+
+ procedure ClearFunctionList;
+
+ property ExceptionProcNo: Cardinal Read ExProc;
+
+ property ExceptionPos: Cardinal Read ExPos;
+
+ property ExceptionCode: TPSError Read ExEx;
+
+ property ExceptionString: tbtstring read ExParam;
+
+ property ExceptionObject: TObject read ExObject write ExObject;
+
+ procedure AddResource(Proc, P: Pointer);
+
+ function IsValidResource(Proc, P: Pointer): Boolean;
+
+ procedure DeleteResource(P: Pointer);
+
+ function FindProcResource(Proc: Pointer): Pointer;
+
+ function FindProcResource2(Proc: Pointer; var StartAt: Longint): Pointer;
+
+ procedure RaiseCurrentException;
+
+ property OnException: TPSOnException read FOnException write FOnException;
+ property OnGetNVariant: TPSOnGetNVariant read FOnGetNVariant write FOnGetNVariant;
+ property OnSetNVariant: TPSOnSetNVariant read FOnSetNVariant write FOnSetNVariant;
+ end;
+
+ TPSStack = class(TPSList)
+ private
+ FDataPtr: Pointer;
+ FCapacity,
+ FLength: Longint;
+ function GetItem(I: Longint): PPSVariant;
+ procedure SetCapacity(const Value: Longint);
+ procedure AdjustLength;
+ public
+
+ property DataPtr: Pointer read FDataPtr;
+
+ property Capacity: Longint read FCapacity write SetCapacity;
+
+ property Length: Longint read FLength;
+
+
+ constructor Create;
+
+ destructor Destroy; override;
+
+ procedure Clear; {$IFDEF DELPHI5UP} reintroduce;{$ELSE} override; {$ENDIF}
+
+ function Push(TotalSize: Longint): PPSVariant;
+
+ function PushType(aType: TPSTypeRec): PPSVariant;
+
+ procedure Pop;
+ function GetInt(ItemNo: Longint): Longint;
+ function GetUInt(ItemNo: Longint): Cardinal;
+{$IFNDEF PS_NOINT64}
+ function GetInt64(ItemNo: Longint): Int64;
+{$ENDIF}
+ function GetString(ItemNo: Longint): string; // calls the native method
+ function GetAnsiString(ItemNo: Longint): tbtstring;
+{$IFNDEF PS_NOWIDESTRING}
+ function GetWideString(ItemNo: Longint): tbtWideString;
+ function GetUnicodeString(ItemNo: Longint): tbtunicodestring;
+{$ENDIF}
+ function GetReal(ItemNo: Longint): Extended;
+ function GetCurrency(ItemNo: Longint): Currency;
+ function GetBool(ItemNo: Longint): Boolean;
+ function GetClass(ItemNo: Longint): TObject;
+
+ procedure SetInt(ItemNo: Longint; const Data: Longint);
+ procedure SetUInt(ItemNo: Longint; const Data: Cardinal);
+{$IFNDEF PS_NOINT64}
+ procedure SetInt64(ItemNo: Longint; const Data: Int64);
+{$ENDIF}
+ procedure SetString(ItemNo: Longint; const Data: string);
+ procedure SetAnsiString(ItemNo: Longint; const Data: tbtstring);
+{$IFNDEF PS_NOWIDESTRING}
+ procedure SetWideString(ItemNo: Longint; const Data: tbtWideString);
+ procedure SetUnicodeString(ItemNo: Longint; const Data: tbtunicodestring);
+{$ENDIF}
+ procedure SetReal(ItemNo: Longint; const Data: Extended);
+ procedure SetCurrency(ItemNo: Longint; const Data: Currency);
+ procedure SetBool(ItemNo: Longint; const Data: Boolean);
+ procedure SetClass(ItemNo: Longint; const Data: TObject);
+
+ property Items[I: Longint]: PPSVariant read GetItem; default;
+ end;
+
+
+function PSErrorToString(x: TPSError; const Param: tbtstring): tbtstring;
+function TIFErrorToString(x: TPSError; const Param: tbtstring): tbtstring;
+function CreateHeapVariant(aType: TPSTypeRec): PPSVariant;
+procedure DestroyHeapVariant(v: PPSVariant);
+
+procedure FreePIFVariantList(l: TPSList);
+procedure FreePSVariantList(l: TPSList);
+
+const
+ ENoError = ERNoError;
+
+
+function PIFVariantToVariant(Src: PIFVariant; var Dest: Variant): Boolean;
+function VariantToPIFVariant(Exec: TPSExec; const Src: Variant; Dest: PIFVariant): Boolean;
+
+function PSGetRecField(const avar: TPSVariantIFC; Fieldno: Longint): TPSVariantIFC;
+function PSGetArrayField(const avar: TPSVariantIFC; Fieldno: Longint): TPSVariantIFC;
+function NewTPSVariantRecordIFC(avar: PPSVariant; Fieldno: Longint): TPSVariantIFC;
+
+function NewTPSVariantIFC(avar: PPSVariant; varparam: boolean): TPSVariantIFC;
+
+function NewPPSVariantIFC(avar: PPSVariant; varparam: boolean): PPSVariantIFC;
+
+procedure DisposePPSVariantIFC(aVar: PPSVariantIFC);
+
+procedure DisposePPSVariantIFCList(list: TPSList);
+
+
+function PSGetObject(Src: Pointer; aType: TPSTypeRec): TObject;
+function PSGetUInt(Src: Pointer; aType: TPSTypeRec): Cardinal;
+{$IFNDEF PS_NOINT64}
+function PSGetInt64(Src: Pointer; aType: TPSTypeRec): Int64;
+{$ENDIF}
+function PSGetReal(Src: Pointer; aType: TPSTypeRec): Extended;
+function PSGetCurrency(Src: Pointer; aType: TPSTypeRec): Currency;
+function PSGetInt(Src: Pointer; aType: TPSTypeRec): Longint;
+function PSGetString(Src: Pointer; aType: TPSTypeRec): string;
+function PSGetAnsiString(Src: Pointer; aType: TPSTypeRec): tbtString;
+{$IFNDEF PS_NOWIDESTRING}
+function PSGetWideString(Src: Pointer; aType: TPSTypeRec): tbtWideString;
+function PSGetUnicodeString(Src: Pointer; aType: TPSTypeRec): tbtunicodestring;
+{$ENDIF}
+
+procedure PSSetObject(Src: Pointer; aType: TPSTypeRec; var Ok: Boolean; Const val: TObject);
+procedure PSSetUInt(Src: Pointer; aType: TPSTypeRec; var Ok: Boolean; const Val: Cardinal);
+{$IFNDEF PS_NOINT64}
+procedure PSSetInt64(Src: Pointer; aType: TPSTypeRec; var Ok: Boolean; const Val: Int64);
+{$ENDIF}
+procedure PSSetReal(Src: Pointer; aType: TPSTypeRec; var Ok: Boolean; const Val: Extended);
+procedure PSSetCurrency(Src: Pointer; aType: TPSTypeRec; var Ok: Boolean; const Val: Currency);
+procedure PSSetInt(Src: Pointer; aType: TPSTypeRec; var Ok: Boolean; const Val: Longint);
+procedure PSSetString(Src: Pointer; aType: TPSTypeRec; var Ok: Boolean; const Val: String);
+procedure PSSetAnsiString(Src: Pointer; aType: TPSTypeRec; var Ok: Boolean; const Val: tbtString);
+{$IFNDEF PS_NOWIDESTRING}
+procedure PSSetWideString(Src: Pointer; aType: TPSTypeRec; var Ok: Boolean; const Val: tbtWideString);
+procedure PSSetUnicodeString(Src: Pointer; aType: TPSTypeRec; var Ok: Boolean; const Val: tbtunicodestring);
+{$ENDIF}
+
+procedure VNSetPointerTo(const Src: TPSVariantIFC; Data: Pointer; aType: TPSTypeRec);
+
+function VNGetUInt(const Src: TPSVariantIFC): Cardinal;
+{$IFNDEF PS_NOINT64}
+function VNGetInt64(const Src: TPSVariantIFC): Int64;
+{$ENDIF}
+function VNGetReal(const Src: TPSVariantIFC): Extended;
+function VNGetCurrency(const Src: TPSVariantIFC): Currency;
+function VNGetInt(const Src: TPSVariantIFC): Longint;
+function VNGetString(const Src: TPSVariantIFC): String;
+function VNGetAnsiString(const Src: TPSVariantIFC): tbtString;
+{$IFNDEF PS_NOWIDESTRING}
+function VNGetWideString(const Src: TPSVariantIFC): tbtWideString;
+function VNGetUnicodeString(const Src: TPSVariantIFC): tbtunicodestring;
+{$ENDIF}
+
+procedure VNSetUInt(const Src: TPSVariantIFC; const Val: Cardinal);
+{$IFNDEF PS_NOINT64}
+procedure VNSetInt64(const Src: TPSVariantIFC; const Val: Int64);
+{$ENDIF}
+procedure VNSetReal(const Src: TPSVariantIFC; const Val: Extended);
+procedure VNSetCurrency(const Src: TPSVariantIFC; const Val: Currency);
+procedure VNSetInt(const Src: TPSVariantIFC; const Val: Longint);
+procedure VNSetString(const Src: TPSVariantIFC; const Val: String);
+procedure VNSetAnsiString(const Src: TPSVariantIFC; const Val: tbtString);
+{$IFNDEF PS_NOWIDESTRING}
+procedure VNSetWideString(const Src: TPSVariantIFC; const Val: tbtWideString);
+procedure VNSetUnicodeString(const Src: TPSVariantIFC; const Val: tbtunicodestring);
+{$ENDIF}
+
+function VGetUInt(const Src: PIFVariant): Cardinal;
+{$IFNDEF PS_NOINT64}
+function VGetInt64(const Src: PIFVariant): Int64;
+{$ENDIF}
+function VGetReal(const Src: PIFVariant): Extended;
+function VGetCurrency(const Src: PIFVariant): Currency;
+function VGetInt(const Src: PIFVariant): Longint;
+function VGetString(const Src: PIFVariant): String;
+function VGetAnsiString(const Src: PIFVariant): tbtString;
+{$IFNDEF PS_NOWIDESTRING}
+function VGetWideString(const Src: PIFVariant): tbtWideString;
+function VGetUnicodeString(const Src: PIFVariant): tbtunicodestring;
+{$ENDIF}
+
+procedure VSetPointerTo(const Src: PIFVariant; Data: Pointer; aType: TPSTypeRec);
+procedure VSetUInt(const Src: PIFVariant; const Val: Cardinal);
+{$IFNDEF PS_NOINT64}
+procedure VSetInt64(const Src: PIFVariant; const Val: Int64);
+{$ENDIF}
+procedure VSetReal(const Src: PIFVariant; const Val: Extended);
+procedure VSetCurrency(const Src: PIFVariant; const Val: Currency);
+procedure VSetInt(const Src: PIFVariant; const Val: Longint);
+procedure VSetString(const Src: PIFVariant; const Val: string);
+procedure VSetAnsiString(const Src: PIFVariant; const Val: tbtString);
+{$IFNDEF PS_NOWIDESTRING}
+procedure VSetWideString(const Src: PIFVariant; const Val: tbtWideString);
+procedure VSetUnicodeString(const Src: PIFVariant; const Val: tbtunicodestring);
+{$ENDIF}
+
+type
+
+ EPSException = class(Exception)
+ private
+ FProcPos: Cardinal;
+ FProcNo: Cardinal;
+ FExec: TPSExec;
+ public
+
+ constructor Create(const Error: tbtstring; Exec: TPSExec; Procno, ProcPos: Cardinal);
+
+ property ProcNo: Cardinal read FProcNo;
+
+ property ProcPos: Cardinal read FProcPos;
+
+ property Exec: TPSExec read FExec;
+ end;
+
+ TPSRuntimeClass = class
+ protected
+ FClassName: tbtstring;
+ FClassNameHash: Longint;
+
+ FClassItems: TPSList;
+ FClass: TClass;
+
+ FEndOfVmt: Longint;
+ public
+
+ procedure RegisterConstructor(ProcPtr: Pointer; const Name: tbtstring);
+
+ procedure RegisterVirtualConstructor(ProcPtr: Pointer; const Name: tbtstring);
+
+ procedure RegisterMethod(ProcPtr: Pointer; const Name: tbtstring);
+
+ procedure RegisterVirtualMethod(ProcPtr: Pointer; const Name: tbtstring);
+
+ procedure RegisterVirtualAbstractMethod(ClassDef: TClass; ProcPtr: Pointer; const Name: tbtstring);
+
+ procedure RegisterPropertyHelper(ReadFunc, WriteFunc: Pointer; const Name: tbtstring);
+
+ procedure RegisterPropertyHelperName(ReadFunc, WriteFunc: Pointer; const Name: tbtstring);
+
+ procedure RegisterEventPropertyHelper(ReadFunc, WriteFunc: Pointer; const Name: tbtstring);
+
+ constructor Create(aClass: TClass; const AName: tbtstring);
+
+ destructor Destroy; override;
+ end;
+
+ TPSRuntimeClassImporter = class
+ private
+ FClasses: TPSList;
+ public
+
+ constructor Create;
+
+ constructor CreateAndRegister(Exec: TPSexec; AutoFree: Boolean);
+
+ destructor Destroy; override;
+
+ function Add(aClass: TClass): TPSRuntimeClass;
+
+ function Add2(aClass: TClass; const Name: tbtstring): TPSRuntimeClass;
+
+ procedure Clear;
+
+ function FindClass(const Name: tbtstring): TPSRuntimeClass;
+ end;
+ TIFPSRuntimeClassImporter = TPSRuntimeClassImporter;
+ TPSResourceFreeProc = procedure (Sender: TPSExec; P: TPSRuntimeClassImporter);
+
+
+procedure RegisterClassLibraryRuntime(SE: TPSExec; Importer: TPSRuntimeClassImporter);
+
+procedure SetVariantToClass(V: PIFVariant; Cl: TObject);
+{$IFNDEF PS_NOINTERFACES}
+procedure SetVariantToInterface(V: PIFVariant; Cl: IUnknown);
+{$ENDIF}
+
+procedure MyAllMethodsHandler;
+
+function GetMethodInfoRec(SE: TPSExec; ProcNo: Cardinal): Pointer;
+
+function MkMethod(FSE: TPSExec; No: Cardinal): TMethod;
+
+type
+ TIFInternalProcRec = TPSInternalProcRec;
+ TIFError = TPSError;
+ TIFStatus = TPSStatus;
+ TIFPSExec = TPSExec;
+ TIFPSStack = TPSStack;
+ TIFTypeRec = TPSTypeRec;
+
+
+ TPSCallingConvention = uPSUtils.TPSCallingConvention;
+const
+
+ cdRegister = uPSUtils.cdRegister;
+
+ cdPascal = uPSUtils.cdPascal;
+
+ cdCdecl = uPSUtils.cdCdecl;
+
+ cdStdCall = uPSUtils.cdStdCall;
+
+ InvalidVal = Cardinal(-1);
+
+function PSDynArrayGetLength(arr: Pointer; aType: TPSTypeRec): Longint;
+procedure PSDynArraySetLength(var arr: Pointer; aType: TPSTypeRec; NewLength: Longint);
+
+function GetPSArrayLength(Arr: PIFVariant): Longint;
+procedure SetPSArrayLength(Arr: PIFVariant; NewLength: Longint);
+
+function PSVariantToString(const p: TPSVariantIFC; const ClassProperties: tbtstring): tbtstring;
+function MakeString(const s: tbtstring): tbtstring;
+{$IFNDEF PS_NOWIDESTRING}
+function MakeWString(const s: tbtunicodestring): tbtstring;
+{$ENDIF}
+
+{$IFNDEF PS_NOIDISPATCH}
+function IDispatchInvoke(Self: IDispatch; PropertySet: Boolean; const Name: tbtString; const Par: array of Variant): Variant;
+{$ENDIF}
+
+
+implementation
+uses
+ TypInfo {$IFDEF DELPHI3UP}{$IFNDEF FPC} , ComObj {$ENDIF}{$ENDIF};
+
+{$IFDEF DELPHI3UP }
+resourceString
+{$ELSE }
+const
+{$ENDIF }
+
+ RPS_UnknownIdentifier = 'Unknown Identifier';
+ RPS_Exception = 'Exception: %s';
+ RPS_Invalid = '[Invalid]';
+
+ //- PSErrorToString
+ RPS_NoError = 'No Error';
+ RPS_CannotImport = 'Cannot Import %s';
+ RPS_InvalidType = 'Invalid Type';
+ RPS_InternalError = 'Internal error';
+ RPS_InvalidHeader = 'Invalid Header';
+ RPS_InvalidOpcode = 'Invalid Opcode';
+ RPS_InvalidOpcodeParameter = 'Invalid Opcode Parameter';
+ RPS_NoMainProc = 'no Main Proc';
+ RPS_OutOfGlobalVarsRange = 'Out of Global Vars range';
+ RPS_OutOfProcRange = 'Out of Proc Range';
+ RPS_OutOfRange = 'Out Of Range';
+ RPS_OutOfStackRange = 'Out Of Stack Range';
+ RPS_TypeMismatch = 'Type Mismatch';
+ RPS_UnexpectedEof = 'Unexpected End Of File';
+ RPS_VersionError = 'Version error';
+ RPS_DivideByZero = 'divide by Zero';
+ RPS_MathError = 'Math error';
+ RPS_CouldNotCallProc = 'Could not call proc';
+ RPS_OutofRecordRange = 'Out of Record Fields Range';
+ RPS_NullPointerException = 'Null Pointer Exception';
+ RPS_NullVariantError = 'Null variant error';
+ RPS_OutOfMemory = 'Out Of Memory';
+ RPS_InterfaceNotSupported = 'Interface not supported';
+ RPS_UnknownError = 'Unknown error';
+
+
+ RPS_InvalidVariable = 'Invalid variable';
+ RPS_InvalidArray = 'Invalid array';
+ RPS_OLEError = 'OLE error %.8x';
+ RPS_UnknownProcedure = 'Unknown procedure';
+ RPS_NotEnoughParameters = 'Not enough parameters';
+ RPS_InvalidParameter = 'Invalid parameter';
+ RPS_TooManyParameters = 'Too many parameters';
+ RPS_OutOfStringRange = 'Out of string range';
+ RPS_CannotCastInterface = 'Cannot cast an interface';
+ RPS_CannotCastObject = 'Cannot cast an object';
+ RPS_CapacityLength = 'Capacity < Length';
+ RPS_CanOnlySendLastItem = 'Can only remove last item from stack';
+ RPS_NILInterfaceException = 'Nil interface';
+ RPS_UnknownMethod = 'Unknown method';
+
+
+
+type
+ PPSExportedVar = ^TPSExportedVar;
+ TPSExportedVar = record
+ FName: tbtstring;
+ FNameHash: Longint;
+ FVarNo: Cardinal;
+ end;
+ PRaiseFrame = ^TRaiseFrame;
+ TRaiseFrame = record
+ NextRaise: PRaiseFrame;
+ ExceptAddr: Pointer;
+ ExceptObject: TObject;
+ ExceptionRecord: Pointer;
+ end;
+ TPSExceptionHandler = class
+ CurrProc: TPSInternalProcRec;
+ BasePtr, StackSize: Cardinal;
+ FinallyOffset, ExceptOffset, Finally2Offset, EndOfBlock: Cardinal;
+ ExceptionData: TPSError;
+ ExceptionObject: TObject;
+ ExceptionParam: tbtString;
+ destructor Destroy; override;
+ end;
+ TPSHeader = packed record
+ HDR: Cardinal;
+ PSBuildNo: Cardinal;
+ TypeCount: Cardinal;
+ ProcCount: Cardinal;
+ VarCount: Cardinal;
+ MainProcNo: Cardinal;
+ ImportTableSize: Cardinal;
+ end;
+
+ TPSExportItem = packed record
+ ProcNo: Cardinal;
+ NameLength: Cardinal;
+ DeclLength: Cardinal;
+ end;
+
+ TPSType = packed record
+ BaseType: TPSBaseType;
+ end;
+ TPSProc = packed record
+ Flags: Byte;
+ end;
+
+ TPSVar = packed record
+ TypeNo: Cardinal;
+ Flags: Byte;
+ end;
+ PSpecialProc = ^TSpecialProc;
+ TSpecialProc = record
+ P: TPSOnSpecialProcImport;
+ namehash: Longint;
+ Name: tbtstring;
+ tag: pointer;
+ end;
+
+destructor TPSExceptionHandler.Destroy;
+begin
+ ExceptionObject.Free;
+ inherited;
+end;
+
+procedure P_CM_A; begin end;
+procedure P_CM_CA; begin end;
+procedure P_CM_P; begin end;
+procedure P_CM_PV; begin end;
+procedure P_CM_PO; begin end;
+procedure P_CM_C; begin end;
+procedure P_CM_G; begin end;
+procedure P_CM_CG; begin end;
+procedure P_CM_CNG; begin end;
+procedure P_CM_R; begin end;
+procedure P_CM_ST; begin end;
+procedure P_CM_PT; begin end;
+procedure P_CM_CO; begin end;
+procedure P_CM_CV; begin end;
+procedure P_CM_SP; begin end;
+procedure P_CM_BN; begin end;
+procedure P_CM_VM; begin end;
+procedure P_CM_SF; begin end;
+procedure P_CM_FG; begin end;
+procedure P_CM_PUEXH; begin end;
+procedure P_CM_POEXH; begin end;
+procedure P_CM_IN; begin end;
+procedure P_CM_SPB; begin end;
+procedure P_CM_INC; begin end;
+procedure P_CM_DEC; begin end;
+
+function IntPIFVariantToVariant(Src: pointer; aType: TPSTypeRec; var Dest: Variant): Boolean; forward;
+
+
+procedure Set_Union(Dest, Src: PByteArray; ByteSize: Integer);
+var
+ i: Longint;
+begin
+ for i := ByteSize -1 downto 0 do
+ Dest^[i] := Dest^[i] or Src^[i];
+end;
+
+procedure Set_Diff(Dest, Src: PByteArray; ByteSize: Integer);
+var
+ i: Longint;
+begin
+ for i := ByteSize -1 downto 0 do
+ Dest^[i] := Dest^[i] and not Src^[i];
+end;
+
+procedure Set_Intersect(Dest, Src: PByteArray; ByteSize: Integer);
+var
+ i: Longint;
+begin
+ for i := ByteSize -1 downto 0 do
+ Dest^[i] := Dest^[i] and Src^[i];
+end;
+
+procedure Set_Subset(Dest, Src: PByteArray; ByteSize: Integer; var Val: Boolean);
+var
+ i: Integer;
+begin
+ for i := ByteSize -1 downto 0 do
+ begin
+ if not (Src^[i] and Dest^[i] = Dest^[i]) then
+ begin
+ Val := False;
+ exit;
+ end;
+ end;
+ Val := True;
+end;
+
+procedure Set_Equal(Dest, Src: PByteArray; ByteSize: Integer; var Val: Boolean);
+var
+ i: Longint;
+begin
+ for i := ByteSize -1 downto 0 do
+ begin
+ if Dest^[i] <> Src^[i] then
+ begin
+ Val := False;
+ exit;
+ end;
+ end;
+ val := True;
+end;
+
+procedure Set_membership(Item: Longint; Src: PByteArray; var Val: Boolean);
+begin
+ Val := (Src^[Item shr 3] and (1 shl (Item and 7))) <> 0;
+end;
+
+
+procedure RCIFreeProc(Sender: TPSExec; P: TPSRuntimeClassImporter);
+begin
+ p.Free;
+end;
+
+function Trim(const s: tbtstring): tbtstring;
+begin
+ Result := s;
+ while (Length(result) > 0) and (Result[1] = #32) do Delete(Result, 1, 1);
+ while (Length(result) > 0) and (Result[Length(Result)] = #32) do Delete(Result, Length(Result), 1);
+end;
+(*function FloatToStr(E: Extended): tbtstring;
+begin
+ Result := Sysutils.FloatToStr(e);
+end;*)
+
+//-------------------------------------------------------------------
+
+function Padl(s: tbtstring; i: longInt): tbtstring;
+begin
+ result := StringOfChar(tbtchar(' '), i - length(s)) + s;
+end;
+//-------------------------------------------------------------------
+
+function Padz(s: tbtString; i: longInt): tbtString;
+begin
+ result := StringOfChar(tbtchar('0'), i - length(s)) + s;
+end;
+//-------------------------------------------------------------------
+
+function Padr(s: tbtString; i: longInt): tbtString;
+begin
+ result := s + StringOfChar(tbtchar(' '), i - Length(s));
+end;
+//-------------------------------------------------------------------
+
+{$IFNDEF PS_NOWIDESTRING}
+function wPadl(s: tbtwidestring; i: longInt): tbtwidestring;
+begin
+ result := StringOfChar(tbtwidechar(' '), i - length(s)) + s;
+end;
+//-------------------------------------------------------------------
+
+function wPadz(s: tbtwidestring; i: longInt): tbtwidestring;
+begin
+ result := StringOfChar(tbtwidechar('0'), i - length(s)) + s;
+end;
+//-------------------------------------------------------------------
+
+function wPadr(s: tbtwidestring; i: longInt): tbtwidestring;
+begin
+ result := s + StringOfChar(tbtwidechar(' '), i - Length(s));
+end;
+
+function uPadl(s: tbtunicodestring; i: longInt): tbtunicodestring;
+begin
+ result := StringOfChar(tbtwidechar(' '), i - length(s)) + s;
+end;
+//-------------------------------------------------------------------
+
+function uPadz(s: tbtunicodestring; i: longInt): tbtunicodestring;
+begin
+ result := StringOfChar(tbtwidechar('0'), i - length(s)) + s;
+end;
+//-------------------------------------------------------------------
+
+function uPadr(s: tbtunicodestring; i: longInt): tbtunicodestring;
+begin
+ result := s + StringOfChar(tbtwidechar(' '), i - Length(s));
+end;
+
+{$ENDIF}
+{$IFNDEF PS_NOWIDESTRING}
+function MakeWString(const s: tbtunicodestring): tbtString;
+var
+ i: Longint;
+ e: tbtString;
+ b: boolean;
+begin
+ Result := tbtString(s);
+ i := 1;
+ b := false;
+ while i <= length(result) do
+ begin
+ if Result[i] = '''' then
+ begin
+ if not b then
+ begin
+ b := true;
+ Insert('''', Result, i);
+ inc(i);
+ end;
+ Insert('''', Result, i);
+ inc(i, 2);
+ end else if (Result[i] < #32) or (Result[i] > #255) then
+ begin
+ e := '#'+inttostr(ord(Result[i]));
+ Delete(Result, i, 1);
+ if b then
+ begin
+ b := false;
+ Insert('''', Result, i);
+ inc(i);
+ end;
+ Insert(e, Result, i);
+ inc(i, length(e));
+ end else begin
+ if not b then
+ begin
+ b := true;
+ Insert('''', Result, i);
+ inc(i, 2);
+ end else
+ inc(i);
+ end;
+ end;
+ if b then
+ begin
+ Result := Result + '''';
+ end;
+ if Result = '' then
+ Result := '''''';
+end;
+{$ENDIF}
+function MakeString(const s: tbtString): tbtString;
+var
+ i: Longint;
+ e: tbtString;
+ b: boolean;
+begin
+ Result := s;
+ i := 1;
+ b := false;
+ while i <= length(result) do
+ begin
+ if Result[i] = '''' then
+ begin
+ if not b then
+ begin
+ b := true;
+ Insert('''', Result, i);
+ inc(i);
+ end;
+ Insert('''', Result, i);
+ inc(i, 2);
+ end else if (Result[i] < #32) then
+ begin
+ e := '#'+inttostr(ord(Result[i]));
+ Delete(Result, i, 1);
+ if b then
+ begin
+ b := false;
+ Insert('''', Result, i);
+ inc(i);
+ end;
+ Insert(e, Result, i);
+ inc(i, length(e));
+ end else begin
+ if not b then
+ begin
+ b := true;
+ Insert('''', Result, i);
+ inc(i, 2);
+ end else
+ inc(i);
+ end;
+ end;
+ if b then
+ begin
+ Result := Result + '''';
+ end;
+ if Result = '' then
+ Result := '''''';
+end;
+
+function SafeStr(const s: tbtString): tbtString;
+var
+ i : Longint;
+begin
+ Result := s;
+ for i := 1 to length(s) do
+ begin
+ if s[i] in [#0..#31] then
+ begin
+ Result := Copy(s, 1, i-1);
+ exit;
+ end;
+ end;
+
+end;
+
+function PropertyToString(Instance: TObject; PName: tbtString): tbtString;
+var
+ s: tbtString;
+ i: Longint;
+ PP: PPropInfo;
+begin
+ if PName = '' then
+ begin
+ Result := tbtString(Instance.ClassName);
+ exit;
+ end;
+ while Length(PName) > 0 do
+ begin
+ i := pos(tbtChar('.'), pname);
+ if i = 0 then
+ begin
+ s := Trim(PNAme);
+ pname := '';
+ end else begin
+ s := trim(Copy(PName, 1, i-1));
+ Delete(PName, 1, i);
+ end;
+ pp := GetPropInfo(PTypeInfo(Instance.ClassInfo), string(s));
+ if pp = nil then begin Result := tbtstring(RPS_UnknownIdentifier); exit; end;
+
+
+ case pp^.PropType^.Kind of
+ tkInteger: begin Result := IntToStr(GetOrdProp(Instance, pp)); exit; end;
+ tkChar: begin Result := '#'+IntToStr(GetOrdProp(Instance, pp)); exit; end;
+ tkEnumeration: begin Result := tbtstring(GetEnumName(pp^.PropType{$IFNDEF FPC}{$IFDEF DELPHI3UP}^{$ENDIF}{$ENDIF}, GetOrdProp(Instance, pp))); exit; end;
+ tkFloat: begin Result := FloatToStr(GetFloatProp(Instance, PP)); exit; end;
+ tkString, tkLString: begin Result := ''''+tbtString(GetStrProp(Instance, PP))+''''; exit; end;
+ tkSet: begin Result := '[Set]'; exit; end;
+ tkClass: begin Instance := TObject(GetOrdProp(Instance, pp)); end;
+ tkMethod: begin Result := '[Method]'; exit; end;
+ tkVariant: begin Result := '[Variant]'; exit; end;
+ {$IFDEF DELPHI6UP}
+ {$IFNDEF PS_NOWIDESTRING}
+ tkWString: begin Result := ''''+tbtString(GetWideStrProp(Instance, pp))+''; end; {$ENDIF}
+ {$ENDIF}
+ else begin Result := '[Unknown]'; exit; end;
+ end;
+ if Instance = nil then begin result := 'nil'; exit; end;
+ end;
+ Result := tbtstring(Instance.ClassName);
+end;
+
+function ClassVariantInfo(const pvar: TPSVariantIFC; const PropertyName: tbtString): tbtString;
+begin
+ if pvar.aType.BaseType = btClass then
+ begin
+ if TObject(pvar.Dta^) = nil then
+ Result := 'nil'
+ else
+ Result := PropertyToString(TObject(pvar.Dta^), PropertyName);
+ end else if pvar.atype.basetype = btInterface then
+ Result := 'Interface'
+ else Result := tbtstring(RPS_InvalidType);
+end;
+
+function PSVariantToString(const p: TPSVariantIFC; const ClassProperties: tbtString): tbtString;
+var
+ i, n: Longint;
+begin
+ if p.Dta = nil then
+ begin
+ Result := 'nil';
+ exit;
+ end;
+ if (p.aType.BaseType = btVariant) then
+ begin
+ try
+ if TVarData(p.Dta^).VType = varDispatch then
+ Result := 'Variant(IDispatch)'
+ else if TVarData(p.Dta^).VType = varNull then
+ REsult := 'Null'
+ else if (TVarData(p.Dta^).VType = varOleStr) then
+ {$IFDEF PS_NOWIDESTRING}
+ Result := MakeString(Variant(p.Dta^))
+ {$ELSE}
+ Result := MakeWString(variant(p.dta^))
+ {$ENDIF}
+ else if TVarData(p.Dta^).VType = varString then
+ Result := MakeString(tbtstring(variant(p.Dta^)))
+ else
+ Result := tbtstring(Variant(p.Dta^));
+ except
+ on e: Exception do
+ Result := tbtstring(Format (RPS_Exception, [e.Message]));
+ end;
+ exit;
+ end;
+ case p.aType.BaseType of
+ btProcptr: begin Result := 'Proc: '+inttostr(tbtu32(p.Dta^)); end;
+ btU8: str(tbtu8(p.dta^), Result);
+ btS8: str(tbts8(p.dta^), Result);
+ btU16: str(tbtu16(p.dta^), Result);
+ btS16: str(tbts16(p.dta^), Result);
+ btU32: str(tbtu32(p.dta^), Result);
+ btS32: str(tbts32(p.dta^), Result);
+ btSingle: str(tbtsingle(p.dta^), Result);
+ btDouble: str(tbtdouble(p.dta^), Result);
+ btExtended: str(tbtextended(p.dta^), Result);
+ btString: Result := makestring(tbtString(p.dta^));
+ btPChar:
+ begin
+ if PansiChar(p.dta^) = nil then
+ Result := 'nil'
+ else
+ Result := MakeString(PAnsiChar(p.dta^));
+ end;
+ btchar: Result := MakeString(tbtchar(p.dta^));
+ {$IFNDEF PS_NOWIDESTRING}
+ btwidechar: Result := MakeWString(tbtwidechar(p.dta^));
+ btWideString: Result := MakeWString(tbtwidestring(p.dta^));
+ btUnicodeString: Result := MakeWString(tbtUnicodeString(p.dta^));
+ {$ENDIF}
+ {$IFNDEF PS_NOINT64}btS64: str(tbts64(p.dta^), Result);{$ENDIF}
+ btStaticArray, btArray:
+ begin
+ Result := '';
+ if p.aType.BaseType = btStaticArray then
+ n := TPSTypeRec_StaticArray(p.aType).Size
+ else
+ n := PSDynArrayGetLength(Pointer(p.dta^), p.aType);
+ for i := 0 to n-1 do begin
+ if Result <> '' then
+ Result := Result + ', ';
+ Result := Result + PSVariantToString(PSGetArrayField(p, i), '');
+ end;
+ Result := '[' + Result + ']';
+ end;
+ btRecord:
+ begin
+ Result := '';
+ n := TPSTypeRec_Record(p.aType).FFieldTypes.Count;
+ for i := 0 to n-1 do begin
+ if Result <> '' then
+ Result := Result + ', ';
+ Result := Result + PSVariantToString(PSGetRecField(p, i), '');
+ end;
+ Result := '(' + Result + ')';
+ end;
+ btPointer: Result := 'Nil';
+ btClass, btInterface:
+ begin
+ Result := ClassVariantInfo(p, ClassProperties)
+ end;
+ else
+ Result := tbtString(RPS_Invalid);
+ end;
+end;
+
+
+
+function TIFErrorToString(x: TPSError; const Param: tbtString): tbtString;
+begin
+ Result := PSErrorToString(x,param);
+end;
+
+function PSErrorToString(x: TPSError; const Param: tbtString): tbtString;
+begin
+ case x of
+ ErNoError: Result := tbtString(RPS_NoError);
+ erCannotImport: Result := tbtString(Format (RPS_CannotImport, [Safestr(Param)]));
+ erInvalidType: Result := tbtString(RPS_InvalidType);
+ ErInternalError: Result := tbtString(RPS_InternalError);
+ erInvalidHeader: Result := tbtString(RPS_InvalidHeader);
+ erInvalidOpcode: Result := tbtString(RPS_InvalidOpcode);
+ erInvalidOpcodeParameter: Result := tbtString(RPS_InvalidOpcodeParameter);
+ erNoMainProc: Result := tbtString(RPS_NoMainProc);
+ erOutOfGlobalVarsRange: Result := tbtString(RPS_OutOfGlobalVarsRange);
+ erOutOfProcRange: Result := tbtString(RPS_OutOfProcRange);
+ ErOutOfRange: Result := tbtString(RPS_OutOfRange);
+ erOutOfStackRange: Result := tbtString(RPS_OutOfStackRange);
+ ErTypeMismatch: Result := tbtString(RPS_TypeMismatch);
+ erUnexpectedEof: Result := tbtString(RPS_UnexpectedEof);
+ erVersionError: Result := tbtString(RPS_VersionError);
+ ErDivideByZero: Result := tbtString(RPS_DivideByZero);
+ erMathError: Result := tbtString(RPS_MathError);
+ erCouldNotCallProc: begin Result := tbtString(RPS_CouldNotCallProc); if (Param <> '') then Result := result +' ('+Param+')'; end;
+ erOutofRecordRange: Result := tbtString(RPS_OutofRecordRange);
+ erNullPointerException: Result := tbtString(RPS_NullPointerException);
+ erNullVariantError: Result := tbtString(RPS_NullVariantError);
+ erOutOfMemory: Result := tbtString(RPS_OutOfMemory);
+ erException: Result := tbtString(Format (RPS_Exception, [Param]));
+ erInterfaceNotSupported: Result := tbtString(RPS_InterfaceNotSupported);
+ erCustomError: Result := Param;
+ else
+ Result := tbtString(RPS_UnknownError);
+ end;
+ //
+end;
+
+
+procedure TPSTypeRec.CalcSize;
+begin
+ case BaseType of
+ btVariant: FRealSize := sizeof(Variant);
+ btChar, bts8, btU8: FrealSize := 1 ;
+ {$IFNDEF PS_NOWIDESTRING}btWideChar, {$ENDIF}bts16, btU16: FrealSize := 2;
+ {$IFNDEF PS_NOWIDESTRING}btWideString,
+ btUnicodeString,
+ {$ENDIF}{$IFNDEF PS_NOINTERFACES}btInterface, {$ENDIF}
+ btclass, btPChar, btString: FrealSize := PointerSize;
+ btSingle, bts32, btU32: FRealSize := 4;
+ btProcPtr: FRealSize := 2 * sizeof(Pointer) + sizeof(Cardinal);
+ btCurrency: FrealSize := Sizeof(Currency);
+ btPointer: FRealSize := 2 * sizeof(Pointer) + sizeof(LongBool); // ptr, type, freewhendone
+ btDouble{$IFNDEF PS_NOINT64}, bts64{$ENDIF}: FrealSize := 8;
+ btExtended: FrealSize := SizeOf(Extended);
+ btReturnAddress: FrealSize := Sizeof(TBTReturnAddress);
+ else
+ FrealSize := 0;
+ end;
+end;
+
+constructor TPSTypeRec.Create(Owner: TPSExec);
+begin
+ inherited Create;
+ FAttributes := TPSRuntimeAttributes.Create(Owner);
+end;
+
+destructor TPSTypeRec.Destroy;
+begin
+ FAttributes.Free;
+ inherited destroy;
+end;
+
+{ TPSTypeRec_Record }
+
+procedure TPSTypeRec_Record.CalcSize;
+begin
+ inherited;
+ FrealSize := TPSTypeRec(FFieldTypes[FFieldTypes.Count-1]).RealSize +
+ IPointer(RealFieldOffsets[RealFieldOffsets.Count -1]);
+end;
+
+constructor TPSTypeRec_Record.Create(Owner: TPSExec);
+begin
+ inherited Create(Owner);
+ FRealFieldOffsets := TPSList.Create;
+ FFieldTypes := TPSList.Create;
+end;
+
+destructor TPSTypeRec_Record.Destroy;
+begin
+ FFieldTypes.Free;
+ FRealFieldOffsets.Free;
+ inherited Destroy;
+end;
+
+
+const
+ RTTISize = sizeof(TPSVariant);
+
+procedure InitializeVariant(p: Pointer; aType: TPSTypeRec);
+var
+ t: TPSTypeRec;
+ i: Longint;
+begin
+ case aType.BaseType of
+ btChar, bts8, btU8: tbtu8(p^) := 0;
+ {$IFNDEF PS_NOWIDESTRING}btWideChar, {$ENDIF}bts16, btU16: tbtu16(p^) := 0;
+ btSingle, bts32, btU32,
+ btPChar, btString, {$IFNDEF PS_NOWIDESTRING}btUnicodeString, btWideString, {$ENDIF}btClass,
+ btInterface, btArray: Pointer(P^) := nil;
+ btPointer:
+ begin
+ Pointer(p^) := nil;
+ Pointer(Pointer(IPointer(p)+PointerSize)^) := nil;
+ Pointer(Pointer(IPointer(p)+(2*PointerSize))^) := nil;
+ end;
+ btProcPtr:
+ begin
+ Longint(p^) := 0;
+ Pointer(Pointer(IPointer(p)+PointerSize)^) := nil;
+ Pointer(Pointer(IPointer(p)+(2*PointerSize))^) := nil;
+ end;
+ btCurrency: tbtCurrency(P^) := 0;
+ btDouble{$IFNDEF PS_NOINT64}, bts64{$ENDIF}: {$IFNDEF PS_NOINT64}tbtS64(P^) := 0{$ELSE}tbtdouble(p^) := 0 {$ENDIF};
+ btExtended: tbtExtended(p^) := 0;
+ btVariant: Initialize(Variant(p^));
+ btReturnAddress:; // there is no point in initializing a return address
+ btRecord:
+ begin
+ for i := 0 to TPSTypeRec_Record(aType).FFieldTypes.Count -1 do
+ begin
+ t := TPSTypeRec_Record(aType).FieldTypes[i];
+ InitializeVariant(P, t);
+ p := Pointer(IPointer(p) + t.FrealSize);
+ end;
+ end;
+ btStaticArray:
+ begin
+ t := TPSTypeRec_Array(aType).ArrayType;
+ for i := 0 to TPSTypeRec_StaticArray(aType).Size -1 do
+ begin
+ InitializeVariant(p, t);
+ p := Pointer(IPointer(p) + t.RealSize);
+ end;
+ end;
+ btSet:
+ begin
+ FillChar(p^, TPSTypeRec_Set(aType).RealSize, 0);
+ end;
+ end;
+end;
+
+procedure DestroyHeapVariant2(v: Pointer; aType: TPSTypeRec); forward;
+
+const
+ NeedFinalization = [btStaticArray, btRecord, btArray, btPointer, btVariant {$IFNDEF PS_NOINTERFACES}, btInterface{$ENDIF}, btString {$IFNDEF PS_NOWIDESTRING}, btUnicodestring,btWideString{$ENDIF}];
+
+procedure FinalizeVariant(p: Pointer; aType: TPSTypeRec);
+var
+ t: TPSTypeRec;
+ elsize: Cardinal;
+ i, l: Longint;
+ darr: Pointer;
+begin
+ case aType.BaseType of
+ btString: tbtString(p^) := '';
+ {$IFNDEF PS_NOWIDESTRING}
+ btWideString: tbtwidestring(p^) := '';
+ btUnicodeString: tbtunicodestring(p^) := '';
+ {$ENDIF}
+ {$IFNDEF PS_NOINTERFACES}btInterface:
+ begin
+ {$IFNDEF DELPHI3UP}
+ if IUnknown(p^) <> nil then
+ IUnknown(p^).Release;
+ {$ENDIF}
+ IUnknown(p^) := nil;
+ end; {$ENDIF}
+ btVariant:
+ begin
+ try
+ Finalize(Variant(p^));
+ except
+ end;
+ end;
+ btPointer:
+ if Pointer(Pointer(IPointer(p)+PointerSize2)^) <> nil then
+ begin
+ DestroyHeapVariant2(Pointer(p^), Pointer(Pointer(IPointer(p)+PointerSize)^));
+ Pointer(p^) := nil;
+ end;
+ btArray:
+ begin
+ if IPointer(P^) = 0 then exit;
+ darr := Pointer(IPointer(p^) - PointerSize2);
+ if Longint(darr^) < 0 then exit;// refcount < 0 means don't free
+ Dec(Longint(darr^));
+ if Longint(darr^) <> 0 then exit;
+ t := TPSTypeRec_Array(aType).ArrayType;
+ elsize := t.RealSize;
+ darr := Pointer(IPointer(darr) + PointerSize);
+ l := Longint(darr^) {$IFDEF FPC}+1{$ENDIF};
+ darr := Pointer(IPointer(darr) + PointerSize);
+ case t.BaseType of
+ btString, {$IFNDEF PS_NOWIDESTRING}
+ btUnicodeString, btWideString, {$ENDIF}{$IFNDEF PS_NOINTERFACES}btInterface, {$ENDIF}btArray, btStaticArray,
+ btRecord, btPointer, btVariant:
+ begin
+ for i := 0 to l -1 do
+ begin
+ FinalizeVariant(darr, t);
+ darr := Pointer(IPointer(darr) + elsize);
+ end;
+ end;
+ end;
+ FreeMem(Pointer(IPointer(p^) - IPointer(PointerSize2)), IPointer(Cardinal(l) * elsize) + IPointer(PointerSize2));
+ Pointer(P^) := nil;
+ end;
+ btRecord:
+ begin
+ for i := 0 to TPSTypeRec_Record(aType).FFieldTypes.Count -1 do
+ begin
+ t := TPSTypeRec_Record(aType).FieldTypes[i];
+ case t.BaseType of
+ btString, {$IFNDEF PS_NOWIDESTRING}btUnicodeString, btWideString, {$ENDIF}{$IFNDEF PS_NOINTERFACES}btInterface, {$ENDIF}btArray, btStaticArray,
+ btRecord: FinalizeVariant(p, t);
+ end;
+ p := Pointer(IPointer(p) + t.FrealSize);
+ end;
+ end;
+ btStaticArray:
+ begin
+ t := TPSTypeRec_Array(aType).ArrayType;
+ case t.BaseType of
+ btString, {$IFNDEF PS_NOWIDESTRING}btUnicodeString, btWideString, {$ENDIF}{$IFNDEF PS_NOINTERFACES}btInterface, {$ENDIF}btArray, btStaticArray,
+ btRecord: ;
+ else Exit;
+ end;
+ for i := 0 to TPSTypeRec_StaticArray(aType).Size -1 do
+ begin
+ FinalizeVariant(p, t);
+ p := Pointer(IPointer(p) + t.RealSize);
+ end;
+ end;
+ end;
+end;
+
+function CreateHeapVariant2(aType: TPSTypeRec): Pointer;
+begin
+ GetMem(Result, aType.RealSize);
+ InitializeVariant(Result, aType);
+end;
+
+procedure DestroyHeapVariant2(v: Pointer; aType: TPSTypeRec);
+begin
+ if v = nil then exit;
+ if atype.BaseType in NeedFinalization then
+ FinalizeVariant(v, aType);
+ FreeMem(v, aType.RealSize);
+end;
+
+
+function CreateHeapVariant(aType: TPSTypeRec): PPSVariant;
+var
+ aSize: Longint;
+begin
+ aSize := aType.RealSize + RTTISize;
+ GetMem(Result, aSize);
+ Result.FType := aType;
+ InitializeVariant(Pointer(IPointer(Result)+PointerSize), aType);
+end;
+
+procedure DestroyHeapVariant(v: PPSVariant);
+begin
+ if v = nil then exit;
+ if v.FType.BaseType in NeedFinalization then
+ FinalizeVariant(Pointer(IPointer(v)+PointerSize), v.FType);
+ FreeMem(v, v.FType.RealSize + RTTISize);
+end;
+
+procedure FreePSVariantList(l: TPSList);
+var
+ i: Longint;
+begin
+ for i:= l.count -1 downto 0 do
+ DestroyHeapVariant(l[i]);
+ l.free;
+end;
+
+procedure FreePIFVariantList(l: TPSList);
+begin
+ FreePsVariantList(l);
+end;
+
+{ TPSExec }
+
+procedure TPSExec.ClearFunctionList;
+var
+ x: PProcRec;
+ l: Longint;
+begin
+ for l := FAttributeTypes.Count -1 downto 0 do
+ begin
+ TPSAttributeType(FAttributeTypes.Data^[l]).Free;
+ end;
+ FAttributeTypes.Clear;
+
+ for l := 0 to FRegProcs.Count - 1 do
+ begin
+ x := FRegProcs.Data^[l];
+ if @x^.FreeProc <> nil then x^.FreeProc(Self, x);
+ Dispose(x);
+ end;
+ FRegProcs.Clear;
+ RegisterStandardProcs;
+end;
+
+class function TPSExec.About: tbtString;
+begin
+ Result := 'RemObjects Pascal Script. Copyright (c) 2004-2009 by RemObjects Software';
+end;
+
+procedure TPSExec.Cleanup;
+var
+ I: Longint;
+ p: Pointer;
+begin
+ if FStatus <> isLoaded then
+ exit;
+ FStack.Clear;
+ FTempVars.Clear;
+ for I := Longint(FGlobalVars.Count) - 1 downto 0 do
+ begin
+ p := FGlobalVars.Items[i];
+ if PIFTypeRec(P^).BaseType in NeedFinalization then
+ FinalizeVariant(Pointer(IPointer(p)+PointerSize), Pointer(P^));
+ InitializeVariant(Pointer(IPointer(p)+PointerSize), Pointer(P^));
+ end;
+end;
+
+procedure TPSExec.Clear;
+var
+ I: Longint;
+ temp: PPSResource;
+ Proc: TPSResourceFreeProc;
+ pp: TPSExceptionHandler;
+begin
+ for i := Longint(FExceptionStack.Count) -1 downto 0 do
+ begin
+ pp := FExceptionStack.Data^[i];
+ pp.Free;
+ end;
+ for i := Longint(FResources.Count) -1 downto 0 do
+ begin
+ Temp := FResources.Data^[i];
+ Proc := Temp^.Proc;
+ Proc(Self, Temp^.P);
+ Dispose(Temp);
+ end;
+ for i := Longint(FExportedVars.Count) -1 downto 0 do
+ Dispose(PPSExportedVar(FExportedVars.Data^[I]));
+ for I := Longint(FProcs.Count) - 1downto 0 do
+ TPSProcRec(FProcs.Data^[i]).Destroy;
+ FProcs.Clear;
+ FGlobalVars.Clear;
+ FStack.Clear;
+ for I := Longint(FTypes.Count) - 1downto 0 do
+ TPSTypeRec(FTypes.Data^[i]).Free;
+ FTypes.Clear;
+ FStatus := isNotLoaded;
+ FResources.Clear;
+ FExportedVars.Clear;
+ FExceptionStack.Clear;
+ FCurrStackBase := InvalidVal;
+end;
+
+constructor TPSExec.Create;
+begin
+ inherited Create;
+ FAttributeTypes := TPSList.Create;
+ FExceptionStack := TPSList.Create;
+ FCallCleanup := False;
+ FResources := TPSList.Create;
+ FTypes := TPSList.Create;
+ FProcs := TPSList.Create;
+ FGlobalVars := TPSStack.Create;
+ FTempVars := TPSStack.Create;
+ FMainProc := 0;
+ FStatus := isNotLoaded;
+ FRegProcs := TPSList.Create;
+ FExportedVars := TPSList.create;
+ FSpecialProcList := TPSList.Create;
+ RegisterStandardProcs;
+ FReturnAddressType := TPSTypeRec.Create(self);
+ FReturnAddressType.BaseType := btReturnAddress;
+ FReturnAddressType.CalcSize;
+ FVariantType := TPSTypeRec.Create(self);
+ FVariantType.BaseType := btVariant;
+ FVariantType.CalcSize;
+ FVariantArrayType := TPSTypeRec_Array.Create(self);
+ FVariantArrayType.BaseType := btArray;
+ FVariantArrayType.CalcSize;
+ TPSTypeRec_Array(FVariantArrayType).ArrayType := FVariantType;
+ FStack := TPSStack.Create;
+end;
+
+destructor TPSExec.Destroy;
+var
+ I: Longint;
+ x: PProcRec;
+ P: PSpecialProc;
+begin
+ Clear;
+ FReturnAddressType.Free;
+ FVariantType.Free;
+ FVariantArrayType.Free;
+
+ if ExObject <> nil then ExObject.Free;
+ for I := FSpecialProcList.Count -1 downto 0 do
+ begin
+ P := FSpecialProcList.Data^[I];
+ Dispose(p);
+ end;
+ FResources.Free;
+ FExportedVars.Free;
+ FTempVars.Free;
+ FStack.Free;
+ FGlobalVars.Free;
+ FProcs.Free;
+ FTypes.Free;
+ FSpecialProcList.Free;
+ for i := FRegProcs.Count - 1 downto 0 do
+ begin
+ x := FRegProcs.Data^[i];
+ if @x^.FreeProc <> nil then x^.FreeProc(Self, x);
+ Dispose(x);
+ end;
+ FRegProcs.Free;
+ FExceptionStack.Free;
+ for i := FAttributeTypes.Count -1 downto 0 do
+ begin
+ TPSAttributeType(FAttributeTypes[i]).Free;
+ end;
+ FAttributeTypes.Free;
+ inherited Destroy;
+end;
+
+procedure TPSExec.ExceptionProc(proc, Position: Cardinal; Ex: TPSError; const s: tbtString; NewObject: TObject);
+var
+ d, l: Longint;
+ pp: TPSExceptionHandler;
+begin
+ ExProc := proc;
+ ExPos := Position;
+ ExEx := Ex;
+ ExParam := s;
+ if ExObject <> nil then
+ ExObject.Free;
+ ExObject := NewObject;
+ if Ex = eNoError then Exit;
+ for d := FExceptionStack.Count -1 downto 0 do
+ begin
+ pp := FExceptionStack[d];
+ if Cardinal(FStack.Count) > pp.StackSize then
+ begin
+ for l := Longint(FStack.count) -1 downto Longint(pp.StackSize) do
+ FStack.Pop;
+ end;
+ if pp.CurrProc = nil then // no point in continuing
+ begin
+ pp.Free;
+ FExceptionStack.DeleteLast;
+
+ FCurrStackBase := InvalidVal;
+ FStatus := isPaused;
+ exit;
+ end;
+ FCurrProc := pp.CurrProc;
+ FData := FCurrProc.Data;
+ FDataLength := FCurrProc.Length;
+
+ FCurrStackBase := pp.BasePtr;
+ if pp.FinallyOffset <> InvalidVal then
+ begin
+ FCurrentPosition := pp.FinallyOffset;
+ pp.FinallyOffset := InvalidVal;
+ Exit;
+ end else if (pp.ExceptOffset <> InvalidVal) and (pp.ExceptOffset <> Cardinal(InvalidVal -1)) then
+ begin
+ FCurrentPosition := pp.ExceptOffset;
+ pp.ExceptOffset := Cardinal(InvalidVal -1);
+ pp.ExceptionObject := ExObject;
+ pp.ExceptionData := ExEx;
+ pp.ExceptionParam := ExParam;
+ ExObject := nil;
+ ExEx := ENoError;
+ Exit;
+ end else if pp.Finally2Offset <> InvalidVal then
+ begin
+ FCurrentPosition := pp.Finally2Offset;
+ pp.Finally2Offset := InvalidVal;
+ Exit;
+ end;
+ pp.Free;
+ FExceptionStack.DeleteLast;
+ end;
+ if FStatus <> isNotLoaded then
+ FStatus := isPaused;
+end;
+
+function LookupProc(List: TPSList; const Name: ShortString): PProcRec;
+var
+ h, l: Longint;
+ p: PProcRec;
+begin
+ h := MakeHash(Name);
+ for l := List.Count - 1 downto 0 do
+ begin
+ p := List.Data^[l];
+ if (p^.Hash = h) and (p^.Name = Name) then
+ begin
+ Result := List[l];
+ exit;
+ end;
+ end;
+ Result := nil;
+end;
+
+function TPSExec.ImportProc(const Name: ShortString; proc: TPSExternalProcRec): Boolean;
+var
+ u: PProcRec;
+ fname: tbtString;
+ I, fnh: Longint;
+ P: PSpecialProc;
+
+begin
+ if name = '' then
+ begin
+ fname := proc.Decl;
+ fname := copy(fname, 1, pos(tbtchar(':'), fname)-1);
+ fnh := MakeHash(fname);
+ for I := FSpecialProcList.Count -1 downto 0 do
+ begin
+ p := FSpecialProcList[I];
+ IF (p^.name = '') or ((p^.namehash = fnh) and (p^.name = fname)) then
+ begin
+ if p^.P(Self, Proc, p^.tag) then
+ begin
+ Result := True;
+ exit;
+ end;
+ end;
+ end;
+ Result := FAlse;
+ exit;
+ end;
+ u := LookupProc(FRegProcs, Name);
+ if u = nil then begin
+ Result := False;
+ exit;
+ end;
+ proc.ProcPtr := u^.ProcPtr;
+ proc.Ext1 := u^.Ext1;
+ proc.Ext2 := u^.Ext2;
+ Result := True;
+end;
+
+function TPSExec.RegisterFunctionName(const Name: tbtString; ProcPtr: TPSProcPtr; Ext1, Ext2: Pointer): PProcRec;
+var
+ p: PProcRec;
+ s: tbtString;
+begin
+ s := FastUppercase(Name);
+ New(p);
+ p^.Name := s;
+ p^.Hash := MakeHash(s);
+ p^.ProcPtr := ProcPtr;
+ p^.FreeProc := nil;
+ p.Ext1 := Ext1;
+ p^.Ext2 := Ext2;
+ FRegProcs.Add(p);
+ Result := P;
+end;
+
+function TPSExec.LoadData(const s: tbtString): Boolean;
+var
+ HDR: TPSHeader;
+ Pos: Cardinal;
+
+ function read(var Data; Len: Cardinal): Boolean;
+ begin
+ if Longint(Pos + Len) <= Length(s) then begin
+ Move(s[Pos + 1], Data, Len);
+ Pos := Pos + Len;
+ read := True;
+ end
+ else
+ read := False;
+ end;
+ function ReadAttributes(Dest: TPSRuntimeAttributes): Boolean;
+ var
+ Count: Cardinal;
+ i: Integer;
+
+ function ReadAttrib: Boolean;
+ var
+ NameLen: Longint;
+ Name: tbtString;
+ TypeNo: Cardinal;
+ i, h, FieldCount: Longint;
+ att: TPSRuntimeAttribute;
+ varp: PIFVariant;
+
+ begin
+ if (not Read(NameLen, 4)) or (NameLen > Length(s) - Longint(Pos)) then
+ begin
+ CMD_Err(ErOutOfRange);
+ Result := false;
+ exit;
+ end;
+ SetLength(Name, NameLen);
+ if not Read(Name[1], NameLen) then
+ begin
+ CMD_Err(ErOutOfRange);
+ Result := false;
+ exit;
+ end;
+ if not Read(FieldCount, 4) then
+ begin
+ CMD_Err(ErOutOfRange);
+ Result := false;
+ exit;
+ end;
+ att := Dest.Add;
+ att.AttribType := Name;
+ att.AttribTypeHash := MakeHash(att.AttribType);
+ for i := 0 to FieldCount -1 do
+ begin
+ if (not Read(TypeNo, 4)) or (TypeNo >= Cardinal(FTypes.Count)) then
+ begin
+ CMD_Err(ErOutOfRange);
+ Result := false;
+ exit;
+ end;
+
+ varp := att.AddValue(FTypes[TypeNo]);
+ case VarP^.FType.BaseType of
+ btSet:
+ begin
+ if not read(PPSVariantSet(varp).Data, TPSTypeRec_Set(varp.FType).aByteSize) then
+ begin
+ CMD_Err(erOutOfRange);
+
+ DestroyHeapVariant(VarP);
+ Result := False;
+ exit;
+ end;
+ end;
+ bts8, btchar, btU8: if not read(PPSVariantU8(VarP)^.data, 1) then
+ begin
+ CMD_Err(erOutOfRange);
+ DestroyHeapVariant(VarP);
+ Result := False;
+ exit;
+ end;
+ bts16, {$IFNDEF PS_NOWIDESTRING}btwidechar,{$ENDIF} btU16: if not read(PPSVariantU16(Varp)^.Data, SizeOf(TbtU16)) then begin
+ CMD_Err(ErOutOfRange);
+ DestroyHeapVariant(VarP);
+ Result := False;
+ exit;
+ end;
+ bts32, btU32:
+ begin
+ if FCurrentPosition + 3 >= FDataLength then
+ begin
+ Cmd_Err(erOutOfRange);
+ DestroyHeapVariant(VarP);
+ Result := False;
+ exit;;
+ end;
+ {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
+ PPSVariantU32(varp)^.Data := unaligned(Cardinal((@FData^[FCurrentPosition])^));
+ {$else}
+ PPSVariantU32(varp)^.Data := Cardinal((@FData^[FCurrentPosition])^);
+ {$endif}
+ Inc(FCurrentPosition, 4);
+ end;
+ btProcPtr:
+ begin
+ if FCurrentPosition + 3 >= FDataLength then
+ begin
+ Cmd_Err(erOutOfRange);
+ DestroyHeapVariant(VarP);
+ Result := False;
+ exit;;
+ end;
+ {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
+ PPSVariantU32(varp)^.Data := unaligned(Cardinal((@FData^[FCurrentPosition])^));
+ {$else}
+ PPSVariantU32(varp)^.Data := Cardinal((@FData^[FCurrentPosition])^);
+ {$endif}
+ if PPSVariantU32(varp)^.Data = 0 then
+ begin
+ PPSVariantProcPtr(varp)^.Ptr := nil;
+ PPSVariantProcPtr(varp)^.Self := nil;
+ end;
+ Inc(FCurrentPosition, 4);
+ end;
+ {$IFNDEF PS_NOINT64}
+ bts64: if not read(PPSVariantS64(VarP)^.Data, sizeof(tbts64)) then
+ begin
+ CMD_Err(erOutOfRange);
+ DestroyHeapVariant(VarP);
+ Result := False;
+ exit;
+ end;
+ {$ENDIF}
+ btSingle: if not read(PPSVariantSingle(VarP)^.Data, SizeOf(TbtSingle))
+ then begin
+ CMD_Err(erOutOfRange);
+ DestroyHeapVariant(VarP);
+ Result := False;
+ exit;
+ end;
+ btDouble: if not read(PPSVariantDouble(varp)^.Data, SizeOf(TbtDouble))
+ then begin
+ CMD_Err(erOutOfRange);
+ DestroyHeapVariant(VarP);
+ Result := False;
+ exit;
+ end;
+ btExtended: if not read(PPSVariantExtended(varp)^.Data, SizeOf(TbtExtended))
+ then begin
+ CMD_Err(erOutOfRange);
+ DestroyHeapVariant(VarP);
+ Result := False;
+ exit;
+ end;
+ btCurrency: if not read(PPSVariantExtended(varp)^.Data, SizeOf(tbtCurrency))
+ then begin
+ CMD_Err(erOutOfRange);
+ DestroyHeapVariant(VarP);
+ Result := False;
+ exit;
+ end;
+ btPchar, btString:
+ begin
+ if not read(NameLen, 4) then
+ begin
+ Cmd_Err(erOutOfRange);
+ DestroyHeapVariant(VarP);
+ Result := False;
+ exit;
+ end;
+ Inc(FCurrentPosition, 4);
+ SetLength(PPSVariantAString(varp)^.Data, NameLen);
+ if not read(PPSVariantAString(varp)^.Data[1], NameLen) then begin
+ CMD_Err(erOutOfRange);
+ DestroyHeapVariant(VarP);
+ Result := False;
+ exit;
+ end;
+ end;
+ {$IFNDEF PS_NOWIDESTRING}
+ btWidestring:
+ begin
+ if not read(NameLen, 4) then
+ begin
+ Cmd_Err(erOutOfRange);
+ DestroyHeapVariant(VarP);
+ Result := False;
+ exit;
+ end;
+ Inc(FCurrentPosition, 4);
+ SetLength(PPSVariantWString(varp).Data, NameLen);
+ if not read(PPSVariantWString(varp).Data[1], NameLen*2) then begin
+ CMD_Err(erOutOfRange);
+ DestroyHeapVariant(VarP);
+ Result := False;
+ exit;
+ end;
+ end;
+ btUnicodeString:
+ begin
+ if not read(NameLen, 4) then
+ begin
+ Cmd_Err(erOutOfRange);
+ DestroyHeapVariant(VarP);
+ Result := False;
+ exit;
+ end;
+ Inc(FCurrentPosition, 4);
+ SetLength(PPSVariantUString(varp).Data, NameLen);
+ if not read(PPSVariantUString(varp).Data[1], NameLen*2) then begin
+ CMD_Err(erOutOfRange);
+ DestroyHeapVariant(VarP);
+ Result := False;
+ exit;
+ end;
+ end;
+ {$ENDIF}
+ else begin
+ CMD_Err(erInvalidType);
+ DestroyHeapVariant(VarP);
+ Result := False;
+ exit;
+ end;
+ end;
+ end;
+ h := MakeHash(att.AttribType);
+ for i := FAttributeTypes.Count -1 downto 0 do
+ begin
+ if (TPSAttributeType(FAttributeTypes.Data^[i]).TypeNameHash = h) and
+ (TPSAttributeType(FAttributeTypes.Data^[i]).TypeName = att.AttribType) then
+ begin
+ if not TPSAttributeType(FAttributeTypes.Data^[i]).UseProc(Self, att.AttribType, Att) then
+ begin
+ Result := False;
+ exit;
+ end;
+ end;
+ end;
+ Result := True;
+ end;
+
+
+ begin
+ if not Read(Count, 4) then
+ begin
+ CMD_Err(erOutofRange);
+ Result := false;
+ exit;
+ end;
+ for i := 0 to Count -1 do
+ begin
+ if not ReadAttrib then
+ begin
+ Result := false;
+ exit;
+ end;
+ end;
+ Result := True;
+ end;
+
+{$WARNINGS OFF}
+
+ function LoadTypes: Boolean;
+ var
+ currf: TPSType;
+ Curr: PIFTypeRec;
+ fe: Boolean;
+ l2, l: Longint;
+ d: Cardinal;
+
+ function resolve(Dta: TPSTypeRec_Record): Boolean;
+ var
+ offs, l: Longint;
+ begin
+ offs := 0;
+ for l := 0 to Dta.FieldTypes.Count -1 do
+ begin
+ Dta.RealFieldOffsets.Add(Pointer(offs));
+ offs := offs + TPSTypeRec(Dta.FieldTypes[l]).RealSize;
+ end;
+ Result := True;
+ end;
+ begin
+ LoadTypes := True;
+ for l := 0 to HDR.TypeCount - 1 do begin
+ if not read(currf, SizeOf(currf)) then begin
+ cmd_err(erUnexpectedEof);
+ LoadTypes := False;
+ exit;
+ end;
+ if (currf.BaseType and 128) <> 0 then begin
+ fe := True;
+ currf.BaseType := currf.BaseType - 128;
+ end else
+ fe := False;
+ case currf.BaseType of
+ {$IFNDEF PS_NOINT64}bts64, {$ENDIF}
+ btU8, btS8, btU16, btS16, btU32, btS32, btSingle, btDouble, btCurrency,
+ btExtended, btString, btPointer, btPChar,
+ btVariant, btChar{$IFNDEF PS_NOWIDESTRING}, btUnicodeString, btWideString, btWideChar{$ENDIF}: begin
+ curr := TPSTypeRec.Create(self);
+ Curr.BaseType := currf.BaseType;
+ FTypes.Add(Curr);
+ end;
+ btClass:
+ begin
+ Curr := TPSTypeRec_Class.Create(self);
+ if (not Read(d, 4)) or (d > 255) then
+ begin
+ curr.Free;
+ cmd_err(erUnexpectedEof);
+ LoadTypes := False;
+ exit;
+ end;
+ setlength(TPSTypeRec_Class(Curr).FCN, d);
+ if not Read(TPSTypeRec_Class(Curr).FCN[1], d) then
+ begin
+ curr.Free;
+ cmd_err(erUnexpectedEof);
+ LoadTypes := False;
+ exit;
+ end;
+ Curr.BaseType := currf.BaseType;
+ FTypes.Add(Curr);
+ end;
+ btProcPtr:
+ begin
+ Curr := TPSTypeRec_ProcPtr.Create(self);
+ if (not Read(d, 4)) or (d > 255) then
+ begin
+ curr.Free;
+ cmd_err(erUnexpectedEof);
+ LoadTypes := False;
+ exit;
+ end;
+ setlength(TPSTypeRec_ProcPtr(Curr).FParamInfo, d);
+ if not Read(TPSTypeRec_ProcPtr(Curr).FParamInfo[1], d) then
+ begin
+ curr.Free;
+ cmd_err(erUnexpectedEof);
+ LoadTypes := False;
+ exit;
+ end;
+ Curr.BaseType := currf.BaseType;
+ FTypes.Add(Curr);
+ end;
+{$IFNDEF PS_NOINTERFACES}
+ btInterface:
+ begin
+ Curr := TPSTypeRec_Interface.Create(self);
+ if not Read(TPSTypeRec_Interface(Curr).FGUID, Sizeof(TGuid)) then
+ begin
+ curr.Free;
+ cmd_err(erUnexpectedEof);
+ LoadTypes := False;
+ exit;
+ end;
+ Curr.BaseType := currf.BaseType;
+ FTypes.Add(Curr);
+ end;
+{$ENDIF}
+ btSet:
+ begin
+ Curr := TPSTypeRec_Set.Create(self);
+ if not Read(d, 4) then
+ begin
+ curr.Free;
+ cmd_err(erUnexpectedEof);
+ LoadTypes := False;
+ exit;
+ end;
+ if (d > 256) then
+ begin
+ curr.Free;
+ cmd_err(erTypeMismatch);
+ LoadTypes := False;
+ exit;
+ end;
+
+ TPSTypeRec_Set(curr).aBitSize := d;
+ TPSTypeRec_Set(curr).aByteSize := TPSTypeRec_Set(curr).aBitSize shr 3;
+ if (TPSTypeRec_Set(curr).aBitSize and 7) <> 0 then inc(TPSTypeRec_Set(curr).fbytesize);
+ Curr.BaseType := currf.BaseType;
+ FTypes.Add(Curr);
+ end;
+ btStaticArray:
+ begin
+ curr := TPSTypeRec_StaticArray.Create(self);
+ if not Read(d, 4) then
+ begin
+ curr.Free;
+ cmd_err(erUnexpectedEof);
+ LoadTypes := False;
+ exit;
+ end;
+ if (d >= FTypes.Count) then
+ begin
+ curr.Free;
+ cmd_err(erTypeMismatch);
+ LoadTypes := False;
+ exit;
+ end;
+ TPSTypeRec_StaticArray(curr).ArrayType := FTypes[d];
+ if not Read(d, 4) then
+ begin
+ curr.Free;
+ cmd_err(erUnexpectedEof);
+ LoadTypes := False;
+ exit;
+ end;
+ if d > (MaxInt div 4) then
+ begin
+ curr.Free;
+ cmd_err(erUnexpectedEof);
+ LoadTypes := False;
+ exit;
+ end;
+ TPSTypeRec_StaticArray(curr).Size := d;
+ if not Read(d,4) then //<-additional StartOffset
+ begin
+ curr.Free;
+ cmd_err(erUnexpectedEof);
+ LoadTypes:=false;
+ Exit;
+ end;
+ TPSTypeRec_StaticArray(curr).StartOffset:=d;
+
+ Curr.BaseType := currf.BaseType;
+ FTypes.Add(Curr);
+ end;
+ btArray: begin
+ Curr := TPSTypeRec_Array.Create(self);
+ if not read(d, 4) then
+ begin // Read type
+ curr.Free;
+ cmd_err(erUnexpectedEof);
+ LoadTypes := False;
+ exit;
+ end;
+ if (d >= FTypes.Count) then
+ begin
+ curr.Free;
+ cmd_err(erTypeMismatch);
+ LoadTypes := False;
+ exit;
+ end;
+ Curr.BaseType := currf.BaseType;
+ TPSTypeRec_Array(curr).ArrayType := FTypes[d];
+ FTypes.Add(Curr);
+ end;
+ btRecord:
+ begin
+ curr := TPSTypeRec_Record.Create(self);
+ if not read(d, 4) or (d = 0) then
+ begin
+ curr.Free;
+ cmd_err(erUnexpectedEof);
+ LoadTypes := false;
+ exit;
+ end;
+ while d > 0 do
+ begin
+ if not Read(l2, 4) then
+ begin
+ curr.Free;
+ cmd_err(erUnexpectedEof);
+ LoadTypes := false;
+ exit;
+ end;
+ if Cardinal(l2) >= FTypes.Count then
+ begin
+ curr.Free;
+ cmd_err(ErOutOfRange);
+ LoadTypes := false;
+ exit;
+ end;
+ TPSTypeRec_Record(curR).FFieldTypes.Add(FTypes[l2]);
+ Dec(D);
+ end;
+ if not resolve(TPSTypeRec_Record(curr)) then
+ begin
+ curr.Free;
+ cmd_err(erInvalidType);
+ LoadTypes := False;
+ exit;
+ end;
+ Curr.BaseType := currf.BaseType;
+ FTypes.Add(Curr);
+ end;
+ else begin
+ LoadTypes := False;
+ CMD_Err(erInvalidType);
+ exit;
+ end;
+ end;
+ if fe then begin
+ if not read(d, 4) then begin
+ cmd_err(erUnexpectedEof);
+ LoadTypes := False;
+ exit;
+ end;
+ if d > PSAddrNegativeStackStart then
+ begin
+ cmd_err(erInvalidType);
+ LoadTypes := False;
+ exit;
+ end;
+ SetLength(Curr.FExportName, d);
+ if not read(Curr.fExportName[1], d) then
+ begin
+ cmd_err(erUnexpectedEof);
+ LoadTypes := False;
+ exit;
+ end;
+ Curr.ExportNameHash := MakeHash(Curr.ExportName);
+ end;
+ curr.CalcSize;
+ if HDR.PSBuildNo >= 21 then // since build 21 we support attributes
+ begin
+ if not ReadAttributes(Curr.Attributes) then
+ begin
+ LoadTypes := False;
+ exit;
+ end;
+ end;
+ end;
+ end;
+
+ function LoadProcs: Boolean;
+ var
+ Rec: TPSProc;
+ n: tbtString;
+ b: Byte;
+ l, L2, L3: Longint;
+ Curr: TPSProcRec;
+ begin
+ LoadProcs := True;
+ for l := 0 to HDR.ProcCount - 1 do begin
+ if not read(Rec, SizeOf(Rec)) then begin
+ cmd_err(erUnexpectedEof);
+ LoadProcs := False;
+ exit;
+ end;
+ if (Rec.Flags and 1) <> 0 then
+ begin
+ Curr := TPSExternalProcRec.Create(Self);
+ if not read(b, 1) then begin
+ Curr.Free;
+ cmd_err(erUnexpectedEof);
+ LoadProcs := False;
+ exit;
+ end;
+ SetLength(n, b);
+ if not read(n[1], b) then begin
+ Curr.Free;
+ cmd_err(erUnexpectedEof);
+ LoadProcs := False;
+ exit;
+ end;
+ TPSExternalProcRec(Curr).Name := n;
+ if (Rec.Flags and 3 = 3) then
+ begin
+ if (not Read(L2, 4)) or (L2 > Length(s) - Pos) then
+ begin
+ Curr.Free;
+ cmd_err(erUnexpectedEof);
+ LoadProcs := False;
+ exit;
+ end;
+ SetLength(n, L2);
+ Read(n[1], L2); // no check is needed
+ TPSExternalProcRec(Curr).FDecl := n;
+ end;
+ if not ImportProc(TPSExternalProcRec(Curr).Name, TPSExternalProcRec(Curr)) then begin
+ if TPSExternalProcRec(Curr).Name <> '' then
+ CMD_Err2(erCannotImport, TPSExternalProcRec(Curr).Name)
+ else
+ CMD_Err2(erCannotImport, TPSExternalProcRec(curr).Decl);
+ Curr.Free;
+ LoadProcs := False;
+ exit;
+ end;
+ end else begin
+ Curr := TPSInternalProcRec.Create(Self);
+ if not read(L2, 4) then begin
+ Curr.Free;
+ cmd_err(erUnexpectedEof);
+ LoadProcs := False;
+ exit;
+ end;
+ if not read(L3, 4) then begin
+ Curr.Free;
+ cmd_err(erUnexpectedEof);
+ LoadProcs := False;
+ exit;
+ end;
+ if (L2 < 0) or (L2 >= Length(s)) or (L2 + L3 > Length(s)) or (L3 = 0) then begin
+ Curr.Free;
+ cmd_err(erUnexpectedEof);
+ LoadProcs := False;
+ exit;
+ end;
+
+ GetMem(TPSInternalProcRec(Curr).FData, L3);
+ Move(s[L2 + 1], TPSInternalProcRec(Curr).FData^, L3);
+ TPSInternalProcRec(Curr).FLength := L3;
+ if (Rec.Flags and 2) <> 0 then begin // exported
+ if not read(L3, 4) then begin
+ Curr.Free;
+ cmd_err(erUnexpectedEof);
+ LoadProcs := False;
+ exit;
+ end;
+ if L3 > PSAddrNegativeStackStart then begin
+ Curr.Free;
+ cmd_err(erUnexpectedEof);
+ LoadProcs := False;
+ exit;
+ end;
+ SetLength(TPSInternalProcRec(Curr).FExportName, L3);
+ if not read(TPSInternalProcRec(Curr).FExportName[1], L3) then begin
+ Curr.Free;
+ cmd_err(erUnexpectedEof);
+ LoadProcs := False;
+ exit;
+ end;
+ if not read(L3, 4) then begin
+ Curr.Free;
+ cmd_err(erUnexpectedEof);
+ LoadProcs := False;
+ exit;
+ end;
+ if L3 > PSAddrNegativeStackStart then begin
+ Curr.Free;
+ cmd_err(erUnexpectedEof);
+ LoadProcs := False;
+ exit;
+ end;
+ SetLength(TPSInternalProcRec(Curr).FExportDecl, L3);
+ if not read(TPSInternalProcRec(Curr).FExportDecl[1], L3) then begin
+ Curr.Free;
+ cmd_err(erUnexpectedEof);
+ LoadProcs := False;
+ exit;
+ end;
+ TPSInternalProcRec(Curr).FExportNameHash := MakeHash(TPSInternalProcRec(Curr).ExportName);
+ end;
+ end;
+ if (Rec.Flags and 4) <> 0 then
+ begin
+ if not ReadAttributes(Curr.Attributes) then
+ begin
+ Curr.Free;
+ LoadProcs := False;
+ exit;
+ end;
+ end;
+ FProcs.Add(Curr);
+ end;
+ end;
+{$WARNINGS ON}
+
+ function LoadVars: Boolean;
+ var
+ l, n: Longint;
+ e: PPSExportedVar;
+ Rec: TPSVar;
+ Curr: PIfVariant;
+ begin
+ LoadVars := True;
+ for l := 0 to HDR.VarCount - 1 do begin
+ if not read(Rec, SizeOf(Rec)) then begin
+ cmd_err(erUnexpectedEof);
+ LoadVars := False;
+ exit;
+ end;
+ if Rec.TypeNo >= HDR.TypeCount then begin
+ cmd_err(erInvalidType);
+ LoadVars := False;
+ exit;
+ end;
+ Curr := FGlobalVars.PushType(FTypes.Data^[Rec.TypeNo]);
+ if Curr = nil then begin
+ cmd_err(erInvalidType);
+ LoadVars := False;
+ exit;
+ end;
+ if (Rec.Flags and 1) <> 0 then
+ begin
+ if not read(n, 4) then begin
+ cmd_err(erUnexpectedEof);
+ LoadVars := False;
+ exit;
+ end;
+ new(e);
+ try
+ SetLength(e^.FName, n);
+ if not Read(e^.FName[1], n) then
+ begin
+ dispose(e);
+ cmd_err(erUnexpectedEof);
+ LoadVars := False;
+ exit;
+ end;
+ e^.FNameHash := MakeHash(e^.FName);
+ e^.FVarNo := FGlobalVars.Count;
+ FExportedVars.Add(E);
+ except
+ dispose(e);
+ cmd_err(erInvalidType);
+ LoadVars := False;
+ exit;
+ end;
+ end;
+ end;
+ end;
+
+begin
+ Clear;
+ Pos := 0;
+ LoadData := False;
+ if not read(HDR, SizeOf(HDR)) then
+ begin
+ CMD_Err(erInvalidHeader);
+ exit;
+ end;
+ if HDR.HDR <> PSValidHeader then
+ begin
+ CMD_Err(erInvalidHeader);
+ exit;
+ end;
+ if (HDR.PSBuildNo > PSCurrentBuildNo) or (HDR.PSBuildNo < PSLowBuildSupport) then begin
+ CMD_Err(erInvalidHeader);
+ exit;
+ end;
+ if not LoadTypes then
+ begin
+ Clear;
+ exit;
+ end;
+ if not LoadProcs then
+ begin
+ Clear;
+ exit;
+ end;
+ if not LoadVars then
+ begin
+ Clear;
+ exit;
+ end;
+ if (HDR.MainProcNo >= FProcs.Count) and (HDR.MainProcNo <> InvalidVal)then begin
+ CMD_Err(erNoMainProc);
+ Clear;
+ exit;
+ end;
+ // Load Import Table
+ FMainProc := HDR.MainProcNo;
+ FStatus := isLoaded;
+ Result := True;
+end;
+
+
+procedure TPSExec.Pause;
+begin
+ if FStatus = isRunning then
+ FStatus := isPaused;
+end;
+
+function TPSExec.ReadData(var Data; Len: Cardinal): Boolean;
+begin
+ if FCurrentPosition + Len <= FDataLength then begin
+ Move(FData^[FCurrentPosition], Data, Len);
+ FCurrentPosition := FCurrentPosition + Len;
+ Result := True;
+ end
+ else
+ Result := False;
+end;
+
+procedure TPSExec.CMD_Err(EC: TPSError); // Error
+begin
+ CMD_Err3(ec, '', nil);
+end;
+
+procedure VNSetPointerTo(const Src: TPSVariantIFC; Data: Pointer; aType: TPSTypeRec);
+begin
+ if Src.aType.BaseType = btPointer then
+ begin
+ if atype.BaseType in NeedFinalization then
+ FinalizeVariant(src.Dta, Src.aType);
+ Pointer(Src.Dta^) := Data;
+ Pointer(Pointer(IPointer(Src.Dta)+PointerSize)^) := aType;
+ Pointer(Pointer(IPointer(Src.Dta)+(2*PointerSize))^) := nil;
+ end;
+end;
+
+function VNGetUInt(const Src: TPSVariantIFC): Cardinal;
+begin
+ Result := PSGetUInt(Src.Dta, Src.aType);
+end;
+
+{$IFNDEF PS_NOINT64}
+function VNGetInt64(const Src: TPSVariantIFC): Int64;
+begin
+ Result := PSGetInt64(Src.Dta, Src.aType);
+end;
+{$ENDIF}
+
+function VNGetReal(const Src: TPSVariantIFC): Extended;
+begin
+ Result := PSGetReal(Src.Dta, Src.aType);
+end;
+
+function VNGetCurrency(const Src: TPSVariantIFC): Currency;
+begin
+ Result := PSGetCurrency(Src.Dta, Src.aType);
+end;
+
+function VNGetInt(const Src: TPSVariantIFC): Longint;
+begin
+ Result := PSGetInt(Src.Dta, Src.aType);
+end;
+
+function VNGetAnsiString(const Src: TPSVariantIFC): tbtString;
+begin
+ Result := PSGetAnsiString(Src.Dta, Src.aType);
+end;
+
+{$IFNDEF PS_NOWIDESTRING}
+function VNGetWideString(const Src: TPSVariantIFC): tbtWideString;
+begin
+ Result := PSGetWideString(Src.Dta, Src.aType);
+end;
+
+function VNGetUnicodeString(const Src: TPSVariantIFC): tbtunicodestring;
+begin
+ Result := PSGetUnicodeString(Src.Dta, Src.aType);
+end;
+{$ENDIF}
+
+procedure VNSetUInt(const Src: TPSVariantIFC; const Val: Cardinal);
+var
+ Dummy: Boolean;
+begin
+ PSSetUInt(Src.Dta, Src.aType, Dummy, Val);
+end;
+
+{$IFNDEF PS_NOINT64}
+procedure VNSetInt64(const Src: TPSVariantIFC; const Val: Int64);
+var
+ Dummy: Boolean;
+begin
+ PSSetInt64(Src.Dta, Src.aType, Dummy, Val);
+end;
+{$ENDIF}
+
+procedure VNSetReal(const Src: TPSVariantIFC; const Val: Extended);
+var
+ Dummy: Boolean;
+begin
+ PSSetReal(Src.Dta, Src.aType, Dummy, Val);
+end;
+
+procedure VNSetCurrency(const Src: TPSVariantIFC; const Val: Currency);
+var
+ Dummy: Boolean;
+begin
+ PSSetCurrency(Src.Dta, Src.aType, Dummy, Val);
+end;
+
+procedure VNSetInt(const Src: TPSVariantIFC; const Val: Longint);
+var
+ Dummy: Boolean;
+begin
+ PSSetInt(Src.Dta, Src.aType, Dummy, Val);
+end;
+
+procedure VNSetAnsiString(const Src: TPSVariantIFC; const Val: tbtString);
+var
+ Dummy: Boolean;
+begin
+ PSSetAnsiString(Src.Dta, Src.aType, Dummy, Val);
+end;
+
+function VNGetString(const Src: TPSVariantIFC): String;
+begin
+ {$IFDEF DELPHI2009UP}
+ Result := VNGetUnicodeString(Src);
+ {$ELSE}
+ Result := VNGetAnsiString(Src);
+ {$ENDIF}
+end;
+
+procedure VNSetString(const Src: TPSVariantIFC; const Val: String);
+begin
+ {$IFDEF DELPHI2009UP}
+ VNSetUnicodeString(Src, Val);
+ {$ELSE}
+ VNSetAnsiString(Src, Val);
+ {$ENDIF}
+end;
+
+{$IFNDEF PS_NOWIDESTRING}
+procedure VNSetWideString(const Src: TPSVariantIFC; const Val: tbtWideString);
+var
+ Dummy: Boolean;
+begin
+ PSSetWideString(Src.Dta, Src.aType, Dummy, Val);
+end;
+
+procedure VNSetUnicodeString(const Src: TPSVariantIFC; const Val: tbtunicodestring);
+var
+ Dummy: Boolean;
+begin
+ PSSetUnicodeString(Src.Dta, Src.aType, Dummy, Val);
+end;
+
+{$ENDIF}
+
+function VGetUInt(const Src: PIFVariant): Cardinal;
+begin
+ Result := PSGetUInt(@PPSVariantData(src).Data, src.FType);
+end;
+
+{$IFNDEF PS_NOINT64}
+function VGetInt64(const Src: PIFVariant): Int64;
+begin
+ Result := PSGetInt64(@PPSVariantData(src).Data, src.FType);
+end;
+{$ENDIF}
+
+function VGetReal(const Src: PIFVariant): Extended;
+begin
+ Result := PSGetReal(@PPSVariantData(src).Data, src.FType);
+end;
+
+function VGetCurrency(const Src: PIFVariant): Currency;
+begin
+ Result := PSGetCurrency(@PPSVariantData(src).Data, src.FType);
+end;
+
+function VGetInt(const Src: PIFVariant): Longint;
+begin
+ Result := PSGetInt(@PPSVariantData(src).Data, src.FType);
+end;
+
+function VGetAnsiString(const Src: PIFVariant): tbtString;
+begin
+ Result := PSGetAnsiString(@PPSVariantData(src).Data, src.FType);
+end;
+
+{$IFNDEF PS_NOWIDESTRING}
+function VGetWideString(const Src: PIFVariant): tbtWideString;
+begin
+ Result := PSGetWideString(@PPSVariantData(src).Data, src.FType);
+end;
+
+function VGetUnicodeString(const Src: PIFVariant): tbtunicodestring;
+begin
+ Result := PSGetUnicodeString(@PPSVariantData(src).Data, src.FType);
+end;
+
+{$ENDIF}
+
+
+procedure VSetPointerTo(const Src: PIFVariant; Data: Pointer; aType: TPSTypeRec);
+var
+ temp: TPSVariantIFC;
+begin
+ if (Atype = nil) or (Data = nil) or (Src = nil) then raise Exception.Create(RPS_InvalidVariable);
+ temp.Dta := @PPSVariantData(Src).Data;
+ temp.aType := Src.FType;
+ temp.VarParam := false;
+ VNSetPointerTo(temp, Data, AType);
+end;
+
+procedure VSetUInt(const Src: PIFVariant; const Val: Cardinal);
+var
+ Dummy: Boolean;
+begin
+ PSSetUInt(@PPSVariantData(src).Data, src.FType, Dummy, Val);
+end;
+
+{$IFNDEF PS_NOINT64}
+procedure VSetInt64(const Src: PIFVariant; const Val: Int64);
+var
+ Dummy: Boolean;
+begin
+ PSSetInt64(@PPSVariantData(src).Data, src.FType, Dummy, Val);
+end;
+{$ENDIF}
+
+procedure VSetReal(const Src: PIFVariant; const Val: Extended);
+var
+ Dummy: Boolean;
+begin
+ PSSetReal(@PPSVariantData(src).Data, src.FType, Dummy, Val);
+end;
+
+procedure VSetCurrency(const Src: PIFVariant; const Val: Currency);
+var
+ Dummy: Boolean;
+begin
+ PSSetCurrency(@PPSVariantData(src).Data, src.FType, Dummy, Val);
+end;
+
+procedure VSetInt(const Src: PIFVariant; const Val: Longint);
+var
+ Dummy: Boolean;
+begin
+ PSSetInt(@PPSVariantData(src).Data, src.FType, Dummy, Val);
+end;
+
+procedure VSetAnsiString(const Src: PIFVariant; const Val: tbtString);
+var
+ Dummy: Boolean;
+begin
+ PSSetAnsiString(@PPSVariantData(src).Data, src.FType, Dummy, Val);
+end;
+
+function VGetString(const Src: PIFVariant): String;
+begin
+ {$IFDEF DELPHI2009UP}
+ Result := PSGetUnicodeString(@PPSVariantData(src).Data, src.FType);
+ {$ELSE}
+ Result := PSGetAnsiString(@PPSVariantData(src).Data, src.FType);
+ {$ENDIF}
+end;
+
+procedure VSetString(const Src: PIFVariant; const Val: string);
+var
+ Dummy: Boolean;
+begin
+ {$IFDEF DELPHI2009UP}
+ PSSetUnicodeString(@PPSVariantData(src).Data, src.FType, Dummy, Val);
+ {$ELSE}
+ PSSetAnsiString(@PPSVariantData(src).Data, src.FType, Dummy, Val);
+ {$ENDIF}
+end;
+
+
+{$IFNDEF PS_NOWIDESTRING}
+procedure VSetWideString(const Src: PIFVariant; const Val: tbtWideString);
+var
+ Dummy: Boolean;
+begin
+ PSSetWideString(@PPSVariantData(src).Data, src.FType, Dummy, Val);
+end;
+
+procedure VSetUnicodeString(const Src: PIFVariant; const Val: tbtunicodestring);
+var
+ Dummy: Boolean;
+begin
+ PSSetUnicodeString(@PPSVariantData(src).Data, src.FType, Dummy, Val);
+end;
+
+
+{$ENDIF}
+
+{$IFNDEF PS_NOWIDESTRING}
+function VarToWideStr(const Data: Variant): tbtunicodestring;
+begin
+ if not VarIsNull(Data) then
+ Result := Data
+ else
+ Result := '';
+end;
+{$ENDIF}
+
+function PSGetUInt(Src: Pointer; aType: TPSTypeRec): Cardinal;
+begin
+ if aType.BaseType = btPointer then
+ begin
+ atype := PIFTypeRec(Pointer(IPointer(Src)+PointerSize)^);
+ Src := Pointer(Src^);
+ if (src = nil) or (aType = nil) then raise Exception.Create(RPS_TypeMismatch);
+ end;
+ case aType.BaseType of
+ btU8: Result := tbtu8(src^);
+ btS8: Result := tbts8(src^);
+ btU16: Result := tbtu16(src^);
+ btS16: Result := tbts16(src^);
+ btU32: Result := tbtu32(src^);
+ btS32: Result := tbts32(src^);
+{$IFNDEF PS_NOINT64} btS64: Result := tbts64(src^);
+{$ENDIF}
+ btChar: Result := Ord(tbtchar(Src^));
+{$IFNDEF PS_NOWIDESTRING} btWideChar: Result := Ord(tbtwidechar(Src^));{$ENDIF}
+ btVariant:
+ case VarType(Variant(Src^)) of
+ varString:
+ if Length(VarToStr(Variant(Src^))) = 1 then
+ Result := Ord(VarToStr(Variant(Src^))[1])
+ else
+ raise Exception.Create(RPS_TypeMismatch);
+{$IFNDEF PS_NOWIDESTRING}
+ varOleStr:
+ if Length(VarToWideStr(Variant(Src^))) = 1 then
+ Result := Ord(VarToWideStr(Variant(Src^))[1])
+ else
+ raise Exception.Create(RPS_TypeMismatch);
+{$ENDIF}
+ else
+ Result := Variant(src^);
+ end;
+ else raise Exception.Create(RPS_TypeMismatch);
+ end;
+end;
+
+function PSGetObject(Src: Pointer; aType: TPSTypeRec): TObject;
+begin
+ if aType.BaseType = btPointer then
+ begin
+ atype := PIFTypeRec(Pointer(IPointer(Src)+PointerSize)^);
+ Src := Pointer(Src^);
+ if (src = nil) or (aType = nil) then raise Exception.Create(RPS_TypeMismatch);
+ end;
+ case aType.BaseType of
+ btClass: Result := TObject(Src^);
+ else raise Exception.Create(RPS_TypeMismatch);
+ end;
+end;
+
+procedure PSSetObject(Src: Pointer; aType: TPSTypeRec; var Ok: Boolean; Const val: TObject);
+begin
+ if aType.BaseType = btPointer then
+ begin
+ atype := PIFTypeRec(Pointer(IPointer(Src)+PointerSize)^);
+ Src := Pointer(Src^);
+ if (src = nil) or (aType = nil) then raise Exception.Create(RPS_TypeMismatch);
+ end;
+ case aType.BaseType of
+ btClass: TObject(Src^) := Val;
+ else raise Exception.Create(RPS_TypeMismatch);
+ end;
+end;
+
+
+{$IFNDEF PS_NOINT64}
+function PSGetInt64(Src: Pointer; aType: TPSTypeRec): Int64;
+begin
+ if aType.BaseType = btPointer then
+ begin
+ atype := PIFTypeRec(Pointer(IPointer(Src)+PointerSize)^);
+ Src := Pointer(Src^);
+ if (src = nil) or (aType = nil) then raise Exception.Create(RPS_TypeMismatch);
+ end;
+ case aType.BaseType of
+ btU8: Result := tbtu8(src^);
+ btS8: Result := tbts8(src^);
+ btU16: Result := tbtu16(src^);
+ btS16: Result := tbts16(src^);
+ btU32: Result := tbtu32(src^);
+ btS32: Result := tbts32(src^);
+ btS64: Result := tbts64(src^);
+ btChar: Result := Ord(tbtchar(Src^));
+{$IFNDEF PS_NOWIDESTRING}
+ btWideChar: Result := Ord(tbtwidechar(Src^));
+{$ENDIF}
+{$IFDEF DELPHI6UP}
+ btVariant: Result := Variant(src^);
+{$ENDIF}
+ else raise Exception.Create(RPS_TypeMismatch);
+ end;
+end;
+{$ENDIF}
+
+function PSGetReal(Src: Pointer; aType: TPSTypeRec): Extended;
+begin
+ if aType.BaseType = btPointer then
+ begin
+ atype := PIFTypeRec(Pointer(IPointer(Src)+PointerSize)^);
+ Src := Pointer(Src^);
+ if (src = nil) or (aType = nil) then raise Exception.Create(RPS_TypeMismatch);
+ end;
+ case aType.BaseType of
+ btU8: Result := tbtu8(src^);
+ btS8: Result := tbts8(src^);
+ btU16: Result := tbtu16(src^);
+ btS16: Result := tbts16(src^);
+ btU32: Result := tbtu32(src^);
+ btS32: Result := tbts32(src^);
+{$IFNDEF PS_NOINT64} btS64: Result := tbts64(src^);{$ENDIF}
+ btSingle: Result := tbtsingle(Src^);
+ btDouble: Result := tbtdouble(Src^);
+ btExtended: Result := tbtextended(Src^);
+ btCurrency: Result := tbtcurrency(Src^);
+ btVariant: Result := Variant(src^);
+ else raise Exception.Create(RPS_TypeMismatch);
+ end;
+end;
+
+function PSGetCurrency(Src: Pointer; aType: TPSTypeRec): Currency;
+begin
+ if aType.BaseType = btPointer then
+ begin
+ atype := PIFTypeRec(Pointer(IPointer(Src)+PointerSize)^);
+ Src := Pointer(Src^);
+ if (src = nil) or (aType = nil) then raise Exception.Create(RPS_TypeMismatch);
+ end;
+ case aType.BaseType of
+ btU8: Result := tbtu8(src^);
+ btS8: Result := tbts8(src^);
+ btU16: Result := tbtu16(src^);
+ btS16: Result := tbts16(src^);
+ btU32: Result := tbtu32(src^);
+ btS32: Result := tbts32(src^);
+{$IFNDEF PS_NOINT64} btS64: Result := tbts64(src^);{$ENDIF}
+ btSingle: Result := tbtsingle(Src^);
+ btDouble: Result := tbtdouble(Src^);
+ btExtended: Result := tbtextended(Src^);
+ btCurrency: Result := tbtcurrency(Src^);
+ btVariant: Result := Variant(src^);
+ else raise Exception.Create(RPS_TypeMismatch);
+ end;
+end;
+
+
+function PSGetInt(Src: Pointer; aType: TPSTypeRec): Longint;
+begin
+ if aType.BaseType = btPointer then
+ begin
+ atype := PIFTypeRec(Pointer(IPointer(Src)+PointerSize)^);
+ Src := Pointer(Src^);
+ if (src = nil) or (aType = nil) then raise Exception.Create(RPS_TypeMismatch);
+ end;
+ case aType.BaseType of
+ btU8: Result := tbtu8(src^);
+ btS8: Result := tbts8(src^);
+ btU16: Result := tbtu16(src^);
+ btS16: Result := tbts16(src^);
+ btU32: Result := tbtu32(src^);
+ btS32: Result := tbts32(src^);
+{$IFNDEF PS_NOINT64} btS64: Result := tbts64(src^);{$ENDIF}
+ btChar: Result := Ord(tbtchar(Src^));
+{$IFNDEF PS_NOWIDESTRING} btWideChar: Result := Ord(tbtwidechar(Src^));{$ENDIF}
+ btVariant: Result := Variant(src^);
+ else raise Exception.Create(RPS_TypeMismatch);
+ end;
+end;
+
+
+function PSGetAnsiString(Src: Pointer; aType: TPSTypeRec): tbtString;
+begin
+ if aType.BaseType = btPointer then
+ begin
+ atype := PIFTypeRec(Pointer(IPointer(Src)+PointerSize)^);
+ Src := Pointer(Src^);
+ if (src = nil) or (aType = nil) then raise Exception.Create(RPS_TypeMismatch);
+ end;
+ case aType.BaseType of
+ btU8: Result := tbtchar(tbtu8(src^));
+ btChar: Result := tbtchar(Src^);
+ btPchar: Result := pansichar(src^);
+{$IFNDEF PS_NOWIDESTRING} btWideChar: Result := tbtString(tbtwidechar(Src^));{$ENDIF}
+ btString: Result := tbtstring(src^);
+{$IFNDEF PS_NOWIDESTRING}
+ btUnicodeString: result := tbtString(tbtUnicodestring(src^));
+ btWideString: Result := tbtString(tbtwidestring(src^));{$ENDIF}
+ btVariant: Result := tbtString(Variant(src^));
+ else raise Exception.Create(RPS_TypeMismatch);
+ end;
+end;
+{$IFNDEF PS_NOWIDESTRING}
+function PSGetWideString(Src: Pointer; aType: TPSTypeRec): tbtWideString;
+begin
+ if aType.BaseType = btPointer then
+ begin
+ atype := PIFTypeRec(Pointer(IPointer(Src)+PointerSize)^);
+ Src := Pointer(Src^);
+ if (src = nil) or (aType = nil) then raise Exception.Create(RPS_TypeMismatch);
+ end;
+ case aType.BaseType of
+ btU8: Result := chr(tbtu8(src^));
+ btU16: Result := widechar(src^);
+ btChar: Result := tbtwidestring(tbtchar(Src^));
+ btPchar: Result := tbtwidestring(pansichar(src^));
+ btWideChar: Result := tbtwidechar(Src^);
+ btString: Result := tbtwidestring(tbtstring(src^));
+ btWideString: Result := tbtwidestring(src^);
+ btVariant: Result := Variant(src^);
+ btUnicodeString: result := tbtUnicodeString(src^);
+ else raise Exception.Create(RPS_TypeMismatch);
+ end;
+end;
+
+function PSGetUnicodeString(Src: Pointer; aType: TPSTypeRec): tbtunicodestring;
+begin
+ if aType.BaseType = btPointer then
+ begin
+ atype := PIFTypeRec(Pointer(IPointer(Src)+PointerSize)^);
+ Src := Pointer(Src^);
+ if (src = nil) or (aType = nil) then raise Exception.Create(RPS_TypeMismatch);
+ end;
+ case aType.BaseType of
+ btU8: Result := chr(tbtu8(src^));
+ btU16: Result := widechar(src^);
+ btChar: Result := tbtwidestring(tbtchar(Src^));
+ btPchar: Result := tbtwidestring(pansichar(src^));
+ btWideChar: Result := tbtwidechar(Src^);
+ btString: Result := tbtwidestring(tbtstring(src^));
+ btWideString: Result := tbtwidestring(src^);
+ btVariant: Result := Variant(src^);
+ btUnicodeString: result := tbtUnicodeString(src^);
+ else raise Exception.Create(RPS_TypeMismatch);
+ end;
+end;
+{$ENDIF}
+
+procedure PSSetUInt(Src: Pointer; aType: TPSTypeRec; var Ok: Boolean; const Val: Cardinal);
+begin
+ if (Src = nil) or (aType = nil) then begin Ok := false; exit; end;
+ if aType.BaseType = btPointer then
+ begin
+ atype := PIFTypeRec(Pointer(IPointer(Src)+PointerSize)^);
+ Src := Pointer(Src^);
+ if (src = nil) or (aType = nil) then begin Ok := false; exit; end;
+ end;
+ case aType.BaseType of
+ btU8: tbtu8(src^) := Val;
+ btS8: tbts8(src^) := Val;
+ btU16: tbtu16(src^) := Val;
+ btS16: tbts16(src^) := Val;
+ btProcPtr:
+ begin
+ tbtu32(src^) := Val;
+ Pointer(Pointer(IPointer(Src)+PointerSize)^) := nil;
+ Pointer(Pointer(IPointer(Src)+PointerSize2)^) := nil;
+ end;
+ btU32: tbtu32(src^) := Val;
+ btS32: tbts32(src^) := Val;
+{$IFNDEF PS_NOINT64} btS64: tbts64(src^) := Val;{$ENDIF}
+ btChar: tbtchar(Src^) := tbtChar(Val);
+{$IFNDEF PS_NOWIDESTRING} btWideChar: tbtwidechar(Src^) := tbtwidechar(Val);{$ENDIF}
+ btSingle: tbtSingle(src^) := Val;
+ btDouble: tbtDouble(src^) := Val;
+ btCurrency: tbtCurrency(src^) := Val;
+ btExtended: tbtExtended(src^) := Val;
+ btVariant:
+ begin
+ try
+ Variant(src^) := {$IFDEF DELPHI6UP}val{$ELSE}tbts32(val){$ENDIF};
+ except
+ Ok := false;
+ end;
+ end;
+ else ok := false;
+ end;
+end;
+
+{$IFNDEF PS_NOINT64}
+procedure PSSetInt64(Src: Pointer; aType: TPSTypeRec; var Ok: Boolean; const Val: Int64);
+begin
+ if (Src = nil) or (aType = nil) then begin Ok := false; exit; end;
+ if aType.BaseType = btPointer then
+ begin
+ atype := PIFTypeRec(Pointer(IPointer(Src)+PointerSize)^);
+ Src := Pointer(Src^);
+ if (src = nil) or (aType = nil) then begin Ok := false; exit; end;
+ end;
+ case aType.BaseType of
+ btU8: tbtu8(src^) := Val;
+ btS8: tbts8(src^) := Val;
+ btU16: tbtu16(src^) := Val;
+ btS16: tbts16(src^) := Val;
+ btU32: tbtu32(src^) := Val;
+ btS32: tbts32(src^) := Val;
+ btS64: tbts64(src^) := Val;
+ btChar: tbtchar(Src^) := tbtChar(Val);
+{$IFNDEF PS_NOWIDESTRING}
+ btWideChar: tbtwidechar(Src^) := tbtwidechar(Val);
+{$ENDIF}
+ btSingle: tbtSingle(src^) := Val;
+ btDouble: tbtDouble(src^) := Val;
+ btCurrency: tbtCurrency(src^) := Val;
+ btExtended: tbtExtended(src^) := Val;
+{$IFDEF DELPHI6UP}
+ btVariant:
+ begin
+ try
+ Variant(src^) := Val;
+ except
+ Ok := false;
+ end;
+ end;
+{$ENDIF}
+ else ok := false;
+ end;
+end;
+{$ENDIF}
+
+procedure PSSetReal(Src: Pointer; aType: TPSTypeRec; var Ok: Boolean; const Val: Extended);
+begin
+ if (Src = nil) or (aType = nil) then begin Ok := false; exit; end;
+ if aType.BaseType = btPointer then
+ begin
+ atype := PIFTypeRec(Pointer(IPointer(Src)+PointerSize)^);
+ Src := Pointer(Src^);
+ if (src = nil) or (aType = nil) then begin Ok := false; exit; end;
+ end;
+ case aType.BaseType of
+ btSingle: tbtSingle(src^) := Val;
+ btDouble: tbtDouble(src^) := Val;
+ btCurrency: tbtCurrency(src^) := Val;
+ btExtended: tbtExtended(src^) := Val;
+ btVariant:
+ begin
+ try
+ Variant(src^) := Val;
+ except
+ Ok := false;
+ end;
+ end;
+ else ok := false;
+ end;
+end;
+
+procedure PSSetCurrency(Src: Pointer; aType: TPSTypeRec; var Ok: Boolean; const Val: Currency);
+begin
+ if (Src = nil) or (aType = nil) then begin Ok := false; exit; end;
+ if aType.BaseType = btPointer then
+ begin
+ atype := PIFTypeRec(Pointer(IPointer(Src)+PointerSize)^);
+ Src := Pointer(Src^);
+ if (src = nil) or (aType = nil) then begin Ok := false; exit; end;
+ end;
+ case aType.BaseType of
+ btSingle: tbtSingle(src^) := Val;
+ btDouble: tbtDouble(src^) := Val;
+ btCurrency: tbtCurrency(src^) := Val;
+ btExtended: tbtExtended(src^) := Val;
+ btVariant:
+ begin
+ try
+ Variant(src^) := Val;
+ except
+ Ok := false;
+ end;
+ end;
+ else ok := false;
+ end;
+end;
+
+procedure PSSetInt(Src: Pointer; aType: TPSTypeRec; var Ok: Boolean; const Val: Longint);
+begin
+ if (Src = nil) or (aType = nil) then begin Ok := false; exit; end;
+ if aType.BaseType = btPointer then
+ begin
+ atype := PIFTypeRec(Pointer(IPointer(Src)+PointerSize)^);
+ Src := Pointer(Src^);
+ if (src = nil) or (aType = nil) then begin Ok := false; exit; end;
+ end;
+ case aType.BaseType of
+ btU8: tbtu8(src^) := Val;
+ btS8: tbts8(src^) := Val;
+ btU16: tbtu16(src^) := Val;
+ btS16: tbts16(src^) := Val;
+ btProcPtr:
+ begin
+ tbtu32(src^) := Val;
+ Pointer(Pointer(IPointer(Src)+PointerSize)^) := nil;
+ Pointer(Pointer(IPointer(Src)+PointerSize2)^) := nil;
+ end;
+ btU32: tbtu32(src^) := Val;
+ btS32: tbts32(src^) := Val;
+{$IFNDEF PS_NOINT64} btS64: tbts64(src^) := Val;{$ENDIF}
+ btChar: tbtchar(Src^) := tbtChar(Val);
+{$IFNDEF PS_NOWIDESTRING} btWideChar: tbtwidechar(Src^) := tbtwidechar(Val);{$ENDIF}
+ btSingle: tbtSingle(src^) := Val;
+ btDouble: tbtDouble(src^) := Val;
+ btCurrency: tbtCurrency(src^) := Val;
+ btExtended: tbtExtended(src^) := Val;
+ btVariant:
+ begin
+ try
+ Variant(src^) := Val;
+ except
+ Ok := false;
+ end;
+ end;
+ else ok := false;
+ end;
+end;
+
+procedure PSSetAnsiString(Src: Pointer; aType: TPSTypeRec; var Ok: Boolean; const Val: tbtString);
+begin
+ if (Src = nil) or (aType = nil) then begin Ok := false; exit; end;
+ if aType.BaseType = btPointer then
+ begin
+ atype := PIFTypeRec(Pointer(IPointer(Src)+PointerSize)^);
+ Src := Pointer(Src^);
+ if (src = nil) or (aType = nil) then begin Ok := false; exit; end;
+ end;
+ case aType.BaseType of
+ btString: tbtstring(src^) := val;
+{$IFNDEF PS_NOWIDESTRING}
+ btUnicodeString: tbtunicodestring(src^) := tbtUnicodeString(AnsiString(val));
+ btWideString: tbtwidestring(src^) := tbtwidestring(AnsiString(val));{$ENDIF}
+ btVariant:
+ begin
+ try
+ Variant(src^) := Val;
+ except
+ Ok := false;
+ end;
+ end;
+ else ok := false;
+ end;
+end;
+{$IFNDEF PS_NOWIDESTRING}
+procedure PSSetWideString(Src: Pointer; aType: TPSTypeRec; var Ok: Boolean; const Val: tbtWideString);
+begin
+ if (Src = nil) or (aType = nil) then begin Ok := false; exit; end;
+ if aType.BaseType = btPointer then
+ begin
+ atype := PIFTypeRec(Pointer(IPointer(Src)+PointerSize)^);
+ Src := Pointer(Src^);
+ if (src = nil) or (aType = nil) then begin Ok := false; exit; end;
+ end;
+ case aType.BaseType of
+ btString: tbtstring(src^) := tbtString(val);
+ btWideString: tbtwidestring(src^) := val;
+ btUnicodeString: tbtunicodestring(src^) := val;
+ btVariant:
+ begin
+ try
+ Variant(src^) := Val;
+ except
+ Ok := false;
+ end;
+ end;
+ else ok := false;
+ end;
+end;
+procedure PSSetUnicodeString(Src: Pointer; aType: TPSTypeRec; var Ok: Boolean; const Val: tbtunicodestring);
+begin
+ if (Src = nil) or (aType = nil) then begin Ok := false; exit; end;
+ if aType.BaseType = btPointer then
+ begin
+ atype := PIFTypeRec(Pointer(IPointer(Src)+PointerSize)^);
+ Src := Pointer(Src^);
+ if (src = nil) or (aType = nil) then begin Ok := false; exit; end;
+ end;
+ case aType.BaseType of
+ btString: tbtstring(src^) := tbtString(val);
+ btWideString: tbtwidestring(src^) := val;
+ btUnicodeString: tbtunicodestring(src^) := val;
+ btVariant:
+ begin
+ try
+ Variant(src^) := Val;
+ except
+ Ok := false;
+ end;
+ end;
+ else ok := false;
+ end;
+end;
+{$ENDIF}
+
+function PSGetString(Src: Pointer; aType: TPSTypeRec): string;
+begin
+ {$IFDEF DELPHI2009UP}
+ result := PSGetUnicodeString(Src, aType);
+ {$ELSE}
+ result := PSGetAnsiString(Src, aType);
+ {$ENDIF}
+end;
+
+procedure PSSetString(Src: Pointer; aType: TPSTypeRec; var Ok: Boolean; const Val: String);
+begin
+ {$IFDEF DELPHI2009UP}
+ PSSetUnicodeString(Src, aType, Ok, Val);
+ {$ELSE}
+ PSSetAnsiString(Src, aType, Ok, Val);
+ {$ENDIF}
+end;
+
+
+function CopyArrayContents(dest, src: Pointer; Len: Longint; aType: TPSTypeRec): Boolean; forward;
+
+function CopyRecordContents(dest, src: Pointer; aType: TPSTypeRec_Record): Boolean;
+var
+ o, i: Longint;
+begin
+ for i := 0 to aType.FieldTypes.Count -1 do
+ begin
+ o := Longint(atype.RealFieldOffsets[i]);
+ CopyArrayContents(Pointer(IPointer(Dest)+Cardinal(o)), Pointer(IPointer(Src)+Cardinal(o)), 1, aType.FieldTypes[i]);
+ end;
+ Result := true;
+end;
+
+function CreateArrayFromVariant(Exec: TPSExec; dest: Pointer; src: Variant; DestType: TPSTypeRec): Boolean;
+var
+ i: Integer;
+ r: Pointer;
+ lVarType: TPSTypeRec;
+ v: variant;
+begin
+ lVarType := Exec.FindType2(btVariant);
+ if lVarType = nil then begin result := false; exit; end;
+ PSDynArraySetLength(Pointer(dest^), desttype, VarArrayHighBound(src, 1) - VarArrayLowBound(src, 1) + 1);
+ r := Pointer(Dest^);
+ DestType := TPSTypeRec_Array(DestType).ArrayType;
+ for i := 0 to VarArrayHighBound(src, 1) - VarArrayLowBound(src, 1) do begin
+ v := src[i + VarArrayLowBound(src, 1)];
+ if not Exec.SetVariantValue(r, @v, desttype, lVarType) then begin result := false; exit; end;
+ r := Pointer(IPointer(r) + Longint(DestType.RealSize));
+ end;
+ Result := true;
+end;
+
+function CopyArrayContents(dest, src: Pointer; Len: Longint; aType: TPSTypeRec): Boolean;
+var
+ elsize: Cardinal;
+ i: Longint;
+begin
+ try
+ case aType.BaseType of
+ btU8, btS8, btChar:
+ for i := 0 to Len -1 do
+ begin
+ tbtU8(Dest^) := tbtU8(Src^);
+ Dest := Pointer(IPointer(Dest) + 1);
+ Src := Pointer(IPointer(Src) + 1);
+ end;
+ btU16, btS16{$IFNDEF PS_NOWIDESTRING}, btWideChar{$ENDIF}:
+ for i := 0 to Len -1 do
+ begin
+ tbtU16(Dest^) := tbtU16(Src^);
+ Dest := Pointer(IPointer(Dest) + 2);
+ Src := Pointer(IPointer(Src) + 2);
+ end;
+ btProcPtr:
+ for i := 0 to Len -1 do
+ begin
+ tbtU32(Dest^) := tbtU32(Src^);
+ Dest := Pointer(IPointer(Dest) + 4);
+ Src := Pointer(IPointer(Src) + 4);
+ Pointer(Dest^) := Pointer(Src^);
+ Dest := Pointer(IPointer(Dest) + PointerSize);
+ Src := Pointer(IPointer(Src) + PointerSize);
+ Pointer(Dest^) := Pointer(Src^);
+ Dest := Pointer(IPointer(Dest) + PointerSize);
+ Src := Pointer(IPointer(Src) + PointerSize);
+ end;
+ btClass, btpchar:
+ for i := 0 to Len -1 do
+ begin
+ Pointer(Dest^) := Pointer(Src^);
+ Dest := Pointer(IPointer(Dest) + PointerSize);
+ Src := Pointer(IPointer(Src) + PointerSize);
+ end;
+ btU32, btS32, btSingle:
+ for i := 0 to Len -1 do
+ begin
+ tbtU32(Dest^) := tbtU32(Src^);
+ Dest := Pointer(IPointer(Dest) + 4);
+ Src := Pointer(IPointer(Src) + 4);
+ end;
+ btDouble:
+ for i := 0 to Len -1 do
+ begin
+ tbtDouble(Dest^) := tbtDouble(Src^);
+ Dest := Pointer(IPointer(Dest) + 8);
+ Src := Pointer(IPointer(Src) + 8);
+ end;
+ {$IFNDEF PS_NOINT64}bts64:
+ for i := 0 to Len -1 do
+ begin
+ tbts64(Dest^) := tbts64(Src^);
+ Dest := Pointer(IPointer(Dest) + 8);
+ Src := Pointer(IPointer(Src) + 8);
+ end;{$ENDIF}
+ btExtended:
+ for i := 0 to Len -1 do
+ begin
+ tbtExtended(Dest^) := tbtExtended(Src^);
+ Dest := Pointer(IPointer(Dest) + SizeOf(Extended));
+ Src := Pointer(IPointer(Src) + SizeOf(Extended));
+ end;
+ btCurrency:
+ for i := 0 to Len -1 do
+ begin
+ tbtCurrency(Dest^) := tbtCurrency(Src^);
+ Dest := Pointer(IPointer(Dest) + SizeOf(Currency));
+ Src := Pointer(IPointer(Src) + SizeOf(Currency));
+ end;
+ btVariant:
+ for i := 0 to Len -1 do
+ begin
+ variant(Dest^) := variant(Src^);
+ Dest := Pointer(IPointer(Dest) + Sizeof(Variant));
+ Src := Pointer(IPointer(Src) + Sizeof(Variant));
+ end;
+ btString:
+ for i := 0 to Len -1 do
+ begin
+ tbtString(Dest^) := tbtString(Src^);
+ Dest := Pointer(IPointer(Dest) + PointerSize);
+ Src := Pointer(IPointer(Src) + PointerSize);
+ end;
+ {$IFNDEF PS_NOWIDESTRING}
+ btUnicodeString:
+ for i := 0 to Len -1 do
+ begin
+ tbtunicodestring(Dest^) := tbtunicodestring(Src^);
+ Dest := Pointer(IPointer(Dest) + PointerSize);
+ Src := Pointer(IPointer(Src) + PointerSize);
+ end;
+ btWideString:
+ for i := 0 to Len -1 do
+ begin
+ tbtWideString(Dest^) := tbtWideString(Src^);
+ Dest := Pointer(IPointer(Dest) + PointerSize);
+ Src := Pointer(IPointer(Src) + PointerSize);
+ end;
+ {$ENDIF}
+ btStaticArray:
+ begin
+ elSize := aType.RealSize;
+ for i := 0 to Len -1 do
+ begin
+ if not CopyArrayContents(Dest, Src, TPSTypeRec_StaticArray(aType).Size, TPSTypeRec_StaticArray(aType).ArrayType) then
+ begin
+ result := false;
+ exit;
+ end;
+ Dest := Pointer(IPointer(Dest) + elsize);
+ Src := Pointer(IPointer(Src) + elsize);
+ end;
+ end;
+ btArray:
+ begin
+ for i := 0 to Len -1 do
+ begin
+ Pointer(Dest^) := Pointer(Src^);
+ if Pointer(Dest^) <> nil then
+ begin
+ Inc(Longint(Pointer(IPointer(Dest^)-(2*PointerSize))^)); // RefCount
+ end;
+ Dest := Pointer(IPointer(Dest) + PointerSize);
+ Src := Pointer(IPointer(Src) + PointerSize);
+ end;
+ end;
+ btRecord:
+ begin
+ elSize := aType.RealSize;
+ for i := 0 to Len -1 do
+ begin
+ if not CopyRecordContents(Dest, Src, TPSTypeRec_Record(aType)) then
+ begin
+ result := false;
+ exit;
+ end;
+ Dest := Pointer(IPointer(Dest) + elsize);
+ Src := Pointer(IPointer(Src) + elsize);
+ end;
+ end;
+ btSet:
+ begin
+ elSize := aType.RealSize;
+ for i := 0 to Len -1 do
+ begin
+ Move(Src^, Dest^, elSize);
+ Dest := Pointer(IPointer(Dest) + elsize);
+ Src := Pointer(IPointer(Src) + elsize);
+ end;
+ end;
+{$IFNDEF PS_NOINTERFACES}
+ btInterface:
+ begin
+ for i := 0 to Len -1 do
+ begin
+ {$IFNDEF DELPHI3UP}
+ if IUnknown(Dest^) <> nil then
+ begin
+ IUnknown(Dest^).Release;
+ IUnknown(Dest^) := nil;
+ end;
+ {$ENDIF}
+ IUnknown(Dest^) := IUnknown(Src^);
+ {$IFNDEF DELPHI3UP}
+ if IUnknown(Dest^) <> nil then
+ IUnknown(Dest^).AddRef;
+ {$ENDIF}
+ Dest := Pointer(IPointer(Dest) + PointerSize);
+ Src := Pointer(IPointer(Src) + PointerSize);
+ end;
+ end;
+{$ENDIF}
+ btPointer:
+ begin
+ if (Pointer(Pointer(IPointer(Dest)+PointerSize2)^) = nil) and (Pointer(Pointer(IPointer(Src)+PointerSize2)^) = nil) then
+ begin
+ for i := 0 to Len -1 do
+ begin
+ Pointer(Dest^) := Pointer(Src^);
+ Dest := Pointer(IPointer(Dest) + PointerSize);
+ Src := Pointer(IPointer(Src) + PointerSize);
+ Pointer(Dest^) := Pointer(Src^);
+ Dest := Pointer(IPointer(Dest) + PointerSize);
+ Src := Pointer(IPointer(Src) + PointerSize);
+ LongBool(Dest^) := false;
+ Dest := Pointer(IPointer(Dest) + sizeof(LongBool));
+ Src := Pointer(IPointer(Src) + sizeof(LongBool));
+ end;
+ end else begin
+ for i := 0 to Len -1 do
+ begin
+ if Pointer(Pointer(IPointer(Dest)+PointerSize2)^) <> nil then
+ DestroyHeapVariant2(Pointer(Dest^), Pointer(Pointer(IPointer(Dest)+PointerSize)^));
+ if Pointer(Src^) <> nil then
+ begin
+ if not LongBool(Pointer(IPointer(Src) + PointerSize2)^) then
+ begin
+ Pointer(Dest^) := Pointer(Src^);
+ Pointer(Pointer(IPointer(Dest) + PointerSize)^) := Pointer(Pointer(IPointer(Src) + PointerSize)^);
+ Pointer(Pointer(IPointer(Dest) + PointerSize2)^) := Pointer(Pointer(IPointer(Src) + PointerSize2)^);
+ end else
+ begin
+ Pointer(Dest^) := CreateHeapVariant2(Pointer(Pointer(IPointer(Src) + PointerSize)^));
+ Pointer(Pointer(IPointer(Dest) + PointerSize)^) := Pointer(Pointer(IPointer(Src) + PointerSize)^);
+ LongBool(Pointer(IPointer(Dest) + PointerSize2)^) := true;
+ if not CopyArrayContents(Pointer(Dest^), Pointer(Src^), 1, Pointer(Pointer(IPointer(Dest) + PointerSize)^)) then
+ begin
+ Result := false;
+ exit;
+ end;
+ end;
+ end else
+ begin
+ Pointer(Dest^) := nil;
+ Pointer(Pointer(IPointer(Dest) + PointerSize)^) := nil;
+ Pointer(Pointer(IPointer(Dest) + PointerSize2)^) := nil;
+ end;
+ Dest := Pointer(IPointer(Dest) + PointerSize*2+sizeof(LongBool));
+ Src := Pointer(IPointer(Src) + PointerSize*2+sizeof(LongBool));
+ end;
+ end;
+ end;
+// btResourcePointer = 15;
+// btVariant = 16;
+ else
+ Result := False;
+ exit;
+ end;
+ except
+ Result := False;
+ exit;
+ end;
+ Result := true;
+end;
+
+function GetPSArrayLength(Arr: PIFVariant): Longint;
+begin
+ result := PSDynArrayGetLength(PPSVariantDynamicArray(arr).Data, arr.FType);
+end;
+
+procedure SetPSArrayLength(Arr: PIFVariant; NewLength: Longint);
+begin
+ PSDynArraySetLength(PPSVariantDynamicArray(arr).Data, arr.FType, NewLength);
+end;
+
+
+function PSDynArrayGetLength(arr: Pointer; aType: TPSTypeRec): Longint;
+begin
+ if aType.BaseType <> btArray then raise Exception.Create(RPS_InvalidArray);
+ if arr = nil then Result := 0 else Result := Longint(Pointer(IPointer(arr)-PointerSize)^) {$IFDEF FPC} +1 {$ENDIF};
+end;
+
+procedure PSDynArraySetLength(var arr: Pointer; aType: TPSTypeRec; NewLength: Longint);
+var
+ elSize, i, OldLen: Longint;
+ p: Pointer;
+begin
+ if aType.BaseType <> btArray then raise Exception.Create(RPS_InvalidArray);
+ OldLen := PSDynArrayGetLength(arr, aType);
+ elSize := TPSTypeRec_Array(aType).ArrayType.RealSize;
+ if (OldLen = 0) and (NewLength = 0) then exit; // already are both 0
+ if (OldLen <> 0) and (Longint(Pointer(IPointer(Arr)-PointerSize2)^) = 1) then // unique copy of this dynamic array
+ begin
+ for i := NewLength to OldLen -1 do
+ begin
+ if TPSTypeRec_Array(aType).ArrayType.BaseType in NeedFinalization then
+ FinalizeVariant(Pointer(IPointer(arr) + Cardinal(elsize * i)), TPSTypeRec_Array(aType).ArrayType);
+ end;
+ arr := Pointer(IPointer(Arr)-PointerSize2);
+ if NewLength <= 0 then
+ begin
+ FreeMem(arr, NewLength * elsize + PointerSize2);
+ arr := nil;
+ exit;
+ end;
+ ReallocMem(arr, NewLength * elSize + PointerSize2);
+ arr := Pointer(IPointer(Arr)+PointerSize);
+ Longint(Arr^) := NewLength {$IFDEF FPC} -1 {$ENDIF};
+ arr := Pointer(IPointer(Arr)+PointerSize);
+ for i := OldLen to NewLength -1 do
+ begin
+ InitializeVariant(Pointer(IPointer(arr) + Cardinal(elsize * i)), TPSTypeRec_Array(aType).ArrayType);
+ end;
+ end else
+ begin
+ if NewLength = 0 then
+ begin
+ if Longint(Pointer(IPointer(Arr)-PointerSize2)^) = 1 then
+ FreeMem(Pointer(IPointer(Arr)-PointerSize2), OldLen * elSize + PointerSize2)
+ else if Longint(Pointer(IPointer(Arr)-PointerSize2)^) > 0 then
+ Dec(Longint(Pointer(IPointer(Arr)-PointerSize2)^));
+ arr := nil;
+ exit;
+ end;
+ GetMem(p, NewLength * elSize + PointerSize2);
+ Longint(p^) := 1;
+ p:= Pointer(IPointer(p)+PointerSize);
+ Longint(p^) := NewLength {$IFDEF FPC} -1 {$ENDIF};
+ p := Pointer(IPointer(p)+PointerSize);
+ if OldLen <> 0 then
+ begin
+ if OldLen > NewLength then
+ CopyArrayContents(p, arr, NewLength, TPSTypeRec_Array(aType).ArrayType)
+ else
+ CopyArrayContents(p, arr, OldLen, TPSTypeRec_Array(aType).ArrayType);
+ FinalizeVariant(@arr, aType);
+ end;
+ arr := p;
+ for i := OldLen to NewLength -1 do
+ begin
+ InitializeVariant(Pointer(IPointer(arr) + Cardinal(elsize * i)), TPSTypeRec_Array(aType).ArrayType);
+ end;
+ end;
+end;
+
+
+
+{$IFDEF FPC}
+function OleErrorMessage(ErrorCode: HResult): tbtString;
+begin
+ Result := SysErrorMessage(ErrorCode);
+ if Result = '' then
+ Result := Format(RPS_OLEError, [ErrorCode]);
+end;
+
+procedure OleError(ErrorCode: HResult);
+begin
+ raise Exception.Create(OleErrorMessage(ErrorCode));
+end;
+
+procedure OleCheck(Result: HResult);
+begin
+ if Result < 0 then OleError(Result);
+end;
+{$ENDIF}
+
+
+{$IFNDEF DELPHI3UP}
+function OleErrorMessage(ErrorCode: HResult): tbtString;
+begin
+ Result := SysErrorMessage(ErrorCode);
+ if Result = '' then
+ Result := Format(RPS_OLEError, [ErrorCode]);
+end;
+
+procedure OleError(ErrorCode: HResult);
+begin
+ raise Exception.Create(OleErrorMessage(ErrorCode));
+end;
+
+procedure OleCheck(Result: HResult);
+begin
+ if Result < 0 then OleError(Result);
+end;
+
+procedure AssignInterface(var Dest: IUnknown; const Src: IUnknown);
+var
+ OldDest: IUnknown;
+begin
+ { Like Delphi 3+'s _IntfCopy, reference source before releasing old dest.
+ so that self assignment (I := I) works right }
+ OldDest := Dest;
+ Dest := Src;
+ if Src <> nil then
+ Src.AddRef;
+ if OldDest <> nil then
+ OldDest.Release;
+end;
+
+procedure AssignVariantFromIDispatch(var Dest: Variant; const Src: IDispatch);
+begin
+ VarClear(Dest);
+ TVarData(Dest).VDispatch := Src;
+ TVarData(Dest).VType := varDispatch;
+ if Src <> nil then
+ Src.AddRef;
+end;
+
+procedure AssignIDispatchFromVariant(var Dest: IDispatch; const Src: Variant);
+const
+ RPS_InvalidVariantRef = 'Invalid variant ref';
+var
+ NewDest: IDispatch;
+begin
+ case TVarData(Src).VType of
+ varEmpty: NewDest := nil;
+ varDispatch: NewDest := TVarData(Src).VDispatch;
+ varDispatch or varByRef: NewDest := Pointer(TVarData(Src).VPointer^);
+ else
+ raise Exception.Create(RPS_InvalidVariantRef);
+ end;
+ AssignInterface(IUnknown(Dest), NewDest);
+end;
+{$ENDIF}
+
+function TPSExec.SetVariantValue(dest, Src: Pointer; desttype, srctype: TPSTypeRec): Boolean;
+var
+ Tmp: TObject;
+ tt: TPSVariantPointer;
+begin
+ Result := True;
+ try
+ case desttype.BaseType of
+ btSet:
+ begin
+ if desttype = srctype then
+ Move(Src^, Dest^, TPSTypeRec_Set(desttype).aByteSize)
+ else
+ Result := False;
+ end;
+ btU8: tbtu8(Dest^) := PSGetUInt(Src, srctype);
+ btS8: tbts8(Dest^) := PSGetInt(Src, srctype);
+ btU16: tbtu16(Dest^) := PSGetUInt(Src, srctype);
+ btS16: tbts16(Dest^) := PSGetInt(Src, srctype);
+ btProcPtr:
+ begin
+ if srctype.BaseType = btPointer then
+ begin
+ srctype := PIFTypeRec(Pointer(IPointer(Src)+PointerSize)^);
+ Src := Pointer(Src^);
+ if (src = nil) or (srctype = nil) then raise Exception.Create(RPS_TypeMismatch);
+ end;
+ case srctype.BaseType of
+ btu32:
+ begin
+ Pointer(Dest^) := Pointer(Src^);
+ end;
+ btProcPtr:
+ begin
+ Pointer(Dest^) := Pointer(Src^);
+ Pointer(Pointer(IPointer(Dest)+PointerSize)^) := Pointer(Pointer(IPointer(Src)+PointerSize)^);
+ Pointer(Pointer(IPointer(Dest)+PointerSize2)^) := Pointer(Pointer(IPointer(Src)+PointerSize2)^);
+ end;
+ else raise Exception.Create(RPS_TypeMismatch);
+ end;
+ end;
+ btU32:
+ begin
+ if srctype.BaseType = btPointer then
+ begin
+ srctype := PIFTypeRec(Pointer(IPointer(Src)+PointerSize)^);
+ Src := Pointer(Src^);
+ if (src = nil) or (srctype = nil) then raise Exception.Create(RPS_TypeMismatch);
+ end;
+ case srctype.BaseType of
+ btU8: tbtu32(Dest^) := tbtu8(src^);
+ btS8: tbtu32(Dest^) := tbts8(src^);
+ btU16: tbtu32(Dest^) := tbtu16(src^);
+ btS16: tbtu32(Dest^) := tbts16(src^);
+ btU32: tbtu32(Dest^) := tbtu32(src^);
+ btS32: tbtu32(Dest^) := tbts32(src^);
+ {$IFNDEF PS_NOINT64} btS64: tbtu32(Dest^) := tbts64(src^);{$ENDIF}
+ btChar: tbtu32(Dest^) := Ord(tbtchar(Src^));
+ {$IFNDEF PS_NOWIDESTRING} btWideChar: tbtu32(Dest^) := Ord(tbtwidechar(Src^));{$ENDIF}
+ btVariant: tbtu32(Dest^) := Variant(src^);
+ else raise Exception.Create(RPS_TypeMismatch);
+ end;
+ end;
+ btS32:
+ begin
+ if srctype.BaseType = btPointer then
+ begin
+ srctype := PIFTypeRec(Pointer(IPointer(Src)+PointerSize)^);
+ Src := Pointer(Src^);
+ if (src = nil) or (srctype = nil) then raise Exception.Create(RPS_TypeMismatch);
+ end;
+ case srctype.BaseType of
+ btU8: tbts32(Dest^) := tbtu8(src^);
+ btS8: tbts32(Dest^) := tbts8(src^);
+ btU16: tbts32(Dest^) := tbtu16(src^);
+ btS16: tbts32(Dest^) := tbts16(src^);
+ btU32: tbts32(Dest^) := tbtu32(src^);
+ btS32: tbts32(Dest^) := tbts32(src^);
+ {$IFNDEF PS_NOINT64} btS64: tbts32(Dest^) := tbts64(src^);{$ENDIF}
+ btChar: tbts32(Dest^) := Ord(tbtchar(Src^));
+ {$IFNDEF PS_NOWIDESTRING} btWideChar: tbts32(Dest^) := Ord(tbtwidechar(Src^));{$ENDIF}
+ btVariant: tbts32(Dest^) := Variant(src^);
+ // nx change start - allow assignment of class
+ btClass: tbtu32(Dest^) := tbtu32(src^);
+ // nx change start
+ else raise Exception.Create(RPS_TypeMismatch);
+ end;
+ end;
+ {$IFNDEF PS_NOINT64}
+ btS64: tbts64(Dest^) := PSGetInt64(Src, srctype);
+ {$ENDIF}
+ btSingle:
+ begin
+ if srctype.BaseType = btPointer then
+ begin
+ srctype := PIFTypeRec(Pointer(IPointer(Src)+PointerSize)^);
+ Src := Pointer(Src^);
+ if (src = nil) or (srctype = nil) then raise Exception.Create(RPS_TypeMismatch);
+ end;
+ case srctype.BaseType of
+ btU8: tbtsingle(Dest^) := tbtu8(src^);
+ btS8: tbtsingle(Dest^) := tbts8(src^);
+ btU16: tbtsingle(Dest^) := tbtu16(src^);
+ btS16: tbtsingle(Dest^) := tbts16(src^);
+ btU32: tbtsingle(Dest^) := tbtu32(src^);
+ btS32: tbtsingle(Dest^) := tbts32(src^);
+ {$IFNDEF PS_NOINT64} btS64: tbtsingle(Dest^) := tbts64(src^);{$ENDIF}
+ btSingle: tbtsingle(Dest^) := tbtsingle(Src^);
+ btDouble: tbtsingle(Dest^) := tbtdouble(Src^);
+ btExtended: tbtsingle(Dest^) := tbtextended(Src^);
+ btCurrency: tbtsingle(Dest^) := tbtcurrency(Src^);
+ btVariant: tbtsingle(Dest^) := Variant(src^);
+ else raise Exception.Create(RPS_TypeMismatch);
+ end;
+ end;
+ btDouble:
+ begin
+ if srctype.BaseType = btPointer then
+ begin
+ srctype := PIFTypeRec(Pointer(IPointer(Src)+PointerSize)^);
+ Src := Pointer(Src^);
+ if (src = nil) or (srctype = nil) then raise Exception.Create(RPS_TypeMismatch);
+ end;
+ case srctype.BaseType of
+ btU8: tbtdouble(Dest^) := tbtu8(src^);
+ btS8: tbtdouble(Dest^) := tbts8(src^);
+ btU16: tbtdouble(Dest^) := tbtu16(src^);
+ btS16: tbtdouble(Dest^) := tbts16(src^);
+ btU32: tbtdouble(Dest^) := tbtu32(src^);
+ btS32: tbtdouble(Dest^) := tbts32(src^);
+ {$IFNDEF PS_NOINT64} btS64: tbtdouble(Dest^) := tbts64(src^);{$ENDIF}
+ btSingle: tbtdouble(Dest^) := tbtsingle(Src^);
+ btDouble: tbtdouble(Dest^) := tbtdouble(Src^);
+ btExtended: tbtdouble(Dest^) := tbtextended(Src^);
+ btCurrency: tbtdouble(Dest^) := tbtcurrency(Src^);
+ btVariant: tbtdouble(Dest^) := Variant(src^);
+ else raise Exception.Create(RPS_TypeMismatch);
+ end;
+
+ end;
+ btExtended:
+ begin
+ if srctype.BaseType = btPointer then
+ begin
+ srctype := PIFTypeRec(Pointer(IPointer(Src)+PointerSize)^);
+ Src := Pointer(Src^);
+ if (src = nil) or (srctype = nil) then raise Exception.Create(RPS_TypeMismatch);
+ end;
+ case srctype.BaseType of
+ btU8: tbtextended(Dest^) := tbtu8(src^);
+ btS8: tbtextended(Dest^) := tbts8(src^);
+ btU16: tbtextended(Dest^) := tbtu16(src^);
+ btS16: tbtextended(Dest^) := tbts16(src^);
+ btU32: tbtextended(Dest^) := tbtu32(src^);
+ btS32: tbtextended(Dest^) := tbts32(src^);
+ {$IFNDEF PS_NOINT64} btS64: tbtextended(Dest^) := tbts64(src^);{$ENDIF}
+ btSingle: tbtextended(Dest^) := tbtsingle(Src^);
+ btDouble: tbtextended(Dest^) := tbtdouble(Src^);
+ btExtended: tbtextended(Dest^) := tbtextended(Src^);
+ btCurrency: tbtextended(Dest^) := tbtcurrency(Src^);
+ btVariant: tbtextended(Dest^) := Variant(src^);
+ else raise Exception.Create(RPS_TypeMismatch);
+ end;
+ end;
+ btCurrency: tbtcurrency(Dest^) := PSGetCurrency(Src, srctype);
+ btPChar: pansichar(dest^) := pansichar(PSGetAnsiString(Src, srctype));
+ btString:
+ tbtstring(dest^) := PSGetAnsiString(Src, srctype);
+ btChar: tbtchar(dest^) := tbtchar(PSGetUInt(Src, srctype));
+ {$IFNDEF PS_NOWIDESTRING}
+ btWideString: tbtwidestring(dest^) := PSGetWideString(Src, srctype);
+ btUnicodeString: tbtUnicodeString(dest^) := PSGetUnicodeString(Src, srctype);
+ btWideChar: tbtwidechar(dest^) := widechar(PSGetUInt(Src, srctype));
+ {$ENDIF}
+ btStaticArray:
+ begin
+ if desttype <> srctype then
+ Result := False
+ else
+ CopyArrayContents(dest, Src, TPSTypeRec_StaticArray(desttype).Size, TPSTypeRec_StaticArray(desttype).ArrayType);
+ end;
+ btArray:
+ begin
+ if (srctype.BaseType = btStaticArray) and (TPSTypeRec_Array(desttype).ArrayType = TPSTypeRec_Array(srctype).ArrayType) then
+ begin
+ PSDynArraySetLength(Pointer(Dest^), desttype, TPSTypeRec_StaticArray(srctype).Size);
+ CopyArrayContents(Pointer(dest^), Src, TPSTypeRec_StaticArray(srctype).Size, TPSTypeRec_StaticArray(srctype).ArrayType);
+ end else if (srctype.BaseType = btvariant) and VarIsArray(Variant(src^)) then
+ Result := CreateArrayFromVariant(Self, dest, Variant(src^), desttype)
+ else if (desttype <> srctype) and not ((desttype.BaseType = btarray) and (srctype.BaseType = btArray)
+ and (TPSTypeRec_Array(desttype).ArrayType = TPSTypeRec_Array(srctype).ArrayType)) then
+ Result := False
+ else
+ CopyArrayContents(dest, src, 1, desttype);
+ end;
+ btRecord:
+ begin
+ if desttype <> srctype then
+ Result := False
+ else
+ CopyArrayContents(dest, Src, 1, desttype);
+ end;
+ btVariant:
+ begin
+{$IFNDEF PS_NOINTERFACES}
+ if srctype.ExportName = 'IDISPATCH' then
+ begin
+ {$IFDEF DELPHI3UP}
+ Variant(Dest^) := IDispatch(Src^);
+ {$ELSE}
+ AssignVariantFromIDispatch(Variant(Dest^), IDispatch(Src^));
+ {$ENDIF}
+ end else
+{$ENDIF}
+ if srctype.BaseType = btVariant then
+ variant(Dest^) := variant(src^)
+ else
+ begin
+ tt.VI.FType := FindType2(btPointer);
+ tt.DestType := srctype;
+ tt.DataDest := src;
+ tt.FreeIt := False;
+ Result := PIFVariantToVariant(@tt, variant(dest^));
+ end;
+ end;
+ btClass:
+ begin
+ if srctype.BaseType = btClass then
+ TObject(Dest^) := TObject(Src^)
+ else
+ // nx change start
+ if (srctype.BaseType in [btS32, btU32]) then
+ TbtU32(Dest^) := TbtU32(Src^)
+ else
+ // nx change end
+ Result := False;
+ end;
+{$IFNDEF PS_NOINTERFACES}
+ btInterface:
+ begin
+ if Srctype.BaseType = btVariant then
+ begin
+ if desttype.ExportName = 'IDISPATCH' then
+ begin
+ {$IFDEF Delphi3UP}
+ IDispatch(Dest^) := IDispatch(Variant(Src^));
+ {$ELSE}
+ AssignIDispatchFromVariant(IDispatch(Dest^), Variant(Src^));
+ {$ENDIF}
+ end else
+ Result := False;
+{$IFDEF Delphi3UP}
+ end else
+ if srctype.BaseType = btClass then
+ begin
+ if (TObject(Src^) = nil) or not TObject(Src^).GetInterface(TPSTypeRec_Interface(desttype).Guid, IUnknown(Dest^)) then
+ begin
+ Result := false;
+ Cmd_Err(erInterfaceNotSupported);
+ exit;
+ end;
+{$ENDIF}
+ end else if srctype.BaseType = btInterface then
+ begin
+ {$IFNDEF Delphi3UP}
+ if IUnknown(Dest^) <> nil then
+ begin
+ IUnknown(Dest^).Release;
+ IUnknown(Dest^) := nil;
+ end;
+ {$ENDIF}
+ IUnknown(Dest^) := IUnknown(Src^);
+ {$IFNDEF Delphi3UP}
+ if IUnknown(Dest^) <> nil then
+ IUnknown(Dest^).AddRef;
+ {$ENDIF}
+ end else
+ Result := False;
+ end;
+{$ENDIF}
+ else begin
+ Result := False;
+ end;
+ end;
+ if Result = False then
+ CMD_Err(ErTypeMismatch);
+ except
+ {$IFDEF DELPHI6UP}
+ Tmp := AcquireExceptionObject;
+ {$ELSE}
+ if RaiseList <> nil then
+ begin
+ Tmp := Exception(PRaiseFrame(RaiseList)^.ExceptObject);
+ PRaiseFrame(RaiseList)^.ExceptObject := nil;
+ end else
+ Tmp := nil;
+ {$ENDIF}
+ if Tmp <> nil then
+ begin
+ if Tmp is EPSException then
+ begin
+ Result := False;
+ ExceptionProc(EPSException(tmp).ProcNo, EPSException(tmp).ProcPos, erCustomError, tbtString(EPSException(tmp).Message), nil);
+ exit;
+ end else
+ if Tmp is EDivByZero then
+ begin
+ Result := False;
+ CMD_Err3(erDivideByZero, '', Tmp);
+ Exit;
+ end;
+ if Tmp is EZeroDivide then
+ begin
+ Result := False;
+ CMD_Err3(erDivideByZero, '', Tmp);
+ Exit;
+ end;
+ if Tmp is EMathError then
+ begin
+ Result := False;
+ CMD_Err3(erMathError, '', Tmp);
+ Exit;
+ end;
+ end;
+ if (tmp <> nil) and (Tmp is Exception) then
+ CMD_Err3(erException, tbtString(Exception(Tmp).Message), Tmp)
+ else
+ CMD_Err3(erException, '', Tmp);
+ Result := False;
+ end;
+end;
+
+function SpecImport(Sender: TPSExec; p: TPSExternalProcRec; Tag: Pointer): Boolean; forward;
+
+
+function Class_IS(Self: TPSExec; Obj: TObject; var2type: TPSTypeRec): Boolean;
+var
+ R: TPSRuntimeClassImporter;
+ cc: TPSRuntimeClass;
+begin
+ if Obj = nil then
+ begin
+ Result := false;
+ exit;
+ end;
+ r := Self.FindSpecialProcImport(SpecImport);
+ if R = nil then
+ begin
+ Result := false;
+ exit;
+ end;
+ cc := r.FindClass(var2type.ExportName);
+ if cc = nil then
+ begin
+ result := false;
+ exit;
+ end;
+ try
+ Result := Obj is cc.FClass;
+ except
+ Result := false;
+ end;
+end;
+
+type
+ TVariantArray = array of Variant;
+ PVariantArray = ^TVariantArray;
+function VariantInArray(var1: Pointer; var1Type: TPSTypeRec; var2: PVariantArray): Boolean;
+var
+ lDest: Variant;
+ i: Integer;
+begin
+ IntPIFVariantToVariant(var1, var1Type, lDest);
+ result := false;
+ for i := 0 to Length(var2^) -1 do begin
+ if var2^[i] = lDest then begin
+ result := true;
+ break;
+ end;
+ end;
+end;
+
+
+function TPSExec.DoBooleanCalc(var1, Var2, into: Pointer; var1Type, var2type, intotype: TPSTypeRec; Cmd: Cardinal): Boolean;
+var
+ b: Boolean;
+ Tmp: TObject;
+ tvar: Variant;
+
+
+ procedure SetBoolean(b: Boolean; var Ok: Boolean);
+ begin
+ Ok := True;
+ case IntoType.BaseType of
+ btU8: tbtu8(Into^):= Cardinal(b);
+ btS8: tbts8(Into^) := Longint(b);
+ btU16: tbtu16(Into^) := Cardinal(b);
+ btS16: tbts16(Into^) := Longint(b);
+ btU32: tbtu32(Into^) := Cardinal(b);
+ btS32: tbts32(Into^) := Longint(b);
+ btVariant: Variant(Into^) := b;
+ else begin
+ CMD_Err(ErTypeMismatch);
+ Ok := False;
+ end;
+ end;
+ end;
+begin
+ Result := true;
+ try
+ case Cmd of
+ 0: begin { >= }
+ case var1Type.BaseType of
+ btU8:
+ if (var2Type.BaseType = btString) or (Var2Type.BaseType = btPChar) then
+ b := tbtchar(tbtu8(var1^)) >= PSGetAnsiString(Var2, var2type)
+ else
+ b := tbtu8(var1^) >= PSGetUInt(Var2, var2type);
+ btS8: b := tbts8(var1^) >= PSGetInt(Var2, var2type);
+ btU16: b := tbtu16(var1^) >= PSGetUInt(Var2, var2type);
+ btS16: b := tbts16(var1^) >= PSGetInt(Var2, var2type);
+ btU32: b := tbtu32(var1^) >= PSGetUInt(Var2, var2type);
+ btS32:
+ begin
+ if var2type.BaseType = btPointer then
+ begin
+ var2type := PIFTypeRec(Pointer(IPointer(var2)+PointerSize)^);
+ var2 := Pointer(var2^);
+ if (var2 = nil) or (var2type = nil) then raise Exception.Create(RPS_TypeMismatch);
+ end;
+ case var2type.BaseType of
+ btU8: b := tbts32(var1^) >= tbtu8(Var2^);
+ btS8: b := tbts32(var1^) >= tbts8(Var2^);
+ btU16: b := tbts32(var1^) >= tbtu16(Var2^);
+ btS16: b := tbts32(var1^) >= tbts16(Var2^);
+ btU32: b := tbts32(var1^) >= Longint(tbtu32(Var2^));
+ btS32: b := tbts32(var1^) >= tbts32(Var2^);
+ btDouble: b := PSGetReal(Var1, var1type) >= tbtdouble(var2^);
+ btSingle: B := psGetReal(Var1, var1Type) >= tbtsingle(var2^);
+ btExtended: B := psGetReal(Var1, var1Type) >= tbtExtended(var2^);
+ {$IFNDEF PS_NOINT64} btS64: b := tbts32(var1^) >= tbts64(Var2^);{$ENDIF}
+ btChar: b := tbts32(var1^) >= Ord(tbtchar(Var2^));
+ {$IFNDEF PS_NOWIDESTRING} btWideChar: b := tbts32(var1^) >= Ord(tbtwidechar(Var2^));{$ENDIF}
+ btVariant: b := tbts32(var1^) >= Variant(Var2^);
+ else raise Exception.Create(RPS_TypeMismatch);
+ end;
+ end;
+ btSingle: b := tbtsingle(var1^) >= PSGetReal(Var2, var2type);
+ btDouble: b := tbtdouble(var1^) >= PSGetReal(Var2, var2type);
+ btCurrency: b := tbtcurrency(var1^) >= PSGetCurrency(Var2, var2type);
+ btExtended: b := tbtextended(var1^) >= PSGetReal(Var2, var2type);
+ {$IFNDEF PS_NOINT64}
+ btS64: b := tbts64(var1^) >= PSGetInt64(Var2, var2type);
+ {$ENDIF}
+ btPChar,btString: b := tbtstring(var1^) >= PSGetAnsiString(Var2, var2type);
+ btChar: b := tbtchar(var1^) >= PSGetAnsiString(Var2, var2type);
+ {$IFNDEF PS_NOWIDESTRING}
+ btWideChar: b := tbtwidechar(var1^) >= PSGetWideString(Var2, var2type);
+ btWideString: b := tbtwidestring(var1^) >= PSGetWideString(Var2, var2type);
+ btUnicodeString: b := tbtUnicodestring(var1^) >= PSGetUnicodeString(Var2, var2type);
+ {$ENDIF}
+ btVariant:
+ begin
+ if not IntPIFVariantToVariant(var2, var2type, tvar) then
+ begin
+ Result := false;
+ end else
+ b := Variant(var1^) >= tvar;
+ end;
+ btSet:
+ begin
+ if var1Type = var2Type then
+ begin
+ Set_Subset(var2, var1, TPSTypeRec_Set(var1Type).aByteSize, b);
+ end else result := False;
+ end;
+ else begin
+ CMD_Err(ErTypeMismatch);
+ exit;
+ end;
+ end;
+ if not Result then begin
+ CMD_Err(ErTypeMismatch);
+ exit;
+ end;
+ SetBoolean(b, Result);
+ end;
+ 1: begin { <= }
+ case var1Type.BaseType of
+ btU8:
+ if (var2Type.BaseType = btString) or (Var2Type.BaseType = btPChar) then
+ b := tbtchar(tbtu8(var1^)) <= PSGetAnsiString(Var2, var2type)
+ else
+ b := tbtu8(var1^) <= PSGetUInt(Var2, var2type);
+ btS8: b := tbts8(var1^) <= PSGetInt(Var2, var2type);
+ btU16: b := tbtu16(var1^) <= PSGetUInt(Var2, var2type);
+ btS16: b := tbts16(var1^) <= PSGetInt(Var2, var2type);
+ btU32: b := tbtu32(var1^) <= PSGetUInt(Var2, var2type);
+ btS32:
+ begin
+ if var2type.BaseType = btPointer then
+ begin
+ var2type := PIFTypeRec(Pointer(IPointer(var2)+PointerSize)^);
+ var2 := Pointer(var2^);
+ if (var2 = nil) or (var2type = nil) then raise Exception.Create(RPS_TypeMismatch);
+ end;
+ case var2type.BaseType of
+ btU8: b := tbts32(var1^) <= tbtu8(Var2^);
+ btS8: b := tbts32(var1^) <= tbts8(Var2^);
+ btU16: b := tbts32(var1^) <= tbtu16(Var2^);
+ btS16: b := tbts32(var1^) <= tbts16(Var2^);
+ btU32: b := tbts32(var1^) <= Longint(tbtu32(Var2^));
+ btS32: b := tbts32(var1^) <= tbts32(Var2^);
+ btDouble: b := PSGetReal(Var1, var1type) <= tbtdouble(var2^);
+ btSingle: B := psGetReal(Var1, var1Type) <= tbtsingle(var2^);
+ btExtended: B := psGetReal(Var1, var1Type) <= tbtExtended(var2^);
+ {$IFNDEF PS_NOINT64} btS64: b := tbts32(var1^) <= tbts64(Var2^);{$ENDIF}
+ btChar: b := tbts32(var1^) <= Ord(tbtchar(Var2^));
+ {$IFNDEF PS_NOWIDESTRING} btWideChar: b := tbts32(var1^) <= Ord(tbtwidechar(Var2^));{$ENDIF}
+ btVariant: b := tbts32(var1^) <= Variant(Var2^);
+ else raise Exception.Create(RPS_TypeMismatch);
+ end;
+ end; btSingle: b := tbtsingle(var1^) <= PSGetReal(Var2, var2type);
+ btCurrency: b := tbtcurrency(var1^) <= PSGetCurrency(Var2, var2type);
+ btDouble: b := tbtdouble(var1^) <= PSGetReal(Var2, var2type);
+ btExtended: b := tbtextended(var1^) <= PSGetReal(Var2, var2type);
+ {$IFNDEF PS_NOINT64}
+ btS64: b := tbts64(var1^) <= PSGetInt64(Var2, var2type);
+ {$ENDIF}
+ btPChar,btString: b := tbtstring(var1^) <= PSGetAnsiString(Var2, var2type);
+ btChar: b := tbtchar(var1^) <= PSGetAnsiString(Var2, var2type);
+ {$IFNDEF PS_NOWIDESTRING}
+ btWideChar: b := tbtwidechar(var1^) <= PSGetWideString(Var2, var2type);
+ btWideString: b := tbtwidestring(var1^) <= PSGetWideString(Var2, var2type);
+ btUnicodeString: b := tbtUnicodestring(var1^) <= PSGetUnicodeString(Var2, var2type);
+ {$ENDIF}
+ btVariant:
+ begin
+ if not IntPIFVariantToVariant(var2, var2type, tvar) then
+ begin
+ Result := false;
+ end else
+ b := Variant(var1^) <= tvar;
+ end;
+ btSet:
+ begin
+ if var1Type = var2Type then
+ begin
+ Set_Subset(var1, var2, TPSTypeRec_Set(var1Type).aByteSize, b);
+ end else result := False;
+ end;
+ else begin
+ CMD_Err(ErTypeMismatch);
+ exit;
+ end;
+ end;
+ if not Result then begin
+ CMD_Err(erTypeMismatch);
+ exit;
+ end;
+ SetBoolean(b, Result);
+ end;
+ 2: begin { > }
+ case var1Type.BaseType of
+ btU8:
+ if (var2Type.BaseType = btString) or (Var2Type.BaseType = btPChar) then
+ b := tbtchar(tbtu8(var1^)) > PSGetAnsiString(Var2, var2type)
+ else
+ b := tbtu8(var1^) > PSGetUInt(Var2, var2type);
+ btS8: b := tbts8(var1^) > PSGetInt(Var2, var2type);
+ btU16: b := tbtu16(var1^) > PSGetUInt(Var2, var2type);
+ btS16: b := tbts16(var1^) > PSGetInt(Var2, var2type);
+ btU32: b := tbtu32(var1^) > PSGetUInt(Var2, var2type);
+ btS32:
+ begin
+ if var2type.BaseType = btPointer then
+ begin
+ var2type := PIFTypeRec(Pointer(IPointer(var2)+PointerSize)^);
+ var2 := Pointer(var2^);
+ if (var2 = nil) or (var2type = nil) then raise Exception.Create(RPS_TypeMismatch);
+ end;
+ case var2type.BaseType of
+ btU8: b := tbts32(var1^) > tbtu8(Var2^);
+ btS8: b := tbts32(var1^) > tbts8(Var2^);
+ btU16: b := tbts32(var1^) > tbtu16(Var2^);
+ btS16: b := tbts32(var1^) > tbts16(Var2^);
+ btU32: b := tbts32(var1^) > Longint(tbtu32(Var2^));
+ btS32: b := tbts32(var1^) > tbts32(Var2^);
+ btDouble: b := PSGetReal(Var1, var1type) > tbtdouble(var2^);
+ btSingle: B := psGetReal(Var1, var1Type) > tbtsingle(var2^);
+ btExtended: B := psGetReal(Var1, var1Type) > tbtExtended(var2^);
+ {$IFNDEF PS_NOINT64} btS64: b := tbts32(var1^) > tbts64(Var2^);{$ENDIF}
+ btChar: b := tbts32(var1^) > Ord(tbtchar(Var2^));
+ {$IFNDEF PS_NOWIDESTRING} btWideChar: b := tbts32(var1^) = Ord(tbtwidechar(Var2^));{$ENDIF}
+ btVariant: b := tbts32(var1^) > Variant(Var2^);
+ else raise Exception.Create(RPS_TypeMismatch);
+ end;
+ end; btSingle: b := tbtsingle(var1^) > PSGetReal(Var2, var2type);
+ btDouble: b := tbtdouble(var1^) > PSGetReal(Var2, var2type);
+ btExtended: b := tbtextended(var1^) > PSGetReal(Var2, var2type);
+ btCurrency: b := tbtcurrency(var1^) > PSGetCurrency(Var2, var2type);
+ {$IFNDEF PS_NOINT64}
+ btS64: b := tbts64(var1^) > PSGetInt64(Var2, var2type);
+ {$ENDIF}
+ btPChar,btString: b := tbtstring(var1^) > PSGetAnsiString(Var2, var2type);
+ btChar: b := tbtchar(var1^) > PSGetAnsiString(Var2, var2type);
+ {$IFNDEF PS_NOWIDESTRING}
+ btWideChar: b := tbtwidechar(var1^) > PSGetWideString(Var2, var2type);
+ btWideString: b := tbtwidestring(var1^) > PSGetWideString(Var2, var2type);
+ btUnicodeString: b := tbtUnicodestring(var1^) > PSGetUnicodeString(Var2, var2type);
+ {$ENDIF}
+ btVariant:
+ begin
+ if not IntPIFVariantToVariant(var2, var2type, tvar) then
+ begin
+ Result := false;
+ end else
+ b := Variant(var1^) > tvar;
+ end;
+ else begin
+ CMD_Err(erTypeMismatch);
+ exit;
+ end;
+ end;
+ if not Result then begin
+ CMD_Err(erTypeMismatch);
+ exit;
+ end;
+ SetBoolean(b, Result);
+ end;
+ 3: begin { < }
+ case var1Type.BaseType of
+ btU8:
+ if (var2Type.BaseType = btString) or (Var2Type.BaseType = btPChar) then
+ b := tbtchar(tbtu8(var1^)) < PSGetAnsiString(Var2, var2type)
+ else
+ b := tbtu8(var1^) < PSGetUInt(Var2, var2type);
+ btS8: b := tbts8(var1^) < PSGetInt(Var2, var2type);
+ btU16: b := tbtu16(var1^) < PSGetUInt(Var2, var2type);
+ btS16: b := tbts16(var1^) < PSGetInt(Var2, var2type);
+ btU32: b := tbtu32(var1^) < PSGetUInt(Var2, var2type);
+ btS32:
+ begin
+ if var2type.BaseType = btPointer then
+ begin
+ var2type := PIFTypeRec(Pointer(IPointer(var2)+PointerSize)^);
+ var2 := Pointer(var2^);
+ if (var2 = nil) or (var2type = nil) then raise Exception.Create(RPS_TypeMismatch);
+ end;
+ case var2type.BaseType of
+ btU8: b := tbts32(var1^) < tbtu8(Var2^);
+ btS8: b := tbts32(var1^) < tbts8(Var2^);
+ btU16: b := tbts32(var1^) < tbtu16(Var2^);
+ btS16: b := tbts32(var1^) < tbts16(Var2^);
+ btU32: b := tbts32(var1^) < Longint(tbtu32(Var2^));
+ btS32: b := tbts32(var1^) < tbts32(Var2^);
+ btDouble: b := PSGetReal(Var1, var1type) < tbtdouble(var2^);
+ btSingle: B := psGetReal(Var1, var1Type) < tbtsingle(var2^);
+ btExtended: B := psGetReal(Var1, var1Type) < tbtExtended(var2^);
+ {$IFNDEF PS_NOINT64} btS64: b := tbts32(var1^) < tbts64(Var2^);{$ENDIF}
+ btChar: b := tbts32(var1^) < Ord(tbtchar(Var2^));
+ {$IFNDEF PS_NOWIDESTRING} btWideChar: b := tbts32(var1^) < Ord(tbtwidechar(Var2^));{$ENDIF}
+ btVariant: b := tbts32(var1^) < Variant(Var2^);
+ else raise Exception.Create(RPS_TypeMismatch);
+ end;
+ end; btSingle: b := tbtsingle(var1^) < PSGetReal(Var2, var2type);
+ btDouble: b := tbtdouble(var1^) < PSGetReal(Var2, var2type);
+ btCurrency: b := tbtcurrency(var1^) < PSGetCurrency(Var2, var2type);
+ btExtended: b := tbtextended(var1^) < PSGetReal(Var2, var2type);
+ {$IFNDEF PS_NOINT64}
+ btS64: b := tbts64(var1^) < PSGetInt64(Var2, var2type);
+ {$ENDIF}
+ btPChar,btString: b := tbtstring(var1^) < PSGetAnsiString(Var2, var2type);
+ btChar: b := tbtchar(var1^) < PSGetAnsiString(Var2, var2type);
+ {$IFNDEF PS_NOWIDESTRING}
+ btWideChar: b := tbtwidechar(var1^) < PSGetWideString(Var2, var2type);
+ btWideString: b := tbtwidestring(var1^) < PSGetWideString(Var2, var2type);
+ btUnicodeString: b := tbtUnicodestring(var1^) < PSGetUnicodeString(Var2, var2type);
+ {$ENDIF}
+ btVariant:
+ begin
+ if not IntPIFVariantToVariant(var2, var2type, tvar) then
+ begin
+ Result := false;
+ end else
+ b := Variant(var1^) < tvar;
+ end;
+ else begin
+ CMD_Err(erTypeMismatch);
+ exit;
+ end;
+ end;
+ if not Result then begin
+ CMD_Err(erTypeMismatch);
+ exit;
+ end;
+ SetBoolean(b, Result);
+ end;
+ 4: begin { <> }
+ case var1Type.BaseType of
+ btInterface:
+ begin
+ if var2Type.BaseType = btInterface then
+ b := Pointer(var1^) <> Pointer(var2^) // no need to cast it to IUnknown
+ else
+ Result := false;
+ end;
+ btClass:
+ begin
+ if var2Type.BaseType = btclass then
+ b := TObject(var1^) <> TObject(var2^)
+ else
+ Result := false;
+ end;
+ btU8:
+ if (var2Type.BaseType = btString) or (Var2Type.BaseType = btPChar) then
+ b := tbtchar(tbtu8(var1^)) <> PSGetAnsiString(Var2, var2type)
+ else
+ b := tbtu8(var1^) <> PSGetUInt(Var2, var2type);
+ btS8: b := tbts8(var1^) <> PSGetInt(Var2, var2type);
+ btU16: b := tbtu16(var1^) <> PSGetUInt(Var2, var2type);
+ btS16: b := tbts16(var1^) <> PSGetInt(Var2, var2type);
+ btProcPtr:
+ begin
+ if Pointer(Var1^) = Pointer(Var2^) then
+ begin
+ if Longint(Var1^) = 0 then
+ b := ((Pointer(Pointer(IPointer(Var1)+PointerSize2)^) <> Pointer(Pointer(IPointer(Var2)+PointerSize2)^)) or
+ (Pointer(Pointer(IPointer(Var1)+PointerSize2)^) <> Pointer(Pointer(IPointer(Var2)+PointerSize2)^)))
+ else
+ b := False;
+ end else b := True;
+ end;
+ btU32: b := tbtu32(var1^) <> PSGetUInt(Var2, var2type);
+ btS32:
+ begin
+ if var2type.BaseType = btPointer then
+ begin
+ var2type := PIFTypeRec(Pointer(IPointer(var2)+PointerSize)^);
+ var2 := Pointer(var2^);
+ if (var2 = nil) or (var2type = nil) then raise Exception.Create(RPS_TypeMismatch);
+ end;
+ case var2type.BaseType of
+ btU8: b := tbts32(var1^) <> tbtu8(Var2^);
+ btS8: b := tbts32(var1^) <> tbts8(Var2^);
+ btU16: b := tbts32(var1^) <> tbtu16(Var2^);
+ btS16: b := tbts32(var1^) <> tbts16(Var2^);
+ btProcPtr, btU32: b := tbts32(var1^)<> Longint(tbtu32(Var2^));
+ btS32: b := tbts32(var1^) <> tbts32(Var2^);
+ btDouble: b := PSGetReal(Var1, var1type) <> tbtdouble(var2^);
+ btSingle: B := psGetReal(Var1, var1Type) <> tbtsingle(var2^);
+ btExtended: B := psGetReal(Var1, var1Type) <> tbtExtended(var2^);
+ {$IFNDEF PS_NOINT64} btS64: b := tbts32(var1^) <> tbts64(Var2^);{$ENDIF}
+ btChar: b := tbts32(var1^) <> Ord(tbtchar(Var2^));
+ {$IFNDEF PS_NOWIDESTRING} btWideChar: b := tbts32(var1^) <> Ord(tbtwidechar(Var2^));{$ENDIF}
+ btVariant: b := tbts32(var1^) <> Variant(Var2^);
+ else raise Exception.Create(RPS_TypeMismatch);
+ end;
+ end; btSingle: b := tbtsingle(var1^) <> PSGetReal(Var2, var2type);
+ btDouble: b := tbtdouble(var1^) <> PSGetReal(Var2, var2type);
+ btExtended: b := tbtextended(var1^) <> PSGetReal(Var2, var2type);
+ btCurrency: b := tbtcurrency(var1^) <> PSGetCurrency(Var2, var2type);
+ btPChar,btString: b := tbtstring(var1^) <> PSGetAnsiString(Var2, var2type);
+ {$IFNDEF PS_NOINT64}
+ btS64: b := tbts64(var1^) <> PSGetInt64(Var2, var2type);
+ {$ENDIF}
+ btChar: b := tbtchar(var1^) <> PSGetAnsiString(Var2, var2type);
+ {$IFNDEF PS_NOWIDESTRING}
+ btWideChar: b := tbtwidechar(var1^) <> PSGetWideString(Var2, var2type);
+ btWideString: b := tbtwidestring(var1^) <> PSGetWideString(Var2, var2type);
+ btUnicodeString: b := tbtUnicodeString(var1^) <> PSGetUnicodeString(Var2, var2type);
+ {$ENDIF}
+ btVariant:
+ begin
+ if not IntPIFVariantToVariant(var2, var2type, tvar) then
+ begin
+ Result := false;
+ end else
+ b := Variant(var1^) <> tvar;
+ end;
+ btSet:
+ begin
+ if var1Type = var2Type then
+ begin
+ Set_Equal(var1, var2, TPSTypeRec_Set(var1Type).aByteSize, b);
+ b := not b;
+ end else result := False;
+ end;
+ btRecord:
+ begin
+ if var1Type = var2Type then
+ begin
+ Set_Equal(var1, var2, TPSTypeRec_Record(var1Type).RealSize, b);
+ b := not b;
+ end else result := False;
+ end
+
+ else begin
+ CMD_Err(erTypeMismatch);
+ exit;
+ end;
+ end;
+ if not Result then begin
+ CMD_Err(erTypeMismatch);
+ exit;
+ end;
+ SetBoolean(b, Result);
+ end;
+ 5: begin { = }
+ case var1Type.BaseType of
+ btInterface:
+ begin
+ if var2Type.BaseType = btInterface then
+ b := Pointer(var1^) = Pointer(var2^) // no need to cast it to IUnknown
+ else
+ Result := false;
+ end;
+ btClass:
+ begin
+ if var2Type.BaseType = btclass then
+ b := TObject(var1^) = TObject(var2^)
+ else
+ Result := false;
+ end;
+ btU8:
+ if (var2Type.BaseType = btString) or (Var2Type.BaseType = btPChar) then
+ b := tbtchar(tbtu8(var1^)) = PSGetAnsiString(Var2, var2type)
+ else
+ b := tbtu8(var1^) = PSGetUInt(Var2, var2type);
+ btS8: b := tbts8(var1^) = PSGetInt(Var2, var2type);
+ btU16: b := tbtu16(var1^) = PSGetUInt(Var2, var2type);
+ btS16: b := tbts16(var1^) = PSGetInt(Var2, var2type);
+ btU32: b := tbtu32(var1^) = PSGetUInt(Var2, var2type);
+ btProcPtr:
+ begin
+ if Pointer(Var1^) = Pointer(Var2^) then
+ begin
+ if Longint(Var1^) = 0 then
+ b := ((Pointer(Pointer(IPointer(Var1)+PointerSize2)^) = Pointer(Pointer(IPointer(Var2)+PointerSize2)^)) and
+ (Pointer(Pointer(IPointer(Var1)+PointerSize2)^) = Pointer(Pointer(IPointer(Var2)+PointerSize2)^)))
+ else
+ b := True;
+ end else b := False;
+ end;
+ btS32:
+ begin
+ if var2type.BaseType = btPointer then
+ begin
+ var2type := PIFTypeRec(Pointer(IPointer(var2)+PointerSize)^);
+ var2 := Pointer(var2^);
+ if (var2 = nil) or (var2type = nil) then raise Exception.Create(RPS_TypeMismatch);
+ end;
+ case var2type.BaseType of
+ btU8: b := tbts32(var1^) = tbtu8(Var2^);
+ btS8: b := tbts32(var1^) = tbts8(Var2^);
+ btU16: b := tbts32(var1^) = tbtu16(Var2^);
+ btS16: b := tbts32(var1^) = tbts16(Var2^);
+ btProcPtr, btU32: b := tbts32(var1^) = Longint(tbtu32(Var2^));
+ btS32: b := tbts32(var1^) = tbts32(Var2^);
+ btDouble: b := PSGetReal(Var1, var1type) = tbtdouble(var2^);
+ btSingle: B := psGetReal(Var1, var1Type) = tbtsingle(var2^);
+ btExtended: B := psGetReal(Var1, var1Type) = tbtExtended(var2^);
+ {$IFNDEF PS_NOINT64} btS64: b := tbts32(var1^) = tbts64(Var2^);{$ENDIF}
+ btChar: b := tbts32(var1^) = Ord(tbtchar(Var2^));
+ {$IFNDEF PS_NOWIDESTRING} btWideChar: b := tbts32(var1^) = Ord(tbtwidechar(Var2^));{$ENDIF}
+ btVariant: b := tbts32(var1^) = Variant(Var2^);
+ else raise Exception.Create(RPS_TypeMismatch);
+ end;
+ end; btSingle: b := tbtsingle(var1^) = PSGetReal(Var2, var2type);
+ btDouble: b := tbtdouble(var1^) = PSGetReal(Var2, var2type);
+ btExtended: b := tbtextended(var1^) = PSGetReal(Var2, var2type);
+ btCurrency: b := tbtcurrency(var1^) = PSGetCurrency(Var2, var2type);
+ btPchar, btString: b := tbtstring(var1^) = PSGetAnsiString(Var2, var2type);
+ {$IFNDEF PS_NOINT64}
+ btS64: b := tbts64(var1^) = PSGetInt64(Var2, var2type);
+ {$ENDIF}
+ btChar: b := tbtchar(var1^) = PSGetAnsiString(Var2, var2type);
+ {$IFNDEF PS_NOWIDESTRING}
+ btWideChar: b := tbtwidechar(var1^) = PSGetWideString(Var2, var2type);
+ btWideString: b := tbtwidestring(var1^) = PSGetWideString(Var2, var2type);
+ btUnicodeString: b := tbtUnicodestring(var1^) = PSGetUnicodeString(Var2, var2type);
+ {$ENDIF}
+ btVariant:
+ begin
+ if not IntPIFVariantToVariant(var2, var2type, tvar) then
+ begin
+ Result := false;
+ end else
+ b := Variant(var1^) = tvar;
+ end;
+ btSet:
+ begin
+ if var1Type = var2Type then
+ begin
+ Set_Equal(var1, var2, TPSTypeRec_Set(var1Type).aByteSize, b);
+ end else result := False;
+ end;
+ btRecord:
+ begin
+ if var1Type = var2Type then
+ begin
+ Set_Equal(var1, var2, TPSTypeRec_Record(var1Type).RealSize, b);
+ end else result := False;
+ end
+ else begin
+ CMD_Err(erTypeMismatch);
+ exit;
+ end;
+ end;
+ if not Result then begin
+ CMD_Err(erTypeMismatch);
+ exit;
+ end;
+ SetBoolean(b, Result);
+ end;
+ 6: begin { in }
+ if (var2Type.BaseType = btArray) and (TPSTypeRec_Array(var2type).ArrayType.BaseType = btVariant) then
+ begin
+ b := VariantInArray(var1, var1Type, var2);
+ SetBoolean(b, Result);
+ end else
+ if var2Type.BaseType = btSet then
+ begin
+ Cmd := PSGetUInt(var1, var1type);
+ if not Result then
+ begin
+ CMD_Err(erTypeMismatch);
+ exit;
+ end;
+ if Cmd >= Cardinal(TPSTypeRec_Set(var2Type).aBitSize) then
+ begin
+ cmd_Err(erOutofRecordRange);
+ Result := False;
+ Exit;
+ end;
+ Set_membership(Cmd, var2, b);
+ SetBoolean(b, Result);
+ end else
+ begin
+ CMD_Err(erTypeMismatch);
+ exit;
+ end;
+ end;
+ 7:
+ begin // is
+ case var1Type.BaseType of
+ btClass:
+ begin
+ if var2type.BaseType <> btU32 then
+ Result := False
+ else
+ begin
+ var2type := FTypes[tbtu32(var2^)];
+ if (var2type = nil) or (var2type.BaseType <> btClass) then
+ Result := false
+ else
+ begin
+ Setboolean(Class_IS(Self, TObject(var1^), var2type), Result);
+ end;
+ end;
+ end;
+ else begin
+ CMD_Err(erTypeMismatch);
+ exit;
+ end;
+ end;
+ if not Result then begin
+ CMD_Err(erTypeMismatch);
+ exit;
+ end;
+ end;
+ else begin
+ Result := False;
+ CMD_Err(erInvalidOpcodeParameter);
+ exit;
+ end;
+ end;
+ except
+ {$IFDEF DELPHI6UP}
+ Tmp := AcquireExceptionObject;
+ {$ELSE}
+ if RaiseList <> nil then
+ begin
+ Tmp := Exception(PRaiseFrame(RaiseList)^.ExceptObject);
+ PRaiseFrame(RaiseList)^.ExceptObject := nil;
+ end else
+ Tmp := nil;
+ {$ENDIF}
+ if Tmp <> nil then
+ begin
+ if Tmp is EPSException then
+ begin
+ Result := False;
+ ExceptionProc(EPSException(tmp).ProcNo, EPSException(tmp).ProcPos, erCustomError, tbtString(EPSException(tmp).Message), nil);
+ exit;
+ end else
+ if Tmp is EDivByZero then
+ begin
+ Result := False;
+ CMD_Err3(erDivideByZero, '', Tmp);
+ Exit;
+ end;
+ if Tmp is EZeroDivide then
+ begin
+ Result := False;
+ CMD_Err3(erDivideByZero, '', Tmp);
+ Exit;
+ end;
+ if Tmp is EMathError then
+ begin
+ Result := False;
+ CMD_Err3(erMathError, '', Tmp);
+ Exit;
+ end;
+ end;
+ if (tmp <> nil) and (Tmp is Exception) then
+ CMD_Err3(erException, tbtString(Exception(Tmp).Message), Tmp)
+ else
+ CMD_Err3(erException, '', Tmp);
+ Result := False;
+ end;
+end;
+
+function VarIsFloat(const V: Variant): Boolean;
+begin
+ Result := VarType(V) in [varSingle, varDouble, varCurrency];
+end;
+
+function TPSExec.DoCalc(var1, Var2: Pointer; var1Type, var2type: TPSTypeRec; CalcType: Cardinal): Boolean;
+ { var1=dest, var2=src }
+var
+ Tmp: TObject;
+ tvar: Variant;
+begin
+ try
+ Result := True;
+ case CalcType of
+ 0: begin { + }
+ case var1Type.BaseType of
+ btU8: tbtU8(var1^) := tbtU8(var1^) + PSGetUInt(Var2, var2type);
+ btS8: tbts8(var1^) := tbts8(var1^) + PSGetInt(Var2, var2type);
+ btU16: tbtU16(var1^) := tbtU16(var1^) + PSGetUInt(Var2, var2type);
+ btS16: tbts16(var1^) := tbts16(var1^) + PSGetInt(Var2, var2type);
+ btU32:
+ begin
+ if var2type.BaseType = btPointer then
+ begin
+ var2type := PIFTypeRec(Pointer(IPointer(var2)+PointerSize)^);
+ var2 := Pointer(var2^);
+ if (var2 = nil) or (var2type = nil) then raise Exception.Create(RPS_TypeMismatch);
+ end;
+ case var2type.BaseType of
+ btU8: tbtU32(var1^) := tbtU32(var1^) + tbtu8(var2^);
+ btS8: tbtU32(var1^) := tbtU32(var1^) + cardinal(longint(tbts8(var2^)));
+ btU16: tbtU32(var1^) := tbtU32(var1^) + tbtu16(var2^);
+ btS16: tbtU32(var1^) := tbtU32(var1^) + cardinal(longint(tbts16(var2^)));
+ btU32: tbtU32(var1^) := tbtU32(var1^) + tbtu32(var2^);
+ btS32: tbtU32(var1^) := tbtU32(var1^) + cardinal(tbts32(var2^));
+ {$IFNDEF PS_NOINT64} btS64: tbtU32(var1^) := tbtU32(var1^) + tbts64(var2^);{$ENDIF}
+ btChar: tbtU32(var1^) := tbtU32(var1^) + Ord(tbtchar(var2^));
+ {$IFNDEF PS_NOWIDESTRING} btWideChar: tbtU32(var1^) := tbtU32(var1^) + Ord(tbtwidechar(var2^));{$ENDIF}
+ btVariant: tbtU32(var1^) := tbtU32(var1^) + Variant(var2^);
+ else raise Exception.Create(RPS_TypeMismatch);
+ end;
+ end;
+ btS32:
+ begin
+ if var2type.BaseType = btPointer then
+ begin
+ var2type := PIFTypeRec(Pointer(IPointer(var2)+PointerSize)^);
+ var2 := Pointer(var2^);
+ if (var2 = nil) or (var2type = nil) then raise Exception.Create(RPS_TypeMismatch);
+ end;
+ case var2type.BaseType of
+ btU8: tbts32(var1^) := tbts32(var1^) + tbtu8(var2^);
+ btS8: tbts32(var1^) := tbts32(var1^) + tbts8(var2^);
+ btU16: tbts32(var1^) := tbts32(var1^) + tbtu16(var2^);
+ btS16: tbts32(var1^) := tbts32(var1^) + tbts16(var2^);
+ btU32: tbts32(var1^) := tbts32(var1^) + Longint(tbtu32(var2^));
+ btS32: tbts32(var1^) := tbts32(var1^) + tbts32(var2^);
+ {$IFNDEF PS_NOINT64} btS64: tbts32(var1^) := tbts32(var1^) + tbts64(var2^);{$ENDIF}
+ btChar: tbts32(var1^) := tbts32(var1^) + Ord(tbtchar(var2^));
+ {$IFNDEF PS_NOWIDESTRING} btWideChar: tbts32(var1^) := tbts32(var1^) + Ord(tbtwidechar(var2^));{$ENDIF}
+ btVariant: tbts32(var1^) := tbts32(var1^) + Variant(var2^);
+ else raise Exception.Create(RPS_TypeMismatch);
+ end;
+ end;
+ {$IFNDEF PS_NOINT64}
+ btS64: tbts64(var1^) := tbts64(var1^) + PSGetInt64(var2, var2type);
+ {$ENDIF}
+ btSingle:
+ begin
+ if var2type.BaseType = btPointer then
+ begin
+ var2type := PIFTypeRec(Pointer(IPointer(var2)+PointerSize)^);
+ var2 := Pointer(var2^);
+ if (var2 = nil) or (var2type = nil) then raise Exception.Create(RPS_TypeMismatch);
+ end;
+ case var2type.BaseType of
+ btU8: tbtsingle(var1^) := tbtsingle(var1^) + tbtu8(var2^);
+ btS8: tbtsingle(var1^) := tbtsingle(var1^) + tbts8(var2^);
+ btU16: tbtsingle(var1^) := tbtsingle(var1^) + tbtu16(var2^);
+ btS16: tbtsingle(var1^) := tbtsingle(var1^) + tbts16(var2^);
+ btU32: tbtsingle(var1^) := tbtsingle(var1^) + tbtu32(var2^);
+ btS32: tbtsingle(var1^) := tbtsingle(var1^) + tbts32(var2^);
+ {$IFNDEF PS_NOINT64} btS64: tbtsingle(var1^) := tbtsingle(var1^) + tbts64(var2^);{$ENDIF}
+ btSingle: tbtsingle(var1^) := tbtsingle(var1^) + tbtsingle(var2^);
+ btDouble: tbtsingle(var1^) := tbtsingle(var1^) + tbtdouble(var2^);
+ btExtended: tbtsingle(var1^) := tbtsingle(var1^) + tbtextended(var2^);
+ btCurrency: tbtsingle(var1^) := tbtsingle(var1^) + tbtcurrency(var2^);
+ btVariant: tbtsingle(var1^) := tbtsingle(var1^) + Variant(var2^);
+ else raise Exception.Create(RPS_TypeMismatch);
+ end;
+ end;
+ btDouble:
+ begin
+ if var2type.BaseType = btPointer then
+ begin
+ var2type := PIFTypeRec(Pointer(IPointer(var2)+PointerSize)^);
+ var2 := Pointer(var2^);
+ if (var2 = nil) or (var2type = nil) then raise Exception.Create(RPS_TypeMismatch);
+ end;
+ case var2type.BaseType of
+ btU8: tbtdouble(var1^) := tbtdouble(var1^) + tbtu8(var2^);
+ btS8: tbtdouble(var1^) := tbtdouble(var1^) + tbts8(var2^);
+ btU16: tbtdouble(var1^) := tbtdouble(var1^) + tbtu16(var2^);
+ btS16: tbtdouble(var1^) := tbtdouble(var1^) + tbts16(var2^);
+ btU32: tbtdouble(var1^) := tbtdouble(var1^) + tbtu32(var2^);
+ btS32: tbtdouble(var1^) := tbtdouble(var1^) + tbts32(var2^);
+ {$IFNDEF PS_NOINT64} btS64: tbtdouble(var1^) := tbtdouble(var1^) + tbts64(var2^);{$ENDIF}
+ btSingle: tbtdouble(var1^) := tbtdouble(var1^) + tbtsingle(var2^);
+ btDouble: tbtdouble(var1^) := tbtdouble(var1^) + tbtdouble(var2^);
+ btExtended: tbtdouble(var1^) := tbtdouble(var1^) + tbtextended(var2^);
+ btCurrency: tbtdouble(var1^) := tbtdouble(var1^) + tbtcurrency(var2^);
+ btVariant: tbtdouble(var1^) := tbtdouble(var1^) + Variant(var2^);
+ else raise Exception.Create(RPS_TypeMismatch);
+ end;
+ end;
+ btCurrency:
+ begin
+ if var2type.BaseType = btPointer then
+ begin
+ var2type := PIFTypeRec(Pointer(IPointer(var2)+PointerSize)^);
+ var2 := Pointer(var2^);
+ if (var2 = nil) or (var2type = nil) then raise Exception.Create(RPS_TypeMismatch);
+ end;
+ case var2type.BaseType of
+ btU8: tbtcurrency(var1^) := tbtcurrency(var1^) + tbtu8(var2^);
+ btS8: tbtcurrency(var1^) := tbtcurrency(var1^) + tbts8(var2^);
+ btU16: tbtcurrency(var1^) := tbtcurrency(var1^) + tbtu16(var2^);
+ btS16: tbtcurrency(var1^) := tbtcurrency(var1^) + tbts16(var2^);
+ btU32: tbtcurrency(var1^) := tbtdouble(var1^) + tbtu32(var2^);
+ btS32: tbtcurrency(var1^) := tbtcurrency(var1^) + tbts32(var2^);
+ {$IFNDEF PS_NOINT64} btS64: tbtcurrency(var1^) := tbtdouble(var1^) + tbts64(var2^);{$ENDIF}
+ btSingle: tbtcurrency(var1^) := tbtcurrency(var1^) + tbtsingle(var2^);
+ btDouble: tbtcurrency(var1^) := tbtcurrency(var1^) + tbtdouble(var2^);
+ btExtended: tbtcurrency(var1^) := tbtcurrency(var1^) + tbtextended(var2^);
+ btCurrency: tbtcurrency(var1^) := tbtcurrency(var1^) + tbtcurrency(var2^);
+ btVariant: tbtcurrency(var1^) := tbtcurrency(var1^) + Variant(var2^);
+ else raise Exception.Create(RPS_TypeMismatch);
+ end;
+ end;
+ btExtended:
+ begin
+ if var2type.BaseType = btPointer then
+ begin
+ var2type := PIFTypeRec(Pointer(IPointer(var2)+PointerSize)^);
+ var2 := Pointer(var2^);
+ if (var2 = nil) or (var2type = nil) then raise Exception.Create(RPS_TypeMismatch);
+ end;
+ case var2type.BaseType of
+ btU8: tbtextended(var1^) := tbtextended(var1^) + tbtu8(var2^);
+ btS8: tbtextended(var1^) := tbtextended(var1^) + tbts8(var2^);
+ btU16: tbtextended(var1^) := tbtextended(var1^) + tbtu16(var2^);
+ btS16: tbtextended(var1^) := tbtextended(var1^) + tbts16(var2^);
+ btU32: tbtextended(var1^) := tbtextended(var1^) + tbtu32(var2^);
+ btS32: tbtextended(var1^) := tbtextended(var1^) + tbts32(var2^);
+ {$IFNDEF PS_NOINT64} btS64: tbtextended(var1^) := tbtextended(var1^) + tbts64(var2^);{$ENDIF}
+ btSingle: tbtextended(var1^) := tbtextended(var1^) + tbtsingle(var2^);
+ btDouble: tbtextended(var1^) := tbtextended(var1^) + tbtdouble(var2^);
+ btExtended: tbtextended(var1^) := tbtextended(var1^) + tbtextended(var2^);
+ btCurrency: tbtextended(var1^) := tbtextended(var1^) + tbtcurrency(var2^);
+ btVariant: tbtextended(var1^) := tbtextended(var1^) + Variant(var2^);
+ else raise Exception.Create(RPS_TypeMismatch);
+ end;
+ end;
+ btPchar, btString: tbtstring(var1^) := tbtstring(var1^) + PSGetAnsiString(Var2, var2type);
+ btChar: tbtchar(var1^) := tbtchar(ord(tbtchar(var1^)) + PSGetUInt(Var2, var2type));
+ {$IFNDEF PS_NOWIDESTRING}
+ btWideChar: tbtwidechar(var1^) := widechar(ord(tbtwidechar(var1^)) + PSGetUInt(Var2, var2type));
+ btWideString: tbtwidestring(var1^) := tbtwidestring(var1^) + PSGetWideString(Var2, var2type);
+ btUnicodeString: tbtUnicodestring(var1^) := tbtUnicodestring(var1^) + PSGetUnicodeString(Var2, var2type);
+ {$ENDIF}
+ btVariant:
+ begin
+ tvar := null;
+ if not IntPIFVariantToVariant(var2, var2type, tvar) then
+ begin
+ Result := false;
+ end else
+ Variant(var1^) := Variant(var1^) + tvar;
+ end;
+ btSet:
+ begin
+ if var1Type = var2Type then
+ begin
+ Set_Union(var1, var2, TPSTypeRec_Set(var1Type).aByteSize);
+ end else result := False;
+ end;
+
+ else begin
+ CMD_Err(erTypeMismatch);
+ exit;
+ end;
+ end;
+ if not Result then begin
+ CMD_Err(erTypeMismatch);
+ exit;
+ end;
+ end;
+ 1: begin { - }
+ case var1Type.BaseType of
+ btU8: tbtU8(var1^) := tbtU8(var1^) - PSGetUInt(Var2, var2type);
+ btS8: tbts8(var1^) := tbts8(var1^) - PSGetInt(Var2, var2type);
+ btU16: tbtU16(var1^) := tbtU16(var1^) - PSGetUInt(Var2, var2type);
+ btS16: tbts16(var1^) := tbts16(var1^) - PSGetInt(Var2, var2type);
+ btU32:
+ begin
+ if var2type.BaseType = btPointer then
+ begin
+ var2type := PIFTypeRec(Pointer(IPointer(var2)+PointerSize)^);
+ var2 := Pointer(var2^);
+ if (var2 = nil) or (var2type = nil) then raise Exception.Create(RPS_TypeMismatch);
+ end;
+ case var2type.BaseType of
+ btU8: tbtU32(var1^) := tbtU32(var1^) - tbtu8(var2^);
+ btS8: tbtU32(var1^) := tbtU32(var1^) - cardinal(longint(tbts8(var2^)));
+ btU16: tbtU32(var1^) := tbtU32(var1^) - tbtu16(var2^);
+ btS16: tbtU32(var1^) := tbtU32(var1^) - cardinal(longint(tbts16(var2^)));
+ btU32: tbtU32(var1^) := tbtU32(var1^) - tbtu32(var2^);
+ btS32: tbtU32(var1^) := tbtU32(var1^) - cardinal(tbts32(var2^));
+ {$IFNDEF PS_NOINT64} btS64: tbtU32(var1^) := tbtU32(var1^) - tbts64(var2^);{$ENDIF}
+ btChar: tbtU32(var1^) := tbtU32(var1^) - Ord(tbtchar(var2^));
+ {$IFNDEF PS_NOWIDESTRING} btWideChar: tbtU32(var1^) := tbtU32(var1^) - Ord(tbtwidechar(var2^));{$ENDIF}
+ btVariant: tbtU32(var1^) := tbtU32(var1^) - Variant(var2^);
+ else raise Exception.Create(RPS_TypeMismatch);
+ end;
+ end;
+ btS32:
+ begin
+ if var2type.BaseType = btPointer then
+ begin
+ var2type := PIFTypeRec(Pointer(IPointer(var2)+PointerSize)^);
+ var2 := Pointer(var2^);
+ if (var2 = nil) or (var2type = nil) then raise Exception.Create(RPS_TypeMismatch);
+ end;
+ case var2type.BaseType of
+ btU8: tbts32(var1^) := tbts32(var1^) - tbtu8(var2^);
+ btS8: tbts32(var1^) := tbts32(var1^) - tbts8(var2^);
+ btU16: tbts32(var1^) := tbts32(var1^) - tbtu16(var2^);
+ btS16: tbts32(var1^) := tbts32(var1^) - tbts16(var2^);
+ btU32: tbts32(var1^) := tbts32(var1^) - Longint(tbtu32(var2^));
+ btS32: tbts32(var1^) := tbts32(var1^) - tbts32(var2^);
+ {$IFNDEF PS_NOINT64} btS64: tbts32(var1^) := tbts32(var1^) - tbts64(var2^);{$ENDIF}
+ btChar: tbts32(var1^) := tbts32(var1^) - Ord(tbtchar(var2^));
+ {$IFNDEF PS_NOWIDESTRING} btWideChar: tbts32(var1^) := tbts32(var1^) - Ord(tbtwidechar(var2^));{$ENDIF}
+ btVariant: tbts32(var1^) := tbts32(var1^) - Variant(var2^);
+ else raise Exception.Create(RPS_TypeMismatch);
+ end;
+ end;
+ {$IFNDEF PS_NOINT64}
+ btS64: tbts64(var1^) := tbts64(var1^) - PSGetInt64(var2, var2type);
+ {$ENDIF}
+ btSingle:
+ begin
+ if var2type.BaseType = btPointer then
+ begin
+ var2type := PIFTypeRec(Pointer(IPointer(var2)+PointerSize)^);
+ var2 := Pointer(var2^);
+ if (var2 = nil) or (var2type = nil) then raise Exception.Create(RPS_TypeMismatch);
+ end;
+ case var2type.BaseType of
+ btU8: tbtsingle(var1^) := tbtsingle(var1^) - tbtu8(var2^);
+ btS8: tbtsingle(var1^) := tbtsingle(var1^) - tbts8(var2^);
+ btU16: tbtsingle(var1^) := tbtsingle(var1^) - tbtu16(var2^);
+ btS16: tbtsingle(var1^) := tbtsingle(var1^) - tbts16(var2^);
+ btU32: tbtsingle(var1^) := tbtsingle(var1^) - tbtu32(var2^);
+ btS32: tbtsingle(var1^) := tbtsingle(var1^) - tbts32(var2^);
+ {$IFNDEF PS_NOINT64} btS64: tbtsingle(var1^) := tbtsingle(var1^) - tbts64(var2^);{$ENDIF}
+ btSingle: tbtsingle(var1^) := tbtsingle(var1^) - tbtsingle(var2^);
+ btDouble: tbtsingle(var1^) := tbtsingle(var1^) - tbtdouble(var2^);
+ btExtended: tbtsingle(var1^) := tbtsingle(var1^) - tbtextended(var2^);
+ btCurrency: tbtsingle(var1^) := tbtsingle(var1^) - tbtcurrency(var2^);
+ btVariant: tbtsingle(var1^) := tbtsingle(var1^) - Variant(var2^);
+ else raise Exception.Create(RPS_TypeMismatch);
+ end;
+ end;
+ btCurrency:
+ begin
+ if var2type.BaseType = btPointer then
+ begin
+ var2type := PIFTypeRec(Pointer(IPointer(var2)+PointerSize)^);
+ var2 := Pointer(var2^);
+ if (var2 = nil) or (var2type = nil) then raise Exception.Create(RPS_TypeMismatch);
+ end;
+ case var2type.BaseType of
+ btU8: tbtcurrency(var1^) := tbtcurrency(var1^) - tbtu8(var2^);
+ btS8: tbtcurrency(var1^) := tbtcurrency(var1^) - tbts8(var2^);
+ btU16: tbtcurrency(var1^) := tbtcurrency(var1^) - tbtu16(var2^);
+ btS16: tbtcurrency(var1^) := tbtcurrency(var1^) - tbts16(var2^);
+ btU32: tbtcurrency(var1^) := tbtdouble(var1^) - tbtu32(var2^);
+ btS32: tbtcurrency(var1^) := tbtcurrency(var1^) - tbts32(var2^);
+ {$IFNDEF PS_NOINT64} btS64: tbtcurrency(var1^) := tbtdouble(var1^) - tbts64(var2^);{$ENDIF}
+ btSingle: tbtcurrency(var1^) := tbtcurrency(var1^) - tbtsingle(var2^);
+ btDouble: tbtcurrency(var1^) := tbtcurrency(var1^) - tbtdouble(var2^);
+ btExtended: tbtcurrency(var1^) := tbtcurrency(var1^) - tbtextended(var2^);
+ btCurrency: tbtcurrency(var1^) := tbtcurrency(var1^) - tbtcurrency(var2^);
+ btVariant: tbtcurrency(var1^) := tbtcurrency(var1^) - Variant(var2^);
+ else raise Exception.Create(RPS_TypeMismatch);
+ end;
+ end;
+ btDouble:
+ begin
+ if var2type.BaseType = btPointer then
+ begin
+ var2type := PIFTypeRec(Pointer(IPointer(var2)+PointerSize)^);
+ var2 := Pointer(var2^);
+ if (var2 = nil) or (var2type = nil) then raise Exception.Create(RPS_TypeMismatch);
+ end;
+ case var2type.BaseType of
+ btU8: tbtdouble(var1^) := tbtdouble(var1^) - tbtu8(var2^);
+ btS8: tbtdouble(var1^) := tbtdouble(var1^) - tbts8(var2^);
+ btU16: tbtdouble(var1^) := tbtdouble(var1^) - tbtu16(var2^);
+ btS16: tbtdouble(var1^) := tbtdouble(var1^) - tbts16(var2^);
+ btU32: tbtdouble(var1^) := tbtdouble(var1^) - tbtu32(var2^);
+ btS32: tbtdouble(var1^) := tbtdouble(var1^) - tbts32(var2^);
+ {$IFNDEF PS_NOINT64} btS64: tbtdouble(var1^) := tbtdouble(var1^) - tbts64(var2^);{$ENDIF}
+ btSingle: tbtdouble(var1^) := tbtdouble(var1^) - tbtsingle(var2^);
+ btDouble: tbtdouble(var1^) := tbtdouble(var1^) - tbtdouble(var2^);
+ btExtended: tbtdouble(var1^) := tbtdouble(var1^) - tbtextended(var2^);
+ btCurrency: tbtdouble(var1^) := tbtdouble(var1^) - tbtcurrency(var2^);
+ btVariant: tbtdouble(var1^) := tbtdouble(var1^) - Variant(var2^);
+ else raise Exception.Create(RPS_TypeMismatch);
+ end;
+ end;
+ btExtended:
+ begin
+ if var2type.BaseType = btPointer then
+ begin
+ var2type := PIFTypeRec(Pointer(IPointer(var2)+PointerSize)^);
+ var2 := Pointer(var2^);
+ if (var2 = nil) or (var2type = nil) then raise Exception.Create(RPS_TypeMismatch);
+ end;
+ case var2type.BaseType of
+ btU8: tbtextended(var1^) := tbtextended(var1^) - tbtu8(var2^);
+ btS8: tbtextended(var1^) := tbtextended(var1^) - tbts8(var2^);
+ btU16: tbtextended(var1^) := tbtextended(var1^) - tbtu16(var2^);
+ btS16: tbtextended(var1^) := tbtextended(var1^) - tbts16(var2^);
+ btU32: tbtextended(var1^) := tbtextended(var1^) - tbtu32(var2^);
+ btS32: tbtextended(var1^) := tbtextended(var1^) - tbts32(var2^);
+ {$IFNDEF PS_NOINT64} btS64: tbtextended(var1^) := tbtextended(var1^) -+tbts64(var2^);{$ENDIF}
+ btSingle: tbtextended(var1^) := tbtextended(var1^) - tbtsingle(var2^);
+ btDouble: tbtextended(var1^) := tbtextended(var1^) - tbtdouble(var2^);
+ btExtended: tbtextended(var1^) := tbtextended(var1^) - tbtextended(var2^);
+ btCurrency: tbtextended(var1^) := tbtextended(var1^) - tbtcurrency(var2^);
+ btVariant: tbtextended(var1^) := tbtextended(var1^) - Variant(var2^);
+ else raise Exception.Create(RPS_TypeMismatch);
+ end;
+ end;
+ btChar: tbtchar(var1^):= tbtchar(ord(tbtchar(var1^)) - PSGetUInt(Var2, var2type));
+ {$IFNDEF PS_NOWIDESTRING}
+ btWideChar: tbtwidechar(var1^) := widechar(ord(tbtwidechar(var1^)) - PSGetUInt(Var2, var2type));
+ {$ENDIF}
+ btVariant:
+ begin
+ if not IntPIFVariantToVariant(var2, var2type, tvar) then
+ begin
+ Result := false;
+ end else
+ Variant(var1^) := Variant(var1^) - tvar;
+ end;
+ btSet:
+ begin
+ if var1Type = var2Type then
+ begin
+ Set_Diff(var1, var2, TPSTypeRec_Set(var1Type).aByteSize);
+ end else result := False;
+ end;
+ else begin
+ CMD_Err(erTypeMismatch);
+ exit;
+ end;
+ end;
+ if not Result then begin
+ CMD_Err(erTypeMismatch);
+ exit;
+ end;
+ end;
+ 2: begin { * }
+ case var1Type.BaseType of
+ btU8: tbtU8(var1^) := tbtU8(var1^) * PSGetUInt(Var2, var2type);
+ btS8: tbts8(var1^) := tbts8(var1^) * PSGetInt(Var2, var2type);
+ btU16: tbtU16(var1^) := tbtU16(var1^) * PSGetUInt(Var2, var2type);
+ btS16: tbts16(var1^) := tbts16(var1^) * PSGetInt(Var2, var2type);
+ btU32:
+ begin
+ if var2type.BaseType = btPointer then
+ begin
+ var2type := PIFTypeRec(Pointer(IPointer(var2)+PointerSize)^);
+ var2 := Pointer(var2^);
+ if (var2 = nil) or (var2type = nil) then raise Exception.Create(RPS_TypeMismatch);
+ end;
+ case var2type.BaseType of
+ btU8: tbtU32(var1^) := tbtU32(var1^) * tbtu8(var2^);
+ btS8: tbtU32(var1^) := tbtU32(var1^) * cardinal(longint(tbts8(var2^)));
+ btU16: tbtU32(var1^) := tbtU32(var1^) * tbtu16(var2^);
+ btS16: tbtU32(var1^) := tbtU32(var1^) * cardinal(longint(tbts16(var2^)));
+ btU32: tbtU32(var1^) := tbtU32(var1^) * tbtu32(var2^);
+ btS32: tbtU32(var1^) := tbtU32(var1^) * cardinal(tbts32(var2^));
+ {$IFNDEF PS_NOINT64} btS64: tbtU32(var1^) := tbtU32(var1^) * tbts64(var2^);{$ENDIF}
+ btChar: tbtU32(var1^) := tbtU32(var1^) * Ord(tbtchar(var2^));
+ {$IFNDEF PS_NOWIDESTRING} btWideChar: tbtU32(var1^) := tbtU32(var1^) * Ord(tbtwidechar(var2^));{$ENDIF}
+ btVariant: tbtU32(var1^) := tbtU32(var1^) * Variant(var2^);
+ else raise Exception.Create(RPS_TypeMismatch);
+ end;
+ end;
+ btS32:
+ begin
+ if var2type.BaseType = btPointer then
+ begin
+ var2type := PIFTypeRec(Pointer(IPointer(var2)+PointerSize)^);
+ var2 := Pointer(var2^);
+ if (var2 = nil) or (var2type = nil) then raise Exception.Create(RPS_TypeMismatch);
+ end;
+ case var2type.BaseType of
+ btU8: tbts32(var1^) := tbts32(var1^) * tbtu8(var2^);
+ btS8: tbts32(var1^) := tbts32(var1^) * tbts8(var2^);
+ btU16: tbts32(var1^) := tbts32(var1^) * tbtu16(var2^);
+ btS16: tbts32(var1^) := tbts32(var1^) * tbts16(var2^);
+ btU32: tbts32(var1^) := tbts32(var1^) * Longint(tbtu32(var2^));
+ btS32: tbts32(var1^) := tbts32(var1^) * tbts32(var2^);
+ {$IFNDEF PS_NOINT64} btS64: tbts32(var1^) := tbts32(var1^) * tbts64(var2^);{$ENDIF}
+ btChar: tbts32(var1^) := tbts32(var1^) * Ord(tbtchar(var2^));
+ {$IFNDEF PS_NOWIDESTRING} btWideChar: tbts32(var1^) := tbts32(var1^) * Ord(tbtwidechar(var2^));{$ENDIF}
+ btVariant: tbts32(var1^) := tbts32(var1^) * Variant(var2^);
+ else raise Exception.Create(RPS_TypeMismatch);
+ end;
+ end;
+ {$IFNDEF PS_NOINT64}
+ btS64: tbts64(var1^) := tbts64(var1^) * PSGetInt64(var2, var2type);
+ {$ENDIF}
+ btCurrency:
+ begin
+ if var2type.BaseType = btPointer then
+ begin
+ var2type := PIFTypeRec(Pointer(IPointer(var2)+PointerSize)^);
+ var2 := Pointer(var2^);
+ if (var2 = nil) or (var2type = nil) then raise Exception.Create(RPS_TypeMismatch);
+ end;
+ case var2type.BaseType of
+ btU8: tbtcurrency(var1^) := tbtcurrency(var1^) * tbtu8(var2^);
+ btS8: tbtcurrency(var1^) := tbtcurrency(var1^) * tbts8(var2^);
+ btU16: tbtcurrency(var1^) := tbtcurrency(var1^) * tbtu16(var2^);
+ btS16: tbtcurrency(var1^) := tbtcurrency(var1^) * tbts16(var2^);
+ btU32: tbtcurrency(var1^) := tbtdouble(var1^) * tbtu32(var2^);
+ btS32: tbtcurrency(var1^) := tbtcurrency(var1^) * tbts32(var2^);
+ {$IFNDEF PS_NOINT64} btS64: tbtcurrency(var1^) := tbtdouble(var1^) * tbts64(var2^);{$ENDIF}
+ btSingle: tbtcurrency(var1^) := tbtcurrency(var1^) * tbtsingle(var2^);
+ btDouble: tbtcurrency(var1^) := tbtcurrency(var1^) * tbtdouble(var2^);
+ btExtended: tbtcurrency(var1^) := tbtcurrency(var1^) * tbtextended(var2^);
+ btCurrency: tbtcurrency(var1^) := tbtcurrency(var1^) * tbtcurrency(var2^);
+ btVariant: tbtcurrency(var1^) := tbtcurrency(var1^) * Variant(var2^);
+ else raise Exception.Create(RPS_TypeMismatch);
+ end;
+ end;
+ btSingle:
+ begin
+ if var2type.BaseType = btPointer then
+ begin
+ var2type := PIFTypeRec(Pointer(IPointer(var2)+PointerSize)^);
+ var2 := Pointer(var2^);
+ if (var2 = nil) or (var2type = nil) then raise Exception.Create(RPS_TypeMismatch);
+ end;
+ case var2type.BaseType of
+ btU8: tbtsingle(var1^) := tbtsingle(var1^) *tbtu8(var2^);
+ btS8: tbtsingle(var1^) := tbtsingle(var1^) *tbts8(var2^);
+ btU16: tbtsingle(var1^) := tbtsingle(var1^) *tbtu16(var2^);
+ btS16: tbtsingle(var1^) := tbtsingle(var1^) *tbts16(var2^);
+ btU32: tbtsingle(var1^) := tbtsingle(var1^) *tbtu32(var2^);
+ btS32: tbtsingle(var1^) := tbtsingle(var1^) *tbts32(var2^);
+ {$IFNDEF PS_NOINT64} btS64: tbtsingle(var1^) := tbtsingle(var1^) *tbts64(var2^);{$ENDIF}
+ btSingle: tbtsingle(var1^) := tbtsingle(var1^) *tbtsingle(var2^);
+ btDouble: tbtsingle(var1^) := tbtsingle(var1^) *tbtdouble(var2^);
+ btExtended: tbtsingle(var1^) := tbtsingle(var1^) *tbtextended(var2^);
+ btCurrency: tbtsingle(var1^) := tbtsingle(var1^) *tbtcurrency(var2^);
+ btVariant: tbtsingle(var1^) := tbtsingle(var1^) * Variant(var2^);
+ else raise Exception.Create(RPS_TypeMismatch);
+ end;
+ end;
+ btDouble:
+ begin
+ if var2type.BaseType = btPointer then
+ begin
+ var2type := PIFTypeRec(Pointer(IPointer(var2)+PointerSize)^);
+ var2 := Pointer(var2^);
+ if (var2 = nil) or (var2type = nil) then raise Exception.Create(RPS_TypeMismatch);
+ end;
+ case var2type.BaseType of
+ btU8: tbtdouble(var1^) := tbtdouble(var1^) *tbtu8(var2^);
+ btS8: tbtdouble(var1^) := tbtdouble(var1^) *tbts8(var2^);
+ btU16: tbtdouble(var1^) := tbtdouble(var1^) *tbtu16(var2^);
+ btS16: tbtdouble(var1^) := tbtdouble(var1^) *tbts16(var2^);
+ btU32: tbtdouble(var1^) := tbtdouble(var1^) *tbtu32(var2^);
+ btS32: tbtdouble(var1^) := tbtdouble(var1^) *tbts32(var2^);
+ {$IFNDEF PS_NOINT64} btS64: tbtdouble(var1^) := tbtdouble(var1^) *tbts64(var2^);{$ENDIF}
+ btSingle: tbtdouble(var1^) := tbtdouble(var1^) *tbtsingle(var2^);
+ btDouble: tbtdouble(var1^) := tbtdouble(var1^) *tbtdouble(var2^);
+ btExtended: tbtdouble(var1^) := tbtdouble(var1^) *tbtextended(var2^);
+ btCurrency: tbtdouble(var1^) := tbtdouble(var1^) *tbtcurrency(var2^);
+ btVariant: tbtdouble(var1^) := tbtdouble(var1^) * Variant(var2^);
+ else raise Exception.Create(RPS_TypeMismatch);
+ end;
+ end;
+ btExtended:
+ begin
+ if var2type.BaseType = btPointer then
+ begin
+ var2type := PIFTypeRec(Pointer(IPointer(var2)+PointerSize)^);
+ var2 := Pointer(var2^);
+ if (var2 = nil) or (var2type = nil) then raise Exception.Create(RPS_TypeMismatch);
+ end;
+ case var2type.BaseType of
+ btU8: tbtextended(var1^) := tbtextended(var1^) *tbtu8(var2^);
+ btS8: tbtextended(var1^) := tbtextended(var1^) *tbts8(var2^);
+ btU16: tbtextended(var1^) := tbtextended(var1^) *tbtu16(var2^);
+ btS16: tbtextended(var1^) := tbtextended(var1^) *tbts16(var2^);
+ btU32: tbtextended(var1^) := tbtextended(var1^) *tbtu32(var2^);
+ btS32: tbtextended(var1^) := tbtextended(var1^) *tbts32(var2^);
+ {$IFNDEF PS_NOINT64} btS64: tbtextended(var1^) := tbtextended(var1^) *tbts64(var2^);{$ENDIF}
+ btSingle: tbtextended(var1^) := tbtextended(var1^) *tbtsingle(var2^);
+ btDouble: tbtextended(var1^) := tbtextended(var1^) *tbtdouble(var2^);
+ btExtended: tbtextended(var1^) := tbtextended(var1^) *tbtextended(var2^);
+ btCurrency: tbtextended(var1^) := tbtextended(var1^) *tbtcurrency(var2^);
+ btVariant: tbtextended(var1^) := tbtextended(var1^) * Variant(var2^);
+ else raise Exception.Create(RPS_TypeMismatch);
+ end;
+ end;
+ btVariant:
+ begin
+ if not IntPIFVariantToVariant(var2, var2type, tvar) then
+ begin
+ Result := false;
+ end else
+ Variant(var1^) := Variant(var1^) * tvar;
+ end;
+ btSet:
+ begin
+ if var1Type = var2Type then
+ begin
+ Set_Intersect(var1, var2, TPSTypeRec_Set(var1Type).aByteSize);
+ end else result := False;
+ end;
+ else begin
+ CMD_Err(erTypeMismatch);
+ exit;
+ end;
+ end;
+ if not Result then begin
+ CMD_Err(erTypeMismatch);
+ exit;
+ end;
+ end;
+ 3: begin { / }
+ case var1Type.BaseType of
+ btU8: tbtU8(var1^) := tbtU8(var1^) div PSGetUInt(Var2, var2type);
+ btS8: tbts8(var1^) := tbts8(var1^) div PSGetInt(Var2, var2type);
+ btU16: tbtU16(var1^) := tbtU16(var1^) div PSGetUInt(Var2, var2type);
+ btS16: tbts16(var1^) := tbts16(var1^) div PSGetInt(Var2, var2type);
+ btU32:
+ begin
+ if var2type.BaseType = btPointer then
+ begin
+ var2type := PIFTypeRec(Pointer(IPointer(var2)+PointerSize)^);
+ var2 := Pointer(var2^);
+ if (var2 = nil) or (var2type = nil) then raise Exception.Create(RPS_TypeMismatch);
+ end;
+ case var2type.BaseType of
+ btU8: tbtU32(var1^) := tbtU32(var1^) div tbtu8(var2^);
+ btS8: tbtU32(var1^) := tbtU32(var1^) div cardinal(longint(tbts8(var2^)));
+ btU16: tbtU32(var1^) := tbtU32(var1^) div tbtu16(var2^);
+ btS16: tbtU32(var1^) := tbtU32(var1^) div cardinal(longint(tbts16(var2^)));
+ btU32: tbtU32(var1^) := tbtU32(var1^) div tbtu32(var2^);
+ btS32: tbtU32(var1^) := tbtU32(var1^) div cardinal(tbts32(var2^));
+ {$IFNDEF PS_NOINT64} btS64: tbtU32(var1^) := tbtU32(var1^) div tbts64(var2^);{$ENDIF}
+ btChar: tbtU32(var1^) := tbtU32(var1^) div Ord(tbtchar(var2^));
+ {$IFNDEF PS_NOWIDESTRING} btWideChar: tbtU32(var1^) := tbtU32(var1^) div Ord(tbtwidechar(var2^));{$ENDIF}
+ btVariant: tbtU32(var1^) := tbtU32(var1^) div Variant(var2^);
+ else raise Exception.Create(RPS_TypeMismatch);
+ end;
+ end;
+ btS32:
+ begin
+ if var2type.BaseType = btPointer then
+ begin
+ var2type := PIFTypeRec(Pointer(IPointer(var2)+PointerSize)^);
+ var2 := Pointer(var2^);
+ if (var2 = nil) or (var2type = nil) then raise Exception.Create(RPS_TypeMismatch);
+ end;
+ case var2type.BaseType of
+ btU8: tbts32(var1^) := tbts32(var1^) div tbtu8(var2^);
+ btS8: tbts32(var1^) := tbts32(var1^) div tbts8(var2^);
+ btU16: tbts32(var1^) := tbts32(var1^) div tbtu16(var2^);
+ btS16: tbts32(var1^) := tbts32(var1^) div tbts16(var2^);
+ btU32: tbts32(var1^) := tbts32(var1^) div Longint(tbtu32(var2^));
+ btS32: tbts32(var1^) := tbts32(var1^) div tbts32(var2^);
+ {$IFNDEF PS_NOINT64} btS64: tbts32(var1^) := tbts32(var1^) div tbts64(var2^);{$ENDIF}
+ btChar: tbts32(var1^) := tbts32(var1^) div Ord(tbtchar(var2^));
+ {$IFNDEF PS_NOWIDESTRING} btWideChar: tbts32(var1^) := tbts32(var1^) div Ord(tbtwidechar(var2^));{$ENDIF}
+ btVariant: tbts32(var1^) := tbts32(var1^) div Variant(var2^);
+ else raise Exception.Create(RPS_TypeMismatch);
+ end;
+ end;
+ {$IFNDEF PS_NOINT64}
+ btS64: tbts64(var1^) := tbts64(var1^) div PSGetInt64(var2, var2type);
+ {$ENDIF}
+ btSingle:
+ begin
+ if var2type.BaseType = btPointer then
+ begin
+ var2type := PIFTypeRec(Pointer(IPointer(var2)+PointerSize)^);
+ var2 := Pointer(var2^);
+ if (var2 = nil) or (var2type = nil) then raise Exception.Create(RPS_TypeMismatch);
+ end;
+ case var2type.BaseType of
+ btU8: tbtsingle(var1^) := tbtsingle(var1^) / tbtu8(var2^);
+ btS8: tbtsingle(var1^) := tbtsingle(var1^) / tbts8(var2^);
+ btU16: tbtsingle(var1^) := tbtsingle(var1^) / tbtu16(var2^);
+ btS16: tbtsingle(var1^) := tbtsingle(var1^) / tbts16(var2^);
+ btU32: tbtsingle(var1^) := tbtsingle(var1^) / tbtu32(var2^);
+ btS32: tbtsingle(var1^) := tbtsingle(var1^) / tbts32(var2^);
+ {$IFNDEF PS_NOINT64} btS64: tbtsingle(var1^) := tbtsingle(var1^) / tbts64(var2^);{$ENDIF}
+ btSingle: tbtsingle(var1^) := tbtsingle(var1^) / tbtsingle(var2^);
+ btDouble: tbtsingle(var1^) := tbtsingle(var1^) / tbtdouble(var2^);
+ btExtended: tbtsingle(var1^) := tbtsingle(var1^) / tbtextended(var2^);
+ btCurrency: tbtsingle(var1^) := tbtsingle(var1^) / tbtcurrency(var2^);
+ btVariant: tbtsingle(var1^) := tbtsingle(var1^) / Variant(var2^);
+ else raise Exception.Create(RPS_TypeMismatch);
+ end;
+ end;
+ btCurrency:
+ begin
+ if var2type.BaseType = btPointer then
+ begin
+ var2type := PIFTypeRec(Pointer(IPointer(var2)+PointerSize)^);
+ var2 := Pointer(var2^);
+ if (var2 = nil) or (var2type = nil) then raise Exception.Create(RPS_TypeMismatch);
+ end;
+ case var2type.BaseType of
+ btU8: tbtcurrency(var1^) := tbtcurrency(var1^) / tbtu8(var2^);
+ btS8: tbtcurrency(var1^) := tbtcurrency(var1^) / tbts8(var2^);
+ btU16: tbtcurrency(var1^) := tbtcurrency(var1^) / tbtu16(var2^);
+ btS16: tbtcurrency(var1^) := tbtcurrency(var1^) / tbts16(var2^);
+ btU32: tbtcurrency(var1^) := tbtdouble(var1^) / tbtu32(var2^);
+ btS32: tbtcurrency(var1^) := tbtcurrency(var1^) / tbts32(var2^);
+ {$IFNDEF PS_NOINT64} btS64: tbtcurrency(var1^) := tbtdouble(var1^) / tbts64(var2^);{$ENDIF}
+ btSingle: tbtcurrency(var1^) := tbtcurrency(var1^) / tbtsingle(var2^);
+ btDouble: tbtcurrency(var1^) := tbtcurrency(var1^) / tbtdouble(var2^);
+ btExtended: tbtcurrency(var1^) := tbtcurrency(var1^) / tbtextended(var2^);
+ btCurrency: tbtcurrency(var1^) := tbtcurrency(var1^) / tbtcurrency(var2^);
+ btVariant: tbtcurrency(var1^) := tbtcurrency(var1^) / Variant(var2^);
+ else raise Exception.Create(RPS_TypeMismatch);
+ end;
+ end;
+ btDouble:
+ begin
+ if var2type.BaseType = btPointer then
+ begin
+ var2type := PIFTypeRec(Pointer(IPointer(var2)+PointerSize)^);
+ var2 := Pointer(var2^);
+ if (var2 = nil) or (var2type = nil) then raise Exception.Create(RPS_TypeMismatch);
+ end;
+ case var2type.BaseType of
+ btU8: tbtdouble(var1^) := tbtdouble(var1^) / tbtu8(var2^);
+ btS8: tbtdouble(var1^) := tbtdouble(var1^) / tbts8(var2^);
+ btU16: tbtdouble(var1^) := tbtdouble(var1^) / tbtu16(var2^);
+ btS16: tbtdouble(var1^) := tbtdouble(var1^) / tbts16(var2^);
+ btU32: tbtdouble(var1^) := tbtdouble(var1^) / tbtu32(var2^);
+ btS32: tbtdouble(var1^) := tbtdouble(var1^) / tbts32(var2^);
+ {$IFNDEF PS_NOINT64} btS64: tbtdouble(var1^) := tbtdouble(var1^) / tbts64(var2^);{$ENDIF}
+ btSingle: tbtdouble(var1^) := tbtdouble(var1^) / tbtsingle(var2^);
+ btDouble: tbtdouble(var1^) := tbtdouble(var1^) / tbtdouble(var2^);
+ btExtended: tbtdouble(var1^) := tbtdouble(var1^) / tbtextended(var2^);
+ btCurrency: tbtdouble(var1^) := tbtdouble(var1^) / tbtcurrency(var2^);
+ btVariant: tbtdouble(var1^) := tbtdouble(var1^) / Variant(var2^);
+ else raise Exception.Create(RPS_TypeMismatch);
+ end;
+ end;
+ btExtended:
+ begin
+ if var2type.BaseType = btPointer then
+ begin
+ var2type := PIFTypeRec(Pointer(IPointer(var2)+PointerSize)^);
+ var2 := Pointer(var2^);
+ if (var2 = nil) or (var2type = nil) then raise Exception.Create(RPS_TypeMismatch);
+ end;
+ case var2type.BaseType of
+ btU8: tbtextended(var1^) := tbtextended(var1^) / tbtu8(var2^);
+ btS8: tbtextended(var1^) := tbtextended(var1^) / tbts8(var2^);
+ btU16: tbtextended(var1^) := tbtextended(var1^) / tbtu16(var2^);
+ btS16: tbtextended(var1^) := tbtextended(var1^) / tbts16(var2^);
+ btU32: tbtextended(var1^) := tbtextended(var1^) / tbtu32(var2^);
+ btS32: tbtextended(var1^) := tbtextended(var1^) / tbts32(var2^);
+ {$IFNDEF PS_NOINT64} btS64: tbtextended(var1^) := tbtextended(var1^) / tbts64(var2^);{$ENDIF}
+ btSingle: tbtextended(var1^) := tbtextended(var1^) / tbtsingle(var2^);
+ btDouble: tbtextended(var1^) := tbtextended(var1^) / tbtdouble(var2^);
+ btExtended: tbtextended(var1^) := tbtextended(var1^) / tbtextended(var2^);
+ btCurrency: tbtextended(var1^) := tbtextended(var1^) / tbtcurrency(var2^);
+ btVariant: tbtextended(var1^) := tbtextended(var1^) / Variant(var2^);
+ else raise Exception.Create(RPS_TypeMismatch);
+ end;
+ end;
+ btVariant:
+ begin
+ if not IntPIFVariantToVariant(var2, var2type, tvar) then
+ begin
+ Result := false;
+ end else
+ begin
+ if VarIsFloat(variant(var1^)) then
+ Variant(var1^) := Variant(var1^) / tvar
+ else
+ Variant(var1^) := Variant(var1^) div tvar;
+ end;
+ end;
+ else begin
+ CMD_Err(erTypeMismatch);
+ exit;
+ end;
+ end;
+ if not Result then begin
+ CMD_Err(erTypeMismatch);
+ exit;
+ end;
+ end;
+ 4: begin { MOD }
+ case var1Type.BaseType of
+ btU8: tbtU8(var1^) := tbtU8(var1^) mod PSGetUInt(Var2, var2type);
+ btS8: tbts8(var1^) := tbts8(var1^) mod PSGetInt(Var2, var2type);
+ btU16: tbtU16(var1^) := tbtU16(var1^) mod PSGetUInt(Var2, var2type);
+ btS16: tbts16(var1^) := tbts16(var1^) mod PSGetInt(Var2, var2type);
+ btU32:
+ begin
+ if var2type.BaseType = btPointer then
+ begin
+ var2type := PIFTypeRec(Pointer(IPointer(var2)+PointerSize)^);
+ var2 := Pointer(var2^);
+ if (var2 = nil) or (var2type = nil) then raise Exception.Create(RPS_TypeMismatch);
+ end;
+ case var2type.BaseType of
+ btU8: tbtU32(var1^) := tbtU32(var1^) mod tbtu8(var2^);
+ btS8: tbtU32(var1^) := tbtU32(var1^) mod cardinal(longint(tbts8(var2^)));
+ btU16: tbtU32(var1^) := tbtU32(var1^) mod tbtu16(var2^);
+ btS16: tbtU32(var1^) := tbtU32(var1^) mod cardinal(longint(tbts16(var2^)));
+ btU32: tbtU32(var1^) := tbtU32(var1^) mod tbtu32(var2^);
+ btS32: tbtU32(var1^) := tbtU32(var1^) mod cardinal(tbts32(var2^));
+ {$IFNDEF PS_NOINT64} btS64: tbtU32(var1^) := tbtU32(var1^) mod tbts64(var2^);{$ENDIF}
+ btChar: tbtU32(var1^) := tbtU32(var1^) mod Ord(tbtchar(var2^));
+ {$IFNDEF PS_NOWIDESTRING} btWideChar: tbtU32(var1^) := tbtU32(var1^) mod Ord(tbtwidechar(var2^));{$ENDIF}
+ btVariant: tbtU32(var1^) := tbtU32(var1^) mod Variant(var2^);
+ else raise Exception.Create(RPS_TypeMismatch);
+ end;
+ end;
+ btS32:
+ begin
+ if var2type.BaseType = btPointer then
+ begin
+ var2type := PIFTypeRec(Pointer(IPointer(var2)+PointerSize)^);
+ var2 := Pointer(var2^);
+ if (var2 = nil) or (var2type = nil) then raise Exception.Create(RPS_TypeMismatch);
+ end;
+ case var2type.BaseType of
+ btU8: tbts32(var1^) := tbts32(var1^) mod tbtu8(var2^);
+ btS8: tbts32(var1^) := tbts32(var1^) mod tbts8(var2^);
+ btU16: tbts32(var1^) := tbts32(var1^) mod tbtu16(var2^);
+ btS16: tbts32(var1^) := tbts32(var1^) mod tbts16(var2^);
+ btU32: tbts32(var1^) := tbts32(var1^) mod Longint(tbtu32(var2^));
+ btS32: tbts32(var1^) := tbts32(var1^) mod tbts32(var2^);
+ {$IFNDEF PS_NOINT64} btS64: tbts32(var1^) := tbts32(var1^) mod tbts64(var2^);{$ENDIF}
+ btChar: tbts32(var1^) := tbts32(var1^) mod Ord(tbtchar(var2^));
+ {$IFNDEF PS_NOWIDESTRING} btWideChar: tbts32(var1^) := tbts32(var1^) mod Ord(tbtwidechar(var2^));{$ENDIF}
+ btVariant: tbts32(var1^) := tbts32(var1^) mod Variant(var2^);
+ else raise Exception.Create(RPS_TypeMismatch);
+ end;
+ end;
+ {$IFNDEF PS_NOINT64}
+ btS64: tbts64(var1^) := tbts64(var1^) mod PSGetInt64(var2, var2type);
+ {$ENDIF}
+ btVariant:
+ begin
+ if not IntPIFVariantToVariant(var2, var2type, tvar) then
+ begin
+ Result := false;
+ end else
+ Variant(var1^) := Variant(var1^) mod tvar;
+ end;
+ else begin
+ CMD_Err(erTypeMismatch);
+ exit;
+ end;
+ end;
+ if not Result then begin
+ CMD_Err(erTypeMismatch);
+ exit;
+ end;
+ end;
+ 5: begin { SHL }
+ case var1Type.BaseType of
+ btU8: tbtU8(var1^) := tbtU8(var1^) shl PSGetUInt(Var2, var2type);
+ btS8: tbts8(var1^) := tbts8(var1^) shl PSGetInt(Var2, var2type);
+ btU16: tbtU16(var1^) := tbtU16(var1^) shl PSGetUInt(Var2, var2type);
+ btS16: tbts16(var1^) := tbts16(var1^) shl PSGetInt(Var2, var2type);
+ btU32: tbtU32(var1^) := tbtU32(var1^) shl PSGetUInt(Var2, var2type);
+ btS32: tbts32(var1^) := tbts32(var1^) shl PSGetInt(Var2, var2type);
+ {$IFNDEF PS_NOINT64}
+ btS64: tbts64(var1^) := tbts64(var1^) shl PSGetInt64(var2, var2type);
+ {$ENDIF}
+ btVariant:
+ begin
+ if not IntPIFVariantToVariant(var2, var2type, tvar) then
+ begin
+ Result := false;
+ end else
+ Variant(var1^) := Variant(var1^) shl tvar;
+ end;
+ else begin
+ CMD_Err(erTypeMismatch);
+ exit;
+ end;
+ end;
+ if not Result then begin
+ CMD_Err(erTypeMismatch);
+ exit;
+ end;
+ end;
+ 6: begin { SHR }
+ case var1Type.BaseType of
+ btU8: tbtU8(var1^) := tbtU8(var1^) shr PSGetUInt(Var2, var2type);
+ btS8: tbts8(var1^) := tbts8(var1^) shr PSGetInt(Var2, var2type);
+ btU16: tbtU16(var1^) := tbtU16(var1^) shr PSGetUInt(Var2, var2type);
+ btS16: tbts16(var1^) := tbts16(var1^) shr PSGetInt(Var2, var2type);
+ btU32: tbtU32(var1^) := tbtU32(var1^) shr PSGetUInt(Var2, var2type);
+ btS32: tbts32(var1^) := tbts32(var1^) shr PSGetInt(Var2, var2type);
+ {$IFNDEF PS_NOINT64}
+ btS64: tbts64(var1^) := tbts64(var1^) shr PSGetInt64(var2, var2type);
+ {$ENDIF}
+ btVariant:
+ begin
+ if not IntPIFVariantToVariant(var2, var2type, tvar) then
+ begin
+ Result := false;
+ end else
+ Variant(var1^) := Variant(var1^) shr tvar;
+ end;
+ else begin
+ CMD_Err(erTypeMismatch);
+ exit;
+ end;
+ end;
+ if not Result then begin
+ CMD_Err(erTypeMismatch);
+ exit;
+ end;
+ end;
+ 7: begin { AND }
+ case var1Type.BaseType of
+ btU8: tbtU8(var1^) := tbtU8(var1^) and PSGetUInt(Var2, var2type);
+ btS8: tbts8(var1^) := tbts8(var1^) and PSGetInt(Var2, var2type);
+ btU16: tbtU16(var1^) := tbtU16(var1^) and PSGetUInt(Var2, var2type);
+ btS16: tbts16(var1^) := tbts16(var1^) and PSGetInt(Var2, var2type);
+ btU32: tbtU32(var1^) := tbtU32(var1^) and PSGetUInt(Var2, var2type);
+ btS32: tbts32(var1^) := tbts32(var1^) and PSGetInt(Var2, var2type);
+ {$IFNDEF PS_NOINT64}
+ btS64: tbts64(var1^) := tbts64(var1^) and PSGetInt64(var2, var2type);
+ {$ENDIF}
+ btVariant:
+ begin
+ if not IntPIFVariantToVariant(var2, var2type, tvar) then
+ begin
+ Result := false;
+ end else
+ Variant(var1^) := Variant(var1^) and tvar;
+ end;
+ else begin
+ CMD_Err(erTypeMismatch);
+ exit;
+ end;
+ end;
+ if not Result then begin
+ CMD_Err(erTypeMismatch);
+ exit;
+ end;
+ end;
+ 8: begin { OR }
+ case var1Type.BaseType of
+ btU8: tbtU8(var1^) := tbtU8(var1^) or PSGetUInt(Var2, var2type);
+ btS8: tbts8(var1^) := tbts8(var1^) or PSGetInt(Var2, var2type);
+ btU16: tbtU16(var1^) := tbtU16(var1^) or PSGetUInt(Var2, var2type);
+ btS16: tbts16(var1^) := tbts16(var1^) or PSGetInt(Var2, var2type);
+ btU32: tbtU32(var1^) := tbtU32(var1^) or PSGetUInt(Var2, var2type);
+ btS32: tbts32(var1^) := tbts32(var1^) or PSGetInt(Var2, var2type);
+ {$IFNDEF PS_NOINT64}
+ btS64: tbts64(var1^) := tbts64(var1^) or PSGetInt64(var2, var2type);
+ {$ENDIF}
+ btVariant:
+ begin
+ if not IntPIFVariantToVariant(var2, var2type, tvar) then
+ begin
+ Result := false;
+ end else
+ Variant(var1^) := Variant(var1^) or tvar;
+ end;
+ else begin
+ CMD_Err(erTypeMismatch);
+ exit;
+ end;
+ end;
+ if not Result then begin
+ CMD_Err(erTypeMismatch);
+ exit;
+ end;
+ end;
+ 9: begin { XOR }
+ case var1Type.BaseType of
+ btU8: tbtU8(var1^) := tbtU8(var1^) xor PSGetUInt(Var2, var2type);
+ btS8: tbts8(var1^) := tbts8(var1^) xor PSGetInt(Var2, var2type);
+ btU16: tbtU16(var1^) := tbtU16(var1^) xor PSGetUInt(Var2, var2type);
+ btS16: tbts16(var1^) := tbts16(var1^) xor PSGetInt(Var2, var2type);
+ btU32: tbtU32(var1^) := tbtU32(var1^) xor PSGetUInt(Var2, var2type);
+ btS32: tbts32(var1^) := tbts32(var1^) xor PSGetInt(Var2, var2type);
+ {$IFNDEF PS_NOINT64}
+ btS64: tbts64(var1^) := tbts64(var1^) xor PSGetInt64(var2, var2type);
+ {$ENDIF}
+ btVariant:
+ begin
+ if not IntPIFVariantToVariant(var2, var2type, tvar) then
+ begin
+ Result := false;
+ end else
+ Variant(var1^) := Variant(var1^) xor tvar;
+ end;
+ else begin
+ CMD_Err(erTypeMismatch);
+ exit;
+ end;
+ end;
+ if not Result then begin
+ CMD_Err(erTypeMismatch);
+ exit;
+ end;
+ end;
+ 10:
+ begin // as
+ case var1Type.BaseType of
+ btClass:
+ begin
+ if var2type.BaseType <> btU32 then
+ Result := False
+ else
+ begin
+ var2type := FTypes[tbtu32(var2^)];
+ if (var2type = nil) or (var2type.BaseType <> btClass) then
+ Result := false
+ else
+ begin
+ if not Class_IS(Self, TObject(var1^), var2type) then
+ Result := false
+ end;
+ end;
+ end;
+ else begin
+ CMD_Err(erTypeMismatch);
+ exit;
+ end;
+ end;
+ if not Result then begin
+ CMD_Err(erTypeMismatch);
+ exit;
+ end;
+ end;
+ else begin
+ Result := False;
+ CMD_Err(erInvalidOpcodeParameter);
+ exit;
+ end;
+ end;
+ except
+ {$IFDEF DELPHI6UP}
+ Tmp := AcquireExceptionObject;
+ {$ELSE}
+ if RaiseList <> nil then
+ begin
+ Tmp := Exception(PRaiseFrame(RaiseList)^.ExceptObject);
+ PRaiseFrame(RaiseList)^.ExceptObject := nil;
+ end else
+ Tmp := nil;
+ {$ENDIF}
+ if Tmp <> nil then
+ begin
+ if Tmp is EPSException then
+ begin
+ Result := False;
+ ExceptionProc(EPSException(tmp).ProcNo, EPSException(tmp).ProcPos, erCustomError, tbtString(EPSException(tmp).Message), nil);
+ exit;
+ end else
+ if Tmp is EDivByZero then
+ begin
+ Result := False;
+ CMD_Err3(erDivideByZero, '', Tmp);
+ Exit;
+ end;
+ if Tmp is EZeroDivide then
+ begin
+ Result := False;
+ CMD_Err3(erDivideByZero, '', Tmp);
+ Exit;
+ end;
+ if Tmp is EMathError then
+ begin
+ Result := False;
+ CMD_Err3(erMathError, '', Tmp);
+ Exit;
+ end;
+ end;
+ if (tmp <> nil) and (Tmp is Exception) then
+ CMD_Err3(erException, tbtString(Exception(Tmp).Message), Tmp)
+ else
+ CMD_Err3(erException, '', Tmp);
+ Result := False;
+ end;
+end;
+
+function TPSExec.ReadVariable(var Dest: TPSResultData; UsePointer: Boolean): Boolean;
+var
+ VarType: Cardinal;
+ Param: Cardinal;
+ Tmp: PIfVariant;
+ at: TPSTypeRec;
+
+begin
+ if FCurrentPosition + 4 >= FDataLength then
+ begin
+ CMD_Err(erOutOfRange); // Error
+ Result := False;
+ exit;
+ end;
+ VarType := FData^[FCurrentPosition];
+ Inc(FCurrentPosition);
+ {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
+ Param := unaligned(Cardinal((@FData^[FCurrentPosition])^));
+ {$else}
+ Param := Cardinal((@FData^[FCurrentPosition])^);
+ {$endif}
+ Inc(FCurrentPosition, 4);
+ case VarType of
+ 0:
+ begin
+ Dest.FreeType := vtNone;
+ if Param < PSAddrNegativeStackStart then
+ begin
+ if Param >= Cardinal(FGlobalVars.Count) then
+ begin
+ CMD_Err(erOutOfGlobalVarsRange);
+ Result := False;
+ exit;
+ end;
+ Tmp := FGlobalVars.Data[param];
+ end else
+ begin
+ Param := Cardinal(Longint(-PSAddrStackStart) +
+ Longint(FCurrStackBase) + Longint(Param));
+ if Param >= Cardinal(FStack.Count) then
+ begin
+ CMD_Err(erOutOfGlobalVarsRange);
+ Result := False;
+ exit;
+ end;
+ Tmp := FStack.Data[param];
+ end;
+ if (UsePointer) and (Tmp.FType.BaseType = btPointer) then
+ begin
+ Dest.aType := PPSVariantPointer(Tmp).DestType;
+ Dest.P := PPSVariantPointer(Tmp).DataDest;
+ if Dest.P = nil then
+ begin
+ Cmd_Err(erNullPointerException);
+ Result := False;
+ exit;
+ end;
+ end else
+ begin
+ Dest.aType := PPSVariantData(Tmp).vi.FType;
+ Dest.P := @PPSVariantData(Tmp).Data;
+ end;
+ end;
+ 1: begin
+ if Param >= FTypes.Count then
+ begin
+ CMD_Err(erInvalidType);
+ Result := False;
+ exit;
+ end;
+ at := FTypes.Data^[Param];
+ Param := FTempVars.FLength;
+ FTempVars.FLength := Cardinal(Longint(Param) + Longint(at.RealSize) + Longint(RTTISize + 3)) and not 3;
+ if FTempVars.FLength > FTempVars.FCapacity then FtempVars.AdjustLength;
+ Tmp := Pointer(IPointer(FtempVars.FDataPtr) + IPointer(Param));
+
+ if Cardinal(FTempVars.FCount) >= Cardinal(FTempVars.FCapacity) then
+ begin
+ Inc(FTempVars.FCapacity, FCapacityInc);// := FCount + 1;
+ ReAllocMem(FTempVars.FData, FTempVars.FCapacity shl 2);
+ end;
+ FTempVars.FData[FTempVars.FCount] := Tmp; // Instead of SetItem
+ Inc(FTempVars.FCount);
+ {$IFNDEF PS_NOSMARTLIST}
+ Inc(FTempVars.FCheckCount);
+ if FTempVars.FCheckCount > FMaxCheckCount then FTempVars.Recreate;
+ {$ENDIF}
+
+
+ Tmp.FType := at;
+ Dest.P := @PPSVariantData(Tmp).Data;
+ Dest.aType := tmp.FType;
+ dest.FreeType := vtTempVar;
+ case Dest.aType.BaseType of
+ btSet:
+ begin
+ if not ReadData(Dest.P^, TPSTypeRec_Set(Dest.aType).aByteSize) then
+ begin
+ CMD_Err(erOutOfRange);
+ FTempVars.Pop;
+ Result := False;
+ exit;
+ end;
+ end;
+ bts8, btchar, btU8:
+ begin
+ if FCurrentPosition >= FDataLength then
+ begin
+ CMD_Err(erOutOfRange);
+ FTempVars.Pop;
+ Result := False;
+ exit;
+ end;
+ tbtu8(dest.p^) := FData^[FCurrentPosition];
+ Inc(FCurrentPosition);
+ end;
+ bts16, {$IFNDEF PS_NOWIDESTRING}btwidechar,{$ENDIF} btU16:
+ begin
+ if FCurrentPosition + 1>= FDataLength then
+ begin
+ CMD_Err(erOutOfRange);
+ FTempVars.Pop;
+ Result := False;
+ exit;
+ end;
+ {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
+ tbtu16(dest.p^) := unaligned(tbtu16((@FData^[FCurrentPosition])^));
+ {$else}
+ tbtu16(dest.p^) := tbtu16((@FData^[FCurrentPosition])^);
+ {$endif}
+ Inc(FCurrentPosition, 2);
+ end;
+ bts32, btU32:
+ begin
+ if FCurrentPosition + 3>= FDataLength then
+ begin
+ CMD_Err(erOutOfRange);
+ FTempVars.Pop;
+ Result := False;
+ exit;
+ end;
+ {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
+ tbtu32(dest.p^) := unaligned(tbtu32((@FData^[FCurrentPosition])^));
+ {$else}
+ tbtu32(dest.p^) := tbtu32((@FData^[FCurrentPosition])^);
+ {$endif}
+ Inc(FCurrentPosition, 4);
+ end;
+ btProcPtr:
+ begin
+ if FCurrentPosition + 3>= FDataLength then
+ begin
+ CMD_Err(erOutOfRange);
+ FTempVars.Pop;
+ Result := False;
+ exit;
+ end;
+ {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
+ tbtu32(dest.p^) := unaligned(tbtu32((@FData^[FCurrentPosition])^));
+ {$else}
+ tbtu32(dest.p^) := tbtu32((@FData^[FCurrentPosition])^);
+ {$endif}
+ tbtu32(Pointer(IPointer(dest.p)+PointerSize)^) := 0;
+ tbtu32(Pointer(IPointer(dest.p)+PointerSize)^) := 0;
+ Inc(FCurrentPosition, 4);
+ end;
+ {$IFNDEF PS_NOINT64}
+ bts64:
+ begin
+ if FCurrentPosition + 7>= FDataLength then
+ begin
+ CMD_Err(erOutOfRange);
+ FTempVars.Pop;
+ Result := False;
+ exit;
+ end;
+ {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
+ tbts64(dest.p^) := unaligned(tbts64((@FData^[FCurrentPosition])^));
+ {$else}
+ tbts64(dest.p^) := tbts64((@FData^[FCurrentPosition])^);
+ {$endif}
+ Inc(FCurrentPosition, 8);
+ end;
+ {$ENDIF}
+ btSingle:
+ begin
+ if FCurrentPosition + (Sizeof(Single)-1)>= FDataLength then
+ begin
+ CMD_Err(erOutOfRange);
+ FTempVars.Pop;
+ Result := False;
+ exit;
+ end;
+ {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
+ tbtsingle(dest.p^) := unaligned(tbtsingle((@FData^[FCurrentPosition])^));
+ {$else}
+ tbtsingle(dest.p^) := tbtsingle((@FData^[FCurrentPosition])^);
+ {$endif}
+ Inc(FCurrentPosition, Sizeof(Single));
+ end;
+ btDouble:
+ begin
+ if FCurrentPosition + (Sizeof(Double)-1)>= FDataLength then
+ begin
+ CMD_Err(erOutOfRange);
+ FTempVars.Pop;
+ Result := False;
+ exit;
+ end;
+ {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
+ tbtdouble(dest.p^) := unaligned(tbtdouble((@FData^[FCurrentPosition])^));
+ {$else}
+ tbtdouble(dest.p^) := tbtdouble((@FData^[FCurrentPosition])^);
+ {$endif}
+ Inc(FCurrentPosition, Sizeof(double));
+ end;
+
+ btExtended:
+ begin
+ if FCurrentPosition + (sizeof(Extended)-1)>= FDataLength then
+ begin
+ CMD_Err(erOutOfRange);
+ FTempVars.Pop;
+ Result := False;
+ exit;
+ end;
+ {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
+ tbtextended(dest.p^) := unaligned(tbtextended((@FData^[FCurrentPosition])^));
+ {$else}
+ tbtextended(dest.p^) := tbtextended((@FData^[FCurrentPosition])^);
+ {$endif}
+ Inc(FCurrentPosition, sizeof(Extended));
+ end;
+ btPchar, btString:
+ begin
+ if FCurrentPosition + 3 >= FDataLength then
+ begin
+ Cmd_Err(erOutOfRange);
+ FTempVars.Pop;
+ Result := False;
+ exit;
+ end;
+ {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
+ Param := unaligned(Cardinal((@FData^[FCurrentPosition])^));
+ {$else}
+ Param := Cardinal((@FData^[FCurrentPosition])^);
+ {$endif}
+ Inc(FCurrentPosition, 4);
+ Pointer(Dest.P^) := nil;
+ SetLength(tbtstring(Dest.P^), Param);
+ if Param <> 0 then begin
+ if not ReadData(tbtstring(Dest.P^)[1], Param) then
+ begin
+ CMD_Err(erOutOfRange);
+ FTempVars.Pop;
+ Result := False;
+ exit;
+ end;
+ pansichar(dest.p^)[Param] := #0;
+ end;
+ end;
+ {$IFNDEF PS_NOWIDESTRING}
+ btWidestring:
+ begin
+ if FCurrentPosition + 3 >= FDataLength then
+ begin
+ Cmd_Err(erOutOfRange);
+ FTempVars.Pop;
+ Result := False;
+ exit;
+ end;
+ {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
+ Param := unaligned(Cardinal((@FData^[FCurrentPosition])^));
+ {$else}
+ Param := Cardinal((@FData^[FCurrentPosition])^);
+ {$endif}
+ Inc(FCurrentPosition, 4);
+ Pointer(Dest.P^) := nil;
+ SetLength(tbtwidestring(Dest.P^), Param);
+ if not ReadData(tbtwidestring(Dest.P^)[1], Param*2) then
+ begin
+ CMD_Err(erOutOfRange);
+ FTempVars.Pop;
+ Result := False;
+ exit;
+ end;
+ end;
+ btUnicodeString:
+ begin
+ if FCurrentPosition + 3 >= FDataLength then
+ begin
+ Cmd_Err(erOutOfRange);
+ FTempVars.Pop;
+ Result := False;
+ exit;
+ end;
+ {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
+ Param := unaligned(Cardinal((@FData^[FCurrentPosition])^));
+ {$else}
+ Param := Cardinal((@FData^[FCurrentPosition])^);
+ {$endif}
+ Inc(FCurrentPosition, 4);
+ Pointer(Dest.P^) := nil;
+ SetLength(tbtUnicodestring(Dest.P^), Param);
+ if not ReadData(tbtUnicodestring(Dest.P^)[1], Param*2) then
+ begin
+ CMD_Err(erOutOfRange);
+ FTempVars.Pop;
+ Result := False;
+ exit;
+ end;
+ end;
+ {$ENDIF}
+ else begin
+ CMD_Err(erInvalidType);
+ FTempVars.Pop;
+ Result := False;
+ exit;
+ end;
+ end;
+ end;
+ 2:
+ begin
+ Dest.FreeType := vtNone;
+ if Param < PSAddrNegativeStackStart then begin
+ if Param >= Cardinal(FGlobalVars.Count) then
+ begin
+ CMD_Err(erOutOfGlobalVarsRange);
+ Result := False;
+ exit;
+ end;
+ Tmp := FGlobalVars.Data[param];
+ end
+ else begin
+ Param := Cardinal(Longint(-PSAddrStackStart) + Longint(FCurrStackBase) + Longint(Param));
+ if Param >= Cardinal(FStack.Count) then
+ begin
+ CMD_Err(erOutOfStackRange);
+ Result := False;
+ exit;
+ end;
+ Tmp := FStack.Data[param];
+ end;
+ if Tmp.FType.BaseType = btPointer then
+ begin
+ Dest.aType := PPSVariantPointer(Tmp).DestType;
+ Dest.P := PPSVariantPointer(Tmp).DataDest;
+ if Dest.P = nil then
+ begin
+ Cmd_Err(erNullPointerException);
+ Result := False;
+ exit;
+ end;
+ end else
+ begin
+ Dest.aType := PPSVariantData(Tmp).vi.FType;
+ Dest.P := @PPSVariantData(Tmp).Data;
+ end;
+ if FCurrentPosition + 3 >= FDataLength then
+ begin
+ CMD_Err(erOutOfRange);
+ Result := False;
+ exit;
+ end;
+ {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
+ Param := unaligned(Cardinal((@FData^[FCurrentPosition])^));
+ {$else}
+ Param := Cardinal((@FData^[FCurrentPosition])^);
+ {$endif}
+ Inc(FCurrentPosition, 4);
+ case Dest.aType.BaseType of
+ btRecord:
+ begin
+ if Param > Cardinal(TPSTypeRec_Record(Dest.aType).FFieldTypes.Count) then
+ begin
+ CMD_Err(erOutOfRange);
+ Result := False;
+ exit;
+ end;
+ Dest.P := Pointer(IPointer(Dest.P) + IPointer(TPSTypeRec_Record(Dest.aType).RealFieldOffsets[Param]));
+ Dest.aType := TPSTypeRec_Record(Dest.aType).FieldTypes[Param];
+ end;
+ btArray:
+ begin
+ if Param >= Cardinal(PSDynArrayGetLength(Pointer(Dest.P^), dest.aType)) then
+ begin
+ CMD_Err(erOutOfRange);
+ Result := False;
+ exit;
+ end;
+ Dest.P := Pointer(IPointer(Dest.P^) + (Param * TPSTypeRec_Array(Dest.aType).FArrayType.RealSize));
+ Dest.aType := TPSTypeRec_Array(dest.aType).ArrayType;
+ end;
+ btStaticArray:
+ begin
+ if Param >= Cardinal(TPSTypeRec_StaticArray(Dest.aType).Size) then
+ begin
+ CMD_Err(erOutOfRange);
+ Result := False;
+ exit;
+ end;
+ Dest.P := Pointer(IPointer(Dest.P) + (Param * TPSTypeRec_Array(Dest.aType).FArrayType.RealSize));
+ Dest.aType := TPSTypeRec_Array(dest.aType).ArrayType;
+ end;
+ else
+ CMD_Err(erInvalidType);
+ Result := False;
+ exit;
+ end;
+
+ if UsePointer and (Dest.aType.BaseType = btPointer) then
+ begin
+ Dest.aType := TPSTypeRec(Pointer(IPointer(Dest.p)+PointerSize)^);
+ Dest.P := Pointer(Dest.p^);
+ if Dest.P = nil then
+ begin
+ Cmd_Err(erNullPointerException);
+ Result := False;
+ exit;
+ end;
+ end;
+ end;
+ 3:
+ begin
+ Dest.FreeType := vtNone;
+ if Param < PSAddrNegativeStackStart then begin
+ if Param >= Cardinal(FGlobalVars.Count) then
+ begin
+ CMD_Err(erOutOfGlobalVarsRange);
+ Result := False;
+ exit;
+ end;
+ Tmp := FGlobalVars.Data[param];
+ end
+ else begin
+ Param := Cardinal(Longint(-PSAddrStackStart) + Longint(FCurrStackBase) + Longint(Param));
+ if Param >= Cardinal(FStack.Count) then
+ begin
+ CMD_Err(erOutOfStackRange);
+ Result := False;
+ exit;
+ end;
+ Tmp := FStack.Data[param];
+ end;
+ if (Tmp.FType.BaseType = btPointer) then
+ begin
+ Dest.aType := PPSVariantPointer(Tmp).DestType;
+ Dest.P := PPSVariantPointer(Tmp).DataDest;
+ if Dest.P = nil then
+ begin
+ Cmd_Err(erNullPointerException);
+ Result := False;
+ exit;
+ end;
+ end else
+ begin
+ Dest.aType := PPSVariantData(Tmp).vi.FType;
+ Dest.P := @PPSVariantData(Tmp).Data;
+ end;
+ {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
+ Param := unaligned(Cardinal((@FData^[FCurrentPosition])^));
+ {$else}
+ Param := Cardinal((@FData^[FCurrentPosition])^);
+ {$endif}
+ Inc(FCurrentPosition, 4);
+ if Param < PSAddrNegativeStackStart then
+ begin
+ if Param >= Cardinal(FGlobalVars.Count) then
+ begin
+ CMD_Err(erOutOfGlobalVarsRange);
+ Result := false;
+ exit;
+ end;
+ Tmp := FGlobalVars[Param];
+ end
+ else begin
+ Param := Cardinal(Longint(-PSAddrStackStart) + Longint(FCurrStackBase) + Longint(Param));
+ if Cardinal(Param) >= Cardinal(FStack.Count) then
+ begin
+ CMD_Err(erOutOfStackRange);
+ Result := false;
+ exit;
+ end;
+ Tmp := FStack[Param];
+ end;
+ case Tmp.FType.BaseType of
+ btu8: Param := PPSVariantU8(Tmp).Data;
+ bts8: Param := PPSVariants8(Tmp).Data;
+ btu16: Param := PPSVariantU16(Tmp).Data;
+ bts16: Param := PPSVariants16(Tmp).Data;
+ btu32: Param := PPSVariantU32(Tmp).Data;
+ bts32: Param := PPSVariants32(Tmp).Data;
+ btPointer:
+ begin
+ if PPSVariantPointer(tmp).DestType <> nil then
+ begin
+ case PPSVariantPointer(tmp).DestType.BaseType of
+ btu8: Param := tbtu8(PPSVariantPointer(tmp).DataDest^);
+ bts8: Param := tbts8(PPSVariantPointer(tmp).DataDest^);
+ btu16: Param := tbtu16(PPSVariantPointer(tmp).DataDest^);
+ bts16: Param := tbts16(PPSVariantPointer(tmp).DataDest^);
+ btu32, btProcPtr: Param := tbtu32(PPSVariantPointer(tmp).DataDest^);
+ bts32: Param := tbts32(PPSVariantPointer(tmp).DataDest^);
+ else
+ begin
+ CMD_Err(ErTypeMismatch);
+ Result := false;
+ exit;
+ end;
+ end;
+ end else
+ begin
+ CMD_Err(ErTypeMismatch);
+ Result := false;
+ exit;
+ end;
+ end;
+ else
+ CMD_Err(ErTypeMismatch);
+ Result := false;
+ exit;
+ end;
+ case Dest.aType.BaseType of
+ btRecord:
+ begin
+ if Param > Cardinal(TPSTypeRec_Record(Dest.aType).FFieldTypes.Count) then
+ begin
+ CMD_Err(erOutOfRange);
+ Result := False;
+ exit;
+ end;
+ Dest.P := Pointer(IPointer(Dest.P) + IPointer(TPSTypeRec_Record(Dest.aType).RealFieldOffsets[Param]));
+ Dest.aType := TPSTypeRec_Record(Dest.aType).FieldTypes[Param];
+ end;
+ btArray:
+ begin
+ if Cardinal(Param) >= Cardinal(PSDynArrayGetLength(Pointer(Dest.P^), dest.aType)) then
+ begin
+ CMD_Err(erOutOfRange);
+ Result := False;
+ exit;
+ end;
+ Dest.P := Pointer(IPointer(Dest.P^) + (Param * TPSTypeRec_Array(Dest.aType).FArrayType.RealSize));
+ Dest.aType := TPSTypeRec_Array(dest.aType).ArrayType;
+ end;
+ btStaticArray:
+ begin
+ if Param >= Cardinal(TPSTypeRec_StaticArray(Dest.aType).Size) then
+ begin
+ CMD_Err(erOutOfRange);
+ Result := False;
+ exit;
+ end;
+ Dest.P := Pointer(IPointer(Dest.P) + (Param * TPSTypeRec_Array(Dest.aType).FArrayType.RealSize));
+ Dest.aType := TPSTypeRec_Array(dest.aType).ArrayType;
+ end;
+ else
+ CMD_Err(erInvalidType);
+ Result := False;
+ exit;
+ end;
+ if UsePointer and (Dest.aType.BaseType = btPointer) then
+ begin
+ Dest.aType := TPSTypeRec(Pointer(IPointer(Dest.p)+PointerSize)^);
+ Dest.P := Pointer(Dest.p^);
+ if Dest.P = nil then
+ begin
+ Cmd_Err(erNullPointerException);
+ Result := False;
+ exit;
+ end;
+ end;
+ end;
+ else
+ begin
+ Result := False;
+ exit;
+ end;
+ end;
+ Result := true;
+end;
+
+function TPSExec.DoMinus(Dta: Pointer; aType: TPSTypeRec): Boolean;
+begin
+ case atype.BaseType of
+ btU8: tbtu8(dta^) := -tbtu8(dta^);
+ btU16: tbtu16(dta^) := -tbtu16(dta^);
+ btU32: tbtu32(dta^) := -tbtu32(dta^);
+ btS8: tbts8(dta^) := -tbts8(dta^);
+ btS16: tbts16(dta^) := -tbts16(dta^);
+ btS32: tbts32(dta^) := -tbts32(dta^);
+ {$IFNDEF PS_NOINT64}
+ bts64: tbts64(dta^) := -tbts64(dta^);
+ {$ENDIF}
+ btSingle: tbtsingle(dta^) := -tbtsingle(dta^);
+ btDouble: tbtdouble(dta^) := -tbtdouble(dta^);
+ btExtended: tbtextended(dta^) := -tbtextended(dta^);
+ btCurrency: tbtcurrency(dta^) := -tbtcurrency(dta^);
+ btVariant:
+ begin
+ try
+ Variant(dta^) := - Variant(dta^);
+ except
+ CMD_Err(erTypeMismatch);
+ Result := False;
+ exit;
+ end;
+ end;
+ else
+ begin
+ CMD_Err(erTypeMismatch);
+ Result := False;
+ exit;
+ end;
+ end;
+ Result := True;
+end;
+
+function TPSExec.DoBooleanNot(Dta: Pointer; aType: TPSTypeRec): Boolean;
+begin
+ case aType.BaseType of
+ btU8: tbtu8(dta^) := tbtu8(tbtu8(dta^) = 0);
+ btU16: tbtu16(dta^) := tbtu16(tbtu16(dta^) = 0);
+ btU32: tbtu32(dta^) := tbtu32(tbtu32(dta^) = 0);
+ btS8: tbts8(dta^) := tbts8(tbts8(dta^) = 0);
+ btS16: tbts16(dta^) := tbts16(tbts16(dta^) = 0);
+ btS32: tbts32(dta^) := tbts32(tbts32(dta^) = 0);
+ {$IFNDEF PS_NOINT64}
+ bts64: tbts64(dta^) := tbts64(tbts64(dta^) = 0);
+ {$ENDIF}
+ btVariant:
+ begin
+ try
+ Variant(dta^) := Variant(dta^) = 0;
+ except
+ CMD_Err(erTypeMismatch);
+ Result := False;
+ exit;
+ end;
+ end;
+ else
+ begin
+ CMD_Err(erTypeMismatch);
+ Result := False;
+ exit;
+ end;
+ end;
+ Result := True;
+end;
+
+
+procedure TPSExec.Stop;
+begin
+ if FStatus = isRunning then
+ FStatus := isLoaded
+ else if FStatus = isPaused then begin
+ FStatus := isLoaded;
+ FStack.Clear;
+ FTempVars.Clear;
+ end;
+end;
+
+
+function TPSExec.ReadLong(var b: Cardinal): Boolean;
+begin
+ if FCurrentPosition + 3 < FDataLength then begin
+ {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
+ b := unaligned(Cardinal((@FData^[FCurrentPosition])^));
+ {$else}
+ b := Cardinal((@FData^[FCurrentPosition])^);
+ {$endif}
+ Inc(FCurrentPosition, 4);
+ Result := True;
+ end
+ else
+ Result := False;
+end;
+
+function TPSExec.RunProcP(const Params: array of Variant; const Procno: Cardinal): Variant;
+var
+ ParamList: TPSList;
+ ct: PIFTypeRec;
+ pvar: PPSVariant;
+ res, s: tbtString;
+ Proc: TPSInternalProcRec;
+ i: Longint;
+begin
+ if ProcNo >= FProcs.Count then raise Exception.Create(RPS_UnknownProcedure);
+ Proc := GetProcNo(ProcNo) as TPSInternalProcRec;
+ ParamList := TPSList.Create;
+ try
+ s := Proc.ExportDecl;
+ res := grfw(s);
+ i := High(Params);
+ while s <> '' do
+ begin
+ if i < 0 then raise Exception.Create(RPS_NotEnoughParameters);
+ ct := FTypes[StrToInt(copy(GRLW(s), 2, MaxInt))];
+ if ct = nil then raise Exception.Create(RPS_InvalidParameter);
+ pvar := CreateHeapVariant(ct);
+ ParamList.Add(pvar);
+
+ if not VariantToPIFVariant(Self, Params[i], pvar) then raise Exception.Create(RPS_InvalidParameter);
+
+ Dec(i);
+ end;
+ if I > -1 then raise Exception.Create(RPS_TooManyParameters);
+ if res <> '-1' then
+ begin
+ pvar := CreateHeapVariant(FTypes[StrToInt(res)]);
+ ParamList.Add(pvar);
+ end else
+ pvar := nil;
+
+ RunProc(ParamList, ProcNo);
+
+ RaiseCurrentException;
+
+ if pvar <> nil then
+ begin
+ PIFVariantToVariant(PVar, Result);
+ end else
+ Result := Null;
+ finally
+ FreePIFVariantList(ParamList);
+ end;
+end;
+function TPSExec.RunProcPVar(var Params: array of Variant; const Procno: Cardinal): Variant;
+var
+ ParamList: TPSList;
+ ct: PIFTypeRec;
+ pvar: PPSVariant;
+ res, s: tbtString;
+ Proc: TPSInternalProcRec;
+ i: Longint;
+begin
+ if ProcNo >= FProcs.Count then raise Exception.Create(RPS_UnknownProcedure);
+ Proc := GetProcNo(ProcNo) as TPSInternalProcRec;
+ ParamList := TPSList.Create;
+ try
+ s := Proc.ExportDecl;
+ res := grfw(s);
+ i := High(Params);
+ while s <> '' do
+ begin
+ if i < 0 then raise Exception.Create(RPS_NotEnoughParameters);
+ ct := FTypes[StrToInt(copy(GRLW(s), 2, MaxInt))];
+ if ct = nil then raise Exception.Create(RPS_InvalidParameter);
+ pvar := CreateHeapVariant(ct);
+ ParamList.Add(pvar);
+
+ if not VariantToPIFVariant(Self, Params[i], pvar) then raise Exception.Create(RPS_InvalidParameter);
+
+ Dec(i);
+ end;
+ if I > -1 then raise Exception.Create(RPS_TooManyParameters);
+ if res <> '-1' then
+ begin
+ pvar := CreateHeapVariant(FTypes[StrToInt(res)]);
+ ParamList.Add(pvar);
+ end else
+ pvar := nil;
+
+ RunProc(ParamList, ProcNo);
+
+ RaiseCurrentException;
+
+ for i := 0 to Length(Params) - 1 do
+ PIFVariantToVariant(ParamList[i],
+ Params[(Length(Params) - 1) - i]);
+
+ if pvar <> nil then
+ begin
+ PIFVariantToVariant(PVar, Result);
+ end else
+ Result := Null;
+ finally
+ FreePIFVariantList(ParamList);
+ end;
+end;
+
+function TPSExec.RunProcPN(const Params: array of Variant; const ProcName: tbtString): Variant;
+var
+ ProcNo: Cardinal;
+begin
+ ProcNo := GetProc(ProcName);
+ if ProcNo = InvalidVal then
+ raise Exception.Create(RPS_UnknownProcedure);
+ Result := RunProcP(Params, ProcNo);
+end;
+
+
+function TPSExec.RunProc(Params: TPSList; ProcNo: Cardinal): Boolean;
+var
+ I, I2: Integer;
+ vnew, Vd: PIfVariant;
+ Cp: TPSInternalProcRec;
+ oldStatus: TPSStatus;
+ tmp: TObject;
+begin
+ if FStatus <> isNotLoaded then begin
+ if ProcNo >= FProcs.Count then begin
+ CMD_Err(erOutOfProcRange);
+ Result := False;
+ exit;
+ end;
+ if Params <> nil then
+ begin
+ for I := 0 to Params.Count - 1 do
+ begin
+ vd := Params[I];
+ if vd = nil then
+ begin
+ Result := False;
+ exit;
+ end;
+ vnew := FStack.PushType(FindType2(btPointer));
+ if vd.FType.BaseType = btPointer then
+ begin
+ PPSVariantPointer(vnew).DestType := PPSVariantPointer(vd).DestType;
+ PPSVariantPointer(vnew).DataDest := PPSVariantPointer(vd).DataDest;
+ end else begin
+ PPSVariantPointer(vnew).DestType := vd.FType;
+ PPSVariantPointer(vnew).DataDest := @PPSVariantData(vd).Data;
+ end;
+ end;
+ end;
+ I := FStack.Count;
+ Cp := FCurrProc;
+ oldStatus := FStatus;
+ if TPSProcRec(FProcs.Data^[ProcNo]).ClassType <> TPSExternalProcRec then
+ begin
+ vd := FStack.PushType(FReturnAddressType);
+ PPSVariantReturnAddress(vd).Addr.ProcNo := nil;
+ PPSVariantReturnAddress(vd).Addr.Position := FCurrentPosition;
+ PPSVariantReturnAddress(vd).Addr.StackBase := FCurrStackBase;
+ FCurrStackBase := FStack.Count - 1;
+ FCurrProc := FProcs.Data^[ProcNo];
+ FData := FCurrProc.Data;
+ FDataLength := FCurrProc.Length;
+ FCurrentPosition := 0;
+ FStatus := isPaused;
+ Result := RunScript;
+ end else
+ begin
+ try
+ Result := TPSExternalProcRec(FProcs.Data^[ProcNo]).ProcPtr(Self, TPSExternalProcRec(FProcs.Data^[ProcNo]), FGlobalVars, FStack);
+ if not Result then
+ begin
+ if ExEx = erNoError then
+ CMD_Err(erCouldNotCallProc);
+ end;
+ except
+ {$IFDEF DELPHI6UP}
+ Tmp := AcquireExceptionObject;
+ {$ELSE}
+ if RaiseList <> nil then
+ begin
+ Tmp := Exception(PRaiseFrame(RaiseList)^.ExceptObject);
+ PRaiseFrame(RaiseList)^.ExceptObject := nil;
+ end else
+ Tmp := nil;
+ {$ENDIF}
+ if Tmp <> nil then
+ begin
+ if Tmp is EPSException then
+ begin
+ Result := False;
+ ExceptionProc(EPSException(tmp).ProcNo, EPSException(tmp).ProcPos, erCustomError, tbtString(EPSException(tmp).Message), nil);
+ exit;
+ end else
+ if Tmp is EDivByZero then
+ begin
+ Result := False;
+ CMD_Err3(erDivideByZero, '', Tmp);
+ Exit;
+ end;
+ if Tmp is EZeroDivide then
+ begin
+ Result := False;
+ CMD_Err3(erDivideByZero, '', Tmp);
+ Exit;
+ end;
+ if Tmp is EMathError then
+ begin
+ Result := False;
+ CMD_Err3(erMathError, '', Tmp);
+ Exit;
+ end;
+ end;
+ if (Tmp <> nil) and (Tmp is Exception) then
+ CMD_Err3(erException, tbtString(Exception(Tmp).Message), Tmp) else
+ CMD_Err3(erException, '', Tmp);
+ Result := false;
+ exit;
+ end;
+ end;
+ if Cardinal(FStack.Count) > Cardinal(I) then
+ begin
+ vd := FStack[I];
+ if (vd <> nil) and (vd.FType = FReturnAddressType) then
+ begin
+ for i2 := FStack.Count - 1 downto I + 1 do
+ FStack.Pop;
+ FCurrentPosition := PPSVariantReturnAddress(vd).Addr.Position;
+ FCurrStackBase := PPSVariantReturnAddress(vd).Addr.StackBase;
+ FStack.Pop;
+ end;
+ end;
+ if Params <> nil then
+ begin
+ for I := Params.Count - 1 downto 0 do
+ begin
+ if FStack.Count = 0 then
+ Break
+ else
+ FStack.Pop;
+ end;
+ end;
+ FStatus := oldStatus;
+ FCurrProc := Cp;
+ if FCurrProc <> nil then
+ begin
+ FData := FCurrProc.Data;
+ FDataLength := FCurrProc.Length;
+ end;
+ end else begin
+ Result := False;
+ end;
+end;
+
+
+function TPSExec.FindType2(BaseType: TPSBaseType): PIFTypeRec;
+var
+ l: Cardinal;
+begin
+ FindType2 := FindType(0, BaseType, l);
+
+end;
+
+function TPSExec.FindType(StartAt: Cardinal; BaseType: TPSBaseType; var l: Cardinal): PIFTypeRec;
+var
+ I: Integer;
+ n: PIFTypeRec;
+begin
+ for I := StartAt to FTypes.Count - 1 do begin
+ n := FTypes[I];
+ if n.BaseType = BaseType then begin
+ l := I;
+ Result := n;
+ exit;
+ end;
+ end;
+ Result := nil;
+end;
+
+function TPSExec.GetTypeNo(l: Cardinal): PIFTypeRec;
+begin
+ Result := FTypes[l];
+end;
+
+function TPSExec.GetProc(const Name: tbtString): Cardinal;
+var
+ MM,
+ I: Longint;
+ n: PIFProcRec;
+ s: tbtString;
+begin
+ s := FastUpperCase(name);
+ MM := MakeHash(s);
+ for I := FProcs.Count - 1 downto 0 do begin
+ n := FProcs.Data^[I];
+ if (n.ClassType = TPSInternalProcRec) and (TPSInternalProcRec(n).ExportNameHash = MM) and (TPSInternalProcRec(n).ExportName = s) then begin
+ Result := I;
+ exit;
+ end else if (n.ClassType = TPSExternalProcRec) and (TPSExternalProcRec(n).Name = s) then
+ begin
+ Result := I;
+ exit;
+ end;
+ end;
+ Result := InvalidVal;
+end;
+
+function TPSExec.GetType(const Name: tbtString): Cardinal;
+var
+ MM,
+ I: Longint;
+ n: PIFTypeRec;
+ s: tbtString;
+begin
+ s := FastUpperCase(name);
+ MM := MakeHash(s);
+ for I := 0 to FTypes.Count - 1 do begin
+ n := FTypes.Data^[I];
+ if (Length(n.ExportName) <> 0) and (n.ExportNameHash = MM) and (n.ExportName = s) then begin
+ Result := I;
+ exit;
+ end;
+ end;
+ Result := InvalidVal;
+end;
+
+
+procedure TPSExec.AddResource(Proc, P: Pointer);
+var
+ Temp: PPSResource;
+begin
+ New(Temp);
+ Temp^.Proc := Proc;
+ Temp^.P := p;
+ FResources.Add(temp);
+end;
+
+procedure TPSExec.DeleteResource(P: Pointer);
+var
+ i: Longint;
+begin
+ for i := Longint(FResources.Count) -1 downto 0 do
+ begin
+ if PPSResource(FResources[I])^.P = P then
+ begin
+ FResources.Delete(I);
+ exit;
+ end;
+ end;
+end;
+
+function TPSExec.FindProcResource(Proc: Pointer): Pointer;
+var
+ I: Longint;
+ temp: PPSResource;
+begin
+ for i := Longint(FResources.Count) -1 downto 0 do
+ begin
+ temp := FResources[I];
+ if temp^.Proc = proc then
+ begin
+ Result := Temp^.P;
+ exit;
+ end;
+ end;
+ Result := nil;
+end;
+
+function TPSExec.IsValidResource(Proc, P: Pointer): Boolean;
+var
+ i: Longint;
+ temp: PPSResource;
+begin
+ for i := 0 to Longint(FResources.Count) -1 do
+ begin
+ temp := FResources[i];
+ if temp^.p = p then begin
+ result := temp^.Proc = Proc;
+ exit;
+ end;
+ end;
+ result := false;
+end;
+
+function TPSExec.FindProcResource2(Proc: Pointer;
+ var StartAt: Longint): Pointer;
+var
+ I: Longint;
+ temp: PPSResource;
+begin
+ if StartAt > longint(FResources.Count) -1 then
+ StartAt := longint(FResources.Count) -1;
+ for i := StartAt downto 0 do
+ begin
+ temp := FResources[I];
+ if temp^.Proc = proc then
+ begin
+ Result := Temp^.P;
+ StartAt := i -1;
+ exit;
+ end;
+ end;
+ StartAt := -1;
+ Result := nil;
+end;
+
+procedure TPSExec.RunLine;
+begin
+ if @FOnRunLine <> nil then
+ FOnRunLine(Self);
+end;
+
+procedure TPSExec.CMD_Err3(EC: TPSError; const Param: tbtString; ExObject: TObject);
+var
+ l: Longint;
+ C: Cardinal;
+begin
+ C := InvalidVal;
+ for l := FProcs.Count - 1 downto 0 do begin
+ if FProcs.Data^[l] = FCurrProc then begin
+ C := l;
+ break;
+ end;
+ end;
+ if @FOnException <> nil then
+ FOnException(Self, Ec, Param, ExObject, C, FCurrentPosition);
+ ExceptionProc(C, FCurrentPosition, EC, Param, ExObject);
+end;
+
+procedure TPSExec.AddSpecialProcImport(const FName: tbtString;
+ P: TPSOnSpecialProcImport; Tag: Pointer);
+var
+ N: PSpecialProc;
+begin
+ New(n);
+ n^.P := P;
+ N^.Name := FName;
+ n^.namehash := MakeHash(N^.Name);
+ n^.Tag := Tag;
+ FSpecialProcList.Add(n);
+end;
+
+function TPSExec.GetVar(const Name: tbtString): Cardinal;
+var
+ l: Longint;
+ h: longint;
+ s: tbtString;
+ p: PPSExportedVar;
+begin
+ s := FastUpperCase(name);
+ h := MakeHash(s);
+ for l := FExportedVars.Count - 1 downto 0 do
+ begin
+ p := FexportedVars.Data^[L];
+ if (p^.FNameHash = h) and(p^.FName=s) then
+ begin
+ Result := L;
+ exit;
+ end;
+ end;
+ Result := InvalidVal;
+end;
+
+function TPSExec.GetVarNo(C: Cardinal): PIFVariant;
+begin
+ Result := FGlobalVars[c];
+end;
+
+function TPSExec.GetVar2(const Name: tbtString): PIFVariant;
+begin
+ Result := GetVarNo(GetVar(Name));
+end;
+
+function TPSExec.GetProcNo(C: Cardinal): PIFProcRec;
+begin
+ Result := FProcs[c];
+end;
+
+function TPSExec.DoIntegerNot(Dta: Pointer; aType: TPSTypeRec): Boolean;
+begin
+ case aType.BaseType of
+ btU8: tbtu8(dta^) := not tbtu8(dta^);
+ btU16: tbtu16(dta^) := not tbtu16(dta^);
+ btU32: tbtu32(dta^) := not tbtu32(dta^);
+ btS8: tbts8(dta^) := not tbts8(dta^);
+ btS16: tbts16(dta^) := not tbts16(dta^);
+ btS32: tbts32(dta^) := not tbts32(dta^);
+ {$IFNDEF PS_NOINT64}
+ bts64: tbts64(dta^) := not tbts64(dta^);
+ {$ENDIF}
+ btVariant:
+ begin
+ try
+ Variant(dta^) := not Variant(dta^);
+ except
+ CMD_Err(erTypeMismatch);
+ Result := False;
+ exit;
+ end;
+ end;
+ else
+ begin
+ CMD_Err(erTypeMismatch);
+ Result := False;
+ exit;
+ end;
+ end;
+ Result := True;
+end;
+
+type
+ TMyRunLine = procedure(Self: TPSExec);
+ TPSRunLine = procedure of object;
+
+function GetRunLine(FOnRunLine: TPSOnLineEvent; meth: TPSRunLine): TMyRunLine;
+begin
+ if (TMethod(Meth).Code = @TPSExec.RunLine) and (@FOnRunLine = nil) then
+ Result := nil
+ else
+ Result := TMethod(Meth).Code;
+end;
+
+function TPSExec.RunScript: Boolean;
+var
+ CalcType: Cardinal;
+ vd, vs, v3: TPSResultData;
+ vtemp: PIFVariant;
+ p: Cardinal;
+ P2: Longint;
+ u: PIFProcRec;
+ Cmd: Cardinal;
+ I: Longint;
+ pp: TPSExceptionHandler;
+ FExitPoint: Cardinal;
+ FOldStatus: TPSStatus;
+ Tmp: TObject;
+ btemp: Boolean;
+ CallRunline: TMyRunLine;
+begin
+ FExitPoint := InvalidVal;
+ if FStatus = isLoaded then
+ begin
+ for i := FExceptionStack.Count -1 downto 0 do
+ begin
+ pp := FExceptionStack.Data[i];
+ pp.Free;
+ end;
+ FExceptionStack.Clear;
+ end;
+ ExceptionProc(InvalidVal, InvalidVal, erNoError, '', nil);
+ RunScript := True;
+ FOldStatus := FStatus;
+ case FStatus of
+ isLoaded: begin
+ if FMainProc = InvalidVal then
+ begin
+ RunScript := False;
+ exit;
+ end;
+ FStatus := isRunning;
+ FCurrProc := FProcs.Data^[FMainProc];
+ if FCurrProc.ClassType = TPSExternalProcRec then begin
+ CMD_Err(erNoMainProc);
+ FStatus := isLoaded;
+ exit;
+ end;
+ FData := FCurrProc.Data;
+ FDataLength := FCurrProc.Length;
+ FCurrStackBase := InvalidVal;
+ FCurrentPosition := 0;
+ end;
+ isPaused: begin
+ FStatus := isRunning;
+ end;
+ else begin
+ RunScript := False;
+ exit;
+ end;
+ end;
+ CallRunLine := GetRunLine(FOnRunLine, Self.RunLine);
+ repeat
+ FStatus := isRunning;
+// Cmd := InvalidVal;
+ while FStatus = isRunning do
+ begin
+ if @CallRunLine <> nil then CallRunLine(Self);
+ if FCurrentPosition >= FDataLength then
+ begin
+ CMD_Err(erOutOfRange); // Error
+ break;
+ end;
+// if cmd <> invalidval then ProfilerExitProc(Cmd+1);
+ cmd := FData^[FCurrentPosition];
+// ProfilerEnterProc(Cmd+1);
+ Inc(FCurrentPosition);
+ case Cmd of
+ CM_A:
+ begin
+ if not ReadVariable(vd, True) then
+ break;
+ if vd.FreeType <> vtNone then
+ begin
+ if vd.aType.BaseType in NeedFinalization then
+ FinalizeVariant(vd.P, vd.aType);
+ p := IPointer(FTempVars.Data^[FtempVars.Count-1]) - IPointer(FtempVars.DataPtr);
+ Dec(FTempVars.FCount);
+ {$IFNDEF PS_NOSMARTLIST}
+ Inc(FTempVars.FCheckCount);
+ if FTempVars.FCheckCount > FMaxCheckCount then FTempVars.Recreate;
+ {$ENDIF}
+ FTempVars.FLength := P;
+ if ((FTempVars.FCapacity - FTempVars.FLength) shr 12) > 2 then FTempVars.AdjustLength;
+
+ CMD_Err(erInvalidOpcodeParameter);
+ break;
+ end;
+ if not ReadVariable(vs, True) then
+ Break;
+ // nx change end
+{ if (vd.aType.BaseType = btClass) and (vs.aType.BaseType in [btS32]) then
+ DWord(vd.P^):=Dword(vs.P^)
+ else
+ if (vd.aType.BaseType in [btS32]) and (vs.aType.BaseType = btClass) then
+ DWord(vd.P^):=Dword(vs.P^)
+ else}
+ // nx change start
+ if not SetVariantValue(vd.P, vs.P, vd.aType, vs.aType) then
+ begin
+ if vs.FreeType <> vtNone then
+ begin
+ if vs.aType.BaseType in NeedFinalization then
+ FinalizeVariant(vs.P, vs.aType);
+ p := IPointer(FTempVars.Data^[FtempVars.Count-1]) - IPointer(FtempVars.DataPtr);
+ Dec(FTempVars.FCount);
+ {$IFNDEF PS_NOSMARTLIST}
+ Inc(FTempVars.FCheckCount);
+ if FTempVars.FCheckCount > FMaxCheckCount then FTempVars.Recreate;
+ {$ENDIF}
+ FTempVars.FLength := P;
+ if ((FTempVars.FCapacity - FTempVars.FLength) shr 12) > 2 then FTempVars.AdjustLength;
+ end;
+ Break;
+ end;
+ if vs.FreeType <> vtNone then
+ begin
+ if vs.aType.BaseType in NeedFinalization then
+ FinalizeVariant(vs.P, vs.aType);
+ p := IPointer(FTempVars.Data^[FtempVars.Count-1]) - IPointer(FtempVars.DataPtr);
+ Dec(FTempVars.FCount);
+ {$IFNDEF PS_NOSMARTLIST}
+ Inc(FTempVars.FCheckCount);
+ if FTempVars.FCheckCount > FMaxCheckCount then FTempVars.Recreate;
+ {$ENDIF}
+ FTempVars.FLength := P;
+ if ((FTempVars.FCapacity - FTempVars.FLength) shr 12) > 2 then FTempVars.AdjustLength;
+ end;
+ end;
+ CM_CA:
+ begin
+ if FCurrentPosition >= FDataLength then
+ begin
+ CMD_Err(erOutOfRange); // Error
+ break;
+ end;
+ calctype := FData^[FCurrentPosition];
+ Inc(FCurrentPosition);
+ if not ReadVariable(vd, True) then
+ break;
+ if vd.FreeType <> vtNone then
+ begin
+ if vd.aType.BaseType in NeedFinalization then
+ FinalizeVariant(vd.P, vd.aType);
+ p := IPointer(FTempVars.Data^[FtempVars.Count-1]) - IPointer(FtempVars.DataPtr);
+ Dec(FTempVars.FCount);
+ {$IFNDEF PS_NOSMARTLIST}
+ Inc(FTempVars.FCheckCount);
+ if FTempVars.FCheckCount > FMaxCheckCount then FTempVars.Recreate;
+ {$ENDIF}
+ FTempVars.FLength := P;
+ if ((FTempVars.FCapacity - FTempVars.FLength) shr 12) > 2 then FTempVars.AdjustLength;
+ CMD_Err(erInvalidOpcodeParameter);
+ break;
+ end;
+ if not ReadVariable(vs, True) then
+ Break;
+ if not DoCalc(vd.P, vs.p, vd.aType, vs.aType, CalcType) then
+ begin
+ if vs.FreeType <> vtNone then
+ begin
+ if vs.aType.BaseType in NeedFinalization then
+ FinalizeVariant(vs.P, vs.aType);
+ p := IPointer(FTempVars.Data^[FtempVars.Count-1]) - IPointer(FtempVars.DataPtr);
+ Dec(FTempVars.FCount);
+ {$IFNDEF PS_NOSMARTLIST}
+ Inc(FTempVars.FCheckCount);
+ if FTempVars.FCheckCount > FMaxCheckCount then FTempVars.Recreate;
+ {$ENDIF}
+ FTempVars.FLength := P;
+ if ((FTempVars.FCapacity - FTempVars.FLength) shr 12) > 2 then FTempVars.AdjustLength;
+ end;
+ Break;
+ end;
+ if vs.FreeType <> vtNone then
+ begin
+ if vs.aType.BaseType in NeedFinalization then
+ FinalizeVariant(vs.P, vs.aType);
+ p := IPointer(FTempVars.Data^[FtempVars.Count-1]) - IPointer(FtempVars.DataPtr);
+ Dec(FTempVars.FCount);
+ {$IFNDEF PS_NOSMARTLIST}
+ Inc(FTempVars.FCheckCount);
+ if FTempVars.FCheckCount > FMaxCheckCount then FTempVars.Recreate;
+ {$ENDIF}
+ FTempVars.FLength := P;
+ if ((FTempVars.FCapacity - FTempVars.FLength) shr 12) > 2 then FTempVars.AdjustLength;
+ end;
+ end;
+ CM_P:
+ begin
+ if not ReadVariable(vs, True) then
+ Break;
+ vtemp := FStack.PushType(vs.aType);
+ vd.P := Pointer(IPointer(vtemp)+PointerSize);
+ vd.aType := Pointer(vtemp^);
+ vd.FreeType := vtNone;
+ if not SetVariantValue(Vd.P, vs.P, vd.aType, vs.aType) then
+ begin
+ if vs.FreeType <> vtnone then
+ begin
+ if vs.aType.BaseType in NeedFinalization then
+ FinalizeVariant(vs.P, vs.aType);
+ p := IPointer(FTempVars.Data^[FtempVars.Count-1]) - IPointer(FtempVars.DataPtr);
+ Dec(FTempVars.FCount);
+ {$IFNDEF PS_NOSMARTLIST}
+ Inc(FTempVars.FCheckCount);
+ if FTempVars.FCheckCount > FMaxCheckCount then FTempVars.Recreate;
+ {$ENDIF}
+ FTempVars.FLength := P;
+ if ((FTempVars.FCapacity - FTempVars.FLength) shr 12) > 2 then FTempVars.AdjustLength;
+ end;
+ break;
+ end;
+ if vs.FreeType <> vtnone then
+ begin
+ if vs.aType.BaseType in NeedFinalization then
+ FinalizeVariant(vs.P, vs.aType);
+ p := IPointer(FTempVars.Data^[FtempVars.Count-1]) - IPointer(FtempVars.DataPtr);
+ Dec(FTempVars.FCount);
+ {$IFNDEF PS_NOSMARTLIST}
+ Inc(FTempVars.FCheckCount);
+ if FTempVars.FCheckCount > FMaxCheckCount then FTempVars.Recreate;
+ {$ENDIF}
+ FTempVars.FLength := P;
+ if ((FTempVars.FCapacity - FTempVars.FLength) shr 12) > 2 then FTempVars.AdjustLength;
+ end;
+ end;
+ CM_PV:
+ begin
+ if not ReadVariable(vs, True) then
+ Break;
+ if vs.FreeType <> vtnone then
+ begin
+ FTempVars.Pop;
+ CMD_Err(erInvalidOpcodeParameter);
+ break;
+ end;
+ vtemp := FStack.PushType(FindType2(btPointer));
+ if vs.aType.BaseType = btPointer then
+ begin
+ PPSVariantPointer(vtemp).DataDest := Pointer(vs.p^);
+ PPSVariantPointer(vtemp).DestType := Pointer(Pointer(IPointer(vs.P)+PointerSize)^);
+ PPSVariantPointer(vtemp).FreeIt := False;
+ end
+ else
+ begin
+ PPSVariantPointer(vtemp).DataDest := vs.p;
+ PPSVariantPointer(vtemp).DestType := vs.aType;
+ PPSVariantPointer(vtemp).FreeIt := False;
+ end;
+ end;
+ CM_PO: begin
+ if FStack.Count = 0 then
+ begin
+ CMD_Err(erOutOfStackRange);
+ break;
+ end;
+ vtemp := FStack.Data^[FStack.Count -1];
+ if (vtemp = nil) or (vtemp.FType.BaseType = btReturnAddress) then
+ begin
+ CMD_Err(erOutOfStackRange);
+ break;
+ end;
+ FStack.Pop;
+(* Dec(FStack.FCount);
+ {$IFNDEF PS_NOSMARTLIST}
+ Inc(FStack.FCheckCount);
+ if FStack.FCheckCount > FMaxCheckCount then FStack.Recreate;
+ {$ENDIF}
+ FStack.FLength := Longint(IPointer(vtemp) - IPointer(FStack.DataPtr));
+ if TPSTypeRec(vtemp^).BaseType in NeedFinalization then
+ FinalizeVariant(Pointer(IPointer(vtemp)+PointerSize), Pointer(vtemp^));
+ if ((FStack.FCapacity - FStack.FLength) shr 12) > 2 then FStack.AdjustLength;*)
+ end;
+ Cm_C: begin
+ if FCurrentPosition + 3 >= FDataLength then
+ begin
+ Cmd_Err(erOutOfRange);
+ Break;
+ end;
+ {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
+ p := unaligned(Cardinal((@FData^[FCurrentPosition])^));
+ {$else}
+ p := Cardinal((@FData^[FCurrentPosition])^);
+ {$endif}
+ Inc(FCurrentPosition, 4);
+ if p >= FProcs.Count then begin
+ CMD_Err(erOutOfProcRange);
+ break;
+ end;
+ u := FProcs.Data^[p];
+ if u.ClassType = TPSExternalProcRec then begin
+ try
+ if not TPSExternalProcRec(u).ProcPtr(Self, TPSExternalProcRec(u), FGlobalVars, FStack) then begin
+ if ExEx = erNoError then
+ CMD_Err(erCouldNotCallProc);
+ Break;
+ end;
+ except
+ {$IFDEF DELPHI6UP}
+ Tmp := AcquireExceptionObject;
+ {$ELSE}
+ if RaiseList <> nil then
+ begin
+ Tmp := Exception(PRaiseFrame(RaiseList)^.ExceptObject);
+ PRaiseFrame(RaiseList)^.ExceptObject := nil;
+ end else
+ Tmp := nil;
+ {$ENDIF}
+ if Tmp <> nil then
+ begin
+ if Tmp is EPSException then
+ begin
+ ExceptionProc(EPSException(tmp).ProcNo, EPSException(tmp).ProcPos, erCustomError, tbtString(EPSException(tmp).Message), nil);
+ Break;
+ end else
+ if Tmp is EDivByZero then
+ begin
+ CMD_Err3(erDivideByZero, '', Tmp);
+ Break;
+ end;
+ if Tmp is EZeroDivide then
+ begin
+ CMD_Err3(erDivideByZero, '', Tmp);
+ Break;
+ end;
+ if Tmp is EMathError then
+ begin
+ CMD_Err3(erMathError, '', Tmp);
+ Break;
+ end;
+ end;
+ if (Tmp <> nil) and (Tmp is Exception) then
+ CMD_Err3(erException, tbtString(Exception(Tmp).Message), Tmp) else
+ CMD_Err3(erException, '', Tmp);
+ Break;
+ end;
+ end
+ else begin
+ Vtemp := Fstack.PushType(FReturnAddressType);
+ vd.P := Pointer(IPointer(VTemp)+PointerSize);
+ vd.aType := pointer(vtemp^);
+ vd.FreeType := vtNone;
+ PPSVariantReturnAddress(vtemp).Addr.ProcNo := FCurrProc;
+ PPSVariantReturnAddress(vtemp).Addr.Position := FCurrentPosition;
+ PPSVariantReturnAddress(vtemp).Addr.StackBase := FCurrStackBase;
+
+ FCurrStackBase := FStack.Count - 1;
+ FCurrProc := TPSInternalProcRec(u);
+ FData := FCurrProc.Data;
+ FDataLength := FCurrProc.Length;
+ FCurrentPosition := 0;
+ end;
+ end;
+ CM_PG:
+ begin
+ FStack.Pop;
+ if FCurrentPosition + 3 >= FDataLength then
+ begin
+ Cmd_Err(erOutOfRange);
+ Break;
+ end;
+ {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
+ p := unaligned(Cardinal((@FData^[FCurrentPosition])^));
+ {$else}
+ p := Cardinal((@FData^[FCurrentPosition])^);
+ {$endif}
+ Inc(FCurrentPosition, 4);
+ FCurrentPosition := FCurrentPosition + p;
+ end;
+ CM_P2G:
+ begin
+ FStack.Pop;
+ FStack.Pop;
+ if FCurrentPosition + 3 >= FDataLength then
+ begin
+ Cmd_Err(erOutOfRange);
+ Break;
+ end;
+ {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
+ p := unaligned(Cardinal((@FData^[FCurrentPosition])^));
+ {$else}
+ p := Cardinal((@FData^[FCurrentPosition])^);
+ {$endif}
+ Inc(FCurrentPosition, 4);
+ FCurrentPosition := FCurrentPosition + p;
+ end;
+ Cm_G:
+ begin
+ if FCurrentPosition + 3 >= FDataLength then
+ begin
+ Cmd_Err(erOutOfRange);
+ Break;
+ end;
+ {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
+ p := unaligned(Cardinal((@FData^[FCurrentPosition])^));
+ {$else}
+ p := Cardinal((@FData^[FCurrentPosition])^);
+ {$endif}
+ Inc(FCurrentPosition, 4);
+ FCurrentPosition := FCurrentPosition + p;
+ end;
+ Cm_CG:
+ begin
+ if FCurrentPosition + 3 >= FDataLength then
+ begin
+ Cmd_Err(erOutOfRange);
+ Break;
+ end;
+ {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
+ p := unaligned(Cardinal((@FData^[FCurrentPosition])^));
+ {$else}
+ p := Cardinal((@FData^[FCurrentPosition])^);
+ {$endif}
+ Inc(FCurrentPosition, 4);
+ btemp := true;
+ if not ReadVariable(vs, btemp) then
+ Break;
+ case Vs.aType.BaseType of
+ btU8: btemp := tbtu8(vs.p^) <> 0;
+ btS8: btemp := tbts8(vs.p^) <> 0;
+ btU16: btemp := tbtu16(vs.p^) <> 0;
+ btS16: btemp := tbts16(vs.p^) <> 0;
+ btU32: btemp := tbtu32(vs.p^) <> 0;
+ btS32: btemp := tbts32(vs.p^) <> 0;
+ else begin
+ CMD_Err(erInvalidType);
+ if vs.FreeType <> vtNone then
+ FTempVars.Pop;
+ break;
+ end;
+ end;
+ if vs.FreeType <> vtNone then
+ FTempVars.Pop;
+ if btemp then
+ FCurrentPosition := FCurrentPosition + p;
+ end;
+ Cm_CNG:
+ begin
+ if FCurrentPosition + 3 >= FDataLength then
+ begin
+ Cmd_Err(erOutOfRange);
+ Break;
+ end;
+ {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
+ p := unaligned(Cardinal((@FData^[FCurrentPosition])^));
+ {$else}
+ p := Cardinal((@FData^[FCurrentPosition])^);
+ {$endif}
+ Inc(FCurrentPosition, 4);
+ btemp := true;
+ if not ReadVariable(vs, BTemp) then
+ Break;
+ case Vs.aType.BaseType of
+ btU8: btemp := tbtu8(vs.p^) = 0;
+ btS8: btemp := tbts8(vs.p^) = 0;
+ btU16: btemp := tbtu16(vs.p^) = 0;
+ btS16: btemp := tbts16(vs.p^) = 0;
+ btU32: btemp := tbtu32(vs.p^) = 0;
+ btS32: btemp := tbts32(vs.p^) = 0;
+ else begin
+ CMD_Err(erInvalidType);
+ if vs.FreeType <> vtNone then
+ FTempVars.Pop;
+ break;
+ end;
+ end;
+ if vs.FreeType <> vtNone then
+ FTempVars.Pop;
+ if btemp then
+ FCurrentPosition := FCurrentPosition + p;
+ end;
+ Cm_R: begin
+ FExitPoint := FCurrentPosition -1;
+ P2 := 0;
+ if FExceptionStack.Count > 0 then
+ begin
+ pp := FExceptionStack.Data[FExceptionStack.Count -1];
+ while (pp.BasePtr = FCurrStackBase) or ((pp.BasePtr > FCurrStackBase) and (pp.BasePtr <> InvalidVal)) do
+ begin
+ if pp.StackSize < Cardinal(FStack.Count) then
+ begin
+ for p := Longint(FStack.count) -1 downto Longint(pp.StackSize) do
+ FStack.Pop
+ end;
+ FCurrStackBase := pp.BasePtr;
+ if pp.FinallyOffset <> InvalidVal then
+ begin
+ FCurrentPosition := pp.FinallyOffset;
+ pp.FinallyOffset := InvalidVal;
+ p2 := 1;
+ break;
+ end else if pp.Finally2Offset <> InvalidVal then
+ begin
+ FCurrentPosition := pp.Finally2Offset;
+ pp.Finally2Offset := InvalidVal;
+ p2 := 1;
+ break;
+ end else
+ begin
+ pp.Free;
+ FExceptionStack.DeleteLast;
+ if FExceptionStack.Count = 0 then break;
+ pp := FExceptionStack.Data[FExceptionStack.Count -1];
+ end;
+ end;
+ end;
+ if p2 = 0 then
+ begin
+ FExitPoint := InvalidVal;
+ if FCurrStackBase = InvalidVal then
+ begin
+ FStatus := FOldStatus;
+ break;
+ end;
+ for P2 := FStack.Count - 1 downto FCurrStackBase + 1 do
+ FStack.Pop;
+ if FCurrStackBase >= FStack.Count then
+ begin
+ FStatus := FOldStatus;
+ break;
+ end;
+ vtemp := FStack.Data[FCurrStackBase];
+ FCurrProc := PPSVariantReturnAddress(vtemp).Addr.ProcNo;
+ FCurrentPosition := PPSVariantReturnAddress(vtemp).Addr.Position;
+ FCurrStackBase := PPSVariantReturnAddress(vtemp).Addr.StackBase;
+ FStack.Pop;
+ if FCurrProc = nil then begin
+ FStatus := FOldStatus;
+ break;
+ end;
+ FData := FCurrProc.Data;
+ FDataLength := FCurrProc.Length;
+ end;
+ end;
+ Cm_Pt: begin
+ if FCurrentPosition + 3 >= FDataLength then
+ begin
+ Cmd_Err(erOutOfRange);
+ Break;
+ end;
+ {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
+ p := unaligned(Cardinal((@FData^[FCurrentPosition])^));
+ {$else}
+ p := Cardinal((@FData^[FCurrentPosition])^);
+ {$endif}
+ Inc(FCurrentPosition, 4);
+ if p > FTypes.Count then
+ begin
+ CMD_Err(erInvalidType);
+ break;
+ end;
+ FStack.PushType(FTypes.Data^[p]);
+ end;
+ cm_bn:
+ begin
+ if not ReadVariable(vd, True) then
+ Break;
+ if vd.FreeType <> vtNone then
+ FTempVars.Pop;
+ if not DoBooleanNot(Vd.P, vd.aType) then
+ break;
+ end;
+ cm_in:
+ begin
+ if not ReadVariable(vd, True) then
+ Break;
+ if vd.FreeType <> vtNone then
+ FTempVars.Pop;
+ if not DoIntegerNot(Vd.P, vd.aType) then
+ break;
+ end;
+ cm_vm:
+ begin
+ if not ReadVariable(vd, True) then
+ Break;
+ if vd.FreeType <> vtNone then
+ FTempVars.Pop;
+ if not DoMinus(Vd.P, vd.aType) then
+ break;
+ end;
+ cm_sf:
+ begin
+ if not ReadVariable(vd, True) then
+ Break;
+ if FCurrentPosition >= FDataLength then
+ begin
+ CMD_Err(erOutOfRange); // Error
+ if vd.FreeType <> vtNone then
+ FTempVars.Pop;
+ break;
+ end;
+ p := FData^[FCurrentPosition];
+ Inc(FCurrentPosition);
+ case Vd.aType.BaseType of
+ btU8: FJumpFlag := tbtu8(Vd.p^) <> 0;
+ btS8: FJumpFlag := tbts8(Vd.p^) <> 0;
+ btU16: FJumpFlag := tbtu16(Vd.p^) <> 0;
+ btS16: FJumpFlag := tbts16(Vd.p^) <> 0;
+ btU32: FJumpFlag := tbtu32(Vd.p^) <> 0;
+ btS32: FJumpFlag := tbts32(Vd.p^) <> 0;
+ else begin
+ CMD_Err(erInvalidType);
+ if vd.FreeType <> vtNone then
+ FTempVars.Pop;
+ break;
+ end;
+ end;
+ if p <> 0 then
+ FJumpFlag := not FJumpFlag;
+ if vd.FreeType <> vtNone then
+ FTempVars.Pop;
+ end;
+ cm_fg:
+ begin
+ if FCurrentPosition + 3 >= FDataLength then
+ begin
+ Cmd_Err(erOutOfRange);
+ Break;
+ end;
+ {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
+ p := unaligned(Cardinal((@FData^[FCurrentPosition])^));
+ {$else}
+ p := Cardinal((@FData^[FCurrentPosition])^);
+ {$endif}
+ Inc(FCurrentPosition, 4);
+ if FJumpFlag then
+ FCurrentPosition := FCurrentPosition + p;
+ end;
+ cm_puexh:
+ begin
+ pp := TPSExceptionHandler.Create;
+ pp.CurrProc := FCurrProc;
+ pp.BasePtr :=FCurrStackBase;
+ pp.StackSize := FStack.Count;
+ if not ReadLong(pp.FinallyOffset) then begin
+ CMD_Err(erOutOfRange);
+ pp.Free;
+ Break;
+ end;
+ if not ReadLong(pp.ExceptOffset) then begin
+ CMD_Err(erOutOfRange);
+ pp.Free;
+ Break;
+ end;
+ if not ReadLong(pp.Finally2Offset) then begin
+ CMD_Err(erOutOfRange);
+ pp.Free;
+ Break;
+ end;
+ if not ReadLong(pp.EndOfBlock) then begin
+ CMD_Err(erOutOfRange);
+ pp.Free;
+ Break;
+ end;
+ if pp.FinallyOffset <> InvalidVal then
+ pp.FinallyOffset := pp.FinallyOffset + FCurrentPosition;
+ if pp.ExceptOffset <> InvalidVal then
+ pp.ExceptOffset := pp.ExceptOffset + FCurrentPosition;
+ if pp.Finally2Offset <> InvalidVal then
+ pp.Finally2Offset := pp.Finally2Offset + FCurrentPosition;
+ if pp.EndOfBlock <> InvalidVal then
+ pp.EndOfBlock := pp.EndOfBlock + FCurrentPosition;
+ if ((pp.FinallyOffset <> InvalidVal) and (pp.FinallyOffset >= FDataLength)) or
+ ((pp.ExceptOffset <> InvalidVal) and (pp.ExceptOffset >= FDataLength)) or
+ ((pp.Finally2Offset <> InvalidVal) and (pp.Finally2Offset >= FDataLength)) or
+ ((pp.EndOfBlock <> InvalidVal) and (pp.EndOfBlock >= FDataLength)) then
+ begin
+ CMD_Err(ErOutOfRange);
+ pp.Free;
+ Break;
+ end;
+ FExceptionStack.Add(pp);
+ end;
+ cm_poexh:
+ begin
+ if FCurrentPosition >= FDataLength then
+ begin
+ CMD_Err(erOutOfRange); // Error
+ break;
+ end;
+ p := FData^[FCurrentPosition];
+ Inc(FCurrentPosition);
+ case p of
+ 2:
+ begin
+ if (FExceptionStack.Count = 0) then
+ begin
+ cmd_err(ErOutOfRange);
+ Break;
+ end;
+ pp := FExceptionStack.Data^[FExceptionStack.Count -1];
+ if pp = nil then begin
+ cmd_err(ErOutOfRange);
+ Break;
+ end;
+ pp.ExceptOffset := InvalidVal;
+ if pp.Finally2Offset <> InvalidVal then
+ begin
+ FCurrentPosition := pp.Finally2Offset;
+ pp.Finally2Offset := InvalidVal;
+ end else begin
+ p := pp.EndOfBlock;
+ pp.Free;
+ FExceptionStack.DeleteLast;
+ if FExitPoint <> InvalidVal then
+ begin
+ FCurrentPosition := FExitPoint;
+ end else begin
+ FCurrentPosition := p;
+ end;
+ end;
+ end;
+ 0:
+ begin
+ pp := FExceptionStack.Data^[FExceptionStack.Count -1];
+ if pp = nil then begin
+ cmd_err(ErOutOfRange);
+ Break;
+ end;
+ if pp.FinallyOffset <> InvalidVal then
+ begin
+ FCurrentPosition := pp.FinallyOffset;
+ pp.FinallyOffset := InvalidVal;
+ end else if pp.Finally2Offset <> InvalidVal then
+ begin
+ FCurrentPosition := pp.Finally2Offset;
+ pp.ExceptOffset := InvalidVal;
+ end else begin
+ p := pp.EndOfBlock;
+ pp.Free;
+ FExceptionStack.DeleteLast;
+ if ExEx <> eNoError then
+ begin
+ Tmp := ExObject;
+ ExObject := nil;
+ ExceptionProc(ExProc, ExPos, ExEx, ExParam, Tmp);
+ end else
+ if FExitPoint <> InvalidVal then
+ begin
+ FCurrentPosition := FExitPoint;
+ end else begin
+ FCurrentPosition := p;
+ end;
+ end;
+ end;
+ 1:
+ begin
+ pp := FExceptionStack.Data^[FExceptionStack.Count -1];
+ if pp = nil then begin
+ cmd_err(ErOutOfRange);
+ Break;
+ end;
+ if (ExEx <> ENoError) and (pp.ExceptOffset <> InvalidVal) and (pp.ExceptOffset <> InvalidVal -1) then
+ begin
+ FCurrentPosition := pp.ExceptOffset;
+ pp.ExceptOffset := Cardinal(InvalidVal -1);
+ pp.ExceptionData := ExEx;
+ pp.ExceptionObject := ExObject;
+ pp.ExceptionParam := ExParam;
+ ExEx := ErNoError;
+ ExObject := nil;
+ end else if (pp.Finally2Offset <> InvalidVal) then
+ begin
+ FCurrentPosition := pp.Finally2Offset;
+ pp.Finally2Offset := InvalidVal;
+ end else begin
+ p := pp.EndOfBlock;
+ pp.Free;
+ FExceptionStack.DeleteLast;
+ if (ExEx <> eNoError) and (p <> InvalidVal) then
+ begin
+ Tmp := ExObject;
+ ExObject := nil;
+ ExceptionProc(ExProc, ExPos, ExEx, ExParam, Tmp);
+ end else
+ if FExitPoint <> InvalidVal then
+ begin
+ FCurrentPosition := FExitPoint;
+ end else begin
+ FCurrentPosition := p;
+ end;
+ end;
+ end;
+ 3:
+ begin
+ pp := FExceptionStack.Data^[FExceptionStack.Count -1];
+ if pp = nil then begin
+ cmd_err(ErOutOfRange);
+ Break;
+ end;
+ p := pp.EndOfBlock;
+ pp.Free;
+ FExceptionStack.DeleteLast;
+ if ExEx <> eNoError then
+ begin
+ Tmp := ExObject;
+ ExObject := nil;
+ ExceptionProc(ExProc, ExPos, ExEx, ExParam, Tmp);
+ end else
+ if FExitPoint <> InvalidVal then
+ begin
+ FCurrentPosition := FExitPoint;
+ end else begin
+ FCurrentPosition := p;
+ end;
+ end;
+ end;
+ end;
+ cm_spc:
+ begin
+ if not ReadVariable(vd, False) then
+ Break;
+ if vd.FreeType <> vtNone then
+ begin
+ FTempVars.Pop;
+ CMD_Err(erInvalidOpcodeParameter);
+ break;
+ end;
+ if (Vd.aType.BaseType <> btPointer) then
+ begin
+ CMD_Err(erInvalidOpcodeParameter);
+ break;
+ end;
+ if not ReadVariable(vs, False) then
+ Break;
+ if Pointer(Pointer(IPointer(vD.P)+PointerSize2)^) <> nil then
+ DestroyHeapVariant2(Pointer(vD.P^), Pointer(Pointer(IPointer(vd.P)+PointerSize)^));
+ if vs.aType.BaseType = btPointer then
+ begin
+ if Pointer(vs.P^) <> nil then
+ begin
+ Pointer(vd.P^) := CreateHeapVariant2(Pointer(Pointer(IPointer(vs.P) + PointerSize)^));
+ Pointer(Pointer(IPointer(vd.P) + PointerSize)^) := Pointer(Pointer(IPointer(vs.P) + PointerSize)^);
+ Pointer(Pointer(IPointer(vd.P) + PointerSize2)^) := Pointer(1);
+ if not CopyArrayContents(Pointer(vd.P^), Pointer(vs.P^), 1, Pointer(Pointer(IPointer(vd.P) + PointerSize)^)) then
+ begin
+ if vs.FreeType <> vtNone then
+ FTempVars.Pop;
+ CMD_Err(ErTypeMismatch);
+ break;
+ end;
+ end else
+ begin
+ Pointer(vd.P^) := nil;
+ Pointer(Pointer(IPointer(vd.P) + PointerSize)^) := nil;
+ Pointer(Pointer(IPointer(vd.P) + PointerSize2)^) := nil;
+ end;
+ end else begin
+ Pointer(vd.P^) := CreateHeapVariant2(vs.aType);
+ Pointer(Pointer(IPointer(vd.P) + PointerSize)^) := vs.aType;
+ LongBool(Pointer(IPointer(vd.P) + PointerSize2)^) := true;
+ if not CopyArrayContents(Pointer(vd.P^), vs.P, 1, vs.aType) then
+ begin
+ if vs.FreeType <> vtNone then
+ FTempVars.Pop;
+ CMD_Err(ErTypeMismatch);
+ break;
+ end;
+ end;
+ if vs.FreeType <> vtNone then
+ FTempVars.Pop;
+
+ end;
+ cm_nop:;
+ cm_dec:
+ begin
+ if not ReadVariable(vd, True) then
+ Break;
+ if vd.FreeType <> vtNone then
+ begin
+ FTempVars.Pop;
+ CMD_Err(erInvalidOpcodeParameter);
+ break;
+ end;
+ case vd.aType.BaseType of
+ btu8: dec(tbtu8(vd.P^));
+ bts8: dec(tbts8(vd.P^));
+ btu16: dec(tbtu16(vd.P^));
+ bts16: dec(tbts16(vd.P^));
+ btu32: dec(tbtu32(vd.P^));
+ bts32: dec(tbts32(vd.P^));
+{$IFNDEF PS_NOINT64}
+ bts64: dec(tbts64(vd.P^));
+{$ENDIF}
+ else
+ begin
+ CMD_Err(ErTypeMismatch);
+ Break;
+ end;
+ end;
+ end;
+ cm_inc:
+ begin
+ if not ReadVariable(vd, True) then
+ Break;
+ if vd.FreeType <> vtNone then
+ begin
+ FTempVars.Pop;
+ CMD_Err(erInvalidOpcodeParameter);
+ break;
+ end;
+ case vd.aType.BaseType of
+ btu8: Inc(tbtu8(vd.P^));
+ bts8: Inc(tbts8(vd.P^));
+ btu16: Inc(tbtu16(vd.P^));
+ bts16: Inc(tbts16(vd.P^));
+ btu32: Inc(tbtu32(vd.P^));
+ bts32: Inc(tbts32(vd.P^));
+{$IFNDEF PS_NOINT64}
+ bts64: Inc(tbts64(vd.P^));
+{$ENDIF}
+ else
+ begin
+ CMD_Err(ErTypeMismatch);
+ Break;
+ end;
+ end;
+ end;
+ cm_sp:
+ begin
+ if not ReadVariable(vd, False) then
+ Break;
+ if vd.FreeType <> vtNone then
+ begin
+ FTempVars.Pop;
+ CMD_Err(erInvalidOpcodeParameter);
+ break;
+ end;
+ if (Vd.aType.BaseType <> btPointer) then
+ begin
+ CMD_Err(erInvalidOpcodeParameter);
+ break;
+ end;
+ if not ReadVariable(vs, False) then
+ Break;
+ if vs.FreeType <> vtNone then
+ begin
+ FTempVars.Pop;
+ CMD_Err(erInvalidOpcodeParameter);
+ break;
+ end;
+ if vs.aType.BaseType = btPointer then
+ begin
+ Pointer(vd.P^) := Pointer(vs.p^);
+ Pointer(Pointer(IPointer(vd.P)+PointerSize)^) := Pointer(Pointer(IPointer(vs.P)+PointerSize)^);
+ end
+ else
+ begin
+ Pointer(vd.P^) := vs.P;
+ Pointer(Pointer(IPointer(vd.P)+PointerSize)^) := vs.aType;
+ end;
+ end;
+ Cm_cv:
+ begin
+ if not ReadVariable(vd, True) then
+ Break;
+ if vd.aType.BaseType <> btProcPtr then
+ begin
+ if vd.FreeType <> vtNone then
+ FTempVars.Pop;
+ CMD_Err(ErTypeMismatch);
+ break;
+ end;
+ p := tbtu32(vd.P^);
+ if vd.FreeType <> vtNone then
+ FTempVars.Pop;
+ if (p = 0) and (Pointer(Pointer(IPointer(vd.p)+PointerSize2)^) <> nil) then
+ begin
+ if not InvokeExternalMethod(TPSTypeRec_ProcPtr(vd.aType), Pointer(Pointer(IPointer(vd.p)+PointerSize)^), Pointer(Pointer(IPointer(vd.p)+PointerSize2)^)) then
+ Break;
+ end else begin
+ if (p >= FProcs.Count) or (p = FMainProc) then begin
+ CMD_Err(erOutOfProcRange);
+ break;
+ end;
+ u := FProcs.Data^[p];
+ if u.ClassType = TPSExternalProcRec then begin
+ try
+ if not TPSExternalProcRec(u).ProcPtr(Self, TPSExternalProcRec(u), FGlobalVars, FStack) then begin
+ if ExEx = erNoError then
+ CMD_Err(erCouldNotCallProc);
+ Break;
+ end;
+ except
+ {$IFDEF DELPHI6UP}
+ Tmp := AcquireExceptionObject;
+ {$ELSE}
+ if RaiseList <> nil then
+ begin
+ Tmp := Exception(PRaiseFrame(RaiseList)^.ExceptObject);
+ PRaiseFrame(RaiseList)^.ExceptObject := nil;
+ end else
+ Tmp := nil;
+ {$ENDIF}
+ if Tmp <> nil then
+ begin
+ if Tmp is EPSException then
+ begin
+ ExceptionProc(EPSException(tmp).ProcNo, EPSException(tmp).ProcPos, erCustomError, tbtString(EPSException(tmp).Message), nil);
+ break;
+ end else
+ if Tmp is EDivByZero then
+ begin
+ CMD_Err3(erDivideByZero, '', Tmp);
+ break;
+ end;
+ if Tmp is EZeroDivide then
+ begin
+ CMD_Err3(erDivideByZero, '', Tmp);
+ break;
+ end;
+ if Tmp is EMathError then
+ begin
+ CMD_Err3(erMathError, '', Tmp);
+ break;
+ end;
+ end;
+ if (Tmp <> nil) and (Tmp is Exception) then
+ CMD_Err3(erException, tbtString(Exception(Tmp).Message), Tmp) else
+ CMD_Err3(erException, '', Tmp);
+ Break;
+ end;
+ end
+ else begin
+ vtemp := FStack.PushType(FReturnAddressType);
+ PPSVariantReturnAddress(vtemp).Addr.ProcNo := FCurrProc;
+ PPSVariantReturnAddress(vtemp).Addr.Position := FCurrentPosition;
+ PPSVariantReturnAddress(vtemp).Addr.StackBase := FCurrStackBase;
+ FCurrStackBase := FStack.Count - 1;
+ FCurrProc := TPSInternalProcRec(u);
+ FData := FCurrProc.Data;
+ FDataLength := FCurrProc.Length;
+ FCurrentPosition := 0;
+ end;
+ end;
+ end;
+ CM_CO:
+ begin
+ if FCurrentPosition >= FDataLength then
+ begin
+ CMD_Err(erOutOfRange); // Error
+ break;
+ end;
+ calctype := FData^[FCurrentPosition];
+ Inc(FCurrentPosition);
+ if not ReadVariable(v3, True) then
+ Break;
+ if v3.FreeType <> vtNone then
+ begin
+ if v3.aType.BaseType in NeedFinalization then
+ FinalizeVariant(v3.P, v3.aType);
+ p := IPointer(FTempVars.Data^[FtempVars.Count-1]) - IPointer(FtempVars.DataPtr);
+ Dec(FTempVars.FCount);
+ {$IFNDEF PS_NOSMARTLIST}
+ Inc(FTempVars.FCheckCount);
+ if FTempVars.FCheckCount > FMaxCheckCount then FTempVars.Recreate;
+ {$ENDIF}
+ FTempVars.FLength := P;
+ if ((FTempVars.FCapacity - FTempVars.FLength) shr 12) > 2 then FTempVars.AdjustLength;
+ CMD_Err(erInvalidOpcodeParameter);
+ break;
+ end;
+ if not ReadVariable(vs, True) then
+ Break;
+ if not ReadVariable(vd, True) then
+ begin
+ if vs.FreeType <> vtNone then
+ begin
+ if vs.aType.BaseType in NeedFinalization then
+ FinalizeVariant(vs.P, vs.aType);
+ p := IPointer(FTempVars.Data^[FtempVars.Count-1]) - IPointer(FtempVars.DataPtr);
+ Dec(FTempVars.FCount);
+ {$IFNDEF PS_NOSMARTLIST}
+ Inc(FTempVars.FCheckCount);
+ if FTempVars.FCheckCount > FMaxCheckCount then FTempVars.Recreate;
+ {$ENDIF}
+ FTempVars.FLength := P;
+ if ((FTempVars.FCapacity - FTempVars.FLength) shr 12) > 2 then FTempVars.AdjustLength;
+ end;
+ Break;
+ end;
+ DoBooleanCalc(Vs.P, Vd.P, v3.P, vs.aType, vd.aType, v3.aType, CalcType);
+ if vd.FreeType <> vtNone then
+ begin
+ if vd.aType.BaseType in NeedFinalization then
+ FinalizeVariant(vd.P, vd.aType);
+ p := IPointer(FTempVars.Data^[FtempVars.Count-1]) - IPointer(FtempVars.DataPtr);
+ Dec(FTempVars.FCount);
+ {$IFNDEF PS_NOSMARTLIST}
+ Inc(FTempVars.FCheckCount);
+ if FTempVars.FCheckCount > FMaxCheckCount then FTempVars.Recreate;
+ {$ENDIF}
+ FTempVars.FLength := P;
+ if ((FTempVars.FCapacity - FTempVars.FLength) shr 12) > 2 then FTempVars.AdjustLength;
+ end;
+ if vs.FreeType <> vtNone then
+ begin
+ if vs.aType.BaseType in NeedFinalization then
+ FinalizeVariant(vs.P, vs.aType);
+ p := IPointer(FTempVars.Data^[FtempVars.Count-1]) - IPointer(FtempVars.DataPtr);
+ Dec(FTempVars.FCount);
+ {$IFNDEF PS_NOSMARTLIST}
+ Inc(FTempVars.FCheckCount);
+ if FTempVars.FCheckCount > FMaxCheckCount then FTempVars.Recreate;
+ {$ENDIF}
+ FTempVars.FLength := P;
+ if ((FTempVars.FCapacity - FTempVars.FLength) shr 12) > 2 then FTempVars.AdjustLength;
+ end;
+ end;
+
+ else
+ CMD_Err(erInvalidOpcode); // Error
+ end;
+ end;
+// if cmd <> invalidval then ProfilerExitProc(Cmd+1);
+// if ExEx <> erNoError then FStatus := FOldStatus;
+ until (FExceptionStack.Count = 0) or (Fstatus <> IsRunning);
+ if FStatus = isLoaded then begin
+ for I := Longint(FStack.Count) - 1 downto 0 do
+ FStack.Pop;
+ FStack.Clear;
+ if FCallCleanup then Cleanup;
+ end;
+ Result := ExEx = erNoError;
+end;
+
+function NVarProc(Caller: TPSExec; p: TPSExternalProcRec; Global, Stack: TPSStack): Boolean;
+var
+ tmp: TPSVariantIFC;
+begin
+ case Longint(p.Ext1) of
+ 0:
+ begin
+ if @Caller.FOnSetNVariant = nil then begin Result := False; exit; end;
+ tmp := NewTPSVariantIFC(Stack.Items[Stack.Count - 2], True);
+ if (Tmp.Dta = nil) or (tmp.aType.BaseType <> btVariant) then begin Result := False; exit; end;
+ Caller.FOnSetNVariant(Caller, Stack.GetAnsiString(-1), Variant(tmp.Dta^));
+ Result := true;
+ end;
+ 1:
+ begin
+ if @Caller.FOnGetNVariant = nil then begin Result := False; exit; end;
+ tmp := NewTPSVariantIFC(Stack.Items[Stack.Count - 1], False);
+ if (Tmp.Dta = nil) or (tmp.aType.BaseType <> btVariant) then begin Result := False; exit; end;
+ Variant(tmp.Dta^) := Caller.FOnGetNVariant(Caller, Stack.GetAnsiString(-2));
+ Result := true;
+ end;
+ else
+ Result := False;
+ end;
+end;
+
+function DefProc(Caller: TPSExec; p: TPSExternalProcRec; Global, Stack: TPSStack): Boolean;
+var
+ temp: TPSVariantIFC;
+ I: Longint;
+ b: Boolean;
+ pex: TPSExceptionHandler;
+ Tmp: TObject;
+begin
+ case Longint(p.Ext1) of
+ 0: Stack.SetAnsiString(-1, IntToStr(Stack.{$IFNDEF PS_NOINT64}GetInt64{$ELSE}GetInt{$ENDIF}(-2))); // inttostr
+ 1: Stack.SetInt(-1, StrToInt(Stack.GetAnsiString(-2))); // strtoint
+ 2: Stack.SetInt(-1, StrToIntDef(Stack.GetAnsiString(-2), Stack.GetInt(-3))); // strtointdef
+ 3:
+ if Stack.GetItem(Stack.Count -2)^.FType.BaseType = btUnicodeString then
+ Stack.SetInt(-1, Pos(Stack.GetUnicodeString(-2), Stack.GetUnicodeString(-3)))// pos
+ else
+ if Stack.GetItem(Stack.Count -2)^.FType.BaseType = btWideString then
+ Stack.SetInt(-1, Pos(Stack.GetWideString(-2), Stack.GetWideString(-3)))// pos
+ else
+ Stack.SetInt(-1, Pos(Stack.GetAnsiString(-2), Stack.GetAnsiString(-3)));// pos
+ 4:
+ if Stack.GetItem(Stack.Count -2)^.FType.BaseType = btWideString then
+ Stack.SetWideString(-1, Copy(Stack.GetWideString(-2), Stack.GetInt(-3), Stack.GetInt(-4))) // copy
+ else
+ if Stack.GetItem(Stack.Count -2)^.FType.BaseType = btUnicodeString then
+ Stack.SetUnicodeString(-1, Copy(Stack.GetUnicodeString(-2), Stack.GetInt(-3), Stack.GetInt(-4))) // copy
+ else
+ Stack.SetAnsiString(-1, Copy(Stack.GetAnsiString(-2), Stack.GetInt(-3), Stack.GetInt(-4))); // copy
+ 5: //delete
+ begin
+ temp := NewTPSVariantIFC(Stack[Stack.Count -1], True);
+ if (temp.Dta <> nil) and (temp.aType.BaseType = btUnicodeString) then
+ begin
+ Delete(tbtUnicodeString(temp.Dta^), Stack.GetInt(-2), Stack.GetInt(-3));
+ end else
+ if (temp.Dta <> nil) and (temp.aType.BaseType = btWideString) then
+ begin
+ Delete(tbtwidestring(temp.Dta^), Stack.GetInt(-2), Stack.GetInt(-3));
+ end else begin
+ if (temp.Dta = nil) or (temp.aType.BaseType <> btString) then
+ begin
+ Result := False;
+ exit;
+ end;
+ Delete(tbtstring(temp.Dta^), Stack.GetInt(-2), Stack.GetInt(-3));
+ end;
+ end;
+ 6: // insert
+ begin
+ temp := NewTPSVariantIFC(Stack[Stack.Count -2], True);
+ if (temp.Dta <> nil) and (temp.aType.BaseType = btUnicodeString) then begin
+ Insert(Stack.GetUnicodeString(-1), tbtUnicodeString(temp.Dta^), Stack.GetInt(-3));
+ end else if (temp.Dta <> nil) and (temp.aType.BaseType = btWideString) then begin
+ Insert(Stack.GetWideString(-1), tbtwidestring(temp.Dta^), Stack.GetInt(-3));
+ end else begin
+ if (temp.Dta = nil) or (temp.aType.BaseType <> btString) then
+ begin
+ Result := False;
+ exit;
+ end;
+ Insert(Stack.GetAnsiString(-1), tbtstring(temp.Dta^), Stack.GetInt(-3));
+ end;
+ end;
+ 7: // StrGet
+ begin
+ temp := NewTPSVariantIFC(Stack[Stack.Count -2], True);
+ if (temp.Dta = nil) or (temp.aType.BaseType <> btString) then
+ begin
+ Result := False;
+ exit;
+ end;
+ I := Stack.GetInt(-3);
+ if (i<1) or (i>length(tbtstring(temp.Dta^))) then
+ begin
+ Caller.CMD_Err2(erCustomError, tbtString(RPS_OutOfStringRange));
+ Result := False;
+ exit;
+ end;
+ Stack.SetInt(-1,Ord(tbtstring(temp.Dta^)[i]));
+ end;
+ 8: // StrSet
+ begin
+ temp := NewTPSVariantIFC(Stack[Stack.Count -3], True);
+ if (temp.Dta = nil) or (temp.aType.BaseType <> btString) then
+ begin
+ Result := False;
+ exit;
+ end;
+ I := Stack.GetInt(-2);
+ if (i<1) or (i>length(tbtstring(temp.Dta^))) then
+ begin
+ Caller.CMD_Err2(erCustomError, tbtString(RPS_OutOfStringRange));
+ Result := True;
+ exit;
+ end;
+ tbtstring(temp.Dta^)[i] := tbtchar(Stack.GetInt(-1));
+ end;
+ 10:
+{$IFDEF DELPHI2009UP}
+ if Stack.GetItem(Stack.Count -2)^.FType.BaseType = btUnicodeString then
+ Stack.SetUnicodeString(-1, UpperCase(Stack.GetUnicodeString(-2))) // Uppercase
+ else
+{$ENDIF}
+ if (Stack.GetItem(Stack.Count -2)^.FType.BaseType = btWideString) or
+ (Stack.GetItem(Stack.Count -2)^.FType.BaseType = btUnicodeString) then
+ Stack.SetWideString(-1, WideUpperCase(Stack.GetWideString(-2))) // Uppercase
+ else
+ Stack.SetAnsiString(-1, FastUppercase(Stack.GetAnsiString(-2))); // Uppercase
+ 11:
+{$IFDEF DELPHI2009UP}
+ if Stack.GetItem(Stack.Count -2)^.FType.BaseType = btUnicodeString then
+ Stack.SetUnicodeString(-1, LowerCase(Stack.GetUnicodeString(-2))) // Uppercase
+ else
+{$ENDIF}
+ if (Stack.GetItem(Stack.Count -2)^.FType.BaseType = btWideString) or
+ (Stack.GetItem(Stack.Count -2)^.FType.BaseType = btUnicodeString) then
+ Stack.SetWideString(-1, WideLowerCase(Stack.GetWideString(-2))) // Uppercase
+ else
+ Stack.SetAnsiString(-1, FastLowercase(Stack.GetAnsiString(-2)));// LowerCase
+ 12:
+ if Stack.GetItem(Stack.Count -2)^.FType.BaseType = btUnicodeString then
+ Stack.SetUnicodeString(-1, SysUtils.Trim(Stack.GetUnicodestring(-2))) // Uppercase
+ else if Stack.GetItem(Stack.Count -2)^.FType.BaseType = btWideString then
+ Stack.SetWideString(-1, SysUtils.Trim(Stack.GetWideString(-2))) // Uppercase
+ else
+ Stack.SetAnsiString(-1, Trim(Stack.GetAnsiString(-2)));// Trim
+ 13: Stack.SetInt(-1, Length(Stack.GetAnsiString(-2))); // Length
+ 14: // SetLength
+ begin
+ temp := NewTPSVariantIFC(Stack[Stack.Count -1], True);
+ if (temp.Dta = nil) or (temp.aType.BaseType <> btString) then
+ begin
+ Result := False;
+ exit;
+ end;
+ SetLength(tbtstring(temp.Dta^), STack.GetInt(-2));
+ end;
+ 15: Stack.SetReal(-1, Sin(Stack.GetReal(-2))); // Sin
+ 16: Stack.SetReal(-1, Cos(Stack.GetReal(-2))); // Cos
+ 17: Stack.SetReal(-1, SQRT(Stack.GetReal(-2))); // Sqrt
+ 18: Stack.SetInt(-1, Round(Stack.GetReal(-2))); // Round
+ 19: Stack.SetInt(-1, Trunc(Stack.GetReal(-2))); // Trunc
+ 20: Stack.SetReal(-1, Int(Stack.GetReal(-2))); // Int
+ 21: Stack.SetReal(-1, Pi); // Pi
+ 22: Stack.SetReal(-1, Abs(Stack.GetReal(-2))); // Abs
+ 23: Stack.SetReal(-1, StrToFloat(Stack.GetAnsiString(-2))); // StrToFloat
+ 24: Stack.SetAnsiString(-1, FloatToStr(Stack.GetReal(-2)));// FloatToStr
+ 25:
+ if Stack.GetItem(Stack.Count -2)^.FType.BaseType = btUnicodeString then
+ Stack.SetUnicodeString(-1, upadL(Stack.GetUnicodeString(-2), Stack.GetInt(-3))) // PadL
+ else
+ if Stack.GetItem(Stack.Count -2)^.FType.BaseType = btWideString then
+ Stack.SetWideString(-1, wPadL(Stack.GetWideString(-2), Stack.GetInt(-3))) // PadL
+ else
+ Stack.SetAnsiString(-1, PadL(Stack.GetAnsiString(-2), Stack.GetInt(-3))); // PadL
+ 26:
+ if Stack.GetItem(Stack.Count -2)^.FType.BaseType = btUnicodeString then
+ Stack.SetUnicodeString(-1, uPadR(Stack.GetUnicodeString(-2), Stack.GetInt(-3))) // PadR
+ else
+ if Stack.GetItem(Stack.Count -2)^.FType.BaseType = btWideString then
+ Stack.SetWideString(-1, wPadR(Stack.GetWideString(-2), Stack.GetInt(-3))) // PadR
+ else
+ Stack.SetAnsiString(-1, PadR(Stack.GetAnsiString(-2), Stack.GetInt(-3))); // PadR
+ 27:
+ if Stack.GetItem(Stack.Count -2)^.FType.BaseType = btUnicodeString then
+ Stack.SetUnicodeString(-1, uPadZ(Stack.GetUnicodeString(-2), Stack.GetInt(-3)))// PadZ
+ else
+ if Stack.GetItem(Stack.Count -2)^.FType.BaseType = btWideString then
+ Stack.SetWideString(-1, wPadZ(Stack.GetWideString(-2), Stack.GetInt(-3)))// PadZ
+ else
+ Stack.SetAnsiString(-1, PadZ(Stack.GetAnsiString(-2), Stack.GetInt(-3)));// PadZ
+ 28: Stack.SetAnsiString(-1, StringOfChar(tbtChar(Stack.GetInt(-2)), Stack.GetInt(-3))); // Replicate/StrOfChar
+ 29: // Assigned
+ begin
+ temp := NewTPSVariantIFC(Stack[Stack.Count -2], True);
+ if Temp.dta = nil then
+ begin
+ Result := False;
+ exit;
+ end;
+ case temp.aType.BaseType of
+ btU8, btS8: b := tbtu8(temp.dta^) <> 0;
+ btU16, btS16: b := tbtu16(temp.dta^) <> 0;
+ btU32, btS32: b := tbtu32(temp.dta^) <> 0;
+ btString, btPChar: b := tbtstring(temp.dta^) <> '';
+{$IFNDEF PS_NOWIDESTRING}
+ btWideString: b := tbtwidestring(temp.dta^)<> '';
+ btUnicodeString: b := tbtUnicodeString(temp.dta^)<> '';
+{$ENDIF}
+ btArray, btClass{$IFNDEF PS_NOINTERFACES}, btInterface{$ENDIF}: b := Pointer(temp.dta^) <> nil;
+ else
+ Result := False;
+ Exit;
+ end;
+ if b then
+ Stack.SetInt(-1, 1)
+ else
+ Stack.SetInt(-1, 0);
+ end;
+ 30:
+ begin {RaiseLastException}
+ if (Caller.FExceptionStack.Count > 0) then begin
+ pex := Caller.FExceptionStack.Data[Caller.fExceptionStack.Count -1];
+ if pex.ExceptOffset = Cardinal(InvalidVal -1) then begin
+ Tmp := pex.ExceptionObject;
+ pex.ExceptionObject := nil;
+ Caller.ExceptionProc(Caller.ExProc, pex.ExceptOffset, pex.ExceptionData, pex.ExceptionParam, tmp);
+ end;
+ end;
+ end;
+ 31: Caller.CMD_Err2(TPSError(Stack.GetInt(-1)), Stack.GetAnsiString(-2)); {RaiseExeption}
+ 32: Stack.SetInt(-1, Ord(Caller.LastEx)); {ExceptionType}
+ 33: Stack.SetAnsiString(-1, Caller.LastExParam); {ExceptionParam}
+ 34: Stack.SetInt(-1, Caller.LastExProc); {ExceptionProc}
+ 35: Stack.SetInt(-1, Caller.LastExPos); {ExceptionPos}
+ 36: Stack.SetAnsiString(-1, PSErrorToString(TPSError(Stack.GetInt(-2)), Stack.GetAnsiString(-3))); {ExceptionToString}
+ 37: Stack.SetAnsiString(-1, tbtString(AnsiUpperCase(string(Stack.GetAnsiString(-2))))); // AnsiUppercase
+ 38: Stack.SetAnsiString(-1, tbtString(AnsiLowercase(string(Stack.GetAnsiString(-2))))); // AnsiLowerCase
+{$IFNDEF PS_NOINT64}
+ 39: Stack.SetInt64(-1, StrToInt64(string(Stack.GetAnsiString(-2)))); // StrToInt64
+ 40: Stack.SetAnsiString(-1, tbtstring(SysUtils.IntToStr(Stack.GetInt64(-2))));// Int64ToStr
+{$ENDIF}
+ 41: // sizeof
+ begin
+ temp := NewTPSVariantIFC(Stack[Stack.Count -2], False);
+ if Temp.aType = nil then
+ Stack.SetInt(-1, 0)
+ else
+ Stack.SetInt(-1, Temp.aType.RealSize)
+ end;
+{$IFNDEF PS_NOWIDESTRING}
+ 42: // WStrGet
+ begin
+ temp := NewTPSVariantIFC(Stack[Stack.Count -2], True);
+ if temp.dta = nil then begin
+ result := false;
+ exit;
+ end;
+ case temp.aType.BaseType of
+ btWideString:
+ begin
+ I := Stack.GetInt(-3);
+ if (i<1) or (i>length(tbtwidestring(temp.Dta^))) then
+ begin
+ Caller.CMD_Err2(erCustomError, tbtString(RPS_OutOfStringRange));
+ Result := False;
+ exit;
+ end;
+ Stack.SetInt(-1,Ord(tbtwidestring(temp.Dta^)[i]));
+ end;
+ btUnicodeString:
+ begin
+ I := Stack.GetInt(-3);
+ if (i<1) or (i>length(tbtUnicodeString(temp.Dta^))) then
+ begin
+ Caller.CMD_Err2(erCustomError, tbtString(RPS_OutOfStringRange));
+ Result := False;
+ exit;
+ end;
+ Stack.SetInt(-1,Ord(tbtUnicodeString(temp.Dta^)[i]));
+ end;
+
+ else
+ begin
+ Result := False;
+ exit;
+ end;
+ end;
+ end;
+ 43: // WStrSet
+ begin
+ temp := NewTPSVariantIFC(Stack[Stack.Count -3], True);
+ if (temp.Dta = nil) then
+ begin
+ Result := False;
+ exit;
+ end;
+ case temp.aType.BaseType of
+ btWideString:
+ begin
+ I := Stack.GetInt(-2);
+ if (i<1) or (i>length(tbtWidestring(temp.Dta^))) then
+ begin
+ Caller.CMD_Err2(erCustomError, tbtString(RPS_OutOfStringRange));
+ Result := True;
+ exit;
+ end;
+ tbtWidestring(temp.Dta^)[i] := WideChar(Stack.GetInt(-1));
+ end;
+
+ btUnicodeString:
+ begin
+ I := Stack.GetInt(-2);
+ if (i<1) or (i>length(tbtunicodestring(temp.Dta^))) then
+ begin
+ Caller.CMD_Err2(erCustomError, tbtString(RPS_OutOfStringRange));
+ Result := True;
+ exit;
+ end;
+ tbtunicodestring(temp.Dta^)[i] := WideChar(Stack.GetInt(-1));
+ end;
+ else
+ begin
+ Result := False;
+ exit;
+ end;
+ end;
+ end;
+{$ENDIF}
+ else
+ begin
+ Result := False;
+ exit;
+ end;
+ end;
+ Result := True;
+end;
+function GetArrayLength(Caller: TPSExec; p: TPSExternalProcRec; Global, Stack: TPSStack): Boolean;
+var
+ arr: TPSVariantIFC;
+begin
+ Arr := NewTPSVariantIFC(Stack[Stack.Count-2], True);
+ if (arr.Dta = nil) or (arr.aType.BaseType <> btArray) then
+ begin
+ Result := false;
+ exit;
+ end;
+ Stack.SetInt(-1, PSDynArrayGetLength(Pointer(arr.Dta^), arr.aType));
+ Result := True;
+end;
+
+function SetArrayLength(Caller: TPSExec; p: TPSExternalProcRec; Global, Stack: TPSStack): Boolean;
+var
+ arr: TPSVariantIFC;
+begin
+ Arr := NewTPSVariantIFC(Stack[Stack.Count-1], True);
+ if (arr.Dta = nil) or (arr.aType.BaseType <> btArray) then
+ begin
+ Result := false;
+ exit;
+ end;
+ PSDynArraySetLength(Pointer(arr.Dta^), arr.aType, Stack.GetInt(-2));
+ Result := True;
+end;
+
+
+function InterfaceProc(Sender: TPSExec; p: TPSExternalProcRec; Tag: Pointer): Boolean; forward;
+
+procedure RegisterInterfaceLibraryRuntime(Se: TPSExec);
+begin
+ SE.AddSpecialProcImport('intf', InterfaceProc, nil);
+end;
+
+{$IFNDEF DELPHI6UP}
+function Null: Variant;
+begin
+ Result := System.Null;
+end;
+
+function Unassigned: Variant;
+begin
+ Result := System.Unassigned;
+end;
+{$ENDIF}
+function Length_(Caller: TPSExec; p: TPSExternalProcRec; Global, Stack: TPSStack): Boolean;
+var
+ arr: TPSVariantIFC;
+begin
+ arr:=NewTPSVariantIFC(Stack[Stack.Count-2],false);
+ case arr.aType.BaseType of
+ btArray:
+ begin
+ Stack.SetInt(-1,PSDynArrayGetLength(Pointer(arr.Dta^),arr.aType));
+ Result:=true;
+ end;
+ btStaticArray:
+ begin
+ Stack.SetInt(-1,TPSTypeRec_StaticArray(arr.aType).Size);
+ Result:=true;
+ end;
+ btString:
+ begin
+ Stack.SetInt(-1,length(tbtstring(arr.Dta^)));
+ Result:=true;
+ end;
+ {$IFNDEF PS_NOWIDESTRING}
+ btWideString:
+ begin
+ Stack.SetInt(-1,length(tbtWidestring(arr.Dta^)));
+ Result:=true;
+ end;
+ btUnicodeString:
+ begin
+ Stack.SetInt(-1,length(tbtUnicodeString(arr.Dta^)));
+ Result:=true;
+ end;
+ {$ENDIF}
+ btvariant:
+ begin
+ Stack.SetInt(-1,length(Variant(arr.Dta^)));
+ Result:=true;
+ end;
+ else
+ begin
+ Caller.CMD_Err(ErTypeMismatch);
+ result := true;
+ end;
+ end;
+end;
+
+
+function SetLength_(Caller: TPSExec; p: TPSExternalProcRec; Global, Stack: TPSStack): Boolean;
+var
+ arr: TPSVariantIFC;
+begin
+ Result:=false;
+ arr:=NewTPSVariantIFC(Stack[Stack.Count-1],true);
+ if arr.aType.BaseType=btArray then
+ begin
+ PSDynArraySetLength(Pointer(arr.Dta^),arr.aType,Stack.GetInt(-2));
+ Result:=true;
+ end else
+ if arr.aType.BaseType=btString then
+ begin
+ SetLength(tbtstring(arr.Dta^),STack.GetInt(-2));
+ Result:=true;
+{$IFNDEF PS_NOWIDESTRING}
+ end else
+ if arr.aType.BaseType=btWideString then
+ begin
+ SetLength(tbtwidestring(arr.Dta^),STack.GetInt(-2));
+ Result:=true;
+ end else
+ if arr.aType.BaseType=btUnicodeString then
+ begin
+ SetLength(tbtUnicodeString(arr.Dta^),STack.GetInt(-2));
+ Result:=true;
+{$ENDIF}
+ end;
+end;
+
+function Low_(Caller: TPSExec; p: TPSExternalProcRec; Global, Stack: TPSStack): Boolean;
+var
+ arr: TPSVariantIFC;
+begin
+ Result:=true;
+ arr:=NewTPSVariantIFC(Stack[Stack.Count-2],false);
+ case arr.aType.BaseType of
+ btArray : Stack.SetInt(-1,0);
+ btStaticArray: Stack.SetInt(-1,TPSTypeRec_StaticArray(arr.aType).StartOffset);
+ btString : Stack.SetInt(-1,1);
+ btU8 : Stack.SetInt(-1,Low(Byte)); //Byte: 0
+ btS8 : Stack.SetInt(-1,Low(ShortInt)); //ShortInt: -128
+ btU16 : Stack.SetInt(-1,Low(Word)); //Word: 0
+ btS16 : Stack.SetInt(-1,Low(SmallInt)); //SmallInt: -32768
+ btU32 : Stack.SetInt(-1,Low(Cardinal)); //Cardinal/LongWord: 0
+ btS32 : Stack.SetInt(-1,Low(Integer)); //Integer/LongInt: -2147483648
+ else Result:=false;
+ end;
+end;
+
+function High_(Caller: TPSExec; p: TPSExternalProcRec; Global, Stack: TPSStack): Boolean;
+var
+ arr: TPSVariantIFC;
+begin
+ Result:=true;
+ arr:=NewTPSVariantIFC(Stack[Stack.Count-2],false);
+ case arr.aType.BaseType of
+ btArray : Stack.SetInt(-1,PSDynArrayGetLength(Pointer(arr.Dta^),arr.aType)-1);
+ btStaticArray: Stack.SetInt(-1,TPSTypeRec_StaticArray(arr.aType).StartOffset+TPSTypeRec_StaticArray(arr.aType).Size-1);
+ btString : Stack.SetInt(-1,Length(tbtstring(arr.Dta^)));
+ btU8 : Stack.SetInt(-1,High(Byte)); //Byte: 255
+ btS8 : Stack.SetInt(-1,High(ShortInt)); //ShortInt: 127
+ btU16 : Stack.SetInt(-1,High(Word)); //Word: 65535
+ btS16 : Stack.SetInt(-1,High(SmallInt)); //SmallInt: 32767
+ btU32 : Stack.SetUInt(-1,High(Cardinal)); //Cardinal/LongWord: 4294967295
+ btS32 : Stack.SetInt(-1,High(Integer)); //Integer/LongInt: 2147483647
+ else Result:=false;
+ end;
+end;
+
+function Dec_(Caller: TPSExec; p: TPSExternalProcRec; Global, Stack: TPSStack): Boolean;
+var
+ arr: TPSVariantIFC;
+begin
+ Result:=true;
+ arr:=NewTPSVariantIFC(Stack[Stack.Count-1],true);
+ case arr.aType.BaseType of
+ btU8 : Stack.SetInt(-1,Tbtu8(arr.dta^)-1); //Byte
+ btS8 : Stack.SetInt(-1,Tbts8(arr.dta^)-1); //ShortInt
+ btU16 : Stack.SetInt(-1,Tbtu16(arr.dta^)-1); //Word
+ btS16 : Stack.SetInt(-1,Tbts16(arr.dta^)-1); //SmallInt
+ btU32 : Stack.SetInt(-1,Tbtu32(arr.dta^)-1); //Cardinal/LongWord
+ btS32 : Stack.SetInt(-1,Tbts32(arr.dta^)-1); //Integer/LongInt
+ else Result:=false;
+ end;
+end;
+
+function Inc_(Caller: TPSExec; p: TPSExternalProcRec; Global, Stack: TPSStack): Boolean;
+var
+ arr: TPSVariantIFC;
+begin
+ Result:=true;
+ arr:=NewTPSVariantIFC(Stack[Stack.Count-1],true);
+ case arr.aType.BaseType of
+ btU8 : Stack.SetInt(-1,Tbtu8(arr.dta^)+1); //Byte
+ btS8 : Stack.SetInt(-1,Tbts8(arr.dta^)+1); //ShortInt
+ btU16 : Stack.SetInt(-1,Tbtu16(arr.dta^)+1); //Word
+ btS16 : Stack.SetInt(-1,Tbts16(arr.dta^)+1); //SmallInt
+ btU32 : Stack.SetInt(-1,Tbtu32(arr.dta^)+1); //Cardinal/LongWord
+ btS32 : Stack.SetInt(-1,Tbts32(arr.dta^)+1); //Integer/LongInt
+ else Result:=false;
+ end;
+end;
+
+
+procedure TPSExec.RegisterStandardProcs;
+begin
+ RegisterFunctionName('!NOTIFICATIONVARIANTSET', NVarProc, Pointer(0), nil);
+ RegisterFunctionName('!NOTIFICATIONVARIANTGET', NVarProc, Pointer(1), nil);
+
+ RegisterFunctionName('INTTOSTR', DefProc, Pointer(0), nil);
+ RegisterFunctionName('STRTOINT', DefProc, Pointer(1), nil);
+ RegisterFunctionName('STRTOINTDEF', DefProc, Pointer(2), nil);
+ RegisterFunctionName('POS', DefProc, Pointer(3), nil);
+ RegisterFunctionName('COPY', DefProc, Pointer(4), nil);
+ RegisterFunctionName('DELETE', DefProc, Pointer(5), nil);
+ RegisterFunctionName('INSERT', DefProc, Pointer(6), nil);
+
+ RegisterFunctionName('STRGET', DefProc, Pointer(7), nil);
+ RegisterFunctionName('STRSET', DefProc, Pointer(8), nil);
+ RegisterFunctionName('UPPERCASE', DefProc, Pointer(10), nil);
+ RegisterFunctionName('LOWERCASE', DefProc, Pointer(11), nil);
+ RegisterFunctionName('TRIM', DefProc, Pointer(12), nil);
+
+ RegisterFunctionName('LENGTH',Length_,nil,nil);
+ RegisterFunctionName('SETLENGTH',SetLength_,nil,nil);
+ RegisterFunctionName('LOW',Low_,nil,nil);
+ RegisterFunctionName('HIGH',High_,nil,nil);
+ RegisterFunctionName('DEC',Dec_,nil,nil);
+ RegisterFunctionName('INC',Inc_,nil,nil);
+
+ RegisterFunctionName('SIN', DefProc, Pointer(15), nil);
+ RegisterFunctionName('COS', DefProc, Pointer(16), nil);
+ RegisterFunctionName('SQRT', DefProc, Pointer(17), nil);
+ RegisterFunctionName('ROUND', DefProc, Pointer(18), nil);
+ RegisterFunctionName('TRUNC', DefProc, Pointer(19), nil);
+ RegisterFunctionName('INT', DefProc, Pointer(20), nil);
+ RegisterFunctionName('PI', DefProc, Pointer(21), nil);
+ RegisterFunctionName('ABS', DefProc, Pointer(22), nil);
+ RegisterFunctionName('STRTOFLOAT', DefProc, Pointer(23), nil);
+ RegisterFunctionName('FLOATTOSTR', DefProc, Pointer(24), nil);
+ RegisterFunctionName('PADL', DefProc, Pointer(25), nil);
+ RegisterFunctionName('PADR', DefProc, Pointer(26), nil);
+ RegisterFunctionName('PADZ', DefProc, Pointer(27), nil);
+ RegisterFunctionName('REPLICATE', DefProc, Pointer(28), nil);
+ RegisterFunctionName('STRINGOFCHAR', DefProc, Pointer(28), nil);
+ RegisterFunctionName('!ASSIGNED', DefProc, Pointer(29), nil);
+
+ RegisterDelphiFunction(@Unassigned, 'UNASSIGNED', cdRegister);
+ RegisterDelphiFunction(@VarIsEmpty, 'VARISEMPTY', cdRegister);
+ RegisterDelphiFunction(@Null, 'NULL', cdRegister);
+ RegisterDelphiFunction(@VarIsNull, 'VARISNULL', cdRegister);
+ RegisterDelphiFunction(@VarType, 'VARTYPE', cdRegister);
+ {$IFNDEF PS_NOIDISPATCH}
+ RegisterDelphiFunction(@IDispatchInvoke, 'IDISPATCHINVOKE', cdregister);
+ {$ENDIF}
+
+
+ RegisterFunctionName('GETARRAYLENGTH', GetArrayLength, nil, nil);
+ RegisterFunctionName('SETARRAYLENGTH', SetArrayLength, nil, nil);
+
+ RegisterFunctionName('RAISELASTEXCEPTION', DefPRoc, Pointer(30), nil);
+ RegisterFunctionName('RAISEEXCEPTION', DefPRoc, Pointer(31), nil);
+ RegisterFunctionName('EXCEPTIONTYPE', DefPRoc, Pointer(32), nil);
+ RegisterFunctionName('EXCEPTIONPARAM', DefPRoc, Pointer(33), nil);
+ RegisterFunctionName('EXCEPTIONPROC', DefPRoc, Pointer(34), nil);
+ RegisterFunctionName('EXCEPTIONPOS', DefPRoc, Pointer(35), nil);
+ RegisterFunctionName('EXCEPTIONTOSTRING', DefProc, Pointer(36), nil);
+ RegisterFunctionName('ANSIUPPERCASE', DefProc, Pointer(37), nil);
+ RegisterFunctionName('ANSILOWERCASE', DefProc, Pointer(38), nil);
+
+ {$IFNDEF PS_NOINT64}
+ RegisterFunctionName('STRTOINT64', DefProc, Pointer(39), nil);
+ RegisterFunctionName('INT64TOSTR', DefProc, Pointer(40), nil);
+ {$ENDIF}
+ RegisterFunctionName('SIZEOF', DefProc, Pointer(41), nil);
+
+ {$IFNDEF PS_NOWIDESTRING}
+ RegisterFunctionName('WSTRGET', DefProc, Pointer(42), nil);
+ RegisterFunctionName('WSTRSET', DefProc, Pointer(43), nil);
+ {$ENDIF}
+
+ RegisterInterfaceLibraryRuntime(Self);
+end;
+
+
+function ToString(p: PansiChar): tbtString;
+begin
+ SetString(Result, p, StrLen(p));
+end;
+
+function IntPIFVariantToVariant(Src: pointer; aType: TPSTypeRec; var Dest: Variant): Boolean;
+ function BuildArray(P: Pointer; aType: TPSTypeRec; Len: Longint): Boolean;
+ var
+ i, elsize: Longint;
+ v: variant;
+ begin
+ elsize := aType.RealSize;
+ Dest := VarArrayCreate([0, Len-1], varVariant);
+ for i := 0 to Len -1 do
+ begin
+ if not IntPIFVariantToVariant(p, aType, v) then
+ begin
+ result := false;
+ exit;
+ end;
+ Dest[i] := v;
+ p := Pointer(IPointer(p) + Cardinal(elSize));
+ end;
+ result := true;
+ end;
+begin
+ if aType = nil then
+ begin
+ Dest := null;
+ Result := True;
+ exit;
+ end;
+ if aType.BaseType = btPointer then
+ begin
+ aType := TPSTypeRec(Pointer(IPointer(src)+PointerSize)^);
+ Src := Pointer(Pointer(Src)^);
+ end;
+
+ case aType.BaseType of
+ btVariant: Dest := variant(src^);
+ btArray: if not BuildArray(Pointer(Src^), TPSTypeRec_Array(aType).ArrayType, PSDynArrayGetLength(Pointer(src^), aType)) then begin result := false; exit; end;
+ btStaticArray: if not BuildArray(Pointer(Src), TPSTypeRec_StaticArray(aType).ArrayType, PSDynArrayGetLength(Pointer(src^), aType)) then begin result := false; exit; end;
+ btU8:
+ if aType.ExportName = 'BOOLEAN' then
+ Dest := boolean(tbtu8(Src^) <> 0)
+ else
+ Dest := tbtu8(Src^);
+ btS8: Dest := tbts8(Src^);
+ btU16: Dest := tbtu16(Src^);
+ btS16: Dest := tbts16(Src^);
+ btU32: Dest := {$IFDEF DELPHI6UP}tbtu32{$ELSE}tbts32{$ENDIF}(Src^);
+ btS32: Dest := tbts32(Src^);
+ btSingle: Dest := tbtsingle(Src^);
+ btCurrency: Dest:=tbtCurrency(Src^);
+ btDouble:
+ begin
+ if aType.ExportName = 'TDATETIME' then
+ Dest := TDateTime(tbtDouble(Src^))
+ else
+ Dest := tbtDouble(Src^);
+ end;
+ btExtended: Dest := tbtExtended(Src^);
+ btString: Dest := tbtString(Src^);
+ btPChar: Dest := ToString(PansiChar(Src^));
+ {$IFNDEF PS_NOINT64}
+ {$IFDEF DELPHI6UP} btS64: Dest := tbts64(Src^); {$ELSE} bts64: begin Result := False; exit; end; {$ENDIF}
+ {$ENDIF}
+ btChar: Dest := tbtString(tbtchar(src^));
+ {$IFNDEF PS_NOWIDESTRING}
+ btWideString: Dest := tbtWideString(src^);
+ btWideChar: Dest := tbtwidestring(tbtwidechar(src^));
+ btUnicodeString: Dest := tbtUnicodeString(src^);
+ {$ENDIF}
+ else
+ begin
+ Result := False;
+ exit;
+ end;
+ end;
+ Result := True;
+end;
+
+function PIFVariantToVariant(Src: PIFVariant; var Dest: Variant): Boolean;
+begin
+ Result := IntPIFVariantToVariant(@PPSVariantData(src).Data, Src.FType, Dest);
+end;
+
+function VariantToPIFVariant(Exec: TPSExec; const Src: Variant; Dest: PIFVariant): Boolean;
+var
+ TT: PIFTypeRec;
+begin
+ if Dest = nil then begin Result := false; exit; end;
+ tt := Exec.FindType2(btVariant);
+ if tt = nil then begin Result := false; exit; end;
+ if Dest.FType.BaseType = btPointer then
+ Result := Exec.SetVariantValue(PPSVariantPointer(Dest).DataDest, @Src, PPSVariantPointer(Dest).DestType, tt)
+ else
+ Result := Exec.SetVariantValue(@PPSVariantData(Dest).Data, @Src, Dest.FType, tt);
+end;
+
+type
+ POpenArray = ^TOpenArray;
+ TOpenArray = record
+ AType: Byte; {0}
+ OrgVar: PPSVariantIFC;
+ FreeIt: Boolean;
+ ElementSize,
+ ItemCount: Longint;
+ Data: Pointer;
+ VarParam: Boolean;
+ end;
+function CreateOpenArray(VarParam: Boolean; Sender: TPSExec; val: PPSVariantIFC): POpenArray;
+var
+ datap, p: Pointer;
+ ctype: TPSTypeRec;
+ cp: Pointer;
+ i: Longint;
+begin
+ if (Val.aType.BaseType <> btArray) and (val.aType.BaseType <> btStaticArray) then
+ begin
+ Result := nil;
+ exit;
+ end;
+ New(Result);
+ Result.AType := 0;
+ Result.OrgVar := Val;
+ Result.VarParam := VarParam;
+
+ if val.aType.BaseType = btStaticArray then
+ begin
+ Result^.ItemCount := TPSTypeRec_StaticArray(val.aType).Size;
+ datap := Val.Dta;
+ end else
+ begin
+ Result^.ItemCount := PSDynArrayGetLength(Pointer(Val.Dta^), val.aType);
+ datap := Pointer(Val.Dta^);
+ end;
+ if TPSTypeRec_Array(Val.aType).ArrayType.BaseType <> btPointer then
+ begin
+ Result.FreeIt := False;
+ result.ElementSize := 0;
+ Result.Data := datap;
+ exit;
+ end;
+ Result.FreeIt := True;
+ Result.ElementSize := sizeof(TVarRec);
+ GetMem(Result.Data, Result.ItemCount * Result.ElementSize);
+ P := Result.Data;
+ FillChar(p^, Result^.ItemCount * Result^.ElementSize, 0);
+ for i := 0 to Result^.ItemCount -1 do
+ begin
+ ctype := Pointer(Pointer(IPointer(datap)+PointerSize)^);
+ cp := Pointer(Datap^);
+ if cp = nil then
+ begin
+ tvarrec(p^).VType := vtPointer;
+ tvarrec(p^).VPointer := nil;
+ end else begin
+ case ctype.BaseType of
+ btVariant: begin
+ tvarrec(p^).VType := vtVariant;
+ tvarrec(p^).VVariant := cp;
+ end;
+ btchar: begin
+ tvarrec(p^).VType := vtChar;
+ tvarrec(p^).VChar := tbtChar(tbtchar(cp^));
+ end;
+ btSingle:
+ begin
+ tvarrec(p^).VType := vtExtended;
+ New(tvarrec(p^).VExtended);
+ tvarrec(p^).VExtended^ := tbtsingle(cp^);
+ end;
+ btExtended:
+ begin
+ tvarrec(p^).VType := vtExtended;
+ New(tvarrec(p^).VExtended);
+ tvarrec(p^).VExtended^ := tbtextended(cp^);;
+ end;
+ btDouble:
+ begin
+ tvarrec(p^).VType := vtExtended;
+ New(tvarrec(p^).VExtended);
+ tvarrec(p^).VExtended^ := tbtdouble(cp^);
+ end;
+ {$IFNDEF PS_NOWIDESTRING}
+ btwidechar: begin
+ tvarrec(p^).VType := vtWideChar;
+ tvarrec(p^).VWideChar := tbtwidechar(cp^);
+ end;
+ {$IFDEF DELPHI2009UP}
+ btUnicodeString: begin
+ tvarrec(p^).VType := vtUnicodeString;
+ tbtunicodestring(TVarRec(p^).VWideString) := tbtunicodestring(cp^);
+ end;
+ {$ELSE}
+ btUnicodeString,
+ {$ENDIF}
+ btwideString: begin
+ tvarrec(p^).VType := vtWideString;
+ tbtwidestring(TVarRec(p^).VWideString) := tbtwidestring(cp^);
+ end;
+ {$ENDIF}
+ btU8: begin
+ tvarrec(p^).VType := vtInteger;
+ tvarrec(p^).VInteger := tbtu8(cp^);
+ end;
+ btS8: begin
+ tvarrec(p^).VType := vtInteger;
+ tvarrec(p^).VInteger := tbts8(cp^);
+ end;
+ btU16: begin
+ tvarrec(p^).VType := vtInteger;
+ tvarrec(p^).VInteger := tbtu16(cp^);
+ end;
+ btS16: begin
+ tvarrec(p^).VType := vtInteger;
+ tvarrec(p^).VInteger := tbts16(cp^);
+ end;
+ btU32: begin
+ tvarrec(p^).VType := vtInteger;
+ tvarrec(p^).VInteger := tbtu32(cp^);
+ end;
+ btS32: begin
+ tvarrec(p^).VType := vtInteger;
+ tvarrec(p^).VInteger := tbts32(cp^);
+ end;
+ {$IFNDEF PS_NOINT64}
+ btS64: begin
+ tvarrec(p^).VType := vtInt64;
+ New(tvarrec(p^).VInt64);
+ tvarrec(p^).VInt64^ := tbts64(cp^);
+ end;
+ {$ENDIF}
+ btString: begin
+ tvarrec(p^).VType := vtAnsiString;
+ tbtString(TVarRec(p^).VAnsiString) := tbtstring(cp^);
+ end;
+ btPChar:
+ begin
+ tvarrec(p^).VType := vtPchar;
+ TVarRec(p^).VPChar := pointer(cp^);
+ end;
+ btClass:
+ begin
+ tvarrec(p^).VType := vtObject;
+ tvarrec(p^).VObject := Pointer(cp^);
+ end;
+{$IFNDEF PS_NOINTERFACES}
+{$IFDEF Delphi3UP}
+ btInterface:
+ begin
+ tvarrec(p^).VType := vtInterface;
+ IUnknown(tvarrec(p^).VInterface) := IUnknown(cp^);
+ end;
+
+{$ENDIF}
+{$ENDIF}
+ end;
+ end;
+ datap := Pointer(IPointer(datap)+ (2*sizeof(Pointer)+sizeof(Longbool)));
+ p := PansiChar(p) + Result^.ElementSize;
+ end;
+end;
+
+procedure DestroyOpenArray(Sender: TPSExec; V: POpenArray);
+var
+ cp, datap: pointer;
+ ctype: TPSTypeRec;
+ p: PVarRec;
+ i: Longint;
+begin
+ if v.FreeIt then // basetype = btPointer
+ begin
+ p := v^.Data;
+ if v.OrgVar.aType.BaseType = btStaticArray then
+ datap := v.OrgVar.Dta
+ else
+ datap := Pointer(v.OrgVar.Dta^);
+ for i := 0 to v^.ItemCount -1 do
+ begin
+ ctype := Pointer(Pointer(IPointer(datap)+PointerSize)^);
+ cp := Pointer(Datap^);
+ case ctype.BaseType of
+ btU8:
+ begin
+ if v^.varParam then
+ tbtu8(cp^) := tvarrec(p^).VInteger
+ end;
+ btS8: begin
+ if v^.varParam then
+ tbts8(cp^) := tvarrec(p^).VInteger
+ end;
+ btU16: begin
+ if v^.varParam then
+ tbtu16(cp^) := tvarrec(p^).VInteger
+ end;
+ btS16: begin
+ if v^.varParam then
+ tbts16(cp^) := tvarrec(p^).VInteger
+ end;
+ btU32: begin
+ if v^.varParam then
+ tbtu32(cp^) := tvarrec(p^).VInteger
+ end;
+ btS32: begin
+ if v^.varParam then
+ tbts32(cp^) := tvarrec(p^).VInteger
+ end;
+ btChar: begin
+ if v^.VarParam then
+ tbtchar(cp^) := tbtChar(tvarrec(p^).VChar)
+ end;
+ btSingle: begin
+ if v^.VarParam then
+ tbtsingle(cp^) := tvarrec(p^).vextended^;
+ dispose(tvarrec(p^).vextended);
+ end;
+ btDouble: begin
+ if v^.VarParam then
+ tbtdouble(cp^) := tvarrec(p^).vextended^;
+ dispose(tvarrec(p^).vextended);
+ end;
+ btExtended: begin
+ if v^.VarParam then
+ tbtextended(cp^) := tvarrec(p^).vextended^;
+ dispose(tvarrec(p^).vextended);
+ end;
+ {$IFNDEF PS_NOINT64}
+ btS64: begin
+ if v^.VarParam then
+ tbts64(cp^) := tvarrec(p^).vInt64^;
+ dispose(tvarrec(p^).VInt64);
+ end;
+ {$ENDIF}
+ {$IFNDEF PS_NOWIDESTRING}
+ btWideChar: begin
+ if v^.varParam then
+ tbtwidechar(cp^) := tvarrec(p^).VWideChar;
+ end;
+ {$IFDEF DELPHI2009UP}
+ btUnicodeString:
+ begin
+ if v^.VarParam then
+ tbtunicodestring(cp^) := tbtunicodestring(TVarRec(p^).VUnicodeString);
+ finalize(tbtunicodestring(TVarRec(p^).VUnicodeString));
+ end;
+ {$ELSE}
+ btUnicodeString,
+ {$ENDIF}
+ btWideString:
+ begin
+ if v^.VarParam then
+ tbtwidestring(cp^) := tbtwidestring(TVarRec(p^).VWideString);
+ finalize(widestring(TVarRec(p^).VWideString));
+ end;
+ {$ENDIF}
+ btString: begin
+ if v^.VarParam then
+ tbtstring(cp^) := tbtstring(TVarRec(p^).VString);
+ finalize(tbtString(TVarRec(p^).VAnsiString));
+ end;
+ btClass: begin
+ if v^.VarParam then
+ Pointer(cp^) := TVarRec(p^).VObject;
+ end;
+{$IFNDEF PS_NOINTERFACES}
+{$IFDEF Delphi3UP}
+ btInterface: begin
+ if v^.VarParam then
+ IUnknown(cp^) := IUnknown(TVarRec(p^).VInterface);
+ finalize(tbtString(TVarRec(p^).VAnsiString));
+ end;
+{$ENDIF}
+{$ENDIF}
+ end;
+ datap := Pointer(IPointer(datap)+ (2*sizeof(Pointer)+sizeof(LongBool)));
+ p := Pointer(IPointer(p) + Cardinal(v^.ElementSize));
+ end;
+ FreeMem(v.Data, v.ElementSize * v.ItemCount);
+ end;
+ Dispose(V);
+end;
+
+
+{$ifndef FPC}
+ {$include x86.inc}
+{$else}
+{$IFDEF Delphi6UP}
+ {$if defined(cpu86)}
+ {$include x86.inc}
+ {$elseif defined(cpupowerpc)}
+ {$include powerpc.inc}
+ {$elseif defined(cpuarm)}
+ {$include arm.inc}
+ {$elseif defined(CPUX86_64)}
+ {$include x64.inc}
+ {$else}
+ {$fatal Pascal Script is not supported for your architecture at the moment!}
+ {$ifend}
+{$ELSE}
+{$include x86.inc}
+{$ENDIF}
+{$endif}
+
+type
+ PScriptMethodInfo = ^TScriptMethodInfo;
+ TScriptMethodInfo = record
+ Se: TPSExec;
+ ProcNo: Cardinal;
+ end;
+
+
+function MkMethod(FSE: TPSExec; No: Cardinal): TMethod;
+begin
+ if (no = 0) or (no = InvalidVal) then
+ begin
+ Result.Code := nil;
+ Result.Data := nil;
+ end else begin
+ Result.Code := @MyAllMethodsHandler;
+ Result.Data := GetMethodInfoRec(FSE, No);
+ end;
+end;
+
+
+procedure PFree(Sender: TPSExec; P: PScriptMethodInfo);
+begin
+ Dispose(p);
+end;
+
+function GetMethodInfoRec(SE: TPSExec; ProcNo: Cardinal): Pointer;
+var
+ I: Longint;
+ pp: PScriptMethodInfo;
+begin
+ if (ProcNo = 0) or (ProcNo = InvalidVal) then
+ begin
+ Result := nil;
+ exit;
+ end;
+ I := 2147483647;
+ repeat
+ pp := Se.FindProcResource2(@PFree, I);
+ if (i <> -1) and (pp^.ProcNo = ProcNo) then
+ begin
+ Result := Pp;
+ exit;
+ end;
+ until i = -1;
+ New(pp);
+ pp^.Se := TPSExec(Se);
+ pp^.ProcNo := Procno;
+ Se.AddResource(@PFree, pp);
+ Result := pp;
+end;
+
+
+
+
+
+type
+ TPtrArr = array[0..1000] of Pointer;
+ PPtrArr = ^TPtrArr;
+ TByteArr = array[0..1000] of byte;
+ PByteArr = ^TByteArr;
+ PPointer = ^Pointer;
+
+
+function VirtualMethodPtrToPtr(Ptr, FSelf: Pointer): Pointer;
+{$IFDEF FPC}
+var
+ x : PPtrArr;
+{$ENDIF}
+begin
+ {$IFDEF FPC}
+ x := Pointer(TObject(FSelf).ClassType) + vmtMethodStart;
+ Result := x^[Longint(Ptr)];
+ {$ELSE}
+ Result := PPtrArr(PPointer(FSelf)^)^[Longint(Ptr)];
+ {$ENDIF}
+end;
+
+function VirtualClassMethodPtrToPtr(Ptr, FSelf: Pointer): Pointer;
+{$IFDEF FPC}
+var
+ x : PPtrArr;
+{$ENDIF}
+begin
+ {$IFDEF FPC}
+ x := Pointer(FSelf) + vmtMethodStart;
+ Result := x^[Longint(Ptr)];
+ {$ELSE}
+ Result := PPtrArr(FSelf)^[Longint(Ptr)];
+ {$ENDIF}
+end;
+
+
+procedure CheckPackagePtr(var P: PByteArr);
+begin
+ if (word((@p[0])^) = $25FF) and (word((@p[6])^)=$C08B)then
+ begin
+ p := PPointer((@p[2])^)^;
+ end;
+end;
+
+{$IFDEF VER90}{$DEFINE NO_vmtSelfPtr}{$ENDIF}
+{$IFDEF FPC}{$DEFINE NO_vmtSelfPtr}{$ENDIF}
+
+{$IFNDEF FPC}
+
+function FindVirtualMethodPtr(Ret: TPSRuntimeClass; FClass: TClass; Ptr: Pointer): Pointer;
+// Idea of getting the number of VMT items from GExperts
+var
+ p: PPtrArr;
+ I: Longint;
+begin
+ p := Pointer(FClass);
+ CheckPackagePtr(PByteArr(Ptr));
+ if Ret.FEndOfVMT = MaxInt then
+ begin
+ I := {$IFDEF NO_vmtSelfPtr}-48{$ELSE}vmtSelfPtr{$ENDIF} div SizeOf(Pointer) + 1;
+ while I < 0 do
+ begin
+ if I < 0 then
+ begin
+ if I <> ({$IFDEF VER90}-44{$ELSE}vmtTypeInfo{$ENDIF} div SizeOf(Pointer)) then
+ begin // from GExperts code
+ if (IPointer(p^[I]) > IPointer(p)) and ((IPointer(p^[I]) - IPointer(p))
+ div
+ PointerSize < Ret.FEndOfVMT) then
+ begin
+ Ret.FEndOfVMT := (IPointer(p^[I]) - IPointer(p)) div SizeOf(Pointer);
+ end;
+ end;
+ end;
+ Inc(I);
+ end;
+ if Ret.FEndOfVMT = MaxInt then
+ begin
+ Ret.FEndOfVMT := 0; // cound not find EndOfVMT
+ Result := nil;
+ exit;
+ end;
+ end;
+ I := 0;
+ while I < Ret.FEndOfVMT do
+ begin
+ if p^[I] = Ptr then
+ begin
+ Result := Pointer(I);
+ exit;
+ end;
+ I := I + 1;
+ end;
+ Result := nil;
+end;
+
+{$ELSE}
+
+function FindVirtualMethodPtr(Ret: TPSRuntimeClass; FClass: TClass; Ptr: Pointer): Pointer;
+var
+ x,p: PPtrArr;
+ I: Longint;
+ t : Pointer;
+begin
+ p := Pointer(FClass) + vmtMethodStart;
+ I := 0;
+ while (p^[I]<>nil) and (I < 10000) do
+ begin
+ if p^[I] = Ptr then
+ begin
+ Result := Pointer(I);
+ x := Pointer(FClass) + vmtMethodStart;
+ t := x^[I];
+ Assert(t=Ptr,'Computation of virtual method pointer fail : t<>Ptr');
+ exit;
+ end;
+ I := I + 1;
+ end;
+ Result := nil;
+end;
+
+{$ENDIF}
+
+
+function NewTPSVariantIFC(avar: PPSVariant; varparam: boolean): TPSVariantIFC;
+begin
+ Result.VarParam := varparam;
+ if avar = nil then
+ begin
+ Result.aType := nil;
+ result.Dta := nil;
+ end else
+ begin
+ Result.aType := avar.FType;
+ result.Dta := @PPSVariantData(avar).Data;
+ if Result.aType.BaseType = btPointer then
+ begin
+ Result.aType := Pointer(Pointer(IPointer(result.dta)+ PointerSize)^);
+ Result.Dta := Pointer(Result.dta^);
+ end;
+ end;
+end;
+
+function NewTPSVariantRecordIFC(avar: PPSVariant; Fieldno: Longint): TPSVariantIFC;
+var
+ offs: Cardinal;
+begin
+ Result := NewTPSVariantIFC(avar, false);
+ if Result.aType.BaseType = btRecord then
+ begin
+ Offs := Cardinal(TPSTypeRec_Record(Result.aType).RealFieldOffsets[FieldNo]);
+ Result.Dta := Pointer(IPointer(Result.dta) + Offs);
+ Result.aType := TPSTypeRec_Record(Result.aType).FieldTypes[FieldNo];
+ end else
+ begin
+ Result.Dta := nil;
+ Result.aType := nil;
+ end;
+end;
+
+function PSGetArrayField(const avar: TPSVariantIFC; Fieldno: Longint): TPSVariantIFC;
+var
+ offs: Cardinal;
+ n: Longint;
+begin
+ Result := aVar;
+ case Result.aType.BaseType of
+ btStaticArray, btArray:
+ begin
+ if Result.aType.BaseType = btStaticArray then
+ n := TPSTypeRec_StaticArray(Result.aType).Size
+ else
+ n := PSDynArrayGetLength(Pointer(Result.Dta^), Result.aType);
+ if (FieldNo <0) or (FieldNo >= n) then
+ begin
+ Result.Dta := nil;
+ Result.aType := nil;
+ exit;
+ end;
+ Offs := TPSTypeRec_Array(Result.aType).ArrayType.RealSize * Cardinal(FieldNo);
+ if Result.aType.BaseType = btStaticArray then
+ Result.Dta := Pointer(IPointer(Result.dta) + Offs)
+ else
+ Result.Dta := Pointer(IPointer(Result.dta^) + Offs);
+ Result.aType := TPSTypeRec_Array(Result.aType).ArrayType;
+ end
+ else
+ Result.Dta := nil;
+ Result.aType := nil;
+ end;
+end;
+
+function PSGetRecField(const avar: TPSVariantIFC; Fieldno: Longint): TPSVariantIFC;
+var
+ offs: Cardinal;
+begin
+ Result := aVar;
+ if Result.aType.BaseType = btRecord then
+ begin
+ Offs := Cardinal(TPSTypeRec_Record(Result.aType).RealFieldOffsets[FieldNo]);
+ Result.aType := TPSTypeRec_Record(Result.aType).FieldTypes[FieldNo];
+ Result.Dta := Pointer(IPointer(Result.dta) + Offs);
+ end else
+ begin
+ Result.Dta := nil;
+ Result.aType := nil;
+ end;
+end;
+
+function NewPPSVariantIFC(avar: PPSVariant; varparam: boolean): PPSVariantIFC;
+begin
+ New(Result);
+ Result^ := NewTPSVariantIFC(avar, varparam);
+end;
+
+
+procedure DisposePPSVariantIFC(aVar: PPSVariantIFC);
+begin
+ if avar <> nil then
+ Dispose(avar);
+end;
+
+procedure DisposePPSVariantIFCList(list: TPSList);
+var
+ i: Longint;
+begin
+ for i := list.Count -1 downto 0 do
+ DisposePPSVariantIFC(list[i]);
+ list.free;
+end;
+
+function ClassCallProcMethod(Caller: TPSExec; p: TPSExternalProcRec; Global, Stack: TPSStack): Boolean;
+var
+ i: Integer;
+ MyList: TPSList;
+ n: PIFVariant;
+ v: PPSVariantIFC;
+ FSelf: Pointer;
+ CurrStack: Cardinal;
+ cc: TPSCallingConvention;
+ s: tbtString;
+begin
+ s := p.Decl;
+ if length(S) < 2 then
+ begin
+ Result := False;
+ exit;
+ end;
+ cc := TPSCallingConvention(s[1]);
+ Delete(s, 1, 1);
+ if s[1] = #0 then
+ n := Stack[Stack.Count -1]
+ else
+ n := Stack[Stack.Count -2];
+ if (n = nil) or (n^.FType.BaseType <> btClass)or (PPSVariantClass(n).Data = nil) then
+ begin
+ Caller.CMD_Err(erNullPointerException);
+ result := false;
+ exit;
+ end;
+ FSelf := PPSVariantClass(n).Data;
+ CurrStack := Cardinal(Stack.Count) - Cardinal(length(s)) -1;
+ if s[1] = #0 then inc(CurrStack);
+ MyList := TPSList.Create;
+ for i := 2 to length(s) do
+ begin
+ MyList.Add(nil);
+ end;
+ for i := length(s) downto 2 do
+ begin
+ n := Stack[CurrStack];
+ MyList[i - 2] := NewPPSVariantIFC(n, s[i] <> #0);
+ inc(CurrStack);
+ end;
+ if s[1] <> #0 then
+ begin
+ v := NewPPSVariantIFC(Stack[CurrStack + 1], True);
+ end else v := nil;
+ try
+ if p.Ext2 = nil then
+ Result := Caller.InnerfuseCall(FSelf, p.Ext1, cc, MyList, v)
+ else
+ Result := Caller.InnerfuseCall(FSelf, VirtualMethodPtrToPtr(p.Ext1, FSelf), cc, MyList, v);
+ finally
+ DisposePPSVariantIFC(v);
+ DisposePPSVariantIFCList(mylist);
+ end;
+end;
+
+function ClassCallProcConstructor(Caller: TPSExec; p: TPSExternalProcRec; Global, Stack: TPSStack): Boolean;
+var
+ i, h: Longint;
+ v: PPSVariantIFC;
+ MyList: TPSList;
+ n: PIFVariant;
+ FSelf: Pointer;
+ CurrStack: Cardinal;
+ cc: TPSCallingConvention;
+ s: tbtString;
+ FType: PIFTypeRec;
+ x: TPSRuntimeClass;
+ IntVal: PIFVariant;
+begin
+ n := Stack[Stack.Count -2];
+ if (n = nil) or (n^.FType.BaseType <> btU32) then
+ begin
+ result := false;
+ exit;
+ end;
+ FType := Caller.GetTypeNo(PPSVariantU32(N).Data);
+ if (FType = nil) then
+ begin
+ Result := False;
+ exit;
+ end;
+ h := MakeHash(FType.ExportName);
+ FSelf := nil;
+ for i := 0 to TPSRuntimeClassImporter(p.Ext2).FClasses.Count -1 do
+ begin
+ x:= TPSRuntimeClassImporter(p.Ext2).FClasses[i];
+ if (x.FClassNameHash = h) and (x.FClassName = FType.ExportName) then
+ begin
+ FSelf := x.FClass;
+ end;
+ end;
+ if FSelf = nil then begin
+ Result := False;
+ exit;
+ end;
+ s := p.Decl;
+ if length(S) < 2 then
+ begin
+ Result := False;
+ exit;
+ end;
+ cc := TPSCallingConvention(s[1]);
+ Delete(s, 1, 1);
+ CurrStack := Cardinal(Stack.Count) - Cardinal(length(s)) -1;
+ if s[1] = #0 then inc(CurrStack);
+ IntVal := CreateHeapVariant(Caller.FindType2(btU32));
+ if IntVal = nil then
+ begin
+ Result := False;
+ exit;
+ end;
+ {$IFDEF FPC}
+ // under FPC a constructor it's called with self=0 (EAX) and
+ // the VMT class pointer in EDX so they are effectively swaped
+ // using register calling convention
+ PPSVariantU32(IntVal).Data := Cardinal(FSelf);
+ FSelf := pointer(1);
+ {$ELSE}
+ PPSVariantU32(IntVal).Data := 1;
+ {$ENDIF}
+ MyList := TPSList.Create;
+ MyList.Add(NewPPSVariantIFC(intval, false));
+ for i := 2 to length(s) do
+ begin
+ MyList.Add(nil);
+ end;
+ for i := length(s) downto 2 do
+ begin
+ n :=Stack[CurrStack];
+// if s[i] <> #0 then
+// begin
+// MyList[i - 2] := NewPPSVariantIFC(n, s[i] <> #0);
+// end;
+ MyList[i - 1] := NewPPSVariantIFC(n, s[i] <> #0);
+ inc(CurrStack);
+ end;
+ if s[1] <> #0 then
+ begin
+ v := NewPPSVariantIFC(Stack[CurrStack + 1], True);
+ end else v := nil;
+ try
+ Result := Caller.InnerfuseCall(FSelf, p.Ext1, TPSCallingConvention(Integer(cc) or 64), MyList, v);
+ finally
+ DisposePPSVariantIFC(v);
+ DisposePPSVariantIFCList(mylist);
+ DestroyHeapVariant(intval);
+ end;
+end;
+
+
+function ClassCallProcVirtualConstructor(Caller: TPSExec; p: TPSExternalProcRec; Global, Stack: TPSStack): Boolean;
+var
+ i, h: Longint;
+ v: PPSVariantIFC;
+ MyList: TPSList;
+ n: PIFVariant;
+ FSelf: Pointer;
+ CurrStack: Cardinal;
+ cc: TPSCallingConvention;
+ s: tbtString;
+ FType: PIFTypeRec;
+ x: TPSRuntimeClass;
+ IntVal: PIFVariant;
+begin
+ n := Stack[Stack.Count -2];
+ if (n = nil) or (n^.FType.BaseType <> btU32) then
+ begin
+ Caller.CMD_Err(erNullPointerException);
+ result := false;
+ exit;
+ end;
+ FType := Caller.GetTypeNo(PPSVariantU32(N).Data);
+ if (FType = nil) then
+ begin
+ Caller.CMD_Err(erNullPointerException);
+ Result := False;
+ exit;
+ end;
+ h := MakeHash(FType.ExportName);
+ FSelf := nil;
+ for i := 0 to TPSRuntimeClassImporter(p.Ext2).FClasses.Count -1 do
+ begin
+ x:= TPSRuntimeClassImporter(p.Ext2).FClasses[i];
+ if (x.FClassNameHash = h) and (x.FClassName = FType.ExportName) then
+ begin
+ FSelf := x.FClass;
+ end;
+ end;
+ if FSelf = nil then begin
+ Result := False;
+ exit;
+ end;
+ s := p.Decl;
+ if length(S) < 2 then
+ begin
+ Result := False;
+ exit;
+ end;
+ cc := TPSCallingConvention(s[1]);
+ delete(s, 1, 1);
+ CurrStack := Cardinal(Stack.Count) - Cardinal(length(s)) -1;
+ if s[1] = #0 then inc(CurrStack);
+ IntVal := CreateHeapVariant(Caller.FindType2(btU32));
+ if IntVal = nil then
+ begin
+ Result := False;
+ exit;
+ end;
+ PPSVariantU32(IntVal).Data := 1;
+ MyList := TPSList.Create;
+ MyList.Add(NewPPSVariantIFC(intval, false));
+ for i := 2 to length(s) do
+ begin
+ MyList.Add(nil);
+ end;
+ for i := length(s) downto 2 do
+ begin
+ n :=Stack[CurrStack];
+ MyList[i - 1] := NewPPSVariantIFC(n, s[i] <> #0);
+ inc(CurrStack);
+ end;
+ if s[1] <> #0 then
+ begin
+ v := NewPPSVariantIFC(Stack[CurrStack + 1], True);
+ end else v := nil;
+ try
+ Result := Caller.InnerfuseCall(FSelf, VirtualClassMethodPtrToPtr(p.Ext1, FSelf), cc, MyList, v);
+ finally
+ DisposePPSVariantIFC(v);
+ DisposePPSVariantIFCList(mylist);
+ DestroyHeapVariant(intval);
+ end;
+end;
+
+function CastProc(Caller: TPSExec; p: TPSExternalProcRec; Global, Stack: TPSStack): Boolean;
+var
+ TypeNo, InVar, ResVar: TPSVariantIFC;
+ FSelf: TClass;
+ FType: PIFTypeRec;
+ H, I: Longint;
+ x: TPSRuntimeClass;
+begin
+ TypeNo := NewTPSVariantIFC(Stack[Stack.Count-3], false);
+ InVar := NewTPSVariantIFC(Stack[Stack.Count-2], false);
+ ResVar := NewTPSVariantIFC(Stack[Stack.Count-1], true);
+ if (TypeNo.Dta = nil) or (InVar.Dta = nil) or (ResVar.Dta = nil) or
+ (TypeNo.aType.BaseType <> btu32) or (resvar.aType <> Caller.FTypes[tbtu32(Typeno.dta^)])
+ then
+ begin
+ Result := False;
+ Exit;
+ end;
+{$IFNDEF PS_NOINTERFACES}
+ if (invar.atype.BaseType = btInterface) and (resvar.aType.BaseType = btInterface) then
+ begin
+{$IFNDEF Delphi3UP}
+ if IUnknown(resvar.Dta^) <> nil then
+ IUnknown(resvar.Dta^).Release;
+{$ENDIF}
+ IUnknown(resvar.Dta^) := nil;
+ if (IUnknown(invar.Dta^) = nil) or (IUnknown(invar.Dta^).QueryInterface(TPSTypeRec_Interface(ResVar.aType).Guid, IUnknown(resvar.Dta^)) <> 0) then
+ begin
+ Caller.CMD_Err2(erCustomError, tbtString(RPS_CannotCastInterface));
+ Result := False;
+ exit;
+ end;
+{$IFDEF Delphi3UP}
+ end else if (Invar.aType.BaseType = btclass) and (resvar.aType.BaseType = btInterface) then
+ begin
+{$IFNDEF Delphi3UP}
+ if IUnknown(resvar.Dta^) <> nil then
+ IUnknown(resvar.Dta^).Release;
+{$ENDIF}
+ IUnknown(resvar.Dta^) := nil;
+ if (TObject(invar.Dta^)= nil) or (not TObject(invar.dta^).GetInterface(TPSTypeRec_Interface(ResVar.aType).Guid, IUnknown(resvar.Dta^))) then
+ begin
+ Caller.CMD_Err2(erCustomError, tbtString(RPS_CannotCastInterface));
+ Result := False;
+ exit;
+ end;
+{$ENDIF}
+ end else {$ENDIF}if (invar.aType.BaseType = btclass) and (resvar.aType.BaseType = btclass ) then
+ begin
+ FType := Caller.GetTypeNo(tbtu32(TypeNo.Dta^));
+ if (FType = nil) then
+ begin
+ Result := False;
+ exit;
+ end;
+ h := MakeHash(FType.ExportName);
+ FSelf := nil;
+ for i := 0 to TPSRuntimeClassImporter(p.Ext2).FClasses.Count -1 do
+ begin
+ x:= TPSRuntimeClassImporter(p.Ext2).FClasses[i];
+ if (x.FClassNameHash = h) and (x.FClassName = FType.ExportName) then
+ begin
+ FSelf := x.FClass;
+ end;
+ end;
+ if FSelf = nil then begin
+ Result := False;
+ exit;
+ end;
+
+ try
+ TObject(ResVar.Dta^) := TObject(InVar.Dta^) as FSelf;
+ except
+ Result := False;
+ Caller.CMD_Err2(erCustomError, tbtString(RPS_CannotCastObject));
+ exit;
+ end;
+ end else
+ begin
+ Result := False;
+ exit;
+ end;
+ result := True;
+end;
+
+
+function NilProc(Caller: TPSExec; p: TPSExternalProcRec; Global, Stack: TPSStack): Boolean;
+var
+ n: TPSVariantIFC;
+begin
+ n := NewTPSVariantIFC(Stack[Stack.Count-1], True);
+ if (n.Dta = nil) or ((n.aType.BaseType <> btClass) and (n.aType.BaseType <> btInterface)) then
+ begin
+ Result := False;
+ Caller.CMD_Err(erNullPointerException);
+ Exit;
+ end;
+{$IFNDEF PS_NOINTERFACES}
+ if n.aType.BaseType = btInterface then
+ begin
+ {$IFNDEF Delphi3UP}
+ if IUnknown(n.Dta^) <> nil then
+ IUnknown(n.Dta^).Release;
+ {$ENDIF}
+ IUnknown(n.Dta^) := nil;
+ end else
+ {$ENDIF}
+ Pointer(n.Dta^) := nil;
+ result := True;
+end;
+function IntfCallProc(Caller: TPSExec; p: TPSExternalProcRec; Global, Stack: TPSStack): Boolean;
+var
+ i: Integer;
+ MyList: TPSList;
+ n: TPSVariantIFC;
+ n2: PPSVariantIFC;
+ FSelf: Pointer;
+ CurrStack: Cardinal;
+ cc: TPSCallingConvention;
+ s: tbtString;
+begin
+ s := p.Decl;
+ if length(S) < 2 then
+ begin
+ Result := False;
+ exit;
+ end;
+ cc := TPSCallingConvention(s[1]);
+ Delete(s, 1, 1);
+ if s[1] = #0 then
+ n := NewTPSVariantIFC(Stack[Stack.Count -1], false)
+ else
+ n := NewTPSVariantIFC(Stack[Stack.Count -2], false);
+ if (n.dta = nil) or (n.atype.BaseType <> btInterface) or (Pointer(n.Dta^) = nil) then
+ begin
+ Caller.CMD_Err(erNullPointerException);
+ result := false;
+ exit;
+ end;
+ FSelf := Pointer(n.dta^);
+ CurrStack := Cardinal(Stack.Count) - Cardinal(length(s)) -1;
+ if s[1] = #0 then inc(CurrStack);
+ MyList := TPSList.Create;
+ for i := 2 to length(s) do
+ begin
+ MyList.Add(nil);
+ end;
+ for i := length(s) downto 2 do
+ begin
+ MyList[i - 2] := NewPPSVariantIFC(Stack[CurrStack], s[i] <> #0);
+ inc(CurrStack);
+ end;
+ if s[1] <> #0 then
+ begin
+ n2 := NewPPSVariantIFC(Stack[CurrStack + 1], True);
+ end else n2 := nil;
+ try
+ Caller.InnerfuseCall(FSelf, Pointer(Pointer(IPointer(FSelf^) + (Cardinal(p.Ext1) * Sizeof(Pointer)))^), cc, MyList, n2);
+ result := true;
+ finally
+ DisposePPSVariantIFC(n2);
+ DisposePPSVariantIFCList(MyList);
+ end;
+end;
+
+
+function InterfaceProc(Sender: TPSExec; p: TPSExternalProcRec; Tag: Pointer): Boolean;
+var
+ s: tbtString;
+begin
+ s := p.Decl;
+ delete(s,1,5); // delete 'intf:'
+ if s = '' then
+ begin
+ Result := False;
+ exit;
+ end;
+ if s[1] = '.'then
+ begin
+ Delete(s,1,1);
+ if length(S) < 6 then
+ begin
+ Result := False;
+ exit;
+ end;
+ p.ProcPtr := IntfCallProc;
+ p.Ext1 := Pointer((@s[1])^); // Proc Offset
+ Delete(s,1,4);
+ P.Decl := s;
+ Result := True;
+ end else Result := False;
+end;
+
+
+function getMethodNo(P: TMethod; SE: TPSExec): Cardinal;
+begin
+ if (p.Code <> @MyAllMethodsHandler) or (p.Data = nil)or (PScriptMethodInfo(p.Data)^.Se <> se) then
+ Result := 0
+ else
+ begin
+ Result := PScriptMethodInfo(p.Data)^.ProcNo;
+ end;
+end;
+
+function ClassCallProcProperty(Caller: TPSExec; p: TPSExternalProcRec; Global, Stack: TPSStack): Boolean;
+var
+ n: TPSVariantIFC;
+ ltemp: Longint;
+ FSelf: Pointer;
+ m: TMethod;
+begin
+ try
+ if p.Ext2 = Pointer(0) then
+ begin
+ n := NewTPSVariantIFC(Stack[Stack.Count -1], False);
+ if (n.Dta = nil) or (n.aType.BaseType <> btclass) then
+ begin
+ result := false;
+ Caller.CMD_Err(erNullPointerException);
+ exit;
+ end;
+ FSelf := Pointer(n.dta^);
+ if FSelf = nil then
+ begin
+ Caller.CMD_Err(erCouldNotCallProc);
+ Result := False;
+ exit;
+ end;
+ n := NewTPSVariantIFC(Stack[Stack.Count -2], false);
+ if (PPropInfo(p.Ext1)^.PropType^.Kind = tkMethod) and ((n.aType.BaseType = btu32) or (n.aType.BaseType = btProcPtr))then
+ begin
+ SetMethodProp(TObject(FSelf), PPropInfo(p.Ext1), MkMethod(Caller, tbtu32(n.dta^)));
+ end else
+ case n.aType.BaseType of
+ btSet:
+ begin
+ ltemp := 0;
+ move(Byte(n.Dta^), ltemp, TPSTypeRec_Set(n.aType).aByteSize);
+ SetOrdProp(TObject(FSelf), PPropInfo(p.Ext1), ltemp);
+ end;
+ btChar, btU8: SetOrdProp(TObject(FSelf), PPropInfo(p.Ext1), tbtu8(n.Dta^));
+ btS8: SetOrdProp(TObject(FSelf), PPropInfo(p.Ext1), tbts8(n.Dta^));
+ {$IFNDEF PS_NOWIDESTRING}btwidechar, {$ENDIF}btU16: SetOrdProp(TObject(FSelf), PPropInfo(p.Ext1), tbtu16(n.Dta^));
+ btS16: SetOrdProp(TObject(FSelf), PPropInfo(p.Ext1), tbts16(n.Dta^));
+ btU32: SetOrdProp(TObject(FSelf), PPropInfo(p.Ext1), tbtu32(n.Dta^));
+ btS32: SetOrdProp(TObject(FSelf), PPropInfo(p.Ext1), tbts32(n.Dta^));
+ btSingle: SetFloatProp(TObject(FSelf), p.Ext1, tbtsingle(n.Dta^));
+ btDouble: SetFloatProp(TObject(FSelf), p.Ext1, tbtdouble(n.Dta^));
+ btExtended: SetFloatProp(TObject(FSelf), p.Ext1, tbtextended(n.Dta^));
+ btString: SetStrProp(TObject(FSelf), p.Ext1, string(tbtString(n.Dta^)));
+ btPChar: SetStrProp(TObject(FSelf), p.Ext1, string(pansichar(n.Dta^)));
+ btClass: SetOrdProp(TObject(FSelf), P.Ext1, Longint(n.Dta^));
+ {$IFDEF DELPHI6UP}
+{$IFNDEF PS_NOWIDESTRING}
+{$IFNDEF DELPHI2009UP}btUnicodeString,{$ENDIF}
+ btWideString: SetWideStrProp(TObject(FSelf), P.Ext1, tbtWidestring(n.dta^));
+{$IFDEF DELPHI2009UP}
+ btUnicodeString: SetUnicodeStrProp(TObject(FSelf), P.Ext1, tbtUnicodestring(n.dta^));
+{$ENDIF}
+ {$ENDIF}
+{$ENDIF}
+ else
+ begin
+ Result := False;
+ exit;
+ end;
+ end;
+ Result := true;
+ end else begin
+ n := NewTPSVariantIFC(Stack[Stack.Count -2], False);
+ if (n.dta = nil) or (n.aType.BaseType <> btClass)then
+ begin
+ result := false;
+ Caller.CMD_Err(erNullPointerException);
+ exit;
+ end;
+ FSelf := Pointer(n.dta^);
+ if FSelf = nil then
+ begin
+ Caller.CMD_Err(erCouldNotCallProc);
+ Result := False;
+ exit;
+ end;
+ n := NewTPSVariantIFC(Stack[Stack.Count -1], false);
+ if (PPropInfo(p.Ext1)^.PropType^.Kind = tkMethod) and ((n.aType.BaseType = btu32) or (n.aType.BaseType = btprocptr)) then
+ begin
+ m := GetMethodProp(TObject(FSelf), PPropInfo(p.Ext1));
+ Cardinal(n.Dta^) := GetMethodNo(m, Caller);
+ if Cardinal(n.dta^) = 0 then
+ begin
+ Pointer(Pointer((IPointer(n.dta)+PointerSize))^) := m.Data;
+ Pointer(Pointer((IPointer(n.dta)+PointerSize2))^) := m.Code;
+ end;
+ end else
+ case n.aType.BaseType of
+ btSet:
+ begin
+ ltemp := GetOrdProp(TObject(FSelf), PPropInfo(p.Ext1));
+ move(ltemp, Byte(n.Dta^), TPSTypeRec_Set(n.aType).aByteSize);
+ end;
+ btU8: tbtu8(n.Dta^) := GetOrdProp(TObject(FSelf), p.Ext1);
+ btS8: tbts8(n.Dta^) := GetOrdProp(TObject(FSelf), p.Ext1);
+ btU16: tbtu16(n.Dta^) := GetOrdProp(TObject(FSelf), p.Ext1);
+ btS16: tbts16(n.Dta^) := GetOrdProp(TObject(FSelf), p.Ext1);
+ btU32: tbtu32(n.Dta^) := GetOrdProp(TObject(FSelf), p.Ext1);
+ btS32: tbts32(n.Dta^) := GetOrdProp(TObject(FSelf), p.Ext1);
+ btSingle: tbtsingle(n.Dta^) := GetFloatProp(TObject(FSelf), p.Ext1);
+ btDouble: tbtdouble(n.Dta^) := GetFloatProp(TObject(FSelf), p.Ext1);
+ btExtended: tbtextended(n.Dta^) := GetFloatProp(TObject(FSelf), p.Ext1);
+ btString: tbtString(n.Dta^) := tbtString(GetStrProp(TObject(FSelf), p.Ext1));
+ btClass: Longint(n.dta^) := GetOrdProp(TObject(FSelf), p.Ext1);
+ {$IFDEF DELPHI6UP}
+{$IFNDEF PS_NOWIDESTRING}
+ {$IFDEF DELPHI2009UP}
+ btUnicodeString: tbtUnicodeString(n.dta^) := GetUnicodeStrProp(TObject(FSelf), P.Ext1);
+ {$ELSE}
+ btUnicodeString,
+ {$ENDIF}
+ btWideString: tbtWidestring(n.dta^) := GetWideStrProp(TObject(FSelf), P.Ext1);
+{$ENDIF}
+{$ENDIF}
+ else
+ begin
+ Result := False;
+ exit;
+ end;
+ end;
+ Result := True;
+ end;
+ finally
+ end;
+end;
+
+function ClassCallProcPropertyHelper(Caller: TPSExec; p: TPSExternalProcRec; Global, Stack: TPSStack): Boolean;
+var
+ I, ParamCount: Longint;
+ Params: TPSList;
+ n: TPSVariantIFC;
+ FSelf: Pointer;
+begin
+ if Length(P.Decl) < 4 then begin
+ Result := False;
+ exit;
+ end;
+ ParamCount := Longint((@P.Decl[1])^);
+ if Longint(Stack.Count) < ParamCount +1 then begin
+ Result := False;
+ exit;
+ end;
+ Dec(ParamCount);
+ if p.Ext1 <> nil then // read
+ begin
+ n := NewTPSVariantIFC(Stack[Longint(Stack.Count) - 2], False);
+ if (n.Dta = nil) or (n.aType.BaseType <> btClass) then
+ begin
+ result := false;
+ Caller.CMD_Err(erNullPointerException);
+ exit;
+ end;
+ FSelf := pointer(n.Dta^);
+ if FSelf = nil then
+ begin
+ Caller.CMD_Err(erCouldNotCallProc);
+ Result := False;
+ exit;
+ end;
+ Params := TPSList.Create;
+ Params.Add(NewPPSVariantIFC(Stack[Longint(Stack.Count) - 1], True));
+ for i := Stack.Count -3 downto Longint(Stack.Count) - ParamCount -2 do
+ begin
+ Params.Add(NewPPSVariantIFC(Stack[I], False));
+ end;
+ try
+ Result := Caller.InnerfuseCall(FSelf, p.Ext1, cdRegister, Params, nil);
+ finally
+ DisposePPSVariantIFCList(Params);
+ end;
+ end else begin
+ n := NewTPSVariantIFC(Stack[Longint(Stack.Count) - 1], False);
+ if (n.Dta = nil) or (n.aType.BaseType <> btClass) then
+ begin
+ result := false;
+ Caller.CMD_Err(erNullPointerException);
+ exit;
+ end;
+ FSelf := pointer(n.Dta^);
+ if FSelf = nil then
+ begin
+ Caller.CMD_Err(erCouldNotCallProc);
+ Result := False;
+ exit;
+ end;
+ Params := TPSList.Create;
+ Params.Add(NewPPSVariantIFC(Stack[Longint(Stack.Count) - ParamCount - 2], False));
+
+ for i := Stack.Count -2 downto Longint(Stack.Count) - ParamCount -1 do
+ begin
+ Params.Add(NewPPSVariantIFC(Stack[I], False));
+ end;
+ try
+ Result := Caller.InnerfuseCall(FSelf, p.Ext2, cdregister, Params, nil);
+ finally
+ DisposePPSVariantIFCList(Params);
+ end;
+ end;
+end;
+
+function ClassCallProcPropertyHelperName(Caller: TPSExec; p: TPSExternalProcRec; Global, Stack: TPSStack): Boolean;
+var
+ I, ParamCount: Longint;
+ Params: TPSList;
+ tt: PIFVariant;
+ n: TPSVariantIFC;
+ FSelf: Pointer;
+begin
+ if Length(P.Decl) < 4 then begin
+ Result := False;
+ exit;
+ end;
+ ParamCount := Longint((@P.Decl[1])^);
+ if Longint(Stack.Count) < ParamCount +1 then begin
+ Result := False;
+ exit;
+ end;
+ Dec(ParamCount);
+ if p.Ext1 <> nil then // read
+ begin
+ n := NewTPSVariantIFC(Stack[Longint(Stack.Count) - 2], false);
+ if (n.Dta = nil) or (n.aType.BaseType <> btClass) then
+ begin
+ result := false;
+ Caller.CMD_Err(erNullPointerException);
+ exit;
+ end;
+ FSelf := Tobject(n.dta^);
+ Params := TPSList.Create;
+ Params.Add(NewPPSVariantIFC(Stack[Longint(Stack.Count) - 1], True));
+ for i := Stack.Count -3 downto Longint(Stack.Count) - ParamCount -2 do
+ Params.Add(NewPPSVariantIFC(Stack[I], False));
+ tt := CreateHeapVariant(Caller.FindType2(btString));
+ if tt <> nil then
+ begin
+ PPSVariantAString(tt).Data := p.Name;
+ Params.Add(NewPPSVariantIFC(tt, false));
+ end;
+ try
+ Result := Caller.InnerfuseCall(FSelf, p.Ext1, cdRegister, Params, nil);
+ finally
+ DestroyHeapVariant(tt);
+ DisposePPSVariantIFCList(Params);
+ end;
+ end else begin
+ n := NewTPSVariantIFC(Stack[Longint(Stack.Count) - 1], false);
+ if (n.Dta = nil) or (n.aType.BaseType <> btClass) then
+ begin
+ result := false;
+ Caller.CMD_Err(erNullPointerException);
+ exit;
+ end;
+ FSelf := Tobject(n.dta^);
+ Params := TPSList.Create;
+ Params.Add(NewPPSVariantIFC(Stack[Longint(Stack.Count) - 2], True));
+
+ for i := Stack.Count -2 downto Longint(Stack.Count) - ParamCount -1 do
+ begin
+ Params.Add(NewPPSVariantIFC(Stack[I], false));
+ end;
+ tt := CreateHeapVariant(Caller.FindType2(btString));
+ if tt <> nil then
+ begin
+ PPSVariantAString(tt).Data := p.Name;
+ Params.Add(NewPPSVariantIFC(tt, false));
+ end;
+ try
+ Result := Caller.InnerfuseCall(FSelf, p.Ext2, cdregister, Params, nil);
+ finally
+ DestroyHeapVariant(tt);
+ DisposePPSVariantIFCList(Params);
+ end;
+ end;
+end;
+
+
+
+function ClassCallProcEventPropertyHelper(Caller: TPSExec; p: TPSExternalProcRec; Global, Stack: TPSStack): Boolean;
+{Event property helper}
+var
+ I, ParamCount: Longint;
+ Params: TPSList;
+ n: TPSVariantIFC;
+ data: TMethod;
+ n2: PIFVariant;
+ FSelf: Pointer;
+begin
+ if Length(P.Decl) < 4 then begin
+ Result := False;
+ exit;
+ end;
+ ParamCount := Longint((@P.Decl[1])^);
+ if Longint(Stack.Count) < ParamCount +1 then begin
+ Result := False;
+ exit;
+ end;
+ Dec(ParamCount);
+ if p.Ext1 <> nil then // read
+ begin
+ n := NewTPSVariantIFC(Stack[Longint(Stack.Count) - 2], false);
+ if (n.Dta = nil) or (n.aType.BaseType <> btClass) then
+ begin
+ result := false;
+ Caller.CMD_Err(erNullPointerException);
+ exit;
+ end;
+ FSelf := Tobject(n.dta^);
+ n := NewTPSVariantIFC(Stack[Longint(Stack.Count) - 1], True); // Result
+ if (n.aType.BaseType <> btU32) and (n.aType.BaseType <> btProcPtr) then
+ begin
+ Result := False;
+ Caller.CMD_Err(erNullPointerException);
+ exit;
+ end;
+ n2 := CreateHeapVariant(Caller.FindType2(btPChar));
+ if n2 = nil then
+ begin
+ Result := False;
+ exit;
+ end;
+ Params := TPSList.Create;
+//{$IFDEF CPU64}
+//{$ELSE}
+ data.Code := nil;
+ data.Data := nil;
+//{$ENDIF}
+ PPSVariantDynamicArray(n2)^.Data:= @data;
+ Params.Add(NewPPSVariantIFC(n2, false));
+ for i := Stack.Count -3 downto Longint(Stack.Count) - ParamCount -2 do
+ Params.Add(NewPPSVariantIFC(Stack[i], False));
+ try
+ Result := Caller.InnerfuseCall(FSelf, p.Ext1, cdRegister, Params, nil);
+ finally
+ Cardinal(n.Dta^) := getMethodNo(data, Caller);
+ if Cardinal(n.Dta^) = 0 then
+ begin
+ Pointer(Pointer((IPointer(n.dta)+PointerSize))^) := data.Data;
+ Pointer(Pointer((IPointer(n.dta)+PointerSize2))^) := data.Code;
+ end;
+ DestroyHeapVariant(n2);
+ DisposePPSVariantIFCList(Params);
+ end;
+ end else begin
+ n := NewTPSVariantIFC(Stack[Longint(Stack.Count) - 1], false);
+ if (n.Dta = nil) or (n.aType.BaseType <> btClass) then
+ begin
+ result := false;
+ Caller.CMD_Err(erNullPointerException);
+ exit;
+ end;
+ FSelf := Tobject(n.dta^);
+ n := NewTPSVariantIFC(Stack[Longint(Stack.Count) - 2], false);
+ if (n.Dta = nil) or ((n.aType.BaseType <> btu32) and (n.aType.BaseType <> btProcPtr)) then
+ begin
+ result := false;
+ Caller.CMD_Err(erNullPointerException);
+ exit;
+ end;
+ n2 := CreateHeapVariant(Caller.FindType2(btPchar));
+ if n2 = nil then
+ begin
+ Result := False;
+ exit;
+ end;
+
+ if (n.aType.BaseType = btProcPtr) and (cardinal(n.dta^) = 0) then
+ data := TMethod(Pointer(IPointer(n.dta^)+4)^)
+ else
+ data := MkMethod(Caller, cardinal(n.dta^));
+ Params := TPSList.Create;
+ Params.Add(NewPPSVariantIFC(n2, False));
+
+ for i := Stack.Count -2 downto Longint(Stack.Count) - ParamCount -1 do
+ begin
+ Params.Add(NewPPSVariantIFC(Stack[I], False));
+ end;
+ try
+ Result := Caller.InnerfuseCall(FSelf, p.Ext2, cdregister, Params, nil);
+ finally
+ DestroyHeapVariant(n2);
+ DisposePPSVariantIFCList(Params);
+ end;
+ end;
+end;
+
+
+{'class:'+CLASSNAME+'|'+FUNCNAME+'|'+chr(CallingConv)+chr(hasresult)+params
+
+For property write functions there is an '@' after the funcname.
+}
+function SpecImport(Sender: TPSExec; p: TPSExternalProcRec; Tag: Pointer): Boolean;
+var
+ H, I: Longint;
+ S, s2: tbtString;
+ CL: TPSRuntimeClass;
+ Px: PClassItem;
+ pp: PPropInfo;
+ IsRead: Boolean;
+begin
+ s := p.Decl;
+ delete(s, 1, 6);
+ if s = '-' then {nil function}
+ begin
+ p.ProcPtr := NilProc;
+ Result := True;
+ exit;
+ end;
+ if s = '+' then {cast function}
+ begin
+ p.ProcPtr := CastProc;
+ p.Ext2 := Tag;
+ Result := True;
+ exit;
+ end;
+ s2 := copy(S, 1, pos(tbtchar('|'), s)-1);
+ delete(s, 1, length(s2) + 1);
+ H := MakeHash(s2);
+ ISRead := False;
+ cl := nil;
+ for I := TPSRuntimeClassImporter(Tag).FClasses.Count -1 downto 0 do
+ begin
+ Cl := TPSRuntimeClassImporter(Tag).FClasses[I];
+ if (Cl.FClassNameHash = h) and (cl.FClassName = s2) then
+ begin
+ IsRead := True;
+ break;
+ end;
+ end;
+ if not isRead then begin
+ Result := False;
+ exit;
+ end;
+ s2 := copy(S, 1, pos(tbtchar('|'), s)-1);
+ delete(s, 1, length(s2) + 1);
+ if (s2 <> '') and (s2[length(s2)] = '@') then
+ begin
+ IsRead := False;
+ Delete(S2, length(s2), 1);
+ end else
+ isRead := True;
+ p.Name := s2;
+ H := MakeHash(s2);
+ for i := cl.FClassItems.Count -1 downto 0 do
+ begin
+ px := cl.FClassItems[I];
+ if (px^.FNameHash = h) and (px^.FName = s2) then
+ begin
+ p.Decl := s;
+ case px^.b of
+ {0: ext1=ptr}
+ {1: ext1=pointerinlist}
+ {2: ext1=propertyinfo}
+ {3: ext1=readfunc; ext2=writefunc}
+ 4:
+ begin
+ p.ProcPtr := ClassCallProcConstructor;
+ p.Ext1 := px^.Ptr;
+ if p.Ext1 = nil then begin result := false; exit; end;
+ p.Ext2 := Tag;
+ end;
+ 5:
+ begin
+ p.ProcPtr := ClassCallProcVirtualConstructor;
+ p.Ext1 := px^.Ptr;
+ if p.Ext1 = nil then begin result := false; exit; end;
+ p.Ext2 := Tag;
+ end;
+ 6:
+ begin
+ p.ProcPtr := ClassCallProcEventPropertyHelper;
+ if IsRead then
+ begin
+ p.Ext1 := px^.FReadFunc;
+ if p.Ext1 = nil then begin result := false; exit; end;
+ p.Ext2 := nil;
+ end else
+ begin
+ p.Ext1 := nil;
+ p.Ext2 := px^.FWriteFunc;
+ if p.Ext2 = nil then begin result := false; exit; end;
+ end;
+ end;
+ 0:
+ begin
+ p.ProcPtr := ClassCallProcMethod;
+ p.Ext1 := px^.Ptr;
+ if p.Ext1 = nil then begin result := false; exit; end;
+ p.Ext2 := nil;
+ end;
+ 1:
+ begin
+ p.ProcPtr := ClassCallProcMethod;
+ p.Ext1 := px^.PointerInList;
+ //if p.Ext1 = nil then begin result := false; exit; end;
+ p.ext2 := pointer(1);
+ end;
+ 3:
+ begin
+ p.ProcPtr := ClassCallProcPropertyHelper;
+ if IsRead then
+ begin
+ p.Ext1 := px^.FReadFunc;
+ if p.Ext1 = nil then begin result := false; exit; end;
+ p.Ext2 := nil;
+ end else
+ begin
+ p.Ext1 := nil;
+ p.Ext2 := px^.FWriteFunc;
+ if p.Ext2 = nil then begin result := false; exit; end;
+ end;
+ end;
+ 7:
+ begin
+ p.ProcPtr := ClassCallProcPropertyHelperName;
+ if IsRead then
+ begin
+ p.Ext1 := px^.FReadFunc;
+ if p.Ext1 = nil then begin result := false; exit; end;
+ p.Ext2 := nil;
+ end else
+ begin
+ p.Ext1 := nil;
+ p.Ext2 := px^.FWriteFunc;
+ if p.Ext2 = nil then begin result := false; exit; end;
+ end;
+ end;
+ else
+ begin
+ result := false;
+ exit;
+ end;
+ end;
+ Result := true;
+ exit;
+ end;
+ end;
+ if cl.FClass.ClassInfo <> nil then
+ begin
+ pp := GetPropInfo(cl.FClass.ClassInfo, string(s2));
+ if pp <> nil then
+ begin
+ p.ProcPtr := ClassCallProcProperty;
+ p.Ext1 := pp;
+ if IsRead then
+ p.Ext2 := Pointer(1)
+ else
+ p.Ext2 := Pointer(0);
+ Result := True;
+ end else
+ result := false;
+ end else
+ Result := False;
+end;
+
+procedure RegisterClassLibraryRuntime(SE: TPSExec; Importer: TPSRuntimeClassImporter);
+begin
+ SE.AddSpecialProcImport('class', SpecImport, Importer);
+end;
+
+
+procedure TPSExec.ClearspecialProcImports;
+var
+ I: Longint;
+ P: PSpecialProc;
+begin
+ for I := FSpecialProcList.Count -1 downto 0 do
+ begin
+ P := FSpecialProcList[I];
+ Dispose(p);
+ end;
+ FSpecialProcList.Clear;
+end;
+
+procedure TPSExec.RaiseCurrentException;
+var
+ ExObj: TObject;
+begin
+ if ExEx = erNoError then exit; // do nothing
+ ExObj := Self.ExObject;
+ if ExObj <> nil then
+ begin
+ Self.ExObject := nil;
+ raise ExObj;
+ end;
+ raise EPSException.Create(PSErrorToString(ExceptionCode, ExceptionString), Self, ExProc, ExPos);
+end;
+
+procedure TPSExec.CMD_Err2(EC: TPSError; const Param: tbtString);
+begin
+ CMD_Err3(EC, Param, Nil);
+end;
+
+function TPSExec.GetProcAsMethod(const ProcNo: Cardinal): TMethod;
+begin
+ Result := MkMethod(Self, ProcNo);
+end;
+
+function TPSExec.GetProcAsMethodN(const ProcName: tbtString): TMethod;
+var
+ procno: Cardinal;
+begin
+ Procno := GetProc(ProcName);
+ if Procno = InvalidVal then
+ begin
+ Result.Code := nil;
+ Result.Data := nil;
+ end
+ else
+ Result := MkMethod(Self, procno)
+end;
+
+
+procedure TPSExec.RegisterAttributeType(useproc: TPSAttributeUseProc;
+ const TypeName: tbtString);
+var
+ att: TPSAttributeType;
+begin
+ att := TPSAttributeType.Create;
+ att.TypeName := TypeName;
+ att.TypeNameHash := MakeHash(TypeName);
+ att.UseProc := UseProc;
+ FAttributeTypes.Add(att);
+end;
+
+function TPSExec.GetProcCount: Cardinal;
+begin
+ Result := FProcs.Count;
+end;
+
+function TPSExec.GetTypeCount: Longint;
+begin
+ Result := FTypes.Count;
+end;
+
+function TPSExec.GetVarCount: Longint;
+begin
+ Result := FGlobalVars.Count;
+end;
+
+function TPSExec.FindSpecialProcImport(
+ P: TPSOnSpecialProcImport): pointer;
+var
+ i: Longint;
+ pr: PSpecialProc;
+begin
+ for i := FSpecialProcList.Count -1 downto 0 do
+ begin
+ pr := FSpecialProcList[i];
+ if @pr.P = @p then
+ begin
+ Result := pr.tag;
+ exit;
+ end;
+ end;
+ result := nil;
+end;
+
+function TPSExec.InvokeExternalMethod(At: TPSTypeRec_ProcPtr; Slf,
+ Ptr: Pointer): Boolean;
+var
+ res: PPSVariantIFC;
+ s: tbtString;
+ CurrStack, i: Longint;
+ n: PPSVariant;
+ MyList: TPSList;
+begin
+ s := TPSTypeRec_ProcPtr(at).ParamInfo;
+ CurrStack := Cardinal(FStack.Count) - Cardinal(length(s));
+ if s[1] = #0 then inc(CurrStack);
+ MyList := TPSList.Create;
+ for i := 2 to length(s) do
+ begin
+ MyList.Add(nil);
+ end;
+ for i := length(s) downto 2 do
+ begin
+ n := FStack[CurrStack];
+ MyList[i - 2] := NewPPSVariantIFC(n, s[i] <> #0);
+ inc(CurrStack);
+ end;
+ if s[1] <> #0 then
+ begin
+ res := NewPPSVariantIFC(FStack[CurrStack + 1], True);
+ end else res := nil;
+ Result := InnerfuseCall(Slf, Ptr, cdRegister, MyList, Res);
+
+ DisposePPSVariantIFC(res);
+ DisposePPSVariantIFCList(mylist);
+end;
+
+function TPSExec.LastEx: TPSError;
+var
+ pp: TPSExceptionHandler;
+begin
+ if FExceptionStack.Count = 0 then begin
+ result := ExEx;
+ exit;
+ end;
+ pp := fExceptionStack[fExceptionStack.Count-1];
+ result := pp.ExceptionData;
+end;
+
+function TPSExec.LastExParam: tbtString;
+begin
+ result := ExParam;
+end;
+
+function TPSExec.LastExPos: Integer;
+begin
+ result := ExPos;
+end;
+
+function TPSExec.LastExProc: Integer;
+begin
+ result := exProc;
+end;
+
+{ TPSRuntimeClass }
+
+constructor TPSRuntimeClass.Create(aClass: TClass; const AName: tbtString);
+begin
+ inherited Create;
+ FClass := AClass;
+ if AName = '' then
+ begin
+ FClassName := FastUpperCase(tbtString(aClass.ClassName));
+ FClassNameHash := MakeHash(FClassName);
+ end else begin
+ FClassName := FastUppercase(AName);
+ FClassNameHash := MakeHash(FClassName);
+ end;
+ FClassItems:= TPSList.Create;
+ FEndOfVmt := MaxInt;
+end;
+
+destructor TPSRuntimeClass.Destroy;
+var
+ I: Longint;
+ P: PClassItem;
+begin
+ for i:= FClassItems.Count -1 downto 0 do
+ begin
+ P := FClassItems[I];
+ Dispose(p);
+ end;
+ FClassItems.Free;
+ inherited Destroy;
+end;
+
+procedure TPSRuntimeClass.RegisterVirtualAbstractMethod(ClassDef: TClass;
+ ProcPtr: Pointer; const Name: tbtString);
+var
+ P: PClassItem;
+begin
+ New(P);
+ p^.FName := FastUppercase(Name);
+ p^.FNameHash := MakeHash(p^.FName);
+ p^.b := 1;
+ p^.PointerInList := FindVirtualMethodPtr(Self, ClassDef, ProcPtr);
+ FClassItems.Add(p);
+end;
+
+procedure TPSRuntimeClass.RegisterConstructor(ProcPtr: Pointer;
+ const Name: tbtString);
+var
+ P: PClassItem;
+begin
+ New(P);
+ p^.FName := FastUppercase(Name);
+ p^.FNameHash := MakeHash(p^.FName);
+ p^.b := 4;
+ p^.Ptr := ProcPtr;
+ FClassItems.Add(p);
+end;
+
+procedure TPSRuntimeClass.RegisterMethod(ProcPtr: Pointer; const Name: tbtString);
+var
+ P: PClassItem;
+begin
+ New(P);
+ p^.FName := FastUppercase(Name);
+ p^.FNameHash := MakeHash(p^.FName);
+ p^.b := 0;
+ p^.Ptr := ProcPtr;
+ FClassItems.Add(p);
+end;
+
+
+procedure TPSRuntimeClass.RegisterPropertyHelper(ReadFunc,
+ WriteFunc: Pointer; const Name: tbtString);
+var
+ P: PClassItem;
+begin
+ New(P);
+ p^.FName := FastUppercase(Name);
+ p^.FNameHash := MakeHash(p^.FName);
+ p^.b := 3;
+ p^.FReadFunc := ReadFunc;
+ p^.FWriteFunc := WriteFunc;
+ FClassItems.Add(p);
+end;
+
+procedure TPSRuntimeClass.RegisterVirtualConstructor(ProcPtr: Pointer;
+ const Name: tbtString);
+var
+ P: PClassItem;
+begin
+ New(P);
+ p^.FName := FastUppercase(Name);
+ p^.FNameHash := MakeHash(p^.FName);
+ p^.b := 5;
+ p^.PointerInList := FindVirtualMethodPtr(Self, FClass, ProcPtr);
+ FClassItems.Add(p);
+end;
+
+procedure TPSRuntimeClass.RegisterVirtualMethod(ProcPtr: Pointer; const Name: tbtString);
+var
+ P: PClassItem;
+begin
+ New(P);
+ p^.FName := FastUppercase(Name);
+ p^.FNameHash := MakeHash(p^.FName);
+ p^.b := 1;
+ p^.PointerInList := FindVirtualMethodPtr(Self, FClass, ProcPtr);
+ FClassItems.Add(p);
+end;
+
+procedure TPSRuntimeClass.RegisterEventPropertyHelper(ReadFunc,
+ WriteFunc: Pointer; const Name: tbtString);
+var
+ P: PClassItem;
+begin
+ New(P);
+ p^.FName := FastUppercase(Name);
+ p^.FNameHash := MakeHash(p^.FName);
+ p^.b := 6;
+ p^.FReadFunc := ReadFunc;
+ p^.FWriteFunc := WriteFunc;
+ FClassItems.Add(p);
+end;
+
+
+procedure TPSRuntimeClass.RegisterPropertyHelperName(ReadFunc,
+ WriteFunc: Pointer; const Name: tbtString);
+var
+ P: PClassItem;
+begin
+ New(P);
+ p^.FName := FastUppercase(Name);
+ p^.FNameHash := MakeHash(p^.FName);
+ p^.b := 7;
+ p^.FReadFunc := ReadFunc;
+ p^.FWriteFunc := WriteFunc;
+ FClassItems.Add(p);
+end;
+
+{ TPSRuntimeClassImporter }
+
+function TPSRuntimeClassImporter.Add(aClass: TClass): TPSRuntimeClass;
+begin
+ Result := FindClass(tbtstring(aClass.ClassName));
+ if Result <> nil then exit;
+ Result := TPSRuntimeClass.Create(aClass, '');
+ FClasses.Add(Result);
+end;
+
+function TPSRuntimeClassImporter.Add2(aClass: TClass;
+ const Name: tbtString): TPSRuntimeClass;
+begin
+ Result := FindClass(Name);
+ if Result <> nil then exit;
+ Result := TPSRuntimeClass.Create(aClass, Name);
+ FClasses.Add(Result);
+end;
+
+procedure TPSRuntimeClassImporter.Clear;
+var
+ I: Longint;
+begin
+ for i := 0 to FClasses.Count -1 do
+ begin
+ TPSRuntimeClass(FClasses[I]).Free;
+ end;
+ FClasses.Clear;
+end;
+
+constructor TPSRuntimeClassImporter.Create;
+begin
+ inherited Create;
+ FClasses := TPSList.Create;
+
+end;
+
+constructor TPSRuntimeClassImporter.CreateAndRegister(Exec: TPSexec;
+ AutoFree: Boolean);
+begin
+ inherited Create;
+ FClasses := TPSList.Create;
+ RegisterClassLibraryRuntime(Exec, Self);
+ if AutoFree then
+ Exec.AddResource(@RCIFreeProc, Self);
+end;
+
+destructor TPSRuntimeClassImporter.Destroy;
+begin
+ Clear;
+ FClasses.Free;
+ inherited Destroy;
+end;
+
+{$IFNDEF PS_NOINTERFACES}
+procedure SetVariantToInterface(V: PIFVariant; Cl: IUnknown);
+begin
+ if (v <> nil) and (v.FType.BaseType = btInterface) then
+ begin
+ PPSVariantinterface(v).Data := cl;
+ {$IFNDEF Delphi3UP}
+ if PPSVariantinterface(v).Data <> nil then
+ PPSVariantinterface(v).Data.AddRef;
+ {$ENDIF}
+ end;
+end;
+{$ENDIF}
+
+procedure SetVariantToClass(V: PIFVariant; Cl: TObject);
+begin
+ if (v <> nil) and (v.FType.BaseType = btClass) then
+ begin
+ PPSVariantclass(v).Data := cl;
+ end;
+end;
+
+function BGRFW(var s: tbtString): tbtString;
+var
+ l: Longint;
+begin
+ l := Length(s);
+ while l >0 do
+ begin
+ if s[l] = ' ' then
+ begin
+ Result := copy(s, l + 1, Length(s) - l);
+ Delete(s, l, Length(s) - l + 1);
+ exit;
+ end;
+ Dec(l);
+ end;
+ Result := s;
+ s := '';
+end;
+
+{$ifdef fpc}
+ {$if defined(cpupowerpc) or defined(cpuarm) or defined(cpu64)}
+ {$define empty_methods_handler}
+ {$ifend}
+{$endif}
+
+{$ifdef empty_methods_handler}
+procedure MyAllMethodsHandler;
+begin
+end;
+{$else}
+
+
+function MyAllMethodsHandler2(Self: PScriptMethodInfo; const Stack: PPointer; _EDX, _ECX: Pointer): Integer; forward;
+
+procedure MyAllMethodsHandler;
+// On entry:
+// EAX = Self pointer
+// EDX, ECX = param1 and param2
+// STACK = param3... paramcount
+asm
+ push 0
+ push ecx
+ push edx
+ mov edx, esp
+ add edx, 16 // was 12
+ pop ecx
+ call MyAllMethodsHandler2
+ pop ecx
+ mov edx, [esp]
+ add esp, eax
+ mov [esp], edx
+ mov eax, ecx
+end;
+
+function ResultAsRegister(b: TPSTypeRec): Boolean;
+begin
+ case b.BaseType of
+ btSingle,
+ btDouble,
+ btExtended,
+ btU8,
+ bts8,
+ bts16,
+ btu16,
+ bts32,
+ btu32,
+{$IFDEF PS_FPCSTRINGWORKAROUND}
+ btString,
+{$ENDIF}
+{$IFNDEF PS_NOINT64}
+ bts64,
+{$ENDIF}
+ btPChar,
+{$IFNDEF PS_NOWIDESTRING}
+ btWideChar,
+{$ENDIF}
+ btChar,
+ btclass,
+ btEnum: Result := true;
+ btSet: Result := b.RealSize <= PointerSize;
+ btStaticArray: Result := b.RealSize <= PointerSize;
+ else
+ Result := false;
+ end;
+end;
+
+function SupportsRegister(b: TPSTypeRec): Boolean;
+begin
+ case b.BaseType of
+ btU8,
+ bts8,
+ bts16,
+ btu16,
+ bts32,
+ btu32,
+ btstring,
+ btclass,
+{$IFNDEF PS_NOINTERFACES}
+ btinterface,
+{$ENDIF}
+ btPChar,
+{$IFNDEF PS_NOWIDESTRING}
+ btwidestring,
+ btUnicodeString,
+ btWideChar,
+{$ENDIF}
+ btChar,
+ btArray,
+ btEnum: Result := true;
+ btSet: Result := b.RealSize <= PointerSize;
+ btStaticArray: Result := b.RealSize <= PointerSize;
+ else
+ Result := false;
+ end;
+end;
+
+function AlwaysAsVariable(aType: TPSTypeRec): Boolean;
+begin
+ case atype.BaseType of
+ btVariant: Result := true;
+ btSet: Result := atype.RealSize > PointerSize;
+ btRecord: Result := atype.RealSize > PointerSize;
+ btStaticArray: Result := atype.RealSize > PointerSize;
+ else
+ Result := false;
+ end;
+end;
+
+
+procedure PutOnFPUStackExtended(ft: extended);
+asm
+// fstp tbyte ptr [ft]
+ fld tbyte ptr [ft]
+
+end;
+
+
+function MyAllMethodsHandler2(Self: PScriptMethodInfo; const Stack: PPointer; _EDX, _ECX: Pointer): Integer;
+var
+ Decl: tbtString;
+ I, C, regno: Integer;
+ Params: TPSList;
+ Res, Tmp: PIFVariant;
+ cpt: PIFTypeRec;
+ fmod: tbtchar;
+ s,e: tbtString;
+ FStack: pointer;
+ ex: TPSExceptionHandler;
+
+
+begin
+ Decl := TPSInternalProcRec(Self^.Se.FProcs[Self^.ProcNo]).ExportDecl;
+
+ FStack := Stack;
+ Params := TPSList.Create;
+ s := decl;
+ grfw(s);
+ while s <> '' do
+ begin
+ Params.Add(nil);
+ grfw(s);
+ end;
+ c := Params.Count;
+ regno := 0;
+ Result := 0;
+ s := decl;
+ grfw(s);
+ for i := c-1 downto 0 do
+ begin
+ e := grfw(s);
+ fmod := e[1];
+ delete(e, 1, 1);
+ cpt := Self.Se.GetTypeNo(StrToInt(e));
+ if ((fmod = '%') or (fmod = '!') or (AlwaysAsVariable(cpt))) and (RegNo < 2) then
+ begin
+ tmp := CreateHeapVariant(self.Se.FindType2(btPointer));
+ PPSVariantPointer(tmp).DestType := cpt;
+ Params[i] := tmp;
+ case regno of
+ 0: begin
+ PPSVariantPointer(tmp).DataDest := Pointer(_EDX);
+ inc(regno);
+ end;
+ 1: begin
+ PPSVariantPointer(tmp).DataDest := Pointer(_ECX);
+ inc(regno);
+ end;
+(* else begin
+ PPSVariantPointer(tmp).DataDest := Pointer(FStack^);
+ FStack := Pointer(IPointer(FStack) + 4);
+ end;*)
+ end;
+ end
+ else if SupportsRegister(cpt) and (RegNo < 2) then
+ begin
+ tmp := CreateHeapVariant(cpt);
+ Params[i] := tmp;
+ case regno of
+ 0: begin
+ CopyArrayContents(@PPSVariantData(tmp)^.Data, @_EDX, 1, cpt);
+ inc(regno);
+ end;
+ 1: begin
+ CopyArrayContents(@PPSVariantData(tmp)^.Data, @_ECX, 1, cpt);
+ inc(regno);
+ end;
+(* else begin
+ CopyArrayContents(@PPSVariantData(tmp)^.Data, Pointer(FStack), 1, cpt);
+ FStack := Pointer(IPointer(FStack) + 4);
+ end;*)
+ end;
+(* end else
+ begin
+ tmp := CreateHeapVariant(cpt);
+ Params[i] := tmp;
+ CopyArrayContents(@PPSVariantData(tmp)^.Data, Pointer(FStack), 1, cpt);
+ FStack := Pointer(IPointer(FStack) + cpt.RealSize + 3 and not 3);*)
+ end;
+ end;
+ s := decl;
+ e := grfw(s);
+
+ if e <> '-1' then
+ begin
+ cpt := Self.Se.GetTypeNo(StrToInt(e));
+ if not ResultAsRegister(cpt) then
+ begin
+ Res := CreateHeapVariant(Self.Se.FindType2(btPointer));
+ PPSVariantPointer(Res).DestType := cpt;
+ Params.Add(Res);
+ case regno of
+ 0: begin
+ PPSVariantPointer(Res).DataDest := Pointer(_EDX);
+ end;
+ 1: begin
+ PPSVariantPointer(Res).DataDest := Pointer(_ECX);
+ end;
+ else begin
+ PPSVariantPointer(Res).DataDest := Pointer(FStack^);
+ Inc(Result, PointerSize);
+ end;
+ end;
+ end else
+ begin
+ Res := CreateHeapVariant(cpt);
+ Params.Add(Res);
+ end;
+ end else Res := nil;
+ s := decl;
+ grfw(s);
+ for i := 0 to c -1 do
+ begin
+ e := grlw(s);
+ fmod := e[1];
+ delete(e, 1, 1);
+ if Params[i] <> nil then Continue;
+ cpt := Self.Se.GetTypeNo(StrToInt(e));
+ if (fmod = '%') or (fmod = '!') or (AlwaysAsVariable(cpt)) then
+ begin
+ tmp := CreateHeapVariant(self.Se.FindType2(btPointer));
+ PPSVariantPointer(tmp).DestType := cpt;
+ Params[i] := tmp;
+ PPSVariantPointer(tmp).DataDest := Pointer(FStack^);
+ FStack := Pointer(IPointer(FStack) + PointerSize);
+ Inc(Result, PointerSize);
+ end
+(* else if SupportsRegister(cpt) then
+ begin
+ tmp := CreateHeapVariant(cpt);
+ Params[i] := tmp;
+ CopyArrayContents(@PPSVariantData(tmp)^.Data, Pointer(FStack), 1, cpt);
+ FStack := Pointer(IPointer(FStack) + 4);
+ end;
+ end *)else
+ begin
+ tmp := CreateHeapVariant(cpt);
+ Params[i] := tmp;
+ CopyArrayContents(@PPSVariantData(tmp)^.Data, Pointer(FStack), 1, cpt);
+ FStack := Pointer((IPointer(FStack) + cpt.RealSize + 3) and not 3);
+ Inc(Result, (cpt.RealSize + 3) and not 3);
+ end;
+ end;
+ ex := TPSExceptionHandler.Create;
+ ex.FinallyOffset := InvalidVal;
+ ex.ExceptOffset := InvalidVal;
+ ex.Finally2Offset := InvalidVal;
+ ex.EndOfBlock := InvalidVal;
+ ex.CurrProc := nil;
+ ex.BasePtr := Self.Se.FCurrStackBase;
+ Ex.StackSize := Self.Se.FStack.Count;
+ i := Self.Se.FExceptionStack.Add(ex);
+ Self.Se.RunProc(Params, Self.ProcNo);
+ if Self.Se.FExceptionStack[i] = ex then
+ begin
+ Self.Se.FExceptionStack.Remove(ex);
+ ex.Free;
+ end;
+
+ if (Res <> nil) then
+ begin
+ Params.DeleteLast;
+ if (ResultAsRegister(Res.FType)) then
+ begin
+ if (res^.FType.BaseType = btSingle) or (res^.FType.BaseType = btDouble) or
+ (res^.FType.BaseType = btCurrency) or (res^.Ftype.BaseType = btExtended) then
+ begin
+ case Res^.FType.BaseType of
+ btSingle: PutOnFPUStackExtended(PPSVariantSingle(res).Data);
+ btDouble: PutOnFPUStackExtended(PPSVariantDouble(res).Data);
+ btExtended: PutOnFPUStackExtended(PPSVariantExtended(res).Data);
+ btCurrency: PutOnFPUStackExtended(PPSVariantCurrency(res).Data);
+ end;
+ DestroyHeapVariant(Res);
+ Res := nil;
+ end else
+ begin
+{$IFNDEF PS_NOINT64}
+ if res^.FType.BaseType <> btS64 then
+{$ENDIF}
+ CopyArrayContents(Pointer(Longint(Stack)-PointerSize2), @PPSVariantData(res)^.Data, 1, Res^.FType);
+ end;
+ end;
+ DestroyHeapVariant(res);
+ end;
+ for i := 0 to Params.Count -1 do
+ DestroyHeapVariant(Params[i]);
+ Params.Free;
+ if Self.Se.ExEx <> erNoError then
+ begin
+ if Self.Se.ExObject <> nil then
+ begin
+ FStack := Self.Se.ExObject;
+ Self.Se.ExObject := nil;
+ raise TObject(FStack);
+ end else
+ raise EPSException.Create(PSErrorToString(Self.SE.ExceptionCode, Self.Se.ExceptionString), Self.Se, Self.Se.ExProc, Self.Se.ExPos);
+ end;
+end;
+{$endif}
+function TPSRuntimeClassImporter.FindClass(const Name: tbtString): TPSRuntimeClass;
+var
+ h, i: Longint;
+ lName: tbtstring;
+ p: TPSRuntimeClass;
+begin
+ lName := FastUpperCase(Name);
+ h := MakeHash(lName);
+ for i := FClasses.Count -1 downto 0 do
+ begin
+ p := FClasses[i];
+ if (p.FClassNameHash = h) and (p.FClassName = lName) then
+ begin
+ Result := P;
+ exit;
+ end;
+ end;
+ Result := nil;
+end;
+
+function DelphiFunctionProc(Caller: TPSExec; p: TPSExternalProcRec; Global, Stack: TPSStack; CC: TPSCallingConvention): Boolean;
+var
+ i: Integer;
+ MyList: TPSList;
+ n: PPSVariantIFC;
+ CurrStack: Cardinal;
+ s: tbtString;
+begin
+ s := P.Decl;
+ if length(s) = 0 then begin Result := False; exit; end;
+ CurrStack := Cardinal(Stack.Count) - Cardinal(length(s));
+ if s[1] = #0 then inc(CurrStack);
+ MyList := TPSList.Create;
+
+ for i := 2 to length(s) do
+ begin
+ MyList.Add(nil);
+ end;
+ for i := length(s) downto 2 do
+ begin
+ MyList[i - 2] := NewPPSVariantIFC(Stack[CurrStack], s[i] <> #0);
+ inc(CurrStack);
+ end;
+ if s[1] <> #0 then
+ begin
+ n := NewPPSVariantIFC(Stack[CurrStack], True);
+ end else n := nil;
+ try
+ result := Caller.InnerfuseCall(p.Ext2, p.Ext1, cc, MyList, n);
+ finally
+ DisposePPSVariantIFC(n);
+ DisposePPSVariantIFCList(mylist);
+ end;
+end;
+
+function DelphiFunctionProc_CDECL(Caller: TPSExec; p: TPSExternalProcRec; Global, Stack: TPSStack): Boolean;
+begin
+ Result := DelphiFunctionProc(Caller, p, Global, Stack, cdCdecl);
+end;
+function DelphiFunctionProc_Register(Caller: TPSExec; p: TPSExternalProcRec; Global, Stack: TPSStack): Boolean;
+begin
+ Result := DelphiFunctionProc(Caller, p, Global, Stack, cdRegister);
+end;
+function DelphiFunctionProc_Pascal(Caller: TPSExec; p: TPSExternalProcRec; Global, Stack: TPSStack): Boolean;
+begin
+ Result := DelphiFunctionProc(Caller, p, Global, Stack, cdPascal);
+end;
+function DelphiFunctionProc_Stdcall(Caller: TPSExec; p: TPSExternalProcRec; Global, Stack: TPSStack): Boolean;
+begin
+ Result := DelphiFunctionProc(Caller, p, Global, Stack, cdStdCall);
+end;
+function DelphiFunctionProc_Safecall(Caller: TPSExec; p: TPSExternalProcRec; Global, Stack: TPSStack): Boolean;
+begin
+ Result := DelphiFunctionProc(Caller, p, Global, Stack, cdSafeCall);
+end;
+
+procedure TPSExec.RegisterDelphiFunction(ProcPtr: Pointer;
+ const Name: tbtString; CC: TPSCallingConvention);
+begin
+ RegisterDelphiMethod(nil, ProcPtr, FastUppercase(Name), CC);
+end;
+
+procedure TPSExec.RegisterDelphiMethod(Slf, ProcPtr: Pointer;
+ const Name: tbtString; CC: TPSCallingConvention);
+begin
+ case cc of
+ cdRegister: RegisterFunctionName(FastUppercase(Name), DelphiFunctionProc_Register, ProcPtr, Slf);
+ cdPascal: RegisterFunctionName(FastUppercase(Name), DelphiFunctionProc_Pascal, ProcPtr, Slf);
+ cdStdCall: RegisterFunctionName(FastUppercase(Name), DelphiFunctionProc_Stdcall, ProcPtr, Slf);
+ cdSafeCall: RegisterFunctionName(FastUppercase(Name), DelphiFunctionProc_Safecall, ProcPtr, Slf);
+ cdCdecl: RegisterFunctionName(FastUppercase(Name), DelphiFunctionProc_CDECL, ProcPtr, Slf);
+ end;
+end;
+
+{ EPSException }
+
+constructor EPSException.Create(const Error: tbtString; Exec: TPSExec;
+ Procno, ProcPos: Cardinal);
+begin
+ inherited Create(string(Error));
+ FExec := Exec;
+ FProcNo := Procno;
+ FProcPos := ProcPos;
+end;
+
+{ TPSRuntimeAttribute }
+
+function TPSRuntimeAttribute.AddValue(aType: TPSTypeRec): PPSVariant;
+begin
+ Result := FValues.PushType(aType);
+end;
+
+procedure TPSRuntimeAttribute.AdjustSize;
+begin
+ FValues.Capacity := FValues.Length;
+end;
+
+constructor TPSRuntimeAttribute.Create(Owner: TPSRuntimeAttributes);
+begin
+ inherited Create;
+ FOwner := Owner;
+ FValues := TPSStack.Create;
+end;
+
+procedure TPSRuntimeAttribute.DeleteValue(i: Longint);
+begin
+ if Cardinal(i) <> Cardinal(FValues.Count -1) then
+ raise Exception.Create(RPS_CanOnlySendLastItem);
+ FValues.Pop;
+end;
+
+destructor TPSRuntimeAttribute.Destroy;
+begin
+ FValues.Free;
+ inherited Destroy;
+end;
+
+function TPSRuntimeAttribute.GetValue(I: Longint): PIFVariant;
+begin
+ Result := FValues[i];
+end;
+
+function TPSRuntimeAttribute.GetValueCount: Longint;
+begin
+ Result := FValues.Count;
+end;
+
+{ TPSRuntimeAttributes }
+
+function TPSRuntimeAttributes.Add: TPSRuntimeAttribute;
+begin
+ Result := TPSRuntimeAttribute.Create(Self);
+ FAttributes.Add(Result);
+end;
+
+constructor TPSRuntimeAttributes.Create(AOwner: TPSExec);
+begin
+ inherited Create;
+ FAttributes := TPSList.Create;
+ FOwner := AOwner;
+end;
+
+procedure TPSRuntimeAttributes.Delete(I: Longint);
+begin
+ TPSRuntimeAttribute(FAttributes[i]).Free;
+ FAttributes.Delete(i);
+end;
+
+destructor TPSRuntimeAttributes.Destroy;
+var
+ i: Longint;
+begin
+ for i := FAttributes.Count -1 downto 0 do
+ TPSRuntimeAttribute(FAttributes[i]).Free;
+ FAttributes.Free;
+ inherited Destroy;
+end;
+
+function TPSRuntimeAttributes.FindAttribute(
+ const Name: tbtString): TPSRuntimeAttribute;
+var
+ n: tbtString;
+ i, h: Longint;
+begin
+ n := FastUpperCase(Name);
+ h := MakeHash(n);
+ for i := 0 to FAttributes.Count -1 do
+ begin
+ Result := FAttributes[i];
+ if (Result.AttribTypeHash = h) and (Result.AttribType = n) then
+ exit;
+ end;
+ Result := nil;
+end;
+
+function TPSRuntimeAttributes.GetCount: Longint;
+begin
+ Result := FAttributes.Count;
+end;
+
+function TPSRuntimeAttributes.GetItem(I: Longint): TPSRuntimeAttribute;
+begin
+ Result := FAttributes[i];
+end;
+
+{ TPSInternalProcRec }
+
+destructor TPSInternalProcRec.Destroy;
+begin
+ if FData <> nil then
+ Freemem(Fdata, FLength);
+ inherited Destroy;
+end;
+
+{ TPsProcRec }
+
+constructor TPSProcRec.Create(Owner: TPSExec);
+begin
+ inherited Create;
+ FAttributes := TPSRuntimeAttributes.Create(Owner);
+end;
+
+destructor TPSProcRec.Destroy;
+begin
+ FAttributes.Free;
+ inherited Destroy;
+end;
+
+{ TPSTypeRec_Array }
+
+procedure TPSTypeRec_Array.CalcSize;
+begin
+ FrealSize := PointerSize;
+end;
+
+{ TPSTypeRec_StaticArray }
+
+procedure TPSTypeRec_StaticArray.CalcSize;
+begin
+ FrealSize := Cardinal(FArrayType.RealSize) * Cardinal(Size);
+end;
+
+{ TPSTypeRec_Set }
+
+procedure TPSTypeRec_Set.CalcSize;
+begin
+ FrealSize := FByteSize;
+end;
+
+const
+ MemDelta = 4096;
+
+{ TPSStack }
+
+procedure TPSStack.AdjustLength;
+var
+ MyLen: Longint;
+begin
+ MyLen := ((FLength shr 12) + 1) shl 12;
+
+ SetCapacity(MyLen);
+end;
+
+procedure TPSStack.Clear;
+var
+ v: Pointer;
+ i: Longint;
+begin
+ for i := Count -1 downto 0 do
+ begin
+ v := Data[i];
+ if TPSTypeRec(v^).BaseType in NeedFinalization then
+ FinalizeVariant(Pointer(IPointer(v)+PointerSize), TPSTypeRec(v^));
+ end;
+ inherited Clear;
+ FLength := 0;
+ SetCapacity(0);
+end;
+
+constructor TPSStack.Create;
+begin
+ inherited Create;
+ GetMem(FDataPtr, MemDelta);
+ FCapacity := MemDelta;
+ FLength := 0;
+end;
+
+destructor TPSStack.Destroy;
+var
+ v: Pointer;
+ i: Longint;
+begin
+ for i := Count -1 downto 0 do
+ begin
+ v := Data[i];
+ if TPSTypeRec(v^).BaseType in NeedFinalization then
+ FinalizeVariant(Pointer(IPointer(v)+PointerSize), Pointer(v^));
+ end;
+ FreeMem(FDataPtr, FCapacity);
+ inherited Destroy;
+end;
+
+function TPSStack.GetBool(ItemNo: Longint): Boolean;
+var
+ val: PPSVariant;
+begin
+ if ItemNo < 0 then
+ val := Items[Longint(ItemNo) + Longint(Count)]
+ else
+ val := Items[ItemNo];
+ Result := PSGetUInt(@PPSVariantData(val).Data, val.FType) <> 0;
+end;
+
+function TPSStack.GetClass(ItemNo: Longint): TObject;
+var
+ val: PPSVariant;
+begin
+ if ItemNo < 0 then
+ val := Items[Longint(ItemNo) + Longint(Count)]
+ else
+ val := Items[ItemNo];
+ Result := PSGetObject(@PPSVariantData(val).Data, val.FType);
+end;
+
+function TPSStack.GetCurrency(ItemNo: Longint): Currency;
+var
+ val: PPSVariant;
+begin
+ if ItemNo < 0 then
+ val := Items[Longint(ItemNo) + Longint(Count)]
+ else
+ val := Items[ItemNo];
+ Result := PSGetCurrency(@PPSVariantData(val).Data, val.FType);
+end;
+
+function TPSStack.GetInt(ItemNo: Longint): Longint;
+var
+ val: PPSVariant;
+begin
+ if ItemNo < 0 then
+ val := items[Longint(ItemNo) + Longint(Count)]
+ else
+ val := items[ItemNo];
+ Result := PSGetInt(@PPSVariantData(val).Data, val.FType);
+end;
+
+{$IFNDEF PS_NOINT64}
+function TPSStack.GetInt64(ItemNo: Longint): Int64;
+var
+ val: PPSVariant;
+begin
+ if ItemNo < 0 then
+ val := items[Longint(ItemNo) + Longint(Count)]
+ else
+ val := items[ItemNo];
+ Result := PSGetInt64(@PPSVariantData(val).Data, val.FType);
+end;
+{$ENDIF}
+
+function TPSStack.GetItem(I: Longint): PPSVariant;
+begin
+ if Cardinal(I) >= Cardinal(Count) then
+ Result := nil
+ else
+ Result := Data[i];
+end;
+
+function TPSStack.GetReal(ItemNo: Longint): Extended;
+var
+ val: PPSVariant;
+begin
+ if ItemNo < 0 then
+ val := items[Longint(ItemNo) + Longint(Count)]
+ else
+ val := items[ItemNo];
+ Result := PSGetreal(@PPSVariantData(val).Data, val.FType);
+end;
+
+function TPSStack.GetAnsiString(ItemNo: Longint): tbtString;
+var
+ val: PPSVariant;
+begin
+ if ItemNo < 0 then
+ val := items[Longint(ItemNo) + Longint(Count)]
+ else
+ val := items[ItemNo];
+ Result := PSGetAnsiString(@PPSVariantData(val).Data, val.FType);
+end;
+
+function TPSStack.GetString(ItemNo: Longint): string; // calls the native method
+begin
+ result := {$IFDEF DELPHI2009UP}GetUnicodeString(ItemNo){$ELSE}GetAnsiString(ItemNo){$ENDIF};
+end;
+
+function TPSStack.GetUInt(ItemNo: Longint): Cardinal;
+var
+ val: PPSVariant;
+begin
+ if ItemNo < 0 then
+ val := items[Longint(ItemNo) + Longint(Count)]
+ else
+ val := items[ItemNo];
+ Result := PSGetUInt(@PPSVariantData(val).Data, val.FType);
+end;
+
+function TPSStack.GetUnicodeString(ItemNo: Integer): tbtunicodestring;
+var
+ val: PPSVariant;
+begin
+ if ItemNo < 0 then
+ val := items[Longint(ItemNo) + Longint(Count)]
+ else
+ val := items[ItemNo];
+ Result := PSGetUnicodeString(@PPSVariantData(val).Data, val.FType);
+end;
+
+{$IFNDEF PS_NOWIDESTRING}
+function TPSStack.GetWideString(ItemNo: Longint): tbtWideString;
+var
+ val: PPSVariant;
+begin
+ if ItemNo < 0 then
+ val := items[Longint(ItemNo) + Longint(Count)]
+ else
+ val := items[ItemNo];
+ Result := PSGetWideString(@PPSVariantData(val).Data, val.FType);
+end;
+{$ENDIF}
+
+procedure TPSStack.Pop;
+var
+ p1: Pointer;
+ c: Longint;
+begin
+ c := count -1;
+ p1 := Data[c];
+ DeleteLast;
+ FLength := IPointer(p1) - IPointer(FDataPtr);
+ if TPSTypeRec(p1^).BaseType in NeedFinalization then
+ FinalizeVariant(Pointer(IPointer(p1)+PointerSize), Pointer(p1^));
+ if ((FCapacity - FLength) shr 12) > 2 then AdjustLength;
+end;
+
+function TPSStack.Push(TotalSize: Longint): PPSVariant;
+var
+ o: Cardinal;
+ p: Pointer;
+begin
+ o := FLength;
+ FLength := (FLength + TotalSize);
+ if FLength mod PointerSize <> 0 then
+ FLength := FLength + (PointerSize - (FLength mod PointerSize));
+ if FLength > FCapacity then AdjustLength;
+ p := Pointer(IPointer(FDataPtr) + IPointer(o));
+ Add(p);
+ Result := P;
+end;
+
+function TPSStack.PushType(aType: TPSTypeRec): PPSVariant;
+begin
+ Result := Push(aType.RealSize + Sizeof(Pointer));
+ Result.FType := aType;
+ InitializeVariant(Pointer(IPointer(Result)+PointerSize), aType);
+end;
+
+procedure TPSStack.SetBool(ItemNo: Longint; const Data: Boolean);
+var
+ val: PPSVariant;
+ ok: Boolean;
+begin
+ if ItemNo < 0 then
+ val := items[Longint(ItemNo) + Longint(Count)]
+ else
+ val := items[ItemNo];
+ ok := true;
+ if Data then
+ PSSetUInt(@PPSVariantData(val).Data, val.FType, ok, 1)
+ else
+ PSSetUInt(@PPSVariantData(val).Data, val.FType, ok, 0);
+ if not ok then raise Exception.Create(RPS_TypeMismatch);
+end;
+
+procedure TPSStack.SetCapacity(const Value: Longint);
+var
+ p: Pointer;
+ OOFS: IPointer;
+ I: Longint;
+begin
+ if Value < FLength then raise Exception.Create(RPS_CapacityLength);
+ if Value = 0 then
+ begin
+ if FDataPtr <> nil then
+ begin
+ FreeMem(FDataPtr, FCapacity);
+ FDataPtr := nil;
+ end;
+ FCapacity := 0;
+ end;
+ GetMem(p, Value);
+ if FDataPtr <> nil then
+ begin
+ if FLength > FCapacity then
+ OOFS := FCapacity
+ else
+ OOFS := FLength;
+ Move(FDataPtr^, p^, OOFS);
+ OOFS := IPointer(P) - IPointer(FDataPtr);
+
+ for i := Count -1 downto 0 do begin
+ Data[i] := Pointer(IPointer(Data[i]) + OOFS);
+ if Items[i].FType.FBaseType = btPointer then begin // check if pointer points to moved stack data
+ if (IPointer(PPSVariantPointer(Data[i]).DataDest) >= IPointer(FDataPtr)) and
+ (IPointer(PPSVariantPointer(Data[i]).DataDest) < IPointer(FDataPtr)+IPointer(FLength)) then
+ PPSVariantPointer(Data[i]).DataDest := Pointer(IPointer(PPSVariantPointer(Data[i]).DataDest) + OOFS);
+ end;
+ end;
+
+ FreeMem(FDataPtr, FCapacity);
+ end;
+ FDataPtr := p;
+ FCapacity := Value;
+end;
+
+procedure TPSStack.SetClass(ItemNo: Longint; const Data: TObject);
+var
+ val: PPSVariant;
+ ok: Boolean;
+begin
+ if ItemNo < 0 then
+ val := items[Longint(ItemNo) + Longint(Count)]
+ else
+ val := items[ItemNo];
+ ok := true;
+ PSSetObject(@PPSVariantData(val).Data, val.FType, ok, Data);
+ if not ok then raise Exception.Create(RPS_TypeMismatch);
+end;
+
+procedure TPSStack.SetCurrency(ItemNo: Longint; const Data: Currency);
+var
+ val: PPSVariant;
+ ok: Boolean;
+begin
+ if ItemNo < 0 then
+ val := items[Longint(ItemNo) + Longint(Count)]
+ else
+ val := items[ItemNo];
+ ok := true;
+ PSSetCurrency(@PPSVariantData(val).Data, val.FType, ok, Data);
+ if not ok then raise Exception.Create(RPS_TypeMismatch);
+end;
+
+procedure TPSStack.SetInt(ItemNo: Longint; const Data: Longint);
+var
+ val: PPSVariant;
+ ok: Boolean;
+begin
+ if ItemNo < 0 then
+ val := items[Longint(ItemNo) + Longint(Count)]
+ else
+ val := items[ItemNo];
+ ok := true;
+ PSSetInt(@PPSVariantData(val).Data, val.FType, ok, Data);
+ if not ok then raise Exception.Create(RPS_TypeMismatch);
+end;
+
+{$IFNDEF PS_NOINT64}
+procedure TPSStack.SetInt64(ItemNo: Longint; const Data: Int64);
+var
+ val: PPSVariant;
+ ok: Boolean;
+begin
+ if ItemNo < 0 then
+ val := items[Longint(ItemNo) + Longint(Count)]
+ else
+ val := items[ItemNo];
+ ok := true;
+ PSSetInt64(@PPSVariantData(val).Data, val.FType, ok, Data);
+ if not ok then raise Exception.Create(RPS_TypeMismatch);
+end;
+{$ENDIF}
+
+procedure TPSStack.SetReal(ItemNo: Longint; const Data: Extended);
+var
+ val: PPSVariant;
+ ok: Boolean;
+begin
+ if ItemNo < 0 then
+ val := items[Longint(ItemNo) + Longint(Count)]
+ else
+ val := items[ItemNo];
+ ok := true;
+ PSSetReal(@PPSVariantData(val).Data, val.FType, ok, Data);
+ if not ok then raise Exception.Create(RPS_TypeMismatch);
+end;
+
+procedure TPSStack.SetAnsiString(ItemNo: Longint; const Data: tbtString);
+var
+ val: PPSVariant;
+ ok: Boolean;
+begin
+ if ItemNo < 0 then
+ val := items[Longint(ItemNo) + Longint(Count)]
+ else
+ val := items[ItemNo];
+ ok := true;
+ PSSetAnsiString(@PPSVariantData(val).Data, val.FType, ok, Data);
+ if not ok then raise Exception.Create(RPS_TypeMismatch);
+end;
+
+procedure TPSStack.SetString(ItemNo: Longint; const Data: string);
+begin
+ {$IFDEF DELPHI2009UP}
+ SetUnicodeString(ItemNo, Data);
+ {$ELSE}
+ SetAnsiString(ItemNo, Data);
+ {$ENDIF}
+end;
+
+
+procedure TPSStack.SetUInt(ItemNo: Longint; const Data: Cardinal);
+var
+ val: PPSVariant;
+ ok: Boolean;
+begin
+ if ItemNo < 0 then
+ val := items[Longint(ItemNo) + Longint(Count)]
+ else
+ val := items[ItemNo];
+ ok := true;
+ PSSetUInt(@PPSVariantData(val).Data, val.FType, ok, Data);
+ if not ok then raise Exception.Create(RPS_TypeMismatch);
+end;
+
+
+{$IFNDEF PS_NOWIDESTRING}
+procedure TPSStack.SetUnicodeString(ItemNo: Integer;
+ const Data: tbtunicodestring);
+var
+ val: PPSVariant;
+ ok: Boolean;
+begin
+ if ItemNo < 0 then
+ val := items[Longint(ItemNo) + Longint(Count)]
+ else
+ val := items[ItemNo];
+ ok := true;
+ PSSetUnicodeString(@PPSVariantData(val).Data, val.FType, ok, Data);
+end;
+
+procedure TPSStack.SetWideString(ItemNo: Longint;
+ const Data: tbtWideString);
+var
+ val: PPSVariant;
+ ok: Boolean;
+begin
+ if ItemNo < 0 then
+ val := items[Longint(ItemNo) + Longint(Count)]
+ else
+ val := items[ItemNo];
+ ok := true;
+ PSSetWideString(@PPSVariantData(val).Data, val.FType, ok, Data);
+ if not ok then raise Exception.Create(RPS_TypeMismatch);
+end;
+{$ENDIF}
+
+
+{$IFNDEF PS_NOIDISPATCH}
+var
+ DispPropertyPut: Integer = DISPID_PROPERTYPUT;
+const
+ LOCALE_SYSTEM_DEFAULT = 2 shl 10; // Delphi 2 doesn't define this
+
+function IDispatchInvoke(Self: IDispatch; PropertySet: Boolean; const Name: tbtString; const Par: array of Variant): Variant;
+var
+ Param: Word;
+ i, ArgErr: Longint;
+ DispatchId: Longint;
+ DispParam: TDispParams;
+ ExceptInfo: TExcepInfo;
+ aName: PWideChar;
+ WSFreeList: TPSList;
+begin
+ FillChar(ExceptInfo, SizeOf(ExceptInfo), 0);
+ if Name='' then begin
+ DispatchId:=0;
+ end else begin
+ aName := StringToOleStr(Name);
+ try
+ if Self = nil then
+ raise Exception.Create(RPS_NILInterfaceException);
+ if Self.GetIDsOfNames(GUID_NULL, @aName, 1, LOCALE_SYSTEM_DEFAULT, @DispatchId) <> S_OK then
+ raise Exception.Create(RPS_UnknownMethod);
+ finally
+ SysFreeString(aName);
+ end;
+ end;
+ DispParam.cNamedArgs := 0;
+ DispParam.rgdispidNamedArgs := nil;
+ DispParam.cArgs := (High(Par) + 1);
+
+ if PropertySet then
+ begin
+ Param := DISPATCH_PROPERTYPUT;
+ DispParam.cNamedArgs := 1;
+ DispParam.rgdispidNamedArgs := @DispPropertyPut;
+ end else
+ Param := DISPATCH_METHOD or DISPATCH_PROPERTYGET;
+
+ WSFreeList := TPSList.Create;
+ try
+ GetMem(DispParam.rgvarg, sizeof(TVariantArg) * (High(Par) + 1));
+ FillCHar(DispParam.rgvarg^, sizeof(TVariantArg) * (High(Par) + 1), 0);
+ try
+ for i := 0 to High(Par) do
+ begin
+ if PVarData(@Par[High(Par)-i]).VType = varString then
+ begin
+ DispParam.rgvarg[i].vt := VT_BSTR;
+ DispParam.rgvarg[i].bstrVal := StringToOleStr(AnsiString(Par[High(Par)-i]));
+ WSFreeList.Add(DispParam.rgvarg[i].bstrVal);
+ {$IFDEF UNICODE}
+ end else if (PVarData(@Par[High(Par)-i]).VType = varOleStr) or (PVarData(@Par[High(Par)-i]).VType = varUString) then
+ begin
+ DispParam.rgvarg[i].vt := VT_BSTR;
+ DispParam.rgvarg[i].bstrVal := StringToOleStr(UnicodeString(Par[High(Par)-i]));
+ WSFreeList.Add(DispParam.rgvarg[i].bstrVal);
+ {$ENDIF}
+ end else
+ begin
+ DispParam.rgvarg[i].vt := VT_VARIANT or VT_BYREF;
+ New(
+ {$IFDEF DELPHI4UP}
+ POleVariant
+ {$ELSE}
+ PVariant{$ENDIF}
+ (DispParam.rgvarg[i].pvarVal));
+
+ (*
+ {$IFDEF DELPHI4UP}
+ POleVariant
+ {$ELSE}
+ PVariant
+ {$ENDIF}
+ (DispParam.rgvarg[i].pvarVal)^ := Par[High(Par)-i];
+ *)
+ Move(Par[High(Par)-i],Pointer(DispParam.rgvarg[i].pvarVal)^,
+ Sizeof({$IFDEF DELPHI4UP}OleVariant{$ELSE}Variant{$ENDIF}));
+
+ end;
+ end;
+ i :=Self.Invoke(DispatchId, GUID_NULL, LOCALE_SYSTEM_DEFAULT, Param, DispParam, @Result, @ExceptInfo, @ArgErr);
+ {$IFNDEF Delphi3UP}
+ try
+ if not Succeeded(i) then
+ begin
+ if i = DISP_E_EXCEPTION then
+ raise Exception.Create(OleStrToString(ExceptInfo.bstrSource)+': '+OleStrToString(ExceptInfo.bstrDescription))
+ else
+ raise Exception.Create(SysErrorMessage(i));
+ end;
+ finally
+ SysFreeString(ExceptInfo.bstrSource);
+ SysFreeString(ExceptInfo.bstrDescription);
+ SysFreeString(ExceptInfo.bstrHelpFile);
+ end;
+ {$ELSE}
+ if not Succeeded(i) then
+ begin
+ if i = DISP_E_EXCEPTION then
+ raise Exception.Create(ExceptInfo.bstrSource+': '+ExceptInfo.bstrDescription)
+ else
+ raise Exception.Create(SysErrorMessage(i));
+ end;
+ {$ENDIF}
+ finally
+ for i := 0 to High(Par) do
+ begin
+ if DispParam.rgvarg[i].vt = (VT_VARIANT or VT_BYREF) then
+ begin
+ if{$IFDEF DELPHI4UP}POleVariant{$ELSE}PVariant{$ENDIF}
+ (DispParam.rgvarg[i].pvarVal) <> nil then
+ Dispose(
+ {$IFDEF DELPHI4UP}
+ POleVariant
+ {$ELSE}
+ PVariant
+ {$ENDIF}
+ (DispParam.rgvarg[i].pvarVal));
+ end;
+ end;
+ FreeMem(DispParam.rgvarg, sizeof(TVariantArg) * (High(Par) + 1));
+ end;
+ finally
+ for i := WSFreeList.Count -1 downto 0 do
+ SysFreeString(WSFreeList[i]);
+ WSFreeList.Free;
+ end;
+end;
+{$ENDIF}
+
+
+{ TPSTypeRec_ProcPtr }
+
+procedure TPSTypeRec_ProcPtr.CalcSize;
+begin
+ FRealSize := 2 * sizeof(Pointer) + Sizeof(Cardinal);
+end;
+
+end.
+
diff --git a/branches/script-component/Units/PascalScript/uPSUtils.pas b/branches/script-component/Units/PascalScript/uPSUtils.pas
new file mode 100644
index 0000000..30873c2
--- /dev/null
+++ b/branches/script-component/Units/PascalScript/uPSUtils.pas
@@ -0,0 +1,1723 @@
+unit uPSUtils;
+{$I PascalScript.inc}
+
+interface
+uses
+ Classes, SysUtils {$IFDEF VER130}, Windows {$ENDIF};
+
+const
+
+ PSMainProcName = '!MAIN';
+
+ PSMainProcNameOrg = 'Main Proc';
+
+ PSLowBuildSupport = 12;
+
+ PSCurrentBuildNo = 23;
+
+ PSCurrentversion = '1.31';
+
+ PSValidHeader = 1397769801;
+
+ PSAddrStackStart = 1610612736;
+
+ PSAddrNegativeStackStart = 1073741824;
+type
+ TbtString = {$IFDEF DELPHI2009UP}AnsiString{$ELSE}String{$ENDIF};
+
+ TPSBaseType = Byte;
+
+ TPSVariableType = (ivtGlobal, ivtParam, ivtVariable);
+
+const
+
+ btReturnAddress = 0;
+
+ btU8 = 1;
+
+ btS8 = 2;
+
+ btU16 = 3;
+
+ btS16 = 4;
+
+ btU32 = 5;
+
+ btS32 = 6;
+
+ btSingle = 7;
+
+ btDouble = 8;
+
+ btExtended = 9;
+
+ btString = 10;
+
+ btRecord = 11;
+
+ btArray = 12;
+
+ btPointer = 13;
+
+ btPChar = 14;
+
+ btResourcePointer = 15;
+
+ btVariant = 16;
+
+{$IFNDEF PS_NOINT64}
+ btS64 = 17;
+{$ENDIF}
+
+ btChar = 18;
+
+{$IFNDEF PS_NOWIDESTRING}
+ btWideString = 19;
+
+ btWideChar = 20;
+{$ENDIF}
+
+ btProcPtr = 21;
+
+ btStaticArray = 22;
+
+ btSet = 23;
+
+ btCurrency = 24;
+
+ btClass = 25;
+
+ btInterface = 26;
+
+ btNotificationVariant = 27;
+
+ btUnicodeString = 28;
+
+ btType = 130;
+
+ btEnum = 129;
+
+ btExtClass = 131;
+
+function MakeHash(const s: TbtString): Longint;
+
+const
+{ Script internal command: Assign command
+ Command: TPSCommand;
+ VarDest, // no data
+ VarSrc: TPSVariable;
+}
+ CM_A = 0;
+{ Script internal command: Calculate Command
+ Command: TPSCommand;
+ CalcType: Byte;
+
+ 0 = +
+ 1 = -
+ 2 = *
+ 3 = /
+ 4 = MOD
+ 5 = SHL
+ 6 = SHR
+ 7 = AND
+ 8 = OR
+ 9 = XOR
+
+ VarDest, // no data
+ VarSrc: TPSVariable;
+
+}
+ CM_CA = 1;
+{ Script internal command: Push
+ Command: TPSCommand;
+ Var: TPSVariable;
+}
+ CM_P = 2;
+{ Script internal command: Push Var
+ Command: TPSCommand;
+ Var: TPSVariable;
+}
+ CM_PV = 3;
+{ Script internal command: Pop
+ Command: TPSCommand;
+}
+ CM_PO = 4;
+{ Script internal command: Call
+ Command: TPSCommand;
+ ProcNo: Longword;
+}
+ Cm_C = 5;
+{ Script internal command: Goto
+ Command: TPSCommand;
+ NewPosition: Longint; //relative to end of this instruction
+}
+ Cm_G = 6;
+{ Script internal command: Conditional Goto
+ Command: TPSCommand;
+ NewPosition: LongWord; //relative to end of this instruction
+ Var: TPSVariable; // no data
+}
+ Cm_CG = 7;
+{ Script internal command: Conditional NOT Goto
+ Command: TPSCommand;
+ NewPosition: LongWord; // relative to end of this instruction
+ Var: TPSVariable; // no data
+}
+ Cm_CNG = 8;
+{ Script internal command: Ret
+ Command: TPSCommand;
+}
+ Cm_R = 9;
+{ Script internal command: Set Stack Type
+ Command: TPSCommand;
+ NewType: LongWord;
+ OffsetFromBase: LongWord;
+}
+ Cm_ST = 10;
+{ Script internal command: Push Type
+ Command: TPSCommand;
+ FType: LongWord;
+}
+ Cm_Pt = 11;
+{ Script internal command: Compare
+ Command: TPSCommand;
+ CompareType: Byte;
+
+ 0 = >=
+ 1 = <=
+ 2 = >
+ 3 = <
+ 4 = <>
+ 5 = =
+
+ IntoVar: TPSAssignment;
+ Compare1, Compare2: TPSAssigment;
+}
+ CM_CO = 12;
+{ Script internal command: Call Var
+ Command: TPSCommand;
+ Var: TPSVariable;
+}
+ Cm_cv = 13;
+{ Script internal command: Set Pointer
+ Command: TPSCommand;
+ VarDest: TPSVariable;
+ VarSrc: TPSVariable;
+}
+ cm_sp = 14;
+{ Script internal command: Boolean NOT
+ Command: TPSCommand;
+ Var: TPSVariable;
+}
+ cm_bn = 15;
+{ Script internal command: Var Minus
+ Command: TPSCommand;
+ Var: TPSVariable;
+}
+ cm_vm = 16;
+{ Script internal command: Set Flag
+ Command: TPSCommand;
+ Var: TPSVariable;
+ DoNot: Boolean;
+}
+ cm_sf = 17;
+{ Script internal command: Flag Goto
+ Command: TPSCommand;
+ Where: Cardinal;
+}
+ cm_fg = 18;
+{ Script internal command: Push Exception Handler
+ Command: TPSCommand;
+ FinallyOffset,
+ ExceptionOffset, // FinallyOffset or ExceptionOffset need to be set.
+ Finally2Offset,
+ EndOfBlock: Cardinal;
+}
+ cm_puexh = 19;
+{ Script internal command: Pop Exception Handler
+ Command:TPSCommand;
+ Position: Byte;
+ 0 = end of try/finally/exception block;
+ 1 = end of first finally
+ 2 = end of except
+ 3 = end of second finally
+
+}
+ cm_poexh = 20;
+{ Script internal command: Integer NOT
+ Command: TPSCommand;
+ Where: Cardinal;
+}
+ cm_in = 21;
+ {Script internal command: Set Stack Pointer To Copy
+ Command: TPSCommand;
+ Where: Cardinal;
+}
+ cm_spc = 22;
+ {Script internal command: Inc
+ Command: TPSCommand;
+ Var: TPSVariable;
+ }
+ cm_inc = 23;
+ {Script internal command: Dec
+ Command: TPSCommand;
+ Var: TPSVariable;
+ }
+ cm_dec = 24;
+ {Script internal command: nop
+ Command: TPSCommand; }
+ cm_nop = 255;
+{ Script internal command: Pop and Goto
+ Command: TPSCommand;
+ NewPosition: Longint; //relative to end of this instruction
+}
+ Cm_PG = 25;
+{ Script internal command: Pop*2 and Goto
+ Command: TPSCommand;
+ NewPosition: Longint; //relative to end of this instruction
+}
+ Cm_P2G = 26;
+
+
+type
+
+ TbtU8 = Byte;
+
+ TbtS8 = ShortInt;
+
+ TbtU16 = Word;
+
+ TbtS16 = SmallInt;
+
+ TbtU32 = Cardinal;
+
+ TbtS32 = Longint;
+
+ TbtSingle = Single;
+
+ TbtDouble = double;
+
+ TbtExtended = Extended;
+
+ tbtCurrency = Currency;
+
+{$IFNDEF PS_NOINT64}
+
+ tbts64 = int64;
+{$ENDIF}
+
+ tbtchar = {$IFDEF DELPHI4UP}AnsiChar{$ELSE}CHAR{$ENDIF};
+{$IFNDEF PS_NOWIDESTRING}
+
+ tbtwidestring = widestring;
+ tbtunicodestring = {$IFDEF DELPHI2009UP}UnicodeString{$ELSE}widestring{$ENDIF};
+
+ tbtwidechar = widechar;
+ tbtNativeString = {$IFDEF DELPHI2009UP}tbtUnicodeString{$ELSE}tbtString{$ENDIF};
+{$ENDIF}
+{$IFDEF FPC}
+ IPointer = PtrUInt;
+{$ELSE}
+ {$IFDEF CPU64} IPointer = LongWord;{$ELSE} IPointer = Cardinal;{$ENDIF}
+{$ENDIF}
+ TPSCallingConvention = (cdRegister, cdPascal, cdCdecl, cdStdCall, cdSafeCall);
+
+
+const
+
+ PointerSize = IPointer({$IFDEF CPU64}8{$ELSE}4{$ENDIF});
+ PointerSize2 = IPointer(2*PointerSize);
+ MaxListSize = Maxint div 16;
+
+type
+
+ PPointerList = ^TPointerList;
+
+ TPointerList = array[0..MaxListSize - 1] of Pointer;
+
+
+ TPSList = class(TObject)
+ protected
+
+ FData: PPointerList;
+
+ FCapacity: Cardinal;
+
+ FCount: Cardinal;
+
+ FCheckCount: Cardinal;
+ private
+ function GetItem(Nr: Cardinal): Pointer;
+ procedure SetItem(Nr: Cardinal; P: Pointer);
+ public
+ {$IFNDEF PS_NOSMARTLIST}
+
+ procedure Recreate;
+ {$ENDIF}
+
+ property Data: PPointerList read FData;
+
+ constructor Create;
+
+ function IndexOf(P: Pointer): Longint;
+
+ destructor Destroy; override;
+
+ property Count: Cardinal read FCount;
+
+ property Items[nr: Cardinal]: Pointer read GetItem write SetItem; default;
+
+ function Add(P: Pointer): Longint;
+
+ procedure AddBlock(List: PPointerList; Count: Longint);
+
+ procedure Remove(P: Pointer);
+
+ procedure Delete(Nr: Cardinal);
+
+ procedure DeleteLast;
+
+ procedure Clear; virtual;
+ end;
+ TIFList = TPSList;
+
+ TPSStringList = class(TObject)
+ private
+ List: TPSList;
+ function GetItem(Nr: LongInt): TbtString;
+ procedure SetItem(Nr: LongInt; const s: TbtString);
+ public
+
+ function Count: LongInt;
+
+ property Items[Nr: Longint]: TbtString read GetItem write SetItem; default;
+
+
+ procedure Add(const P: TbtString);
+
+ procedure Delete(NR: LongInt);
+
+ procedure Clear;
+
+ constructor Create;
+
+ destructor Destroy; override;
+ end;
+ TIFStringList = TPsStringList;
+
+ TPSUnitList = class;
+
+ TPSUnit = class(TObject)
+ private
+ fList : TPSUnitList;
+ fUnits : TPSList;
+ fUnitName : TbtString;
+ procedure SetUnitName(const Value: TbtString);
+ public
+ constructor Create(List: TPSUnitList);
+
+ destructor Destroy; override;
+
+ procedure AddUses(pUnitName: TbtString);
+
+ function HasUses(pUnitName: TbtString): Boolean;
+
+ property UnitName: TbtString read fUnitName write SetUnitName;
+ end;
+
+ TPSUnitList = class
+ private
+ fList: TPSList;
+ function Add: TPSUnit;
+
+ public
+ constructor Create;
+
+ function GetUnit(UnitName: TbtString): TPSUnit;
+
+ destructor Destroy; override;
+ end;
+
+
+
+type
+
+ TPSPasToken = (
+ CSTI_EOF,
+
+ CSTIINT_Comment,
+ CSTIINT_WhiteSpace,
+
+ CSTI_Identifier,
+ CSTI_SemiColon,
+ CSTI_Comma,
+ CSTI_Period,
+ CSTI_Colon,
+ CSTI_OpenRound,
+ CSTI_CloseRound,
+ CSTI_OpenBlock,
+ CSTI_CloseBlock,
+ CSTI_Assignment,
+ CSTI_Equal,
+ CSTI_NotEqual,
+ CSTI_Greater,
+ CSTI_GreaterEqual,
+ CSTI_Less,
+ CSTI_LessEqual,
+ CSTI_Plus,
+ CSTI_Minus,
+ CSTI_Divide,
+ CSTI_Multiply,
+ CSTI_Integer,
+ CSTI_Real,
+ CSTI_String,
+ CSTI_Char,
+ CSTI_HexInt,
+ CSTI_AddressOf,
+ CSTI_Dereference,
+ CSTI_TwoDots,
+
+ CSTII_and,
+ CSTII_array,
+ CSTII_begin,
+ CSTII_case,
+ CSTII_const,
+ CSTII_div,
+ CSTII_do,
+ CSTII_downto,
+ CSTII_else,
+ CSTII_end,
+ CSTII_for,
+ CSTII_function,
+ CSTII_if,
+ CSTII_in,
+ CSTII_mod,
+ CSTII_not,
+ CSTII_of,
+ CSTII_or,
+ CSTII_procedure,
+ CSTII_program,
+ CSTII_repeat,
+ CSTII_record,
+ CSTII_set,
+ CSTII_shl,
+ CSTII_shr,
+ CSTII_then,
+ CSTII_to,
+ CSTII_type,
+ CSTII_until,
+ CSTII_uses,
+ CSTII_var,
+ CSTII_while,
+ CSTII_with,
+ CSTII_xor,
+ CSTII_exit,
+ CSTII_class,
+ CSTII_constructor,
+ CSTII_destructor,
+ CSTII_inherited,
+ CSTII_private,
+ CSTII_public,
+ CSTII_published,
+ CSTII_protected,
+ CSTII_property,
+ CSTII_virtual,
+ CSTII_override,
+ //CSTII_default, //Birb
+ CSTII_As,
+ CSTII_Is,
+ CSTII_Unit,
+ CSTII_Try,
+ CSTII_Except,
+ CSTII_Finally,
+ CSTII_External,
+ CSTII_Forward,
+ CSTII_Export,
+ CSTII_Label,
+ CSTII_Goto,
+ CSTII_Chr,
+ CSTII_Ord,
+ CSTII_Interface,
+ CSTII_Implementation,
+ CSTII_initialization, //* Nvds
+ CSTII_finalization, //* Nvds
+ CSTII_out,
+ CSTII_nil
+ );
+
+ TPSParserErrorKind = (iNoError
+ , iCommentError
+ , iStringError
+ , iCharError
+ , iSyntaxError
+ );
+ TPSParserErrorEvent = procedure (Parser: TObject; Kind: TPSParserErrorKind) of object;
+
+
+ TPSPascalParser = class(TObject)
+ protected
+ FData: TbtString;
+ FText: {$IFDEF DELPHI4UP}PAnsiChar{$ELSE}PChar{$ENDIF};
+ FLastEnterPos, FRow, FRealPosition, FTokenLength: Cardinal;
+ FTokenId: TPSPasToken;
+ FToken: TbtString;
+ FOriginalToken: TbtString;
+ FParserError: TPSParserErrorEvent;
+ FEnableComments: Boolean;
+ FEnableWhitespaces: Boolean;
+ function GetCol: Cardinal;
+ // only applicable when Token in [CSTI_Identifier, CSTI_Integer, CSTI_Real, CSTI_String, CSTI_Char, CSTI_HexInt]
+ public
+
+ property EnableComments: Boolean read FEnableComments write FEnableComments;
+
+ property EnableWhitespaces: Boolean read FEnableWhitespaces write FEnableWhitespaces;
+
+ procedure Next; virtual;
+
+ property GetToken: TbtString read FToken;
+
+ property OriginalToken: TbtString read FOriginalToken;
+
+ property CurrTokenPos: Cardinal read FRealPosition;
+
+ property CurrTokenID: TPSPasToken read FTokenId;
+
+ property Row: Cardinal read FRow;
+
+ property Col: Cardinal read GetCol;
+
+ procedure SetText(const Data: TbtString); virtual;
+
+ property OnParserError: TPSParserErrorEvent read FParserError write FParserError;
+ end;
+
+function FloatToStr(E: Extended): TbtString;
+
+function FastLowerCase(const s: TbtString): TbtString;
+
+function Fw(const S: TbtString): TbtString;
+
+function IntToStr(I: LongInt): TbtString;
+
+function StrToIntDef(const S: TbtString; Def: LongInt): LongInt;
+
+function StrToInt(const S: TbtString): LongInt;
+function StrToFloat(const s: TbtString): Extended;
+
+function FastUpperCase(const s: TbtString): TbtString;
+
+function GRFW(var s: TbtString): TbtString;
+function GRLW(var s: TbtString): TbtString;
+
+const
+
+ FCapacityInc = 32;
+{$IFNDEF PS_NOSMARTLIST}
+
+ FMaxCheckCount = (FCapacityInc div 4) * 64;
+{$ENDIF}
+
+{$IFDEF VER130}
+function WideUpperCase(const S: WideString): WideString;
+function WideLowerCase(const S: WideString): WideString;
+{$ENDIF}
+implementation
+
+{$IFDEF DELPHI3UP }
+resourceString
+{$ELSE }
+const
+{$ENDIF }
+ RPS_InvalidFloat = 'Invalid float';
+
+{$IFDEF VER130}
+
+function WideUpperCase(const S: WideString): WideString;
+var
+ Len: Integer;
+begin
+ // CharUpperBuffW is stubbed out on Win9x platofmrs
+ if Win32Platform = VER_PLATFORM_WIN32_NT then
+ begin
+ Len := Length(S);
+ SetString(Result, PWideChar(S), Len);
+ if Len > 0 then CharUpperBuffW(Pointer(Result), Len);
+ end
+ else
+ Result := AnsiUpperCase(S);
+end;
+
+function WideLowerCase(const S: WideString): WideString;
+var
+ Len: Integer;
+begin
+ // CharLowerBuffW is stubbed out on Win9x platofmrs
+ if Win32Platform = VER_PLATFORM_WIN32_NT then
+ begin
+ Len := Length(S);
+ SetString(Result, PWideChar(S), Len);
+ if Len > 0 then CharLowerBuffW(Pointer(Result), Len);
+ end
+ else
+ Result := AnsiLowerCase(S);
+end;
+
+{$ENDIF}
+
+
+function MakeHash(const s: TbtString): Longint;
+{small hash maker}
+var
+ I: Integer;
+begin
+ Result := 0;
+ for I := 1 to Length(s) do
+ Result := ((Result shl 7) or (Result shr 25)) + Ord(s[I]);
+end;
+
+function GRFW(var s: TbtString): TbtString;
+var
+ l: Longint;
+begin
+ l := 1;
+ while l <= Length(s) do
+ begin
+ if s[l] = ' ' then
+ begin
+ Result := copy(s, 1, l - 1);
+ Delete(s, 1, l);
+ exit;
+ end;
+ l := l + 1;
+ end;
+ Result := s;
+ s := '';
+end;
+
+function GRLW(var s: TbtString): TbtString;
+var
+ l: Longint;
+begin
+ l := Length(s);
+ while l >= 1 do
+ begin
+ if s[l] = ' ' then
+ begin
+ Result := copy(s, l+1, MaxInt);
+ Delete(s, l, MaxInt);
+ exit;
+ end;
+ Dec(l);
+ end;
+ Result := s;
+ s := '';
+end;
+
+function StrToFloat(const s: TbtString): Extended;
+var
+ i: longint;
+begin
+ Val(string(s), Result, i);
+ if i <> 0 then raise Exception.Create(RPS_InvalidFloat);
+end;
+//-------------------------------------------------------------------
+
+function IntToStr(I: LongInt): TbtString;
+var
+ s: tbtstring;
+begin
+ Str(i, s);
+ IntToStr := s;
+end;
+//-------------------------------------------------------------------
+
+function FloatToStr(E: Extended): TbtString;
+var
+ s: tbtstring;
+begin
+ Str(e:0:12, s);
+ result := s;
+end;
+
+function StrToInt(const S: TbtString): LongInt;
+var
+ e: Integer;
+ Res: LongInt;
+begin
+ Val(string(S), Res, e);
+ if e <> 0 then
+ StrToInt := -1
+ else
+ StrToInt := Res;
+end;
+//-------------------------------------------------------------------
+
+function StrToIntDef(const S: TbtString; Def: LongInt): LongInt;
+var
+ e: Integer;
+ Res: LongInt;
+begin
+ Val(string(S), Res, e);
+ if e <> 0 then
+ StrToIntDef := Def
+ else
+ StrToIntDef := Res;
+end;
+//-------------------------------------------------------------------
+
+constructor TPSList.Create;
+begin
+ inherited Create;
+ FCount := 0;
+ FCapacity := 16;
+ {$IFNDEF PS_NOSMARTLIST}
+ FCheckCount := 0;
+ {$ENDIF}
+ GetMem(FData, FCapacity * PointerSize);
+end;
+
+
+function MM(i1,i2: Integer): Integer;
+begin
+ if ((i1 div i2) * i2) < i1 then
+ mm := (i1 div i2 + 1) * i2
+ else
+ mm := (i1 div i2) * i2;
+end;
+
+{$IFNDEF PS_NOSMARTLIST}
+procedure TPSList.Recreate;
+var
+ NewData: PPointerList;
+ NewCapacity: Cardinal;
+ I: Longint;
+
+begin
+
+ FCheckCount := 0;
+ NewCapacity := mm(FCount, FCapacityInc);
+ if NewCapacity < 64 then NewCapacity := 64;
+ GetMem(NewData, NewCapacity * PointerSize);
+ for I := 0 to Longint(FCount) -1 do
+ begin
+ NewData^[i] := FData^[I];
+ end;
+ FreeMem(FData, FCapacity * PointerSize);
+ FData := NewData;
+ FCapacity := NewCapacity;
+end;
+{$ENDIF}
+
+//-------------------------------------------------------------------
+
+function TPSList.Add(P: Pointer): Longint;
+begin
+ if FCount >= FCapacity then
+ begin
+ Inc(FCapacity, FCapacityInc);// := FCount + 1;
+ ReAllocMem(FData, FCapacity * PointerSize);
+ end;
+ FData[FCount] := P; // Instead of SetItem
+ Result := FCount;
+ Inc(FCount);
+{$IFNDEF PS_NOSMARTLIST}
+ Inc(FCheckCount);
+ if FCheckCount > FMaxCheckCount then Recreate;
+{$ENDIF}
+end;
+
+procedure TPSList.AddBlock(List: PPointerList; Count: Longint);
+var
+ L: Longint;
+
+begin
+ if Longint(FCount) + Count > Longint(FCapacity) then
+ begin
+ Inc(FCapacity, mm(Count, FCapacityInc));
+ ReAllocMem(FData, FCapacity *PointerSize);
+ end;
+ for L := 0 to Count -1 do
+ begin
+ FData^[FCount] := List^[L];
+ Inc(FCount);
+ end;
+{$IFNDEF PS_NOSMARTLIST}
+ Inc(FCheckCount);
+ if FCheckCount > FMaxCheckCount then Recreate;
+{$ENDIF}
+end;
+
+
+//-------------------------------------------------------------------
+
+procedure TPSList.DeleteLast;
+begin
+ if FCount = 0 then Exit;
+ Dec(FCount);
+{$IFNDEF PS_NOSMARTLIST}
+ Inc(FCheckCount);
+ if FCheckCount > FMaxCheckCount then Recreate;
+{$ENDIF}
+end;
+
+
+
+procedure TPSList.Delete(Nr: Cardinal);
+begin
+ if FCount = 0 then Exit;
+ if Nr < FCount then
+ begin
+ Move(FData[Nr + 1], FData[Nr], (FCount - Nr) * PointerSize);
+ Dec(FCount);
+{$IFNDEF PS_NOSMARTLIST}
+ Inc(FCheckCount);
+ if FCheckCount > FMaxCheckCount then Recreate;
+{$ENDIF}
+ end;
+end;
+//-------------------------------------------------------------------
+
+procedure TPSList.Remove(P: Pointer);
+var
+ I: Cardinal;
+begin
+ if FCount = 0 then Exit;
+ I := 0;
+ while I < FCount do
+ begin
+ if FData[I] = P then
+ begin
+ Delete(I);
+ Exit;
+ end;
+ Inc(I);
+ end;
+end;
+//-------------------------------------------------------------------
+
+procedure TPSList.Clear;
+begin
+ FCount := 0;
+{$IFNDEF PS_NOSMARTLIST}
+ Recreate;
+{$ENDIF}
+end;
+//-------------------------------------------------------------------
+
+destructor TPSList.Destroy;
+begin
+ FreeMem(FData, FCapacity * PointerSize);
+ inherited Destroy;
+end;
+//-------------------------------------------------------------------
+
+procedure TPSList.SetItem(Nr: Cardinal; P: Pointer);
+begin
+ if (FCount = 0) or (Nr >= FCount) then
+ Exit;
+ FData[Nr] := P;
+end;
+//-------------------------------------------------------------------
+
+function TPSList.GetItem(Nr: Cardinal): Pointer; {12}
+begin
+ if Nr < FCount then
+ GetItem := FData[Nr]
+ else
+ GetItem := nil;
+end;
+
+
+
+//-------------------------------------------------------------------
+
+function TPSStringList.Count: LongInt;
+begin
+ count := List.count;
+end;
+type pStr = ^TbtString;
+
+//-------------------------------------------------------------------
+
+function TPSStringList.GetItem(Nr: LongInt): TbtString;
+var
+ S: PStr;
+begin
+ s := List.GetItem(Nr);
+ if s = nil then
+ Result := ''
+ else
+
+ Result := s^;
+end;
+//-------------------------------------------------------------------
+
+
+procedure TPSStringList.SetItem(Nr: LongInt; const s: TbtString);
+var
+ p: PStr;
+begin
+ p := List.GetItem(Nr);
+ if p = nil
+ then
+ Exit;
+ p^ := s;
+end;
+//-------------------------------------------------------------------
+
+procedure TPSStringList.Add(const P: TbtString);
+var
+ w: PStr;
+begin
+ new(w);
+ w^ := p;
+ List.Add(w);
+end;
+//-------------------------------------------------------------------
+
+procedure TPSStringList.Delete(NR: LongInt);
+var
+ W: PStr;
+begin
+ W := list.getitem(nr);
+ if w<>nil then
+ begin
+ dispose(w);
+ end;
+ list.Delete(Nr);
+end;
+
+procedure TPSStringList.Clear;
+begin
+ while List.Count > 0 do Delete(0);
+end;
+
+constructor TPSStringList.Create;
+begin
+ inherited Create;
+ List := TPSList.Create;
+end;
+
+destructor TPSStringList.Destroy;
+begin
+ while List.Count > 0 do
+ Delete(0);
+ List.Destroy;
+ inherited Destroy;
+end;
+
+//-------------------------------------------------------------------
+
+
+function Fw(const S: TbtString): TbtString; // First word
+var
+ x: integer;
+begin
+ x := pos(tbtstring(' '), s);
+ if x > 0
+ then Fw := Copy(S, 1, x - 1)
+ else Fw := S;
+end;
+//-------------------------------------------------------------------
+function FastUpperCase(const s: TbtString): TbtString;
+{Fast uppercase}
+var
+ I: Integer;
+ C: tbtChar;
+begin
+ Result := S;
+ I := Length(Result);
+ while I > 0 do
+ begin
+ C := Result[I];
+ if c in [#97..#122] then
+ Result[I] := tbtchar(Ord(Result[I]) -32);
+ Dec(I);
+ end;
+end;
+function FastLowerCase(const s: TbtString): TbtString;
+{Fast lowercase}
+var
+ I: Integer;
+ C: tbtChar;
+begin
+ Result := S;
+ I := Length(Result);
+ while I > 0 do
+ begin
+ C := Result[I];
+ if C in [#65..#90] then
+ Result[I] := tbtchar(Ord(Result[I]) + 32);
+ Dec(I);
+ end;
+end;
+//-------------------------------------------------------------------
+
+type
+ TRTab = record
+ name: TbtString;
+ c: TPSPasToken;
+ end;
+
+
+const
+ KEYWORD_COUNT = 65; //*NVDS
+ LookupTable: array[0..KEYWORD_COUNT - 1] of TRTab = (
+ (name: 'AND'; c: CSTII_and),
+ (name: 'ARRAY'; c: CSTII_array),
+ (name: 'AS'; c: CSTII_as),
+ (name: 'BEGIN'; c: CSTII_begin),
+ (name: 'CASE'; c: CSTII_case),
+ (name: 'CHR'; c: CSTII_chr),
+ (name: 'CLASS'; c: CSTII_class),
+ (name: 'CONST'; c: CSTII_const),
+ (name: 'CONSTRUCTOR'; c: CSTII_constructor),
+ (name: 'DESTRUCTOR'; c: CSTII_destructor),
+ (name: 'DIV'; c: CSTII_div),
+ (name: 'DO'; c: CSTII_do),
+ (name: 'DOWNTO'; c: CSTII_downto),
+ (name: 'ELSE'; c: CSTII_else),
+ (name: 'END'; c: CSTII_end),
+ (name: 'EXCEPT'; c: CSTII_except),
+ (name: 'EXIT'; c: CSTII_exit),
+ (name: 'EXPORT'; c: CSTII_Export),
+ (name: 'EXTERNAL'; c: CSTII_External),
+ (Name: 'FINALIZATION'; c : CSTII_finalization),//* Nvds
+ (name: 'FINALLY'; c: CSTII_finally),
+ (name: 'FOR'; c: CSTII_for),
+ (name: 'FORWARD'; c: CSTII_Forward),
+ (name: 'FUNCTION'; c: CSTII_function),
+ (name: 'GOTO'; c: CSTII_Goto),
+ (name: 'IF'; c: CSTII_if),
+ (name: 'IMPLEMENTATION'; c: CSTII_Implementation),
+ (name: 'IN'; c: CSTII_in),
+ (name: 'INHERITED'; c: CSTII_inherited),
+ (Name: 'INITIALIZATION'; c: CSTII_initialization), //* Nvds
+ (name: 'INTERFACE'; c: CSTII_Interface),
+ (name: 'IS'; c: CSTII_is),
+ (name: 'LABEL'; c: CSTII_Label),
+ (name: 'MOD'; c: CSTII_mod),
+ (name: 'NIL'; c: CSTII_nil),
+ (name: 'NOT'; c: CSTII_not),
+ (name: 'OF'; c: CSTII_of),
+ (name: 'OR'; c: CSTII_or),
+ (name: 'ORD'; c: CSTII_ord),
+ (name: 'OUT'; c: CSTII_Out),
+ (name: 'OVERRIDE'; c: CSTII_override),
+ //(name: 'DEFAULT'; c: CSTII_default), //Birb (if added, don't forget to increase KEYWORD_COUNT)
+ (name: 'PRIVATE'; c: CSTII_private),
+ (name: 'PROCEDURE'; c: CSTII_procedure),
+ (name: 'PROGRAM'; c: CSTII_program),
+ (name: 'PROPERTY'; c: CSTII_property),
+ (name: 'PROTECTED'; c: CSTII_protected),
+ (name: 'PUBLIC'; c: CSTII_public),
+ (name: 'PUBLISHED'; c: CSTII_published),
+ (name: 'RECORD'; c: CSTII_record),
+ (name: 'REPEAT'; c: CSTII_repeat),
+ (name: 'SET'; c: CSTII_set),
+ (name: 'SHL'; c: CSTII_shl),
+ (name: 'SHR'; c: CSTII_shr),
+ (name: 'THEN'; c: CSTII_then),
+ (name: 'TO'; c: CSTII_to),
+ (name: 'TRY'; c: CSTII_try),
+ (name: 'TYPE'; c: CSTII_type),
+ (name: 'UNIT'; c: CSTII_Unit),
+ (name: 'UNTIL'; c: CSTII_until),
+ (name: 'USES'; c: CSTII_uses),
+ (name: 'VAR'; c: CSTII_var),
+ (name: 'VIRTUAL'; c: CSTII_virtual),
+ (name: 'WHILE'; c: CSTII_while),
+ (name: 'WITH'; c: CSTII_with),
+ (name: 'XOR'; c: CSTII_xor));
+
+function TPSPascalParser.GetCol: Cardinal;
+begin
+ Result := FRealPosition - FLastEnterPos + 1;
+end;
+
+procedure TPSPascalParser.Next;
+var
+ Err: TPSParserErrorKind;
+ FLastUpToken: TbtString;
+ function CheckReserved(Const S: ShortString; var CurrTokenId: TPSPasToken): Boolean;
+ var
+ L, H, I: LongInt;
+ J: tbtChar;
+ SName: ShortString;
+ begin
+ L := 0;
+ J := S[0];
+ H := KEYWORD_COUNT-1;
+ while L <= H do
+ begin
+ I := (L + H) shr 1;
+ SName := LookupTable[i].Name;
+ if J = SName[0] then
+ begin
+ if S = SName then
+ begin
+ CheckReserved := True;
+ CurrTokenId := LookupTable[I].c;
+ Exit;
+ end;
+ if S > SName then
+ L := I + 1
+ else
+ H := I - 1;
+ end else
+ if S > SName then
+ L := I + 1
+ else
+ H := I - 1;
+ end;
+ CheckReserved := False;
+ end;
+ //-------------------------------------------------------------------
+
+ function _GetToken(CurrTokenPos, CurrTokenLen: Cardinal): TbtString;
+ var
+ s: tbtString;
+ begin
+ SetLength(s, CurrTokenLen);
+ Move(FText[CurrTokenPos], S[1], CurrtokenLen);
+ Result := s;
+ end;
+
+ function ParseToken(var CurrTokenPos, CurrTokenLen: Cardinal; var CurrTokenId: TPSPasToken): TPSParserErrorKind;
+ {Parse the token}
+ var
+ ct, ci: Cardinal;
+ hs: Boolean;
+ p: {$IFDEF DELPHI4UP}PAnsiChar{$ELSE}PChar{$ENDIF};
+ begin
+ ParseToken := iNoError;
+ ct := CurrTokenPos;
+ case FText[ct] of
+ #0:
+ begin
+ CurrTokenId := CSTI_EOF;
+ CurrTokenLen := 0;
+ end;
+ 'A'..'Z', 'a'..'z', '_':
+ begin
+ ci := ct + 1;
+ while (FText[ci] in ['_', '0'..'9', 'a'..'z', 'A'..'Z']) do begin
+ Inc(ci);
+ end;
+ CurrTokenLen := ci - ct;
+
+ FLastUpToken := _GetToken(CurrTokenPos, CurrtokenLen);
+ p := {$IFDEF DELPHI4UP}PAnsiChar{$ELSE}pchar{$ENDIF}(FLastUpToken);
+ while p^<>#0 do
+ begin
+ if p^ in [#97..#122] then
+ Dec(Byte(p^), 32);
+ inc(p);
+ end;
+ if not CheckReserved(FLastUpToken, CurrTokenId) then
+ begin
+ CurrTokenId := CSTI_Identifier;
+ end;
+ end;
+ '$':
+ begin
+ ci := ct + 1;
+
+ while (FText[ci] in ['0'..'9', 'a'..'f', 'A'..'F'])
+ do Inc(ci);
+
+ CurrTokenId := CSTI_HexInt;
+ CurrTokenLen := ci - ct;
+ end;
+
+ '0'..'9':
+ begin
+ hs := False;
+ ci := ct;
+ while (FText[ci] in ['0'..'9']) do
+ begin
+ Inc(ci);
+ if (FText[ci] = '.') and (not hs) then
+ begin
+ if FText[ci+1] = '.' then break;
+ hs := True;
+ Inc(ci);
+ end;
+ end;
+ if (FText[ci] in ['E','e']) and ((FText[ci+1] in ['0'..'9'])
+ or ((FText[ci+1] in ['+','-']) and (FText[ci+2] in ['0'..'9']))) then
+ begin
+ hs := True;
+ Inc(ci);
+ if FText[ci] in ['+','-'] then
+ Inc(ci);
+ repeat
+ Inc(ci);
+ until not (FText[ci] in ['0'..'9']);
+ end;
+
+ if hs
+ then CurrTokenId := CSTI_Real
+ else CurrTokenId := CSTI_Integer;
+
+ CurrTokenLen := ci - ct;
+ end;
+
+
+ #39:
+ begin
+ ci := ct + 1;
+ while true do
+ begin
+ if (FText[ci] = #0) or (FText[ci] = #13) or (FText[ci] = #10) then Break;
+ if (FText[ci] = #39) then
+ begin
+ if FText[ci+1] = #39 then
+ Inc(ci)
+ else
+ Break;
+ end;
+ Inc(ci);
+ end;
+ if FText[ci] = #39 then
+ CurrTokenId := CSTI_String
+ else
+ begin
+ CurrTokenId := CSTI_String;
+ ParseToken := iStringError;
+ end;
+ CurrTokenLen := ci - ct + 1;
+ end;
+ '#':
+ begin
+ ci := ct + 1;
+ if FText[ci] = '$' then
+ begin
+ inc(ci);
+ while (FText[ci] in ['A'..'F', 'a'..'f', '0'..'9']) do begin
+ Inc(ci);
+ end;
+ CurrTokenId := CSTI_Char;
+ CurrTokenLen := ci - ct;
+ end else
+ begin
+ while (FText[ci] in ['0'..'9']) do begin
+ Inc(ci);
+ end;
+ if FText[ci] in ['A'..'Z', 'a'..'z', '_'] then
+ begin
+ ParseToken := iCharError;
+ CurrTokenId := CSTI_Char;
+ end else
+ CurrTokenId := CSTI_Char;
+ CurrTokenLen := ci - ct;
+ end;
+ end;
+ '=':
+ begin
+ CurrTokenId := CSTI_Equal;
+ CurrTokenLen := 1;
+ end;
+ '>':
+ begin
+ if FText[ct + 1] = '=' then
+ begin
+ CurrTokenid := CSTI_GreaterEqual;
+ CurrTokenLen := 2;
+ end else
+ begin
+ CurrTokenid := CSTI_Greater;
+ CurrTokenLen := 1;
+ end;
+ end;
+ '<':
+ begin
+ if FText[ct + 1] = '=' then
+ begin
+ CurrTokenId := CSTI_LessEqual;
+ CurrTokenLen := 2;
+ end else
+ if FText[ct + 1] = '>' then
+ begin
+ CurrTokenId := CSTI_NotEqual;
+ CurrTokenLen := 2;
+ end else
+ begin
+ CurrTokenId := CSTI_Less;
+ CurrTokenLen := 1;
+ end;
+ end;
+ ')':
+ begin
+ CurrTokenId := CSTI_CloseRound;
+ CurrTokenLen := 1;
+ end;
+ '(':
+ begin
+ if FText[ct + 1] = '*' then
+ begin
+ ci := ct + 1;
+ while (FText[ci] <> #0) do begin
+ if (FText[ci] = '*') and (FText[ci + 1] = ')') then
+ Break;
+ if FText[ci] = #13 then
+ begin
+ inc(FRow);
+ if FText[ci+1] = #10 then
+ inc(ci);
+ FLastEnterPos := ci +1;
+ end else if FText[ci] = #10 then
+ begin
+ inc(FRow);
+ FLastEnterPos := ci +1;
+ end;
+ Inc(ci);
+ end;
+ if (FText[ci] = #0) then
+ begin
+ CurrTokenId := CSTIINT_Comment;
+ ParseToken := iCommentError;
+ end else
+ begin
+ CurrTokenId := CSTIINT_Comment;
+ Inc(ci, 2);
+ end;
+ CurrTokenLen := ci - ct;
+ end
+ else
+ begin
+ CurrTokenId := CSTI_OpenRound;
+ CurrTokenLen := 1;
+ end;
+ end;
+ '[':
+ begin
+ CurrTokenId := CSTI_OpenBlock;
+ CurrTokenLen := 1;
+ end;
+ ']':
+ begin
+ CurrTokenId := CSTI_CloseBlock;
+ CurrTokenLen := 1;
+ end;
+ ',':
+ begin
+ CurrTokenId := CSTI_Comma;
+ CurrTokenLen := 1;
+ end;
+ '.':
+ begin
+ if FText[ct + 1] = '.' then
+ begin
+ CurrTokenLen := 2;
+ CurrTokenId := CSTI_TwoDots;
+ end else
+ begin
+ CurrTokenId := CSTI_Period;
+ CurrTokenLen := 1;
+ end;
+ end;
+ '@':
+ begin
+ CurrTokenId := CSTI_AddressOf;
+ CurrTokenLen := 1;
+ end;
+ '^':
+ begin
+ CurrTokenId := CSTI_Dereference;
+ CurrTokenLen := 1;
+ end;
+ ';':
+ begin
+ CurrTokenId := CSTI_Semicolon;
+ CurrTokenLen := 1;
+ end;
+ ':':
+ begin
+ if FText[ct + 1] = '=' then
+ begin
+ CurrTokenId := CSTI_Assignment;
+ CurrTokenLen := 2;
+ end else
+ begin
+ CurrTokenId := CSTI_Colon;
+ CurrTokenLen := 1;
+ end;
+ end;
+ '+':
+ begin
+ CurrTokenId := CSTI_Plus;
+ CurrTokenLen := 1;
+ end;
+ '-':
+ begin
+ CurrTokenId := CSTI_Minus;
+ CurrTokenLen := 1;
+ end;
+ '*':
+ begin
+ CurrTokenId := CSTI_Multiply;
+ CurrTokenLen := 1;
+ end;
+ '/':
+ begin
+ if FText[ct + 1] = '/' then
+ begin
+ ci := ct + 1;
+ while (FText[ci] <> #0) and (FText[ci] <> #13) and
+ (FText[ci] <> #10) do begin
+ Inc(ci);
+ end;
+ if (FText[ci] = #0) then
+ begin
+ CurrTokenId := CSTIINT_Comment;
+ end else
+ begin
+ CurrTokenId := CSTIINT_Comment;
+ end;
+ CurrTokenLen := ci - ct;
+ end else
+ begin
+ CurrTokenId := CSTI_Divide;
+ CurrTokenLen := 1;
+ end;
+ end;
+ #32, #9, #13, #10:
+ begin
+ ci := ct;
+ while (FText[ci] in [#32, #9, #13, #10]) do
+ begin
+ if FText[ci] = #13 then
+ begin
+ inc(FRow);
+ if FText[ci+1] = #10 then
+ inc(ci);
+ FLastEnterPos := ci +1;
+ end else if FText[ci] = #10 then
+ begin
+ inc(FRow);
+ FLastEnterPos := ci +1;
+ end;
+ Inc(ci);
+ end;
+ CurrTokenId := CSTIINT_WhiteSpace;
+ CurrTokenLen := ci - ct;
+ end;
+ '{':
+ begin
+ ci := ct + 1;
+ while (FText[ci] <> #0) and (FText[ci] <> '}') do begin
+ if FText[ci] = #13 then
+ begin
+ inc(FRow);
+ if FText[ci+1] = #10 then
+ inc(ci);
+ FLastEnterPos := ci + 1;
+ end else if FText[ci] = #10 then
+ begin
+ inc(FRow);
+ FLastEnterPos := ci + 1;
+ end;
+ Inc(ci);
+ end;
+ if (FText[ci] = #0) then
+ begin
+ CurrTokenId := CSTIINT_Comment;
+ ParseToken := iCommentError;
+ end else
+ CurrTokenId := CSTIINT_Comment;
+ CurrTokenLen := ci - ct + 1;
+ end;
+ else
+ begin
+ ParseToken := iSyntaxError;
+ CurrTokenId := CSTIINT_Comment;
+ CurrTokenLen := 1;
+ end;
+ end;
+ end;
+ //-------------------------------------------------------------------
+begin
+ if FText = nil then
+ begin
+ FTokenLength := 0;
+ FRealPosition := 0;
+ FTokenId := CSTI_EOF;
+ Exit;
+ end;
+ repeat
+ FRealPosition := FRealPosition + Cardinal(FTokenLength);
+ Err := ParseToken(FRealPosition, Cardinal(FTokenLength), FTokenID);
+ if Err <> iNoError then
+ begin
+ FTokenLength := 0;
+ FTokenId := CSTI_EOF;
+ FToken := '';
+ FOriginalToken := '';
+ if @FParserError <> nil then FParserError(Self, Err);
+ exit;
+ end;
+
+ case FTokenID of
+ CSTIINT_Comment: if not FEnableComments then Continue else
+ begin
+ SetLength(FOriginalToken, FTokenLength);
+ Move(FText[CurrTokenPos], FOriginalToken[1], FTokenLength);
+ FToken := FOriginalToken;
+ end;
+ CSTIINT_WhiteSpace: if not FEnableWhitespaces then Continue else
+ begin
+ SetLength(FOriginalToken, FTokenLength);
+ Move(FText[CurrTokenPos], FOriginalToken[1], FTokenLength);
+ FToken := FOriginalToken;
+ end;
+ CSTI_Integer, CSTI_Real, CSTI_String, CSTI_Char, CSTI_HexInt:
+ begin
+ SetLength(FOriginalToken, FTokenLength);
+ Move(FText[CurrTokenPos], FOriginalToken[1], FTokenLength);
+ FToken := FOriginalToken;
+ end;
+ CSTI_Identifier:
+ begin
+ SetLength(FOriginalToken, FTokenLength);
+ Move(FText[CurrTokenPos], FOriginalToken[1], FTokenLength);
+ FToken := FLastUpToken;
+ end;
+ else
+ begin
+ FOriginalToken := '';
+ FToken := '';
+ end;
+ end;
+ Break;
+ until False;
+end;
+
+procedure TPSPascalParser.SetText(const Data: TbtString);
+begin
+ FData := Data;
+ FText := Pointer(FData);
+ FTokenLength := 0;
+ FRealPosition := 0;
+ FTokenId := CSTI_EOF;
+ FLastEnterPos := 0;
+ FRow := 1;
+ Next;
+end;
+
+function TPSList.IndexOf(P: Pointer): Longint;
+var
+ i: Integer;
+begin
+ for i := FCount -1 downto 0 do
+ begin
+ if FData[i] = p then
+ begin
+ result := i;
+ exit;
+ end;
+ end;
+ result := -1;
+end;
+
+{ TPSUnitList }
+
+function TPSUnitList.Add: TPSUnit;
+begin
+ result:=TPSUnit.Create(Self);
+
+ fList.Add(result);
+end;
+
+constructor TPSUnitList.Create;
+begin
+ fList:=TPSList.Create;
+end;
+
+destructor TPSUnitList.Destroy;
+var
+ Dummy: Integer;
+begin
+ for Dummy:=0 to fList.Count-1 do
+ TObject(fList[Dummy]).Free;
+
+ FreeAndNil(fList);
+
+ inherited;
+end;
+
+function TPSUnitList.GetUnit(UnitName: TbtString): TPSUnit;
+var
+ Dummy: Integer;
+begin
+ UnitName:=FastUpperCase(UnitName);
+ for Dummy:=0 to fList.Count-1 do
+ begin
+ if TPSUnit(fList[Dummy]).UnitName=UnitName then
+ begin
+ result:=TPSUnit(fList[Dummy]);
+ exit;
+ end;
+ end;
+
+ result:=Add;
+
+ result.UnitName:=UnitName;
+end;
+
+{ TPSUnit }
+
+procedure TPSUnit.AddUses(pUnitName: TbtString);
+var
+ UsesUnit: TPSUnit;
+begin
+ UsesUnit:=fList.GetUnit(pUnitName);
+ fUnits.Add(UsesUnit);
+end;
+
+constructor TPSUnit.Create(List: TPSUnitList);
+begin
+ fUnits:=TPSList.Create;
+
+ fList:=List;
+end;
+
+destructor TPSUnit.Destroy;
+begin
+ FreeAndNIl(fUnits);
+ inherited;
+end;
+
+function TPSUnit.HasUses(pUnitName: TbtString): Boolean;
+var
+ Dummy: Integer;
+begin
+ pUnitName:=FastUpperCase(pUnitName);
+
+ if fUnitName=pUnitName then
+ begin
+ result:=true;
+ exit;
+ end;
+
+ result:=false;
+
+ for Dummy:=0 to fUnits.Count-1 do
+ begin
+ result:=TPSUnit(fUnits[Dummy]).HasUses(pUnitName);
+
+ if result then
+ exit;
+ end;
+end;
+
+procedure TPSUnit.SetUnitName(const Value: TbtString);
+begin
+ fUnitName := FastUpperCase(Value);
+end;
+
+
+end.
+
+
diff --git a/branches/script-component/Units/PascalScript/uPS_ExtReg.pas b/branches/script-component/Units/PascalScript/uPS_ExtReg.pas
new file mode 100644
index 0000000..19cc4df
--- /dev/null
+++ b/branches/script-component/Units/PascalScript/uPS_ExtReg.pas
@@ -0,0 +1,17 @@
+unit uPS_ExtReg;
+
+interface
+
+procedure Register;
+
+implementation
+
+uses classes, uPSI_IBX, uPSI_Mask, upSI_JvMail, uPSI_Dialogs, uPSI_Registry;
+
+procedure Register;
+begin
+ RegisterComponents('Pascal Script', [TPSImport_IBX, TPSImport_Mask, TPSImport_JvMail,
+ TPSImport_Dialogs, TPSImport_Registry]);
+end;
+
+end.
diff --git a/branches/script-component/Units/PascalScript/uROPSImports.pas b/branches/script-component/Units/PascalScript/uROPSImports.pas
new file mode 100644
index 0000000..bc81094
--- /dev/null
+++ b/branches/script-component/Units/PascalScript/uROPSImports.pas
@@ -0,0 +1,366 @@
+unit uROPSImports;
+
+interface
+
+uses
+ uPSCompiler, uPSRuntime, uROBINMessage, uROIndyHTTPChannel,
+ uROXMLSerializer, uROIndyTCPChannel, idTcpClient,
+ uROPSServerLink, uROWinInetHttpChannel;
+
+
+procedure SIRegisterTROBINMESSAGE(CL: TIFPSPascalCompiler);
+procedure SIRegisterTROINDYHTTPCHANNEL(CL: TIFPSPascalCompiler);
+procedure SIRegisterTROINDYTCPCHANNEL(CL: TIFPSPascalCompiler);
+procedure SIRegisterTIDTCPCLIENT(CL: TIFPSPascalCompiler);
+procedure SIRegisterRODLImports(Cl: TIFPSPascalCompiler);
+
+
+
+procedure RIRegisterTROBINMESSAGE(Cl: TIFPSRuntimeClassImporter);
+procedure RIRegisterTROINDYHTTPCHANNEL(Cl: TIFPSRuntimeClassImporter);
+procedure RIRegisterTROINDYTCPCHANNEL(Cl: TIFPSRuntimeClassImporter);
+procedure RIRegisterTIDTCPCLIENT(Cl: TIFPSRuntimeClassImporter);
+procedure RIRegisterRODLImports(CL: TIFPSRuntimeClassImporter);
+(*
+Todo:
+ TROWinInetHTTPChannel = class(TROTransportChannel, IROTransport, IROTCPTransport, IROHTTPTransport)
+ published
+ property UserAgent:string read GetUserAgent write SetUserAgent;
+ property TargetURL : string read fTargetURL write SetTargetURL;
+ property StoreConnected:boolean read fStoreConnected write fStoreConnected default false;
+ property KeepConnection:boolean read fKeepConnection write fKeepConnection default false;
+ end;
+*)
+type
+
+ TPSROIndyTCPModule = class(TPSROModule)
+ protected
+ class procedure ExecImp(exec: TIFPSExec; ri: TIFPSRuntimeClassImporter); override;
+ class procedure CompImp(comp: TIFPSPascalCompiler); override;
+ end;
+
+ TPSROIndyHTTPModule = class(TPSROModule)
+ protected
+ class procedure ExecImp(exec: TIFPSExec; ri: TIFPSRuntimeClassImporter); override;
+ class procedure CompImp(comp: TIFPSPascalCompiler); override;
+ end;
+
+ TPSROBinModule = class(TPSROModule)
+ protected
+ class procedure ExecImp(exec: TIFPSExec; ri: TIFPSRuntimeClassImporter); override;
+ class procedure CompImp(comp: TIFPSPascalCompiler); override;
+ end;
+
+
+implementation
+
+{procedure TROSOAPMESSAGESERIALIZATIONOPTIONS_W(Self: TROSOAPMESSAGE;
+ const T: TXMLSERIALIZATIONOPTIONS);
+begin
+ Self.SERIALIZATIONOPTIONS := T;
+end;
+
+procedure TROSOAPMESSAGESERIALIZATIONOPTIONS_R(Self: TROSOAPMESSAGE;
+ var T: TXMLSERIALIZATIONOPTIONS);
+begin
+ T := Self.SERIALIZATIONOPTIONS;
+end;
+
+procedure TROSOAPMESSAGECUSTOMLOCATION_W(Self: TROSOAPMESSAGE; const T: string);
+begin
+ Self.CUSTOMLOCATION := T;
+end;
+
+procedure TROSOAPMESSAGECUSTOMLOCATION_R(Self: TROSOAPMESSAGE; var T: string);
+begin
+ T := Self.CUSTOMLOCATION;
+end;
+
+procedure TROSOAPMESSAGELIBRARYNAME_W(Self: TROSOAPMESSAGE; const T: string);
+begin
+ Self.LIBRARYNAME := T;
+end;
+
+procedure TROSOAPMESSAGELIBRARYNAME_R(Self: TROSOAPMESSAGE; var T: string);
+begin
+ T := Self.LIBRARYNAME;
+end; }
+
+procedure TROBINMESSAGEUSECOMPRESSION_W(Self: TROBINMESSAGE; const T: boolean);
+begin
+ Self.USECOMPRESSION := T;
+end;
+
+procedure TROBINMESSAGEUSECOMPRESSION_R(Self: TROBINMESSAGE; var T: boolean);
+begin
+ T := Self.USECOMPRESSION;
+end;
+
+procedure TROINDYHTTPCHANNELTARGETURL_W(Self: TROINDYHTTPCHANNEL; const T: string);
+begin
+ Self.TARGETURL := T;
+end;
+
+procedure TROINDYHTTPCHANNELTARGETURL_R(Self: TROINDYHTTPCHANNEL; var T: string);
+begin
+ T := Self.TARGETURL;
+end;
+
+procedure TROINDYTCPCHANNELINDYCLIENT_R(Self: TROINDYTCPCHANNEL; var T: TIdTCPClientBaseClass);
+begin
+ T := Self.INDYCLIENT;
+end;
+
+procedure TIDTCPCLIENTPORT_W(Self: TIDTCPCLIENT; const T: integer);
+begin
+ Self.PORT := T;
+end;
+
+procedure TIDTCPCLIENTPORT_R(Self: TIdTCPClientBaseClass; var T: integer);
+begin
+ T := TIdIndy10HackClient(Self).PORT;
+end;
+
+procedure TIDTCPCLIENTHOST_W(Self: TIdTCPClientBaseClass; const T: string);
+begin
+ TIdIndy10HackClient(Self).HOST := T;
+end;
+
+procedure TIDTCPCLIENTHOST_R(Self: TIdTCPClientBaseClass; var T: string);
+begin
+ T := TIdIndy10HackClient(Self).HOST;
+end;
+
+{procedure TIDTCPCLIENTBOUNDPORT_W(Self: TIdTCPClientBaseClass; const T: integer);
+begin
+ Self.BOUNDPORT := T;
+end;
+
+procedure TIDTCPCLIENTBOUNDPORT_R(Self: TIdTCPClientBaseClass; var T: integer);
+begin
+ T := Self.BOUNDPORT;
+end;
+
+procedure TIDTCPCLIENTBOUNDIP_W(Self: TIdTCPClientBaseClass; const T: string);
+begin
+ Self.BOUNDIP := T;
+end;
+
+procedure TIDTCPCLIENTBOUNDIP_R(Self: TIdTCPClientBaseClass; var T: string);
+begin
+ T := Self.BOUNDIP;
+end;]
+
+procedure TIDTCPCLIENTBOUNDPORTMIN_W(Self: TIdTCPClientBaseClass; const T: integer);
+begin
+ Self.BOUNDPORTMIN := T;
+end;
+
+procedure TIDTCPCLIENTBOUNDPORTMIN_R(Self: TIdTCPClientBaseClass; var T: integer);
+begin
+ T := Self.BOUNDPORTMIN;
+end;
+
+procedure TIDTCPCLIENTBOUNDPORTMAX_W(Self: TIdTCPClientBaseClass; const T: integer);
+begin
+ Self.BOUNDPORTMAX := T;
+end;
+
+procedure TIDTCPCLIENTBOUNDPORTMAX_R(Self: TIdTCPClientBaseClass; var T: integer);
+begin
+ T := Self.BOUNDPORTMAX;
+end;
+
+{procedure RIRegisterTROSOAPMESSAGE(Cl: TIFPSRuntimeClassImporter);
+begin
+ with Cl.Add(TROSOAPMESSAGE) do
+ begin
+ RegisterPropertyHelper(@TROSOAPMESSAGELIBRARYNAME_R, @TROSOAPMESSAGELIBRARYNAME_W,
+ 'LIBRARYNAME');
+ RegisterPropertyHelper(@TROSOAPMESSAGECUSTOMLOCATION_R,
+ @TROSOAPMESSAGECUSTOMLOCATION_W, 'CUSTOMLOCATION');
+ RegisterPropertyHelper(@TROSOAPMESSAGESERIALIZATIONOPTIONS_R,
+ @TROSOAPMESSAGESERIALIZATIONOPTIONS_W, 'SERIALIZATIONOPTIONS');
+ end;
+end; }
+
+procedure RIRegisterTROBINMESSAGE(Cl: TIFPSRuntimeClassImporter);
+begin
+ with Cl.Add(TROBINMESSAGE) do
+ begin
+ RegisterPropertyHelper(@TROBINMESSAGEUSECOMPRESSION_R,
+ @TROBINMESSAGEUSECOMPRESSION_W, 'USECOMPRESSION');
+ end;
+end;
+
+procedure RIRegisterTROINDYHTTPCHANNEL(Cl: TIFPSRuntimeClassImporter);
+begin
+ with Cl.Add(TROINDYHTTPCHANNEL) do
+ begin
+ RegisterPropertyHelper(@TROINDYHTTPCHANNELTARGETURL_R,
+ @TROINDYHTTPCHANNELTARGETURL_W, 'TARGETURL');
+ end;
+end;
+
+procedure RIRegisterTROINDYTCPCHANNEL(Cl: TIFPSRuntimeClassImporter);
+begin
+ with Cl.Add(TROINDYTCPCHANNEL) do
+ begin
+ RegisterPropertyHelper(@TROINDYTCPCHANNELINDYCLIENT_R, nil, 'INDYCLIENT');
+ end;
+end;
+
+procedure RIRegisterTIDTCPCLIENT(Cl: TIFPSRuntimeClassImporter);
+begin
+ with Cl.Add(TIdTCPClientBaseClass) do
+ begin
+ {RegisterPropertyHelper(@TIDTCPCLIENTBOUNDPORTMAX_R, @TIDTCPCLIENTBOUNDPORTMAX_W,
+ 'BOUNDPORTMAX');
+ RegisterPropertyHelper(@TIDTCPCLIENTBOUNDPORTMIN_R, @TIDTCPCLIENTBOUNDPORTMIN_W,
+ 'BOUNDPORTMIN');
+ RegisterPropertyHelper(@TIDTCPCLIENTBOUNDIP_R, @TIDTCPCLIENTBOUNDIP_W, 'BOUNDIP');
+ RegisterPropertyHelper(@TIDTCPCLIENTBOUNDPORT_R, @TIDTCPCLIENTBOUNDPORT_W,
+ 'BOUNDPORT');}
+ RegisterPropertyHelper(@TIDTCPCLIENTHOST_R, @TIDTCPCLIENTHOST_W, 'HOST');
+ RegisterPropertyHelper(@TIDTCPCLIENTPORT_R, @TIDTCPCLIENTPORT_W, 'PORT');
+ end;
+end;
+
+procedure RIRegisterRODLImports(CL: TIFPSRuntimeClassImporter);
+begin
+ RIRegisterTIDTCPCLIENT(Cl);
+ RIRegisterTROINDYTCPCHANNEL(Cl);
+ RIRegisterTROINDYHTTPCHANNEL(Cl);
+ RIRegisterTROBINMESSAGE(Cl);
+ //RIRegisterTROSOAPMESSAGE(Cl);
+end;
+
+function RegClassS(cl: TIFPSPascalCompiler; const InheritsFrom,
+ ClassName: string): TPSCompileTimeClass;
+begin
+ Result := cl.FindClass(ClassName);
+ if Result = nil then
+ Result := cl.AddClassN(cl.FindClass(InheritsFrom), ClassName)
+ else
+ Result.ClassInheritsFrom := cl.FindClass(InheritsFrom);
+end;
+
+{procedure SIRegisterTROSOAPMESSAGE(CL: TIFPSPascalCompiler);
+begin
+ Cl.addTypeS('TXMLSERIALIZATIONOPTIONS', 'BYTE');
+ Cl.AddConstantN('XSOWRITEMULTIREFARRAY', 'BYTE').SetInt(1);
+ Cl.AddConstantN('XSOWRITEMULTIREFOBJECT', 'BYTE').SetInt(2);
+ Cl.AddConstantN('XSOSENDUNTYPED', 'BYTE').SetInt(4);
+ with RegClassS(cl, 'TROMESSAGE', 'TROSOAPMESSAGE') do
+ begin
+ RegisterProperty('LIBRARYNAME', 'STRING', iptrw);
+ RegisterProperty('CUSTOMLOCATION', 'STRING', iptrw);
+ RegisterProperty('SERIALIZATIONOPTIONS', 'TXMLSERIALIZATIONOPTIONS', iptrw);
+ end;
+end;}
+
+procedure SIRegisterTROBINMESSAGE(CL: TIFPSPascalCompiler);
+begin
+ with RegClassS(cl, 'TROMESSAGE', 'TROBINMESSAGE') do
+ begin
+ RegisterProperty('USECOMPRESSION', 'BOOLEAN', iptrw);
+ end;
+end;
+
+procedure SIRegisterTROINDYHTTPCHANNEL(CL: TIFPSPascalCompiler);
+begin
+ with RegClassS(cl, 'TROINDYTCPCHANNEL', 'TROINDYHTTPCHANNEL') do
+ begin
+ RegisterProperty('TARGETURL', 'STRING', iptrw);
+ end;
+end;
+
+procedure SIRegisterTROINDYTCPCHANNEL(CL: TIFPSPascalCompiler);
+begin
+ with RegClassS(cl, 'TROTRANSPORTCHANNEL', 'TROINDYTCPCHANNEL') do
+ begin
+ RegisterProperty('INDYCLIENT', 'TIdTCPClientBaseClass', iptr);
+ end;
+end;
+
+procedure SIRegisterTIDTCPCLIENT(CL: TIFPSPascalCompiler);
+begin
+ with RegClassS(cl, 'TCOMPONENT', 'TIdTCPClientBaseClass') do
+ begin
+ RegisterProperty('BOUNDPORTMAX', 'INTEGER', iptrw);
+ RegisterProperty('BOUNDPORTMIN', 'INTEGER', iptrw);
+ RegisterProperty('BOUNDIP', 'STRING', iptrw);
+ RegisterProperty('BOUNDPORT', 'INTEGER', iptrw);
+ RegisterProperty('HOST', 'STRING', iptrw);
+ RegisterProperty('PORT', 'INTEGER', iptrw);
+ end;
+end;
+
+procedure SIRegisterRODLImports(Cl: TIFPSPascalCompiler);
+begin
+ SIRegisterTIDTCPCLIENT(Cl);
+ SIRegisterTROINDYTCPCHANNEL(Cl);
+ SIRegisterTROINDYHTTPCHANNEL(Cl);
+ SIRegisterTROBINMESSAGE(Cl);
+ //SIRegisterTROSOAPMESSAGE(Cl);
+end;
+
+{ TPSROIndyTCPModule }
+
+class procedure TPSROIndyTCPModule.CompImp(comp: TIFPSPascalCompiler);
+begin
+ SIRegisterTIDTCPCLIENT(Comp);
+ SIRegisterTROINDYTCPCHANNEL(Comp);
+end;
+
+class procedure TPSROIndyTCPModule.ExecImp(exec: TIFPSExec;
+ ri: TIFPSRuntimeClassImporter);
+begin
+ RIRegisterTIDTCPCLIENT(ri);
+ RIRegisterTROINDYTCPCHANNEL(ri);
+end;
+
+{ TPSROIndyHTTPModule }
+
+class procedure TPSROIndyHTTPModule.CompImp(comp: TIFPSPascalCompiler);
+begin
+ if Comp.FindClass('TROINDYTCPCHANNEL') = nil then
+ TPSROIndyTCPModule.CompImp(Comp);
+ SIRegisterTROINDYHTTPCHANNEL(Comp);
+end;
+
+class procedure TPSROIndyHTTPModule.ExecImp(exec: TIFPSExec;
+ ri: TIFPSRuntimeClassImporter);
+begin
+ if ri.FindClass('TROINDYTCPCHANNEL') = nil then
+ TPSROIndyTCPModule.ExecImp(exec, ri);
+ RIRegisterTROINDYHTTPCHANNEL(ri);
+end;
+
+{ TPSROSoapModule }
+
+{class procedure TPSROSoapModule.CompImp(comp: TIFPSPascalCompiler);
+begin
+ SIRegisterTROSOAPMESSAGE(comp);
+end;
+
+class procedure TPSROSoapModule.ExecImp(exec: TIFPSExec;
+ ri: TIFPSRuntimeClassImporter);
+begin
+ RIRegisterTROSOAPMESSAGE(ri);
+end;}
+
+{ TPSROBinModule }
+
+class procedure TPSROBinModule.CompImp(comp: TIFPSPascalCompiler);
+begin
+ SIRegisterTROBINMESSAGE(Comp);
+end;
+
+class procedure TPSROBinModule.ExecImp(exec: TIFPSExec;
+ ri: TIFPSRuntimeClassImporter);
+begin
+ RIRegisterTROBINMESSAGE(ri);
+end;
+
+end.
diff --git a/branches/script-component/Units/PascalScript/uROPSServerLink.pas b/branches/script-component/Units/PascalScript/uROPSServerLink.pas
new file mode 100644
index 0000000..86ff5ef
--- /dev/null
+++ b/branches/script-component/Units/PascalScript/uROPSServerLink.pas
@@ -0,0 +1,1231 @@
+unit uROPSServerLink;
+
+interface
+uses
+ SysUtils, Classes, uPSCompiler, uPSUtils, uPSRuntime,
+ uROServer, uROClient, uRODL{$IFDEF WIN32},
+ Windows{$ELSE}, Types{$ENDIF}, uROTypes, uROClientIntf,
+ uROSerializer, uPSComponent;
+
+type
+
+ TPSROModule = class
+ protected
+ class procedure ExecImp(exec: TPSExec; ri: TPSRuntimeClassImporter); virtual;
+ class procedure CompImp(comp: TPSPascalCompiler); virtual;
+ end;
+ TPSROModuleClass = class of TPSROModule;
+ TPSRemObjectsSdkPlugin = class;
+ TPSROModuleLoadEvent = procedure (Sender: TPSRemObjectsSdkPlugin) of object;
+
+ TPSRemObjectsSdkPlugin = class(TPSPlugin)
+ private
+ FRodl: TRODLLibrary;
+ FModules: TList;
+ FOnLoadModule: TPSROModuleLoadEvent;
+
+ FEnableIndyTCP: Boolean;
+ FEnableIndyHTTP: Boolean;
+ FEnableBinary: Boolean;
+ function GetHaveRodl: Boolean;
+ function MkStructName(Struct: TRODLStruct): string;
+ public
+ procedure CompileImport1(CompExec: TPSScript); override;
+ procedure ExecImport1(CompExec: TPSScript; const ri: TPSRuntimeClassImporter); override;
+ protected
+ procedure Loaded; override;
+ public
+
+ procedure RODLLoadFromFile(const FileName: string);
+
+ procedure RODLLoadFromResource;
+
+ procedure RODLLoadFromStream(S: TStream);
+
+ procedure ClearRodl;
+
+ property HaveRodl: Boolean read GetHaveRodl;
+
+ constructor Create(AOwner: TComponent); override;
+
+ destructor Destroy; override;
+
+
+ procedure ReloadModules;
+
+ procedure RegisterModule(Module: TPSROModuleClass);
+ published
+ property OnLoadModule: TPSROModuleLoadEvent read FOnLoadModule write FOnLoadModule;
+
+ property EnableIndyTCP: Boolean read FEnableIndyTCP write FEnableIndyTCP default true;
+
+ property EnableIndyHTTP: Boolean read FEnableIndyHTTP write FEnableIndyHTTP default true;
+
+ property EnableBinary: Boolean read FEnableBinary write FEnableBinary default true;
+ end;
+
+implementation
+uses
+ uRODLToXML, uROPSImports;
+
+procedure SIRegisterTROTRANSPORTCHANNEL(CL: TPSPascalCompiler);
+Begin
+With cl.AddClassN(cl.FindClass('TComponent'), 'TROTRANSPORTCHANNEL') do
+ begin
+ end;
+end;
+
+procedure SIRegisterTROMESSAGE(CL: TPSPascalCompiler);
+Begin
+With cl.AddClassN(cl.FindClass('TComponent'),'TROMESSAGE') do
+ begin
+ RegisterProperty('MESSAGENAME', 'STRING', iptrw);
+ RegisterProperty('INTERFACENAME', 'STRING', iptrw);
+ end;
+end;
+
+procedure TROMESSAGEINTERFACENAME_W(Self: TROMESSAGE; const T: STRING);
+begin Self.INTERFACENAME := T; end;
+
+procedure TROMESSAGEINTERFACENAME_R(Self: TROMESSAGE; var T: STRING);
+begin T := Self.INTERFACENAME; end;
+
+procedure TROMESSAGEMESSAGENAME_W(Self: TROMESSAGE; const T: STRING);
+begin Self.MESSAGENAME := T; end;
+
+procedure TROMESSAGEMESSAGENAME_R(Self: TROMESSAGE; var T: STRING);
+begin T := Self.MESSAGENAME; end;
+
+procedure RIRegisterTROTRANSPORTCHANNEL(Cl: TPSRuntimeClassImporter);
+Begin
+with Cl.Add(TROTRANSPORTCHANNEL) do
+ begin
+ RegisterVirtualConstructor(@TROTRANSPORTCHANNEL.CREATE, 'CREATE');
+ end;
+end;
+
+procedure RIRegisterTROMESSAGE(Cl: TPSRuntimeClassImporter);
+Begin
+with Cl.Add(TROMESSAGE) do
+ begin
+ RegisterVirtualConstructor(@TROMESSAGE.CREATE, 'CREATE');
+ RegisterPropertyHelper(@TROMESSAGEMESSAGENAME_R,@TROMESSAGEMESSAGENAME_W,'MESSAGENAME');
+ RegisterPropertyHelper(@TROMESSAGEINTERFACENAME_R,@TROMESSAGEINTERFACENAME_W,'INTERFACENAME');
+ end;
+end;
+
+
+(*----------------------------------------------------------------------------*)
+procedure SIRegister_TROBinaryMemoryStream(CL: TPSPascalCompiler);
+begin
+ //with RegClassS(CL,'TMemoryStream', 'TROBinaryMemoryStream') do
+ with CL.AddClassN(CL.FindClass('TMemoryStream'),'TROBinaryMemoryStream') do
+ begin
+ RegisterMethod('Constructor Create2( const iString : Ansistring);');
+ RegisterMethod('Constructor Create;');
+ RegisterMethod('Procedure Assign( iSource : TStream)');
+ RegisterMethod('Function Clone : TROBinaryMemoryStream');
+ RegisterMethod('Procedure LoadFromString( const iString : Ansistring)');
+ RegisterMethod('Procedure LoadFromHexString( const iString : Ansistring)');
+ RegisterMethod('Function ToString : AnsiString');
+ RegisterMethod('Function ToHexString : Ansistring');
+ RegisterMethod('Function ToReadableString : Ansistring');
+ RegisterMethod('Function WriteAnsiString( AString : AnsiString) : integer');
+ RegisterProperty('CapacityIncrement', 'integer', iptrw);
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure SIRegister_uROClasses(CL: TPSPascalCompiler);
+begin
+ SIRegister_TROBinaryMemoryStream(CL);
+end;
+
+(* === run-time registration functions === *)
+(*----------------------------------------------------------------------------*)
+procedure TROBinaryMemoryStreamCapacityIncrement_W(Self: TROBinaryMemoryStream; const T: integer);
+begin Self.CapacityIncrement := T; end;
+
+(*----------------------------------------------------------------------------*)
+procedure TROBinaryMemoryStreamCapacityIncrement_R(Self: TROBinaryMemoryStream; var T: integer);
+begin T := Self.CapacityIncrement; end;
+
+(*----------------------------------------------------------------------------*)
+Function TROBinaryMemoryStreamCreate_P(Self: TClass; CreateNewInstance: Boolean):TObject;
+Begin Result := TROBinaryMemoryStream.Create; END;
+
+(*----------------------------------------------------------------------------*)
+Function TROBinaryMemoryStreamCreate2_P(Self: TClass; CreateNewInstance: Boolean; const iString : Ansistring):TObject;
+Begin Result := TROBinaryMemoryStream.Create(iString); END;
+
+(*----------------------------------------------------------------------------*)
+procedure RIRegister_TROBinaryMemoryStream(CL: TPSRuntimeClassImporter);
+begin
+ with CL.Add(TROBinaryMemoryStream) do
+ begin
+ RegisterConstructor(@TROBinaryMemoryStreamCreate2_P, 'Create2');
+ RegisterConstructor(@TROBinaryMemoryStreamCreate_P, 'Create');
+ RegisterMethod(@TROBinaryMemoryStream.Assign, 'Assign');
+ RegisterMethod(@TROBinaryMemoryStream.Clone, 'Clone');
+ RegisterMethod(@TROBinaryMemoryStream.LoadFromString, 'LoadFromString');
+ RegisterMethod(@TROBinaryMemoryStream.LoadFromHexString, 'LoadFromHexString');
+ RegisterMethod(@TROBinaryMemoryStream.ToString, 'ToString');
+ RegisterMethod(@TROBinaryMemoryStream.ToHexString, 'ToHexString');
+ RegisterMethod(@TROBinaryMemoryStream.ToReadableString, 'ToReadableString');
+ RegisterMethod(@TROBinaryMemoryStream.WriteAnsiString, 'WriteAnsiString');
+ RegisterPropertyHelper(@TROBinaryMemoryStreamCapacityIncrement_R,@TROBinaryMemoryStreamCapacityIncrement_W,'CapacityIncrement');
+ end;
+end;
+
+(*----------------------------------------------------------------------------*)
+procedure RIRegister_uROClasses(CL: TPSRuntimeClassImporter);
+begin
+ RIRegister_TROBinaryMemoryStream(CL);
+end;
+
+
+
+(*----------------------------------------------------------------------------*)
+
+type
+ TRoObjectInstance = class;
+ { }
+ IROClass = interface
+ ['{246B5804-461F-48EC-B2CA-FBB7B69B0D64}']
+ function SLF: TRoObjectInstance;
+ end;
+ TRoObjectInstance = class(TInterfacedObject, IROClass)
+ private
+ FMessage: IROMessage;
+ FChannel: IROTransportChannel;
+ public
+ constructor Create;
+ function SLF: TRoObjectInstance;
+ property Message: IROMessage read FMessage write FMessage;
+ property Channel: IROTransportChannel read FChannel write FChannel;
+ end;
+
+
+
+function CreateProc(Caller: TPSExec; p: PIFProcRec; Global, Stack: TPSStack): Boolean;
+var
+ temp, res: TPSVariantIFC;
+ Chan: TROTransportChannel;
+ Msg: TROMessage;
+ NewRes: TRoObjectInstance;
+begin
+ res := NewTPSVariantIFC(Stack[Stack.count -1], True);
+ if (Res.Dta = nil) or (res.aType.BaseType <> btInterface) then
+ begin
+ Caller.CMD_Err2(erCustomError, 'RO Invoker: Invalid Parameters');
+ Result := False;
+ exit;
+ end;
+ IUnknown(Res.Dta^) := nil;
+
+ NewRes := TRoObjectInstance.Create;
+
+ temp := NewTPSVariantIFC(Stack[Stack.Count -4], True);
+
+ if (temp.aType <> nil) and (temp.Dta <> nil) and (Temp.aType.BaseType = btClass) and (TObject(Temp.Dta^) is TROTransportChannel) then
+ Chan := TROTransportChannel(temp.dta^)
+ else
+ Chan := nil;
+ temp := NewTPSVariantIFC(Stack[Stack.Count -3], True);
+ if (temp.aType <> nil) and (temp.Dta <> nil) and (Temp.aType.BaseType = btClass) and (TObject(Temp.Dta^) is TROMessage) then
+ Msg := TROMessage(temp.dta^)
+ else
+ Msg := nil;
+ if (msg = nil) or (chan = nil) then
+ begin
+ Chan.free;
+ msg.Free;
+
+ NewRes.Free;
+ Result := false;
+ Caller.CMD_Err2(erCustomError, 'Could not create message');
+ exit;
+ end;
+
+ IRoClass(Res.Dta^) := NewRes;
+
+ NewRes.Message := Msg;
+ NewRes.Channel := Chan;
+ Result := True;
+end;
+
+function NilProc(Caller: TPSExec; p: PIFProcRec; Global, Stack: TPSStack): Boolean;
+var
+ n: TPSVariantIFC;
+begin
+ n := NewTPSVariantIFC(Stack[Stack.count -1], True);
+ if (n.Dta = nil) or (n.aType = nil) or (n.aType.BaseType <> btInterface) then
+ begin
+ Caller.CMD_Err2(erCustomError, 'RO Invoker: Cannot free');
+ Result := False;
+ exit;
+ end;
+ IUnknown(n.Dta^) := nil;
+ Result := True;
+end;
+
+type
+ TROStructure = class(TPersistent, IROCustomStreamableType, IROCustomStreamableStruct)
+ private
+ FVar: TPSVariantIFC;
+ FExec: TPSExec;
+ protected
+ function GetTypeName: string;
+ procedure SetTypeName(const s: string);
+ procedure Write(Serializer: TROSerializer; const Name: string);
+ procedure Read(Serializer: TROSerializer; const Name: string);
+ function _AddRef: Integer; stdcall;
+ function _Release: Integer; stdcall;
+ function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
+ function CanImplementType(const aName: string):boolean;
+ procedure SetNull(b: Boolean);
+ function IsNull: Boolean;
+ public
+ constructor Create(aVar: TPSVariantIfc; Exec: TPSExec);
+ end;
+ TROArray = class(TROStructure, IROCustomStreamableType, IROCustomStreamableStruct, IROCustomStreamableArray)
+ protected
+ function GetCount: Longint;
+ procedure SetCount(l: Longint);
+ end;
+
+procedure WriteUserDefined(Exec: TPSExec; const Msg: IROMessage; const Name: string; const n: TPSVariantIfc);
+var
+ obj: TROStructure;
+begin
+ if n.aType.BaseType = btArray then
+ obj := TROArray.Create(n, exec)
+ else if n.aType.BaseType = btRecord then
+ obj := TROStructure.Create(n, exec)
+ else
+ raise Exception.Create('Unknown custom type');
+ try
+ Msg.Write(Name, obj.ClassInfo, obj, []);
+ finally
+ obj.Free;
+ end;
+end;
+
+procedure ReadUserDefined(Exec: TPSExec; const Msg: IROMessage; const Name: string; const n: TPSVariantIfc);
+var
+ obj: TROStructure;
+begin
+ if n.aType.BaseType = btArray then
+ obj := TROArray.Create(n, exec)
+ else if n.aType.BaseType = btRecord then
+ obj := TROStructure.Create(n, exec)
+ else
+ raise Exception.Create('Unknown custom type');
+ try
+ Msg.Read(Name, obj.ClassInfo, obj, []);
+ finally
+ obj.Free;
+ end;
+end;
+
+function RoProc(Caller: TPSExec; p: TIFExternalProcRec; Global, Stack: TIfList): Boolean;
+var
+ s, s2: string;
+ res, n: TPSVariantIFC;
+ aType: TRODataType;
+ aMode: TRODLParamFlag;
+ StartOffset, I: Longint;
+ __request, __response : TMemoryStream;
+ Inst: TRoObjectInstance;
+
+begin
+ s := p.Decl;
+
+ if s[1] = #255 then
+ begin
+ n := NewTPSVariantIFC(Stack[Stack.Count -1], True);
+ res.Dta := nil;
+ res.aType := nil;
+ StartOffset := Stack.Count -2;
+ end
+ else
+ begin
+ n := NewTPSVariantIFC(Stack[Stack.Count -2], True);
+ res := NewTPSVariantIFC(Stack[Stack.Count -1], True);
+ StartOffset := Stack.Count -3;
+ end;
+
+ if (n.Dta = nil) or (N.aType = nil) or (n.aType.BaseType <> btInterface) or (Longint(n.Dta^) = 0) then
+ begin
+ Caller.CMD_Err2(erCustomError, 'RO Invoker: Invalid Parameters');
+ Result := False;
+ exit;
+ end;
+
+ Inst := IROClass(n.dta^).Slf;
+ Delete(s, 1, 1);
+ i := StartOffset;
+ try
+ Inst.SLF.Message.InitializeRequestMessage(Inst.Channel, '', Copy(p.Name,1,pos('.', p.Name) -1), Copy(p.Name, pos('.', p.Name)+1, MaxInt));
+ while Length(s) > 0 do
+ begin
+ s2 := copy(s, 2, ord(s[1]));
+ aMode := TRODLParamFlag(ord(s[length(s2)+2]));
+ aType := TRODataType(ord(s[length(s2)+3]));
+ Delete(s, 1, length(s2)+3);
+ n := NewTPSVariantIFC(Stack[i], True);
+ Dec(I);
+ if ((aMode = fIn) or (aMode = fInOut)) and (n.Dta <> nil) then
+ begin
+ case aType of
+ rtInteger: Inst.Message.Write(s2, TypeInfo(Integer), Integer(n.Dta^), []);
+ rtDateTime: Inst.Message.Write(s2, TypeInfo(DateTime), Double(n.Dta^), []);
+ rtDouble: Inst.Message.Write(s2, TypeInfo(Double), Double(n.Dta^), []);
+ rtCurrency: Inst.Message.Write(s2, TypeInfo(Double), Double(n.Dta^), []);
+ rtWideString: Inst.Message.Write(s2, TypeInfo(WideString), WideString(n.Dta^), []);
+ rtString: Inst.Message.Write(s2, TypeInfo(String), String(n.Dta^), []);
+ rtInt64: Inst.Message.Write(s2, TypeInfo(Int64), Int64(n.Dta^), []);
+ rtBoolean: Inst.Message.Write(s2, TypeInfo(Boolean), Byte(n.Dta^), []);
+ rtUserDefined: WriteUserDefined(Caller, Inst.Message, s2, n);
+ end;
+ end;
+ end;
+ __request := TMemoryStream.Create;
+ __response := TMemoryStream.Create;
+ try
+ Inst.Message.WriteToStream(__request);
+ Inst.Channel.Dispatch(__request, __response);
+ Inst.Message.ReadFromStream(__response);
+ finally
+ __request.Free;
+ __response.Free;
+ end;
+ s := p.Decl;
+ Delete(s, 1, 1);
+ i := StartOffset;
+ while Length(s) > 0 do
+ begin
+ s2 := copy(s, 2, ord(s[1]));
+ aMode := TRODLParamFlag(ord(s[length(s2)+2]));
+ aType := TRODataType(ord(s[length(s2)+3]));
+ Delete(s, 1, length(s2)+3);
+ n := NewTPSVariantIFC(Stack[i], True);
+ Dec(I);
+ if ((aMode = fOut) or (aMode = fInOut)) and (n.Dta <> nil) then
+ begin
+ case aType of
+ rtInteger: Inst.Message.Read(s2, TypeInfo(Integer), Longint(n.Dta^), []);
+ rtDateTime: Inst.Message.Read(s2, TypeInfo(DateTime), double(n.dta^), []);
+ rtDouble: Inst.Message.Read(s2, TypeInfo(Double), double(n.dta^), []);
+ rtCurrency: Inst.Message.Read(s2, TypeInfo(Double), double(n.dta^), []);
+ rtWideString: Inst.Message.Read(s2, TypeInfo(WideString), widestring(n.Dta^), []);
+ rtString: Inst.Message.Read(s2, TypeInfo(String), string(n.dta^), []);
+ rtInt64: Inst.Message.Read(s2, TypeInfo(Int64), Int64(n.Dta^), []);
+ rtBoolean: Inst.Message.Read(s2, TypeInfo(Boolean), Boolean(n.Dta^), []);
+ rtUserDefined: ReadUserDefined(Caller, Inst.Message, s2, n);
+ end;
+ end;
+ end;
+ aType := TRODataType(p.Decl[1]);
+ case aType of
+ rtInteger: Inst.Message.Read('Result', TypeInfo(Integer), Longint(res.Dta^), []);
+ rtDateTime: Inst.Message.Read('Result', TypeInfo(DateTime), Double(res.dta^), []);
+ rtDouble: Inst.Message.Read('Result', TypeInfo(Double), Double(res.Dta^), []);
+ rtCurrency: Inst.Message.Read('Result', TypeInfo(Double), double(res.Dta^), []);
+ rtWideString: Inst.Message.Read('Result', TypeInfo(WideString), WideString(res.Dta^), []);
+ rtString: Inst.Message.Read('Result', TypeInfo(String), String(res.Dta^), []);
+ rtInt64: Inst.Message.Read('Result', TypeInfo(Int64), Int64(res.dta^), []);
+ rtBoolean: Inst.Message.Read('Result', TypeInfo(Boolean), Boolean(res.dta^), []);
+ rtUserDefined: ReadUserDefined(Caller, Inst.Message, 'Result', res);
+ end;
+ except
+ on e: Exception do
+ begin
+ Caller.CMD_Err2(erCustomError, e.Message);
+ Result := False;
+ exit;
+ end;
+ end;
+ Result := True;
+end;
+
+function SProcImport(Sender: TPSExec; p: TIFExternalProcRec; Tag: Pointer): Boolean;
+var
+ s: string;
+begin
+ s := p.Decl;
+ Delete(s, 1, pos(':', s));
+ if s[1] = '-' then
+ p.ProcPtr := @NilProc
+ else if s[1] = '!' then
+ begin
+ P.ProcPtr := @CreateProc;
+ p.Decl := Copy(s, 2, MaxInt);
+ end else
+ begin
+ Delete(s, 1, 1);
+ p.Name := Copy(S,1,pos('!', s)-1);
+ Delete(s, 1, pos('!', s));
+ p.Decl := s;
+ p.ProcPtr := @RoProc;
+ end;
+ Result := True;
+end;
+
+
+type
+ TMYComp = class(TPSPascalCompiler);
+ TRoClass = class(TPSExternalClass)
+ private
+ FService: TRODLService;
+ FNilProcNo: Cardinal;
+ FCompProcno: Cardinal;
+ function CreateParameterString(l: TRODLOperation): string;
+ function GetDT(DataType: string): TRODataType;
+ procedure MakeDeclFor(Dest: TPSParametersDecl; l: TRODLOperation);
+ public
+ constructor Create(Se: TPSPascalCompiler; Service: TRODLService; Const Typeno: TPSType);
+
+ function SelfType: TPSType; override;
+ function Func_Find(const Name: tbtstring; var Index: Cardinal): Boolean; override;
+ function Func_Call(Index: Cardinal; var ProcNo: Cardinal): Boolean; override;
+ function SetNil(var ProcNo: Cardinal): Boolean; override;
+
+ function ClassFunc_Find(const Name: tbtstring; var Index: Cardinal): Boolean; override;
+ function ClassFunc_Call(Index: Cardinal; var ProcNo: Cardinal): Boolean; override;
+ function IsCompatibleWith(Cl: TPSExternalClass): Boolean; override;
+ end;
+
+{ TROPSLink }
+procedure TPSRemObjectsSdkPlugin.RODLLoadFromFile(const FileName: string);
+var
+ f: TFileStream;
+begin
+ f := TFileStream.Create(FileName, fmOpenRead or fmShareDenyNone);
+ try
+ RODLLoadFromStream(f);
+ finally
+ f.Free;
+ end;
+end;
+
+procedure TPSRemObjectsSdkPlugin.RODLLoadFromResource;
+var
+ rs: TResourceStream;
+begin
+ rs := TResourceStream.Create(HInstance, 'RODLFILE', RT_RCDATA);
+ try
+ RODLLoadFromStream(rs);
+ finally
+ rs.Free;
+ end;
+end;
+
+procedure TPSRemObjectsSdkPlugin.RODLLoadFromStream(S: TStream);
+begin
+ FreeAndNil(FRodl);
+ with TXMLToRODL.Create do
+ begin
+ try
+ FRodl := Read(S);
+ finally
+ Free;
+ end;
+ end;
+end;
+
+
+destructor TPSRemObjectsSdkPlugin.Destroy;
+begin
+ FreeAndNil(FRodl);
+ FModules.Free;
+ inherited Destroy;
+end;
+
+{ TRoClass }
+
+constructor TRoClass.Create(Se: TPSPascalCompiler; Service: TRODLService; Const Typeno: TPSType);
+begin
+ inherited Create(SE, TypeNo);
+ FService := Service;
+ FNilProcNo := Cardinal(-1);
+ FCompProcNo := Cardinal(-1);
+end;
+
+function TRoClass.GetDT(DataType: string): TRODataType;
+begin
+ DataType := LowerCase(DataType);
+ if DataType = 'integer' then
+ Result := rtInteger
+ else if DataType = 'datetime' then
+ Result := rtDateTime
+ else if DataType = 'double' then
+ Result := rtDouble
+ else if DataType = 'currency' then
+ Result := rtCurrency
+ else if DataType = 'widestring' then
+ Result := rtWidestring
+ else if DataType = 'string' then
+ Result := rtString
+ else if DataType = 'int64' then
+ Result := rtInt64
+ else if DataType = 'boolean' then
+ Result := rtBoolean
+ else if DataType = 'variant' then
+ Result := rtVariant
+ else if DataType = 'binary' then
+ Result := rtBinary
+ else
+ Result := rtUserDefined;
+end;
+
+function TRoClass.CreateParameterString(l: TRODLOperation): string;
+var
+ i: Longint;
+begin
+ if L.Result = nil then
+ begin
+ Result := #$FF;
+ end else
+ begin
+ Result := Chr(Ord(GetDT(l.Result.DataType)));
+ end;
+ for i := 0 to l.Count -1 do
+ begin
+ if l.Items[i].Flag = fResult then Continue;
+ Result := Result + Chr(Length(l.Items[i].Info.Name))+ l.Items[i].Info.Name + Chr(Ord(l.Items[i].Flag)) + Chr(Ord(GetDT(l.Items[i].DataType)));
+ end;
+end;
+
+procedure TRoClass.MakeDeclFor(Dest: TPSParametersDecl; l: TRODLOperation);
+var
+ i: Longint;
+ dd: TPSParameterDecl;
+begin
+ if l.Result <> nil then
+ begin
+ Dest.Result := TMyComp(SE).at2ut(SE.FindType(l.Result.DataType));
+ end;
+ for i := 0 to l.Count -1 do
+ begin
+ if l.Items[i].Flag = fResult then Continue;
+ dd := Dest.AddParam;
+ if l.Items[i].Flag = fIn then
+ dd.mode := pmIn
+ else
+ dd.Mode := pmInOut;
+ dd.OrgName := l.Items[i].Info.Name;
+ dd.aType := TMyComp(SE).at2ut(SE.FindType(l.Items[i].DataType));
+ end;
+end;
+
+function TRoClass.Func_Call(Index: Cardinal; var ProcNo: Cardinal): Boolean;
+var
+ h, i: Longint;
+ s, e: string;
+ P: TPSProcedure;
+ p2: TPSExternalProcedure;
+begin
+ s := 'roclass:_'+FService.Info.Name + '.' + FService.Default.Items[Index].Info.Name;
+ h := MakeHash(s);
+ for i := 0 to TMyComp(SE).FProcs.Count -1 do
+ begin
+ P := TMyComp(SE).FProcs[i];
+ if (p is TPSExternalProcedure) then
+ begin
+ p2 := TPSExternalProcedure(p);
+ if (p2.RegProc.NameHash = h) and (Copy(p2.RegProc.ImportDecl, 1, pos(tbtchar('!'), p2.RegProc.ImportDecl)) = s) then
+ begin
+ Procno := I;
+ Result := True;
+ Exit;
+ end;
+ end;
+ end;
+ e := CreateParameterString(FService.Default.Items[Index]);
+ s := s + '!' + e;
+ ProcNo := TMyComp(SE).AddUsedFunction2(P2);
+ p2.RegProc := TPSRegProc.Create;
+ TMYComp(SE).FRegProcs.Add(p2.RegProc);
+ p2.RegProc.Name := '';
+ p2.RegProc.ExportName := True;
+ MakeDeclFor(p2.RegProc.Decl, FService.Default.Items[Index]);
+ p2.RegProc.ImportDecl := s;
+ Result := True;
+end;
+
+function TRoClass.Func_Find(const Name: tbtstring; var Index: Cardinal): Boolean;
+var
+ i: Longint;
+begin
+ for i := 0 to FService.Default.Count -1 do
+ begin
+ if CompareText(FService.Default.Items[i].Info.Name, Name) = 0 then
+ begin
+ Index := i;
+ Result := True;
+ Exit;
+ end;
+ end;
+ Result := False;
+end;
+
+const
+ PSClassType = '!ROClass';
+ MyGuid: TGuid = '{CADCCF37-7FA0-452E-971D-65DA691F7648}';
+
+function TRoClass.SelfType: TPSType;
+begin
+ Result := SE.FindType(PSClassType);
+ if Result = nil then
+ begin
+ Result := se.AddInterface(se.FindInterface('IUnknown'), MyGuid, PSClassType).aType;
+ end;
+end;
+
+function TRoClass.SetNil(var ProcNo: Cardinal): Boolean;
+var
+ P: TPSExternalProcedure;
+begin
+ if FNilProcNo <> Cardinal(-1) then
+ ProcNo:= FNilProcNo
+ else
+ begin
+ ProcNo := TMyComp(SE).AddUsedFunction2(P);
+ p.RegProc := TPSRegProc.Create;
+ TMyComp(SE).FRegProcs.Add(p.RegProc);
+ p.RegProc.Name := '';
+ p.RegProc.ExportName := True;
+ with p.RegProc.Decl.AddParam do
+ begin
+ OrgName := 'VarNo';
+ aType := TMYComp(Se).at2ut(SelfType);
+ end;
+ p.RegProc.ImportDecl := 'roclass:-';
+ FNilProcNo := Procno;
+ end;
+ Result := True;
+end;
+
+function TRoClass.ClassFunc_Call(Index: Cardinal;
+ var ProcNo: Cardinal): Boolean;
+var
+ P: TPSExternalProcedure;
+begin
+ if FCompProcNo <> Cardinal(-1) then
+ begin
+ Procno := FCompProcNo;
+ Result := True;
+ Exit;
+ end;
+ ProcNo := TMyComp(SE).AddUsedFunction2(P);
+ p.RegProc := TPSRegProc.Create;
+ TMyComp(SE).FRegProcs.Add(p.RegProc);
+ p.RegProc.ExportName := True;
+ p.RegProc.Decl.Result := TMyComp(SE).at2ut(SelfType);
+ with p.RegProc.Decl.AddParam do
+ begin
+ Orgname := 'Message';
+ aType :=TMyComp(SE).at2ut(SE.FindType('TROMESSAGE'));
+ end;
+ with p.RegProc.Decl.AddParam do
+ begin
+ Orgname := 'Channel';
+ aType :=TMyComp(SE).at2ut(SE.FindType('TROTRANSPORTCHANNEL'));
+ end;
+ p.RegProc.ImportDecl := 'roclass:!';
+ FCompProcNo := Procno;
+ Result := True;
+end;
+
+function TRoClass.ClassFunc_Find(const Name: tbtstring;
+ var Index: Cardinal): Boolean;
+begin
+ if Name = 'CREATE' then
+ begin
+ Result := True;
+ Index := 0;
+ end else
+ result := False;
+end;
+
+function TRoClass.IsCompatibleWith(Cl: TPSExternalClass): Boolean;
+begin
+ Result := Cl is TRoClass;
+end;
+
+{ TRoObjectInstance }
+
+function TRoObjectInstance.SLF: TRoObjectInstance;
+begin
+ Result := Self;
+end;
+
+constructor TRoObjectInstance.Create;
+begin
+ FRefCount := 1;
+end;
+
+
+function TPSRemObjectsSdkPlugin.MkStructName(Struct: TRODLStruct): string;
+var
+ i: Longint;
+begin
+ Result := '!ROStruct!'+Struct.Info.Name+ ',';
+ for i := 0 to Struct.Count -1 do
+ begin
+ Result := Result + Struct.Items[i].Info.Name+ ',';
+ end;
+end;
+
+function CompareStructItem(const S1, S2: TRODLTypedEntity): Integer;
+begin
+ Result := CompareText(S1.Info.Name, S2.Info.Name);
+end;
+
+procedure SortStruct(struct: TRODLStruct; First, Last: Longint);
+var
+ l, r, Pivot: Integer;
+begin
+ while First < Last do
+ begin
+ Pivot := (First + Last) div 2;
+ l := First - 1;
+ r := Last + 1;
+ repeat
+ repeat inc(l); until CompareStructItem(Struct.Items[l], Struct.Items[Pivot]) >= 0;
+ repeat dec(r); until CompareStructItem(Struct.Items[r], Struct.Items[Pivot]) <= 0;
+ if l >= r then break;
+ Struct.Exchange(l, r);
+ until false;
+ if First < r then SortStruct(Struct, First, r);
+ First := r+1;
+ end;
+end;
+
+procedure TPSRemObjectsSdkPlugin.CompileImport1(CompExec: TPSScript);
+var
+ i, i1: Longint;
+ Enum: TRODLEnum;
+ TempType: TPSType;
+ Struct: TRODLStruct;
+ Arr: TRODLArray;
+ RecType: TPSRecordFieldTypeDef;
+ Service: TRODLService;
+begin
+ if FRODL = nil then exit;
+ if CompExec.Comp.FindType('TDateTime') = nil then
+ raise Exception.Create('Please register the DateUtils library first');
+ if CompExec.Comp.FindType('TStream') = nil then
+ raise Exception.Create('Please register the sysutils/classes library first');
+ SIRegisterTROTRANSPORTCHANNEL(CompExec.Comp);
+ SIRegisterTROMESSAGE(CompExec.Comp);
+ SIRegister_uROClasses(CompExec.Comp);
+ CompExec.Comp.AddTypeCopyN('Binary', 'TROBinaryMemoryStream');
+ if CompExec.Comp.FindType('DateTime') = nil then
+ CompExec.Comp.AddTypeCopyN('DateTime', 'TDateTime');
+ if CompExec.Comp.FindType('Currency') = nil then
+ CompExec.Comp.AddTypeCopyN('Currency', 'Double'); // for now
+ for i := 0 to FRodl.EnumCount -1 do
+ begin
+ Enum := FRodl.Enums[i];
+ TempType := CompExec.Comp.AddType(Enum.Info.Name, btEnum);
+ for i1 := 0 to Enum.Count -1 do
+ begin
+ CompExec.Comp.AddConstant(Enum.Items[i1].Info.Name, TempType).SetUInt(i1);
+ end;
+ end;
+ for i := 0 to FRodl.StructCount -1 do
+ begin
+ Struct := FRodl.Structs[i];
+ SortStruct(Struct, 0, Struct.Count-1);
+ TempType := CompExec.Comp.AddType('', btRecord);
+ TempType.ExportName := True;
+ TempType.Name := MkStructName(Struct);
+ for i1 := 0 to Struct.Count -1 do
+ begin
+ RecType := TPSRecordType(TempType).AddRecVal;
+ RecType.FieldOrgName := Struct.Items[i1].Info.Name;
+ RecType.aType := CompExec.Comp.FindType(Struct.Items[i1].DataType);
+ if RecType.aType = nil then begin
+ Arr := fRodl.FindArray(Struct.Items[i1].DataType);
+ if Arr <> nil then begin
+ RecType.aType := CompExec.Comp.AddType(Arr.Info.Name, btArray);
+ TPSArrayType(RecType.aType).ArrayTypeNo := CompExec.Comp.FindType(Arr.ElementType);
+ end;
+ end;
+ end;
+ CompExec.Comp.AddTypeCopy(Struct.Info.Name, TempType);
+ end;
+ for i := 0 to FRodl.ArrayCount -1 do
+ begin
+ Arr := FRodl.Arrays[i];
+ TempType := CompExec.Comp.FindType(Arr.Info.Name);
+ if TempType <> nil then begin
+ if not (TempType is TPSArrayType) then begin
+ CompExec.Comp.MakeError('ROPS', ecDuplicateIdentifier, Arr.Info.Name);
+ end;
+ end else begin
+ TempType := CompExec.Comp.AddType(Arr.Info.Name, btArray);
+ end;
+ TPSArrayType(TempType).ArrayTypeNo := CompExec.Comp.FindType(Arr.ElementType);
+ end;
+ for i := 0 to FRodl.ServiceCount -1 do
+ begin
+ Service := FRodl.Services[i];
+ TempType := CompExec.Comp.AddType(Service.Info.Name, btExtClass);
+ TPSUndefinedClassType(TempType).ExtClass := TRoClass.Create(CompExec.Comp, Service, TempType);
+ end;
+ for i := 0 to FModules.Count -1 do
+ TPSROModuleClass(FModules[i]).CompImp(CompExec.Comp);
+end;
+
+function TPSRemObjectsSdkPlugin.GetHaveRodl: Boolean;
+begin
+ Result := FRodl <> nil;
+end;
+
+procedure TPSRemObjectsSdkPlugin.ClearRodl;
+begin
+ FRodl.Free;
+ FRodl := nil;
+end;
+
+procedure TPSRemObjectsSdkPlugin.ExecImport1(CompExec: TPSScript;
+ const ri: TPSRuntimeClassImporter);
+var
+ i: Longint;
+begin
+ if FRODL = nil then exit;
+ CompExec.Exec.AddSpecialProcImport('roclass', SProcImport, nil);
+ RIRegisterTROTRANSPORTCHANNEL(ri);
+ RIRegisterTROMESSAGE(ri);
+ RIRegister_TROBinaryMemoryStream(ri);
+ for i := 0 to FModules.Count -1 do
+ TPSROModuleClass(FModules[i]).ExecImp(CompExec.Exec, ri);
+end;
+
+constructor TPSRemObjectsSdkPlugin.Create(AOwner: TComponent);
+begin
+ inherited Create(AOwner);
+ FModules := TList.Create;
+ //FEnableSOAP := True;
+ FEnableBinary := True;
+ FEnableIndyTCP := True;
+ FEnableIndyHTTP := True;
+end;
+
+procedure TPSRemObjectsSdkPlugin.Loaded;
+begin
+ inherited Loaded;
+ ReloadModules;
+end;
+
+procedure TPSRemObjectsSdkPlugin.RegisterModule(
+ Module: TPSROModuleClass);
+begin
+ FModules.Add(Module);
+end;
+
+procedure TPSRemObjectsSdkPlugin.ReloadModules;
+begin
+ FModules.Clear;
+ if FEnableIndyTCP then RegisterModule(TPSROIndyTCPModule);
+ if FEnableIndyHTTP then RegisterModule(TPSROIndyHTTPModule);
+ //if FEnableSOAP then RegisterModule(TPSROSoapModule);
+ if FEnableBinary then RegisterModule(TPSROBinModule);
+ if assigned(FOnLoadModule) then
+ FOnLoadModule(Self);
+end;
+
+{ TPSROModule }
+
+class procedure TPSROModule.CompImp(comp: TPSPascalCompiler);
+begin
+ // do nothing
+end;
+
+class procedure TPSROModule.ExecImp(exec: TPSExec;
+ ri: TPSRuntimeClassImporter);
+begin
+ // do nothing
+end;
+
+procedure IntRead(Exec: TPSExec; Serializer: TROSerializer;
+ const Name: string; aVar: TPSVariantIFC; arridx: Longint);
+var
+ i: Longint;
+ s, s2: string;
+ r: TROStructure;
+begin
+ case aVar.aType.BaseType of
+ btS64: Serializer.Read(Name, TypeInfo(int64), Int64(avar.Dta^), arridx);
+ btu32: Serializer.Read(Name, TypeInfo(cardinal), Cardinal(avar.Dta^), arridx);
+ bts32: Serializer.Read(Name, TypeInfo(longint), Longint(avar.Dta^), arridx);
+ btu16: Serializer.Read(Name, TypeInfo(word), Word(aVar.Dta^), arridx);
+ btS16: Serializer.Read(Name, TypeInfo(smallint), Smallint(aVar.Dta^), arridx);
+ btu8: Serializer.Read(Name, TypeInfo(byte), Byte(aVar.Dta^), arridx);
+ btS8: Serializer.Read(Name, TypeInfo(shortint), Shortint(aVar.Dta^), arridx);
+ btDouble:
+ begin
+ if aVar.aType.ExportName = 'TDATETIME' then
+ Serializer.Read(Name, TypeInfo(datetime), Double(avar.Dta^), arridx)
+ else
+ Serializer.Read(Name, TypeInfo(double), Double(aVar.Dta^), arridx);
+ end;
+ btSingle: Serializer.Read(Name, TypeInfo(single), Single(avar.Dta^), arridx);
+ btExtended: Serializer.Read(Name, TypeInfo(extended), Extended(avar.dta^), arridx);
+ btWideString: Serializer.Read(Name, TypeInfo(widestring), widestring(avar.dta^), arridx);
+ btString: Serializer.Read(Name, TypeInfo(string), string(avar.dta^), arridx);
+ btArray:
+ begin
+ if (TPSTypeRec_Array(avar.aType).ArrayType.BaseType = btRecord) then
+ begin
+ for i := 0 to PSDynArrayGetLength(Pointer(aVar.Dta^), aVar.aType) -1 do
+ begin
+ r := TROStructure.Create(PSGetArrayField(avar, i), Exec);
+ try
+ Serializer.Read(Name, typeinfo(TROArray), r, i);
+ finally
+ r.Free;
+ end;
+ end;
+ end else if (TPSTypeRec_Array(avar.aType).ArrayType.BaseType = btArray) then
+ begin
+ for i := 0 to PSDynArrayGetLength(Pointer(aVar.Dta^), aVar.aType) -1 do
+ begin
+ r := TROArray.Create(PSGetArrayField(avar, i), Exec);
+ try
+ Serializer.Read(Name, typeinfo(TROArray), r, i);
+ finally
+ r.Free;
+ end;
+ end;
+ end else begin
+ for i := 0 to PSDynArrayGetLength(Pointer(aVar.Dta^), aVar.aType) -1 do
+ begin
+ IntRead(Exec, Serializer, Name, PSGetArrayField(avar, i), i);
+ end;
+ end;
+ end;
+ btRecord:
+ begin
+ s := avar.aType.ExportName;
+ if copy(s,1, 10) <> '!ROStruct!' then
+ raise Exception.Create('Invalid structure: '+s);
+ Delete(s,1,pos(',',s));
+ for i := 0 to TPSTypeRec_Record(aVar.aType).FieldTypes.Count -1 do
+ begin
+ s2 := copy(s,1,pos(',',s)-1);
+ delete(s,1,pos(',',s));
+ if (TPSTypeRec(TPSTypeRec_Record(aVar.aType).FieldTypes[i]).BaseType = btRecord) then
+ begin
+
+ r := TROStructure.Create(PSGetRecField(aVar, i), Exec);
+ try
+ Serializer.Read(s2, typeinfo(TROStructure), r, -1);
+ finally
+ r.Free;
+ end;
+ end else if (TPSTypeRec(TPSTypeRec_Record(aVar.aType).FieldTypes[i]).BaseType = btArray) then
+ begin
+ r := TROArray.Create(PSGetRecField(aVar, i), Exec);
+ try
+ Serializer.Read(s2, typeinfo(TROArray), r, -1);
+ finally
+ r.Free;
+ end;
+ end else
+ IntRead(Exec, Serializer, s2, PSGetRecField(aVar, i), -1);
+ end;
+ end;
+ else
+ raise Exception.Create('Unable to read type');
+
+ end;
+end;
+
+procedure IntWrite(Exec: TPSExec; Serializer: TROSerializer;
+ const Name: string; aVar: TPSVariantIFC; arridx: Longint);
+var
+ i: Longint;
+ s, s2: string;
+ r: TROStructure;
+begin
+ case aVar.aType.BaseType of
+ btS64: Serializer.Write(Name, TypeInfo(int64), Int64(avar.Dta^), arridx);
+ btu32: Serializer.Write(Name, TypeInfo(cardinal), Cardinal(avar.Dta^), arridx);
+ bts32: Serializer.Write(Name, TypeInfo(longint), Longint(avar.Dta^), arridx);
+ btu16: Serializer.Write(Name, TypeInfo(word), Word(avar.Dta^), arridx);
+ btS16: Serializer.Write(Name, TypeInfo(smallint), Smallint(aVar.Dta^), arridx);
+ btu8: Serializer.Write(Name, TypeInfo(byte), Byte(aVar.Dta^), arridx);
+ btS8: Serializer.Write(Name, TypeInfo(shortint), ShortInt(aVar.Dta^), arridx);
+ btDouble:
+ begin
+ if aVar.aType.ExportName = 'TDATETIME' then
+ Serializer.Write(Name, TypeInfo(datetime), Double(aVar.Dta^), arridx)
+ else
+ Serializer.Write(Name, TypeInfo(double), Double(aVar.Dta^), arridx);
+ end;
+ btSingle: Serializer.Write(Name, TypeInfo(single), Single(aVar.Dta^), arridx);
+ btExtended: Serializer.Write(Name, TypeInfo(extended), Extended(aVar.Dta^), arridx);
+ btWideString: Serializer.Write(Name, TypeInfo(widestring), WideString(aVar.Dta^), arridx);
+ btString: Serializer.Write(Name, TypeInfo(string), String(aVar.Dta^), arridx);
+ btArray:
+ begin
+ if (TPSTypeRec_Array(avar.aType).ArrayType.BaseType = btRecord) then
+ begin
+ for i := 0 to PSDynArrayGetLength(Pointer(aVar.Dta^), aVar.aType) -1 do
+ begin
+ r := TROStructure.Create(PSGetArrayField(aVar, i), Exec);
+ try
+ Serializer.Write(Name, typeinfo(TROArray), r, i);
+ finally
+ r.Free;
+ end;
+ end;
+ end else if (TPSTypeRec_Array(avar.aType).ArrayType.BaseType = btArray) then
+ begin
+ for i := 0 to PSDynArrayGetLength(Pointer(aVar.Dta^), aVar.aType) -1 do
+ begin
+ r := TROArray.Create(PSGetArrayField(aVar, i), Exec);
+ try
+ Serializer.Write(Name, typeinfo(TROArray), r, i);
+ finally
+ r.Free;
+ end;
+ end;
+ end else begin
+ for i := 0 to PSDynArrayGetLength(Pointer(aVar.Dta^), aVar.aType) -1 do
+ begin
+ IntWrite(Exec, Serializer, Name, PSGetArrayField(aVar, i), i);
+ end;
+ end;
+ end;
+ btRecord:
+ begin
+ s := avar.aType.ExportName;
+ if copy(s,1, 10) <> '!ROStruct!' then
+ raise Exception.Create('Invalid structure: '+s);
+ Delete(s,1,pos(',',s));
+ for i := 0 to TPSTypeRec_Record(aVar.aType).FieldTypes.Count -1 do
+ begin
+ s2 := copy(s,1,pos(',',s)-1);
+ delete(s,1,pos(',',s));
+ if (TPSTypeRec(TPSTypeRec_Record(aVar.aType).FieldTypes[i]).BaseType = btRecord) then
+ begin
+ r := TROStructure.Create(PSGetRecField(aVar, i), Exec);
+ try
+ Serializer.Write(s2, typeinfo(TROStructure), r, -1);
+ finally
+ r.Free;
+ end;
+ end else if (TPSTypeRec(TPSTypeRec_Record(aVar.aType).FieldTypes[i]).BaseType = btArray) then
+ begin
+ r := TROArray.Create(PSGetRecField(aVar, i), Exec);
+ try
+ Serializer.Write(s2, typeinfo(TROArray), r, -1);
+ finally
+ r.Free;
+ end;
+ end else
+ IntWrite(Exec, Serializer, s2, PSGetRecField(aVar, i), -1);
+ end;
+ end;
+ else
+ raise Exception.Create('Unable to read type');
+
+ end;
+end;
+
+{ TROStructure }
+
+constructor TROStructure.Create(aVar: TPSVariantIfc; Exec: TPSExec);
+begin
+ inherited Create;
+ FVar := aVar;
+ FExec := Exec;
+end;
+
+function TROStructure.IsNull: Boolean;
+begin
+ Result := False;
+end;
+
+function TROStructure.QueryInterface(const IID: TGUID;
+ out Obj): HResult;
+begin
+ if GetInterface(IID, Obj) then
+ Result := 0
+ else
+ Result := E_NOINTERFACE;
+end;
+
+procedure TROStructure.Read(Serializer: TROSerializer;
+ const Name: string);
+begin
+ IntRead(FExec, Serializer, Name, FVar, -1);
+end;
+
+procedure TROStructure.SetNull(b: Boolean);
+begin
+ // null not supported
+end;
+
+function TROStructure.GetTypeName: string;
+var
+ s: string;
+begin
+ s := fvar.atype.ExportName;
+ delete(s,1,1);
+ delete(s,1,pos('!', s));
+ result := copy(s,1,pos(',',s)-1);
+end;
+
+procedure TROStructure.Write(Serializer: TROSerializer;
+ const Name: string);
+begin
+ IntWrite(FExec, Serializer, Name, FVar, -1);
+end;
+
+
+function TROStructure._AddRef: Integer;
+begin
+ // do nothing
+ Result := 1;
+end;
+
+function TROStructure._Release: Integer;
+begin
+ // do nothing
+ Result := 1;
+end;
+
+function TROStructure.CanImplementType(const aName: string): boolean;
+begin
+ if SameText(aName, Self.GetTypeName) then
+ Result := True
+ else
+ Result := False;
+end;
+
+procedure TROStructure.SetTypeName(const s: string);
+begin
+ // Do nothing
+end;
+
+{ TROArray }
+
+function TROArray.GetCount: Longint;
+begin
+
+ // we should have an array in pVar now so assume that's true
+ Result := PSDynArrayGetLength(Pointer(fVar.Dta^), fvar.aType);
+end;
+
+procedure TROArray.SetCount(l: Integer);
+begin
+ PSDynArraySetLength(Pointer(fVAr.Dta^), fVar.aType, l);
+end;
+
+end.
diff --git a/branches/script-component/Units/PascalScript/x64.inc b/branches/script-component/Units/PascalScript/x64.inc
new file mode 100644
index 0000000..edc0dd9
--- /dev/null
+++ b/branches/script-component/Units/PascalScript/x64.inc
@@ -0,0 +1,667 @@
+{ implementation of x64 abi }
+//procedure DebugBreak; external 'Kernel32.dll';
+const
+ EmptyPchar: array[0..0] of char = #0;
+{$ASMMODE INTEL}
+
+{$IFDEF WINDOWS}
+procedure x64call(
+ Address: Pointer;
+ out _RAX: IPointer;
+ _RCX, _RDX, _R8, _R9: IPointer;
+ var _XMM0: Double;
+ _XMM1, _XMM2, _XMM3: Double;
+ aStack: Pointer; aItems: Integer); assembler; nostackframe;
+asm
+(* Registers:
+ RCX: Address
+ RDX: *_RAX
+ R8: _RCX
+ R9: _RDX
+
+ fpc inserts an 20h emty space
+*)
+ push rbp
+ mov rbp,rsp
+// call debugbreak
+ push rcx // address
+ push rdx // _rax
+ push r8 // _rcx
+ push r9 // _rdx
+ mov rcx, aItems
+ mov rdx, aStack
+ jmp @compareitems
+@work:
+ push [rdx]
+ dec rcx
+ sub rdx,8
+@compareitems:
+ or rcx, rcx
+ jnz @work
+
+ // copy registers
+ movd xmm0,[_XMM0]
+ movd xmm1,_XMM1
+ movd xmm2,_XMM2
+ movd xmm3,_XMM3
+ mov RAX, [rbp-8]
+ mov RCX, [rbp-24]
+ mov RDX, [rbp-32]
+ mov R8, _R8
+ mov R9, _R9
+
+ // weird thing on windows, it needs 32 bytes in the CALLEE side to do whatever in
+ sub RSP, 32
+
+ call RAX
+
+ add RSP, 32 // undo the damage done earlier
+
+ // copy result back
+ mov RDX, [rbp-16]
+ mov [RDX], RAX
+ movd [_XMM0],xmm0
+
+ pop r9
+ pop r8
+ pop rdx
+ pop rcx
+ leave
+ ret
+end;
+{$ELSE}
+type
+ TRegisters = packed record
+ _RDI, // 0
+ _RSI, // 8
+ _RDX, // 16
+ _RCX, // 24
+ _R8, // 32
+ _R9: IPointer; // 40
+ _XMM1, // 48
+ _XMM2, // 56
+ _XMM3, // 64
+ _XMM4, // 72
+ _XMM5, // 80
+ _XMM6, // 88
+ _XMM7: Double; // 96
+ SingleBits: Integer; //104
+ end;
+
+procedure x64call(
+ Address: Pointer;
+ out _RAX: IPointer;
+
+ var Registers: TRegisters;
+ aStack: Pointer; aItems: Integer; var _XMM0: Double); assembler; nostackframe;
+
+
+asm
+(* Registers:
+ RDI: Address
+ RSI: _RAX
+ RDX: Registers
+ RCX: aStack
+ R8: aItems
+ R9: XMM0
+
+ rbp-8 addr
+ rbp-16 _rax
+ rbp-24 _xmm0
+ rbp-32 regs
+*)
+ push rbp
+ mov rbp,rsp
+ push rdi // address
+ push rsi // _rax
+ push r9 // xmm0
+ push rdx
+{$IFDEF PS_STACKALIGN}
+ bt r8, 0
+ jnc @skipjump
+ sub rsp, 8
+@skipjump:
+{$ENDIF}
+ mov rax, rdx
+ jmp @compareitems
+@work:
+ push [rcx]
+ dec r8
+ sub rcx,8
+@compareitems:
+ or r8, r8
+ jnz @work
+
+ // copy registers
+ // xmm0
+ mov rdx,[rbp-24]
+ bt [rax+104], 0
+ jnc @skipxmm0
+ cvtsd2ss xmm0,[rdx]
+ jmp @skipxmm0re
+ @skipxmm0:
+ movd xmm0,[rdx]
+ @skipxmm0re:
+
+ // xmm1
+ bt [rax+104], 1
+ jnc @skipxmm1
+ cvtsd2ss xmm1,[rax+48]
+ jmp @skipxmm1re
+ @skipxmm1:
+ movd xmm1,[rax+48]
+ @skipxmm1re:
+
+ // xmm2
+ bt [rax+104], 2
+ jnc @skipxmm2
+ cvtsd2ss xmm2,[rax+56]
+ jmp @skipxmm2re
+ @skipxmm2:
+ movd xmm2,[rax+56]
+ @skipxmm2re:
+
+ // xmm3
+ bt [rax+104], 3
+ jnc @skipxmm3
+ cvtsd2ss xmm3,[rax+64]
+ jmp @skipxmm3re
+ @skipxmm3:
+ movd xmm3,[rax+64]
+ @skipxmm3re:
+
+ // xmm4
+ bt [rax+104], 4
+ jnc @skipxmm4
+ cvtsd2ss xmm4,[rax+72]
+ jmp @skipxmm4re
+ @skipxmm4:
+ movd xmm4,[rax+72]
+ @skipxmm4re:
+
+ // xmm5
+ bt [rax+104], 5
+ jnc @skipxmm5
+ cvtsd2ss xmm5,[rax+80]
+ jmp @skipxmm5re
+ @skipxmm5:
+ movd xmm5,[rax+80]
+ @skipxmm5re:
+
+ // xmm6
+ bt [rax+104], 6
+ jnc @skipxmm6
+ cvtsd2ss xmm6,[rax+88]
+ jmp @skipxmm6re
+ @skipxmm6:
+ movd xmm6,[rax+88]
+ @skipxmm6re:
+// xmm7
+ bt [rax+104], 7
+ jnc @skipxmm7
+ cvtsd2ss xmm7,[rax+96]
+ jmp @skipxmm7re
+ @skipxmm7:
+ movd xmm7,[rax+96]
+ @skipxmm7re:
+
+
+ mov RDI, [rax]
+ mov RSI, [rax+ 8]
+ mov RDX, [rax+16]
+ mov RCX, [rax+24]
+ mov R8, [rax+32]
+ mov R9, [rax+40]
+
+ // weird thing on windows, it needs 32 bytes in the CALLEE side to do whatever in; not sure about linux
+ //sub RSP, 32
+
+ mov rax, [rbp-8]
+ call RAX
+
+// add rsp, 8
+
+ // add RSP, 32 // undo the damage done earlier
+
+ // copy result back
+ mov rsi, [rbp-16]
+ mov [rsi], RAX
+ mov rsi, [rbp-24]
+
+ // xmm0 res
+ mov rax, [rbp-32]
+ bt [rax+104], 8
+ jnc @skipres
+ cvtss2sd xmm1,xmm0
+ movd [rsi],xmm1
+ jmp @skipresre
+ @skipres:
+ movd [rsi],xmm0
+ @skipresre:
+
+ pop rdx
+ pop r9 // xmm0
+ pop rsi // _rax
+ pop rdi // address
+ leave
+ ret
+end;
+{$ENDIF}
+
+function TPSExec.InnerfuseCall(_Self, Address: Pointer; CallingConv: TPSCallingConvention; Params: TPSList; res: PPSVariantIFC): Boolean;
+var
+ Stack: array of Byte;
+ _RAX: IPointer;
+{$IFDEF WINDOWS}
+ _RCX, _RDX, _R8, _R9: IPointer;
+ _XMM0, _XMM1, _XMM2, _XMM3: Double;
+{$ELSE}
+_XMM0: Double;
+ Registers: TRegisters;
+ RegUsageFloat: Byte;
+{$ENDIF}
+ RegUsage: Byte;
+ CallData: TPSList;
+ I: Integer;
+ pp: ^Byte;
+
+ function rp(p: PPSVariantIFC): PPSVariantIFC;
+ begin
+ if p = nil then
+ begin
+ result := nil;
+ exit;
+ end;
+ if p.aType.BaseType = btPointer then
+ begin
+ p^.aType := Pointer(Pointer(IPointer(p^.dta) + PointerSize)^);
+ p^.Dta := Pointer(p^.dta^);
+ end;
+ Result := p;
+ end;
+{$IFDEF WINDOWS}
+ procedure StoreReg(data: IPointer); overload;
+ var p: Pointer;
+ begin
+ case RegUsage of
+ 0: begin inc(RegUsage); _RCX:=Data; end;
+ 1: begin inc(RegUsage); _RDX:=Data; end;
+ 2: begin inc(RegUsage); _R8:=Data; end;
+ 3: begin inc(RegUsage); _R9:=Data; end;
+ else begin
+ SetLength(Stack, Length(Stack)+8);
+ p := @Stack[LEngth(Stack)-8];
+ IPointer(p^) := data;
+ end;
+ end;
+ end;
+ {$ELSE}
+ procedure StoreReg(data: IPointer); overload;
+ var p: Pointer;
+ begin
+ case RegUsage of
+ 0: begin inc(RegUsage); Registers._RDI:=Data; end;
+ 1: begin inc(RegUsage); Registers._RSI:=Data; end;
+ 2: begin inc(RegUsage); Registers._RDX:=Data; end;
+ 3: begin inc(RegUsage); Registers._RCX:=Data; end;
+ 4: begin inc(RegUsage); Registers._R8:=Data; end;
+ 5: begin inc(RegUsage); Registers._R9:=Data; end;
+ else begin
+ SetLength(Stack, Length(Stack)+8);
+ p := @Stack[LEngth(Stack)-8];
+ IPointer(p^) := data;
+ end;
+ end;
+ end;
+{$ENDIF}
+
+ procedure StoreStack(const aData; Len: Integer);
+ var
+ p: Pointer;
+ begin
+ if Len > 8 then
+ if Length(Stack) mod 16 <> 0 then begin
+ SetLength(Stack, Length(Stack)+ (16-(Length(Stack) mod 16)));
+ end;
+ SetLength(Stack, Length(Stack)+Len);
+ p := @Stack[Length(Stack)-Len];
+ Move(aData, p^, Len);
+ end;
+
+{$IFDEF WINDOWS}
+ procedure StoreReg(data: Double); overload;
+ var p: Pointer;
+ begin
+ case RegUsage of
+ 0: begin inc(RegUsage); _XMM0:=Data; end;
+ 1: begin inc(RegUsage); _XMM1:=Data; end;
+ 2: begin inc(RegUsage); _XMM2:=Data; end;
+ 3: begin inc(RegUsage); _XMM3:=Data; end;
+ else begin
+ SetLength(Stack, Length(Stack)+8);
+ p := @Stack[LEngth(Stack)-8];
+ Double(p^) := data;
+ end;
+ end;
+ end;
+ {$ELSE}
+ procedure StoreReg(data: Double); overload;
+ var p: Pointer;
+ begin
+ case RegUsageFloat of
+ 0: begin inc(RegUsageFloat); _XMM0:=Data; end;
+ 1: begin inc(RegUsageFloat); Registers._XMM1:=Data; end;
+ 2: begin inc(RegUsageFloat); Registers._XMM2:=Data; end;
+ 3: begin inc(RegUsageFloat); Registers._XMM3:=Data; end;
+ 4: begin inc(RegUsageFloat); Registers._XMM4:=Data; end;
+ 5: begin inc(RegUsageFloat); Registers._XMM5:=Data; end;
+ 6: begin inc(RegUsageFloat); Registers._XMM6:=Data; end;
+ 7: begin inc(RegUsageFloat); Registers._XMM7:=Data; end;
+ else begin
+ SetLength(Stack, Length(Stack)+8);
+ p := @Stack[LEngth(Stack)-8];
+ Double(p^) := data;
+ end;
+ end;
+ end;
+ procedure StoreReg(data: Single); overload;
+ var p: Pointer;
+ begin
+ case RegUsageFloat of
+ 0: begin inc(RegUsageFloat); Registers.SingleBits := Registers.SingleBits or 1; _XMM0:=Data; end;
+ 1: begin inc(RegUsageFloat); Registers.SingleBits := Registers.SingleBits or 2; Registers._XMM1:=Data; end;
+ 2: begin inc(RegUsageFloat); Registers.SingleBits := Registers.SingleBits or 4; Registers._XMM2:=Data; end;
+ 3: begin inc(RegUsageFloat); Registers.SingleBits := Registers.SingleBits or 8; Registers._XMM3:=Data; end;
+ 4: begin inc(RegUsageFloat); Registers.SingleBits := Registers.SingleBits or 16; Registers._XMM4:=Data; end;
+ 5: begin inc(RegUsageFloat); Registers.SingleBits := Registers.SingleBits or 32; Registers._XMM5:=Data; end;
+ 6: begin inc(RegUsageFloat); Registers.SingleBits := Registers.SingleBits or 64; Registers._XMM6:=Data; end;
+ 7: begin inc(RegUsageFloat); Registers.SingleBits := Registers.SingleBits or 128; Registers._XMM7:=Data; end;
+ else begin
+ SetLength(Stack, Length(Stack)+8);
+ p := @Stack[LEngth(Stack)-8];
+ Double(p^) := data;
+ end;
+ end;
+ end;
+ {$ENDIF}
+ function GetPtr(fVar: PPSVariantIFC): Boolean;
+ var
+ varPtr: Pointer;
+ //UseReg: Boolean;
+ //tempstr: tbtstring;
+ p: Pointer;
+ begin
+ Result := False;
+ if FVar = nil then exit;
+ if fVar.VarParam then
+ begin
+ case fvar.aType.BaseType of
+ btArray:
+ begin
+ if Copy(fvar.aType.ExportName, 1, 10) = '!OPENARRAY' then
+ begin
+ p := CreateOpenArray(True, Self, FVar);
+ if p = nil then exit;
+ CallData.Add(p);
+ StoreReg(IPointer(POpenArray(p)^.Data));
+ StoreReg(IPointer(POpenArray(p)^.ItemCount -1));
+ Result := True;
+ Exit;
+ end else begin
+ varptr := fvar.Dta;
+// Exit;
+ end;
+ end;
+ btVariant,
+ btSet,
+ btStaticArray,
+ btRecord,
+ btInterface,
+ btClass,
+ {$IFNDEF PS_NOWIDESTRING} btUnicodeString, btWideString, btWideChar, {$ENDIF} btU8, btS8, btU16,
+ btS16, btU32, btS32, btSingle, btDouble, btExtended, btString, btPChar, btChar, btCurrency
+ {$IFNDEF PS_NOINT64}, bts64{$ENDIF}:
+ begin
+ Varptr := fvar.Dta;
+ end;
+ else begin
+ exit; //invalid type
+ end;
+ end; {case}
+
+ StoreReg(IPointer(VarPtr));
+ end else begin
+// UseReg := True;
+ case fVar^.aType.BaseType of
+ btSet:
+ begin
+ case TPSTypeRec_Set(fvar.aType).aByteSize of
+ 1: StoreReg(IPointer(byte(fvar.dta^)));
+ 2: StoreReg(IPointer(word(fvar.dta^)));
+ 3, 4: StoreReg(IPointer(cardinal(fvar.dta^)));
+ 5,6,7,8: StoreReg(IPointer(fVar.Dta^));
+ else
+ StoreReg(IPointer(fvar.Dta));
+ end;
+ end;
+ btArray:
+ begin
+ if Copy(fvar^.aType.ExportName, 1, 10) = '!OPENARRAY' then
+ begin
+ p := CreateOpenArray(False, SElf, FVar);
+ if p =nil then exit;
+ CallData.Add(p);
+ StoreReg(IPointer(POpenArray(p)^.Data));
+ StoreReg(IPointer(POpenArray(p)^.ItemCount -1));
+ Result := True;
+ exit;
+ end else begin
+ {$IFDEF FPC}
+ StoreReg(IPointer(FVar.Dta));
+ {$ELSE}
+ StoreReg(IPointer(FVar.Dta^));
+ {$ENDIF}
+ end;
+ end;
+ btRecord:
+ begin
+ if fvar^.aType.RealSize <= sizeof(IPointer) then
+ StoreReg(IPointer(fvar.dta^))
+ else
+ StoreReg(IPointer(fVar.Dta));
+ end;
+ btVariant
+ , btStaticArray:
+ begin
+ StoreReg(IPointer(fVar.Dta));
+ end;
+ btExtended, btDouble: {8 bytes} begin
+ StoreReg(double(fvar.dta^));
+ end;
+ btCurrency: {8 bytes} begin
+ StoreReg(IPointer(fvar.dta^));
+ end;
+ btSingle: {4 bytes} begin
+ StoreReg(single(fvar.dta^));
+ end;
+
+ btChar,
+ btU8,
+ btS8: begin
+ StoreReg(IPointer(byte(fVar^.dta^)));
+ end;
+ btWideChar,
+ btu16, btS16: begin
+ StoreReg(IPointer(word(fVar^.dta^)));
+ end;
+ btu32, bts32: begin
+ StoreReg(IPointer(cardinal(fVar^.dta^)));
+ end;
+ btPchar:
+ begin
+ if pointer(fvar^.dta^) = nil then
+ StoreReg(IPointer(@EmptyPchar))
+ else
+ StoreReg(IPointer(fvar^.dta^));
+ end;
+ btclass, btinterface, btString:
+ begin
+ StoreReg(IPointer(fvar^.dta^));
+ end;
+ btWideString: begin
+ StoreReg(IPointer(fvar^.dta^));
+ end;
+ btUnicodeString: begin
+ StoreReg(IPointer(fvar^.dta^));
+ end;
+
+ btProcPtr:
+ begin
+ GetMem(p, PointerSize2);
+ TMethod(p^) := MKMethod(Self, Longint(FVar.Dta^));
+ StoreStack(p^, Pointersize2);
+ FreeMem(p);
+ end;
+
+ bts64:
+ begin
+ StoreReg(IPointer(int64(fvar^.dta^)));
+ end;
+ end; {case}
+ end;
+ Result := True;
+ end;
+begin
+ InnerfuseCall := False;
+ if Address = nil then
+ exit; // need address
+ SetLength(Stack, 0);
+ CallData := TPSList.Create;
+ res := rp(res);
+ if res <> nil then
+ res.VarParam := true;
+ try
+{$IFNDEF WINDOWS}
+ (*_RSI := 0;
+ _RDI := 0;
+ _XMM4 := 0;
+ _XMM5 := 0;
+ _XMM6 := 0;
+ _XMM7 := 0;*)
+ FillChar(Registers, Sizeof(REgisters), 0);
+ _XMM0 := 0;
+ RegUsageFloat := 0;
+{$ELSE}
+ _RCX := 0;
+ _RDX := 0;
+ _R8 := 0;
+ _R9 := 0;
+ _XMM0 := 0;
+ _XMM1 := 0;
+ _XMM2 := 0;
+ _XMM3 := 0;
+{$ENDIF}
+ _RAX := 0;
+ RegUsage := 0;
+ if assigned(_Self) then begin
+ StoreReg(IPointer(_Self));
+ end;
+{$IFNDEF WINDOWS}
+ if assigned(res) and (res^.atype.basetype = btSingle) then begin
+ Registers.Singlebits := Registers.Singlebits or 256;
+ end;
+{$ENDIF}
+{$IFDEF PS_RESBEFOREPARAMETERS}
+ if assigned(res) then begin
+ case res^.aType.BaseType of
+ {$IFDEF x64_string_result_as_varparameter}
+ btstring, btWideString, btUnicodeString,
+ {$ENDIF}
+ btInterface, btArray, btVariant, btStaticArray:
+ GetPtr(res);
+ btSet:
+ begin
+ if res.aType.RealSize > PointerSize then GetPtr(res);
+ end;
+ end;
+ end;
+{$ENDIF}
+ for I := 0 to Params.Count - 1 do
+ begin
+ if not GetPtr(rp(Params[I])) then Exit;
+ end;
+ if assigned(res) then begin
+{$IFNDEF PS_RESBEFOREPARAMETERS}
+ case res^.aType.BaseType of
+ {$IFDEF x64_string_result_as_varparameter}
+ btstring, btWideString, btUnicodeString,
+ {$ENDIF}
+ btInterface, btArray, btVariant, btStaticArray:
+ GetPtr(res);
+ btSet:
+ begin
+ if res.aType.RealSize > PointerSize then GetPtr(res);
+ end;
+ end;
+{$ENDIF}
+ if Stack = nil then pp := nil else pp := @Stack[Length(Stack) -8];
+{$IFDEF WINDOWS}
+ x64call(Address, _RAX, _RCX, _RDX, _R8, _R9, _XMM0, _XMM1, _XMM2, _XMM3, pp, Length(Stack) div 8);
+{$ELSE}
+ x64call(Address, _RAX, Registers, pp, Length(Stack) div 8, _XMM0);
+{$ENDIF}
+ case res^.aType.BaseType of
+ btRecord, btSet:
+ begin
+ case res.aType.RealSize of
+ 1: byte(res.Dta^) := _RAX;
+ 2: word(res.Dta^) := _RAX;
+ 3,
+ 4: Longint(res.Dta^) := _RAX;
+ 5,6,7,8: IPointer(res.dta^) := _RAX;
+ end;
+ end;
+ btSingle: tbtsingle(res.Dta^) := _XMM0;
+ btDouble: tbtdouble(res.Dta^) := _XMM0;
+ btExtended: tbtextended(res.Dta^) := _XMM0;
+ btchar,btU8, btS8: tbtu8(res.dta^) := _RAX;
+ btWideChar, btu16, bts16: tbtu16(res.dta^) := _RAX;
+ btClass : IPointer(res.dta^) := _RAX;
+ btu32,bts32: tbtu32(res.dta^) := _RAX;
+ btPChar: pansichar(res.dta^) := Pansichar(_RAX);
+ bts64: tbts64(res.dta^) := Int64(_RAX);
+ btCurrency: tbtCurrency(res.Dta^) := Int64(_RAX);
+ btInterface,
+ btVariant,
+ {$IFDEF x64_string_result_as_varparameter}
+ btWidestring,btUnicodestring, btstring ,
+ {$ENDIF}
+ btStaticArray, btArray:;
+ {$IFNDEF x64_string_result_as_varparameter}
+ btUnicodeString, btWideString, btstring: Int64(res.dta^) := _RAX;
+ {$ENDIF}
+ else
+ exit;
+ end;
+ end else begin
+ if Stack = nil then pp := nil else pp := @Stack[Length(Stack) -8];
+{$IFDEF WINDOWS}
+ x64call(Address, _RAX, _RCX, _RDX, _R8, _R9, _XMM0, _XMM1, _XMM2, _XMM3, pp, Length(Stack) div 8);
+{$ELSE}
+ x64call(Address, _RAX, Registers, pp, Length(Stack) div 8, _XMM0);
+{$ENDIF}
+ end;
+ Result := True;
+ finally
+ for i := CallData.Count -1 downto 0 do
+ begin
+ pp := CallData[i];
+ case pp^ of
+ 0: DestroyOpenArray(Self, Pointer(pp));
+ end;
+ end;
+ CallData.Free;
+ end;
+end;
+
+
diff --git a/branches/script-component/Units/PascalScript/x86.inc b/branches/script-component/Units/PascalScript/x86.inc
new file mode 100644
index 0000000..62fc8ea
--- /dev/null
+++ b/branches/script-component/Units/PascalScript/x86.inc
@@ -0,0 +1,739 @@
+{ implementation of x86 abi }
+{$ifdef FPC}
+{$define PS_ARRAY_ON_STACK}
+{$endif}
+function RealFloatCall_Register(p: Pointer;
+ _EAX, _EDX, _ECX: Cardinal;
+ StackData: Pointer;
+ StackDataLen: Longint // stack length are in 4 bytes. (so 1 = 4 bytes)
+ ): Extended; Stdcall; // make sure all things are on stack
+var
+ E: Extended;
+begin
+ asm
+ mov ecx, stackdatalen
+ jecxz @@2
+ mov eax, stackdata
+ @@1:
+ mov edx, [eax]
+ push edx
+ sub eax, 4
+ dec ecx
+ or ecx, ecx
+ jnz @@1
+ @@2:
+ mov eax,_EAX
+ mov edx,_EDX
+ mov ecx,_ECX
+ call p
+ fstp tbyte ptr [e]
+ end;
+ Result := E;
+end;
+
+function RealFloatCall_Other(p: Pointer;
+ StackData: Pointer;
+ StackDataLen: Longint // stack length are in 4 bytes. (so 1 = 4 bytes)
+ ): Extended; Stdcall; // make sure all things are on stack
+var
+ E: Extended;
+begin
+ asm
+ mov ecx, stackdatalen
+ jecxz @@2
+ mov eax, stackdata
+ @@1:
+ mov edx, [eax]
+ push edx
+ sub eax, 4
+ dec ecx
+ or ecx, ecx
+ jnz @@1
+ @@2:
+ call p
+ fstp tbyte ptr [e]
+ end;
+ Result := E;
+end;
+
+function RealFloatCall_CDecl(p: Pointer;
+ StackData: Pointer;
+ StackDataLen: Longint // stack length are in 4 bytes. (so 1 = 4 bytes)
+ ): Extended; Stdcall; // make sure all things are on stack
+var
+ E: Extended;
+begin
+ asm
+ mov ecx, stackdatalen
+ jecxz @@2
+ mov eax, stackdata
+ @@1:
+ mov edx, [eax]
+ push edx
+ sub eax, 4
+ dec ecx
+ or ecx, ecx
+ jnz @@1
+ @@2:
+ call p
+ fstp tbyte ptr [e]
+ @@5:
+ mov ecx, stackdatalen
+ jecxz @@2
+ @@6:
+ pop edx
+ dec ecx
+ or ecx, ecx
+ jnz @@6
+ end;
+ Result := E;
+end;
+
+function RealCall_Register(p: Pointer;
+ _EAX, _EDX, _ECX: Cardinal;
+ StackData: Pointer;
+ StackDataLen: Longint; // stack length are in 4 bytes. (so 1 = 4 bytes)
+ ResultLength: Longint; ResEDX: Pointer): Longint; Stdcall; // make sure all things are on stack
+var
+ r: Longint;
+begin
+ asm
+ mov ecx, stackdatalen
+ jecxz @@2
+ mov eax, stackdata
+ @@1:
+ mov edx, [eax]
+ push edx
+ sub eax, 4
+ dec ecx
+ or ecx, ecx
+ jnz @@1
+ @@2:
+ mov eax,_EAX
+ mov edx,_EDX
+ mov ecx,_ECX
+ call p
+ mov ecx, resultlength
+ cmp ecx, 0
+ je @@5
+ cmp ecx, 1
+ je @@3
+ cmp ecx, 2
+ je @@4
+ mov r, eax
+ jmp @@5
+ @@3:
+ xor ecx, ecx
+ mov cl, al
+ mov r, ecx
+ jmp @@5
+ @@4:
+ xor ecx, ecx
+ mov cx, ax
+ mov r, ecx
+ @@5:
+ mov ecx, resedx
+ jecxz @@6
+ mov [ecx], edx
+ @@6:
+ end;
+ Result := r;
+end;
+
+function RealCall_Other(p: Pointer;
+ StackData: Pointer;
+ StackDataLen: Longint; // stack length are in 4 bytes. (so 1 = 4 bytes)
+ ResultLength: Longint; ResEDX: Pointer): Longint; Stdcall; // make sure all things are on stack
+var
+ r: Longint;
+begin
+ asm
+ mov ecx, stackdatalen
+ jecxz @@2
+ mov eax, stackdata
+ @@1:
+ mov edx, [eax]
+ push edx
+ sub eax, 4
+ dec ecx
+ or ecx, ecx
+ jnz @@1
+ @@2:
+ call p
+ mov ecx, resultlength
+ cmp ecx, 0
+ je @@5
+ cmp ecx, 1
+ je @@3
+ cmp ecx, 2
+ je @@4
+ mov r, eax
+ jmp @@5
+ @@3:
+ xor ecx, ecx
+ mov cl, al
+ mov r, ecx
+ jmp @@5
+ @@4:
+ xor ecx, ecx
+ mov cx, ax
+ mov r, ecx
+ @@5:
+ mov ecx, resedx
+ jecxz @@6
+ mov [ecx], edx
+ @@6:
+ end;
+ Result := r;
+end;
+
+function RealCall_CDecl(p: Pointer;
+ StackData: Pointer;
+ StackDataLen: Longint; // stack length are in 4 bytes. (so 1 = 4 bytes)
+ ResultLength: Longint; ResEDX: Pointer): Longint; Stdcall; // make sure all things are on stack
+var
+ r: Longint;
+begin
+ asm
+ mov ecx, stackdatalen
+ jecxz @@2
+ mov eax, stackdata
+ @@1:
+ mov edx, [eax]
+ push edx
+ sub eax, 4
+ dec ecx
+ or ecx, ecx
+ jnz @@1
+ @@2:
+ call p
+ mov ecx, resultlength
+ cmp ecx, 0
+ je @@5
+ cmp ecx, 1
+ je @@3
+ cmp ecx, 2
+ je @@4
+ mov r, eax
+ jmp @@5
+ @@3:
+ xor ecx, ecx
+ mov cl, al
+ mov r, ecx
+ jmp @@5
+ @@4:
+ xor ecx, ecx
+ mov cx, ax
+ mov r, ecx
+ @@5:
+ mov ecx, stackdatalen
+ jecxz @@7
+ @@6:
+ pop eax
+ dec ecx
+ or ecx, ecx
+ jnz @@6
+ mov ecx, resedx
+ jecxz @@7
+ mov [ecx], edx
+ @@7:
+ end;
+ Result := r;
+end;
+
+const
+ EmptyPchar: array[0..0] of char = #0;
+
+function TPSExec.InnerfuseCall(_Self, Address: Pointer; CallingConv: TPSCallingConvention; Params: TPSList; res: PPSVariantIFC): Boolean;
+var
+ Stack: ansistring;
+ I: Longint;
+ RegUsage: Byte;
+ CallData: TPSList;
+ pp: ^Byte;
+ IsConstructor: Boolean;
+
+ EAX, EDX, ECX: Longint;
+
+ function rp(p: PPSVariantIFC): PPSVariantIFC;
+ begin
+ if p = nil then
+ begin
+ result := nil;
+ exit;
+ end;
+ if p.aType.BaseType = btPointer then
+ begin
+ p^.aType := Pointer(Pointer(IPointer(p^.dta) + 4)^);
+ p^.Dta := Pointer(p^.dta^);
+ end;
+ Result := p;
+ end;
+
+ function GetPtr(fVar: PPSVariantIFC): Boolean;
+ var
+ varPtr: Pointer;
+ UseReg: Boolean;
+ tempstr: tbtstring;
+ p: Pointer;
+ begin
+ Result := False;
+ if FVar = nil then exit;
+ if fVar.VarParam then
+ begin
+ case fvar.aType.BaseType of
+ btArray:
+ begin
+ if Copy(fvar.aType.ExportName, 1, 10) = '!OPENARRAY' then
+ begin
+ p := CreateOpenArray(True, Self, FVar);
+ if p = nil then exit;
+ CallData.Add(p);
+ case RegUsage of
+ 0: begin EAX := Longint(POpenArray(p)^.Data); Inc(RegUsage); end;
+ 1: begin EDX := Longint(POpenArray(p)^.Data); Inc(RegUsage); end;
+ 2: begin ECX := Longint(POpenArray(p)^.Data); Inc(RegUsage); end;
+ else begin
+ Stack := StringOfChar(AnsiChar(#0),4) + Stack;
+ Pointer((@Stack[1])^) := POpenArray(p)^.Data;
+ end;
+ end;
+ case RegUsage of
+ 0: begin EAX := Longint(POpenArray(p)^.ItemCount - 1); Inc(RegUsage); end;
+ 1: begin EDX := Longint(POpenArray(p)^.ItemCount -1); Inc(RegUsage); end;
+ 2: begin ECX := Longint(POpenArray(p)^.ItemCount -1); Inc(RegUsage); end;
+ else begin
+ Stack := StringOfChar(AnsiChar(#0),4) + Stack;
+ Longint((@Stack[1])^) := POpenArray(p)^.ItemCount -1;
+ end;
+ end;
+ Result := True;
+ Exit;
+ end else begin
+ {$IFDEF PS_DYNARRAY}
+ varptr := fvar.Dta;
+ {$ELSE}
+ Exit;
+ {$ENDIF}
+ end;
+ end;
+ btVariant,
+ btSet,
+ btStaticArray,
+ btRecord,
+ btInterface,
+ btClass,
+ {$IFNDEF PS_NOWIDESTRING} btUnicodeString, btWideString, btWideChar, {$ENDIF} btU8, btS8, btU16,
+ btS16, btU32, btS32, btSingle, btDouble, btExtended, btString, btPChar, btChar, btCurrency
+ {$IFNDEF PS_NOINT64}, bts64{$ENDIF}:
+ begin
+ Varptr := fvar.Dta;
+ end;
+ else begin
+ exit; //invalid type
+ end;
+ end; {case}
+ case RegUsage of
+ 0: begin EAX := Longint(VarPtr); Inc(RegUsage); end;
+ 1: begin EDX := Longint(VarPtr); Inc(RegUsage); end;
+ 2: begin ECX := Longint(VarPtr); Inc(RegUsage); end;
+ else begin
+ Stack := StringOfChar(AnsiChar(#0),4) + Stack;
+ Pointer((@Stack[1])^) := VarPtr;
+ end;
+ end;
+ end else begin
+ UseReg := True;
+ case fVar^.aType.BaseType of
+ btSet:
+ begin
+ tempstr := StringOfChar(AnsiChar(#0),4);
+ case TPSTypeRec_Set(fvar.aType).aByteSize of
+ 1: Byte((@tempstr[1])^) := byte(fvar.dta^);
+ 2: word((@tempstr[1])^) := word(fvar.dta^);
+ 3, 4: cardinal((@tempstr[1])^) := cardinal(fvar.dta^);
+ else
+ pointer((@tempstr[1])^) := fvar.dta;
+ end;
+ end;
+ btArray:
+ begin
+ if Copy(fvar^.aType.ExportName, 1, 10) = '!OPENARRAY' then
+ begin
+ p := CreateOpenArray(False, SElf, FVar);
+ if p =nil then exit;
+ CallData.Add(p);
+ case RegUsage of
+ 0: begin EAX := Longint(POpenArray(p)^.Data); Inc(RegUsage); end;
+ 1: begin EDX := Longint(POpenArray(p)^.Data); Inc(RegUsage); end;
+ 2: begin ECX := Longint(POpenArray(p)^.Data); Inc(RegUsage); end;
+ else begin
+ Stack := StringOfChar(AnsiChar(#0),4) + Stack;
+ Pointer((@Stack[1])^) := POpenArray(p)^.Data;
+ end;
+ end;
+ case RegUsage of
+ 0: begin EAX := Longint(POpenArray(p)^.ItemCount -1); Inc(RegUsage); end;
+ 1: begin EDX := Longint(POpenArray(p)^.ItemCount -1); Inc(RegUsage); end;
+ 2: begin ECX := Longint(POpenArray(p)^.ItemCount -1); Inc(RegUsage); end;
+ else begin
+ Stack := StringOfChar(AnsiChar(#0),4) + Stack;
+ Longint((@Stack[1])^) := POpenArray(p)^.ItemCount -1;
+ end;
+ end;
+ Result := True;
+ exit;
+ end else begin
+ {$IFDEF PS_DYNARRAY}
+ TempStr := StringOfChar(AnsiChar(#0),4);
+ Pointer((@TempStr[1])^) := Pointer(fvar.Dta^);
+ {$IFDEF PS_ARRAY_ON_STACK}
+ UseReg := false;
+ {$ENDIF}
+ {$ELSE}
+ Exit;
+ {$ENDIF}
+ end;
+ end;
+ btVariant
+ , btStaticArray, btRecord:
+ begin
+ TempStr := StringOfChar(AnsiChar(#0),4);
+ Pointer((@TempStr[1])^) := Pointer(fvar.Dta);
+ end;
+ btDouble: {8 bytes} begin
+ TempStr := StringOfChar(AnsiChar(#0),8);
+ UseReg := False;
+ double((@TempStr[1])^) := double(fvar.dta^);
+ end;
+ btCurrency: {8 bytes} begin
+ TempStr := StringOfChar(AnsiChar(#0),8);
+ UseReg := False;
+ currency((@TempStr[1])^) := currency(fvar.dta^);
+ end;
+ btSingle: {4 bytes} begin
+ TempStr := StringOfChar(AnsiChar(#0),4);;
+ UseReg := False;
+ Single((@TempStr[1])^) := single(fvar.dta^);
+ end;
+
+ btExtended: {10 bytes} begin
+ UseReg := False;
+ TempStr:= StringOfChar(AnsiChar(#0),12);
+ Extended((@TempStr[1])^) := extended(fvar.dta^);
+ end;
+ btChar,
+ btU8,
+ btS8: begin
+ TempStr := tbtchar(fVar^.dta^) + tbtstring(StringOfChar(AnsiChar(#0),3));
+ end;
+ {$IFNDEF PS_NOWIDESTRING}btWideChar, {$ENDIF}
+ btu16, btS16: begin
+ TempStr := StringOfChar(AnsiChar(#0),4);
+ Word((@TempStr[1])^) := word(fVar^.dta^);
+ end;
+ btu32, bts32: begin
+ TempStr := StringOfChar(AnsiChar(#0),4);
+ Longint((@TempStr[1])^) := Longint(fVar^.dta^);
+ end;
+ btPchar:
+ begin
+ TempStr := StringOfChar(AnsiChar(#0),4);
+ if pointer(fvar^.dta^) = nil then
+ Pointer((@TempStr[1])^) := @EmptyPchar
+ else
+ Pointer((@TempStr[1])^) := pointer(fvar^.dta^);
+ end;
+ btclass, btinterface, btString:
+ begin
+ TempStr := StringOfChar(AnsiChar(#0),4);
+ Pointer((@TempStr[1])^) := pointer(fvar^.dta^);
+ end;
+ {$IFNDEF PS_NOWIDESTRING}
+ btWideString: begin
+ TempStr := StringOfChar(AnsiChar(#0),4);
+ Pointer((@TempStr[1])^) := pointer(fvar^.dta^);
+ end;
+ btUnicodeString: begin
+ TempStr := StringOfChar(AnsiChar(#0),4);
+ Pointer((@TempStr[1])^) := pointer(fvar^.dta^);
+ end;
+ {$ENDIF}
+
+ btProcPtr:
+ begin
+ tempstr := StringOfChar(AnsiChar(#0),8);
+ TMethod((@TempStr[1])^) := MKMethod(Self, Longint(FVar.Dta^));
+ UseReg := false;
+ end;
+
+ {$IFNDEF PS_NOINT64}bts64:
+ begin
+ TempStr:= StringOfChar(AnsiChar(#0),8);
+ Int64((@TempStr[1])^) := int64(fvar^.dta^);
+ UseReg := False;
+ end;{$ENDIF}
+ end; {case}
+ if UseReg then
+ begin
+ case RegUsage of
+ 0: begin EAX := Longint((@Tempstr[1])^); Inc(RegUsage); end;
+ 1: begin EDX := Longint((@Tempstr[1])^); Inc(RegUsage); end;
+ 2: begin ECX := Longint((@Tempstr[1])^); Inc(RegUsage); end;
+ else begin
+ {$IFDEF FPC_OLD_FIX}
+ if CallingConv = cdRegister then
+ Stack := Stack + TempStr
+ else
+ {$ENDIF}
+ Stack := TempStr + Stack;
+ end;
+ end;
+ end else begin
+ {$IFDEF FPC_OLD_FIX}
+ if CallingConv = cdRegister then
+ Stack := Stack + TempStr
+ else
+ {$ENDIF}
+ Stack := TempStr + Stack;
+ end;
+ end;
+ Result := True;
+ end;
+begin
+ if (Integer(CallingConv) and 64) <> 0 then begin
+ IsConstructor := true;
+ CAllingConv := TPSCallingConvention(Integer(CallingConv) and not 64);
+ end else IsConstructor := false;
+
+ InnerfuseCall := False;
+ if Address = nil then
+ exit; // need address
+ Stack := '';
+ CallData := TPSList.Create;
+ res := rp(res);
+ if res <> nil then
+ res.VarParam := true;
+ try
+ case CallingConv of
+ cdRegister: begin
+ EAX := 0;
+ EDX := 0;
+ ECX := 0;
+ RegUsage := 0;
+
+{$IFDEF FPC} // FIX FOR FPC constructor calls
+ if IsConstructor then begin
+ if not GetPtr(rp(Params[0])) then exit; // this goes first
+ RegUsage := 2;
+ EDX := Longint(_Self);
+ Params.Delete(0);
+ end else
+{$ENDIF}
+ if assigned(_Self) then begin
+ RegUsage := 1;
+ EAX := Longint(_Self);
+ end;
+
+ for I := 0 to Params.Count - 1 do
+ begin
+ if not GetPtr(rp(Params[I])) then Exit;
+ end;
+
+ if assigned(res) then begin
+ case res^.aType.BaseType of
+ {$IFNDEF PS_NOWIDESTRING}btWideString, btUnicodeString, {$ENDIF}
+ btInterface, btArray, btrecord, {$IFNDEF PS_FPCSTRINGWORKAROUND}btstring, {$ENDIF}btVariant, btStaticArray: GetPtr(res);
+ btSet:
+ begin
+ if TPSTypeRec_Set(res.aType).aByteSize >4 then GetPtr(res);
+ end;
+ end;
+ case res^.aType.BaseType of
+ btSet:
+ begin
+ case TPSTypeRec_Set(res.aType).aByteSize of
+ 1: byte(res.Dta^) := RealCall_Register(Address, EAX, EDX, ECX, @Stack[Length(Stack)-3], Length(Stack) div 4, 1, nil);
+ 2: word(res.Dta^) := RealCall_Register(Address, EAX, EDX, ECX, @Stack[Length(Stack)-3], Length(Stack) div 4, 2, nil);
+ 3,
+ 4: Longint(res.Dta^) := RealCall_Register(Address, EAX, EDX, ECX, @Stack[Length(Stack)-3], Length(Stack) div 4, 4, nil);
+ else RealCall_Register(Address, EAX, EDX, ECX, @Stack[Length(Stack)-3], Length(Stack) div 4, 0, nil)
+ end;
+ end;
+ btSingle: tbtsingle(res.Dta^) := RealFloatCall_Register(Address, EAX, EDX, ECX, @Stack[Length(Stack)-3], Length(Stack) div 4);
+ btDouble: tbtdouble(res.Dta^) := RealFloatCall_Register(Address, EAX, EDX, ECX, @Stack[Length(Stack)-3], Length(Stack) div 4);
+ btExtended: tbtextended(res.Dta^) := RealFloatCall_Register(Address, EAX, EDX, ECX, @Stack[Length(Stack)-3], Length(Stack) div 4);
+ btchar,btU8, btS8: tbtu8(res.dta^) := RealCall_Register(Address, EAX, EDX, ECX, @Stack[Length(Stack)-3], Length(Stack) div 4, 1, nil);
+ {$IFNDEF PS_NOWIDESTRING}btWideChar, {$ENDIF}btu16, bts16: tbtu16(res.dta^) := RealCall_Register(Address, EAX, EDX, ECX, @Stack[Length(Stack)-3], Length(Stack) div 4, 2, nil);
+ btClass :
+ {$IFDEF FPC}
+ tbtu32(res.dta^) := RealCall_Register(Address, EDX, EAX, ECX,
+ @Stack[Length(Stack) - 3], Length(Stack) div 4, 4, nil);
+ {$ELSE}
+ tbtu32(res.dta^) := RealCall_Register(Address, EAX, EDX, ECX,
+ @Stack[Length(Stack) - 3], Length(Stack) div 4, 4, nil);
+ {$ENDIF}
+
+ btu32,bts32: tbtu32(res.dta^) := RealCall_Register(Address, EAX, EDX, ECX, @Stack[Length(Stack)-3], Length(Stack) div 4, 4, nil);
+ btPChar: pansichar(res.dta^) := Pansichar(RealCall_Register(Address, EAX, EDX, ECX, @Stack[Length(Stack)-3], Length(Stack) div 4, 4, nil));
+ {$IFNDEF PS_NOINT64}bts64:
+ begin
+ EAX := RealCall_Register(Address, EAX, EDX, ECX, @Stack[Length(Stack)-3], Length(Stack) div 4, 4, @EDX);
+ tbts64(res.dta^) := Int64(Cardinal(EDX)) shl 32 or Cardinal(EAX);
+ end;
+ {$ENDIF}
+ btCurrency: tbtCurrency(res.Dta^) := RealFloatCall_Register(Address, EAX, EDX, ECX, @Stack[Length(Stack)-3], Length(Stack) div 4) / 10000;
+ btInterface,
+ btVariant,
+ {$IFNDEF PS_NOWIDESTRING}btWidestring,btUnicodestring, {$ENDIF}
+ btStaticArray, btArray, btrecord{$IFNDEF PS_FPCSTRINGWORKAROUND}, btstring {$ENDIF}: RealCall_Register(Address, EAX, EDX, ECX, @Stack[Length(Stack)-3], Length(Stack) div 4, 0, nil);
+ {$IFDEF PS_FPCSTRINGWORKAROUND}
+ btstring: begin
+ eax := RealCall_Register(Address, EAX, EDX, ECX, @Stack[Length(Stack)-3], Length(Stack) div 4, 4, nil);
+ Longint(res.dta^) := eax;
+ end;
+ {$ENDIF}
+ else
+ exit;
+ end;
+ end else
+ RealCall_Register(Address, EAX, EDX, ECX, @Stack[Length(Stack)-3], Length(Stack) div 4, 0, nil);
+ Result := True;
+ end;
+ cdPascal: begin
+ RegUsage := 3;
+ for I := 0 to Params.Count - 1 do begin
+ if not GetPtr(Params[i]) then Exit;
+ end;
+ if assigned(res) then begin
+ case res^.aType.BaseType of
+ {$IFNDEF PS_NOWIDESTRING}btWideString, btUnicodeString, {$ENDIF}btInterface, btArray, btrecord, btstring, btVariant: GetPtr(res);
+ end;
+ end;
+ if assigned(_Self) then begin
+ Stack := StringOfChar(AnsiChar(#0),4) +Stack;
+ Pointer((@Stack[1])^) := _Self;
+ end;
+ if assigned(res) then begin
+ case res^.aType.BaseType of
+ btSingle: tbtsingle(res^.Dta^) := RealFloatCall_Other(Address, @Stack[Length(Stack)-3], Length(Stack) div 4);
+ btDouble: tbtdouble(res^.Dta^) := RealFloatCall_Other(Address, @Stack[Length(Stack)-3], Length(Stack) div 4);
+ btExtended: tbtextended(res^.Dta^) := RealFloatCall_Other(Address, @Stack[Length(Stack)-3], Length(Stack) div 4);
+ btChar, btU8, btS8: tbtu8(res^.Dta^) := RealCall_Other(Address, @Stack[Length(Stack)-3], Length(Stack) div 4, 1, nil);
+ {$IFNDEF PS_NOWIDESTRING}btWideChar, {$ENDIF}btu16, bts16: tbtu16(res^.Dta^) := RealCall_Other(Address, @Stack[Length(Stack)-3], Length(Stack) div 4, 2, nil);
+ btClass, btu32, bts32: tbtu32(res^.Dta^):= RealCall_Other(Address, @Stack[Length(Stack)-3], Length(Stack) div 4, 4, nil);
+ btPChar: TBTSTRING(res^.dta^) := Pansichar(RealCall_Other(Address, @Stack[Length(Stack)-3], Length(Stack) div 4, 4, nil));
+ {$IFNDEF PS_NOINT64}bts64:
+ begin
+ EAX := RealCall_Other(Address, @Stack[Length(Stack)-3], Length(Stack) div 4, 4, @EDX);
+ tbts64(res^.dta^) := Int64(EAX) shl 32 or EDX;
+ end;
+ {$ENDIF}
+ btVariant,
+ btInterface, btrecord, btstring: RealCall_Other(Address, @Stack[Length(Stack)-3], Length(Stack) div 4, 0, nil);
+ else
+ exit;
+ end;
+ end else
+ RealCall_Other(Address, @Stack[Length(Stack)-3], Length(Stack) div 4, 0, nil);
+ Result := True;
+ end;
+ cdSafeCall: begin
+ RegUsage := 3;
+ if assigned(res) then begin
+ GetPtr(res);
+ end;
+ for I := Params.Count - 1 downto 0 do begin
+ if not GetPtr(Params[i]) then Exit;
+ end;
+ if assigned(_Self) then begin
+ Stack := StringOfChar(AnsiChar(#0),4) +Stack;
+ Pointer((@Stack[1])^) := _Self;
+ end;
+ OleCheck(RealCall_Other(Address, @Stack[Length(Stack)-3], Length(Stack) div 4, 4, nil));
+ Result := True;
+ end;
+
+ CdCdecl: begin
+ RegUsage := 3;
+ if assigned(_Self) then begin
+ Stack := StringOfChar(AnsiChar(#0),4);
+ Pointer((@Stack[1])^) := _Self;
+ end;
+ for I := Params.Count - 1 downto 0 do begin
+ if not GetPtr(Params[I]) then Exit;
+ end;
+ if assigned(res) then begin
+ case res^.aType.BaseType of
+ btSingle: tbtsingle(res^.dta^) := RealFloatCall_Cdecl(Address, @Stack[Length(Stack)-3], Length(Stack) div 4);
+ btDouble: tbtdouble(res^.dta^) := RealFloatCall_Cdecl(Address, @Stack[Length(Stack)-3], Length(Stack) div 4);
+ btExtended: tbtextended(res^.dta^) := RealFloatCall_Cdecl(Address, @Stack[Length(Stack)-3], Length(Stack) div 4);
+ btCHar, btU8, btS8: tbtu8(res^.dta^) := RealCall_Cdecl(Address, @Stack[Length(Stack)-3], Length(Stack) div 4, 1, nil);
+ {$IFNDEF PS_NOWIDESTRING}btWideChar, {$ENDIF}btu16, bts16: tbtu16(res^.dta^) := RealCall_Cdecl(Address, @Stack[Length(Stack)-3], Length(Stack) div 4, 2, nil);
+ btClass, btu32, bts32: tbtu32(res^.dta^) := RealCall_Cdecl(Address, @Stack[Length(Stack)-3], Length(Stack) div 4, 4, nil);
+ btPChar: TBTSTRING(res^.dta^) := Pansichar(RealCall_Cdecl(Address, @Stack[Length(Stack)-3], Length(Stack) div 4, 4, nil));
+ {$IFNDEF PS_NOINT64}bts64:
+ begin
+ EAX := RealCall_CDecl(Address, @Stack[Length(Stack)-3], Length(Stack) div 4, 4, @EDX);
+ tbts64(res^.Dta^) := Int64(EAX) shl 32 or EDX;
+ end;
+ {$ENDIF}
+ btVariant, {$IFNDEF PS_NOWIDESTRING}btUnicodeString, btWideString, {$ENDIF}
+ btInterface,
+ btArray, btrecord, btstring: begin GetPtr(res); RealCall_Cdecl(Address, @Stack[Length(Stack)-3], Length(Stack) div 4, 0, nil); end;
+ else
+ exit;
+ end;
+ end else begin
+ RealCall_CDecl(Address, @Stack[Length(Stack)-3], Length(Stack) div 4, 0, nil);
+ end;
+ Result := True;
+ end;
+ CdStdCall: begin
+ RegUsage := 3;
+ for I := Params.Count - 1 downto 0 do begin
+ if not GetPtr(Params[I]) then exit;
+ end;
+ if assigned(_Self) then begin
+ Stack := StringOfChar(AnsiChar(#0),4) + Stack;
+ Pointer((@Stack[1])^) := _Self;
+ end;
+ if assigned(res) then begin
+ case res^.aType.BaseType of
+ btSingle: tbtsingle(res^.dta^) := RealFloatCall_Other(Address, @Stack[Length(Stack)-3], Length(Stack) div 4);
+ btDouble: tbtdouble(res^.dta^) := RealFloatCall_Other(Address, @Stack[Length(Stack)-3], Length(Stack) div 4);
+ btExtended: tbtextended(res^.dta^):= RealFloatCall_Other(Address, @Stack[Length(Stack)-3], Length(Stack) div 4);
+ btChar, btU8, btS8: tbtu8(res^.dta^) := RealCall_Other(Address, @Stack[Length(Stack)-3], Length(Stack) div 4, 1, nil);
+ {$IFNDEF PS_NOWIDESTRING}btWideChar, {$ENDIF}btu16, bts16: tbtu16(res^.dta^) := RealCall_Other(Address, @Stack[Length(Stack)-3], Length(Stack) div 4, 2, nil);
+ btclass, btu32, bts32: tbtu32(res^.dta^) := RealCall_Other(Address, @Stack[Length(Stack)-3], Length(Stack) div 4, 4, nil);
+ btPChar: TBTSTRING(res^.dta^) := Pansichar(RealCall_Other(Address, @Stack[Length(Stack)-3], Length(Stack) div 4, 4, nil));
+ {$IFNDEF PS_NOINT64}bts64:
+ begin
+ EAX := RealCall_Other(Address, @Stack[Length(Stack)-3], Length(Stack) div 4, 4, @EDX);
+ tbts64(res^.dta^) := Int64(EAX) shl 32 or EDX;
+ end;
+ {$ENDIF}
+ btVariant, {$IFNDEF PS_NOWIDESTRING}btUnicodeString, btWideString, {$ENDIF}
+ btInterface, btArray, btrecord, btstring: begin GetPtr(res); RealCall_Other(Address, @Stack[Length(Stack)-3], Length(Stack) div 4, 0, nil); end;
+ else
+ exit;
+ end;
+ end else begin
+ RealCall_Other(Address, @Stack[Length(Stack)-3], Length(Stack) div 4, 0, nil);
+ end;
+ Result := True;
+ end;
+ end;
+ finally
+ for i := CallData.Count -1 downto 0 do
+ begin
+ pp := CallData[i];
+ case pp^ of
+ 0: DestroyOpenArray(Self, Pointer(pp));
+ end;
+ end;
+ CallData.Free;
+ end;
+end;
+
+
diff --git a/branches/script-component/Units/Synapse/asn1util.pas b/branches/script-component/Units/Synapse/asn1util.pas
new file mode 100644
index 0000000..55d0892
--- /dev/null
+++ b/branches/script-component/Units/Synapse/asn1util.pas
@@ -0,0 +1,505 @@
+{==============================================================================|
+| Project : Ararat Synapse | 001.004.004 |
+|==============================================================================|
+| Content: support for ASN.1 BER coding and decoding |
+|==============================================================================|
+| Copyright (c)1999-2003, Lukas Gebauer |
+| All rights reserved. |
+| |
+| Redistribution and use in source and binary forms, with or without |
+| modification, are permitted provided that the following conditions are met: |
+| |
+| Redistributions of source code must retain the above copyright notice, this |
+| list of conditions and the following disclaimer. |
+| |
+| Redistributions in binary form must reproduce the above copyright notice, |
+| this list of conditions and the following disclaimer in the documentation |
+| and/or other materials provided with the distribution. |
+| |
+| Neither the name of Lukas Gebauer nor the names of its contributors may |
+| be used to endorse or promote products derived from this software without |
+| specific prior written permission. |
+| |
+| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
+| AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
+| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
+| ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR |
+| ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
+| DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
+| SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
+| CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
+| LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
+| OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
+| DAMAGE. |
+|==============================================================================|
+| The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).|
+| Portions created by Lukas Gebauer are Copyright (c) 1999-2003 |
+| Portions created by Hernan Sanchez are Copyright (c) 2000. |
+| All Rights Reserved. |
+|==============================================================================|
+| Contributor(s): |
+| Hernan Sanchez (hernan.sanchez@iname.com) |
+|==============================================================================|
+| History: see HISTORY.HTM from distribution package |
+| (Found at URL: http://www.ararat.cz/synapse/) |
+|==============================================================================}
+
+{: @abstract(Utilities for handling ASN.1 BER encoding)
+By this unit you can parse ASN.1 BER encoded data to elements or build back any
+ elements to ASN.1 BER encoded buffer. You can dump ASN.1 BER encoded data to
+ human readable form for easy debugging, too.
+
+Supported element types are: ASN1_BOOL, ASN1_INT, ASN1_OCTSTR, ASN1_NULL,
+ ASN1_OBJID, ASN1_ENUM, ASN1_SEQ, ASN1_SETOF, ASN1_IPADDR, ASN1_COUNTER,
+ ASN1_GAUGE, ASN1_TIMETICKS, ASN1_OPAQUE
+
+For sample of using, look to @link(TSnmpSend) or @link(TLdapSend)class.
+}
+
+{$Q-}
+{$H+}
+{$IFDEF FPC}
+ {$MODE DELPHI}
+{$ENDIF}
+
+unit asn1util;
+
+interface
+
+uses
+ SysUtils, Classes, synautil;
+
+const
+ ASN1_BOOL = $01;
+ ASN1_INT = $02;
+ ASN1_OCTSTR = $04;
+ ASN1_NULL = $05;
+ ASN1_OBJID = $06;
+ ASN1_ENUM = $0a;
+ ASN1_SEQ = $30;
+ ASN1_SETOF = $31;
+ ASN1_IPADDR = $40;
+ ASN1_COUNTER = $41;
+ ASN1_GAUGE = $42;
+ ASN1_TIMETICKS = $43;
+ ASN1_OPAQUE = $44;
+
+{:Encodes OID item to binary form.}
+function ASNEncOIDItem(Value: Integer): AnsiString;
+
+{:Decodes an OID item of the next element in the "Buffer" from the "Start"
+ position.}
+function ASNDecOIDItem(var Start: Integer; const Buffer: AnsiString): Integer;
+
+{:Encodes the length of ASN.1 element to binary.}
+function ASNEncLen(Len: Integer): AnsiString;
+
+{:Decodes length of next element in "Buffer" from the "Start" position.}
+function ASNDecLen(var Start: Integer; const Buffer: AnsiString): Integer;
+
+{:Encodes a signed integer to ASN.1 binary}
+function ASNEncInt(Value: Integer): AnsiString;
+
+{:Encodes unsigned integer into ASN.1 binary}
+function ASNEncUInt(Value: Integer): AnsiString;
+
+{:Encodes ASN.1 object to binary form.}
+function ASNObject(const Data: AnsiString; ASNType: Integer): AnsiString;
+
+{:Beginning with the "Start" position, decode the ASN.1 item of the next element
+ in "Buffer". Type of item is stored in "ValueType."}
+function ASNItem(var Start: Integer; const Buffer: AnsiString;
+ var ValueType: Integer): AnsiString;
+
+{:Encodes an MIB OID string to binary form.}
+function MibToId(Mib: String): AnsiString;
+
+{:Decodes MIB OID from binary form to string form.}
+function IdToMib(const Id: AnsiString): String;
+
+{:Encodes an one number from MIB OID to binary form. (used internally from
+@link(MibToId))}
+function IntMibToStr(const Value: AnsiString): AnsiString;
+
+{:Convert ASN.1 BER encoded buffer to human readable form for debugging.}
+function ASNdump(const Value: AnsiString): AnsiString;
+
+implementation
+
+{==============================================================================}
+function ASNEncOIDItem(Value: Integer): AnsiString;
+var
+ x, xm: Integer;
+ b: Boolean;
+begin
+ x := Value;
+ b := False;
+ Result := '';
+ repeat
+ xm := x mod 128;
+ x := x div 128;
+ if b then
+ xm := xm or $80;
+ if x > 0 then
+ b := True;
+ Result := AnsiChar(xm) + Result;
+ until x = 0;
+end;
+
+{==============================================================================}
+function ASNDecOIDItem(var Start: Integer; const Buffer: AnsiString): Integer;
+var
+ x: Integer;
+ b: Boolean;
+begin
+ Result := 0;
+ repeat
+ Result := Result * 128;
+ x := Ord(Buffer[Start]);
+ Inc(Start);
+ b := x > $7F;
+ x := x and $7F;
+ Result := Result + x;
+ until not b;
+end;
+
+{==============================================================================}
+function ASNEncLen(Len: Integer): AnsiString;
+var
+ x, y: Integer;
+begin
+ if Len < $80 then
+ Result := AnsiChar(Len)
+ else
+ begin
+ x := Len;
+ Result := '';
+ repeat
+ y := x mod 256;
+ x := x div 256;
+ Result := AnsiChar(y) + Result;
+ until x = 0;
+ y := Length(Result);
+ y := y or $80;
+ Result := AnsiChar(y) + Result;
+ end;
+end;
+
+{==============================================================================}
+function ASNDecLen(var Start: Integer; const Buffer: AnsiString): Integer;
+var
+ x, n: Integer;
+begin
+ x := Ord(Buffer[Start]);
+ Inc(Start);
+ if x < $80 then
+ Result := x
+ else
+ begin
+ Result := 0;
+ x := x and $7F;
+ for n := 1 to x do
+ begin
+ Result := Result * 256;
+ x := Ord(Buffer[Start]);
+ Inc(Start);
+ Result := Result + x;
+ end;
+ end;
+end;
+
+{==============================================================================}
+function ASNEncInt(Value: Integer): AnsiString;
+var
+ x, y: Cardinal;
+ neg: Boolean;
+begin
+ neg := Value < 0;
+ x := Abs(Value);
+ if neg then
+ x := not (x - 1);
+ Result := '';
+ repeat
+ y := x mod 256;
+ x := x div 256;
+ Result := AnsiChar(y) + Result;
+ until x = 0;
+ if (not neg) and (Result[1] > #$7F) then
+ Result := #0 + Result;
+end;
+
+{==============================================================================}
+function ASNEncUInt(Value: Integer): AnsiString;
+var
+ x, y: Integer;
+ neg: Boolean;
+begin
+ neg := Value < 0;
+ x := Value;
+ if neg then
+ x := x and $7FFFFFFF;
+ Result := '';
+ repeat
+ y := x mod 256;
+ x := x div 256;
+ Result := AnsiChar(y) + Result;
+ until x = 0;
+ if neg then
+ Result[1] := AnsiChar(Ord(Result[1]) or $80);
+end;
+
+{==============================================================================}
+function ASNObject(const Data: AnsiString; ASNType: Integer): AnsiString;
+begin
+ Result := AnsiChar(ASNType) + ASNEncLen(Length(Data)) + Data;
+end;
+
+{==============================================================================}
+function ASNItem(var Start: Integer; const Buffer: AnsiString;
+ var ValueType: Integer): AnsiString;
+var
+ ASNType: Integer;
+ ASNSize: Integer;
+ y, n: Integer;
+ x: byte;
+ s: AnsiString;
+ c: AnsiChar;
+ neg: Boolean;
+ l: Integer;
+begin
+ Result := '';
+ ValueType := ASN1_NULL;
+ l := Length(Buffer);
+ if l < (Start + 1) then
+ Exit;
+ ASNType := Ord(Buffer[Start]);
+ ValueType := ASNType;
+ Inc(Start);
+ ASNSize := ASNDecLen(Start, Buffer);
+ if (Start + ASNSize - 1) > l then
+ Exit;
+ if (ASNType and $20) > 0 then
+// Result := '$' + IntToHex(ASNType, 2)
+ Result := Copy(Buffer, Start, ASNSize)
+ else
+ case ASNType of
+ ASN1_INT, ASN1_ENUM, ASN1_BOOL:
+ begin
+ y := 0;
+ neg := False;
+ for n := 1 to ASNSize do
+ begin
+ x := Ord(Buffer[Start]);
+ if (n = 1) and (x > $7F) then
+ neg := True;
+ if neg then
+ x := not x;
+ y := y * 256 + x;
+ Inc(Start);
+ end;
+ if neg then
+ y := -(y + 1);
+ Result := IntToStr(y);
+ end;
+ ASN1_COUNTER, ASN1_GAUGE, ASN1_TIMETICKS:
+ begin
+ y := 0;
+ for n := 1 to ASNSize do
+ begin
+ y := y * 256 + Ord(Buffer[Start]);
+ Inc(Start);
+ end;
+ Result := IntToStr(y);
+ end;
+ ASN1_OCTSTR, ASN1_OPAQUE:
+ begin
+ for n := 1 to ASNSize do
+ begin
+ c := AnsiChar(Buffer[Start]);
+ Inc(Start);
+ s := s + c;
+ end;
+ Result := s;
+ end;
+ ASN1_OBJID:
+ begin
+ for n := 1 to ASNSize do
+ begin
+ c := AnsiChar(Buffer[Start]);
+ Inc(Start);
+ s := s + c;
+ end;
+ Result := IdToMib(s);
+ end;
+ ASN1_IPADDR:
+ begin
+ s := '';
+ for n := 1 to ASNSize do
+ begin
+ if (n <> 1) then
+ s := s + '.';
+ y := Ord(Buffer[Start]);
+ Inc(Start);
+ s := s + IntToStr(y);
+ end;
+ Result := s;
+ end;
+ ASN1_NULL:
+ begin
+ Result := '';
+ Start := Start + ASNSize;
+ end;
+ else // unknown
+ begin
+ for n := 1 to ASNSize do
+ begin
+ c := AnsiChar(Buffer[Start]);
+ Inc(Start);
+ s := s + c;
+ end;
+ Result := s;
+ end;
+ end;
+end;
+
+{==============================================================================}
+function MibToId(Mib: String): AnsiString;
+var
+ x: Integer;
+
+ function WalkInt(var s: String): Integer;
+ var
+ x: Integer;
+ t: AnsiString;
+ begin
+ x := Pos('.', s);
+ if x < 1 then
+ begin
+ t := s;
+ s := '';
+ end
+ else
+ begin
+ t := Copy(s, 1, x - 1);
+ s := Copy(s, x + 1, Length(s) - x);
+ end;
+ Result := StrToIntDef(t, 0);
+ end;
+
+begin
+ Result := '';
+ x := WalkInt(Mib);
+ x := x * 40 + WalkInt(Mib);
+ Result := ASNEncOIDItem(x);
+ while Mib <> '' do
+ begin
+ x := WalkInt(Mib);
+ Result := Result + ASNEncOIDItem(x);
+ end;
+end;
+
+{==============================================================================}
+function IdToMib(const Id: AnsiString): String;
+var
+ x, y, n: Integer;
+begin
+ Result := '';
+ n := 1;
+ while Length(Id) + 1 > n do
+ begin
+ x := ASNDecOIDItem(n, Id);
+ if (n - 1) = 1 then
+ begin
+ y := x div 40;
+ x := x mod 40;
+ Result := IntToStr(y);
+ end;
+ Result := Result + '.' + IntToStr(x);
+ end;
+end;
+
+{==============================================================================}
+function IntMibToStr(const Value: AnsiString): AnsiString;
+var
+ n, y: Integer;
+begin
+ y := 0;
+ for n := 1 to Length(Value) - 1 do
+ y := y * 256 + Ord(Value[n]);
+ Result := IntToStr(y);
+end;
+
+{==============================================================================}
+function ASNdump(const Value: AnsiString): AnsiString;
+var
+ i, at, x, n: integer;
+ s, indent: AnsiString;
+ il: TStringList;
+begin
+ il := TStringList.Create;
+ try
+ Result := '';
+ i := 1;
+ indent := '';
+ while i < Length(Value) do
+ begin
+ for n := il.Count - 1 downto 0 do
+ begin
+ x := StrToIntDef(il[n], 0);
+ if x <= i then
+ begin
+ il.Delete(n);
+ Delete(indent, 1, 2);
+ end;
+ end;
+ s := ASNItem(i, Value, at);
+ Result := Result + indent + '$' + IntToHex(at, 2);
+ if (at and $20) > 0 then
+ begin
+ x := Length(s);
+ Result := Result + ' constructed: length ' + IntToStr(x);
+ indent := indent + ' ';
+ il.Add(IntToStr(x + i - 1));
+ end
+ else
+ begin
+ case at of
+ ASN1_BOOL:
+ Result := Result + ' BOOL: ';
+ ASN1_INT:
+ Result := Result + ' INT: ';
+ ASN1_ENUM:
+ Result := Result + ' ENUM: ';
+ ASN1_COUNTER:
+ Result := Result + ' COUNTER: ';
+ ASN1_GAUGE:
+ Result := Result + ' GAUGE: ';
+ ASN1_TIMETICKS:
+ Result := Result + ' TIMETICKS: ';
+ ASN1_OCTSTR:
+ Result := Result + ' OCTSTR: ';
+ ASN1_OPAQUE:
+ Result := Result + ' OPAQUE: ';
+ ASN1_OBJID:
+ Result := Result + ' OBJID: ';
+ ASN1_IPADDR:
+ Result := Result + ' IPADDR: ';
+ ASN1_NULL:
+ Result := Result + ' NULL: ';
+ else // other
+ Result := Result + ' unknown: ';
+ end;
+ if IsBinaryString(s) then
+ s := DumpExStr(s);
+ Result := Result + s;
+ end;
+ Result := Result + #$0d + #$0a;
+ end;
+ finally
+ il.Free;
+ end;
+end;
+
+{==============================================================================}
+
+end.
diff --git a/branches/script-component/Units/Synapse/blcksock.pas b/branches/script-component/Units/Synapse/blcksock.pas
new file mode 100644
index 0000000..3ac6b6a
--- /dev/null
+++ b/branches/script-component/Units/Synapse/blcksock.pas
@@ -0,0 +1,4169 @@
+{==============================================================================|
+| Project : Ararat Synapse | 009.006.000 |
+|==============================================================================|
+| Content: Library base |
+|==============================================================================|
+| Copyright (c)1999-2008, Lukas Gebauer |
+| All rights reserved. |
+| |
+| Redistribution and use in source and binary forms, with or without |
+| modification, are permitted provided that the following conditions are met: |
+| |
+| Redistributions of source code must retain the above copyright notice, this |
+| list of conditions and the following disclaimer. |
+| |
+| Redistributions in binary form must reproduce the above copyright notice, |
+| this list of conditions and the following disclaimer in the documentation |
+| and/or other materials provided with the distribution. |
+| |
+| Neither the name of Lukas Gebauer nor the names of its contributors may |
+| be used to endorse or promote products derived from this software without |
+| specific prior written permission. |
+| |
+| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
+| AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
+| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
+| ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR |
+| ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
+| DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
+| SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
+| CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
+| LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
+| OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
+| DAMAGE. |
+|==============================================================================|
+| The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).|
+| Portions created by Lukas Gebauer are Copyright (c)1999-2008. |
+| All Rights Reserved. |
+|==============================================================================|
+| Contributor(s): |
+|==============================================================================|
+| History: see HISTORY.HTM from distribution package |
+| (Found at URL: http://www.ararat.cz/synapse/) |
+|==============================================================================}
+
+{
+Special thanks to Gregor Ibic
+ (Intelicom d.o.o., http://www.intelicom.si)
+ for good inspiration about SSL programming.
+}
+
+{$DEFINE ONCEWINSOCK}
+{Note about define ONCEWINSOCK:
+If you remove this compiler directive, then socket interface is loaded and
+initialized on constructor of TBlockSocket class for each socket separately.
+Socket interface is used only if your need it.
+
+If you leave this directive here, then socket interface is loaded and
+initialized only once at start of your program! It boost performace on high
+count of created and destroyed sockets. It eliminate possible small resource
+leak on Windows systems too.
+}
+
+//{$DEFINE RAISEEXCEPT}
+{When you enable this define, then is Raiseexcept property is on by default
+}
+
+{:@abstract(Synapse's library core)
+
+Core with implementation basic socket classes.
+}
+
+{$IFDEF FPC}
+ {$MODE DELPHI}
+{$ENDIF}
+{$IFDEF VER125}
+ {$DEFINE BCB}
+{$ENDIF}
+{$IFDEF BCB}
+ {$ObjExportAll On}
+{$ENDIF}
+{$Q-}
+{$H+}
+{$M+}
+
+unit blcksock;
+
+interface
+
+uses
+ SysUtils, Classes,
+ synafpc,
+ synsock, synautil, synacode, synaip
+{$IFDEF CIL}
+ ,System.Net
+ ,System.Net.Sockets
+ ,System.Text
+{$ENDIF}
+ ;
+
+const
+
+ SynapseRelease = '38';
+
+ cLocalhost = '127.0.0.1';
+ cAnyHost = '0.0.0.0';
+ cBroadcast = '255.255.255.255';
+ c6Localhost = '::1';
+ c6AnyHost = '::0';
+ c6Broadcast = 'ffff::1';
+ cAnyPort = '0';
+ CR = #$0d;
+ LF = #$0a;
+ CRLF = CR + LF;
+ c64k = 65536;
+
+type
+
+ {:@abstract(Exception clas used by Synapse)
+ When you enable generating of exceptions, this exception is raised by
+ Synapse's units.}
+ ESynapseError = class(Exception)
+ private
+ FErrorCode: Integer;
+ FErrorMessage: string;
+ published
+ {:Code of error. Value depending on used operating system}
+ property ErrorCode: Integer read FErrorCode Write FErrorCode;
+ {:Human readable description of error.}
+ property ErrorMessage: string read FErrorMessage Write FErrorMessage;
+ end;
+
+ {:Types of OnStatus events}
+ THookSocketReason = (
+ {:Resolving is begin. Resolved IP and port is in parameter in format like:
+ 'localhost.somewhere.com:25'.}
+ HR_ResolvingBegin,
+ {:Resolving is done. Resolved IP and port is in parameter in format like:
+ 'localhost.somewhere.com:25'. It is always same as in HR_ResolvingBegin!}
+ HR_ResolvingEnd,
+ {:Socket created by CreateSocket method. It reporting Family of created
+ socket too!}
+ HR_SocketCreate,
+ {:Socket closed by CloseSocket method.}
+ HR_SocketClose,
+ {:Socket binded to IP and Port. Binded IP and Port is in parameter in format
+ like: 'localhost.somewhere.com:25'.}
+ HR_Bind,
+ {:Socket connected to IP and Port. Connected IP and Port is in parameter in
+ format like: 'localhost.somewhere.com:25'.}
+ HR_Connect,
+ {:Called when CanRead method is used with @True result.}
+ HR_CanRead,
+ {:Called when CanWrite method is used with @True result.}
+ HR_CanWrite,
+ {:Socket is swithed to Listen mode. (TCP socket only)}
+ HR_Listen,
+ {:Socket Accepting client connection. (TCP socket only)}
+ HR_Accept,
+ {:report count of bytes readed from socket. Number is in parameter string.
+ If you need is in integer, you must use StrToInt function!}
+ HR_ReadCount,
+ {:report count of bytes writed to socket. Number is in parameter string. If
+ you need is in integer, you must use StrToInt function!}
+ HR_WriteCount,
+ {:If is limiting of bandwidth on, then this reason is called when sending or
+ receiving is stopped for satisfy bandwidth limit. Parameter is count of
+ waiting milliseconds.}
+ HR_Wait,
+ {:report situation where communication error occured. When raiseexcept is
+ @true, then exception is called after this Hook reason.}
+ HR_Error
+ );
+
+ {:Procedural type for OnStatus event. Sender is calling TBlockSocket object,
+ Reason is one of set Status events and value is optional data.}
+ THookSocketStatus = procedure(Sender: TObject; Reason: THookSocketReason;
+ const Value: String) of object;
+
+ {:This procedural type is used for DataFilter hooks.}
+ THookDataFilter = procedure(Sender: TObject; var Value: AnsiString) of object;
+
+ {:This procedural type is used for hook OnCreateSocket. By this hook you can
+ insert your code after initialisation of socket. (you can set special socket
+ options, etc.)}
+ THookCreateSocket = procedure(Sender: TObject) of object;
+
+ {:This procedural type is used for monitoring of communication.}
+ THookMonitor = procedure(Sender: TObject; Writing: Boolean;
+ const Buffer: TMemory; Len: Integer) of object;
+
+ {:This procedural type is used for hook OnAfterConnect. By this hook you can
+ insert your code after TCP socket has been sucessfully connected.}
+ THookAfterConnect = procedure(Sender: TObject) of object;
+
+ {:This procedural type is used for hook OnHeartbeat. By this hook you can
+ call your code repeately during long socket operations.
+ You must enable heartbeats by @Link(HeartbeatRate) property!}
+ THookHeartbeat = procedure(Sender: TObject) of object;
+
+ {:Specify family of socket.}
+ TSocketFamily = (
+ {:Default mode. Socket family is defined by target address for connection.
+ It allows instant access to IPv4 and IPv6 nodes. When you need IPv6 address
+ as destination, then is used IPv6 mode. othervise is used IPv4 mode.
+ However this mode not working properly with preliminary IPv6 supports!}
+ SF_Any,
+ {:Turn this class to pure IPv4 mode. This mode is totally compatible with
+ previous Synapse releases.}
+ SF_IP4,
+ {:Turn to only IPv6 mode.}
+ SF_IP6
+ );
+
+ {:specify possible values of SOCKS modes.}
+ TSocksType = (
+ ST_Socks5,
+ ST_Socks4
+ );
+
+ {:Specify requested SSL/TLS version for secure connection.}
+ TSSLType = (
+ LT_all,
+ LT_SSLv2,
+ LT_SSLv3,
+ LT_TLSv1,
+ LT_TLSv1_1,
+ LT_SSHv2
+ );
+
+ {:Specify type of socket delayed option.}
+ TSynaOptionType = (
+ SOT_Linger,
+ SOT_RecvBuff,
+ SOT_SendBuff,
+ SOT_NonBlock,
+ SOT_RecvTimeout,
+ SOT_SendTimeout,
+ SOT_Reuse,
+ SOT_TTL,
+ SOT_Broadcast,
+ SOT_MulticastTTL,
+ SOT_MulticastLoop
+ );
+
+ {:@abstract(this object is used for remember delayed socket option set.)}
+ TSynaOption = class(TObject)
+ public
+ Option: TSynaOptionType;
+ Enabled: Boolean;
+ Value: Integer;
+ end;
+
+ TCustomSSL = class;
+ TSSLClass = class of TCustomSSL;
+
+ {:@abstract(Basic IP object.)
+ This is parent class for other class with protocol implementations. Do not
+ use this class directly! Use @link(TICMPBlockSocket), @link(TRAWBlockSocket),
+ @link(TTCPBlockSocket) or @link(TUDPBlockSocket) instead.}
+ TBlockSocket = class(TObject)
+ private
+ FOnStatus: THookSocketStatus;
+ FOnReadFilter: THookDataFilter;
+ FOnCreateSocket: THookCreateSocket;
+ FOnMonitor: THookMonitor;
+ FOnHeartbeat: THookHeartbeat;
+ FLocalSin: TVarSin;
+ FRemoteSin: TVarSin;
+ FTag: integer;
+ FBuffer: AnsiString;
+ FRaiseExcept: Boolean;
+ FNonBlockMode: Boolean;
+ FMaxLineLength: Integer;
+ FMaxSendBandwidth: Integer;
+ FNextSend: LongWord;
+ FMaxRecvBandwidth: Integer;
+ FNextRecv: LongWord;
+ FConvertLineEnd: Boolean;
+ FLastCR: Boolean;
+ FLastLF: Boolean;
+ FBinded: Boolean;
+ FFamily: TSocketFamily;
+ FFamilySave: TSocketFamily;
+ FIP6used: Boolean;
+ FPreferIP4: Boolean;
+ FDelayedOptions: TList;
+ FInterPacketTimeout: Boolean;
+ {$IFNDEF CIL}
+ FFDSet: TFDSet;
+ {$ENDIF}
+ FRecvCounter: Integer;
+ FSendCounter: Integer;
+ FSendMaxChunk: Integer;
+ FStopFlag: Boolean;
+ FNonblockSendTimeout: Integer;
+ FHeartbeatRate: integer;
+ function GetSizeRecvBuffer: Integer;
+ procedure SetSizeRecvBuffer(Size: Integer);
+ function GetSizeSendBuffer: Integer;
+ procedure SetSizeSendBuffer(Size: Integer);
+ procedure SetNonBlockMode(Value: Boolean);
+ procedure SetTTL(TTL: integer);
+ function GetTTL:integer;
+ procedure SetFamily(Value: TSocketFamily); virtual;
+ procedure SetSocket(Value: TSocket); virtual;
+ function GetWsaData: TWSAData;
+ function FamilyToAF(f: TSocketFamily): TAddrFamily;
+ protected
+ FSocket: TSocket;
+ FLastError: Integer;
+ FLastErrorDesc: string;
+ procedure SetDelayedOption(const Value: TSynaOption);
+ procedure DelayedOption(const Value: TSynaOption);
+ procedure ProcessDelayedOptions;
+ procedure InternalCreateSocket(Sin: TVarSin);
+ procedure SetSin(var Sin: TVarSin; IP, Port: string);
+ function GetSinIP(Sin: TVarSin): string;
+ function GetSinPort(Sin: TVarSin): Integer;
+ procedure DoStatus(Reason: THookSocketReason; const Value: string);
+ procedure DoReadFilter(Buffer: TMemory; var Len: Integer);
+ procedure DoMonitor(Writing: Boolean; const Buffer: TMemory; Len: Integer);
+ procedure DoCreateSocket;
+ procedure DoHeartbeat;
+ procedure LimitBandwidth(Length: Integer; MaxB: integer; var Next: LongWord);
+ procedure SetBandwidth(Value: Integer);
+ function TestStopFlag: Boolean;
+ procedure InternalSendStream(const Stream: TStream; WithSize, Indy: boolean); virtual;
+ function InternalCanRead(Timeout: Integer): Boolean; virtual;
+ public
+ constructor Create;
+
+ {:Create object and load all necessary socket library. What library is
+ loaded is described by STUB parameter. If STUB is empty string, then is
+ loaded default libraries.}
+ constructor CreateAlternate(Stub: string);
+ destructor Destroy; override;
+
+ {:If @link(family) is not SF_Any, then create socket with type defined in
+ @link(Family) property. If family is SF_Any, then do nothing! (socket is
+ created automaticly when you know what type of socket you need to create.
+ (i.e. inside @link(Connect) or @link(Bind) call.) When socket is created,
+ then is aplyed all stored delayed socket options.}
+ procedure CreateSocket;
+
+ {:It create socket. Address resolving of Value tells what type of socket is
+ created. If Value is resolved as IPv4 IP, then is created IPv4 socket. If
+ value is resolved as IPv6 address, then is created IPv6 socket.}
+ procedure CreateSocketByName(const Value: String);
+
+ {:Destroy socket in use. This method is also automatically called from
+ object destructor.}
+ procedure CloseSocket; virtual;
+
+ {:Abort any work on Socket and destroy them.}
+ procedure AbortSocket; virtual;
+
+ {:Connects socket to local IP address and PORT. IP address may be numeric or
+ symbolic ('192.168.74.50', 'cosi.nekde.cz', 'ff08::1'). The same for PORT
+ - it may be number or mnemonic port ('23', 'telnet').
+
+ If port value is '0', system chooses itself and conects unused port in the
+ range 1024 to 4096 (this depending by operating system!). Structure
+ LocalSin is filled after calling this method.
+
+ Note: If you call this on non-created socket, then socket is created
+ automaticly.
+
+ Warning: when you call : Bind('0.0.0.0','0'); then is nothing done! In this
+ case is used implicit system bind instead.}
+ procedure Bind(IP, Port: string);
+
+ {:Connects socket to remote IP address and PORT. The same rules as with
+ @link(BIND) method are valid. The only exception is that PORT with 0 value
+ will not be connected!
+
+ Structures LocalSin and RemoteSin will be filled with valid values.
+
+ When you call this on non-created socket, then socket is created
+ automaticly. Type of created socket is by @link(Family) property. If is
+ used SF_IP4, then is created socket for IPv4. If is used SF_IP6, then is
+ created socket for IPv6. When you have family on SF_Any (default!), then
+ type of created socket is determined by address resolving of destination
+ address. (Not work properly on prilimitary winsock IPv6 support!)}
+ procedure Connect(IP, Port: string); virtual;
+
+ {:Sends data of LENGTH from BUFFER address via connected socket. System
+ automatically splits data to packets.}
+ function SendBuffer(Buffer: Tmemory; Length: Integer): Integer; virtual;
+
+ {:One data BYTE is sent via connected socket.}
+ procedure SendByte(Data: Byte); virtual;
+
+ {:Send data string via connected socket. Any terminator is not added! If you
+ need send true string with CR-LF termination, you must add CR-LF characters
+ to sended string! Because any termination is not added automaticly, you can
+ use this function for sending any binary data in binary string.}
+ procedure SendString(Data: AnsiString); virtual;
+
+ {:Send integer as four bytes to socket.}
+ procedure SendInteger(Data: integer); virtual;
+
+ {:Send data as one block to socket. Each block begin with 4 bytes with
+ length of data in block. This 4 bytes is added automaticly by this
+ function.}
+ procedure SendBlock(const Data: AnsiString); virtual;
+
+ {:Send data from stream to socket.}
+ procedure SendStreamRaw(const Stream: TStream); virtual;
+
+ {:Send content of stream to socket. It using @link(SendBlock) method}
+ procedure SendStream(const Stream: TStream); virtual;
+
+ {:Send content of stream to socket. It using @link(SendBlock) method and
+ this is compatible with streams in Indy library.}
+ procedure SendStreamIndy(const Stream: TStream); virtual;
+
+ {:Note: This is low-level receive function. You must be sure if data is
+ waiting for read before call this function for avoid deadlock!
+
+ Waits until allocated buffer is filled by received data. Returns number of
+ data received, which equals to LENGTH value under normal operation. If it
+ is not equal the communication channel is possibly broken.
+
+ On stream oriented sockets if is received 0 bytes, it mean 'socket is
+ closed!"
+
+ On datagram socket is readed first waiting datagram.}
+ function RecvBuffer(Buffer: TMemory; Length: Integer): Integer; virtual;
+
+ {:Note: This is high-level receive function. It using internal
+ @link(LineBuffer) and you can combine this function freely with other
+ high-level functions!
+
+ Method waits until data is received. If no data is received within TIMEOUT
+ (in milliseconds) period, @link(LastError) is set to WSAETIMEDOUT. Methods
+ serves for reading any size of data (i.e. one megabyte...). This method is
+ preffered for reading from stream sockets (like TCP).}
+ function RecvBufferEx(Buffer: Tmemory; Len: Integer;
+ Timeout: Integer): Integer; virtual;
+
+ {:Similar to @link(RecvBufferEx), but readed data is stored in binary
+ string, not in memory buffer.}
+ function RecvBufferStr(Len: Integer; Timeout: Integer): AnsiString; virtual;
+
+ {:Note: This is high-level receive function. It using internal
+ @link(LineBuffer) and you can combine this function freely with other
+ high-level functions.
+
+ Waits until one data byte is received which is also returned as function
+ result. If no data is received within TIMEOUT (in milliseconds)period,
+ @link(LastError) is set to WSAETIMEDOUT and result have value 0.}
+ function RecvByte(Timeout: Integer): Byte; virtual;
+
+ {:Note: This is high-level receive function. It using internal
+ @link(LineBuffer) and you can combine this function freely with other
+ high-level functions.
+
+ Waits until one four bytes are received and return it as one Ineger Value.
+ If no data is received within TIMEOUT (in milliseconds)period,
+ @link(LastError) is set to WSAETIMEDOUT and result have value 0.}
+ function RecvInteger(Timeout: Integer): Integer; virtual;
+
+ {:Note: This is high-level receive function. It using internal
+ @link(LineBuffer) and you can combine this function freely with other
+ high-level functions.
+
+ Method waits until data string is received. This string is terminated by
+ CR-LF characters. The resulting string is returned without this termination
+ (CR-LF)! If @link(ConvertLineEnd) is used, then CR-LF sequence may not be
+ exactly CR-LF. See @link(ConvertLineEnd) description. If no data is
+ received within TIMEOUT (in milliseconds) period, @link(LastError) is set
+ to WSAETIMEDOUT. You may also specify maximum length of reading data by
+ @link(MaxLineLength) property.}
+ function RecvString(Timeout: Integer): AnsiString; virtual;
+
+ {:Note: This is high-level receive function. It using internal
+ @link(LineBuffer) and you can combine this function freely with other
+ high-level functions.
+
+ Method waits until data string is received. This string is terminated by
+ Terminator string. The resulting string is returned without this
+ termination. If no data is received within TIMEOUT (in milliseconds)
+ period, @link(LastError) is set to WSAETIMEDOUT. You may also specify
+ maximum length of reading data by @link(MaxLineLength) property.}
+ function RecvTerminated(Timeout: Integer; const Terminator: AnsiString): AnsiString; virtual;
+
+ {:Note: This is high-level receive function. It using internal
+ @link(LineBuffer) and you can combine this function freely with other
+ high-level functions.
+
+ Method reads all data waiting for read. If no data is received within
+ TIMEOUT (in milliseconds) period, @link(LastError) is set to WSAETIMEDOUT.
+ Methods serves for reading unknown size of data. Because before call this
+ function you don't know size of received data, returned data is stored in
+ dynamic size binary string. This method is preffered for reading from
+ stream sockets (like TCP). It is very goot for receiving datagrams too!
+ (UDP protocol)}
+ function RecvPacket(Timeout: Integer): AnsiString; virtual;
+
+ {:Read one block of data from socket. Each block begin with 4 bytes with
+ length of data in block. This function read first 4 bytes for get lenght,
+ then it wait for reported count of bytes.}
+ function RecvBlock(Timeout: Integer): AnsiString; virtual;
+
+ {:Read all data from socket to stream until socket is closed (or any error
+ occured.)}
+ procedure RecvStreamRaw(const Stream: TStream; Timeout: Integer); virtual;
+ {:Read requested count of bytes from socket to stream.}
+ procedure RecvStreamSize(const Stream: TStream; Timeout: Integer; Size: Integer);
+
+ {:Receive data to stream. It using @link(RecvBlock) method.}
+ procedure RecvStream(const Stream: TStream; Timeout: Integer); virtual;
+
+ {:Receive data to stream. This function is compatible with similar function
+ in Indy library. It using @link(RecvBlock) method.}
+ procedure RecvStreamIndy(const Stream: TStream; Timeout: Integer); virtual;
+
+ {:Same as @link(RecvBuffer), but readed data stays in system input buffer.
+ Warning: this function not respect data in @link(LineBuffer)! Is not
+ recommended to use this function!}
+ function PeekBuffer(Buffer: TMemory; Length: Integer): Integer; virtual;
+
+ {:Same as @link(RecvByte), but readed data stays in input system buffer.
+ Warning: this function not respect data in @link(LineBuffer)! Is not
+ recommended to use this function!}
+ function PeekByte(Timeout: Integer): Byte; virtual;
+
+ {:On stream sockets it returns number of received bytes waiting for picking.
+ 0 is returned when there is no such data. On datagram socket it returns
+ length of the first waiting datagram. Returns 0 if no datagram is waiting.}
+ function WaitingData: Integer; virtual;
+
+ {:Same as @link(WaitingData), but if exists some of data in @link(Linebuffer),
+ return their length instead.}
+ function WaitingDataEx: Integer;
+
+ {:Clear all waiting data for read from buffers.}
+ procedure Purge;
+
+ {:Sets linger. Enabled linger means that the system waits another LINGER
+ (in milliseconds) time for delivery of sent data. This function is only for
+ stream type of socket! (TCP)}
+ procedure SetLinger(Enable: Boolean; Linger: Integer);
+
+ {:Actualize values in @link(LocalSin).}
+ procedure GetSinLocal;
+
+ {:Actualize values in @link(RemoteSin).}
+ procedure GetSinRemote;
+
+ {:Actualize values in @link(LocalSin) and @link(RemoteSin).}
+ procedure GetSins;
+
+ {:Reset @link(LastError) and @link(LastErrorDesc) to non-error state.}
+ procedure ResetLastError;
+
+ {:If you "manually" call Socket API functions, forward their return code as
+ parameter to this function, which evaluates it, eventually calls
+ GetLastError and found error code returns and stores to @link(LastError).}
+ function SockCheck(SockResult: Integer): Integer; virtual;
+
+ {:If @link(LastError) contains some error code and @link(RaiseExcept)
+ property is @true, raise adequate exception.}
+ procedure ExceptCheck;
+
+ {:Returns local computer name as numerical or symbolic value. It try get
+ fully qualified domain name. Name is returned in the format acceptable by
+ functions demanding IP as input parameter.}
+ function LocalName: string;
+
+ {:Try resolve name to all possible IP address. i.e. If you pass as name
+ result of @link(LocalName) method, you get all IP addresses used by local
+ system.}
+ procedure ResolveNameToIP(Name: string; const IPList: TStrings);
+
+ {:Try resolve name to primary IP address. i.e. If you pass as name result of
+ @link(LocalName) method, you get primary IP addresses used by local system.}
+ function ResolveName(Name: string): string;
+
+ {:Try resolve IP to their primary domain name. If IP not have domain name,
+ then is returned original IP.}
+ function ResolveIPToName(IP: string): string;
+
+ {:Try resolve symbolic port name to port number. (i.e. 'Echo' to 8)}
+ function ResolvePort(Port: string): Word;
+
+ {:Set information about remote side socket. It is good for seting remote
+ side for sending UDP packet, etc.}
+ procedure SetRemoteSin(IP, Port: string);
+
+ {:Picks IP socket address from @link(LocalSin).}
+ function GetLocalSinIP: string; virtual;
+
+ {:Picks IP socket address from @link(RemoteSin).}
+ function GetRemoteSinIP: string; virtual;
+
+ {:Picks socket PORT number from @link(LocalSin).}
+ function GetLocalSinPort: Integer; virtual;
+
+ {:Picks socket PORT number from @link(RemoteSin).}
+ function GetRemoteSinPort: Integer; virtual;
+
+ {:Return @TRUE, if you can read any data from socket or is incoming
+ connection on TCP based socket. Status is tested for time Timeout (in
+ milliseconds). If value in Timeout is 0, status is only tested and
+ continue. If value in Timeout is -1, run is breaked and waiting for read
+ data maybe forever.
+
+ This function is need only on special cases, when you need use
+ @link(RecvBuffer) function directly! read functioms what have timeout as
+ calling parameter, calling this function internally.}
+ function CanRead(Timeout: Integer): Boolean; virtual;
+
+ {:Same as @link(CanRead), but additionally return @TRUE if is some data in
+ @link(LineBuffer).}
+ function CanReadEx(Timeout: Integer): Boolean; virtual;
+
+ {:Return @TRUE, if you can to socket write any data (not full sending
+ buffer). Status is tested for time Timeout (in milliseconds). If value in
+ Timeout is 0, status is only tested and continue. If value in Timeout is
+ -1, run is breaked and waiting for write data maybe forever.
+
+ This function is need only on special cases!}
+ function CanWrite(Timeout: Integer): Boolean; virtual;
+
+ {:Same as @link(SendBuffer), but send datagram to address from
+ @link(RemoteSin). Usefull for sending reply to datagram received by
+ function @link(RecvBufferFrom).}
+ function SendBufferTo(Buffer: TMemory; Length: Integer): Integer; virtual;
+
+ {:Note: This is low-lever receive function. You must be sure if data is
+ waiting for read before call this function for avoid deadlock!
+
+ Receives first waiting datagram to allocated buffer. If there is no waiting
+ one, then waits until one comes. Returns length of datagram stored in
+ BUFFER. If length exceeds buffer datagram is truncated. After this
+ @link(RemoteSin) structure contains information about sender of UDP packet.}
+ function RecvBufferFrom(Buffer: TMemory; Length: Integer): Integer; virtual;
+{$IFNDEF CIL}
+ {:This function is for check for incoming data on set of sockets. Whitch
+ sockets is checked is decribed by SocketList Tlist with TBlockSocket
+ objects. TList may have maximal number of objects defined by FD_SETSIZE
+ constant. Return @TRUE, if you can from some socket read any data or is
+ incoming connection on TCP based socket. Status is tested for time Timeout
+ (in milliseconds). If value in Timeout is 0, status is only tested and
+ continue. If value in Timeout is -1, run is breaked and waiting for read
+ data maybe forever. If is returned @TRUE, CanReadList TList is filled by all
+ TBlockSocket objects what waiting for read.}
+ function GroupCanRead(const SocketList: TList; Timeout: Integer;
+ const CanReadList: TList): Boolean;
+{$ENDIF}
+ {:By this method you may turn address reuse mode for local @link(bind). It
+ is good specially for UDP protocol. Using this with TCP protocol is
+ hazardous!}
+ procedure EnableReuse(Value: Boolean);
+
+ {:Try set timeout for all sending and receiving operations, if socket
+ provider can do it. (It not supported by all socket providers!)}
+ procedure SetTimeout(Timeout: Integer);
+
+ {:Try set timeout for all sending operations, if socket provider can do it.
+ (It not supported by all socket providers!)}
+ procedure SetSendTimeout(Timeout: Integer);
+
+ {:Try set timeout for all receiving operations, if socket provider can do
+ it. (It not supported by all socket providers!)}
+ procedure SetRecvTimeout(Timeout: Integer);
+
+ {:Return value of socket type.}
+ function GetSocketType: integer; Virtual;
+
+ {:Return value of protocol type for socket creation.}
+ function GetSocketProtocol: integer; Virtual;
+
+ {:WSA structure with information about socket provider. On linux is this
+ structure simulated!}
+ property WSAData: TWSADATA read GetWsaData;
+
+ {:Structure describing local socket side.}
+ property LocalSin: TVarSin read FLocalSin write FLocalSin;
+
+ {:Structure describing remote socket side.}
+ property RemoteSin: TVarSin read FRemoteSin write FRemoteSin;
+
+ {:Socket handler. Suitable for "manual" calls to socket API or manual
+ connection of socket to a previously created socket (i.e by Accept method
+ on TCP socket)}
+ property Socket: TSocket read FSocket write SetSocket;
+
+ {:Last socket operation error code. Error codes are described in socket
+ documentation. Human readable error description is stored in
+ @link(LastErrorDesc) property.}
+ property LastError: Integer read FLastError;
+
+ {:Human readable error description of @link(LastError) code.}
+ property LastErrorDesc: string read FLastErrorDesc;
+
+ {:Buffer used by all high-level receiving functions. This buffer is used for
+ optimized reading of data from socket. In normal cases you not need access
+ to this buffer directly!}
+ property LineBuffer: AnsiString read FBuffer write FBuffer;
+
+ {:Size of Winsock receive buffer. If it is not supported by socket provider,
+ it return as size one kilobyte.}
+ property SizeRecvBuffer: Integer read GetSizeRecvBuffer write SetSizeRecvBuffer;
+
+ {:Size of Winsock send buffer. If it is not supported by socket provider, it
+ return as size one kilobyte.}
+ property SizeSendBuffer: Integer read GetSizeSendBuffer write SetSizeSendBuffer;
+
+ {:If @True, turn class to non-blocking mode. Not all functions are working
+ properly in this mode, you must know exactly what you are doing! However
+ when you have big experience with non-blocking programming, then you can
+ optimise your program by non-block mode!}
+ property NonBlockMode: Boolean read FNonBlockMode Write SetNonBlockMode;
+
+ {:Set Time-to-live value. (if system supporting it!)}
+ property TTL: Integer read GetTTL Write SetTTL;
+
+ {:If is @true, then class in in IPv6 mode.}
+ property IP6used: Boolean read FIP6used;
+
+ {:Return count of received bytes on this socket from begin of current
+ connection.}
+ property RecvCounter: Integer read FRecvCounter;
+
+ {:Return count of sended bytes on this socket from begin of current
+ connection.}
+ property SendCounter: Integer read FSendCounter;
+ published
+ {:Return descriptive string for given error code. This is class function.
+ You may call it without created object!}
+ class function GetErrorDesc(ErrorCode: Integer): string;
+
+ {:Return descriptive string for @link(LastError).}
+ function GetErrorDescEx: string; virtual;
+
+ {:this value is for free use.}
+ property Tag: Integer read FTag write FTag;
+
+ {:If @true, winsock errors raises exception. Otherwise is setted
+ @link(LastError) value only and you must check it from your program! Default
+ value is @false.}
+ property RaiseExcept: Boolean read FRaiseExcept write FRaiseExcept;
+
+ {:Define maximum length in bytes of @link(LineBuffer) for high-level
+ receiving functions. If this functions try to read more data then this
+ limit, error is returned! If value is 0 (default), no limitation is used.
+ This is very good protection for stupid attacks to your server by sending
+ lot of data without proper terminator... until all your memory is allocated
+ by LineBuffer!
+
+ Note: This maximum length is checked only in functions, what read unknown
+ number of bytes! (like @link(RecvString) or @link(RecvTerminated))}
+ property MaxLineLength: Integer read FMaxLineLength Write FMaxLineLength;
+
+ {:Define maximal bandwidth for all sending operations in bytes per second.
+ If value is 0 (default), bandwidth limitation is not used.}
+ property MaxSendBandwidth: Integer read FMaxSendBandwidth Write FMaxSendBandwidth;
+
+ {:Define maximal bandwidth for all receiving operations in bytes per second.
+ If value is 0 (default), bandwidth limitation is not used.}
+ property MaxRecvBandwidth: Integer read FMaxRecvBandwidth Write FMaxRecvBandwidth;
+
+ {:Define maximal bandwidth for all sending and receiving operations in bytes
+ per second. If value is 0 (default), bandwidth limitation is not used.}
+ property MaxBandwidth: Integer Write SetBandwidth;
+
+ {:Do a conversion of non-standard line terminators to CRLF. (Off by default)
+ If @True, then terminators like sigle CR, single LF or LFCR are converted
+ to CRLF internally. This have effect only in @link(RecvString) method!}
+ property ConvertLineEnd: Boolean read FConvertLineEnd Write FConvertLineEnd;
+
+ {:Specified Family of this socket. When you are using Windows preliminary
+ support for IPv6, then I recommend to set this property!}
+ property Family: TSocketFamily read FFamily Write SetFamily;
+
+ {:When resolving of domain name return both IPv4 and IPv6 addresses, then
+ specify if is used IPv4 (dafault - @true) or IPv6.}
+ property PreferIP4: Boolean read FPreferIP4 Write FPreferIP4;
+
+ {:By default (@true) is all timeouts used as timeout between two packets in
+ reading operations. If you set this to @false, then Timeouts is for overall
+ reading operation!}
+ property InterPacketTimeout: Boolean read FInterPacketTimeout Write FInterPacketTimeout;
+
+ {:All sended datas was splitted by this value.}
+ property SendMaxChunk: Integer read FSendMaxChunk Write FSendMaxChunk;
+
+ {:By setting this property to @true you can stop any communication. You can
+ use this property for soft abort of communication.}
+ property StopFlag: Boolean read FStopFlag Write FStopFlag;
+
+ {:Timeout for data sending by non-blocking socket mode.}
+ property NonblockSendTimeout: Integer read FNonblockSendTimeout Write FNonblockSendTimeout;
+
+ {:This event is called by various reasons. It is good for monitoring socket,
+ create gauges for data transfers, etc.}
+ property OnStatus: THookSocketStatus read FOnStatus write FOnStatus;
+
+ {:this event is good for some internal thinks about filtering readed datas.
+ It is used by telnet client by example.}
+ property OnReadFilter: THookDataFilter read FOnReadFilter write FOnReadFilter;
+
+ {:This event is called after real socket creation for setting special socket
+ options, because you not know when socket is created. (it is depended on
+ Ipv4, IPv6 or automatic mode)}
+ property OnCreateSocket: THookCreateSocket read FOnCreateSocket write FOnCreateSocket;
+
+ {:This event is good for monitoring content of readed or writed datas.}
+ property OnMonitor: THookMonitor read FOnMonitor write FOnMonitor;
+
+ {:This event is good for calling your code during long socket operations.
+ (Example, for refresing UI if class in not called within the thread.)
+ Rate of heartbeats can be modified by @link(HeartbeatRate) property.}
+ property OnHeartbeat: THookHeartbeat read FOnHeartbeat write FOnHeartbeat;
+
+ {:Specify typical rate of @link(OnHeartbeat) event and @link(StopFlag) testing.
+ Default value 0 disabling heartbeats! Value is in milliseconds.
+ Real rate can be higher or smaller then this value, because it depending
+ on real socket operations too!
+ Note: Each heartbeat slowing socket processing.}
+ property HeartbeatRate: integer read FHeartbeatRate Write FHeartbeatRate;
+ end;
+
+ {:@abstract(Support for SOCKS4 and SOCKS5 proxy)
+ Layer with definition all necessary properties and functions for
+ implementation SOCKS proxy client. Do not use this class directly.}
+ TSocksBlockSocket = class(TBlockSocket)
+ protected
+ FSocksIP: string;
+ FSocksPort: string;
+ FSocksTimeout: integer;
+ FSocksUsername: string;
+ FSocksPassword: string;
+ FUsingSocks: Boolean;
+ FSocksResolver: Boolean;
+ FSocksLastError: integer;
+ FSocksResponseIP: string;
+ FSocksResponsePort: string;
+ FSocksLocalIP: string;
+ FSocksLocalPort: string;
+ FSocksRemoteIP: string;
+ FSocksRemotePort: string;
+ FBypassFlag: Boolean;
+ FSocksType: TSocksType;
+ function SocksCode(IP, Port: string): Ansistring;
+ function SocksDecode(Value: Ansistring): integer;
+ public
+ constructor Create;
+
+ {:Open connection to SOCKS proxy and if @link(SocksUsername) is set, do
+ authorisation to proxy. This is needed only in special cases! (it is called
+ internally!)}
+ function SocksOpen: Boolean;
+
+ {:Send specified request to SOCKS proxy. This is needed only in special
+ cases! (it is called internally!)}
+ function SocksRequest(Cmd: Byte; const IP, Port: string): Boolean;
+
+ {:Receive response to previosly sended request. This is needed only in
+ special cases! (it is called internally!)}
+ function SocksResponse: Boolean;
+
+ {:Is @True when class is using SOCKS proxy.}
+ property UsingSocks: Boolean read FUsingSocks;
+
+ {:If SOCKS proxy failed, here is error code returned from SOCKS proxy.}
+ property SocksLastError: integer read FSocksLastError;
+ published
+ {:Address of SOCKS server. If value is empty string, SOCKS support is
+ disabled. Assingning any value to this property enable SOCKS mode.
+ Warning: You cannot combine this mode with HTTP-tunneling mode!}
+ property SocksIP: string read FSocksIP write FSocksIP;
+
+ {:Port of SOCKS server. Default value is '1080'.}
+ property SocksPort: string read FSocksPort write FSocksPort;
+
+ {:If you need authorisation on SOCKS server, set username here.}
+ property SocksUsername: string read FSocksUsername write FSocksUsername;
+
+ {:If you need authorisation on SOCKS server, set password here.}
+ property SocksPassword: string read FSocksPassword write FSocksPassword;
+
+ {:Specify timeout for communicatin with SOCKS server. Default is one minute.}
+ property SocksTimeout: integer read FSocksTimeout write FSocksTimeout;
+
+ {:If @True, all symbolic names of target hosts is not translated to IP's
+ locally, but resolving is by SOCKS proxy. Default is @True.}
+ property SocksResolver: Boolean read FSocksResolver write FSocksResolver;
+
+ {:Specify SOCKS type. By default is used SOCKS5, but you can use SOCKS4 too.
+ When you select SOCKS4, then if @link(SOCKSResolver) is enabled, then is
+ used SOCKS4a. Othervise is used pure SOCKS4.}
+ property SocksType: TSocksType read FSocksType write FSocksType;
+ end;
+
+ {:@abstract(Implementation of TCP socket.)
+ Supported features: IPv4, IPv6, SSL/TLS or SSH (depending on used plugin),
+ SOCKS5 proxy (outgoing connections and limited incomming), SOCKS4/4a proxy
+ (outgoing connections and limited incomming), TCP through HTTP proxy tunnel.}
+ TTCPBlockSocket = class(TSocksBlockSocket)
+ protected
+ FOnAfterConnect: THookAfterConnect;
+ FSSL: TCustomSSL;
+ FHTTPTunnelIP: string;
+ FHTTPTunnelPort: string;
+ FHTTPTunnel: Boolean;
+ FHTTPTunnelRemoteIP: string;
+ FHTTPTunnelRemotePort: string;
+ FHTTPTunnelUser: string;
+ FHTTPTunnelPass: string;
+ FHTTPTunnelTimeout: integer;
+ procedure SocksDoConnect(IP, Port: string);
+ procedure HTTPTunnelDoConnect(IP, Port: string);
+ procedure DoAfterConnect;
+ public
+ {:Create TCP socket class with default plugin for SSL/TSL/SSH implementation
+ (see @link(SSLImplementation))}
+ constructor Create;
+
+ {:Create TCP socket class with desired plugin for SSL/TSL/SSH implementation}
+ constructor CreateWithSSL(SSLPlugin: TSSLClass);
+ destructor Destroy; override;
+
+ {:Return descriptive string for @link(LastError). On case of error
+ in SSL/TLS subsystem, it returns right error description.}
+ function GetErrorDescEx: string; override;
+
+ {:See @link(TBlockSocket.CloseSocket)}
+ procedure CloseSocket; override;
+
+ {:See @link(TBlockSocket.WaitingData)}
+ function WaitingData: Integer; override;
+
+ {:Sets socket to receive mode for new incoming connections. It is necessary
+ to use @link(TBlockSocket.BIND) function call before this method to select
+ receiving port!
+
+ If you use SOCKS, activate incoming TCP connection by this proxy. (By BIND
+ method of SOCKS.)}
+ procedure Listen; virtual;
+
+ {:Waits until new incoming connection comes. After it comes a new socket is
+ automatically created (socket handler is returned by this function as
+ result).
+
+ If you use SOCKS, new socket is not created! In this case is used same
+ socket as socket for listening! So, you can accept only one connection in
+ SOCKS mode.}
+ function Accept: TSocket;
+
+ {:Connects socket to remote IP address and PORT. The same rules as with
+ @link(TBlockSocket.BIND) method are valid. The only exception is that PORT
+ with 0 value will not be connected. After call to this method
+ a communication channel between local and remote socket is created. Local
+ socket is assigned automatically if not controlled by previous call to
+ @link(TBlockSocket.BIND) method. Structures @link(TBlockSocket.LocalSin)
+ and @link(TBlockSocket.RemoteSin) will be filled with valid values.
+
+ If you use SOCKS, activate outgoing TCP connection by SOCKS proxy specified
+ in @link(TSocksBlockSocket.SocksIP). (By CONNECT method of SOCKS.)
+
+ If you use HTTP-tunnel mode, activate outgoing TCP connection by HTTP
+ tunnel specified in @link(HTTPTunnelIP). (By CONNECT method of HTTP
+ protocol.)
+
+ Note: If you call this on non-created socket, then socket is created
+ automaticly.}
+ procedure Connect(IP, Port: string); override;
+
+ {:If you need upgrade existing TCP connection to SSL/TLS (or SSH2, if plugin
+ allows it) mode, then call this method. This method switch this class to
+ SSL mode and do SSL/TSL handshake.}
+ procedure SSLDoConnect;
+
+ {:By this method you can downgrade existing SSL/TLS connection to normal TCP
+ connection.}
+ procedure SSLDoShutdown;
+
+ {:If you need use this component as SSL/TLS TCP server, then after accepting
+ of inbound connection you need start SSL/TLS session by this method. Before
+ call this function, you must have assigned all neeeded certificates and
+ keys!}
+ function SSLAcceptConnection: Boolean;
+
+ {:See @link(TBlockSocket.GetLocalSinIP)}
+ function GetLocalSinIP: string; override;
+
+ {:See @link(TBlockSocket.GetRemoteSinIP)}
+ function GetRemoteSinIP: string; override;
+
+ {:See @link(TBlockSocket.GetLocalSinPort)}
+ function GetLocalSinPort: Integer; override;
+
+ {:See @link(TBlockSocket.GetRemoteSinPort)}
+ function GetRemoteSinPort: Integer; override;
+
+ {:See @link(TBlockSocket.SendBuffer)}
+ function SendBuffer(Buffer: TMemory; Length: Integer): Integer; override;
+
+ {:See @link(TBlockSocket.RecvBuffer)}
+ function RecvBuffer(Buffer: TMemory; Len: Integer): Integer; override;
+
+ {:Return value of socket type. For TCP return SOCK_STREAM.}
+ function GetSocketType: integer; override;
+
+ {:Return value of protocol type for socket creation. For TCP return
+ IPPROTO_TCP.}
+ function GetSocketProtocol: integer; override;
+
+ {:Class implementing SSL/TLS support. It is allways some descendant
+ of @link(TCustomSSL) class. When programmer not select some SSL plugin
+ class, then is used @link(TSSLNone)}
+ property SSL: TCustomSSL read FSSL;
+
+ {:@True if is used HTTP tunnel mode.}
+ property HTTPTunnel: Boolean read FHTTPTunnel;
+ published
+ {:Specify IP address of HTTP proxy. Assingning non-empty value to this
+ property enable HTTP-tunnel mode. This mode is for tunnelling any outgoing
+ TCP connection through HTTP proxy server. (If policy on HTTP proxy server
+ allow this!) Warning: You cannot combine this mode with SOCK5 mode!}
+ property HTTPTunnelIP: string read FHTTPTunnelIP Write FHTTPTunnelIP;
+
+ {:Specify port of HTTP proxy for HTTP-tunneling.}
+ property HTTPTunnelPort: string read FHTTPTunnelPort Write FHTTPTunnelPort;
+
+ {:Specify authorisation username for access to HTTP proxy in HTTP-tunnel
+ mode. If you not need authorisation, then let this property empty.}
+ property HTTPTunnelUser: string read FHTTPTunnelUser Write FHTTPTunnelUser;
+
+ {:Specify authorisation password for access to HTTP proxy in HTTP-tunnel
+ mode.}
+ property HTTPTunnelPass: string read FHTTPTunnelPass Write FHTTPTunnelPass;
+
+ {:Specify timeout for communication with HTTP proxy in HTTPtunnel mode.}
+ property HTTPTunnelTimeout: integer read FHTTPTunnelTimeout Write FHTTPTunnelTimeout;
+
+ {:This event is called after sucessful TCP socket connection.}
+ property OnAfterConnect: THookAfterConnect read FOnAfterConnect write FOnAfterConnect;
+ end;
+
+ {:@abstract(Datagram based communication)
+ This class implementing datagram based communication instead default stream
+ based communication style.}
+ TDgramBlockSocket = class(TSocksBlockSocket)
+ public
+ {:Fill @link(TBlockSocket.RemoteSin) structure. This address is used for
+ sending data.}
+ procedure Connect(IP, Port: string); override;
+
+ {:Silently redirected to @link(TBlockSocket.SendBufferTo).}
+ function SendBuffer(Buffer: TMemory; Length: Integer): Integer; override;
+
+ {:Silently redirected to @link(TBlockSocket.RecvBufferFrom).}
+ function RecvBuffer(Buffer: TMemory; Length: Integer): Integer; override;
+ end;
+
+ {:@abstract(Implementation of UDP socket.)
+ NOTE: in this class is all receiving redirected to RecvBufferFrom. You can
+ use for reading any receive function. Preffered is RecvPacket! Similary all
+ sending is redirected to SendbufferTo. You can use for sending UDP packet any
+ sending function, like SendString.
+
+ Supported features: IPv4, IPv6, unicasts, broadcasts, multicasts, SOCKS5
+ proxy (only unicasts! Outgoing and incomming.)}
+ TUDPBlockSocket = class(TDgramBlockSocket)
+ protected
+ FSocksControlSock: TTCPBlockSocket;
+ function UdpAssociation: Boolean;
+ procedure SetMulticastTTL(TTL: integer);
+ function GetMulticastTTL:integer;
+ public
+ destructor Destroy; override;
+
+ {:Enable or disable sending of broadcasts. If seting OK, result is @true.
+ This method is not supported in SOCKS5 mode! IPv6 does not support
+ broadcasts! In this case you must use Multicasts instead.}
+ procedure EnableBroadcast(Value: Boolean);
+
+ {:See @link(TBlockSocket.SendBufferTo)}
+ function SendBufferTo(Buffer: TMemory; Length: Integer): Integer; override;
+
+ {:See @link(TBlockSocket.RecvBufferFrom)}
+ function RecvBufferFrom(Buffer: TMemory; Length: Integer): Integer; override;
+{$IFNDEF CIL}
+ {:Add this socket to given multicast group. You cannot use Multicasts in
+ SOCKS mode!}
+ procedure AddMulticast(MCastIP:string);
+
+ {:Remove this socket from given multicast group.}
+ procedure DropMulticast(MCastIP:string);
+{$ENDIF}
+ {:All sended multicast datagrams is loopbacked to your interface too. (you
+ can read your sended datas.) You can disable this feature by this function.
+ This function not working on some Windows systems!}
+ procedure EnableMulticastLoop(Value: Boolean);
+
+ {:Return value of socket type. For UDP return SOCK_DGRAM.}
+ function GetSocketType: integer; override;
+
+ {:Return value of protocol type for socket creation. For UDP return
+ IPPROTO_UDP.}
+ function GetSocketProtocol: integer; override;
+
+ {:Set Time-to-live value for multicasts packets. It define number of routers
+ for transfer of datas. If you set this to 1 (dafault system value), then
+ multicasts packet goes only to you local network. If you need transport
+ multicast packet to worldwide, then increase this value, but be carefull,
+ lot of routers on internet does not transport multicasts packets!}
+ property MulticastTTL: Integer read GetMulticastTTL Write SetMulticastTTL;
+ end;
+
+ {:@abstract(Implementation of RAW ICMP socket.)
+ For this object you must have rights for creating RAW sockets!}
+ TICMPBlockSocket = class(TDgramBlockSocket)
+ public
+ {:Return value of socket type. For RAW and ICMP return SOCK_RAW.}
+ function GetSocketType: integer; override;
+
+ {:Return value of protocol type for socket creation. For ICMP returns
+ IPPROTO_ICMP or IPPROTO_ICMPV6}
+ function GetSocketProtocol: integer; override;
+ end;
+
+ {:@abstract(Implementation of RAW socket.)
+ For this object you must have rights for creating RAW sockets!}
+ TRAWBlockSocket = class(TBlockSocket)
+ public
+ {:Return value of socket type. For RAW and ICMP return SOCK_RAW.}
+ function GetSocketType: integer; override;
+
+ {:Return value of protocol type for socket creation. For RAW returns
+ IPPROTO_RAW.}
+ function GetSocketProtocol: integer; override;
+ end;
+
+ {:@abstract(Parent class for all SSL plugins.)
+ This is abstract class defining interface for other SSL plugins.
+
+ Instance of this class will be created for each @link(TTCPBlockSocket).
+
+ Warning: not all methods and propertis can work in all existing SSL plugins!
+ Please, read documentation of used SSL plugin.}
+ TCustomSSL = class(TObject)
+ protected
+ FSocket: TTCPBlockSocket;
+ FSSLEnabled: Boolean;
+ FLastError: integer;
+ FLastErrorDesc: string;
+ FSSLType: TSSLType;
+ FKeyPassword: string;
+ FCiphers: string;
+ FCertificateFile: string;
+ FPrivateKeyFile: string;
+ FCertificate: Ansistring;
+ FPrivateKey: Ansistring;
+ FPFX: Ansistring;
+ FPFXfile: string;
+ FCertCA: Ansistring;
+ FCertCAFile: string;
+ FTrustCertificate: Ansistring;
+ FTrustCertificateFile: string;
+ FVerifyCert: Boolean;
+ FUsername: string;
+ FPassword: string;
+ FSSHChannelType: string;
+ FSSHChannelArg1: string;
+ FSSHChannelArg2: string;
+ procedure ReturnError;
+ function CreateSelfSignedCert(Host: string): Boolean; virtual;
+ public
+ {: Create plugin class. it is called internally from @link(TTCPBlockSocket)}
+ constructor Create(const Value: TTCPBlockSocket); virtual;
+
+ {: Assign settings (certificates and configuration) from another SSL plugin
+ class.}
+ procedure Assign(const Value: TCustomSSL); virtual;
+
+ {: return description of used plugin. It usually return name and version
+ of used SSL library.}
+ function LibVersion: String; virtual;
+
+ {: return name of used plugin.}
+ function LibName: String; virtual;
+
+ {: Do not call this directly. It is used internally by @link(TTCPBlockSocket)!
+
+ Here is needed code for start SSL connection.}
+ function Connect: boolean; virtual;
+
+ {: Do not call this directly. It is used internally by @link(TTCPBlockSocket)!
+
+ Here is needed code for acept new SSL connection.}
+ function Accept: boolean; virtual;
+
+ {: Do not call this directly. It is used internally by @link(TTCPBlockSocket)!
+
+ Here is needed code for hard shutdown of SSL connection. (for example,
+ before socket is closed)}
+ function Shutdown: boolean; virtual;
+
+ {: Do not call this directly. It is used internally by @link(TTCPBlockSocket)!
+
+ Here is needed code for soft shutdown of SSL connection. (for example,
+ when you need to continue with unprotected connection.)}
+ function BiShutdown: boolean; virtual;
+
+ {: Do not call this directly. It is used internally by @link(TTCPBlockSocket)!
+
+ Here is needed code for sending some datas by SSL connection.}
+ function SendBuffer(Buffer: TMemory; Len: Integer): Integer; virtual;
+
+ {: Do not call this directly. It is used internally by @link(TTCPBlockSocket)!
+
+ Here is needed code for receiving some datas by SSL connection.}
+ function RecvBuffer(Buffer: TMemory; Len: Integer): Integer; virtual;
+
+ {: Do not call this directly. It is used internally by @link(TTCPBlockSocket)!
+
+ Here is needed code for getting count of datas what waiting for read.
+ If SSL plugin not allows this, then it should return 0.}
+ function WaitingData: Integer; virtual;
+
+ {:Return string with identificator of SSL/TLS version of existing
+ connection.}
+ function GetSSLVersion: string; virtual;
+
+ {:Return subject of remote SSL peer.}
+ function GetPeerSubject: string; virtual;
+
+ {:Return issuer certificate of remote SSL peer.}
+ function GetPeerIssuer: string; virtual;
+
+ {:Return peer name from remote side certificate. This is good for verify,
+ if certificate is generated for remote side IP name.}
+ function GetPeerName: string; virtual;
+
+ {:Return fingerprint of remote SSL peer.}
+ function GetPeerFingerprint: string; virtual;
+
+ {:Return all detailed information about certificate from remote side of
+ SSL/TLS connection. Result string can be multilined! Each plugin can return
+ this informations in different format!}
+ function GetCertInfo: string; virtual;
+
+ {:Return currently used Cipher.}
+ function GetCipherName: string; virtual;
+
+ {:Return currently used number of bits in current Cipher algorythm.}
+ function GetCipherBits: integer; virtual;
+
+ {:Return number of bits in current Cipher algorythm.}
+ function GetCipherAlgBits: integer; virtual;
+
+ {:Return result value of verify remote side certificate. Look to OpenSSL
+ documentation for possible values. For example 0 is successfuly verified
+ certificate, or 18 is self-signed certificate.}
+ function GetVerifyCert: integer; virtual;
+
+ {: Resurn @true if SSL mode is enabled on existing cvonnection.}
+ property SSLEnabled: Boolean read FSSLEnabled;
+
+ {:Return error code of last SSL operation. 0 is OK.}
+ property LastError: integer read FLastError;
+
+ {:Return error description of last SSL operation.}
+ property LastErrorDesc: string read FLastErrorDesc;
+ published
+ {:Here you can specify requested SSL/TLS mode. Default is autodetection, but
+ on some servers autodetection not working properly. In this case you must
+ specify requested SSL/TLS mode by your hand!}
+ property SSLType: TSSLType read FSSLType write FSSLType;
+
+ {:Password for decrypting of encoded certificate or key.}
+ property KeyPassword: string read FKeyPassword write FKeyPassword;
+
+ {:Username for possible credentials.}
+ property Username: string read FUsername write FUsername;
+
+ {:password for possible credentials.}
+ property Password: string read FPassword write FPassword;
+
+ {:By this property you can modify default set of SSL/TLS ciphers.}
+ property Ciphers: string read FCiphers write FCiphers;
+
+ {:Used for loading certificate from disk file. See to plugin documentation
+ if this method is supported and how!}
+ property CertificateFile: string read FCertificateFile write FCertificateFile;
+
+ {:Used for loading private key from disk file. See to plugin documentation
+ if this method is supported and how!}
+ property PrivateKeyFile: string read FPrivateKeyFile write FPrivateKeyFile;
+
+ {:Used for loading certificate from binary string. See to plugin documentation
+ if this method is supported and how!}
+ property Certificate: Ansistring read FCertificate write FCertificate;
+
+ {:Used for loading private key from binary string. See to plugin documentation
+ if this method is supported and how!}
+ property PrivateKey: Ansistring read FPrivateKey write FPrivateKey;
+
+ {:Used for loading PFX from binary string. See to plugin documentation
+ if this method is supported and how!}
+ property PFX: Ansistring read FPFX write FPFX;
+
+ {:Used for loading PFX from disk file. See to plugin documentation
+ if this method is supported and how!}
+ property PFXfile: string read FPFXfile write FPFXfile;
+
+ {:Used for loading trusted certificates from disk file. See to plugin documentation
+ if this method is supported and how!}
+ property TrustCertificateFile: string read FTrustCertificateFile write FTrustCertificateFile;
+
+ {:Used for loading trusted certificates from binary string. See to plugin documentation
+ if this method is supported and how!}
+ property TrustCertificate: Ansistring read FTrustCertificate write FTrustCertificate;
+
+ {:Used for loading CA certificates from binary string. See to plugin documentation
+ if this method is supported and how!}
+ property CertCA: Ansistring read FCertCA write FCertCA;
+
+ {:Used for loading CA certificates from disk file. See to plugin documentation
+ if this method is supported and how!}
+ property CertCAFile: string read FCertCAFile write FCertCAFile;
+
+ {:If @true, then is verified client certificate. (it is good for writing
+ SSL/TLS servers.) When you are not server, but you are client, then if this
+ property is @true, verify servers certificate.}
+ property VerifyCert: Boolean read FVerifyCert write FVerifyCert;
+
+ {:channel type for possible SSH connections}
+ property SSHChannelType: string read FSSHChannelType write FSSHChannelType;
+
+ {:First argument of channel type for possible SSH connections}
+ property SSHChannelArg1: string read FSSHChannelArg1 write FSSHChannelArg1;
+
+ {:Second argument of channel type for possible SSH connections}
+ property SSHChannelArg2: string read FSSHChannelArg2 write FSSHChannelArg2;
+ end;
+
+ {:@abstract(Default SSL plugin with no SSL support.)
+ Dummy SSL plugin implementation for applications without SSL/TLS support.}
+ TSSLNone = class (TCustomSSL)
+ public
+ {:See @inherited}
+ function LibVersion: String; override;
+ {:See @inherited}
+ function LibName: String; override;
+ end;
+
+ {:@abstract(Record with definition of IP packet header.)
+ For reading data from ICMP or RAW sockets.}
+ TIPHeader = record
+ VerLen: Byte;
+ TOS: Byte;
+ TotalLen: Word;
+ Identifer: Word;
+ FragOffsets: Word;
+ TTL: Byte;
+ Protocol: Byte;
+ CheckSum: Word;
+ SourceIp: LongWord;
+ DestIp: LongWord;
+ Options: LongWord;
+ end;
+
+ {:@abstract(Parent class of application protocol implementations.)
+ By this class is defined common properties.}
+ TSynaClient = Class(TObject)
+ protected
+ FTargetHost: string;
+ FTargetPort: string;
+ FIPInterface: string;
+ FTimeout: integer;
+ FUserName: string;
+ FPassword: string;
+ public
+ constructor Create;
+ published
+ {:Specify terget server IP (or symbolic name). Default is 'localhost'.}
+ property TargetHost: string read FTargetHost Write FTargetHost;
+
+ {:Specify terget server port (or symbolic name).}
+ property TargetPort: string read FTargetPort Write FTargetPort;
+
+ {:Defined local socket address. (outgoing IP address). By default is used
+ '0.0.0.0' as wildcard for default IP.}
+ property IPInterface: string read FIPInterface Write FIPInterface;
+
+ {:Specify default timeout for socket operations.}
+ property Timeout: integer read FTimeout Write FTimeout;
+
+ {:If protocol need user authorization, then fill here username.}
+ property UserName: string read FUserName Write FUserName;
+
+ {:If protocol need user authorization, then fill here password.}
+ property Password: string read FPassword Write FPassword;
+ end;
+
+var
+ {:Selected SSL plugin. Default is @link(TSSLNone).
+
+ Do not change this value directly!!!
+
+ Just add your plugin unit to your project uses instead. Each plugin unit have
+ initialization code what modify this variable.}
+ SSLImplementation: TSSLClass = TSSLNone;
+
+implementation
+
+{$IFDEF ONCEWINSOCK}
+var
+ WsaDataOnce: TWSADATA;
+ e: ESynapseError;
+{$ENDIF}
+
+
+constructor TBlockSocket.Create;
+begin
+ CreateAlternate('');
+end;
+
+constructor TBlockSocket.CreateAlternate(Stub: string);
+{$IFNDEF ONCEWINSOCK}
+var
+ e: ESynapseError;
+{$ENDIF}
+begin
+ inherited Create;
+ FDelayedOptions := TList.Create;
+ FRaiseExcept := False;
+{$IFDEF RAISEEXCEPT}
+ FRaiseExcept := True;
+{$ENDIF}
+ FSocket := INVALID_SOCKET;
+ FBuffer := '';
+ FLastCR := False;
+ FLastLF := False;
+ FBinded := False;
+ FNonBlockMode := False;
+ FMaxLineLength := 0;
+ FMaxSendBandwidth := 0;
+ FNextSend := 0;
+ FMaxRecvBandwidth := 0;
+ FNextRecv := 0;
+ FConvertLineEnd := False;
+ FFamily := SF_Any;
+ FFamilySave := SF_Any;
+ FIP6used := False;
+ FPreferIP4 := True;
+ FInterPacketTimeout := True;
+ FRecvCounter := 0;
+ FSendCounter := 0;
+ FSendMaxChunk := c64k;
+ FStopFlag := False;
+ FNonblockSendTimeout := 15000;
+ FHeartbeatRate := 0;
+{$IFNDEF ONCEWINSOCK}
+ if Stub = '' then
+ Stub := DLLStackName;
+ if not InitSocketInterface(Stub) then
+ begin
+ e := ESynapseError.Create('Error loading Socket interface (' + Stub + ')!');
+ e.ErrorCode := 0;
+ e.ErrorMessage := 'Error loading Socket interface (' + Stub + ')!';
+ raise e;
+ end;
+ SockCheck(synsock.WSAStartup(WinsockLevel, FWsaDataOnce));
+ ExceptCheck;
+{$ENDIF}
+end;
+
+destructor TBlockSocket.Destroy;
+var
+ n: integer;
+ p: TSynaOption;
+begin
+ CloseSocket;
+{$IFNDEF ONCEWINSOCK}
+ synsock.WSACleanup;
+ DestroySocketInterface;
+{$ENDIF}
+ for n := FDelayedOptions.Count - 1 downto 0 do
+ begin
+ p := TSynaOption(FDelayedOptions[n]);
+ p.Free;
+ end;
+ FDelayedOptions.Free;
+ inherited Destroy;
+end;
+
+function TBlockSocket.FamilyToAF(f: TSocketFamily): TAddrFamily;
+begin
+ case f of
+ SF_ip4:
+ Result := AF_INET;
+ SF_ip6:
+ Result := AF_INET6;
+ else
+ Result := AF_UNSPEC;
+ end;
+end;
+
+procedure TBlockSocket.SetDelayedOption(const Value: TSynaOption);
+var
+ li: TLinger;
+ x: integer;
+ buf: TMemory;
+{$IFNDEF WIN32}
+ timeval: TTimeval;
+{$ENDIF}
+begin
+ case value.Option of
+ SOT_Linger:
+ begin
+ {$IFDEF CIL}
+ li := TLinger.Create(Value.Enabled, Value.Value div 1000);
+ synsock.SetSockOptObj(FSocket, integer(SOL_SOCKET), integer(SO_LINGER), li);
+ {$ELSE}
+ li.l_onoff := Ord(Value.Enabled);
+ li.l_linger := Value.Value div 1000;
+ buf := @li;
+ synsock.SetSockOpt(FSocket, integer(SOL_SOCKET), integer(SO_LINGER), buf, SizeOf(li));
+ {$ENDIF}
+ end;
+ SOT_RecvBuff:
+ begin
+ {$IFDEF CIL}
+ buf := System.BitConverter.GetBytes(value.Value);
+ {$ELSE}
+ buf := @Value.Value;
+ {$ENDIF}
+ synsock.SetSockOpt(FSocket, integer(SOL_SOCKET), integer(SO_RCVBUF),
+ buf, SizeOf(Value.Value));
+ end;
+ SOT_SendBuff:
+ begin
+ {$IFDEF CIL}
+ buf := System.BitConverter.GetBytes(value.Value);
+ {$ELSE}
+ buf := @Value.Value;
+ {$ENDIF}
+ synsock.SetSockOpt(FSocket, integer(SOL_SOCKET), integer(SO_SNDBUF),
+ buf, SizeOf(Value.Value));
+ end;
+ SOT_NonBlock:
+ begin
+ FNonBlockMode := Value.Enabled;
+ x := Ord(FNonBlockMode);
+ synsock.IoctlSocket(FSocket, FIONBIO, x);
+ end;
+ SOT_RecvTimeout:
+ begin
+ {$IFDEF CIL}
+ buf := System.BitConverter.GetBytes(value.Value);
+ synsock.SetSockOpt(FSocket, integer(SOL_SOCKET), integer(SO_RCVTIMEO),
+ buf, SizeOf(Value.Value));
+ {$ELSE}
+ {$IFDEF WIN32}
+ buf := @Value.Value;
+ synsock.SetSockOpt(FSocket, integer(SOL_SOCKET), integer(SO_RCVTIMEO),
+ buf, SizeOf(Value.Value));
+ {$ELSE}
+ timeval.tv_sec:=Value.Value div 1000;
+ timeval.tv_usec:=(Value.Value mod 1000) * 1000;
+ synsock.SetSockOpt(FSocket, integer(SOL_SOCKET), integer(SO_RCVTIMEO),
+ @timeval, SizeOf(timeval));
+ {$ENDIF}
+ {$ENDIF}
+ end;
+ SOT_SendTimeout:
+ begin
+ {$IFDEF CIL}
+ buf := System.BitConverter.GetBytes(value.Value);
+ {$ELSE}
+ {$IFDEF WIN32}
+ buf := @Value.Value;
+ synsock.SetSockOpt(FSocket, integer(SOL_SOCKET), integer(SO_SNDTIMEO),
+ buf, SizeOf(Value.Value));
+ {$ELSE}
+ timeval.tv_sec:=Value.Value div 1000;
+ timeval.tv_usec:=(Value.Value mod 1000) * 1000;
+ synsock.SetSockOpt(FSocket, integer(SOL_SOCKET), integer(SO_SNDTIMEO),
+ @timeval, SizeOf(timeval));
+ {$ENDIF}
+ {$ENDIF}
+ end;
+ SOT_Reuse:
+ begin
+ x := Ord(Value.Enabled);
+ {$IFDEF CIL}
+ buf := System.BitConverter.GetBytes(x);
+ {$ELSE}
+ buf := @x;
+ {$ENDIF}
+ synsock.SetSockOpt(FSocket, integer(SOL_SOCKET), integer(SO_REUSEADDR), buf, SizeOf(x));
+ end;
+ SOT_TTL:
+ begin
+ {$IFDEF CIL}
+ buf := System.BitConverter.GetBytes(value.Value);
+ {$ELSE}
+ buf := @Value.Value;
+ {$ENDIF}
+ if FIP6Used then
+ synsock.SetSockOpt(FSocket, integer(IPPROTO_IPV6), integer(IPV6_UNICAST_HOPS),
+ buf, SizeOf(Value.Value))
+ else
+ synsock.SetSockOpt(FSocket, integer(IPPROTO_IP), integer(IP_TTL),
+ buf, SizeOf(Value.Value));
+ end;
+ SOT_Broadcast:
+ begin
+//#todo1 broadcasty na IP6
+ x := Ord(Value.Enabled);
+ {$IFDEF CIL}
+ buf := System.BitConverter.GetBytes(x);
+ {$ELSE}
+ buf := @x;
+ {$ENDIF}
+ synsock.SetSockOpt(FSocket, integer(SOL_SOCKET), integer(SO_BROADCAST), buf, SizeOf(x));
+ end;
+ SOT_MulticastTTL:
+ begin
+ {$IFDEF CIL}
+ buf := System.BitConverter.GetBytes(value.Value);
+ {$ELSE}
+ buf := @Value.Value;
+ {$ENDIF}
+ if FIP6Used then
+ synsock.SetSockOpt(FSocket, integer(IPPROTO_IPV6), integer(IPV6_MULTICAST_HOPS),
+ buf, SizeOf(Value.Value))
+ else
+ synsock.SetSockOpt(FSocket, integer(IPPROTO_IP), integer(IP_MULTICAST_TTL),
+ buf, SizeOf(Value.Value));
+ end;
+ SOT_MulticastLoop:
+ begin
+ x := Ord(Value.Enabled);
+ {$IFDEF CIL}
+ buf := System.BitConverter.GetBytes(x);
+ {$ELSE}
+ buf := @x;
+ {$ENDIF}
+ if FIP6Used then
+ synsock.SetSockOpt(FSocket, integer(IPPROTO_IPV6), integer(IPV6_MULTICAST_LOOP), buf, SizeOf(x))
+ else
+ synsock.SetSockOpt(FSocket, integer(IPPROTO_IP), integer(IP_MULTICAST_LOOP), buf, SizeOf(x));
+ end;
+ end;
+ Value.free;
+end;
+
+procedure TBlockSocket.DelayedOption(const Value: TSynaOption);
+begin
+ if FSocket = INVALID_SOCKET then
+ begin
+ FDelayedOptions.Insert(0, Value);
+ end
+ else
+ SetDelayedOption(Value);
+end;
+
+procedure TBlockSocket.ProcessDelayedOptions;
+var
+ n: integer;
+ d: TSynaOption;
+begin
+ for n := FDelayedOptions.Count - 1 downto 0 do
+ begin
+ d := TSynaOption(FDelayedOptions[n]);
+ SetDelayedOption(d);
+ end;
+ FDelayedOptions.Clear;
+end;
+
+procedure TBlockSocket.SetSin(var Sin: TVarSin; IP, Port: string);
+var
+ f: TSocketFamily;
+begin
+ DoStatus(HR_ResolvingBegin, IP + ':' + Port);
+ ResetLastError;
+ //if socket exists, then use their type, else use users selection
+ f := SF_Any;
+ if (FSocket = INVALID_SOCKET) and (FFamily = SF_any) then
+ begin
+ if IsIP(IP) then
+ f := SF_IP4
+ else
+ if IsIP6(IP) then
+ f := SF_IP6;
+ end
+ else
+ f := FFamily;
+ FLastError := synsock.SetVarSin(sin, ip, port, FamilyToAF(f),
+ GetSocketprotocol, GetSocketType, FPreferIP4);
+ DoStatus(HR_ResolvingEnd, GetSinIP(sin) + ':' + IntTostr(GetSinPort(sin)));
+end;
+
+function TBlockSocket.GetSinIP(Sin: TVarSin): string;
+begin
+ Result := synsock.GetSinIP(sin);
+end;
+
+function TBlockSocket.GetSinPort(Sin: TVarSin): Integer;
+begin
+ Result := synsock.GetSinPort(sin);
+end;
+
+procedure TBlockSocket.CreateSocket;
+var
+ sin: TVarSin;
+begin
+ //dummy for SF_Any Family mode
+ ResetLastError;
+ if (FFamily <> SF_Any) and (FSocket = INVALID_SOCKET) then
+ begin
+ {$IFDEF CIL}
+ if FFamily = SF_IP6 then
+ sin := TVarSin.Create(IPAddress.Parse('::0'), 0)
+ else
+ sin := TVarSin.Create(IPAddress.Parse('0.0.0.0'), 0);
+ {$ELSE}
+ FillChar(Sin, Sizeof(Sin), 0);
+ if FFamily = SF_IP6 then
+ sin.sin_family := AF_INET6
+ else
+ sin.sin_family := AF_INET;
+ {$ENDIF}
+ InternalCreateSocket(Sin);
+ end;
+end;
+
+procedure TBlockSocket.CreateSocketByName(const Value: String);
+var
+ sin: TVarSin;
+begin
+ ResetLastError;
+ if FSocket = INVALID_SOCKET then
+ begin
+ SetSin(sin, value, '0');
+ if FLastError = 0 then
+ InternalCreateSocket(Sin);
+ end;
+end;
+
+procedure TBlockSocket.InternalCreateSocket(Sin: TVarSin);
+begin
+ FStopFlag := False;
+ FRecvCounter := 0;
+ FSendCounter := 0;
+ ResetLastError;
+ if FSocket = INVALID_SOCKET then
+ begin
+ FBuffer := '';
+ FBinded := False;
+ FIP6Used := Sin.AddressFamily = AF_INET6;
+ FSocket := synsock.Socket(integer(Sin.AddressFamily), GetSocketType, GetSocketProtocol);
+ if FSocket = INVALID_SOCKET then
+ FLastError := synsock.WSAGetLastError;
+ {$IFNDEF CIL}
+ FD_ZERO(FFDSet);
+ FD_SET(FSocket, FFDSet);
+ {$ENDIF}
+ ExceptCheck;
+ if FIP6used then
+ DoStatus(HR_SocketCreate, 'IPv6')
+ else
+ DoStatus(HR_SocketCreate, 'IPv4');
+ ProcessDelayedOptions;
+ DoCreateSocket;
+ end;
+end;
+
+procedure TBlockSocket.CloseSocket;
+begin
+ AbortSocket;
+end;
+
+procedure TBlockSocket.AbortSocket;
+var
+ n: integer;
+ p: TSynaOption;
+begin
+ if FSocket <> INVALID_SOCKET then
+ synsock.CloseSocket(FSocket);
+ FSocket := INVALID_SOCKET;
+ for n := FDelayedOptions.Count - 1 downto 0 do
+ begin
+ p := TSynaOption(FDelayedOptions[n]);
+ p.Free;
+ end;
+ FDelayedOptions.Clear;
+ FFamily := FFamilySave;
+ DoStatus(HR_SocketClose, '');
+end;
+
+procedure TBlockSocket.Bind(IP, Port: string);
+var
+ Sin: TVarSin;
+begin
+ ResetLastError;
+ if (FSocket <> INVALID_SOCKET)
+ or not((FFamily = SF_ANY) and (IP = cAnyHost) and (Port = cAnyPort)) then
+ begin
+ SetSin(Sin, IP, Port);
+ if FLastError = 0 then
+ begin
+ if FSocket = INVALID_SOCKET then
+ InternalCreateSocket(Sin);
+ SockCheck(synsock.Bind(FSocket, Sin));
+ GetSinLocal;
+ FBuffer := '';
+ FBinded := True;
+ end;
+ ExceptCheck;
+ DoStatus(HR_Bind, IP + ':' + Port);
+ end;
+end;
+
+procedure TBlockSocket.Connect(IP, Port: string);
+var
+ Sin: TVarSin;
+begin
+ SetSin(Sin, IP, Port);
+ if FLastError = 0 then
+ begin
+ if FSocket = INVALID_SOCKET then
+ InternalCreateSocket(Sin);
+ SockCheck(synsock.Connect(FSocket, Sin));
+ if FLastError = 0 then
+ GetSins;
+ FBuffer := '';
+ FLastCR := False;
+ FLastLF := False;
+ end;
+ ExceptCheck;
+ DoStatus(HR_Connect, IP + ':' + Port);
+end;
+
+procedure TBlockSocket.GetSinLocal;
+begin
+ synsock.GetSockName(FSocket, FLocalSin);
+end;
+
+procedure TBlockSocket.GetSinRemote;
+begin
+ synsock.GetPeerName(FSocket, FRemoteSin);
+end;
+
+procedure TBlockSocket.GetSins;
+begin
+ GetSinLocal;
+ GetSinRemote;
+end;
+
+procedure TBlockSocket.SetBandwidth(Value: Integer);
+begin
+ MaxSendBandwidth := Value;
+ MaxRecvBandwidth := Value;
+end;
+
+procedure TBlockSocket.LimitBandwidth(Length: Integer; MaxB: integer; var Next: LongWord);
+var
+ x: LongWord;
+ y: LongWord;
+ n: integer;
+begin
+ if FStopFlag then
+ exit;
+ if MaxB > 0 then
+ begin
+ y := GetTick;
+ if Next > y then
+ begin
+ x := Next - y;
+ if x > 0 then
+ begin
+ DoStatus(HR_Wait, IntToStr(x));
+ sleep(x mod 250);
+ for n := 1 to x div 250 do
+ if FStopFlag then
+ Break
+ else
+ sleep(250);
+ end;
+ end;
+ Next := GetTick + Trunc((Length / MaxB) * 1000);
+ end;
+end;
+
+function TBlockSocket.TestStopFlag: Boolean;
+begin
+ DoHeartbeat;
+ Result := FStopFlag;
+ if Result then
+ begin
+ FStopFlag := False;
+ FLastError := WSAECONNABORTED;
+ ExceptCheck;
+ end;
+end;
+
+
+function TBlockSocket.SendBuffer(Buffer: TMemory; Length: Integer): Integer;
+{$IFNDEF CIL}
+var
+ x, y: integer;
+ l, r: integer;
+ p: Pointer;
+{$ENDIF}
+begin
+ Result := 0;
+ if TestStopFlag then
+ Exit;
+ DoMonitor(True, Buffer, Length);
+{$IFDEF CIL}
+ Result := synsock.Send(FSocket, Buffer, Length, 0);
+{$ELSE}
+ l := Length;
+ x := 0;
+ while x < l do
+ begin
+ y := l - x;
+ if y > FSendMaxChunk then
+ y := FSendMaxChunk;
+ if y > 0 then
+ begin
+ LimitBandwidth(y, FMaxSendBandwidth, FNextsend);
+ p := IncPoint(Buffer, x);
+ r := synsock.Send(FSocket, p, y, MSG_NOSIGNAL);
+ SockCheck(r);
+ if FLastError = WSAEWOULDBLOCK then
+ begin
+ if CanWrite(FNonblockSendTimeout) then
+ begin
+ r := synsock.Send(FSocket, p, y, MSG_NOSIGNAL);
+ SockCheck(r);
+ end
+ else
+ FLastError := WSAETIMEDOUT;
+ end;
+ if FLastError <> 0 then
+ Break;
+ Inc(x, r);
+ Inc(Result, r);
+ Inc(FSendCounter, r);
+ DoStatus(HR_WriteCount, IntToStr(r));
+ end
+ else
+ break;
+ end;
+{$ENDIF}
+ ExceptCheck;
+end;
+
+procedure TBlockSocket.SendByte(Data: Byte);
+{$IFDEF CIL}
+var
+ buf: TMemory;
+{$ENDIF}
+begin
+{$IFDEF CIL}
+ setlength(buf, 1);
+ buf[0] := Data;
+ SendBuffer(buf, 1);
+{$ELSE}
+ SendBuffer(@Data, 1);
+{$ENDIF}
+end;
+
+procedure TBlockSocket.SendString(Data: AnsiString);
+var
+ buf: TMemory;
+begin
+ {$IFDEF CIL}
+ buf := BytesOf(Data);
+ {$ELSE}
+ buf := Pointer(data);
+ {$ENDIF}
+ SendBuffer(buf, Length(Data));
+end;
+
+procedure TBlockSocket.SendInteger(Data: integer);
+var
+ buf: TMemory;
+begin
+ {$IFDEF CIL}
+ buf := System.BitConverter.GetBytes(Data);
+ {$ELSE}
+ buf := @Data;
+ {$ENDIF}
+ SendBuffer(buf, SizeOf(Data));
+end;
+
+procedure TBlockSocket.SendBlock(const Data: AnsiString);
+var
+ i: integer;
+begin
+ i := SwapBytes(Length(data));
+ SendString(Codelongint(i) + Data);
+end;
+
+procedure TBlockSocket.InternalSendStream(const Stream: TStream; WithSize, Indy: boolean);
+var
+ l: integer;
+ yr: integer;
+ s: AnsiString;
+ b: boolean;
+{$IFDEF CIL}
+ buf: TMemory;
+{$ENDIF}
+begin
+ b := true;
+ if WithSize then
+ begin
+ l := Stream.Size - Stream.Position;;
+ if Indy then
+ l := SwapBytes(l);
+ end;
+ repeat
+ {$IFDEF CIL}
+ Setlength(buf, FSendMaxChunk);
+ yr := Stream.read(buf, FSendMaxChunk);
+ if yr > 0 then
+ begin
+ if WithSize and b then
+ begin
+ b := false;
+ SendString(CodeLongInt(l));
+ end;
+ SendBuffer(buf, yr);
+ if FLastError <> 0 then
+ break;
+ end
+ {$ELSE}
+ Setlength(s, FSendMaxChunk);
+ yr := Stream.read(Pointer(s)^, FSendMaxChunk);
+ if yr > 0 then
+ begin
+ SetLength(s, yr);
+ if WithSize and b then
+ begin
+ b := false;
+ SendString(CodeLongInt(l) + s);
+ end
+ else
+ SendString(s);
+ if FLastError <> 0 then
+ break;
+ end
+ {$ENDIF}
+ until yr <= 0;
+end;
+
+procedure TBlockSocket.SendStreamRaw(const Stream: TStream);
+begin
+ InternalSendStream(Stream, false, false);
+end;
+
+procedure TBlockSocket.SendStreamIndy(const Stream: TStream);
+begin
+ InternalSendStream(Stream, true, true);
+end;
+
+procedure TBlockSocket.SendStream(const Stream: TStream);
+begin
+ InternalSendStream(Stream, true, false);
+end;
+
+function TBlockSocket.RecvBuffer(Buffer: TMemory; Length: Integer): Integer;
+begin
+ Result := 0;
+ if TestStopFlag then
+ Exit;
+ LimitBandwidth(Length, FMaxRecvBandwidth, FNextRecv);
+// Result := synsock.Recv(FSocket, Buffer^, Length, MSG_NOSIGNAL);
+ Result := synsock.Recv(FSocket, Buffer, Length, MSG_NOSIGNAL);
+ if Result = 0 then
+ FLastError := WSAECONNRESET
+ else
+ SockCheck(Result);
+ ExceptCheck;
+ if Result > 0 then
+ begin
+ Inc(FRecvCounter, Result);
+ DoStatus(HR_ReadCount, IntToStr(Result));
+ DoMonitor(False, Buffer, Result);
+ DoReadFilter(Buffer, Result);
+ end;
+end;
+
+function TBlockSocket.RecvBufferEx(Buffer: TMemory; Len: Integer;
+ Timeout: Integer): Integer;
+var
+ s: AnsiString;
+ rl, l: integer;
+ ti: LongWord;
+{$IFDEF CIL}
+ n: integer;
+ b: TMemory;
+{$ENDIF}
+begin
+ ResetLastError;
+ Result := 0;
+ if Len > 0 then
+ begin
+ rl := 0;
+ repeat
+ ti := GetTick;
+ s := RecvPacket(Timeout);
+ l := Length(s);
+ if (rl + l) > Len then
+ l := Len - rl;
+ {$IFDEF CIL}
+ b := BytesOf(s);
+ for n := 0 to l do
+ Buffer[rl + n] := b[n];
+ {$ELSE}
+ Move(Pointer(s)^, IncPoint(Buffer, rl)^, l);
+ {$ENDIF}
+ rl := rl + l;
+ if FLastError <> 0 then
+ Break;
+ if rl >= Len then
+ Break;
+ if not FInterPacketTimeout then
+ begin
+ Timeout := Timeout - integer(TickDelta(ti, GetTick));
+ if Timeout <= 0 then
+ begin
+ FLastError := WSAETIMEDOUT;
+ Break;
+ end;
+ end;
+ until False;
+ delete(s, 1, l);
+ FBuffer := s;
+ Result := rl;
+ end;
+end;
+
+function TBlockSocket.RecvBufferStr(Len: Integer; Timeout: Integer): AnsiString;
+var
+ x: integer;
+{$IFDEF CIL}
+ buf: Tmemory;
+{$ENDIF}
+begin
+ Result := '';
+ if Len > 0 then
+ begin
+ {$IFDEF CIL}
+ Setlength(Buf, Len);
+ x := RecvBufferEx(buf, Len , Timeout);
+ if FLastError = 0 then
+ begin
+ SetLength(Buf, x);
+ Result := StringOf(buf);
+ end
+ else
+ Result := '';
+ {$ELSE}
+ Setlength(Result, Len);
+ x := RecvBufferEx(Pointer(Result), Len , Timeout);
+ if FLastError = 0 then
+ SetLength(Result, x)
+ else
+ Result := '';
+ {$ENDIF}
+ end;
+end;
+
+function TBlockSocket.RecvPacket(Timeout: Integer): AnsiString;
+var
+ x: integer;
+{$IFDEF CIL}
+ buf: TMemory;
+{$ENDIF}
+begin
+ Result := '';
+ ResetLastError;
+ if FBuffer <> '' then
+ begin
+ Result := FBuffer;
+ FBuffer := '';
+ end
+ else
+ begin
+ {$IFDEF WIN32}
+ //not drain CPU on large downloads...
+ Sleep(0);
+ {$ENDIF}
+ x := WaitingData;
+ if x > 0 then
+ begin
+ {$IFDEF CIL}
+ SetLength(Buf, x);
+ x := RecvBuffer(Buf, x);
+ if x >= 0 then
+ begin
+ SetLength(Buf, x);
+ Result := StringOf(Buf);
+ end;
+ {$ELSE}
+ SetLength(Result, x);
+ x := RecvBuffer(Pointer(Result), x);
+ if x >= 0 then
+ SetLength(Result, x);
+ {$ENDIF}
+ end
+ else
+ begin
+ if CanRead(Timeout) then
+ begin
+ x := WaitingData;
+ if x = 0 then
+ FLastError := WSAECONNRESET;
+ if x > 0 then
+ begin
+ {$IFDEF CIL}
+ SetLength(Buf, x);
+ x := RecvBuffer(Buf, x);
+ if x >= 0 then
+ begin
+ SetLength(Buf, x);
+ result := StringOf(Buf);
+ end;
+ {$ELSE}
+ SetLength(Result, x);
+ x := RecvBuffer(Pointer(Result), x);
+ if x >= 0 then
+ SetLength(Result, x);
+ {$ENDIF}
+ end;
+ end
+ else
+ FLastError := WSAETIMEDOUT;
+ end;
+ end;
+ if FConvertLineEnd and (Result <> '') then
+ begin
+ if FLastCR and (Result[1] = LF) then
+ Delete(Result, 1, 1);
+ if FLastLF and (Result[1] = CR) then
+ Delete(Result, 1, 1);
+ FLastCR := False;
+ FLastLF := False;
+ end;
+ ExceptCheck;
+end;
+
+
+function TBlockSocket.RecvByte(Timeout: Integer): Byte;
+begin
+ Result := 0;
+ ResetLastError;
+ if FBuffer = '' then
+ FBuffer := RecvPacket(Timeout);
+ if (FLastError = 0) and (FBuffer <> '') then
+ begin
+ Result := Ord(FBuffer[1]);
+ Delete(FBuffer, 1, 1);
+ end;
+ ExceptCheck;
+end;
+
+function TBlockSocket.RecvInteger(Timeout: Integer): Integer;
+var
+ s: AnsiString;
+begin
+ Result := 0;
+ s := RecvBufferStr(4, Timeout);
+ if FLastError = 0 then
+ Result := (ord(s[1]) + ord(s[2]) * 256) + (ord(s[3]) + ord(s[4]) * 256) * 65536;
+end;
+
+function TBlockSocket.RecvTerminated(Timeout: Integer; const Terminator: AnsiString): AnsiString;
+var
+ x: Integer;
+ s: AnsiString;
+ l: Integer;
+ CorCRLF: Boolean;
+ t: AnsiString;
+ tl: integer;
+ ti: LongWord;
+begin
+ ResetLastError;
+ Result := '';
+ l := Length(Terminator);
+ if l = 0 then
+ Exit;
+ tl := l;
+ CorCRLF := FConvertLineEnd and (Terminator = CRLF);
+ s := '';
+ x := 0;
+ repeat
+ //get rest of FBuffer or incomming new data...
+ ti := GetTick;
+ s := s + RecvPacket(Timeout);
+ if FLastError <> 0 then
+ Break;
+ x := 0;
+ if Length(s) > 0 then
+ if CorCRLF then
+ begin
+ t := '';
+ x := PosCRLF(s, t);
+ tl := Length(t);
+ if t = CR then
+ FLastCR := True;
+ if t = LF then
+ FLastLF := True;
+ end
+ else
+ begin
+ x := pos(Terminator, s);
+ tl := l;
+ end;
+ if (FMaxLineLength <> 0) and (Length(s) > FMaxLineLength) then
+ begin
+ FLastError := WSAENOBUFS;
+ Break;
+ end;
+ if x > 0 then
+ Break;
+ if not FInterPacketTimeout then
+ begin
+ Timeout := Timeout - integer(TickDelta(ti, GetTick));
+ if Timeout <= 0 then
+ begin
+ FLastError := WSAETIMEDOUT;
+ Break;
+ end;
+ end;
+ until False;
+ if x > 0 then
+ begin
+ Result := Copy(s, 1, x - 1);
+ Delete(s, 1, x + tl - 1);
+ end;
+ FBuffer := s;
+ ExceptCheck;
+end;
+
+function TBlockSocket.RecvString(Timeout: Integer): AnsiString;
+var
+ s: AnsiString;
+begin
+ Result := '';
+ s := RecvTerminated(Timeout, CRLF);
+ if FLastError = 0 then
+ Result := s;
+end;
+
+function TBlockSocket.RecvBlock(Timeout: Integer): AnsiString;
+var
+ x: integer;
+begin
+ Result := '';
+ x := RecvInteger(Timeout);
+ if FLastError = 0 then
+ Result := RecvBufferStr(x, Timeout);
+end;
+
+procedure TBlockSocket.RecvStreamRaw(const Stream: TStream; Timeout: Integer);
+var
+ s: AnsiString;
+begin
+ repeat
+ s := RecvPacket(Timeout);
+ if FLastError = 0 then
+ WriteStrToStream(Stream, s);
+ until FLastError <> 0;
+end;
+
+procedure TBlockSocket.RecvStreamSize(const Stream: TStream; Timeout: Integer; Size: Integer);
+var
+ s: AnsiString;
+ n: integer;
+{$IFDEF CIL}
+ buf: TMemory;
+{$ENDIF}
+begin
+ for n := 1 to (Size div FSendMaxChunk) do
+ begin
+ {$IFDEF CIL}
+ SetLength(buf, FSendMaxChunk);
+ RecvBufferEx(buf, FSendMaxChunk, Timeout);
+ if FLastError <> 0 then
+ Exit;
+ Stream.Write(buf, FSendMaxChunk);
+ {$ELSE}
+ s := RecvBufferStr(FSendMaxChunk, Timeout);
+ if FLastError <> 0 then
+ Exit;
+ WriteStrToStream(Stream, s);
+ {$ENDIF}
+ end;
+ n := Size mod FSendMaxChunk;
+ if n > 0 then
+ begin
+ {$IFDEF CIL}
+ SetLength(buf, n);
+ RecvBufferEx(buf, n, Timeout);
+ if FLastError <> 0 then
+ Exit;
+ Stream.Write(buf, n);
+ {$ELSE}
+ s := RecvBufferStr(n, Timeout);
+ if FLastError <> 0 then
+ Exit;
+ WriteStrToStream(Stream, s);
+ {$ENDIF}
+ end;
+end;
+
+procedure TBlockSocket.RecvStreamIndy(const Stream: TStream; Timeout: Integer);
+var
+ x: integer;
+begin
+ x := RecvInteger(Timeout);
+ x := synsock.NToHL(x);
+ if FLastError = 0 then
+ RecvStreamSize(Stream, Timeout, x);
+end;
+
+procedure TBlockSocket.RecvStream(const Stream: TStream; Timeout: Integer);
+var
+ x: integer;
+begin
+ x := RecvInteger(Timeout);
+ if FLastError = 0 then
+ RecvStreamSize(Stream, Timeout, x);
+end;
+
+function TBlockSocket.PeekBuffer(Buffer: TMemory; Length: Integer): Integer;
+begin
+ {$IFNDEF CIL}
+// Result := synsock.Recv(FSocket, Buffer^, Length, MSG_PEEK + MSG_NOSIGNAL);
+ Result := synsock.Recv(FSocket, Buffer, Length, MSG_PEEK + MSG_NOSIGNAL);
+ SockCheck(Result);
+ ExceptCheck;
+ {$ENDIF}
+end;
+
+function TBlockSocket.PeekByte(Timeout: Integer): Byte;
+var
+ s: string;
+begin
+ {$IFNDEF CIL}
+ Result := 0;
+ if CanRead(Timeout) then
+ begin
+ SetLength(s, 1);
+ PeekBuffer(Pointer(s), 1);
+ if s <> '' then
+ Result := Ord(s[1]);
+ end
+ else
+ FLastError := WSAETIMEDOUT;
+ ExceptCheck;
+ {$ENDIF}
+end;
+
+procedure TBlockSocket.ResetLastError;
+begin
+ FLastError := 0;
+ FLastErrorDesc := '';
+end;
+
+function TBlockSocket.SockCheck(SockResult: Integer): Integer;
+begin
+ ResetLastError;
+ if SockResult = integer(SOCKET_ERROR) then
+ begin
+ FLastError := synsock.WSAGetLastError;
+ FLastErrorDesc := GetErrorDescEx;
+ end;
+ Result := FLastError;
+end;
+
+procedure TBlockSocket.ExceptCheck;
+var
+ e: ESynapseError;
+begin
+ FLastErrorDesc := GetErrorDescEx;
+ if (LastError <> 0) and (LastError <> WSAEINPROGRESS)
+ and (LastError <> WSAEWOULDBLOCK) then
+ begin
+ DoStatus(HR_Error, IntToStr(FLastError) + ',' + FLastErrorDesc);
+ if FRaiseExcept then
+ begin
+ e := ESynapseError.Create(Format('Synapse TCP/IP Socket error %d: %s',
+ [FLastError, FLastErrorDesc]));
+ e.ErrorCode := FLastError;
+ e.ErrorMessage := FLastErrorDesc;
+ raise e;
+ end;
+ end;
+end;
+
+function TBlockSocket.WaitingData: Integer;
+var
+ x: Integer;
+begin
+ Result := 0;
+ if synsock.IoctlSocket(FSocket, FIONREAD, x) = 0 then
+ Result := x;
+ if Result > c64k then
+ Result := c64k;
+end;
+
+function TBlockSocket.WaitingDataEx: Integer;
+begin
+ if FBuffer <> '' then
+ Result := Length(FBuffer)
+ else
+ Result := WaitingData;
+end;
+
+procedure TBlockSocket.Purge;
+begin
+ Sleep(1);
+ try
+ while (Length(FBuffer) > 0) or (WaitingData > 0) do
+ begin
+ RecvPacket(0);
+ if FLastError <> 0 then
+ break;
+ end;
+ except
+ on exception do;
+ end;
+ ResetLastError;
+end;
+
+procedure TBlockSocket.SetLinger(Enable: Boolean; Linger: Integer);
+var
+ d: TSynaOption;
+begin
+ d := TSynaOption.Create;
+ d.Option := SOT_Linger;
+ d.Enabled := Enable;
+ d.Value := Linger;
+ DelayedOption(d);
+end;
+
+function TBlockSocket.LocalName: string;
+begin
+ Result := synsock.GetHostName;
+ if Result = '' then
+ Result := '127.0.0.1';
+end;
+
+procedure TBlockSocket.ResolveNameToIP(Name: string; const IPList: TStrings);
+begin
+ IPList.Clear;
+ synsock.ResolveNameToIP(Name, FamilyToAF(FFamily), GetSocketprotocol, GetSocketType, IPList);
+ if IPList.Count = 0 then
+ IPList.Add(cAnyHost);
+end;
+
+function TBlockSocket.ResolveName(Name: string): string;
+var
+ l: TStringList;
+begin
+ l := TStringList.Create;
+ try
+ ResolveNameToIP(Name, l);
+ Result := l[0];
+ finally
+ l.Free;
+ end;
+end;
+
+function TBlockSocket.ResolvePort(Port: string): Word;
+begin
+ Result := synsock.ResolvePort(Port, FamilyToAF(FFamily), GetSocketProtocol, GetSocketType);
+end;
+
+function TBlockSocket.ResolveIPToName(IP: string): string;
+begin
+ if not IsIP(IP) or not IsIp6(IP) then
+ IP := ResolveName(IP);
+ Result := synsock.ResolveIPToName(IP, FamilyToAF(FFamily), GetSocketProtocol, GetSocketType);
+end;
+
+procedure TBlockSocket.SetRemoteSin(IP, Port: string);
+begin
+ SetSin(FRemoteSin, IP, Port);
+end;
+
+function TBlockSocket.GetLocalSinIP: string;
+begin
+ Result := GetSinIP(FLocalSin);
+end;
+
+function TBlockSocket.GetRemoteSinIP: string;
+begin
+ Result := GetSinIP(FRemoteSin);
+end;
+
+function TBlockSocket.GetLocalSinPort: Integer;
+begin
+ Result := GetSinPort(FLocalSin);
+end;
+
+function TBlockSocket.GetRemoteSinPort: Integer;
+begin
+ Result := GetSinPort(FRemoteSin);
+end;
+
+function TBlockSocket.InternalCanRead(Timeout: Integer): Boolean;
+{$IFDEF CIL}
+begin
+ Result := FSocket.Poll(Timeout * 1000, SelectMode.SelectRead);
+{$ELSE}
+var
+ TimeVal: PTimeVal;
+ TimeV: TTimeVal;
+ x: Integer;
+ FDSet: TFDSet;
+begin
+ TimeV.tv_usec := (Timeout mod 1000) * 1000;
+ TimeV.tv_sec := Timeout div 1000;
+ TimeVal := @TimeV;
+ if Timeout = -1 then
+ TimeVal := nil;
+ FDSet := FFdSet;
+ x := synsock.Select(FSocket + 1, @FDSet, nil, nil, TimeVal);
+ SockCheck(x);
+ if FLastError <> 0 then
+ x := 0;
+ Result := x > 0;
+{$ENDIF}
+end;
+
+function TBlockSocket.CanRead(Timeout: Integer): Boolean;
+var
+ ti, tr: Integer;
+ n: integer;
+begin
+ if (FHeartbeatRate <> 0) and (Timeout <> -1) then
+ begin
+ ti := Timeout div FHeartbeatRate;
+ tr := Timeout mod FHeartbeatRate;
+ end
+ else
+ begin
+ ti := 0;
+ tr := Timeout;
+ end;
+ Result := InternalCanRead(tr);
+ if not Result then
+ for n := 0 to ti do
+ begin
+ DoHeartbeat;
+ if FStopFlag then
+ begin
+ Result := False;
+ FStopFlag := False;
+ Break;
+ end;
+ Result := InternalCanRead(FHeartbeatRate);
+ if Result then
+ break;
+ end;
+ ExceptCheck;
+ if Result then
+ DoStatus(HR_CanRead, '');
+end;
+
+function TBlockSocket.CanWrite(Timeout: Integer): Boolean;
+{$IFDEF CIL}
+begin
+ Result := FSocket.Poll(Timeout * 1000, SelectMode.SelectWrite);
+{$ELSE}
+var
+ TimeVal: PTimeVal;
+ TimeV: TTimeVal;
+ x: Integer;
+ FDSet: TFDSet;
+begin
+ TimeV.tv_usec := (Timeout mod 1000) * 1000;
+ TimeV.tv_sec := Timeout div 1000;
+ TimeVal := @TimeV;
+ if Timeout = -1 then
+ TimeVal := nil;
+ FDSet := FFdSet;
+ x := synsock.Select(FSocket + 1, nil, @FDSet, nil, TimeVal);
+ SockCheck(x);
+ if FLastError <> 0 then
+ x := 0;
+ Result := x > 0;
+{$ENDIF}
+ ExceptCheck;
+ if Result then
+ DoStatus(HR_CanWrite, '');
+end;
+
+function TBlockSocket.CanReadEx(Timeout: Integer): Boolean;
+begin
+ if FBuffer <> '' then
+ Result := True
+ else
+ Result := CanRead(Timeout);
+end;
+
+function TBlockSocket.SendBufferTo(Buffer: TMemory; Length: Integer): Integer;
+begin
+ Result := 0;
+ if TestStopFlag then
+ Exit;
+ DoMonitor(True, Buffer, Length);
+ LimitBandwidth(Length, FMaxSendBandwidth, FNextsend);
+ Result := synsock.SendTo(FSocket, Buffer, Length, MSG_NOSIGNAL, FRemoteSin);
+ SockCheck(Result);
+ ExceptCheck;
+ Inc(FSendCounter, Result);
+ DoStatus(HR_WriteCount, IntToStr(Result));
+end;
+
+function TBlockSocket.RecvBufferFrom(Buffer: TMemory; Length: Integer): Integer;
+begin
+ Result := 0;
+ if TestStopFlag then
+ Exit;
+ LimitBandwidth(Length, FMaxRecvBandwidth, FNextRecv);
+ Result := synsock.RecvFrom(FSocket, Buffer, Length, MSG_NOSIGNAL, FRemoteSin);
+ SockCheck(Result);
+ ExceptCheck;
+ Inc(FRecvCounter, Result);
+ DoStatus(HR_ReadCount, IntToStr(Result));
+ DoMonitor(False, Buffer, Result);
+end;
+
+function TBlockSocket.GetSizeRecvBuffer: Integer;
+var
+ l: Integer;
+{$IFDEF CIL}
+ buf: TMemory;
+{$ENDIF}
+begin
+{$IFDEF CIL}
+ setlength(buf, 4);
+ SockCheck(synsock.GetSockOpt(FSocket, integer(SOL_SOCKET), integer(SO_RCVBUF), buf, l));
+ Result := System.BitConverter.ToInt32(buf,0);
+{$ELSE}
+ l := SizeOf(Result);
+ SockCheck(synsock.GetSockOpt(FSocket, SOL_SOCKET, SO_RCVBUF, @Result, l));
+ if FLastError <> 0 then
+ Result := 1024;
+ ExceptCheck;
+{$ENDIF}
+end;
+
+procedure TBlockSocket.SetSizeRecvBuffer(Size: Integer);
+var
+ d: TSynaOption;
+begin
+ d := TSynaOption.Create;
+ d.Option := SOT_RecvBuff;
+ d.Value := Size;
+ DelayedOption(d);
+end;
+
+function TBlockSocket.GetSizeSendBuffer: Integer;
+var
+ l: Integer;
+{$IFDEF CIL}
+ buf: TMemory;
+{$ENDIF}
+begin
+{$IFDEF CIL}
+ setlength(buf, 4);
+ SockCheck(synsock.GetSockOpt(FSocket, integer(SOL_SOCKET), integer(SO_SNDBUF), buf, l));
+ Result := System.BitConverter.ToInt32(buf,0);
+{$ELSE}
+ l := SizeOf(Result);
+ SockCheck(synsock.GetSockOpt(FSocket, SOL_SOCKET, SO_SNDBUF, @Result, l));
+ if FLastError <> 0 then
+ Result := 1024;
+ ExceptCheck;
+{$ENDIF}
+end;
+
+procedure TBlockSocket.SetSizeSendBuffer(Size: Integer);
+var
+ d: TSynaOption;
+begin
+ d := TSynaOption.Create;
+ d.Option := SOT_SendBuff;
+ d.Value := Size;
+ DelayedOption(d);
+end;
+
+procedure TBlockSocket.SetNonBlockMode(Value: Boolean);
+var
+ d: TSynaOption;
+begin
+ d := TSynaOption.Create;
+ d.Option := SOT_nonblock;
+ d.Enabled := Value;
+ DelayedOption(d);
+end;
+
+procedure TBlockSocket.SetTimeout(Timeout: Integer);
+begin
+ SetSendTimeout(Timeout);
+ SetRecvTimeout(Timeout);
+end;
+
+procedure TBlockSocket.SetSendTimeout(Timeout: Integer);
+var
+ d: TSynaOption;
+begin
+ d := TSynaOption.Create;
+ d.Option := SOT_sendtimeout;
+ d.Value := Timeout;
+ DelayedOption(d);
+end;
+
+procedure TBlockSocket.SetRecvTimeout(Timeout: Integer);
+var
+ d: TSynaOption;
+begin
+ d := TSynaOption.Create;
+ d.Option := SOT_recvtimeout;
+ d.Value := Timeout;
+ DelayedOption(d);
+end;
+
+{$IFNDEF CIL}
+function TBlockSocket.GroupCanRead(const SocketList: TList; Timeout: Integer;
+ const CanReadList: TList): boolean;
+var
+ FDSet: TFDSet;
+ TimeVal: PTimeVal;
+ TimeV: TTimeVal;
+ x, n: Integer;
+ Max: Integer;
+begin
+ TimeV.tv_usec := (Timeout mod 1000) * 1000;
+ TimeV.tv_sec := Timeout div 1000;
+ TimeVal := @TimeV;
+ if Timeout = -1 then
+ TimeVal := nil;
+ FD_ZERO(FDSet);
+ Max := 0;
+ for n := 0 to SocketList.Count - 1 do
+ if TObject(SocketList.Items[n]) is TBlockSocket then
+ begin
+ if TBlockSocket(SocketList.Items[n]).Socket > Max then
+ Max := TBlockSocket(SocketList.Items[n]).Socket;
+ FD_SET(TBlockSocket(SocketList.Items[n]).Socket, FDSet);
+ end;
+ x := synsock.Select(Max + 1, @FDSet, nil, nil, TimeVal);
+ SockCheck(x);
+ ExceptCheck;
+ if FLastError <> 0 then
+ x := 0;
+ Result := x > 0;
+ CanReadList.Clear;
+ if Result then
+ for n := 0 to SocketList.Count - 1 do
+ if TObject(SocketList.Items[n]) is TBlockSocket then
+ if FD_ISSET(TBlockSocket(SocketList.Items[n]).Socket, FDSet) then
+ CanReadList.Add(TBlockSocket(SocketList.Items[n]));
+end;
+{$ENDIF}
+
+procedure TBlockSocket.EnableReuse(Value: Boolean);
+var
+ d: TSynaOption;
+begin
+ d := TSynaOption.Create;
+ d.Option := SOT_reuse;
+ d.Enabled := Value;
+ DelayedOption(d);
+end;
+
+procedure TBlockSocket.SetTTL(TTL: integer);
+var
+ d: TSynaOption;
+begin
+ d := TSynaOption.Create;
+ d.Option := SOT_TTL;
+ d.Value := TTL;
+ DelayedOption(d);
+end;
+
+function TBlockSocket.GetTTL:integer;
+var
+ l: Integer;
+begin
+{$IFNDEF CIL}
+ l := SizeOf(Result);
+ if FIP6Used then
+ synsock.GetSockOpt(FSocket, IPPROTO_IPV6, IPV6_UNICAST_HOPS, @Result, l)
+ else
+ synsock.GetSockOpt(FSocket, IPPROTO_IP, IP_TTL, @Result, l);
+{$ENDIF}
+end;
+
+procedure TBlockSocket.SetFamily(Value: TSocketFamily);
+begin
+ FFamily := Value;
+ FFamilySave := Value;
+end;
+
+procedure TBlockSocket.SetSocket(Value: TSocket);
+begin
+ FRecvCounter := 0;
+ FSendCounter := 0;
+ FSocket := Value;
+{$IFNDEF CIL}
+ FD_ZERO(FFDSet);
+ FD_SET(FSocket, FFDSet);
+{$ENDIF}
+ GetSins;
+ FIP6Used := FRemoteSin.AddressFamily = AF_INET6;
+end;
+
+function TBlockSocket.GetWsaData: TWSAData;
+begin
+ Result := WsaDataOnce;
+end;
+
+function TBlockSocket.GetSocketType: integer;
+begin
+ Result := 0;
+end;
+
+function TBlockSocket.GetSocketProtocol: integer;
+begin
+ Result := integer(IPPROTO_IP);
+end;
+
+procedure TBlockSocket.DoStatus(Reason: THookSocketReason; const Value: string);
+begin
+ if assigned(OnStatus) then
+ OnStatus(Self, Reason, Value);
+end;
+
+procedure TBlockSocket.DoReadFilter(Buffer: TMemory; var Len: Integer);
+var
+ s: AnsiString;
+begin
+ if assigned(OnReadFilter) then
+ if Len > 0 then
+ begin
+ {$IFDEF CIL}
+ s := StringOf(Buffer);
+ {$ELSE}
+ SetLength(s, Len);
+ Move(Buffer^, Pointer(s)^, Len);
+ {$ENDIF}
+ OnReadFilter(Self, s);
+ if Length(s) > Len then
+ SetLength(s, Len);
+ Len := Length(s);
+ {$IFDEF CIL}
+ Buffer := BytesOf(s);
+ {$ELSE}
+ Move(Pointer(s)^, Buffer^, Len);
+ {$ENDIF}
+ end;
+end;
+
+procedure TBlockSocket.DoCreateSocket;
+begin
+ if assigned(OnCreateSocket) then
+ OnCreateSocket(Self);
+end;
+
+procedure TBlockSocket.DoMonitor(Writing: Boolean; const Buffer: TMemory; Len: Integer);
+begin
+ if assigned(OnMonitor) then
+ begin
+ OnMonitor(Self, Writing, Buffer, Len);
+ end;
+end;
+
+procedure TBlockSocket.DoHeartbeat;
+begin
+ if assigned(OnHeartbeat) and (FHeartbeatRate <> 0) then
+ begin
+ OnHeartbeat(Self);
+ end;
+end;
+
+function TBlockSocket.GetErrorDescEx: string;
+begin
+ Result := GetErrorDesc(FLastError);
+end;
+
+class function TBlockSocket.GetErrorDesc(ErrorCode: Integer): string;
+begin
+{$IFDEF CIL}
+ if ErrorCode = 0 then
+ Result := ''
+ else
+ begin
+ Result := WSAGetLastErrorDesc;
+ if Result = '' then
+ Result := 'Other Winsock error (' + IntToStr(ErrorCode) + ')';
+ end;
+{$ELSE}
+ case ErrorCode of
+ 0:
+ Result := '';
+ WSAEINTR: {10004}
+ Result := 'Interrupted system call';
+ WSAEBADF: {10009}
+ Result := 'Bad file number';
+ WSAEACCES: {10013}
+ Result := 'Permission denied';
+ WSAEFAULT: {10014}
+ Result := 'Bad address';
+ WSAEINVAL: {10022}
+ Result := 'Invalid argument';
+ WSAEMFILE: {10024}
+ Result := 'Too many open files';
+ WSAEWOULDBLOCK: {10035}
+ Result := 'Operation would block';
+ WSAEINPROGRESS: {10036}
+ Result := 'Operation now in progress';
+ WSAEALREADY: {10037}
+ Result := 'Operation already in progress';
+ WSAENOTSOCK: {10038}
+ Result := 'Socket operation on nonsocket';
+ WSAEDESTADDRREQ: {10039}
+ Result := 'Destination address required';
+ WSAEMSGSIZE: {10040}
+ Result := 'Message too long';
+ WSAEPROTOTYPE: {10041}
+ Result := 'Protocol wrong type for Socket';
+ WSAENOPROTOOPT: {10042}
+ Result := 'Protocol not available';
+ WSAEPROTONOSUPPORT: {10043}
+ Result := 'Protocol not supported';
+ WSAESOCKTNOSUPPORT: {10044}
+ Result := 'Socket not supported';
+ WSAEOPNOTSUPP: {10045}
+ Result := 'Operation not supported on Socket';
+ WSAEPFNOSUPPORT: {10046}
+ Result := 'Protocol family not supported';
+ WSAEAFNOSUPPORT: {10047}
+ Result := 'Address family not supported';
+ WSAEADDRINUSE: {10048}
+ Result := 'Address already in use';
+ WSAEADDRNOTAVAIL: {10049}
+ Result := 'Can''t assign requested address';
+ WSAENETDOWN: {10050}
+ Result := 'Network is down';
+ WSAENETUNREACH: {10051}
+ Result := 'Network is unreachable';
+ WSAENETRESET: {10052}
+ Result := 'Network dropped connection on reset';
+ WSAECONNABORTED: {10053}
+ Result := 'Software caused connection abort';
+ WSAECONNRESET: {10054}
+ Result := 'Connection reset by peer';
+ WSAENOBUFS: {10055}
+ Result := 'No Buffer space available';
+ WSAEISCONN: {10056}
+ Result := 'Socket is already connected';
+ WSAENOTCONN: {10057}
+ Result := 'Socket is not connected';
+ WSAESHUTDOWN: {10058}
+ Result := 'Can''t send after Socket shutdown';
+ WSAETOOMANYREFS: {10059}
+ Result := 'Too many references:can''t splice';
+ WSAETIMEDOUT: {10060}
+ Result := 'Connection timed out';
+ WSAECONNREFUSED: {10061}
+ Result := 'Connection refused';
+ WSAELOOP: {10062}
+ Result := 'Too many levels of symbolic links';
+ WSAENAMETOOLONG: {10063}
+ Result := 'File name is too long';
+ WSAEHOSTDOWN: {10064}
+ Result := 'Host is down';
+ WSAEHOSTUNREACH: {10065}
+ Result := 'No route to host';
+ WSAENOTEMPTY: {10066}
+ Result := 'Directory is not empty';
+ WSAEPROCLIM: {10067}
+ Result := 'Too many processes';
+ WSAEUSERS: {10068}
+ Result := 'Too many users';
+ WSAEDQUOT: {10069}
+ Result := 'Disk quota exceeded';
+ WSAESTALE: {10070}
+ Result := 'Stale NFS file handle';
+ WSAEREMOTE: {10071}
+ Result := 'Too many levels of remote in path';
+ WSASYSNOTREADY: {10091}
+ Result := 'Network subsystem is unusable';
+ WSAVERNOTSUPPORTED: {10092}
+ Result := 'Winsock DLL cannot support this application';
+ WSANOTINITIALISED: {10093}
+ Result := 'Winsock not initialized';
+ WSAEDISCON: {10101}
+ Result := 'Disconnect';
+ WSAHOST_NOT_FOUND: {11001}
+ Result := 'Host not found';
+ WSATRY_AGAIN: {11002}
+ Result := 'Non authoritative - host not found';
+ WSANO_RECOVERY: {11003}
+ Result := 'Non recoverable error';
+ WSANO_DATA: {11004}
+ Result := 'Valid name, no data record of requested type'
+ else
+ Result := 'Other Winsock error (' + IntToStr(ErrorCode) + ')';
+ end;
+{$ENDIF}
+end;
+
+{======================================================================}
+
+constructor TSocksBlockSocket.Create;
+begin
+ inherited Create;
+ FSocksIP:= '';
+ FSocksPort:= '1080';
+ FSocksTimeout:= 60000;
+ FSocksUsername:= '';
+ FSocksPassword:= '';
+ FUsingSocks := False;
+ FSocksResolver := True;
+ FSocksLastError := 0;
+ FSocksResponseIP := '';
+ FSocksResponsePort := '';
+ FSocksLocalIP := '';
+ FSocksLocalPort := '';
+ FSocksRemoteIP := '';
+ FSocksRemotePort := '';
+ FBypassFlag := False;
+ FSocksType := ST_Socks5;
+end;
+
+function TSocksBlockSocket.SocksOpen: boolean;
+var
+ Buf: string;
+ n: integer;
+begin
+ Result := False;
+ FUsingSocks := False;
+ if FSocksType <> ST_Socks5 then
+ begin
+ FUsingSocks := True;
+ Result := True;
+ end
+ else
+ begin
+ FBypassFlag := True;
+ try
+ if FSocksUsername = '' then
+ Buf := #5 + #1 + #0
+ else
+ Buf := #5 + #2 + #2 +#0;
+ SendString(Buf);
+ Buf := RecvBufferStr(2, FSocksTimeout);
+ if Length(Buf) < 2 then
+ Exit;
+ if Buf[1] <> #5 then
+ Exit;
+ n := Ord(Buf[2]);
+ case n of
+ 0: //not need authorisation
+ ;
+ 2:
+ begin
+ Buf := #1 + char(Length(FSocksUsername)) + FSocksUsername
+ + char(Length(FSocksPassword)) + FSocksPassword;
+ SendString(Buf);
+ Buf := RecvBufferStr(2, FSocksTimeout);
+ if Length(Buf) < 2 then
+ Exit;
+ if Buf[2] <> #0 then
+ Exit;
+ end;
+ else
+ //other authorisation is not supported!
+ Exit;
+ end;
+ FUsingSocks := True;
+ Result := True;
+ finally
+ FBypassFlag := False;
+ end;
+ end;
+end;
+
+function TSocksBlockSocket.SocksRequest(Cmd: Byte;
+ const IP, Port: string): Boolean;
+var
+ Buf: string;
+begin
+ FBypassFlag := True;
+ try
+ if FSocksType <> ST_Socks5 then
+ Buf := #4 + char(Cmd) + SocksCode(IP, Port)
+ else
+ Buf := #5 + char(Cmd) + #0 + SocksCode(IP, Port);
+ SendString(Buf);
+ Result := FLastError = 0;
+ finally
+ FBypassFlag := False;
+ end;
+end;
+
+function TSocksBlockSocket.SocksResponse: Boolean;
+var
+ Buf, s: string;
+ x: integer;
+begin
+ Result := False;
+ FBypassFlag := True;
+ try
+ FSocksResponseIP := '';
+ FSocksResponsePort := '';
+ FSocksLastError := -1;
+ if FSocksType <> ST_Socks5 then
+ begin
+ Buf := RecvBufferStr(8, FSocksTimeout);
+ if FLastError <> 0 then
+ Exit;
+ if Buf[1] <> #0 then
+ Exit;
+ FSocksLastError := Ord(Buf[2]);
+ end
+ else
+ begin
+ Buf := RecvBufferStr(4, FSocksTimeout);
+ if FLastError <> 0 then
+ Exit;
+ if Buf[1] <> #5 then
+ Exit;
+ case Ord(Buf[4]) of
+ 1:
+ s := RecvBufferStr(4, FSocksTimeout);
+ 3:
+ begin
+ x := RecvByte(FSocksTimeout);
+ if FLastError <> 0 then
+ Exit;
+ s := char(x) + RecvBufferStr(x, FSocksTimeout);
+ end;
+ 4:
+ s := RecvBufferStr(16, FSocksTimeout);
+ else
+ Exit;
+ end;
+ Buf := Buf + s + RecvBufferStr(2, FSocksTimeout);
+ if FLastError <> 0 then
+ Exit;
+ FSocksLastError := Ord(Buf[2]);
+ end;
+ if ((FSocksLastError <> 0) and (FSocksLastError <> 90)) then
+ Exit;
+ SocksDecode(Buf);
+ Result := True;
+ finally
+ FBypassFlag := False;
+ end;
+end;
+
+function TSocksBlockSocket.SocksCode(IP, Port: string): Ansistring;
+var
+ ip6: TIp6Bytes;
+ n: integer;
+begin
+ if FSocksType <> ST_Socks5 then
+ begin
+ Result := CodeInt(ResolvePort(Port));
+ if not FSocksResolver then
+ IP := ResolveName(IP);
+ if IsIP(IP) then
+ begin
+ Result := Result + IPToID(IP);
+ Result := Result + FSocksUsername + #0;
+ end
+ else
+ begin
+ Result := Result + IPToID('0.0.0.1');
+ Result := Result + FSocksUsername + #0;
+ Result := Result + IP + #0;
+ end;
+ end
+ else
+ begin
+ if not FSocksResolver then
+ IP := ResolveName(IP);
+ if IsIP(IP) then
+ Result := #1 + IPToID(IP)
+ else
+ if IsIP6(IP) then
+ begin
+ ip6 := StrToIP6(IP);
+ Result := #4;
+ for n := 0 to 15 do
+ Result := Result + char(ip6[n]);
+ end
+ else
+ Result := #3 + char(Length(IP)) + IP;
+ Result := Result + CodeInt(ResolvePort(Port));
+ end;
+end;
+
+function TSocksBlockSocket.SocksDecode(Value: Ansistring): integer;
+var
+ Atyp: Byte;
+ y, n: integer;
+ w: Word;
+ ip6: TIp6Bytes;
+begin
+ FSocksResponsePort := '0';
+ Result := 0;
+ if FSocksType <> ST_Socks5 then
+ begin
+ if Length(Value) < 8 then
+ Exit;
+ Result := 3;
+ w := DecodeInt(Value, Result);
+ FSocksResponsePort := IntToStr(w);
+ FSocksResponseIP := Format('%d.%d.%d.%d',
+ [Ord(Value[5]), Ord(Value[6]), Ord(Value[7]), Ord(Value[8])]);
+ Result := 9;
+ end
+ else
+ begin
+ if Length(Value) < 4 then
+ Exit;
+ Atyp := Ord(Value[4]);
+ Result := 5;
+ case Atyp of
+ 1:
+ begin
+ if Length(Value) < 10 then
+ Exit;
+ FSocksResponseIP := Format('%d.%d.%d.%d',
+ [Ord(Value[5]), Ord(Value[6]), Ord(Value[7]), Ord(Value[8])]);
+ Result := 9;
+ end;
+ 3:
+ begin
+ y := Ord(Value[5]);
+ if Length(Value) < (5 + y + 2) then
+ Exit;
+ for n := 6 to 6 + y - 1 do
+ FSocksResponseIP := FSocksResponseIP + Value[n];
+ Result := 5 + y + 1;
+ end;
+ 4:
+ begin
+ if Length(Value) < 22 then
+ Exit;
+ for n := 0 to 15 do
+ ip6[n] := ord(Value[n + 5]);
+ FSocksResponseIP := IP6ToStr(ip6);
+ Result := 21;
+ end;
+ else
+ Exit;
+ end;
+ w := DecodeInt(Value, Result);
+ FSocksResponsePort := IntToStr(w);
+ Result := Result + 2;
+ end;
+end;
+
+{======================================================================}
+
+procedure TDgramBlockSocket.Connect(IP, Port: string);
+begin
+ SetRemoteSin(IP, Port);
+ InternalCreateSocket(FRemoteSin);
+ FBuffer := '';
+ DoStatus(HR_Connect, IP + ':' + Port);
+end;
+
+function TDgramBlockSocket.RecvBuffer(Buffer: TMemory; Length: Integer): Integer;
+begin
+ Result := RecvBufferFrom(Buffer, Length);
+end;
+
+function TDgramBlockSocket.SendBuffer(Buffer: TMemory; Length: Integer): Integer;
+begin
+ Result := SendBufferTo(Buffer, Length);
+end;
+
+{======================================================================}
+
+destructor TUDPBlockSocket.Destroy;
+begin
+ if Assigned(FSocksControlSock) then
+ FSocksControlSock.Free;
+ inherited;
+end;
+
+procedure TUDPBlockSocket.EnableBroadcast(Value: Boolean);
+var
+ d: TSynaOption;
+begin
+ d := TSynaOption.Create;
+ d.Option := SOT_Broadcast;
+ d.Enabled := Value;
+ DelayedOption(d);
+end;
+
+function TUDPBlockSocket.UdpAssociation: Boolean;
+var
+ b: Boolean;
+begin
+ Result := True;
+ FUsingSocks := False;
+ if FSocksIP <> '' then
+ begin
+ Result := False;
+ if not Assigned(FSocksControlSock) then
+ FSocksControlSock := TTCPBlockSocket.Create;
+ FSocksControlSock.CloseSocket;
+ FSocksControlSock.CreateSocketByName(FSocksIP);
+ FSocksControlSock.Connect(FSocksIP, FSocksPort);
+ if FSocksControlSock.LastError <> 0 then
+ Exit;
+ // if not assigned local port, assign it!
+ if not FBinded then
+ Bind(cAnyHost, cAnyPort);
+ //open control TCP connection to SOCKS
+ FSocksControlSock.FSocksUsername := FSocksUsername;
+ FSocksControlSock.FSocksPassword := FSocksPassword;
+ b := FSocksControlSock.SocksOpen;
+ if b then
+ b := FSocksControlSock.SocksRequest(3, GetLocalSinIP, IntToStr(GetLocalSinPort));
+ if b then
+ b := FSocksControlSock.SocksResponse;
+ if not b and (FLastError = 0) then
+ FLastError := WSANO_RECOVERY;
+ FUsingSocks :=FSocksControlSock.UsingSocks;
+ FSocksRemoteIP := FSocksControlSock.FSocksResponseIP;
+ FSocksRemotePort := FSocksControlSock.FSocksResponsePort;
+ Result := b and (FLastError = 0);
+ end;
+end;
+
+function TUDPBlockSocket.SendBufferTo(Buffer: TMemory; Length: Integer): Integer;
+var
+ SIp: string;
+ SPort: integer;
+ Buf: Ansistring;
+begin
+ Result := 0;
+ FUsingSocks := False;
+ if (FSocksIP <> '') and (not UdpAssociation) then
+ FLastError := WSANO_RECOVERY
+ else
+ begin
+ if FUsingSocks then
+ begin
+{$IFNDEF CIL}
+ Sip := GetRemoteSinIp;
+ SPort := GetRemoteSinPort;
+ SetRemoteSin(FSocksRemoteIP, FSocksRemotePort);
+ SetLength(Buf,Length);
+ Move(Buffer^, Pointer(Buf)^, Length);
+ Buf := #0 + #0 + #0 + SocksCode(Sip, IntToStr(SPort)) + Buf;
+ Result := inherited SendBufferTo(Pointer(Buf), System.Length(buf));
+ SetRemoteSin(Sip, IntToStr(SPort));
+{$ENDIF}
+ end
+ else
+ Result := inherited SendBufferTo(Buffer, Length);
+ end;
+end;
+
+function TUDPBlockSocket.RecvBufferFrom(Buffer: TMemory; Length: Integer): Integer;
+var
+ Buf: Ansistring;
+ x: integer;
+begin
+ Result := inherited RecvBufferFrom(Buffer, Length);
+ if FUsingSocks then
+ begin
+{$IFNDEF CIL}
+ SetLength(Buf, Result);
+ Move(Buffer^, Pointer(Buf)^, Result);
+ x := SocksDecode(Buf);
+ Result := Result - x + 1;
+ Buf := Copy(Buf, x, Result);
+ Move(Pointer(Buf)^, Buffer^, Result);
+ SetRemoteSin(FSocksResponseIP, FSocksResponsePort);
+{$ENDIF}
+ end;
+end;
+
+{$IFNDEF CIL}
+procedure TUDPBlockSocket.AddMulticast(MCastIP: string);
+var
+ Multicast: TIP_mreq;
+ Multicast6: TIPv6_mreq;
+ n: integer;
+ ip6: Tip6bytes;
+begin
+ if FIP6Used then
+ begin
+ ip6 := StrToIp6(MCastIP);
+ for n := 0 to 15 do
+ Multicast6.ipv6mr_multiaddr.u6_addr8[n] := Ip6[n];
+ Multicast6.ipv6mr_interface := 0;
+ SockCheck(synsock.SetSockOpt(FSocket, IPPROTO_IPV6, IPV6_JOIN_GROUP,
+ PAnsiChar(@Multicast6), SizeOf(Multicast6)));
+ end
+ else
+ begin
+ Multicast.imr_multiaddr.S_addr := swapbytes(strtoip(MCastIP));
+ Multicast.imr_interface.S_addr := INADDR_ANY;
+ SockCheck(synsock.SetSockOpt(FSocket, IPPROTO_IP, IP_ADD_MEMBERSHIP,
+ PAnsiChar(@Multicast), SizeOf(Multicast)));
+ end;
+ ExceptCheck;
+end;
+
+procedure TUDPBlockSocket.DropMulticast(MCastIP: string);
+var
+ Multicast: TIP_mreq;
+ Multicast6: TIPv6_mreq;
+ n: integer;
+ ip6: Tip6bytes;
+begin
+ if FIP6Used then
+ begin
+ ip6 := StrToIp6(MCastIP);
+ for n := 0 to 15 do
+ Multicast6.ipv6mr_multiaddr.u6_addr8[n] := Ip6[n];
+ Multicast6.ipv6mr_interface := 0;
+ SockCheck(synsock.SetSockOpt(FSocket, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
+ PAnsiChar(@Multicast6), SizeOf(Multicast6)));
+ end
+ else
+ begin
+ Multicast.imr_multiaddr.S_addr := swapbytes(strtoip(MCastIP));
+ Multicast.imr_interface.S_addr := INADDR_ANY;
+ SockCheck(synsock.SetSockOpt(FSocket, IPPROTO_IP, IP_DROP_MEMBERSHIP,
+ PAnsiChar(@Multicast), SizeOf(Multicast)));
+ end;
+ ExceptCheck;
+end;
+{$ENDIF}
+
+procedure TUDPBlockSocket.SetMulticastTTL(TTL: integer);
+var
+ d: TSynaOption;
+begin
+ d := TSynaOption.Create;
+ d.Option := SOT_MulticastTTL;
+ d.Value := TTL;
+ DelayedOption(d);
+end;
+
+function TUDPBlockSocket.GetMulticastTTL:integer;
+var
+ l: Integer;
+begin
+{$IFNDEF CIL}
+ l := SizeOf(Result);
+ if FIP6Used then
+ synsock.GetSockOpt(FSocket, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, @Result, l)
+ else
+ synsock.GetSockOpt(FSocket, IPPROTO_IP, IP_MULTICAST_TTL, @Result, l);
+{$ENDIF}
+end;
+
+procedure TUDPBlockSocket.EnableMulticastLoop(Value: Boolean);
+var
+ d: TSynaOption;
+begin
+ d := TSynaOption.Create;
+ d.Option := SOT_MulticastLoop;
+ d.Enabled := Value;
+ DelayedOption(d);
+end;
+
+function TUDPBlockSocket.GetSocketType: integer;
+begin
+ Result := integer(SOCK_DGRAM);
+end;
+
+function TUDPBlockSocket.GetSocketProtocol: integer;
+begin
+ Result := integer(IPPROTO_UDP);
+end;
+
+{======================================================================}
+constructor TTCPBlockSocket.CreateWithSSL(SSLPlugin: TSSLClass);
+begin
+ inherited Create;
+ FSSL := SSLPlugin.Create(self);
+ FHTTPTunnelIP := '';
+ FHTTPTunnelPort := '';
+ FHTTPTunnel := False;
+ FHTTPTunnelRemoteIP := '';
+ FHTTPTunnelRemotePort := '';
+ FHTTPTunnelUser := '';
+ FHTTPTunnelPass := '';
+ FHTTPTunnelTimeout := 30000;
+end;
+
+constructor TTCPBlockSocket.Create;
+begin
+ CreateWithSSL(SSLImplementation);
+end;
+
+destructor TTCPBlockSocket.Destroy;
+begin
+ inherited Destroy;
+ FSSL.Free;
+end;
+
+function TTCPBlockSocket.GetErrorDescEx: string;
+begin
+ Result := inherited GetErrorDescEx;
+ if (FLastError = WSASYSNOTREADY) and (self.SSL.LastError <> 0) then
+ begin
+ Result := self.SSL.LastErrorDesc;
+ end;
+end;
+
+procedure TTCPBlockSocket.CloseSocket;
+begin
+ if FSSL.SSLEnabled then
+ FSSL.Shutdown;
+ if (FSocket <> INVALID_SOCKET) and (FLastError = 0) then
+ begin
+ Synsock.Shutdown(FSocket, 1);
+ Purge;
+ end;
+ inherited CloseSocket;
+end;
+
+procedure TTCPBlockSocket.DoAfterConnect;
+begin
+ if assigned(OnAfterConnect) then
+ begin
+ OnAfterConnect(Self);
+ end;
+end;
+
+function TTCPBlockSocket.WaitingData: Integer;
+begin
+ Result := 0;
+ if FSSL.SSLEnabled and (FSocket <> INVALID_SOCKET) then
+ Result := FSSL.WaitingData;
+ if Result = 0 then
+ Result := inherited WaitingData;
+end;
+
+procedure TTCPBlockSocket.Listen;
+var
+ b: Boolean;
+ Sip,SPort: string;
+begin
+ if FSocksIP = '' then
+ begin
+ SockCheck(synsock.Listen(FSocket, SOMAXCONN));
+ GetSins;
+ end
+ else
+ begin
+ Sip := GetLocalSinIP;
+ if Sip = cAnyHost then
+ Sip := LocalName;
+ SPort := IntToStr(GetLocalSinPort);
+ inherited Connect(FSocksIP, FSocksPort);
+ b := SocksOpen;
+ if b then
+ b := SocksRequest(2, Sip, SPort);
+ if b then
+ b := SocksResponse;
+ if not b and (FLastError = 0) then
+ FLastError := WSANO_RECOVERY;
+ FSocksLocalIP := FSocksResponseIP;
+ if FSocksLocalIP = cAnyHost then
+ FSocksLocalIP := FSocksIP;
+ FSocksLocalPort := FSocksResponsePort;
+ FSocksRemoteIP := '';
+ FSocksRemotePort := '';
+ end;
+ ExceptCheck;
+ DoStatus(HR_Listen, '');
+end;
+
+function TTCPBlockSocket.Accept: TSocket;
+begin
+ if FUsingSocks then
+ begin
+ if not SocksResponse and (FLastError = 0) then
+ FLastError := WSANO_RECOVERY;
+ FSocksRemoteIP := FSocksResponseIP;
+ FSocksRemotePort := FSocksResponsePort;
+ Result := FSocket;
+ end
+ else
+ begin
+ Result := synsock.Accept(FSocket, FRemoteSin);
+/// SockCheck(Result);
+ end;
+ ExceptCheck;
+ DoStatus(HR_Accept, '');
+end;
+
+procedure TTCPBlockSocket.Connect(IP, Port: string);
+begin
+ if FSocksIP <> '' then
+ SocksDoConnect(IP, Port)
+ else
+ if FHTTPTunnelIP <> '' then
+ HTTPTunnelDoConnect(IP, Port)
+ else
+ inherited Connect(IP, Port);
+ if FLasterror = 0 then
+ DoAfterConnect;
+end;
+
+procedure TTCPBlockSocket.SocksDoConnect(IP, Port: string);
+var
+ b: Boolean;
+begin
+ inherited Connect(FSocksIP, FSocksPort);
+ if FLastError = 0 then
+ begin
+ b := SocksOpen;
+ if b then
+ b := SocksRequest(1, IP, Port);
+ if b then
+ b := SocksResponse;
+ if not b and (FLastError = 0) then
+ FLastError := WSASYSNOTREADY;
+ FSocksLocalIP := FSocksResponseIP;
+ FSocksLocalPort := FSocksResponsePort;
+ FSocksRemoteIP := IP;
+ FSocksRemotePort := Port;
+ end;
+ ExceptCheck;
+ DoStatus(HR_Connect, IP + ':' + Port);
+end;
+
+procedure TTCPBlockSocket.HTTPTunnelDoConnect(IP, Port: string);
+//bugfixed by Mike Green (mgreen@emixode.com)
+var
+ s: string;
+begin
+ Port := IntToStr(ResolvePort(Port));
+ inherited Connect(FHTTPTunnelIP, FHTTPTunnelPort);
+ if FLastError <> 0 then
+ Exit;
+ FHTTPTunnel := False;
+ if IsIP6(IP) then
+ IP := '[' + IP + ']';
+ SendString('CONNECT ' + IP + ':' + Port + ' HTTP/1.0' + CRLF);
+ if FHTTPTunnelUser <> '' then
+ Sendstring('Proxy-Authorization: Basic ' +
+ EncodeBase64(FHTTPTunnelUser + ':' + FHTTPTunnelPass) + CRLF);
+ SendString(CRLF);
+ repeat
+ s := RecvTerminated(FHTTPTunnelTimeout, #$0a);
+ if FLastError <> 0 then
+ Break;
+ if (Pos('HTTP/', s) = 1) and (Length(s) > 11) then
+ FHTTPTunnel := s[10] = '2';
+ until (s = '') or (s = #$0d);
+ if (FLasterror = 0) and not FHTTPTunnel then
+ FLastError := WSASYSNOTREADY;
+ FHTTPTunnelRemoteIP := IP;
+ FHTTPTunnelRemotePort := Port;
+ ExceptCheck;
+end;
+
+procedure TTCPBlockSocket.SSLDoConnect;
+begin
+ ResetLastError;
+ if not FSSL.Connect then
+ FLastError := WSASYSNOTREADY;
+ ExceptCheck;
+end;
+
+procedure TTCPBlockSocket.SSLDoShutdown;
+begin
+ ResetLastError;
+ FSSL.BiShutdown;
+end;
+
+function TTCPBlockSocket.GetLocalSinIP: string;
+begin
+ if FUsingSocks then
+ Result := FSocksLocalIP
+ else
+ Result := inherited GetLocalSinIP;
+end;
+
+function TTCPBlockSocket.GetRemoteSinIP: string;
+begin
+ if FUsingSocks then
+ Result := FSocksRemoteIP
+ else
+ if FHTTPTunnel then
+ Result := FHTTPTunnelRemoteIP
+ else
+ Result := inherited GetRemoteSinIP;
+end;
+
+function TTCPBlockSocket.GetLocalSinPort: Integer;
+begin
+ if FUsingSocks then
+ Result := StrToIntDef(FSocksLocalPort, 0)
+ else
+ Result := inherited GetLocalSinPort;
+end;
+
+function TTCPBlockSocket.GetRemoteSinPort: Integer;
+begin
+ if FUsingSocks then
+ Result := ResolvePort(FSocksRemotePort)
+ else
+ if FHTTPTunnel then
+ Result := StrToIntDef(FHTTPTunnelRemotePort, 0)
+ else
+ Result := inherited GetRemoteSinPort;
+end;
+
+function TTCPBlockSocket.RecvBuffer(Buffer: TMemory; Len: Integer): Integer;
+begin
+ if FSSL.SSLEnabled then
+ begin
+ Result := 0;
+ if TestStopFlag then
+ Exit;
+ ResetLastError;
+ LimitBandwidth(Len, FMaxRecvBandwidth, FNextRecv);
+ Result := FSSL.RecvBuffer(Buffer, Len);
+ if FSSL.LastError <> 0 then
+ FLastError := WSASYSNOTREADY;
+ ExceptCheck;
+ Inc(FRecvCounter, Result);
+ DoStatus(HR_ReadCount, IntToStr(Result));
+ DoMonitor(False, Buffer, Result);
+ DoReadFilter(Buffer, Result);
+ end
+ else
+ Result := inherited RecvBuffer(Buffer, Len);
+end;
+
+function TTCPBlockSocket.SendBuffer(Buffer: TMemory; Length: Integer): Integer;
+var
+ x, y: integer;
+ l, r: integer;
+{$IFNDEF CIL}
+ p: Pointer;
+{$ENDIF}
+begin
+ if FSSL.SSLEnabled then
+ begin
+ Result := 0;
+ if TestStopFlag then
+ Exit;
+ ResetLastError;
+ DoMonitor(True, Buffer, Length);
+{$IFDEF CIL}
+ Result := FSSL.SendBuffer(Buffer, Length);
+ if FSSL.LastError <> 0 then
+ FLastError := WSASYSNOTREADY;
+ Inc(FSendCounter, Result);
+ DoStatus(HR_WriteCount, IntToStr(Result));
+{$ELSE}
+ l := Length;
+ x := 0;
+ while x < l do
+ begin
+ y := l - x;
+ if y > FSendMaxChunk then
+ y := FSendMaxChunk;
+ if y > 0 then
+ begin
+ LimitBandwidth(y, FMaxSendBandwidth, FNextsend);
+ p := IncPoint(Buffer, x);
+ r := FSSL.SendBuffer(p, y);
+ if FSSL.LastError <> 0 then
+ FLastError := WSASYSNOTREADY;
+ if Flasterror <> 0 then
+ Break;
+ Inc(x, r);
+ Inc(Result, r);
+ Inc(FSendCounter, r);
+ DoStatus(HR_WriteCount, IntToStr(r));
+ end
+ else
+ break;
+ end;
+{$ENDIF}
+ ExceptCheck;
+ end
+ else
+ Result := inherited SendBuffer(Buffer, Length);
+end;
+
+function TTCPBlockSocket.SSLAcceptConnection: Boolean;
+begin
+ ResetLastError;
+ if not FSSL.Accept then
+ FLastError := WSASYSNOTREADY;
+ ExceptCheck;
+ Result := FLastError = 0;
+end;
+
+function TTCPBlockSocket.GetSocketType: integer;
+begin
+ Result := integer(SOCK_STREAM);
+end;
+
+function TTCPBlockSocket.GetSocketProtocol: integer;
+begin
+ Result := integer(IPPROTO_TCP);
+end;
+
+{======================================================================}
+
+function TICMPBlockSocket.GetSocketType: integer;
+begin
+ Result := integer(SOCK_RAW);
+end;
+
+function TICMPBlockSocket.GetSocketProtocol: integer;
+begin
+ if FIP6Used then
+ Result := integer(IPPROTO_ICMPV6)
+ else
+ Result := integer(IPPROTO_ICMP);
+end;
+
+{======================================================================}
+
+function TRAWBlockSocket.GetSocketType: integer;
+begin
+ Result := integer(SOCK_RAW);
+end;
+
+function TRAWBlockSocket.GetSocketProtocol: integer;
+begin
+ Result := integer(IPPROTO_RAW);
+end;
+
+{======================================================================}
+
+constructor TSynaClient.Create;
+begin
+ inherited Create;
+ FIPInterface := cAnyHost;
+ FTargetHost := cLocalhost;
+ FTargetPort := cAnyPort;
+ FTimeout := 5000;
+ FUsername := '';
+ FPassword := '';
+end;
+
+{======================================================================}
+
+constructor TCustomSSL.Create(const Value: TTCPBlockSocket);
+begin
+ inherited Create;
+ FSocket := Value;
+ FSSLEnabled := False;
+ FUsername := '';
+ FPassword := '';
+ FLastError := 0;
+ FLastErrorDesc := '';
+ FVerifyCert := False;
+ FSSLType := LT_all;
+ FKeyPassword := '';
+ FCiphers := '';
+ FCertificateFile := '';
+ FPrivateKeyFile := '';
+ FCertCAFile := '';
+ FCertCA := '';
+ FTrustCertificate := '';
+ FTrustCertificateFile := '';
+ FCertificate := '';
+ FPrivateKey := '';
+ FPFX := '';
+ FPFXfile := '';
+ FSSHChannelType := '';
+ FSSHChannelArg1 := '';
+ FSSHChannelArg2 := '';
+end;
+
+procedure TCustomSSL.Assign(const Value: TCustomSSL);
+begin
+ FUsername := Value.Username;
+ FPassword := Value.Password;
+ FVerifyCert := Value.VerifyCert;
+ FSSLType := Value.SSLType;
+ FKeyPassword := Value.KeyPassword;
+ FCiphers := Value.Ciphers;
+ FCertificateFile := Value.CertificateFile;
+ FPrivateKeyFile := Value.PrivateKeyFile;
+ FCertCAFile := Value.CertCAFile;
+ FCertCA := Value.CertCA;
+ FTrustCertificate := Value.TrustCertificate;
+ FTrustCertificateFile := Value.TrustCertificateFile;
+ FCertificate := Value.Certificate;
+ FPrivateKey := Value.PrivateKey;
+ FPFX := Value.PFX;
+ FPFXfile := Value.PFXfile;
+end;
+
+procedure TCustomSSL.ReturnError;
+begin
+ FLastError := -1;
+ FLastErrorDesc := 'SSL/TLS support is not compiled!';
+end;
+
+function TCustomSSL.LibVersion: String;
+begin
+ Result := '';
+end;
+
+function TCustomSSL.LibName: String;
+begin
+ Result := '';
+end;
+
+function TCustomSSL.CreateSelfSignedCert(Host: string): Boolean;
+begin
+ Result := False;
+end;
+
+function TCustomSSL.Connect: boolean;
+begin
+ ReturnError;
+ Result := False;
+end;
+
+function TCustomSSL.Accept: boolean;
+begin
+ ReturnError;
+ Result := False;
+end;
+
+function TCustomSSL.Shutdown: boolean;
+begin
+ ReturnError;
+ Result := False;
+end;
+
+function TCustomSSL.BiShutdown: boolean;
+begin
+ ReturnError;
+ Result := False;
+end;
+
+function TCustomSSL.SendBuffer(Buffer: TMemory; Len: Integer): Integer;
+begin
+ ReturnError;
+ Result := integer(SOCKET_ERROR);
+end;
+
+function TCustomSSL.RecvBuffer(Buffer: TMemory; Len: Integer): Integer;
+begin
+ ReturnError;
+ Result := integer(SOCKET_ERROR);
+end;
+
+function TCustomSSL.WaitingData: Integer;
+begin
+ ReturnError;
+ Result := 0;
+end;
+
+function TCustomSSL.GetSSLVersion: string;
+begin
+ Result := '';
+end;
+
+function TCustomSSL.GetPeerSubject: string;
+begin
+ Result := '';
+end;
+
+function TCustomSSL.GetPeerName: string;
+begin
+ Result := '';
+end;
+
+function TCustomSSL.GetPeerIssuer: string;
+begin
+ Result := '';
+end;
+
+function TCustomSSL.GetPeerFingerprint: string;
+begin
+ Result := '';
+end;
+
+function TCustomSSL.GetCertInfo: string;
+begin
+ Result := '';
+end;
+
+function TCustomSSL.GetCipherName: string;
+begin
+ Result := '';
+end;
+
+function TCustomSSL.GetCipherBits: integer;
+begin
+ Result := 0;
+end;
+
+function TCustomSSL.GetCipherAlgBits: integer;
+begin
+ Result := 0;
+end;
+
+function TCustomSSL.GetVerifyCert: integer;
+begin
+ Result := 1;
+end;
+
+{======================================================================}
+
+function TSSLNone.LibVersion: String;
+begin
+ Result := 'Without SSL support';
+end;
+
+function TSSLNone.LibName: String;
+begin
+ Result := 'ssl_none';
+end;
+
+{======================================================================}
+
+{$IFDEF ONCEWINSOCK}
+initialization
+begin
+ if not InitSocketInterface(DLLStackName) then
+ begin
+ e := ESynapseError.Create('Error loading Socket interface (' + DLLStackName + ')!');
+ e.ErrorCode := 0;
+ e.ErrorMessage := 'Error loading Socket interface (' + DLLStackName + ')!';
+ raise e;
+ end;
+ synsock.WSAStartup(WinsockLevel, WsaDataOnce);
+end;
+{$ENDIF}
+
+finalization
+begin
+{$IFDEF ONCEWINSOCK}
+ synsock.WSACleanup;
+ DestroySocketInterface;
+{$ENDIF}
+end;
+
+end.
diff --git a/branches/script-component/Units/Synapse/clamsend.pas b/branches/script-component/Units/Synapse/clamsend.pas
new file mode 100644
index 0000000..91a9f56
--- /dev/null
+++ b/branches/script-component/Units/Synapse/clamsend.pas
@@ -0,0 +1,271 @@
+{==============================================================================|
+| Project : Ararat Synapse | 001.001.000 |
+|==============================================================================|
+| Content: ClamAV-daemon client |
+|==============================================================================|
+| Copyright (c)2005-2009, Lukas Gebauer |
+| All rights reserved. |
+| |
+| Redistribution and use in source and binary forms, with or without |
+| modification, are permitted provided that the following conditions are met: |
+| |
+| Redistributions of source code must retain the above copyright notice, this |
+| list of conditions and the following disclaimer. |
+| |
+| Redistributions in binary form must reproduce the above copyright notice, |
+| this list of conditions and the following disclaimer in the documentation |
+| and/or other materials provided with the distribution. |
+| |
+| Neither the name of Lukas Gebauer nor the names of its contributors may |
+| be used to endorse or promote products derived from this software without |
+| specific prior written permission. |
+| |
+| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
+| AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
+| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
+| ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR |
+| ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
+| DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
+| SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
+| CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
+| LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
+| OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
+| DAMAGE. |
+|==============================================================================|
+| The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).|
+| Portions created by Lukas Gebauer are Copyright (c)2005-2009. |
+| All Rights Reserved. |
+|==============================================================================|
+| Contributor(s): |
+|==============================================================================|
+| History: see HISTORY.HTM from distribution package |
+| (Found at URL: http://www.ararat.cz/synapse/) |
+|==============================================================================}
+
+{:@abstract( ClamAV-daemon client)
+
+This unit is capable to do antivirus scan of your data by TCP channel to ClamD
+daemon from ClamAV. See more about ClamAV on @LINK(http://www.clamav.net)
+}
+
+{$IFDEF FPC}
+ {$MODE DELPHI}
+{$ENDIF}
+{$Q-}
+{$H+}
+
+unit clamsend;
+
+interface
+
+uses
+ SysUtils, Classes,
+ synsock, blcksock, synautil;
+
+const
+ cClamProtocol = '3310';
+
+type
+
+ {:@abstract(Implementation of ClamAV-daemon client protocol)
+ By this class you can scan any your data by ClamAV opensource antivirus.
+
+ This class can connect to ClamD by TCP channel, send your data to ClamD
+ and read result.}
+ TClamSend = class(TSynaClient)
+ private
+ FSock: TTCPBlockSocket;
+ FDSock: TTCPBlockSocket;
+ FSession: boolean;
+ function Login: boolean; virtual;
+ function Logout: Boolean; virtual;
+ function OpenStream: Boolean; virtual;
+ public
+ constructor Create;
+ destructor Destroy; override;
+
+ {:Call any command to ClamD. Used internally by other methods.}
+ function DoCommand(const Value: AnsiString): AnsiString; virtual;
+
+ {:Return ClamAV version and version of loaded databases.}
+ function GetVersion: AnsiString; virtual;
+
+ {:Scan content of TStrings.}
+ function ScanStrings(const Value: TStrings): AnsiString; virtual;
+
+ {:Scan content of TStream.}
+ function ScanStream(const Value: TStream): AnsiString; virtual;
+
+ {:Scan content of TStrings by new 0.95 API.}
+ function ScanStrings2(const Value: TStrings): AnsiString; virtual;
+
+ {:Scan content of TStream by new 0.95 API.}
+ function ScanStream2(const Value: TStream): AnsiString; virtual;
+ published
+ {:Socket object used for TCP/IP operation. Good for seting OnStatus hook, etc.}
+ property Sock: TTCPBlockSocket read FSock;
+
+ {:Socket object used for TCP data transfer operation. Good for seting OnStatus hook, etc.}
+ property DSock: TTCPBlockSocket read FDSock;
+
+ {:Can turn-on session mode of communication with ClamD. Default is @false,
+ because ClamAV developers design their TCP code very badly and session mode
+ is broken now (CVS-20051031). Maybe ClamAV developers fix their bugs
+ and this mode will be possible in future.}
+ property Session: boolean read FSession write FSession;
+ end;
+
+implementation
+
+constructor TClamSend.Create;
+begin
+ inherited Create;
+ FSock := TTCPBlockSocket.Create;
+ FDSock := TTCPBlockSocket.Create;
+ FTimeout := 60000;
+ FTargetPort := cClamProtocol;
+ FSession := false;
+end;
+
+destructor TClamSend.Destroy;
+begin
+ Logout;
+ FDSock.Free;
+ FSock.Free;
+ inherited Destroy;
+end;
+
+function TClamSend.DoCommand(const Value: AnsiString): AnsiString;
+begin
+ Result := '';
+ if not FSession then
+ FSock.CloseSocket
+ else
+ FSock.SendString(Value + LF);
+ if not FSession or (FSock.LastError <> 0) then
+ begin
+ if Login then
+ FSock.SendString(Value + LF)
+ else
+ Exit;
+ end;
+ Result := FSock.RecvTerminated(FTimeout, LF);
+end;
+
+function TClamSend.Login: boolean;
+begin
+ Result := False;
+ Sock.CloseSocket;
+ FSock.Bind(FIPInterface, cAnyPort);
+ if FSock.LastError <> 0 then
+ Exit;
+ FSock.Connect(FTargetHost, FTargetPort);
+ if FSock.LastError <> 0 then
+ Exit;
+ if FSession then
+ FSock.SendString('SESSION' + LF);
+ Result := FSock.LastError = 0;
+end;
+
+function TClamSend.Logout: Boolean;
+begin
+ FSock.SendString('END' + LF);
+ Result := FSock.LastError = 0;
+ FSock.CloseSocket;
+end;
+
+function TClamSend.GetVersion: AnsiString;
+begin
+ Result := DoCommand('nVERSION');
+end;
+
+function TClamSend.OpenStream: Boolean;
+var
+ S: AnsiString;
+begin
+ Result := False;
+ s := DoCommand('nSTREAM');
+ if (s <> '') and (Copy(s, 1, 4) = 'PORT') then
+ begin
+ s := SeparateRight(s, ' ');
+ FDSock.CloseSocket;
+ FDSock.Bind(FIPInterface, cAnyPort);
+ if FDSock.LastError <> 0 then
+ Exit;
+ FDSock.Connect(FTargetHost, s);
+ if FDSock.LastError <> 0 then
+ Exit;
+ Result := True;
+ end;
+end;
+
+function TClamSend.ScanStrings(const Value: TStrings): AnsiString;
+begin
+ Result := '';
+ if OpenStream then
+ begin
+ DSock.SendString(Value.Text);
+ DSock.CloseSocket;
+ Result := FSock.RecvTerminated(FTimeout, LF);
+ end;
+end;
+
+function TClamSend.ScanStream(const Value: TStream): AnsiString;
+begin
+ Result := '';
+ if OpenStream then
+ begin
+ DSock.SendStreamRaw(Value);
+ DSock.CloseSocket;
+ Result := FSock.RecvTerminated(FTimeout, LF);
+ end;
+end;
+
+function TClamSend.ScanStrings2(const Value: TStrings): AnsiString;
+var
+ i: integer;
+ s: AnsiString;
+begin
+ Result := '';
+ if not FSession then
+ FSock.CloseSocket
+ else
+ FSock.sendstring('nINSTREAM' + LF);
+ if not FSession or (FSock.LastError <> 0) then
+ begin
+ if Login then
+ FSock.sendstring('nINSTREAM' + LF)
+ else
+ Exit;
+ end;
+ s := Value.text;
+ i := length(s);
+ FSock.SendString(CodeLongint(i) + s + #0#0#0#0);
+ Result := FSock.RecvTerminated(FTimeout, LF);
+end;
+
+function TClamSend.ScanStream2(const Value: TStream): AnsiString;
+var
+ i: integer;
+ s: AnsiString;
+begin
+ Result := '';
+ if not FSession then
+ FSock.CloseSocket
+ else
+ FSock.sendstring('nINSTREAM' + LF);
+ if not FSession or (FSock.LastError <> 0) then
+ begin
+ if Login then
+ FSock.sendstring('nINSTREAM' + LF)
+ else
+ Exit;
+ end;
+ i := value.Size;
+ FSock.SendString(CodeLongint(i));
+ FSock.SendStreamRaw(Value);
+ FSock.SendString(#0#0#0#0);
+ Result := FSock.RecvTerminated(FTimeout, LF);
+end;
+
+end.
diff --git a/branches/script-component/Units/Synapse/dnssend.pas b/branches/script-component/Units/Synapse/dnssend.pas
new file mode 100644
index 0000000..f7684ce
--- /dev/null
+++ b/branches/script-component/Units/Synapse/dnssend.pas
@@ -0,0 +1,596 @@
+{==============================================================================|
+| Project : Ararat Synapse | 002.007.004 |
+|==============================================================================|
+| Content: DNS client |
+|==============================================================================|
+| Copyright (c)1999-2007, Lukas Gebauer |
+| All rights reserved. |
+| |
+| Redistribution and use in source and binary forms, with or without |
+| modification, are permitted provided that the following conditions are met: |
+| |
+| Redistributions of source code must retain the above copyright notice, this |
+| list of conditions and the following disclaimer. |
+| |
+| Redistributions in binary form must reproduce the above copyright notice, |
+| this list of conditions and the following disclaimer in the documentation |
+| and/or other materials provided with the distribution. |
+| |
+| Neither the name of Lukas Gebauer nor the names of its contributors may |
+| be used to endorse or promote products derived from this software without |
+| specific prior written permission. |
+| |
+| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
+| AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
+| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
+| ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR |
+| ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
+| DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
+| SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
+| CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
+| LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
+| OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
+| DAMAGE. |
+|==============================================================================|
+| The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).|
+| Portions created by Lukas Gebauer are Copyright (c)2000-2007. |
+| All Rights Reserved. |
+|==============================================================================|
+| Contributor(s): |
+|==============================================================================|
+| History: see HISTORY.HTM from distribution package |
+| (Found at URL: http://www.ararat.cz/synapse/) |
+|==============================================================================}
+{: @abstract(DNS client by UDP or TCP)
+Support for sending DNS queries by UDP or TCP protocol. It can retrieve zone
+ transfers too!
+
+Used RFC: RFC-1035, RFC-1183, RFC1706, RFC1712, RFC2163, RFC2230
+}
+
+{$IFDEF FPC}
+ {$MODE DELPHI}
+{$ENDIF}
+{$Q-}
+{$H+}
+
+unit dnssend;
+
+interface
+
+uses
+ SysUtils, Classes,
+ blcksock, synautil, synaip, synsock;
+
+const
+ cDnsProtocol = '53';
+
+ QTYPE_A = 1;
+ QTYPE_NS = 2;
+ QTYPE_MD = 3;
+ QTYPE_MF = 4;
+ QTYPE_CNAME = 5;
+ QTYPE_SOA = 6;
+ QTYPE_MB = 7;
+ QTYPE_MG = 8;
+ QTYPE_MR = 9;
+ QTYPE_NULL = 10;
+ QTYPE_WKS = 11; //
+ QTYPE_PTR = 12;
+ QTYPE_HINFO = 13;
+ QTYPE_MINFO = 14;
+ QTYPE_MX = 15;
+ QTYPE_TXT = 16;
+
+ QTYPE_RP = 17;
+ QTYPE_AFSDB = 18;
+ QTYPE_X25 = 19;
+ QTYPE_ISDN = 20;
+ QTYPE_RT = 21;
+ QTYPE_NSAP = 22;
+ QTYPE_NSAPPTR = 23;
+ QTYPE_SIG = 24; // RFC-2065
+ QTYPE_KEY = 25; // RFC-2065
+ QTYPE_PX = 26;
+ QTYPE_GPOS = 27;
+ QTYPE_AAAA = 28;
+ QTYPE_LOC = 29; // RFC-1876
+ QTYPE_NXT = 30; // RFC-2065
+
+ QTYPE_SRV = 33;
+ QTYPE_NAPTR = 35; // RFC-2168
+ QTYPE_KX = 36;
+ QTYPE_SPF = 99;
+
+ QTYPE_AXFR = 252;
+ QTYPE_MAILB = 253; //
+ QTYPE_MAILA = 254; //
+ QTYPE_ALL = 255;
+
+type
+ {:@abstract(Implementation of DNS protocol by UDP or TCP protocol.)
+
+ Note: Are you missing properties for specify server address and port? Look to
+ parent @link(TSynaClient) too!}
+ TDNSSend = class(TSynaClient)
+ private
+ FID: Word;
+ FRCode: Integer;
+ FBuffer: AnsiString;
+ FSock: TUDPBlockSocket;
+ FTCPSock: TTCPBlockSocket;
+ FUseTCP: Boolean;
+ FAnswerInfo: TStringList;
+ FNameserverInfo: TStringList;
+ FAdditionalInfo: TStringList;
+ FAuthoritative: Boolean;
+ FTruncated: Boolean;
+ function CompressName(const Value: AnsiString): AnsiString;
+ function CodeHeader: AnsiString;
+ function CodeQuery(const Name: AnsiString; QType: Integer): AnsiString;
+ function DecodeLabels(var From: Integer): AnsiString;
+ function DecodeString(var From: Integer): AnsiString;
+ function DecodeResource(var i: Integer; const Info: TStringList;
+ QType: Integer): AnsiString;
+ function RecvTCPResponse(const WorkSock: TBlockSocket): AnsiString;
+ function DecodeResponse(const Buf: AnsiString; const Reply: TStrings;
+ QType: Integer):boolean;
+ public
+ constructor Create;
+ destructor Destroy; override;
+
+ {:Query a DNSHost for QType resources correspond to a name. Supported QType
+ values are: Qtype_A, Qtype_NS, Qtype_MD, Qtype_MF, Qtype_CNAME, Qtype_SOA,
+ Qtype_MB, Qtype_MG, Qtype_MR, Qtype_NULL, Qtype_PTR, Qtype_HINFO,
+ Qtype_MINFO, Qtype_MX, Qtype_TXT, Qtype_RP, Qtype_AFSDB, Qtype_X25,
+ Qtype_ISDN, Qtype_RT, Qtype_NSAP, Qtype_NSAPPTR, Qtype_PX, Qtype_GPOS,
+ Qtype_KX.
+
+ Type for zone transfers QTYPE_AXFR is supported too, but only in TCP mode!
+
+ "Name" is domain name or host name for queried resource. If "name" is
+ IP address, automatically convert to reverse domain form (.in-addr.arpa).
+
+ If result is @true, Reply contains resource records. One record on one line.
+ If Resource record have multiple fields, they are stored on line divided by
+ comma. (example: MX record contains value 'rs.cesnet.cz' with preference
+ number 10, string in Reply is: '10,rs.cesnet.cz'). All numbers or IP address
+ in resource are converted to string form.}
+ function DNSQuery(Name: AnsiString; QType: Integer;
+ const Reply: TStrings): Boolean;
+ published
+
+ {:Socket object used for UDP operation. Good for seting OnStatus hook, etc.}
+ property Sock: TUDPBlockSocket read FSock;
+
+ {:Socket object used for TCP operation. Good for seting OnStatus hook, etc.}
+ property TCPSock: TTCPBlockSocket read FTCPSock;
+
+ {:if @true, then is used TCP protocol instead UDP. It is needed for zone
+ transfers, etc.}
+ property UseTCP: Boolean read FUseTCP Write FUseTCP;
+
+ {:After DNS operation contains ResultCode of DNS operation.
+ Values are: 0-no error, 1-format error, 2-server failure, 3-name error,
+ 4-not implemented, 5-refused.}
+ property RCode: Integer read FRCode;
+
+ {:@True, if answer is authoritative.}
+ property Authoritative: Boolean read FAuthoritative;
+
+ {:@True, if answer is truncated to 512 bytes.}
+ property Truncated: Boolean read FTRuncated;
+
+ {:Detailed informations from name server reply. One record per line. Record
+ have comma delimited entries with type number, TTL and data filelds.
+ This information contains detailed information about query reply.}
+ property AnswerInfo: TStringList read FAnswerInfo;
+
+ {:Detailed informations from name server reply. One record per line. Record
+ have comma delimited entries with type number, TTL and data filelds.
+ This information contains detailed information about nameserver.}
+ property NameserverInfo: TStringList read FNameserverInfo;
+
+ {:Detailed informations from name server reply. One record per line. Record
+ have comma delimited entries with type number, TTL and data filelds.
+ This information contains detailed additional information.}
+ property AdditionalInfo: TStringList read FAdditionalInfo;
+ end;
+
+{:A very useful function, and example of it's use is found in the TDNSSend object.
+ This function is used to get mail servers for a domain and sort them by
+ preference numbers. "Servers" contains only the domain names of the mail
+ servers in the right order (without preference number!). The first domain name
+ will always be the highest preferenced mail server. Returns boolean @TRUE if
+ all went well.}
+function GetMailServers(const DNSHost, Domain: AnsiString;
+ const Servers: TStrings): Boolean;
+
+implementation
+
+constructor TDNSSend.Create;
+begin
+ inherited Create;
+ FSock := TUDPBlockSocket.Create;
+ FTCPSock := TTCPBlockSocket.Create;
+ FUseTCP := False;
+ FTimeout := 10000;
+ FTargetPort := cDnsProtocol;
+ FAnswerInfo := TStringList.Create;
+ FNameserverInfo := TStringList.Create;
+ FAdditionalInfo := TStringList.Create;
+ Randomize;
+end;
+
+destructor TDNSSend.Destroy;
+begin
+ FAnswerInfo.Free;
+ FNameserverInfo.Free;
+ FAdditionalInfo.Free;
+ FTCPSock.Free;
+ FSock.Free;
+ inherited Destroy;
+end;
+
+function TDNSSend.CompressName(const Value: AnsiString): AnsiString;
+var
+ n: Integer;
+ s: AnsiString;
+begin
+ Result := '';
+ if Value = '' then
+ Result := #0
+ else
+ begin
+ s := '';
+ for n := 1 to Length(Value) do
+ if Value[n] = '.' then
+ begin
+ Result := Result + Char(Length(s)) + s;
+ s := '';
+ end
+ else
+ s := s + Value[n];
+ if s <> '' then
+ Result := Result + Char(Length(s)) + s;
+ Result := Result + #0;
+ end;
+end;
+
+function TDNSSend.CodeHeader: AnsiString;
+begin
+ FID := Random(32767);
+ Result := CodeInt(FID); // ID
+ Result := Result + CodeInt($0100); // flags
+ Result := Result + CodeInt(1); // QDCount
+ Result := Result + CodeInt(0); // ANCount
+ Result := Result + CodeInt(0); // NSCount
+ Result := Result + CodeInt(0); // ARCount
+end;
+
+function TDNSSend.CodeQuery(const Name: AnsiString; QType: Integer): AnsiString;
+begin
+ Result := CompressName(Name);
+ Result := Result + CodeInt(QType);
+ Result := Result + CodeInt(1); // Type INTERNET
+end;
+
+function TDNSSend.DecodeString(var From: Integer): AnsiString;
+var
+ Len: integer;
+begin
+ Len := Ord(FBuffer[From]);
+ Inc(From);
+ Result := Copy(FBuffer, From, Len);
+ Inc(From, Len);
+end;
+
+function TDNSSend.DecodeLabels(var From: Integer): AnsiString;
+var
+ l, f: Integer;
+begin
+ Result := '';
+ while True do
+ begin
+ if From >= Length(FBuffer) then
+ Break;
+ l := Ord(FBuffer[From]);
+ Inc(From);
+ if l = 0 then
+ Break;
+ if Result <> '' then
+ Result := Result + '.';
+ if (l and $C0) = $C0 then
+ begin
+ f := l and $3F;
+ f := f * 256 + Ord(FBuffer[From]) + 1;
+ Inc(From);
+ Result := Result + DecodeLabels(f);
+ Break;
+ end
+ else
+ begin
+ Result := Result + Copy(FBuffer, From, l);
+ Inc(From, l);
+ end;
+ end;
+end;
+
+function TDNSSend.DecodeResource(var i: Integer; const Info: TStringList;
+ QType: Integer): AnsiString;
+var
+ Rname: AnsiString;
+ RType, Len, j, x, y, z, n: Integer;
+ R: AnsiString;
+ t1, t2, ttl: integer;
+ ip6: TIp6bytes;
+begin
+ Result := '';
+ R := '';
+ Rname := DecodeLabels(i);
+ RType := DecodeInt(FBuffer, i);
+ Inc(i, 4);
+ t1 := DecodeInt(FBuffer, i);
+ Inc(i, 2);
+ t2 := DecodeInt(FBuffer, i);
+ Inc(i, 2);
+ ttl := t1 * 65536 + t2;
+ Len := DecodeInt(FBuffer, i);
+ Inc(i, 2); // i point to begin of data
+ j := i;
+ i := i + len; // i point to next record
+ if Length(FBuffer) >= (i - 1) then
+ case RType of
+ QTYPE_A:
+ begin
+ R := IntToStr(Ord(FBuffer[j]));
+ Inc(j);
+ R := R + '.' + IntToStr(Ord(FBuffer[j]));
+ Inc(j);
+ R := R + '.' + IntToStr(Ord(FBuffer[j]));
+ Inc(j);
+ R := R + '.' + IntToStr(Ord(FBuffer[j]));
+ end;
+ QTYPE_AAAA:
+ begin
+ for n := 0 to 15 do
+ ip6[n] := ord(FBuffer[j + n]);
+ R := IP6ToStr(ip6);
+ end;
+ QTYPE_NS, QTYPE_MD, QTYPE_MF, QTYPE_CNAME, QTYPE_MB,
+ QTYPE_MG, QTYPE_MR, QTYPE_PTR, QTYPE_X25, QTYPE_NSAP,
+ QTYPE_NSAPPTR:
+ R := DecodeLabels(j);
+ QTYPE_SOA:
+ begin
+ R := DecodeLabels(j);
+ R := R + ',' + DecodeLabels(j);
+ for n := 1 to 5 do
+ begin
+ x := DecodeInt(FBuffer, j) * 65536 + DecodeInt(FBuffer, j + 2);
+ Inc(j, 4);
+ R := R + ',' + IntToStr(x);
+ end;
+ end;
+ QTYPE_NULL:
+ begin
+ end;
+ QTYPE_WKS:
+ begin
+ end;
+ QTYPE_HINFO:
+ begin
+ R := DecodeString(j);
+ R := R + ',' + DecodeString(j);
+ end;
+ QTYPE_MINFO, QTYPE_RP, QTYPE_ISDN:
+ begin
+ R := DecodeLabels(j);
+ R := R + ',' + DecodeLabels(j);
+ end;
+ QTYPE_MX, QTYPE_AFSDB, QTYPE_RT, QTYPE_KX:
+ begin
+ x := DecodeInt(FBuffer, j);
+ Inc(j, 2);
+ R := IntToStr(x);
+ R := R + ',' + DecodeLabels(j);
+ end;
+ QTYPE_TXT, QTYPE_SPF:
+ begin
+ R := '';
+ while j < i do
+ R := R + DecodeString(j);
+ end;
+ QTYPE_GPOS:
+ begin
+ R := DecodeLabels(j);
+ R := R + ',' + DecodeLabels(j);
+ R := R + ',' + DecodeLabels(j);
+ end;
+ QTYPE_PX:
+ begin
+ x := DecodeInt(FBuffer, j);
+ Inc(j, 2);
+ R := IntToStr(x);
+ R := R + ',' + DecodeLabels(j);
+ R := R + ',' + DecodeLabels(j);
+ end;
+ QTYPE_SRV:
+ // Author: Dan
+ begin
+ x := DecodeInt(FBuffer, j);
+ Inc(j, 2);
+ y := DecodeInt(FBuffer, j);
+ Inc(j, 2);
+ z := DecodeInt(FBuffer, j);
+ Inc(j, 2);
+ R := IntToStr(x); // Priority
+ R := R + ',' + IntToStr(y); // Weight
+ R := R + ',' + IntToStr(z); // Port
+ R := R + ',' + DecodeLabels(j); // Server DNS Name
+ end;
+ end;
+ if R <> '' then
+ Info.Add(RName + ',' + IntToStr(RType) + ',' + IntToStr(ttl) + ',' + R);
+ if QType = RType then
+ Result := R;
+end;
+
+function TDNSSend.RecvTCPResponse(const WorkSock: TBlockSocket): AnsiString;
+var
+ l: integer;
+begin
+ Result := '';
+ l := WorkSock.recvbyte(FTimeout) * 256 + WorkSock.recvbyte(FTimeout);
+ if l > 0 then
+ Result := WorkSock.RecvBufferStr(l, FTimeout);
+end;
+
+function TDNSSend.DecodeResponse(const Buf: AnsiString; const Reply: TStrings;
+ QType: Integer):boolean;
+var
+ n, i: Integer;
+ flag, qdcount, ancount, nscount, arcount: Integer;
+ s: AnsiString;
+begin
+ Result := False;
+ Reply.Clear;
+ FAnswerInfo.Clear;
+ FNameserverInfo.Clear;
+ FAdditionalInfo.Clear;
+ FAuthoritative := False;
+ if (Length(Buf) > 13) and (FID = DecodeInt(Buf, 1)) then
+ begin
+ Result := True;
+ flag := DecodeInt(Buf, 3);
+ FRCode := Flag and $000F;
+ FAuthoritative := (Flag and $0400) > 0;
+ FTruncated := (Flag and $0200) > 0;
+ if FRCode = 0 then
+ begin
+ qdcount := DecodeInt(Buf, 5);
+ ancount := DecodeInt(Buf, 7);
+ nscount := DecodeInt(Buf, 9);
+ arcount := DecodeInt(Buf, 11);
+ i := 13; //begin of body
+ if (qdcount > 0) and (Length(Buf) > i) then //skip questions
+ for n := 1 to qdcount do
+ begin
+ while (Buf[i] <> #0) and ((Ord(Buf[i]) and $C0) <> $C0) do
+ Inc(i);
+ Inc(i, 5);
+ end;
+ if (ancount > 0) and (Length(Buf) > i) then // decode reply
+ for n := 1 to ancount do
+ begin
+ s := DecodeResource(i, FAnswerInfo, QType);
+ if s <> '' then
+ Reply.Add(s);
+ end;
+ if (nscount > 0) and (Length(Buf) > i) then // decode nameserver info
+ for n := 1 to nscount do
+ DecodeResource(i, FNameserverInfo, QType);
+ if (arcount > 0) and (Length(Buf) > i) then // decode additional info
+ for n := 1 to arcount do
+ DecodeResource(i, FAdditionalInfo, QType);
+ end;
+ end;
+end;
+
+function TDNSSend.DNSQuery(Name: AnsiString; QType: Integer;
+ const Reply: TStrings): Boolean;
+var
+ WorkSock: TBlockSocket;
+ t: TStringList;
+ b: boolean;
+begin
+ Result := False;
+ if IsIP(Name) then
+ Name := ReverseIP(Name) + '.in-addr.arpa';
+ if IsIP6(Name) then
+ Name := ReverseIP6(Name) + '.ip6.arpa';
+ FBuffer := CodeHeader + CodeQuery(Name, QType);
+ if FUseTCP then
+ WorkSock := FTCPSock
+ else
+ WorkSock := FSock;
+ WorkSock.Bind(FIPInterface, cAnyPort);
+ WorkSock.Connect(FTargetHost, FTargetPort);
+ if FUseTCP then
+ FBuffer := Codeint(length(FBuffer)) + FBuffer;
+ WorkSock.SendString(FBuffer);
+ if FUseTCP then
+ FBuffer := RecvTCPResponse(WorkSock)
+ else
+ FBuffer := WorkSock.RecvPacket(FTimeout);
+ if FUseTCP and (QType = QTYPE_AXFR) then //zone transfer
+ begin
+ t := TStringList.Create;
+ try
+ repeat
+ b := DecodeResponse(FBuffer, Reply, QType);
+ if (t.Count > 1) and (AnswerInfo.Count > 0) then //find end of transfer
+ b := b and (t[0] <> AnswerInfo[AnswerInfo.count - 1]);
+ if b then
+ begin
+ t.AddStrings(AnswerInfo);
+ FBuffer := RecvTCPResponse(WorkSock);
+ if FBuffer = '' then
+ Break;
+ if WorkSock.LastError <> 0 then
+ Break;
+ end;
+ until not b;
+ Reply.Assign(t);
+ Result := True;
+ finally
+ t.free;
+ end;
+ end
+ else //normal query
+ if WorkSock.LastError = 0 then
+ Result := DecodeResponse(FBuffer, Reply, QType);
+end;
+
+{==============================================================================}
+
+function GetMailServers(const DNSHost, Domain: AnsiString;
+ const Servers: TStrings): Boolean;
+var
+ DNS: TDNSSend;
+ t: TStringList;
+ n, m, x: Integer;
+begin
+ Result := False;
+ Servers.Clear;
+ t := TStringList.Create;
+ DNS := TDNSSend.Create;
+ try
+ DNS.TargetHost := DNSHost;
+ if DNS.DNSQuery(Domain, QType_MX, t) then
+ begin
+ { normalize preference number to 5 digits }
+ for n := 0 to t.Count - 1 do
+ begin
+ x := Pos(',', t[n]);
+ if x > 0 then
+ for m := 1 to 6 - x do
+ t[n] := '0' + t[n];
+ end;
+ { sort server list }
+ t.Sorted := True;
+ { result is sorted list without preference numbers }
+ for n := 0 to t.Count - 1 do
+ begin
+ x := Pos(',', t[n]);
+ Servers.Add(Copy(t[n], x + 1, Length(t[n]) - x));
+ end;
+ Result := True;
+ end;
+ finally
+ DNS.Free;
+ t.Free;
+ end;
+end;
+
+end.
diff --git a/branches/script-component/Units/Synapse/ftpsend.pas b/branches/script-component/Units/Synapse/ftpsend.pas
new file mode 100644
index 0000000..49b2a00
--- /dev/null
+++ b/branches/script-component/Units/Synapse/ftpsend.pas
@@ -0,0 +1,1943 @@
+{==============================================================================|
+| Project : Ararat Synapse | 003.005.001 |
+|==============================================================================|
+| Content: FTP client |
+|==============================================================================|
+| Copyright (c)1999-2008, Lukas Gebauer |
+| All rights reserved. |
+| |
+| Redistribution and use in source and binary forms, with or without |
+| modification, are permitted provided that the following conditions are met: |
+| |
+| Redistributions of source code must retain the above copyright notice, this |
+| list of conditions and the following disclaimer. |
+| |
+| Redistributions in binary form must reproduce the above copyright notice, |
+| this list of conditions and the following disclaimer in the documentation |
+| and/or other materials provided with the distribution. |
+| |
+| Neither the name of Lukas Gebauer nor the names of its contributors may |
+| be used to endorse or promote products derived from this software without |
+| specific prior written permission. |
+| |
+| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
+| AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
+| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
+| ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR |
+| ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
+| DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
+| SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
+| CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
+| LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
+| OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
+| DAMAGE. |
+|==============================================================================|
+| The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).|
+| Portions created by Lukas Gebauer are Copyright (c) 1999-2008. |
+| All Rights Reserved. |
+|==============================================================================|
+| Contributor(s): |
+| Petr Esner |
+|==============================================================================|
+| History: see HISTORY.HTM from distribution package |
+| (Found at URL: http://www.ararat.cz/synapse/) |
+|==============================================================================}
+
+{: @abstract(FTP client protocol)
+
+Used RFC: RFC-959, RFC-2228, RFC-2428
+}
+
+{$IFDEF FPC}
+ {$MODE DELPHI}
+{$ENDIF}
+{$H+}
+
+unit ftpsend;
+
+interface
+
+uses
+ SysUtils, Classes,
+ blcksock, synautil, synaip, synsock;
+
+const
+ cFtpProtocol = '21';
+ cFtpDataProtocol = '20';
+
+ {:Terminating value for TLogonActions}
+ FTP_OK = 255;
+ {:Terminating value for TLogonActions}
+ FTP_ERR = 254;
+
+type
+ {:Array for holding definition of logon sequence.}
+ TLogonActions = array [0..17] of byte;
+
+ {:Procedural type for OnStatus event. Sender is calling @link(TFTPSend) object.
+ Value is FTP command or reply to this comand. (if it is reply, Response
+ is @True).}
+ TFTPStatus = procedure(Sender: TObject; Response: Boolean;
+ const Value: string) of object;
+
+ {: @abstract(Object for holding file information) parsed from directory
+ listing of FTP server.}
+ TFTPListRec = class(TObject)
+ private
+ FFileName: string;
+ FDirectory: Boolean;
+ FReadable: Boolean;
+ FFileSize: Longint;
+ FFileTime: TDateTime;
+ FOriginalLine: string;
+ FMask: string;
+ FPermission: string;
+ public
+ {: You can assign another TFTPListRec to this object.}
+ procedure Assign(Value: TFTPListRec); virtual;
+ published
+ {:name of file}
+ property FileName: string read FFileName write FFileName;
+ {:if name is subdirectory not file.}
+ property Directory: Boolean read FDirectory write FDirectory;
+ {:if you have rights to read}
+ property Readable: Boolean read FReadable write FReadable;
+ {:size of file in bytes}
+ property FileSize: Longint read FFileSize write FFileSize;
+ {:date and time of file. Local server timezone is used. Any timezone
+ conversions was not done!}
+ property FileTime: TDateTime read FFileTime write FFileTime;
+ {:original unparsed line}
+ property OriginalLine: string read FOriginalLine write FOriginalLine;
+ {:mask what was used for parsing}
+ property Mask: string read FMask write FMask;
+ {:permission string (depending on used mask!)}
+ property Permission: string read FPermission write FPermission;
+ end;
+
+ {:@abstract(This is TList of TFTPListRec objects.)
+ This object is used for holding lististing of all files information in listed
+ directory on FTP server.}
+ TFTPList = class(TObject)
+ protected
+ FList: TList;
+ FLines: TStringList;
+ FMasks: TStringList;
+ FUnparsedLines: TStringList;
+ Monthnames: string;
+ BlockSize: string;
+ DirFlagValue: string;
+ FileName: string;
+ VMSFileName: string;
+ Day: string;
+ Month: string;
+ ThreeMonth: string;
+ YearTime: string;
+ Year: string;
+ Hours: string;
+ HoursModif: string;
+ Minutes: string;
+ Seconds: string;
+ Size: string;
+ Permissions: string;
+ DirFlag: string;
+ function GetListItem(Index: integer): TFTPListRec; virtual;
+ function ParseEPLF(Value: string): Boolean; virtual;
+ procedure ClearStore; virtual;
+ function ParseByMask(Value, NextValue, Mask: string): Integer; virtual;
+ function CheckValues: Boolean; virtual;
+ procedure FillRecord(const Value: TFTPListRec); virtual;
+ public
+ {:Constructor. You not need create this object, it is created by TFTPSend
+ class as their property.}
+ constructor Create;
+ destructor Destroy; override;
+
+ {:Clear list.}
+ procedure Clear; virtual;
+
+ {:count of holded @link(TFTPListRec) objects}
+ function Count: integer; virtual;
+
+ {:Assigns one list to another}
+ procedure Assign(Value: TFTPList); virtual;
+
+ {:try to parse raw directory listing in @link(lines) to list of
+ @link(TFTPListRec).}
+ procedure ParseLines; virtual;
+
+ {:By this property you have access to list of @link(TFTPListRec).
+ This is for compatibility only. Please, use @link(Items) instead.}
+ property List: TList read FList;
+
+ {:By this property you have access to list of @link(TFTPListRec).}
+ property Items[Index: Integer]: TFTPListRec read GetListItem; default;
+
+ {:Set of lines with RAW directory listing for @link(parseLines)}
+ property Lines: TStringList read FLines;
+
+ {:Set of masks for directory listing parser. It is predefined by default,
+ however you can modify it as you need. (for example, you can add your own
+ definition mask.) Mask is same as mask used in TotalCommander.}
+ property Masks: TStringList read FMasks;
+
+ {:After @link(ParseLines) it holding lines what was not sucessfully parsed.}
+ property UnparsedLines: TStringList read FUnparsedLines;
+ end;
+
+ {:@abstract(Implementation of FTP protocol.)
+ Note: Are you missing properties for setting Username and Password? Look to
+ parent @link(TSynaClient) object! (Username and Password have default values
+ for "anonymous" FTP login)
+
+ Are you missing properties for specify server address and port? Look to
+ parent @link(TSynaClient) too!}
+ TFTPSend = class(TSynaClient)
+ protected
+ FOnStatus: TFTPStatus;
+ FSock: TTCPBlockSocket;
+ FDSock: TTCPBlockSocket;
+ FResultCode: Integer;
+ FResultString: string;
+ FFullResult: TStringList;
+ FAccount: string;
+ FFWHost: string;
+ FFWPort: string;
+ FFWUsername: string;
+ FFWPassword: string;
+ FFWMode: integer;
+ FDataStream: TMemoryStream;
+ FDataIP: string;
+ FDataPort: string;
+ FDirectFile: Boolean;
+ FDirectFileName: string;
+ FCanResume: Boolean;
+ FPassiveMode: Boolean;
+ FForceDefaultPort: Boolean;
+ FForceOldPort: Boolean;
+ FFtpList: TFTPList;
+ FBinaryMode: Boolean;
+ FAutoTLS: Boolean;
+ FIsTLS: Boolean;
+ FIsDataTLS: Boolean;
+ FTLSonData: Boolean;
+ FFullSSL: Boolean;
+ function Auth(Mode: integer): Boolean; virtual;
+ function Connect: Boolean; virtual;
+ function InternalStor(const Command: string; RestoreAt: integer): Boolean; virtual;
+ function DataSocket: Boolean; virtual;
+ function AcceptDataSocket: Boolean; virtual;
+ procedure DoStatus(Response: Boolean; const Value: string); virtual;
+ public
+ {:Custom definition of login sequence. You can use this when you set
+ @link(FWMode) to value -1.}
+ CustomLogon: TLogonActions;
+
+ constructor Create;
+ destructor Destroy; override;
+
+ {:Waits and read FTP server response. You need this only in special cases!}
+ function ReadResult: Integer; virtual;
+
+ {:Parse remote side information of data channel from value string (returned
+ by PASV command). This function you need only in special cases!}
+ procedure ParseRemote(Value: string); virtual;
+
+ {:Parse remote side information of data channel from value string (returned
+ by EPSV command). This function you need only in special cases!}
+ procedure ParseRemoteEPSV(Value: string); virtual;
+
+ {:Send Value as FTP command to FTP server. Returned result code is result of
+ this function.
+ This command is good for sending site specific command, or non-standard
+ commands.}
+ function FTPCommand(const Value: string): integer; virtual;
+
+ {:Connect and logon to FTP server. If you specify any FireWall, connect to
+ firewall and throw them connect to FTP server. Login sequence depending on
+ @link(FWMode).}
+ function Login: Boolean; virtual;
+
+ {:Logoff and disconnect from FTP server.}
+ function Logout: Boolean; virtual;
+
+ {:Break current transmission of data. (You can call this method from
+ Sock.OnStatus event, or from another thread.)}
+ procedure Abort; virtual;
+
+ {:Break current transmission of data. It is same as Abort, but it send abort
+ telnet commands prior ABOR FTP command. Some servers need it. (You can call
+ this method from Sock.OnStatus event, or from another thread.)}
+ procedure TelnetAbort; virtual;
+
+ {:Download directory listing of Directory on FTP server. If Directory is
+ empty string, download listing of current working directory.
+ If NameList is @true, download only names of files in directory.
+ (internally use NLST command instead LIST command)
+ If NameList is @false, returned list is also parsed to @link(FTPList)
+ property.}
+ function List(Directory: string; NameList: Boolean): Boolean; virtual;
+
+ {:Read data from FileName on FTP server. If Restore is @true and server
+ supports resume dowloads, download is resumed. (received is only rest
+ of file)}
+ function RetrieveFile(const FileName: string; Restore: Boolean): Boolean; virtual;
+
+ {:Send data to FileName on FTP server. If Restore is @true and server
+ supports resume upload, upload is resumed. (send only rest of file)
+ In this case if remote file is same length as local file, nothing will be
+ done. If remote file is larger then local, resume is disabled and file is
+ transfered from begin!}
+ function StoreFile(const FileName: string; Restore: Boolean): Boolean; virtual;
+
+ {:Send data to FTP server and assing unique name for this file.}
+ function StoreUniqueFile: Boolean; virtual;
+
+ {:Append data to FileName on FTP server.}
+ function AppendFile(const FileName: string): Boolean; virtual;
+
+ {:Rename on FTP server file with OldName to NewName.}
+ function RenameFile(const OldName, NewName: string): Boolean; virtual;
+
+ {:Delete file FileName on FTP server.}
+ function DeleteFile(const FileName: string): Boolean; virtual;
+
+ {:Return size of Filename file on FTP server. If command failed (i.e. not
+ implemented), return -1.}
+ function FileSize(const FileName: string): integer; virtual;
+
+ {:Send NOOP command to FTP server for preserve of disconnect by inactivity
+ timeout.}
+ function NoOp: Boolean; virtual;
+
+ {:Change currect working directory to Directory on FTP server.}
+ function ChangeWorkingDir(const Directory: string): Boolean; virtual;
+
+ {:walk to upper directory on FTP server.}
+ function ChangeToParentDir: Boolean; virtual;
+
+ {:walk to root directory on FTP server. (May not work with all servers properly!)}
+ function ChangeToRootDir: Boolean; virtual;
+
+ {:Delete Directory on FTP server.}
+ function DeleteDir(const Directory: string): Boolean; virtual;
+
+ {:Create Directory on FTP server.}
+ function CreateDir(const Directory: string): Boolean; virtual;
+
+ {:Return current working directory on FTP server.}
+ function GetCurrentDir: String; virtual;
+
+ {:Establish data channel to FTP server and retrieve data.
+ This function you need only in special cases, i.e. when you need to implement
+ some special unsupported FTP command!}
+ function DataRead(const DestStream: TStream): Boolean; virtual;
+
+ {:Establish data channel to FTP server and send data.
+ This function you need only in special cases, i.e. when you need to implement
+ some special unsupported FTP command.}
+ function DataWrite(const SourceStream: TStream): Boolean; virtual;
+ published
+ {:After FTP command contains result number of this operation.}
+ property ResultCode: Integer read FResultCode;
+
+ {:After FTP command contains main line of result.}
+ property ResultString: string read FResultString;
+
+ {:After any FTP command it contains all lines of FTP server reply.}
+ property FullResult: TStringList read FFullResult;
+
+ {:Account information used in some cases inside login sequence.}
+ property Account: string read FAccount Write FAccount;
+
+ {:Address of firewall. If empty string (default), firewall not used.}
+ property FWHost: string read FFWHost Write FFWHost;
+
+ {:port of firewall. standard value is same port as ftp server used. (21)}
+ property FWPort: string read FFWPort Write FFWPort;
+
+ {:Username for login to firewall. (if needed)}
+ property FWUsername: string read FFWUsername Write FFWUsername;
+
+ {:password for login to firewall. (if needed)}
+ property FWPassword: string read FFWPassword Write FFWPassword;
+
+ {:Type of Firewall. Used only if you set some firewall address. Supported
+ predefined firewall login sequences are described by comments in source
+ file where you can see pseudocode decribing each sequence.}
+ property FWMode: integer read FFWMode Write FFWMode;
+
+ {:Socket object used for TCP/IP operation on control channel. Good for
+ seting OnStatus hook, etc.}
+ property Sock: TTCPBlockSocket read FSock;
+
+ {:Socket object used for TCP/IP operation on data channel. Good for seting
+ OnStatus hook, etc.}
+ property DSock: TTCPBlockSocket read FDSock;
+
+ {:If you not use @link(DirectFile) mode, all data transfers is made to or
+ from this stream.}
+ property DataStream: TMemoryStream read FDataStream;
+
+ {:After data connection is established, contains remote side IP of this
+ connection.}
+ property DataIP: string read FDataIP;
+
+ {:After data connection is established, contains remote side port of this
+ connection.}
+ property DataPort: string read FDataPort;
+
+ {:Mode of data handling by data connection. If @False, all data operations
+ are made to or from @link(DataStream) TMemoryStream.
+ If @true, data operations is made directly to file in your disk. (filename
+ is specified by @link(DirectFileName) property.) Dafault is @False!}
+ property DirectFile: Boolean read FDirectFile Write FDirectFile;
+
+ {:Filename for direct disk data operations.}
+ property DirectFileName: string read FDirectFileName Write FDirectFileName;
+
+ {:Indicate after @link(Login) if remote server support resume downloads and
+ uploads.}
+ property CanResume: Boolean read FCanResume;
+
+ {:If true (default value), all transfers is made by passive method.
+ It is safer method for various firewalls.}
+ property PassiveMode: Boolean read FPassiveMode Write FPassiveMode;
+
+ {:Force to listen for dataconnection on standard port (20). Default is @false,
+ dataconnections will be made to any non-standard port reported by PORT FTP
+ command. This setting is not used, if you use passive mode.}
+ property ForceDefaultPort: Boolean read FForceDefaultPort Write FForceDefaultPort;
+
+ {:When is @true, then is disabled EPSV and EPRT support. However without this
+ commands you cannot use IPv6! (Disabling of this commands is needed only
+ when you are behind some crap firewall/NAT.}
+ property ForceOldPort: Boolean read FForceOldPort Write FForceOldPort;
+
+ {:You may set this hook for monitoring FTP commands and replies.}
+ property OnStatus: TFTPStatus read FOnStatus write FOnStatus;
+
+ {:After LIST command is here parsed list of files in given directory.}
+ property FtpList: TFTPList read FFtpList;
+
+ {:if @true (default), then data transfers is in binary mode. If this is set
+ to @false, then ASCII mode is used.}
+ property BinaryMode: Boolean read FBinaryMode Write FBinaryMode;
+
+ {:if is true, then if server support upgrade to SSL/TLS mode, then use them.}
+ property AutoTLS: Boolean read FAutoTLS Write FAutoTLS;
+
+ {:if server listen on SSL/TLS port, then you set this to true.}
+ property FullSSL: Boolean read FFullSSL Write FFullSSL;
+
+ {:Signalise, if control channel is in SSL/TLS mode.}
+ property IsTLS: Boolean read FIsTLS;
+
+ {:Signalise, if data transfers is in SSL/TLS mode.}
+ property IsDataTLS: Boolean read FIsDataTLS;
+
+ {:If @true (default), then try to use SSL/TLS on data transfers too.
+ If @false, then SSL/TLS is used only for control connection.}
+ property TLSonData: Boolean read FTLSonData write FTLSonData;
+ end;
+
+{:A very useful function, and example of use can be found in the TFtpSend object.
+ Dowload specified file from FTP server to LocalFile.}
+function FtpGetFile(const IP, Port, FileName, LocalFile,
+ User, Pass: string): Boolean;
+
+{:A very useful function, and example of use can be found in the TFtpSend object.
+ Upload specified LocalFile to FTP server.}
+function FtpPutFile(const IP, Port, FileName, LocalFile,
+ User, Pass: string): Boolean;
+
+{:A very useful function, and example of use can be found in the TFtpSend object.
+ Initiate transfer of file between two FTP servers.}
+function FtpInterServerTransfer(
+ const FromIP, FromPort, FromFile, FromUser, FromPass: string;
+ const ToIP, ToPort, ToFile, ToUser, ToPass: string): Boolean;
+
+implementation
+
+constructor TFTPSend.Create;
+begin
+ inherited Create;
+ FFullResult := TStringList.Create;
+ FDataStream := TMemoryStream.Create;
+ FSock := TTCPBlockSocket.Create;
+ FSock.ConvertLineEnd := True;
+ FDSock := TTCPBlockSocket.Create;
+ FFtpList := TFTPList.Create;
+ FTimeout := 300000;
+ FTargetPort := cFtpProtocol;
+ FUsername := 'anonymous';
+ FPassword := 'anonymous@' + FSock.LocalName;
+ FDirectFile := False;
+ FPassiveMode := True;
+ FForceDefaultPort := False;
+ FForceOldPort := false;
+ FAccount := '';
+ FFWHost := '';
+ FFWPort := cFtpProtocol;
+ FFWUsername := '';
+ FFWPassword := '';
+ FFWMode := 0;
+ FBinaryMode := True;
+ FAutoTLS := False;
+ FFullSSL := False;
+ FIsTLS := False;
+ FIsDataTLS := False;
+ FTLSonData := True;
+end;
+
+destructor TFTPSend.Destroy;
+begin
+ FDSock.Free;
+ FSock.Free;
+ FFTPList.Free;
+ FDataStream.Free;
+ FFullResult.Free;
+ inherited Destroy;
+end;
+
+procedure TFTPSend.DoStatus(Response: Boolean; const Value: string);
+begin
+ if assigned(OnStatus) then
+ OnStatus(Self, Response, Value);
+end;
+
+function TFTPSend.ReadResult: Integer;
+var
+ s, c: string;
+begin
+ FFullResult.Clear;
+ c := '';
+ repeat
+ s := FSock.RecvString(FTimeout);
+ if c = '' then
+ if length(s) > 3 then
+ if s[4] in [' ', '-'] then
+ c :=Copy(s, 1, 3);
+ FResultString := s;
+ FFullResult.Add(s);
+ DoStatus(True, s);
+ if FSock.LastError <> 0 then
+ Break;
+ until (c <> '') and (Pos(c + ' ', s) = 1);
+ Result := StrToIntDef(c, 0);
+ FResultCode := Result;
+end;
+
+function TFTPSend.FTPCommand(const Value: string): integer;
+begin
+ FSock.Purge;
+ FSock.SendString(Value + CRLF);
+ DoStatus(False, Value);
+ Result := ReadResult;
+end;
+
+// based on idea by Petr Esner
+function TFTPSend.Auth(Mode: integer): Boolean;
+const
+ //if not USER then
+ // if not PASS then
+ // if not ACCT then ERROR!
+ //OK!
+ Action0: TLogonActions =
+ (0, FTP_OK, 3,
+ 1, FTP_OK, 6,
+ 2, FTP_OK, FTP_ERR,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0);
+
+ //if not USER then
+ // if not PASS then ERROR!
+ //if SITE then ERROR!
+ //if not USER then
+ // if not PASS then
+ // if not ACCT then ERROR!
+ //OK!
+ Action1: TLogonActions =
+ (3, 6, 3,
+ 4, 6, FTP_ERR,
+ 5, FTP_ERR, 9,
+ 0, FTP_OK, 12,
+ 1, FTP_OK, 15,
+ 2, FTP_OK, FTP_ERR);
+
+ //if not USER then
+ // if not PASS then ERROR!
+ //if USER '@' then OK!
+ //if not PASS then
+ // if not ACCT then ERROR!
+ //OK!
+ Action2: TLogonActions =
+ (3, 6, 3,
+ 4, 6, FTP_ERR,
+ 6, FTP_OK, 9,
+ 1, FTP_OK, 12,
+ 2, FTP_OK, FTP_ERR,
+ 0, 0, 0);
+
+ //if not USER then
+ // if not PASS then ERROR!
+ //if not USER then
+ // if not PASS then
+ // if not ACCT then ERROR!
+ //OK!
+ Action3: TLogonActions =
+ (3, 6, 3,
+ 4, 6, FTP_ERR,
+ 0, FTP_OK, 9,
+ 1, FTP_OK, 12,
+ 2, FTP_OK, FTP_ERR,
+ 0, 0, 0);
+
+ //OPEN
+ //if not USER then
+ // if not PASS then
+ // if not ACCT then ERROR!
+ //OK!
+ Action4: TLogonActions =
+ (7, 3, 3,
+ 0, FTP_OK, 6,
+ 1, FTP_OK, 9,
+ 2, FTP_OK, FTP_ERR,
+ 0, 0, 0, 0, 0, 0);
+
+ //if USER '@' then OK!
+ //if not PASS then
+ // if not ACCT then ERROR!
+ //OK!
+ Action5: TLogonActions =
+ (6, FTP_OK, 3,
+ 1, FTP_OK, 6,
+ 2, FTP_OK, FTP_ERR,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0);
+
+ //if not USER @ then
+ // if not PASS then ERROR!
+ //if not USER then
+ // if not PASS then
+ // if not ACCT then ERROR!
+ //OK!
+ Action6: TLogonActions =
+ (8, 6, 3,
+ 4, 6, FTP_ERR,
+ 0, FTP_OK, 9,
+ 1, FTP_OK, 12,
+ 2, FTP_OK, FTP_ERR,
+ 0, 0, 0);
+
+ //if USER @ then ERROR!
+ //if not PASS then
+ // if not ACCT then ERROR!
+ //OK!
+ Action7: TLogonActions =
+ (9, FTP_ERR, 3,
+ 1, FTP_OK, 6,
+ 2, FTP_OK, FTP_ERR,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0);
+
+ //if not USER @@ then
+ // if not PASS @ then
+ // if not ACCT then ERROR!
+ //OK!
+ Action8: TLogonActions =
+ (10, FTP_OK, 3,
+ 11, FTP_OK, 6,
+ 2, FTP_OK, FTP_ERR,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0);
+var
+ FTPServer: string;
+ LogonActions: TLogonActions;
+ i: integer;
+ s: string;
+ x: integer;
+begin
+ Result := False;
+ if FFWHost = '' then
+ Mode := 0;
+ if (FTargetPort = cFtpProtocol) or (FTargetPort = '21') then
+ FTPServer := FTargetHost
+ else
+ FTPServer := FTargetHost + ':' + FTargetPort;
+ case Mode of
+ -1:
+ LogonActions := CustomLogon;
+ 1:
+ LogonActions := Action1;
+ 2:
+ LogonActions := Action2;
+ 3:
+ LogonActions := Action3;
+ 4:
+ LogonActions := Action4;
+ 5:
+ LogonActions := Action5;
+ 6:
+ LogonActions := Action6;
+ 7:
+ LogonActions := Action7;
+ 8:
+ LogonActions := Action8;
+ else
+ LogonActions := Action0;
+ end;
+ i := 0;
+ repeat
+ case LogonActions[i] of
+ 0: s := 'USER ' + FUserName;
+ 1: s := 'PASS ' + FPassword;
+ 2: s := 'ACCT ' + FAccount;
+ 3: s := 'USER ' + FFWUserName;
+ 4: s := 'PASS ' + FFWPassword;
+ 5: s := 'SITE ' + FTPServer;
+ 6: s := 'USER ' + FUserName + '@' + FTPServer;
+ 7: s := 'OPEN ' + FTPServer;
+ 8: s := 'USER ' + FFWUserName + '@' + FTPServer;
+ 9: s := 'USER ' + FUserName + '@' + FTPServer + ' ' + FFWUserName;
+ 10: s := 'USER ' + FUserName + '@' + FFWUserName + '@' + FTPServer;
+ 11: s := 'PASS ' + FPassword + '@' + FFWPassword;
+ end;
+ x := FTPCommand(s);
+ x := x div 100;
+ if (x <> 2) and (x <> 3) then
+ Exit;
+ i := LogonActions[i + x - 1];
+ case i of
+ FTP_ERR:
+ Exit;
+ FTP_OK:
+ begin
+ Result := True;
+ Exit;
+ end;
+ end;
+ until False;
+end;
+
+
+function TFTPSend.Connect: Boolean;
+begin
+ FSock.CloseSocket;
+ FSock.Bind(FIPInterface, cAnyPort);
+ if FSock.LastError = 0 then
+ if FFWHost = '' then
+ FSock.Connect(FTargetHost, FTargetPort)
+ else
+ FSock.Connect(FFWHost, FFWPort);
+ if FSock.LastError = 0 then
+ if FFullSSL then
+ FSock.SSLDoConnect;
+ Result := FSock.LastError = 0;
+end;
+
+function TFTPSend.Login: Boolean;
+var
+ x: integer;
+begin
+ Result := False;
+ FCanResume := False;
+ if not Connect then
+ Exit;
+ FIsTLS := FFullSSL;
+ FIsDataTLS := False;
+ repeat
+ x := ReadResult div 100;
+ until x <> 1;
+ if x <> 2 then
+ Exit;
+ if FAutoTLS and not(FIsTLS) then
+ if (FTPCommand('AUTH TLS') div 100) = 2 then
+ begin
+ FSock.SSLDoConnect;
+ FIsTLS := FSock.LastError = 0;
+ if not FIsTLS then
+ begin
+ Result := False;
+ Exit;
+ end;
+ end;
+ if not Auth(FFWMode) then
+ Exit;
+ if FIsTLS then
+ begin
+ FTPCommand('PBSZ 0');
+ if FTLSonData then
+ FIsDataTLS := (FTPCommand('PROT P') div 100) = 2;
+ if not FIsDataTLS then
+ FTPCommand('PROT C');
+ end;
+ FTPCommand('TYPE I');
+ FTPCommand('STRU F');
+ FTPCommand('MODE S');
+ if FTPCommand('REST 0') = 350 then
+ if FTPCommand('REST 1') = 350 then
+ begin
+ FTPCommand('REST 0');
+ FCanResume := True;
+ end;
+ Result := True;
+end;
+
+function TFTPSend.Logout: Boolean;
+begin
+ Result := (FTPCommand('QUIT') div 100) = 2;
+ FSock.CloseSocket;
+end;
+
+procedure TFTPSend.ParseRemote(Value: string);
+var
+ n: integer;
+ nb, ne: integer;
+ s: string;
+ x: integer;
+begin
+ Value := trim(Value);
+ nb := Pos('(',Value);
+ ne := Pos(')',Value);
+ if (nb = 0) or (ne = 0) then
+ begin
+ nb:=RPos(' ',Value);
+ s:=Copy(Value, nb + 1, Length(Value) - nb);
+ end
+ else
+ begin
+ s:=Copy(Value,nb+1,ne-nb-1);
+ end;
+ for n := 1 to 4 do
+ if n = 1 then
+ FDataIP := Fetch(s, ',')
+ else
+ FDataIP := FDataIP + '.' + Fetch(s, ',');
+ x := StrToIntDef(Fetch(s, ','), 0) * 256;
+ x := x + StrToIntDef(Fetch(s, ','), 0);
+ FDataPort := IntToStr(x);
+end;
+
+procedure TFTPSend.ParseRemoteEPSV(Value: string);
+var
+ n: integer;
+ s, v: string;
+begin
+ s := SeparateRight(Value, '(');
+ s := Trim(SeparateLeft(s, ')'));
+ Delete(s, Length(s), 1);
+ v := '';
+ for n := Length(s) downto 1 do
+ if s[n] in ['0'..'9'] then
+ v := s[n] + v
+ else
+ Break;
+ FDataPort := v;
+ FDataIP := FTargetHost;
+end;
+
+function TFTPSend.DataSocket: boolean;
+var
+ s: string;
+begin
+ Result := False;
+ if FIsDataTLS then
+ FPassiveMode := True;
+ if FPassiveMode then
+ begin
+ if FSock.IP6used then
+ s := '2'
+ else
+ s := '1';
+ if not(FForceOldPort) and ((FTPCommand('EPSV ' + s) div 100) = 2) then
+ begin
+ ParseRemoteEPSV(FResultString);
+ end
+ else
+ if FSock.IP6used then
+ Exit
+ else
+ begin
+ if (FTPCommand('PASV') div 100) <> 2 then
+ Exit;
+ ParseRemote(FResultString);
+ end;
+ FDSock.CloseSocket;
+ FDSock.Bind(FIPInterface, cAnyPort);
+ FDSock.Connect(FDataIP, FDataPort);
+ Result := FDSock.LastError = 0;
+ end
+ else
+ begin
+ FDSock.CloseSocket;
+ if FForceDefaultPort then
+ s := cFtpDataProtocol
+ else
+ s := '0';
+ //data conection from same interface as command connection
+ FDSock.Bind(FSock.GetLocalSinIP, s);
+ if FDSock.LastError <> 0 then
+ Exit;
+ FDSock.SetLinger(True, 10000);
+ FDSock.Listen;
+ FDSock.GetSins;
+ FDataIP := FDSock.GetLocalSinIP;
+ FDataIP := FDSock.ResolveName(FDataIP);
+ FDataPort := IntToStr(FDSock.GetLocalSinPort);
+ if not FForceOldPort then
+ begin
+ if IsIp6(FDataIP) then
+ s := '2'
+ else
+ s := '1';
+ s := 'EPRT |' + s +'|' + FDataIP + '|' + FDataPort + '|';
+ Result := (FTPCommand(s) div 100) = 2;
+ end;
+ if not Result and IsIP(FDataIP) then
+ begin
+ s := ReplaceString(FDataIP, '.', ',');
+ s := 'PORT ' + s + ',' + IntToStr(FDSock.GetLocalSinPort div 256)
+ + ',' + IntToStr(FDSock.GetLocalSinPort mod 256);
+ Result := (FTPCommand(s) div 100) = 2;
+ end;
+ end;
+end;
+
+function TFTPSend.AcceptDataSocket: Boolean;
+var
+ x: TSocket;
+begin
+ if FPassiveMode then
+ Result := True
+ else
+ begin
+ Result := False;
+ if FDSock.CanRead(FTimeout) then
+ begin
+ x := FDSock.Accept;
+ if not FDSock.UsingSocks then
+ FDSock.CloseSocket;
+ FDSock.Socket := x;
+ Result := True;
+ end;
+ end;
+ if Result and FIsDataTLS then
+ begin
+ FDSock.SSL.Assign(FSock.SSL);
+ FDSock.SSLDoConnect;
+ Result := FDSock.LastError = 0;
+ end;
+end;
+
+function TFTPSend.DataRead(const DestStream: TStream): Boolean;
+var
+ x: integer;
+begin
+ Result := False;
+ try
+ if not AcceptDataSocket then
+ Exit;
+ FDSock.RecvStreamRaw(DestStream, FTimeout);
+ FDSock.CloseSocket;
+ x := ReadResult;
+ Result := (x div 100) = 2;
+ finally
+ FDSock.CloseSocket;
+ end;
+end;
+
+function TFTPSend.DataWrite(const SourceStream: TStream): Boolean;
+var
+ x: integer;
+ b: Boolean;
+begin
+ Result := False;
+ try
+ if not AcceptDataSocket then
+ Exit;
+ FDSock.SendStreamRaw(SourceStream);
+ b := FDSock.LastError = 0;
+ FDSock.CloseSocket;
+ x := ReadResult;
+ Result := b and ((x div 100) = 2);
+ finally
+ FDSock.CloseSocket;
+ end;
+end;
+
+function TFTPSend.List(Directory: string; NameList: Boolean): Boolean;
+var
+ x: integer;
+begin
+ Result := False;
+ FDataStream.Clear;
+ FFTPList.Clear;
+ if Directory <> '' then
+ Directory := ' ' + Directory;
+ FTPCommand('TYPE A');
+ if not DataSocket then
+ Exit;
+ if NameList then
+ x := FTPCommand('NLST' + Directory)
+ else
+ x := FTPCommand('LIST' + Directory);
+ if (x div 100) <> 1 then
+ Exit;
+ Result := DataRead(FDataStream);
+ if (not NameList) and Result then
+ begin
+ FDataStream.Position := 0;
+ FFTPList.Lines.LoadFromStream(FDataStream);
+ FFTPList.ParseLines;
+ end;
+ FDataStream.Position := 0;
+end;
+
+function TFTPSend.RetrieveFile(const FileName: string; Restore: Boolean): Boolean;
+var
+ RetrStream: TStream;
+begin
+ Result := False;
+ if FileName = '' then
+ Exit;
+ if not DataSocket then
+ Exit;
+ Restore := Restore and FCanResume;
+ if FDirectFile then
+ if Restore and FileExists(FDirectFileName) then
+ RetrStream := TFileStream.Create(FDirectFileName,
+ fmOpenReadWrite or fmShareExclusive)
+ else
+ RetrStream := TFileStream.Create(FDirectFileName,
+ fmCreate or fmShareDenyWrite)
+ else
+ RetrStream := FDataStream;
+ try
+ if FBinaryMode then
+ FTPCommand('TYPE I')
+ else
+ FTPCommand('TYPE A');
+ if Restore then
+ begin
+ RetrStream.Position := RetrStream.Size;
+ if (FTPCommand('REST ' + IntToStr(RetrStream.Size)) div 100) <> 3 then
+ Exit;
+ end
+ else
+ if RetrStream is TMemoryStream then
+ TMemoryStream(RetrStream).Clear;
+ if (FTPCommand('RETR ' + FileName) div 100) <> 1 then
+ Exit;
+ Result := DataRead(RetrStream);
+ if not FDirectFile then
+ RetrStream.Position := 0;
+ finally
+ if FDirectFile then
+ RetrStream.Free;
+ end;
+end;
+
+function TFTPSend.InternalStor(const Command: string; RestoreAt: integer): Boolean;
+var
+ SendStream: TStream;
+ StorSize: integer;
+begin
+ Result := False;
+ if FDirectFile then
+ if not FileExists(FDirectFileName) then
+ Exit
+ else
+ SendStream := TFileStream.Create(FDirectFileName,
+ fmOpenRead or fmShareDenyWrite)
+ else
+ SendStream := FDataStream;
+ try
+ if not DataSocket then
+ Exit;
+ if FBinaryMode then
+ FTPCommand('TYPE I')
+ else
+ FTPCommand('TYPE A');
+ StorSize := SendStream.Size;
+ if not FCanResume then
+ RestoreAt := 0;
+ if (StorSize > 0) and (RestoreAt = StorSize) then
+ begin
+ Result := True;
+ Exit;
+ end;
+ if RestoreAt > StorSize then
+ RestoreAt := 0;
+ FTPCommand('ALLO ' + IntToStr(StorSize - RestoreAt));
+ if FCanResume then
+ if (FTPCommand('REST ' + IntToStr(RestoreAt)) div 100) <> 3 then
+ Exit;
+ SendStream.Position := RestoreAt;
+ if (FTPCommand(Command) div 100) <> 1 then
+ Exit;
+ Result := DataWrite(SendStream);
+ finally
+ if FDirectFile then
+ SendStream.Free;
+ end;
+end;
+
+function TFTPSend.StoreFile(const FileName: string; Restore: Boolean): Boolean;
+var
+ RestoreAt: integer;
+begin
+ Result := False;
+ if FileName = '' then
+ Exit;
+ RestoreAt := 0;
+ Restore := Restore and FCanResume;
+ if Restore then
+ begin
+ RestoreAt := Self.FileSize(FileName);
+ if RestoreAt < 0 then
+ RestoreAt := 0;
+ end;
+ Result := InternalStor('STOR ' + FileName, RestoreAt);
+end;
+
+function TFTPSend.StoreUniqueFile: Boolean;
+begin
+ Result := InternalStor('STOU', 0);
+end;
+
+function TFTPSend.AppendFile(const FileName: string): Boolean;
+begin
+ Result := False;
+ if FileName = '' then
+ Exit;
+ Result := InternalStor('APPE '+FileName, 0);
+end;
+
+function TFTPSend.NoOp: Boolean;
+begin
+ Result := (FTPCommand('NOOP') div 100) = 2;
+end;
+
+function TFTPSend.RenameFile(const OldName, NewName: string): Boolean;
+begin
+ Result := False;
+ if (FTPCommand('RNFR ' + OldName) div 100) <> 3 then
+ Exit;
+ Result := (FTPCommand('RNTO ' + NewName) div 100) = 2;
+end;
+
+function TFTPSend.DeleteFile(const FileName: string): Boolean;
+begin
+ Result := (FTPCommand('DELE ' + FileName) div 100) = 2;
+end;
+
+function TFTPSend.FileSize(const FileName: string): integer;
+var
+ s: string;
+begin
+ Result := -1;
+ if (FTPCommand('SIZE ' + FileName) div 100) = 2 then
+ begin
+ s := Trim(SeparateRight(ResultString, ' '));
+ s := Trim(SeparateLeft(s, ' '));
+ Result := StrToIntDef(s, -1);
+ end;
+end;
+
+function TFTPSend.ChangeWorkingDir(const Directory: string): Boolean;
+begin
+ Result := (FTPCommand('CWD ' + Directory) div 100) = 2;
+end;
+
+function TFTPSend.ChangeToParentDir: Boolean;
+begin
+ Result := (FTPCommand('CDUP') div 100) = 2;
+end;
+
+function TFTPSend.ChangeToRootDir: Boolean;
+begin
+ Result := ChangeWorkingDir('/');
+end;
+
+function TFTPSend.DeleteDir(const Directory: string): Boolean;
+begin
+ Result := (FTPCommand('RMD ' + Directory) div 100) = 2;
+end;
+
+function TFTPSend.CreateDir(const Directory: string): Boolean;
+begin
+ Result := (FTPCommand('MKD ' + Directory) div 100) = 2;
+end;
+
+function TFTPSend.GetCurrentDir: String;
+begin
+ Result := '';
+ if (FTPCommand('PWD') div 100) = 2 then
+ begin
+ Result := SeparateRight(FResultString, '"');
+ Result := Trim(Separateleft(Result, '"'));
+ end;
+end;
+
+procedure TFTPSend.Abort;
+begin
+ FSock.SendString('ABOR' + CRLF);
+ FDSock.StopFlag := True;
+end;
+
+procedure TFTPSend.TelnetAbort;
+begin
+ FSock.SendString(#$FF + #$F4 + #$FF + #$F2);
+ Abort;
+end;
+
+{==============================================================================}
+
+procedure TFTPListRec.Assign(Value: TFTPListRec);
+begin
+ FFileName := Value.FileName;
+ FDirectory := Value.Directory;
+ FReadable := Value.Readable;
+ FFileSize := Value.FileSize;
+ FFileTime := Value.FileTime;
+ FOriginalLine := Value.OriginalLine;
+ FMask := Value.Mask;
+end;
+
+constructor TFTPList.Create;
+begin
+ inherited Create;
+ FList := TList.Create;
+ FLines := TStringList.Create;
+ FMasks := TStringList.Create;
+ FUnparsedLines := TStringList.Create;
+ //various UNIX
+ FMasks.add('pppppppppp $!!!S*$TTT$DD$hh mm ss$YYYY$n*');
+ FMasks.add('pppppppppp $!!!S*$DD$TTT$hh mm ss$YYYY$n*');
+ FMasks.add('pppppppppp $!!!S*$TTT$DD$UUUUU$n*'); //mostly used UNIX format
+ FMasks.add('pppppppppp $!!!S*$DD$TTT$UUUUU$n*');
+ //MacOS
+ FMasks.add('pppppppppp $!!S*$TTT$DD$UUUUU$n*');
+ FMasks.add('pppppppppp $!S*$TTT$DD$UUUUU$n*');
+ //Novell
+ FMasks.add('d $!S*$TTT$DD$UUUUU$n*');
+ //Windows
+ FMasks.add('MM DD YY hh mmH !S* n*');
+ FMasks.add('MM DD YY hh mmH $ d!n*');
+ FMasks.add('MM DD YYYY hh mmH !S* n*');
+ FMasks.add('MM DD YYYY hh mmH $ d!n*');
+ FMasks.add('DD MM YYYY hh mmH !S* n*');
+ FMasks.add('DD MM YYYY hh mmH $ d!n*');
+ //VMS
+ FMasks.add('v*$ DD TTT YYYY hh mm');
+ FMasks.add('v*$!DD TTT YYYY hh mm');
+ FMasks.add('n*$ YYYY MM DD hh mm$S*');
+ //AS400
+ FMasks.add('!S*$MM DD YY hh mm ss !n*');
+ FMasks.add('!S*$DD MM YY hh mm ss !n*');
+ FMasks.add('n*!S*$MM DD YY hh mm ss d');
+ FMasks.add('n*!S*$DD MM YY hh mm ss d');
+ //VxWorks
+ FMasks.add('$S* TTT DD YYYY hh mm ss $n* $ d');
+ FMasks.add('$S* TTT DD YYYY hh mm ss $n*');
+ //Distinct
+ FMasks.add('d $S*$TTT DD YYYY hh mm$n*');
+ FMasks.add('d $S*$TTT DD$hh mm$n*');
+ //PC-NFSD
+ FMasks.add('nnnnnnnn.nnn dSSSSSSSSSSS MM DD YY hh mmH');
+ //VOS
+ FMasks.add('- SSSSS YY MM DD hh mm ss n*');
+ FMasks.add('- d= SSSSS YY MM DD hh mm ss n*');
+ //Unissys ClearPath
+ FMasks.add('nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn SSSSSSSSS MM DD YYYY hh mm');
+ FMasks.add('n*\x SSSSSSSSS MM DD YYYY hh mm');
+ //IBM
+ FMasks.add('- SSSSSSSSSSSS d MM DD YYYY hh mm n*');
+ //OS9
+ FMasks.add('- YY MM DD hhmm d SSSSSSSSS n*');
+ //tandem
+ FMasks.add('nnnnnnnn SSSSSSS DD TTT YY hh mm ss');
+ //MVS
+ FMasks.add('- YYYY MM DD SSSSS d=O n*');
+ //BullGCOS8
+ FMasks.add(' $S* MM DD YY hh mm ss !n*');
+ FMasks.add('d $S* MM DD YY !n*');
+ //BullGCOS7
+ FMasks.add(' TTT DD YYYY n*');
+ FMasks.add(' d n*');
+end;
+
+destructor TFTPList.Destroy;
+begin
+ Clear;
+ FList.Free;
+ FLines.Free;
+ FMasks.Free;
+ FUnparsedLines.Free;
+ inherited Destroy;
+end;
+
+procedure TFTPList.Clear;
+var
+ n:integer;
+begin
+ for n := 0 to FList.Count - 1 do
+ if Assigned(FList[n]) then
+ TFTPListRec(FList[n]).Free;
+ FList.Clear;
+ FLines.Clear;
+ FUnparsedLines.Clear;
+end;
+
+function TFTPList.Count: integer;
+begin
+ Result := FList.Count;
+end;
+
+function TFTPList.GetListItem(Index: integer): TFTPListRec;
+begin
+ Result := nil;
+ if Index < Count then
+ Result := TFTPListRec(FList[Index]);
+end;
+
+procedure TFTPList.Assign(Value: TFTPList);
+var
+ flr: TFTPListRec;
+ n: integer;
+begin
+ Clear;
+ for n := 0 to Value.Count - 1 do
+ begin
+ flr := TFTPListRec.Create;
+ flr.Assign(Value[n]);
+ Flist.Add(flr);
+ end;
+ Lines.Assign(Value.Lines);
+ Masks.Assign(Value.Masks);
+ UnparsedLines.Assign(Value.UnparsedLines);
+end;
+
+procedure TFTPList.ClearStore;
+begin
+ Monthnames := '';
+ BlockSize := '';
+ DirFlagValue := '';
+ FileName := '';
+ VMSFileName := '';
+ Day := '';
+ Month := '';
+ ThreeMonth := '';
+ YearTime := '';
+ Year := '';
+ Hours := '';
+ HoursModif := '';
+ Minutes := '';
+ Seconds := '';
+ Size := '';
+ Permissions := '';
+ DirFlag := '';
+end;
+
+function TFTPList.ParseByMask(Value, NextValue, Mask: string): Integer;
+var
+ Ivalue, IMask: integer;
+ MaskC, LastMaskC: Char;
+ c: char;
+ s: string;
+begin
+ ClearStore;
+ Result := 0;
+ if Value = '' then
+ Exit;
+ if Mask = '' then
+ Exit;
+ Ivalue := 1;
+ IMask := 1;
+ Result := 1;
+ LastMaskC := ' ';
+ while Imask <= Length(mask) do
+ begin
+ if (Mask[Imask] <> '*') and (Ivalue > Length(Value)) then
+ begin
+ Result := 0;
+ Exit;
+ end;
+ MaskC := Mask[Imask];
+ if Ivalue > Length(Value) then
+ Exit;
+ c := Value[Ivalue];
+ case MaskC of
+ 'n':
+ FileName := FileName + c;
+ 'v':
+ VMSFileName := VMSFileName + c;
+ '.':
+ begin
+ if c in ['.', ' '] then
+ FileName := TrimSP(FileName) + '.'
+ else
+ begin
+ Result := 0;
+ Exit;
+ end;
+ end;
+ 'D':
+ Day := Day + c;
+ 'M':
+ Month := Month + c;
+ 'T':
+ ThreeMonth := ThreeMonth + c;
+ 'U':
+ YearTime := YearTime + c;
+ 'Y':
+ Year := Year + c;
+ 'h':
+ Hours := Hours + c;
+ 'H':
+ HoursModif := HoursModif + c;
+ 'm':
+ Minutes := Minutes + c;
+ 's':
+ Seconds := Seconds + c;
+ 'S':
+ Size := Size + c;
+ 'p':
+ Permissions := Permissions + c;
+ 'd':
+ DirFlag := DirFlag + c;
+ 'x':
+ if c <> ' ' then
+ begin
+ Result := 0;
+ Exit;
+ end;
+ '*':
+ begin
+ s := '';
+ if LastMaskC in ['n', 'v'] then
+ begin
+ if Imask = Length(Mask) then
+ s := Copy(Value, IValue, Maxint)
+ else
+ while IValue <= Length(Value) do
+ begin
+ if Value[Ivalue] = ' ' then
+ break;
+ s := s + Value[Ivalue];
+ Inc(Ivalue);
+ end;
+ if LastMaskC = 'n' then
+ FileName := FileName + s
+ else
+ VMSFileName := VMSFileName + s;
+ end
+ else
+ begin
+ while IValue <= Length(Value) do
+ begin
+ if not(Value[Ivalue] in ['0'..'9']) then
+ break;
+ s := s + Value[Ivalue];
+ Inc(Ivalue);
+ end;
+ case LastMaskC of
+ 'S':
+ Size := Size + s;
+ end;
+ end;
+ Dec(IValue);
+ end;
+ '!':
+ begin
+ while IValue <= Length(Value) do
+ begin
+ if Value[Ivalue] = ' ' then
+ break;
+ Inc(Ivalue);
+ end;
+ while IValue <= Length(Value) do
+ begin
+ if Value[Ivalue] <> ' ' then
+ break;
+ Inc(Ivalue);
+ end;
+ Dec(IValue);
+ end;
+ '$':
+ begin
+ while IValue <= Length(Value) do
+ begin
+ if not(Value[Ivalue] in [' ', #9]) then
+ break;
+ Inc(Ivalue);
+ end;
+ Dec(IValue);
+ end;
+ '=':
+ begin
+ s := '';
+ case LastmaskC of
+ 'S':
+ begin
+ while Imask <= Length(Mask) do
+ begin
+ if not(Mask[Imask] in ['0'..'9']) then
+ break;
+ s := s + Mask[Imask];
+ Inc(Imask);
+ end;
+ Dec(Imask);
+ BlockSize := s;
+ end;
+ 'T':
+ begin
+ Monthnames := Copy(Mask, IMask, 12 * 3);
+ Inc(IMask, 12 * 3);
+ end;
+ 'd':
+ begin
+ Inc(Imask);
+ DirFlagValue := Mask[Imask];
+ end;
+ end;
+ end;
+ '\':
+ begin
+ Value := NextValue;
+ IValue := 0;
+ Result := 2;
+ end;
+ end;
+ Inc(Ivalue);
+ Inc(Imask);
+ LastMaskC := MaskC;
+ end;
+end;
+
+function TFTPList.CheckValues: Boolean;
+var
+ x, n: integer;
+begin
+ Result := false;
+ if FileName <> '' then
+ begin
+ if pos('?', VMSFilename) > 0 then
+ Exit;
+ if pos('*', VMSFilename) > 0 then
+ Exit;
+ end;
+ if VMSFileName <> '' then
+ if pos(';', VMSFilename) <= 0 then
+ Exit;
+ if (FileName = '') and (VMSFileName = '') then
+ Exit;
+ if Permissions <> '' then
+ begin
+ if length(Permissions) <> 10 then
+ Exit;
+ for n := 1 to 10 do
+ if not(Permissions[n] in
+ ['a', 'b', 'c', 'd', 'h', 'l', 'p', 'r', 's', 't', 'w', 'x', 'y', '-']) then
+ Exit;
+ end;
+ if Day <> '' then
+ begin
+ Day := TrimSP(Day);
+ x := StrToIntDef(day, -1);
+ if (x < 1) or (x > 31) then
+ Exit;
+ end;
+ if Month <> '' then
+ begin
+ Month := TrimSP(Month);
+ x := StrToIntDef(Month, -1);
+ if (x < 1) or (x > 12) then
+ Exit;
+ end;
+ if Hours <> '' then
+ begin
+ Hours := TrimSP(Hours);
+ x := StrToIntDef(Hours, -1);
+ if (x < 0) or (x > 24) then
+ Exit;
+ end;
+ if HoursModif <> '' then
+ begin
+ if not (HoursModif[1] in ['a', 'A', 'p', 'P']) then
+ Exit;
+ end;
+ if Minutes <> '' then
+ begin
+ Minutes := TrimSP(Minutes);
+ x := StrToIntDef(Minutes, -1);
+ if (x < 0) or (x > 59) then
+ Exit;
+ end;
+ if Seconds <> '' then
+ begin
+ Seconds := TrimSP(Seconds);
+ x := StrToIntDef(Seconds, -1);
+ if (x < 0) or (x > 59) then
+ Exit;
+ end;
+ if Size <> '' then
+ begin
+ Size := TrimSP(Size);
+ for n := 1 to Length(Size) do
+ if not (Size[n] in ['0'..'9']) then
+ Exit;
+ end;
+
+ if length(Monthnames) = (12 * 3) then
+ for n := 1 to 12 do
+ CustomMonthNames[n] := Copy(Monthnames, ((n - 1) * 3) + 1, 3);
+ if ThreeMonth <> '' then
+ begin
+ x := GetMonthNumber(ThreeMonth);
+ if (x = 0) then
+ Exit;
+ end;
+ if YearTime <> '' then
+ begin
+ YearTime := ReplaceString(YearTime, '-', ':');
+ if pos(':', YearTime) > 0 then
+ begin
+ if (GetTimeFromstr(YearTime) = -1) then
+ Exit;
+ end
+ else
+ begin
+ YearTime := TrimSP(YearTime);
+ x := StrToIntDef(YearTime, -1);
+ if (x = -1) then
+ Exit;
+ if (x < 1900) or (x > 2100) then
+ Exit;
+ end;
+ end;
+ if Year <> '' then
+ begin
+ Year := TrimSP(Year);
+ x := StrToIntDef(Year, -1);
+ if (x = -1) then
+ Exit;
+ if Length(Year) = 4 then
+ begin
+ if not((x > 1900) and (x < 2100)) then
+ Exit;
+ end
+ else
+ if Length(Year) = 2 then
+ begin
+ if not((x >= 0) and (x <= 99)) then
+ Exit;
+ end
+ else
+ if Length(Year) = 3 then
+ begin
+ if not((x >= 100) and (x <= 110)) then
+ Exit;
+ end
+ else
+ Exit;
+ end;
+ Result := True;
+end;
+
+procedure TFTPList.FillRecord(const Value: TFTPListRec);
+var
+ s: string;
+ x: integer;
+ myear: Word;
+ mmonth: Word;
+ mday: Word;
+ mhours, mminutes, mseconds: word;
+ n: integer;
+begin
+ s := DirFlagValue;
+ if s = '' then
+ s := 'D';
+ s := Uppercase(s);
+ Value.Directory := s = Uppercase(DirFlag);
+ if FileName <> '' then
+ Value.FileName := SeparateLeft(Filename, ' -> ');
+ if VMSFileName <> '' then
+ begin
+ Value.FileName := VMSFilename;
+ Value.Directory := Pos('.DIR;',VMSFilename) > 0;
+ end;
+ Value.FileName := TrimSPRight(Value.FileName);
+ Value.Readable := not Value.Directory;
+ if BlockSize <> '' then
+ x := StrToIntDef(BlockSize, 1)
+ else
+ x := 1;
+ Value.FileSize := x * StrToIntDef(Size, 0);
+
+ DecodeDate(Date,myear,mmonth,mday);
+ mhours := 0;
+ mminutes := 0;
+ mseconds := 0;
+
+ if Day <> '' then
+ mday := StrToIntDef(day, 1);
+ if Month <> '' then
+ mmonth := StrToIntDef(Month, 1);
+ if length(Monthnames) = (12 * 3) then
+ for n := 1 to 12 do
+ CustomMonthNames[n] := Copy(Monthnames, ((n - 1) * 3) + 1, 3);
+ if ThreeMonth <> '' then
+ mmonth := GetMonthNumber(ThreeMonth);
+ if Year <> '' then
+ begin
+ myear := StrToIntDef(Year, 0);
+ if (myear <= 99) and (myear > 50) then
+ myear := myear + 1900;
+ if myear <= 50 then
+ myear := myear + 2000;
+ end;
+ if YearTime <> '' then
+ begin
+ if pos(':', YearTime) > 0 then
+ begin
+ YearTime := TrimSP(YearTime);
+ mhours := StrToIntDef(Separateleft(YearTime, ':'), 0);
+ mminutes := StrToIntDef(SeparateRight(YearTime, ':'), 0);
+ if (Encodedate(myear, mmonth, mday)
+ + EncodeTime(mHours, mminutes, 0, 0)) > now then
+ Dec(mYear);
+ end
+ else
+ myear := StrToIntDef(YearTime, 0);
+ end;
+ if Minutes <> '' then
+ mminutes := StrToIntDef(Minutes, 0);
+ if Seconds <> '' then
+ mseconds := StrToIntDef(Seconds, 0);
+ if Hours <> '' then
+ begin
+ mHours := StrToIntDef(Hours, 0);
+ if HoursModif <> '' then
+ if Uppercase(HoursModif[1]) = 'P' then
+ if mHours <> 12 then
+ mHours := MHours + 12;
+ end;
+ Value.FileTime := Encodedate(myear, mmonth, mday)
+ + EncodeTime(mHours, mminutes, mseconds, 0);
+ if Permissions <> '' then
+ begin
+ Value.Permission := Permissions;
+ Value.Readable := Uppercase(permissions)[2] = 'R';
+ if Uppercase(permissions)[1] = 'D' then
+ begin
+ Value.Directory := True;
+ Value.Readable := false;
+ end
+ else
+ if Uppercase(permissions)[1] = 'L' then
+ Value.Directory := True;
+ end;
+end;
+
+function TFTPList.ParseEPLF(Value: string): Boolean;
+var
+ s, os: string;
+ flr: TFTPListRec;
+begin
+ Result := False;
+ if Value <> '' then
+ if Value[1] = '+' then
+ begin
+ os := Value;
+ Delete(Value, 1, 1);
+ flr := TFTPListRec.create;
+ flr.FileName := SeparateRight(Value, #9);
+ s := Fetch(Value, ',');
+ while s <> '' do
+ begin
+ if s[1] = #9 then
+ Break;
+ case s[1] of
+ '/':
+ flr.Directory := true;
+ 'r':
+ flr.Readable := true;
+ 's':
+ flr.FileSize := StrToIntDef(Copy(s, 2, Length(s) - 1), 0);
+ 'm':
+ flr.FileTime := (StrToIntDef(Copy(s, 2, Length(s) - 1), 0) / 86400)
+ + 25569;
+ end;
+ s := Fetch(Value, ',');
+ end;
+ if flr.FileName <> '' then
+ if (flr.Directory and ((flr.FileName = '.') or (flr.FileName = '..')))
+ or (flr.FileName = '') then
+ flr.free
+ else
+ begin
+ flr.OriginalLine := os;
+ flr.Mask := 'EPLF';
+ Flist.Add(flr);
+ Result := True;
+ end;
+ end;
+end;
+
+procedure TFTPList.ParseLines;
+var
+ flr: TFTPListRec;
+ n, m: Integer;
+ S: string;
+ x: integer;
+ b: Boolean;
+begin
+ n := 0;
+ while n < Lines.Count do
+ begin
+ if n = Lines.Count - 1 then
+ s := ''
+ else
+ s := Lines[n + 1];
+ b := False;
+ x := 0;
+ if ParseEPLF(Lines[n]) then
+ begin
+ b := True;
+ x := 1;
+ end
+ else
+ for m := 0 to Masks.Count - 1 do
+ begin
+ x := ParseByMask(Lines[n], s, Masks[m]);
+ if x > 0 then
+ if CheckValues then
+ begin
+ flr := TFTPListRec.create;
+ FillRecord(flr);
+ flr.OriginalLine := Lines[n];
+ flr.Mask := Masks[m];
+ if flr.Directory and ((flr.FileName = '.') or (flr.FileName = '..')) then
+ flr.free
+ else
+ Flist.Add(flr);
+ b := True;
+ Break;
+ end;
+ end;
+ if not b then
+ FUnparsedLines.Add(Lines[n]);
+ Inc(n);
+ if x > 1 then
+ Inc(n, x - 1);
+ end;
+end;
+
+{==============================================================================}
+
+function FtpGetFile(const IP, Port, FileName, LocalFile,
+ User, Pass: string): Boolean;
+begin
+ Result := False;
+ with TFTPSend.Create do
+ try
+ if User <> '' then
+ begin
+ Username := User;
+ Password := Pass;
+ end;
+ TargetHost := IP;
+ TargetPort := Port;
+ if not Login then
+ Exit;
+ DirectFileName := LocalFile;
+ DirectFile:=True;
+ Result := RetrieveFile(FileName, False);
+ Logout;
+ finally
+ Free;
+ end;
+end;
+
+function FtpPutFile(const IP, Port, FileName, LocalFile,
+ User, Pass: string): Boolean;
+begin
+ Result := False;
+ with TFTPSend.Create do
+ try
+ if User <> '' then
+ begin
+ Username := User;
+ Password := Pass;
+ end;
+ TargetHost := IP;
+ TargetPort := Port;
+ if not Login then
+ Exit;
+ DirectFileName := LocalFile;
+ DirectFile:=True;
+ Result := StoreFile(FileName, False);
+ Logout;
+ finally
+ Free;
+ end;
+end;
+
+function FtpInterServerTransfer(
+ const FromIP, FromPort, FromFile, FromUser, FromPass: string;
+ const ToIP, ToPort, ToFile, ToUser, ToPass: string): Boolean;
+var
+ FromFTP, ToFTP: TFTPSend;
+ s: string;
+ x: integer;
+begin
+ Result := False;
+ FromFTP := TFTPSend.Create;
+ toFTP := TFTPSend.Create;
+ try
+ if FromUser <> '' then
+ begin
+ FromFTP.Username := FromUser;
+ FromFTP.Password := FromPass;
+ end;
+ if ToUser <> '' then
+ begin
+ ToFTP.Username := ToUser;
+ ToFTP.Password := ToPass;
+ end;
+ FromFTP.TargetHost := FromIP;
+ FromFTP.TargetPort := FromPort;
+ ToFTP.TargetHost := ToIP;
+ ToFTP.TargetPort := ToPort;
+ if not FromFTP.Login then
+ Exit;
+ if not ToFTP.Login then
+ Exit;
+ if (FromFTP.FTPCommand('PASV') div 100) <> 2 then
+ Exit;
+ FromFTP.ParseRemote(FromFTP.ResultString);
+ s := ReplaceString(FromFTP.DataIP, '.', ',');
+ s := 'PORT ' + s + ',' + IntToStr(StrToIntDef(FromFTP.DataPort, 0) div 256)
+ + ',' + IntToStr(StrToIntDef(FromFTP.DataPort, 0) mod 256);
+ if (ToFTP.FTPCommand(s) div 100) <> 2 then
+ Exit;
+ x := ToFTP.FTPCommand('RETR ' + FromFile);
+ if (x div 100) <> 1 then
+ Exit;
+ x := FromFTP.FTPCommand('STOR ' + ToFile);
+ if (x div 100) <> 1 then
+ Exit;
+ FromFTP.Timeout := 21600000;
+ x := FromFTP.ReadResult;
+ if (x div 100) <> 2 then
+ Exit;
+ ToFTP.Timeout := 21600000;
+ x := ToFTP.ReadResult;
+ if (x div 100) <> 2 then
+ Exit;
+ Result := True;
+ finally
+ ToFTP.Free;
+ FromFTP.Free;
+ end;
+end;
+
+end.
diff --git a/branches/script-component/Units/Synapse/ftptsend.pas b/branches/script-component/Units/Synapse/ftptsend.pas
new file mode 100644
index 0000000..9cf7bab
--- /dev/null
+++ b/branches/script-component/Units/Synapse/ftptsend.pas
@@ -0,0 +1,397 @@
+{==============================================================================|
+| Project : Ararat Synapse | 001.001.000 |
+|==============================================================================|
+| Content: Trivial FTP (TFTP) client and server |
+|==============================================================================|
+| Copyright (c)1999-2004, Lukas Gebauer |
+| All rights reserved. |
+| |
+| Redistribution and use in source and binary forms, with or without |
+| modification, are permitted provided that the following conditions are met: |
+| |
+| Redistributions of source code must retain the above copyright notice, this |
+| list of conditions and the following disclaimer. |
+| |
+| Redistributions in binary form must reproduce the above copyright notice, |
+| this list of conditions and the following disclaimer in the documentation |
+| and/or other materials provided with the distribution. |
+| |
+| Neither the name of Lukas Gebauer nor the names of its contributors may |
+| be used to endorse or promote products derived from this software without |
+| specific prior written permission. |
+| |
+| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
+| AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
+| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
+| ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR |
+| ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
+| DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
+| SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
+| CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
+| LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
+| OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
+| DAMAGE. |
+|==============================================================================|
+| The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).|
+| Portions created by Lukas Gebauer are Copyright (c)2003-2004. |
+| All Rights Reserved. |
+|==============================================================================|
+| Contributor(s): |
+|==============================================================================|
+| History: see HISTORY.HTM from distribution package |
+| (Found at URL: http://www.ararat.cz/synapse/) |
+|==============================================================================}
+
+{: @abstract(TFTP client and server protocol)
+
+Used RFC: RFC-1350
+}
+
+{$IFDEF FPC}
+ {$MODE DELPHI}
+{$ENDIF}
+{$Q-}
+{$H+}
+
+unit ftptsend;
+
+interface
+
+uses
+ SysUtils, Classes,
+ blcksock, synautil;
+
+const
+ cTFTPProtocol = '69';
+
+ cTFTP_RRQ = word(1);
+ cTFTP_WRQ = word(2);
+ cTFTP_DTA = word(3);
+ cTFTP_ACK = word(4);
+ cTFTP_ERR = word(5);
+
+type
+ {:@abstract(Implementation of TFTP client and server)
+ Note: Are you missing properties for specify server address and port? Look to
+ parent @link(TSynaClient) too!}
+ TTFTPSend = class(TSynaClient)
+ private
+ FSock: TUDPBlockSocket;
+ FErrorCode: integer;
+ FErrorString: string;
+ FData: TMemoryStream;
+ FRequestIP: string;
+ FRequestPort: string;
+ function SendPacket(Cmd: word; Serial: word; const Value: string): Boolean;
+ function RecvPacket(Serial: word; var Value: string): Boolean;
+ public
+ constructor Create;
+ destructor Destroy; override;
+
+ {:Upload @link(data) as file to TFTP server.}
+ function SendFile(const Filename: string): Boolean;
+
+ {:Download file from TFTP server to @link(data).}
+ function RecvFile(const Filename: string): Boolean;
+
+ {:Acts as TFTP server and wait for client request. When some request
+ incoming within Timeout, result is @true and parametres is filled with
+ information from request. You must handle this request, validate it, and
+ call @link(ReplyError), @link(ReplyRecv) or @link(ReplySend) for send reply
+ to TFTP Client.}
+ function WaitForRequest(var Req: word; var filename: string): Boolean;
+
+ {:send error to TFTP client, when you acts as TFTP server.}
+ procedure ReplyError(Error: word; Description: string);
+
+ {:Accept uploaded file from TFTP client to @link(data), when you acts as
+ TFTP server.}
+ function ReplyRecv: Boolean;
+
+ {:Accept download request file from TFTP client and send content of
+ @link(data), when you acts as TFTP server.}
+ function ReplySend: Boolean;
+ published
+ {:Code of TFTP error.}
+ property ErrorCode: integer read FErrorCode;
+
+ {:Human readable decription of TFTP error. (if is sended by remote side)}
+ property ErrorString: string read FErrorString;
+
+ {:MemoryStream with datas for sending or receiving}
+ property Data: TMemoryStream read FData;
+
+ {:Address of TFTP remote side.}
+ property RequestIP: string read FRequestIP write FRequestIP;
+
+ {:Port of TFTP remote side.}
+ property RequestPort: string read FRequestPort write FRequestPort;
+ end;
+
+implementation
+
+constructor TTFTPSend.Create;
+begin
+ inherited Create;
+ FSock := TUDPBlockSocket.Create;
+ FTargetPort := cTFTPProtocol;
+ FData := TMemoryStream.Create;
+ FErrorCode := 0;
+ FErrorString := '';
+end;
+
+destructor TTFTPSend.Destroy;
+begin
+ FSock.Free;
+ FData.Free;
+ inherited Destroy;
+end;
+
+function TTFTPSend.SendPacket(Cmd: word; Serial: word; const Value: string): Boolean;
+var
+ s, sh: string;
+begin
+ FErrorCode := 0;
+ FErrorString := '';
+ Result := false;
+ if Cmd <> 2 then
+ s := CodeInt(Cmd) + CodeInt(Serial) + Value
+ else
+ s := CodeInt(Cmd) + Value;
+ FSock.SendString(s);
+ s := FSock.RecvPacket(FTimeout);
+ if FSock.LastError = 0 then
+ if length(s) >= 4 then
+ begin
+ sh := CodeInt(4) + CodeInt(Serial);
+ if Pos(sh, s) = 1 then
+ Result := True
+ else
+ if s[1] = #5 then
+ begin
+ FErrorCode := DecodeInt(s, 3);
+ Delete(s, 1, 4);
+ FErrorString := SeparateLeft(s, #0);
+ end;
+ end;
+end;
+
+function TTFTPSend.RecvPacket(Serial: word; var Value: string): Boolean;
+var
+ s: string;
+ ser: word;
+begin
+ FErrorCode := 0;
+ FErrorString := '';
+ Result := False;
+ Value := '';
+ s := FSock.RecvPacket(FTimeout);
+ if FSock.LastError = 0 then
+ if length(s) >= 4 then
+ if DecodeInt(s, 1) = 3 then
+ begin
+ ser := DecodeInt(s, 3);
+ if ser = Serial then
+ begin
+ Delete(s, 1, 4);
+ Value := s;
+ S := CodeInt(4) + CodeInt(ser);
+ FSock.SendString(s);
+ Result := FSock.LastError = 0;
+ end
+ else
+ begin
+ S := CodeInt(5) + CodeInt(5) + 'Unexcepted serial#' + #0;
+ FSock.SendString(s);
+ end;
+ end;
+ if DecodeInt(s, 1) = 5 then
+ begin
+ FErrorCode := DecodeInt(s, 3);
+ Delete(s, 1, 4);
+ FErrorString := SeparateLeft(s, #0);
+ end;
+end;
+
+function TTFTPSend.SendFile(const Filename: string): Boolean;
+var
+ s: string;
+ ser: word;
+ n, n1, n2: integer;
+begin
+ Result := False;
+ FErrorCode := 0;
+ FErrorString := '';
+ FSock.CloseSocket;
+ FSock.Connect(FTargetHost, FTargetPort);
+ try
+ if FSock.LastError = 0 then
+ begin
+ s := Filename + #0 + 'octet' + #0;
+ if not Sendpacket(2, 0, s) then
+ Exit;
+ ser := 1;
+ FData.Position := 0;
+ n1 := FData.Size div 512;
+ n2 := FData.Size mod 512;
+ for n := 1 to n1 do
+ begin
+ s := ReadStrFromStream(FData, 512);
+// SetLength(s, 512);
+// FData.Read(pointer(s)^, 512);
+ if not Sendpacket(3, ser, s) then
+ Exit;
+ inc(ser);
+ end;
+ s := ReadStrFromStream(FData, n2);
+// SetLength(s, n2);
+// FData.Read(pointer(s)^, n2);
+ if not Sendpacket(3, ser, s) then
+ Exit;
+ Result := True;
+ end;
+ finally
+ FSock.CloseSocket;
+ end;
+end;
+
+function TTFTPSend.RecvFile(const Filename: string): Boolean;
+var
+ s: string;
+ ser: word;
+begin
+ Result := False;
+ FErrorCode := 0;
+ FErrorString := '';
+ FSock.CloseSocket;
+ FSock.Connect(FTargetHost, FTargetPort);
+ try
+ if FSock.LastError = 0 then
+ begin
+ s := CodeInt(1) + Filename + #0 + 'octet' + #0;
+ FSock.SendString(s);
+ if FSock.LastError <> 0 then
+ Exit;
+ FData.Clear;
+ ser := 1;
+ repeat
+ if not RecvPacket(ser, s) then
+ Exit;
+ inc(ser);
+ WriteStrToStream(FData, s);
+// FData.Write(pointer(s)^, length(s));
+ until length(s) <> 512;
+ FData.Position := 0;
+ Result := true;
+ end;
+ finally
+ FSock.CloseSocket;
+ end;
+end;
+
+function TTFTPSend.WaitForRequest(var Req: word; var filename: string): Boolean;
+var
+ s: string;
+begin
+ Result := False;
+ FErrorCode := 0;
+ FErrorString := '';
+ FSock.CloseSocket;
+ FSock.Bind('0.0.0.0', FTargetPort);
+ if FSock.LastError = 0 then
+ begin
+ s := FSock.RecvPacket(FTimeout);
+ if FSock.LastError = 0 then
+ if Length(s) >= 4 then
+ begin
+ FRequestIP := FSock.GetRemoteSinIP;
+ FRequestPort := IntToStr(FSock.GetRemoteSinPort);
+ Req := DecodeInt(s, 1);
+ delete(s, 1, 2);
+ filename := Trim(SeparateLeft(s, #0));
+ s := SeparateRight(s, #0);
+ s := SeparateLeft(s, #0);
+ Result := lowercase(trim(s)) = 'octet';
+ end;
+ end;
+end;
+
+procedure TTFTPSend.ReplyError(Error: word; Description: string);
+var
+ s: string;
+begin
+ FSock.CloseSocket;
+ FSock.Connect(FRequestIP, FRequestPort);
+ s := CodeInt(5) + CodeInt(Error) + Description + #0;
+ FSock.SendString(s);
+ FSock.CloseSocket;
+end;
+
+function TTFTPSend.ReplyRecv: Boolean;
+var
+ s: string;
+ ser: integer;
+begin
+ Result := False;
+ FErrorCode := 0;
+ FErrorString := '';
+ FSock.CloseSocket;
+ FSock.Connect(FRequestIP, FRequestPort);
+ try
+ s := CodeInt(4) + CodeInt(0);
+ FSock.SendString(s);
+ FData.Clear;
+ ser := 1;
+ repeat
+ if not RecvPacket(ser, s) then
+ Exit;
+ inc(ser);
+ WriteStrToStream(FData, s);
+// FData.Write(pointer(s)^, length(s));
+ until length(s) <> 512;
+ FData.Position := 0;
+ Result := true;
+ finally
+ FSock.CloseSocket;
+ end;
+end;
+
+function TTFTPSend.ReplySend: Boolean;
+var
+ s: string;
+ ser: word;
+ n, n1, n2: integer;
+begin
+ Result := False;
+ FErrorCode := 0;
+ FErrorString := '';
+ FSock.CloseSocket;
+ FSock.Connect(FRequestIP, FRequestPort);
+ try
+ ser := 1;
+ FData.Position := 0;
+ n1 := FData.Size div 512;
+ n2 := FData.Size mod 512;
+ for n := 1 to n1 do
+ begin
+ s := ReadStrFromStream(FData, 512);
+// SetLength(s, 512);
+// FData.Read(pointer(s)^, 512);
+ if not Sendpacket(3, ser, s) then
+ Exit;
+ inc(ser);
+ end;
+ s := ReadStrFromStream(FData, n2);
+// SetLength(s, n2);
+// FData.Read(pointer(s)^, n2);
+ if not Sendpacket(3, ser, s) then
+ Exit;
+ Result := True;
+ finally
+ FSock.CloseSocket;
+ end;
+end;
+
+{==============================================================================}
+
+end.
diff --git a/branches/script-component/Units/Synapse/httpsend.pas b/branches/script-component/Units/Synapse/httpsend.pas
new file mode 100644
index 0000000..feef6b0
--- /dev/null
+++ b/branches/script-component/Units/Synapse/httpsend.pas
@@ -0,0 +1,828 @@
+{==============================================================================|
+| Project : Ararat Synapse | 003.012.002 |
+|==============================================================================|
+| Content: HTTP client |
+|==============================================================================|
+| Copyright (c)1999-2008, Lukas Gebauer |
+| All rights reserved. |
+| |
+| Redistribution and use in source and binary forms, with or without |
+| modification, are permitted provided that the following conditions are met: |
+| |
+| Redistributions of source code must retain the above copyright notice, this |
+| list of conditions and the following disclaimer. |
+| |
+| Redistributions in binary form must reproduce the above copyright notice, |
+| this list of conditions and the following disclaimer in the documentation |
+| and/or other materials provided with the distribution. |
+| |
+| Neither the name of Lukas Gebauer nor the names of its contributors may |
+| be used to endorse or promote products derived from this software without |
+| specific prior written permission. |
+| |
+| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
+| AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
+| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
+| ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR |
+| ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
+| DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
+| SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
+| CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
+| LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
+| OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
+| DAMAGE. |
+|==============================================================================|
+| The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).|
+| Portions created by Lukas Gebauer are Copyright (c) 1999-2008. |
+| All Rights Reserved. |
+|==============================================================================|
+| Contributor(s): |
+|==============================================================================|
+| History: see HISTORY.HTM from distribution package |
+| (Found at URL: http://www.ararat.cz/synapse/) |
+|==============================================================================}
+
+{:@abstract(HTTP protocol client)
+
+Used RFC: RFC-1867, RFC-1947, RFC-2388, RFC-2616
+}
+
+{$IFDEF FPC}
+ {$MODE DELPHI}
+{$ENDIF}
+{$H+}
+
+unit httpsend;
+
+interface
+
+uses
+ SysUtils, Classes,
+ blcksock, synautil, synaip, synacode, synsock;
+
+const
+ cHttpProtocol = '80';
+
+type
+ {:These encoding types are used internally by the THTTPSend object to identify
+ the transfer data types.}
+ TTransferEncoding = (TE_UNKNOWN, TE_IDENTITY, TE_CHUNKED);
+
+ {:abstract(Implementation of HTTP protocol.)}
+ THTTPSend = class(TSynaClient)
+ protected
+ FSock: TTCPBlockSocket;
+ FTransferEncoding: TTransferEncoding;
+ FAliveHost: string;
+ FAlivePort: string;
+ FHeaders: TStringList;
+ FDocument: TMemoryStream;
+ FMimeType: string;
+ FProtocol: string;
+ FKeepAlive: Boolean;
+ FKeepAliveTimeout: integer;
+ FStatus100: Boolean;
+ FProxyHost: string;
+ FProxyPort: string;
+ FProxyUser: string;
+ FProxyPass: string;
+ FResultCode: Integer;
+ FResultString: string;
+ FUserAgent: string;
+ FCookies: TStringList;
+ FDownloadSize: integer;
+ FUploadSize: integer;
+ FRangeStart: integer;
+ FRangeEnd: integer;
+ FAddPortNumberToHost: Boolean;
+ function ReadUnknown: Boolean;
+ function ReadIdentity(Size: Integer): Boolean;
+ function ReadChunked: Boolean;
+ procedure ParseCookies;
+ function PrepareHeaders: string;
+ function InternalDoConnect(needssl: Boolean): Boolean;
+ function InternalConnect(needssl: Boolean): Boolean;
+ public
+ constructor Create;
+ destructor Destroy; override;
+
+ {:Reset headers and document and Mimetype.}
+ procedure Clear;
+
+ {:Decode ResultCode and ResultString from Value.}
+ procedure DecodeStatus(const Value: string);
+
+ {:Connects to host define in URL and access to resource defined in URL by
+ method. If Document is not empty, send it to server as part of HTTP request.
+ Server response is in Document and headers. Connection may be authorised
+ by username and password in URL. If you define proxy properties, connection
+ is made by this proxy. If all OK, result is @true, else result is @false.
+
+ If you use in URL 'https:' instead only 'http:', then your request is made
+ by SSL/TLS connection (if you not specify port, then port 443 is used
+ instead standard port 80). If you use SSL/TLS request and you have defined
+ HTTP proxy, then HTTP-tunnel mode is automaticly used .}
+ function HTTPMethod(const Method, URL: string): Boolean;
+
+ {:You can call this method from OnStatus event for break current data
+ transfer. (or from another thread.)}
+ procedure Abort;
+ published
+ {:Before HTTP operation you may define any non-standard headers for HTTP
+ request, except of: 'Expect: 100-continue', 'Content-Length', 'Content-Type',
+ 'Connection', 'Authorization', 'Proxy-Authorization' and 'Host' headers.
+ After HTTP operation contains full headers of returned document.}
+ property Headers: TStringList read FHeaders;
+
+ {:This is stringlist with name-value stringlist pairs. Each this pair is one
+ cookie. After HTTP request is returned cookies parsed to this stringlist.
+ You can leave this cookies untouched for next HTTP request. You can also
+ save this stringlist for later use.}
+ property Cookies: TStringList read FCookies;
+
+ {:Stream with document to send (before request, or with document received
+ from HTTP server (after request).}
+ property Document: TMemoryStream read FDocument;
+
+ {:If you need download only part of requested document, here specify
+ possition of subpart begin. If here 0, then is requested full document.}
+ property RangeStart: integer read FRangeStart Write FRangeStart;
+
+ {:If you need download only part of requested document, here specify
+ possition of subpart end. If here 0, then is requested document from
+ rangeStart to end of document. (for broken download restoration,
+ for example.)}
+ property RangeEnd: integer read FRangeEnd Write FRangeEnd;
+
+ {:Mime type of sending data. Default is: 'text/html'.}
+ property MimeType: string read FMimeType Write FMimeType;
+
+ {:Define protocol version. Possible values are: '1.1', '1.0' (default)
+ and '0.9'.}
+ property Protocol: string read FProtocol Write FProtocol;
+
+ {:If @true (default value), keepalives in HTTP protocol 1.1 is enabled.}
+ property KeepAlive: Boolean read FKeepAlive Write FKeepAlive;
+
+ {:Define timeout for keepalives in seconds!}
+ property KeepAliveTimeout: integer read FKeepAliveTimeout Write FKeepAliveTimeout;
+
+ {:if @true, then server is requested for 100status capability when uploading
+ data. Default is @false (off).}
+ property Status100: Boolean read FStatus100 Write FStatus100;
+
+ {:Address of proxy server (IP address or domain name) where you want to
+ connect in @link(HTTPMethod) method.}
+ property ProxyHost: string read FProxyHost Write FProxyHost;
+
+ {:Port number for proxy connection. Default value is 8080.}
+ property ProxyPort: string read FProxyPort Write FProxyPort;
+
+ {:Username for connect to proxy server where you want to connect in
+ HTTPMethod method.}
+ property ProxyUser: string read FProxyUser Write FProxyUser;
+
+ {:Password for connect to proxy server where you want to connect in
+ HTTPMethod method.}
+ property ProxyPass: string read FProxyPass Write FProxyPass;
+
+ {:Here you can specify custom User-Agent indentification. By default is
+ used: 'Mozilla/4.0 (compatible; Synapse)'}
+ property UserAgent: string read FUserAgent Write FUserAgent;
+
+ {:After successful @link(HTTPMethod) method contains result code of
+ operation.}
+ property ResultCode: Integer read FResultCode;
+
+ {:After successful @link(HTTPMethod) method contains string after result code.}
+ property ResultString: string read FResultString;
+
+ {:if this value is not 0, then data download pending. In this case you have
+ here total sice of downloaded data. It is good for draw download
+ progressbar from OnStatus event.}
+ property DownloadSize: integer read FDownloadSize;
+
+ {:if this value is not 0, then data upload pending. In this case you have
+ here total sice of uploaded data. It is good for draw upload progressbar
+ from OnStatus event.}
+ property UploadSize: integer read FUploadSize;
+ {:Socket object used for TCP/IP operation. Good for seting OnStatus hook, etc.}
+ property Sock: TTCPBlockSocket read FSock;
+
+ {:To have possibility to switch off port number in 'Host:' HTTP header, by
+ default @TRUE. Some buggy servers not like port informations in this header.}
+ property AddPortNumberToHost: Boolean read FAddPortNumberToHost write FAddPortNumberToHost;
+ end;
+
+{:A very usefull function, and example of use can be found in the THTTPSend
+ object. It implements the GET method of the HTTP protocol. This function sends
+ the GET method for URL document to an HTTP server. Returned document is in the
+ "Response" stringlist (without any headers). Returns boolean TRUE if all went
+ well.}
+function HttpGetText(const URL: string; const Response: TStrings): Boolean;
+
+{:A very usefull function, and example of use can be found in the THTTPSend
+ object. It implements the GET method of the HTTP protocol. This function sends
+ the GET method for URL document to an HTTP server. Returned document is in the
+ "Response" stream. Returns boolean TRUE if all went well.}
+function HttpGetBinary(const URL: string; const Response: TStream): Boolean;
+
+{:A very useful function, and example of use can be found in the THTTPSend
+ object. It implements the POST method of the HTTP protocol. This function sends
+ the SEND method for a URL document to an HTTP server. The document to be sent
+ is located in "Data" stream. The returned document is in the "Data" stream.
+ Returns boolean TRUE if all went well.}
+function HttpPostBinary(const URL: string; const Data: TStream): Boolean;
+
+{:A very useful function, and example of use can be found in the THTTPSend
+ object. It implements the POST method of the HTTP protocol. This function is
+ good for POSTing form data. It sends the POST method for a URL document to
+ an HTTP server. You must prepare the form data in the same manner as you would
+ the URL data, and pass this prepared data to "URLdata". The following is
+ a sample of how the data would appear: 'name=Lukas&field1=some%20data'.
+ The information in the field must be encoded by EncodeURLElement function.
+ The returned document is in the "Data" stream. Returns boolean TRUE if all
+ went well.}
+function HttpPostURL(const URL, URLData: string; const Data: TStream): Boolean;
+
+{:A very useful function, and example of use can be found in the THTTPSend
+ object. It implements the POST method of the HTTP protocol. This function sends
+ the POST method for a URL document to an HTTP server. This function simulate
+ posting of file by HTML form used method 'multipart/form-data'. Posting file
+ is in DATA stream. Its name is Filename string. Fieldname is for name of
+ formular field with file. (simulate HTML INPUT FILE) The returned document is
+ in the ResultData Stringlist. Returns boolean TRUE if all went well.}
+function HttpPostFile(const URL, FieldName, FileName: string;
+ const Data: TStream; const ResultData: TStrings): Boolean;
+
+implementation
+
+constructor THTTPSend.Create;
+begin
+ inherited Create;
+ FHeaders := TStringList.Create;
+ FCookies := TStringList.Create;
+ FDocument := TMemoryStream.Create;
+ FSock := TTCPBlockSocket.Create;
+ FSock.ConvertLineEnd := True;
+ FSock.SizeRecvBuffer := c64k;
+ FSock.SizeSendBuffer := c64k;
+ FTimeout := 90000;
+ FTargetPort := cHttpProtocol;
+ FProxyHost := '';
+ FProxyPort := '8080';
+ FProxyUser := '';
+ FProxyPass := '';
+ FAliveHost := '';
+ FAlivePort := '';
+ FProtocol := '1.0';
+ FKeepAlive := True;
+ FStatus100 := False;
+ FUserAgent := 'Mozilla/4.0 (compatible; Synapse)';
+ FDownloadSize := 0;
+ FUploadSize := 0;
+ FAddPortNumberToHost := true;
+ FKeepAliveTimeout := 300;
+ Clear;
+end;
+
+destructor THTTPSend.Destroy;
+begin
+ FSock.Free;
+ FDocument.Free;
+ FCookies.Free;
+ FHeaders.Free;
+ inherited Destroy;
+end;
+
+procedure THTTPSend.Clear;
+begin
+ FRangeStart := 0;
+ FRangeEnd := 0;
+ FDocument.Clear;
+ FHeaders.Clear;
+ FMimeType := 'text/html';
+end;
+
+procedure THTTPSend.DecodeStatus(const Value: string);
+var
+ s, su: string;
+begin
+ s := Trim(SeparateRight(Value, ' '));
+ su := Trim(SeparateLeft(s, ' '));
+ FResultCode := StrToIntDef(su, 0);
+ FResultString := Trim(SeparateRight(s, ' '));
+ if FResultString = s then
+ FResultString := '';
+end;
+
+function THTTPSend.PrepareHeaders: string;
+begin
+ if FProtocol = '0.9' then
+ Result := FHeaders[0] + CRLF
+ else
+{$IFNDEF WIN32}
+ Result := AdjustLineBreaks(FHeaders.Text, tlbsCRLF);
+{$ELSE}
+ Result := FHeaders.Text;
+{$ENDIF}
+end;
+
+function THTTPSend.InternalDoConnect(needssl: Boolean): Boolean;
+begin
+ Result := False;
+ FSock.CloseSocket;
+ FSock.Bind(FIPInterface, cAnyPort);
+ if FSock.LastError <> 0 then
+ Exit;
+ FSock.Connect(FTargetHost, FTargetPort);
+ if FSock.LastError <> 0 then
+ Exit;
+ if needssl then
+ begin
+ FSock.SSLDoConnect;
+ if FSock.LastError <> 0 then
+ Exit;
+ end;
+ FAliveHost := FTargetHost;
+ FAlivePort := FTargetPort;
+ Result := True;
+end;
+
+function THTTPSend.InternalConnect(needssl: Boolean): Boolean;
+begin
+ if FSock.Socket = INVALID_SOCKET then
+ Result := InternalDoConnect(needssl)
+ else
+ if (FAliveHost <> FTargetHost) or (FAlivePort <> FTargetPort)
+ or FSock.CanRead(0) then
+ Result := InternalDoConnect(needssl)
+ else
+ Result := True;
+end;
+
+function THTTPSend.HTTPMethod(const Method, URL: string): Boolean;
+var
+ Sending, Receiving: Boolean;
+ status100: Boolean;
+ status100error: string;
+ ToClose: Boolean;
+ Size: Integer;
+ Prot, User, Pass, Host, Port, Path, Para, URI: string;
+ s, su: string;
+ HttpTunnel: Boolean;
+ n: integer;
+ pp: string;
+ UsingProxy: boolean;
+ l: TStringList;
+ x: integer;
+begin
+ {initial values}
+ Result := False;
+ FResultCode := 500;
+ FResultString := '';
+ FDownloadSize := 0;
+ FUploadSize := 0;
+
+ URI := ParseURL(URL, Prot, User, Pass, Host, Port, Path, Para);
+ if User = '' then
+ begin
+ User := FUsername;
+ Pass := FPassword;
+ end;
+ if UpperCase(Prot) = 'HTTPS' then
+ begin
+ HttpTunnel := FProxyHost <> '';
+ FSock.HTTPTunnelIP := FProxyHost;
+ FSock.HTTPTunnelPort := FProxyPort;
+ FSock.HTTPTunnelUser := FProxyUser;
+ FSock.HTTPTunnelPass := FProxyPass;
+ end
+ else
+ begin
+ HttpTunnel := False;
+ FSock.HTTPTunnelIP := '';
+ FSock.HTTPTunnelPort := '';
+ FSock.HTTPTunnelUser := '';
+ FSock.HTTPTunnelPass := '';
+ end;
+ UsingProxy := (FProxyHost <> '') and not(HttpTunnel);
+ Sending := FDocument.Size > 0;
+ {Headers for Sending data}
+ status100 := FStatus100 and Sending and (FProtocol = '1.1');
+ if status100 then
+ FHeaders.Insert(0, 'Expect: 100-continue');
+ if Sending then
+ begin
+ FHeaders.Insert(0, 'Content-Length: ' + IntToStr(FDocument.Size));
+ if FMimeType <> '' then
+ FHeaders.Insert(0, 'Content-Type: ' + FMimeType);
+ end;
+ { setting User-agent }
+ if FUserAgent <> '' then
+ FHeaders.Insert(0, 'User-Agent: ' + FUserAgent);
+ { setting Ranges }
+ if (FRangeStart > 0) or (FRangeEnd > 0) then
+ begin
+ if FRangeEnd >= FRangeStart then
+ FHeaders.Insert(0, 'Range: bytes=' + IntToStr(FRangeStart) + '-' + IntToStr(FRangeEnd))
+ else
+ FHeaders.Insert(0, 'Range: bytes=' + IntToStr(FRangeStart) + '-');
+ end;
+ { setting Cookies }
+ s := '';
+ for n := 0 to FCookies.Count - 1 do
+ begin
+ if s <> '' then
+ s := s + '; ';
+ s := s + FCookies[n];
+ end;
+ if s <> '' then
+ FHeaders.Insert(0, 'Cookie: ' + s);
+ { setting KeepAlives }
+ pp := '';
+ if UsingProxy then
+ pp := 'Proxy-';
+ if FKeepAlive then
+ begin
+ FHeaders.Insert(0, pp + 'Connection: keep-alive');
+ FHeaders.Insert(0, 'Keep-Alive: ' + IntToStr(FKeepAliveTimeout));
+ end
+ else
+ FHeaders.Insert(0, pp + 'Connection: close');
+ { set target servers/proxy, authorizations, etc... }
+ if User <> '' then
+ FHeaders.Insert(0, 'Authorization: Basic ' + EncodeBase64(User + ':' + Pass));
+ if UsingProxy and (FProxyUser <> '') then
+ FHeaders.Insert(0, 'Proxy-Authorization: Basic ' +
+ EncodeBase64(FProxyUser + ':' + FProxyPass));
+ if isIP6(Host) then
+ s := '[' + Host + ']'
+ else
+ s := Host;
+ if FAddPortNumberToHost and (Port <> '80') then
+ FHeaders.Insert(0, 'Host: ' + s + ':' + Port)
+ else
+ FHeaders.Insert(0, 'Host: ' + s);
+ if UsingProxy then
+ URI := Prot + '://' + s + ':' + Port + URI;
+ if URI = '/*' then
+ URI := '*';
+ if FProtocol = '0.9' then
+ FHeaders.Insert(0, UpperCase(Method) + ' ' + URI)
+ else
+ FHeaders.Insert(0, UpperCase(Method) + ' ' + URI + ' HTTP/' + FProtocol);
+ if UsingProxy then
+ begin
+ FTargetHost := FProxyHost;
+ FTargetPort := FProxyPort;
+ end
+ else
+ begin
+ FTargetHost := Host;
+ FTargetPort := Port;
+ end;
+ if FHeaders[FHeaders.Count - 1] <> '' then
+ FHeaders.Add('');
+
+ { connect }
+ if not InternalConnect(UpperCase(Prot) = 'HTTPS') then
+ begin
+ FAliveHost := '';
+ FAlivePort := '';
+ Exit;
+ end;
+
+ { reading Status }
+ FDocument.Position := 0;
+ Status100Error := '';
+ if status100 then
+ begin
+ { send Headers }
+ FSock.SendString(PrepareHeaders);
+ if FSock.LastError <> 0 then
+ Exit;
+ repeat
+ s := FSock.RecvString(FTimeout);
+ if s <> '' then
+ Break;
+ until FSock.LastError <> 0;
+ DecodeStatus(s);
+ Status100Error := s;
+ repeat
+ s := FSock.recvstring(FTimeout);
+ if s = '' then
+ Break;
+ until FSock.LastError <> 0;
+ if (FResultCode >= 100) and (FResultCode < 200) then
+ begin
+ { we can upload content }
+ Status100Error := '';
+ FUploadSize := FDocument.Size;
+ FSock.SendBuffer(FDocument.Memory, FDocument.Size);
+ end;
+ end
+ else
+ { upload content }
+ if sending then
+ begin
+ if FDocument.Size >= c64k then
+ begin
+ FSock.SendString(PrepareHeaders);
+ FUploadSize := FDocument.Size;
+ FSock.SendBuffer(FDocument.Memory, FDocument.Size);
+ end
+ else
+ begin
+ s := PrepareHeaders + ReadStrFromStream(FDocument, FDocument.Size);
+ FUploadSize := Length(s);
+ FSock.SendString(s);
+ end;
+ end
+ else
+ begin
+ { we not need to upload document, send headers only }
+ FSock.SendString(PrepareHeaders);
+ end;
+
+ if FSock.LastError <> 0 then
+ Exit;
+
+ Clear;
+ Size := -1;
+ FTransferEncoding := TE_UNKNOWN;
+
+ { read status }
+ if Status100Error = '' then
+ begin
+ repeat
+ repeat
+ s := FSock.RecvString(FTimeout);
+ if s <> '' then
+ Break;
+ until FSock.LastError <> 0;
+ if Pos('HTTP/', UpperCase(s)) = 1 then
+ begin
+ FHeaders.Add(s);
+ DecodeStatus(s);
+ end
+ else
+ begin
+ { old HTTP 0.9 and some buggy servers not send result }
+ s := s + CRLF;
+ WriteStrToStream(FDocument, s);
+ FResultCode := 0;
+ end;
+ until (FSock.LastError <> 0) or (FResultCode <> 100);
+ end
+ else
+ FHeaders.Add(Status100Error);
+
+ { if need receive headers, receive and parse it }
+ ToClose := FProtocol <> '1.1';
+ if FHeaders.Count > 0 then
+ begin
+ l := TStringList.Create;
+ try
+ repeat
+ s := FSock.RecvString(FTimeout);
+ l.Add(s);
+ if s = '' then
+ Break;
+ until FSock.LastError <> 0;
+ x := 0;
+ while l.Count > x do
+ begin
+ s := NormalizeHeader(l, x);
+ FHeaders.Add(s);
+ su := UpperCase(s);
+ if Pos('CONTENT-LENGTH:', su) = 1 then
+ begin
+ Size := StrToIntDef(Trim(SeparateRight(s, ' ')), -1);
+ if (Size <> -1) and (FTransferEncoding = TE_UNKNOWN) then
+ FTransferEncoding := TE_IDENTITY;
+ end;
+ if Pos('CONTENT-TYPE:', su) = 1 then
+ FMimeType := Trim(SeparateRight(s, ' '));
+ if Pos('TRANSFER-ENCODING:', su) = 1 then
+ begin
+ s := Trim(SeparateRight(su, ' '));
+ if Pos('CHUNKED', s) > 0 then
+ FTransferEncoding := TE_CHUNKED;
+ end;
+ if UsingProxy then
+ begin
+ if Pos('PROXY-CONNECTION:', su) = 1 then
+ if Pos('CLOSE', su) > 0 then
+ ToClose := True;
+ end
+ else
+ begin
+ if Pos('CONNECTION:', su) = 1 then
+ if Pos('CLOSE', su) > 0 then
+ ToClose := True;
+ end;
+ end;
+ finally
+ l.free;
+ end;
+ end;
+
+ Result := FSock.LastError = 0;
+ if not Result then
+ Exit;
+
+ {if need receive response body, read it}
+ Receiving := Method <> 'HEAD';
+ Receiving := Receiving and (FResultCode <> 204);
+ Receiving := Receiving and (FResultCode <> 304);
+ if Receiving then
+ case FTransferEncoding of
+ TE_UNKNOWN:
+ Result := ReadUnknown;
+ TE_IDENTITY:
+ Result := ReadIdentity(Size);
+ TE_CHUNKED:
+ Result := ReadChunked;
+ end;
+
+ FDocument.Seek(0, soFromBeginning);
+ if ToClose then
+ begin
+ FSock.CloseSocket;
+ FAliveHost := '';
+ FAlivePort := '';
+ end;
+ ParseCookies;
+end;
+
+function THTTPSend.ReadUnknown: Boolean;
+var
+ s: string;
+begin
+ Result := false;
+ repeat
+ s := FSock.RecvPacket(FTimeout);
+ if FSock.LastError = 0 then
+ WriteStrToStream(FDocument, s);
+ until FSock.LastError <> 0;
+ if FSock.LastError = WSAECONNRESET then
+ begin
+ Result := true;
+ FSock.ResetLastError;
+ end;
+end;
+
+function THTTPSend.ReadIdentity(Size: Integer): Boolean;
+begin
+ if Size > 0 then
+ begin
+ FDownloadSize := Size;
+ FSock.RecvStreamSize(FDocument, FTimeout, Size);
+ FDocument.Position := FDocument.Size;
+ Result := FSock.LastError = 0;
+ end
+ else
+ Result := true;
+end;
+
+function THTTPSend.ReadChunked: Boolean;
+var
+ s: string;
+ Size: Integer;
+begin
+ repeat
+ repeat
+ s := FSock.RecvString(FTimeout);
+ until (s <> '') or (FSock.LastError <> 0);
+ if FSock.LastError <> 0 then
+ Break;
+ s := Trim(SeparateLeft(s, ' '));
+ s := Trim(SeparateLeft(s, ';'));
+ Size := StrToIntDef('$' + s, 0);
+ if Size = 0 then
+ Break;
+ if not ReadIdentity(Size) then
+ break;
+ until False;
+ Result := FSock.LastError = 0;
+end;
+
+procedure THTTPSend.ParseCookies;
+var
+ n: integer;
+ s: string;
+ sn, sv: string;
+begin
+ for n := 0 to FHeaders.Count - 1 do
+ if Pos('set-cookie:', lowercase(FHeaders[n])) = 1 then
+ begin
+ s := SeparateRight(FHeaders[n], ':');
+ s := trim(SeparateLeft(s, ';'));
+ sn := trim(SeparateLeft(s, '='));
+ sv := trim(SeparateRight(s, '='));
+ FCookies.Values[sn] := sv;
+ end;
+end;
+
+procedure THTTPSend.Abort;
+begin
+ FSock.StopFlag := True;
+end;
+
+{==============================================================================}
+
+function HttpGetText(const URL: string; const Response: TStrings): Boolean;
+var
+ HTTP: THTTPSend;
+begin
+ HTTP := THTTPSend.Create;
+ try
+ Result := HTTP.HTTPMethod('GET', URL);
+ if Result then
+ Response.LoadFromStream(HTTP.Document);
+ finally
+ HTTP.Free;
+ end;
+end;
+
+function HttpGetBinary(const URL: string; const Response: TStream): Boolean;
+var
+ HTTP: THTTPSend;
+begin
+ HTTP := THTTPSend.Create;
+ try
+ Result := HTTP.HTTPMethod('GET', URL);
+ if Result then
+ begin
+ Response.Seek(0, soFromBeginning);
+ Response.CopyFrom(HTTP.Document, 0);
+ end;
+ finally
+ HTTP.Free;
+ end;
+end;
+
+function HttpPostBinary(const URL: string; const Data: TStream): Boolean;
+var
+ HTTP: THTTPSend;
+begin
+ HTTP := THTTPSend.Create;
+ try
+ HTTP.Document.CopyFrom(Data, 0);
+ HTTP.MimeType := 'Application/octet-stream';
+ Result := HTTP.HTTPMethod('POST', URL);
+ Data.Size := 0;
+ if Result then
+ begin
+ Data.Seek(0, soFromBeginning);
+ Data.CopyFrom(HTTP.Document, 0);
+ end;
+ finally
+ HTTP.Free;
+ end;
+end;
+
+function HttpPostURL(const URL, URLData: string; const Data: TStream): Boolean;
+var
+ HTTP: THTTPSend;
+begin
+ HTTP := THTTPSend.Create;
+ try
+ WriteStrToStream(HTTP.Document, URLData);
+ HTTP.MimeType := 'application/x-www-form-urlencoded';
+ Result := HTTP.HTTPMethod('POST', URL);
+ if Result then
+ Data.CopyFrom(HTTP.Document, 0);
+ finally
+ HTTP.Free;
+ end;
+end;
+
+function HttpPostFile(const URL, FieldName, FileName: string;
+ const Data: TStream; const ResultData: TStrings): Boolean;
+var
+ HTTP: THTTPSend;
+ Bound, s: string;
+begin
+ Bound := IntToHex(Random(MaxInt), 8) + '_Synapse_boundary';
+ HTTP := THTTPSend.Create;
+ try
+ s := '--' + Bound + CRLF;
+ s := s + 'content-disposition: form-data; name="' + FieldName + '";';
+ s := s + ' filename="' + FileName +'"' + CRLF;
+ s := s + 'Content-Type: Application/octet-string' + CRLF + CRLF;
+ WriteStrToStream(HTTP.Document, s);
+ HTTP.Document.CopyFrom(Data, 0);
+ s := CRLF + '--' + Bound + '--' + CRLF;
+ WriteStrToStream(HTTP.Document, s);
+ HTTP.MimeType := 'multipart/form-data; boundary=' + Bound;
+ Result := HTTP.HTTPMethod('POST', URL);
+ if Result then
+ ResultData.LoadFromStream(HTTP.Document);
+ finally
+ HTTP.Free;
+ end;
+end;
+
+end.
diff --git a/branches/script-component/Units/Synapse/imapsend.pas b/branches/script-component/Units/Synapse/imapsend.pas
new file mode 100644
index 0000000..1e91b08
--- /dev/null
+++ b/branches/script-component/Units/Synapse/imapsend.pas
@@ -0,0 +1,863 @@
+{==============================================================================|
+| Project : Ararat Synapse | 002.005.001 |
+|==============================================================================|
+| Content: IMAP4rev1 client |
+|==============================================================================|
+| Copyright (c)1999-2004, Lukas Gebauer |
+| All rights reserved. |
+| |
+| Redistribution and use in source and binary forms, with or without |
+| modification, are permitted provided that the following conditions are met: |
+| |
+| Redistributions of source code must retain the above copyright notice, this |
+| list of conditions and the following disclaimer. |
+| |
+| Redistributions in binary form must reproduce the above copyright notice, |
+| this list of conditions and the following disclaimer in the documentation |
+| and/or other materials provided with the distribution. |
+| |
+| Neither the name of Lukas Gebauer nor the names of its contributors may |
+| be used to endorse or promote products derived from this software without |
+| specific prior written permission. |
+| |
+| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
+| AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
+| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
+| ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR |
+| ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
+| DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
+| SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
+| CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
+| LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
+| OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
+| DAMAGE. |
+|==============================================================================|
+| The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).|
+| Portions created by Lukas Gebauer are Copyright (c)2001-2004. |
+| All Rights Reserved. |
+|==============================================================================|
+| Contributor(s): |
+|==============================================================================|
+| History: see HISTORY.HTM from distribution package |
+| (Found at URL: http://www.ararat.cz/synapse/) |
+|==============================================================================}
+
+{:@abstract(IMAP4 rev1 protocol client)
+
+Used RFC: RFC-2060, RFC-2595
+}
+
+{$IFDEF FPC}
+ {$MODE DELPHI}
+{$ENDIF}
+{$H+}
+
+unit imapsend;
+
+interface
+
+uses
+ SysUtils, Classes,
+ blcksock, synautil;
+
+const
+ cIMAPProtocol = '143';
+
+type
+ {:@abstract(Implementation of IMAP4 protocol.)
+ Note: Are you missing properties for setting Username and Password? Look to
+ parent @link(TSynaClient) object!
+
+ Are you missing properties for specify server address and port? Look to
+ parent @link(TSynaClient) too!}
+ TIMAPSend = class(TSynaClient)
+ protected
+ FSock: TTCPBlockSocket;
+ FTagCommand: integer;
+ FResultString: string;
+ FFullResult: TStringList;
+ FIMAPcap: TStringList;
+ FAuthDone: Boolean;
+ FSelectedFolder: string;
+ FSelectedCount: integer;
+ FSelectedRecent: integer;
+ FSelectedUIDvalidity: integer;
+ FUID: Boolean;
+ FAutoTLS: Boolean;
+ FFullSSL: Boolean;
+ function ReadResult: string;
+ function AuthLogin: Boolean;
+ function Connect: Boolean;
+ procedure ParseMess(Value:TStrings);
+ procedure ParseFolderList(Value:TStrings);
+ procedure ParseSelect;
+ procedure ParseSearch(Value:TStrings);
+ procedure ProcessLiterals;
+ public
+ constructor Create;
+ destructor Destroy; override;
+
+ {:By this function you can call any IMAP command. Result of this command is
+ in adequate properties.}
+ function IMAPcommand(Value: string): string;
+
+ {:By this function you can call any IMAP command what need upload any data.
+ Result of this command is in adequate properties.}
+ function IMAPuploadCommand(Value: string; const Data:TStrings): string;
+
+ {:Call CAPABILITY command and fill IMAPcap property by new values.}
+ function Capability: Boolean;
+
+ {:Connect to IMAP server and do login to this server. This command begin
+ session.}
+ function Login: Boolean;
+
+ {:Disconnect from IMAP server and terminate session session. If exists some
+ deleted and non-purged messages, these messages are not deleted!}
+ function Logout: Boolean;
+
+ {:Do NOOP. It is for prevent disconnect by timeout.}
+ function NoOp: Boolean;
+
+ {:Lists folder names. You may specify level of listing. If you specify
+ FromFolder as empty string, return is all folders in system.}
+ function List(FromFolder: string; const FolderList: TStrings): Boolean;
+
+ {:Lists folder names what match search criteria. You may specify level of
+ listing. If you specify FromFolder as empty string, return is all folders
+ in system.}
+ function ListSearch(FromFolder, Search: string; const FolderList: TStrings): Boolean;
+
+ {:Lists subscribed folder names. You may specify level of listing. If you
+ specify FromFolder as empty string, return is all subscribed folders in
+ system.}
+ function ListSubscribed(FromFolder: string; const FolderList: TStrings): Boolean;
+
+ {:Lists subscribed folder names what matching search criteria. You may
+ specify level of listing. If you specify FromFolder as empty string, return
+ is all subscribed folders in system.}
+ function ListSearchSubscribed(FromFolder, Search: string; const FolderList: TStrings): Boolean;
+
+ {:Create a new folder.}
+ function CreateFolder(FolderName: string): Boolean;
+
+ {:Delete a folder.}
+ function DeleteFolder(FolderName: string): Boolean;
+
+ {:Rename folder names.}
+ function RenameFolder(FolderName, NewFolderName: string): Boolean;
+
+ {:Subscribe folder.}
+ function SubscribeFolder(FolderName: string): Boolean;
+
+ {:Unsubscribe folder.}
+ function UnsubscribeFolder(FolderName: string): Boolean;
+
+ {:Select folder.}
+ function SelectFolder(FolderName: string): Boolean;
+
+ {:Select folder, but only for reading. Any changes are not allowed!}
+ function SelectROFolder(FolderName: string): Boolean;
+
+ {:Close a folder. (end of Selected state)}
+ function CloseFolder: Boolean;
+
+ {:Ask for given status of folder. I.e. if you specify as value 'UNSEEN',
+ result is number of unseen messages in folder. For another status
+ indentificator check IMAP documentation and documentation of your IMAP
+ server (each IMAP server can have their own statuses.)}
+ function StatusFolder(FolderName, Value: string): integer;
+
+ {:Hardly delete all messages marked as 'deleted' in current selected folder.}
+ function ExpungeFolder: Boolean;
+
+ {:Touch to folder. (use as update status of folder, etc.)}
+ function CheckFolder: Boolean;
+
+ {:Append given message to specified folder.}
+ function AppendMess(ToFolder: string; const Mess: TStrings): Boolean;
+
+ {:'Delete' message from current selected folder. It mark message as Deleted.
+ Real deleting will be done after sucessfull @link(CloseFolder) or
+ @link(ExpungeFolder)}
+ function DeleteMess(MessID: integer): boolean;
+
+ {:Get full message from specified message in selected folder.}
+ function FetchMess(MessID: integer; const Mess: TStrings): Boolean;
+
+ {:Get message headers only from specified message in selected folder.}
+ function FetchHeader(MessID: integer; const Headers: TStrings): Boolean;
+
+ {:Return message size of specified message from current selected folder.}
+ function MessageSize(MessID: integer): integer;
+
+ {:Copy message from current selected folder to another folder.}
+ function CopyMess(MessID: integer; ToFolder: string): Boolean;
+
+ {:Return message numbers from currently selected folder as result
+ of searching. Search criteria is very complex language (see to IMAP
+ specification) similar to SQL (but not same syntax!).}
+ function SearchMess(Criteria: string; const FoundMess: TStrings): Boolean;
+
+ {:Sets flags of message from current selected folder.}
+ function SetFlagsMess(MessID: integer; Flags: string): Boolean;
+
+ {:Gets flags of message from current selected folder.}
+ function GetFlagsMess(MessID: integer; var Flags: string): Boolean;
+
+ {:Add flags to message's flags.}
+ function AddFlagsMess(MessID: integer; Flags: string): Boolean;
+
+ {:Remove flags from message's flags.}
+ function DelFlagsMess(MessID: integer; Flags: string): Boolean;
+
+ {:Call STARTTLS command for upgrade connection to SSL/TLS mode.}
+ function StartTLS: Boolean;
+
+ {:return UID of requested message ID.}
+ function GetUID(MessID: integer; var UID : Integer): Boolean;
+
+ {:Try to find given capabily in capabilty string returned from IMAP server.}
+ function FindCap(const Value: string): string;
+ published
+ {:Status line with result of last operation.}
+ property ResultString: string read FResultString;
+
+ {:Full result of last IMAP operation.}
+ property FullResult: TStringList read FFullResult;
+
+ {:List of server capabilites.}
+ property IMAPcap: TStringList read FIMAPcap;
+
+ {:Authorization is successful done.}
+ property AuthDone: Boolean read FAuthDone;
+
+ {:Turn on or off usage of UID (unicate identificator) of messages instead
+ only sequence numbers.}
+ property UID: Boolean read FUID Write FUID;
+
+ {:Name of currently selected folder.}
+ property SelectedFolder: string read FSelectedFolder;
+
+ {:Count of messages in currently selected folder.}
+ property SelectedCount: integer read FSelectedCount;
+
+ {:Count of not-visited messages in currently selected folder.}
+ property SelectedRecent: integer read FSelectedRecent;
+
+ {:This number with name of folder is unique indentificator of folder.
+ (If someone delete folder and next create new folder with exactly same name
+ of folder, this number is must be different!)}
+ property SelectedUIDvalidity: integer read FSelectedUIDvalidity;
+
+ {:If is set to true, then upgrade to SSL/TLS mode if remote server support it.}
+ property AutoTLS: Boolean read FAutoTLS Write FAutoTLS;
+
+ {:SSL/TLS mode is used from first contact to server. Servers with full
+ SSL/TLS mode usualy using non-standard TCP port!}
+ property FullSSL: Boolean read FFullSSL Write FFullSSL;
+
+ {:Socket object used for TCP/IP operation. Good for seting OnStatus hook, etc.}
+ property Sock: TTCPBlockSocket read FSock;
+ end;
+
+implementation
+
+constructor TIMAPSend.Create;
+begin
+ inherited Create;
+ FFullResult := TStringList.Create;
+ FIMAPcap := TStringList.Create;
+ FSock := TTCPBlockSocket.Create;
+ FSock.ConvertLineEnd := True;
+ FSock.SizeRecvBuffer := 32768;
+ FSock.SizeSendBuffer := 32768;
+ FTimeout := 60000;
+ FTargetPort := cIMAPProtocol;
+ FTagCommand := 0;
+ FSelectedFolder := '';
+ FSelectedCount := 0;
+ FSelectedRecent := 0;
+ FSelectedUIDvalidity := 0;
+ FUID := False;
+ FAutoTLS := False;
+ FFullSSL := False;
+end;
+
+destructor TIMAPSend.Destroy;
+begin
+ FSock.Free;
+ FIMAPcap.Free;
+ FFullResult.Free;
+ inherited Destroy;
+end;
+
+
+function TIMAPSend.ReadResult: string;
+var
+ s: string;
+ x, l: integer;
+begin
+ Result := '';
+ FFullResult.Clear;
+ FResultString := '';
+ repeat
+ s := FSock.RecvString(FTimeout);
+ if Pos('S' + IntToStr(FTagCommand) + ' ', s) = 1 then
+ begin
+ FResultString := s;
+ break;
+ end
+ else
+ FFullResult.Add(s);
+ if (s <> '') and (s[Length(s)]='}') then
+ begin
+ s := Copy(s, 1, Length(s) - 1);
+ x := RPos('{', s);
+ s := Copy(s, x + 1, Length(s) - x);
+ l := StrToIntDef(s, -1);
+ if l <> -1 then
+ begin
+ s := FSock.RecvBufferStr(l, FTimeout);
+ FFullResult.Add(s);
+ end;
+ end;
+ until FSock.LastError <> 0;
+ s := Trim(separateright(FResultString, ' '));
+ Result:=uppercase(Trim(separateleft(s, ' ')));
+end;
+
+procedure TIMAPSend.ProcessLiterals;
+var
+ l: TStringList;
+ n, x: integer;
+ b: integer;
+ s: string;
+begin
+ l := TStringList.Create;
+ try
+ l.Assign(FFullResult);
+ FFullResult.Clear;
+ b := 0;
+ for n := 0 to l.Count - 1 do
+ begin
+ s := l[n];
+ if b > 0 then
+ begin
+ FFullResult[FFullresult.Count - 1] :=
+ FFullResult[FFullresult.Count - 1] + s;
+ inc(b);
+ if b > 2 then
+ b := 0;
+ end
+ else
+ begin
+ if (s <> '') and (s[Length(s)]='}') then
+ begin
+ x := RPos('{', s);
+ Delete(s, x, Length(s) - x + 1);
+ b := 1;
+ end
+ else
+ b := 0;
+ FFullResult.Add(s);
+ end;
+ end;
+ finally
+ l.Free;
+ end;
+end;
+
+function TIMAPSend.IMAPcommand(Value: string): string;
+begin
+ Inc(FTagCommand);
+ FSock.SendString('S' + IntToStr(FTagCommand) + ' ' + Value + CRLF);
+ Result := ReadResult;
+end;
+
+function TIMAPSend.IMAPuploadCommand(Value: string; const Data:TStrings): string;
+var
+ l: integer;
+begin
+ Inc(FTagCommand);
+ l := Length(Data.Text);
+ FSock.SendString('S' + IntToStr(FTagCommand) + ' ' + Value + ' {'+ IntToStr(l) + '}' + CRLF);
+ FSock.RecvString(FTimeout);
+ FSock.SendString(Data.Text + CRLF);
+ Result := ReadResult;
+end;
+
+procedure TIMAPSend.ParseMess(Value:TStrings);
+var
+ n: integer;
+begin
+ Value.Clear;
+ for n := 0 to FFullResult.Count - 2 do
+ if FFullResult[n][Length(FFullResult[n])] = '}' then
+ begin
+ Value.Text := FFullResult[n + 1];
+ Break;
+ end;
+end;
+
+procedure TIMAPSend.ParseFolderList(Value:TStrings);
+var
+ n, x: integer;
+ s: string;
+begin
+ ProcessLiterals;
+ Value.Clear;
+ for n := 0 to FFullResult.Count - 1 do
+ begin
+ s := FFullResult[n];
+ if (s <> '') and (Pos('\NOSELECT', UpperCase(s)) = 0) then
+ begin
+ if s[Length(s)] = '"' then
+ begin
+ Delete(s, Length(s), 1);
+ x := RPos('"', s);
+ end
+ else
+ x := RPos(' ', s);
+ if (x > 0) then
+ Value.Add(Copy(s, x + 1, Length(s) - x));
+ end;
+ end;
+end;
+
+procedure TIMAPSend.ParseSelect;
+var
+ n: integer;
+ s, t: string;
+begin
+ ProcessLiterals;
+ FSelectedCount := 0;
+ FSelectedRecent := 0;
+ FSelectedUIDvalidity := 0;
+ for n := 0 to FFullResult.Count - 1 do
+ begin
+ s := uppercase(FFullResult[n]);
+ if Pos(' EXISTS', s) > 0 then
+ begin
+ t := Trim(separateleft(s, ' EXISTS'));
+ t := Trim(separateright(t, '* '));
+ FSelectedCount := StrToIntDef(t, 0);
+ end;
+ if Pos(' RECENT', s) > 0 then
+ begin
+ t := Trim(separateleft(s, ' RECENT'));
+ t := Trim(separateright(t, '* '));
+ FSelectedRecent := StrToIntDef(t, 0);
+ end;
+ if Pos('UIDVALIDITY', s) > 0 then
+ begin
+ t := Trim(separateright(s, 'UIDVALIDITY '));
+ t := Trim(separateleft(t, ']'));
+ FSelectedUIDvalidity := StrToIntDef(t, 0);
+ end;
+ end;
+end;
+
+procedure TIMAPSend.ParseSearch(Value:TStrings);
+var
+ n: integer;
+ s: string;
+begin
+ ProcessLiterals;
+ Value.Clear;
+ for n := 0 to FFullResult.Count - 1 do
+ begin
+ s := uppercase(FFullResult[n]);
+ if Pos('* SEARCH', s) = 1 then
+ begin
+ s := Trim(SeparateRight(s, '* SEARCH'));
+ while s <> '' do
+ Value.Add(Fetch(s, ' '));
+ end;
+ end;
+end;
+
+function TIMAPSend.FindCap(const Value: string): string;
+var
+ n: Integer;
+ s: string;
+begin
+ s := UpperCase(Value);
+ Result := '';
+ for n := 0 to FIMAPcap.Count - 1 do
+ if Pos(s, UpperCase(FIMAPcap[n])) = 1 then
+ begin
+ Result := FIMAPcap[n];
+ Break;
+ end;
+end;
+
+function TIMAPSend.AuthLogin: Boolean;
+begin
+ Result := IMAPcommand('LOGIN "' + FUsername + '" "' + FPassword + '"') = 'OK';
+end;
+
+function TIMAPSend.Connect: Boolean;
+begin
+ FSock.CloseSocket;
+ FSock.Bind(FIPInterface, cAnyPort);
+ if FSock.LastError = 0 then
+ FSock.Connect(FTargetHost, FTargetPort);
+ if FSock.LastError = 0 then
+ if FFullSSL then
+ FSock.SSLDoConnect;
+ Result := FSock.LastError = 0;
+end;
+
+function TIMAPSend.Capability: Boolean;
+var
+ n: Integer;
+ s, t: string;
+begin
+ Result := False;
+ FIMAPcap.Clear;
+ s := IMAPcommand('CAPABILITY');
+ if s = 'OK' then
+ begin
+ ProcessLiterals;
+ for n := 0 to FFullResult.Count - 1 do
+ if Pos('* CAPABILITY ', FFullResult[n]) = 1 then
+ begin
+ s := Trim(SeparateRight(FFullResult[n], '* CAPABILITY '));
+ while not (s = '') do
+ begin
+ t := Trim(separateleft(s, ' '));
+ s := Trim(separateright(s, ' '));
+ if s = t then
+ s := '';
+ FIMAPcap.Add(t);
+ end;
+ end;
+ Result := True;
+ end;
+end;
+
+function TIMAPSend.Login: Boolean;
+var
+ s: string;
+begin
+ FSelectedFolder := '';
+ FSelectedCount := 0;
+ FSelectedRecent := 0;
+ FSelectedUIDvalidity := 0;
+ Result := False;
+ FAuthDone := False;
+ if not Connect then
+ Exit;
+ s := FSock.RecvString(FTimeout);
+ if Pos('* PREAUTH', s) = 1 then
+ FAuthDone := True
+ else
+ if Pos('* OK', s) = 1 then
+ FAuthDone := False
+ else
+ Exit;
+ if Capability then
+ begin
+ if Findcap('IMAP4rev1') = '' then
+ Exit;
+ if FAutoTLS and (Findcap('STARTTLS') <> '') then
+ if StartTLS then
+ Capability;
+ end;
+ Result := AuthLogin;
+end;
+
+function TIMAPSend.Logout: Boolean;
+begin
+ Result := IMAPcommand('LOGOUT') = 'OK';
+ FSelectedFolder := '';
+ FSock.CloseSocket;
+end;
+
+function TIMAPSend.NoOp: Boolean;
+begin
+ Result := IMAPcommand('NOOP') = 'OK';
+end;
+
+function TIMAPSend.List(FromFolder: string; const FolderList: TStrings): Boolean;
+begin
+ Result := IMAPcommand('LIST "' + FromFolder + '" *') = 'OK';
+ ParseFolderList(FolderList);
+end;
+
+function TIMAPSend.ListSearch(FromFolder, Search: string; const FolderList: TStrings): Boolean;
+begin
+ Result := IMAPcommand('LIST "' + FromFolder + '" "' + Search +'"') = 'OK';
+ ParseFolderList(FolderList);
+end;
+
+function TIMAPSend.ListSubscribed(FromFolder: string; const FolderList: TStrings): Boolean;
+begin
+ Result := IMAPcommand('LSUB "' + FromFolder + '" *') = 'OK';
+ ParseFolderList(FolderList);
+end;
+
+function TIMAPSend.ListSearchSubscribed(FromFolder, Search: string; const FolderList: TStrings): Boolean;
+begin
+ Result := IMAPcommand('LSUB "' + FromFolder + '" "' + Search +'"') = 'OK';
+ ParseFolderList(FolderList);
+end;
+
+function TIMAPSend.CreateFolder(FolderName: string): Boolean;
+begin
+ Result := IMAPcommand('CREATE "' + FolderName + '"') = 'OK';
+end;
+
+function TIMAPSend.DeleteFolder(FolderName: string): Boolean;
+begin
+ Result := IMAPcommand('DELETE "' + FolderName + '"') = 'OK';
+end;
+
+function TIMAPSend.RenameFolder(FolderName, NewFolderName: string): Boolean;
+begin
+ Result := IMAPcommand('RENAME "' + FolderName + '" "' + NewFolderName + '"') = 'OK';
+end;
+
+function TIMAPSend.SubscribeFolder(FolderName: string): Boolean;
+begin
+ Result := IMAPcommand('SUBSCRIBE "' + FolderName + '"') = 'OK';
+end;
+
+function TIMAPSend.UnsubscribeFolder(FolderName: string): Boolean;
+begin
+ Result := IMAPcommand('UNSUBSCRIBE "' + FolderName + '"') = 'OK';
+end;
+
+function TIMAPSend.SelectFolder(FolderName: string): Boolean;
+begin
+ Result := IMAPcommand('SELECT "' + FolderName + '"') = 'OK';
+ FSelectedFolder := FolderName;
+ ParseSelect;
+end;
+
+function TIMAPSend.SelectROFolder(FolderName: string): Boolean;
+begin
+ Result := IMAPcommand('EXAMINE "' + FolderName + '"') = 'OK';
+ FSelectedFolder := FolderName;
+ ParseSelect;
+end;
+
+function TIMAPSend.CloseFolder: Boolean;
+begin
+ Result := IMAPcommand('CLOSE') = 'OK';
+ FSelectedFolder := '';
+end;
+
+function TIMAPSend.StatusFolder(FolderName, Value: string): integer;
+var
+ n: integer;
+ s, t: string;
+begin
+ Result := -1;
+ Value := Uppercase(Value);
+ if IMAPcommand('STATUS "' + FolderName + '" (' + Value + ')' ) = 'OK' then
+ begin
+ ProcessLiterals;
+ for n := 0 to FFullResult.Count - 1 do
+ begin
+ s := FFullResult[n];
+// s := UpperCase(FFullResult[n]);
+ if (Pos('* ', s) = 1) and (Pos(FolderName, s) >= 1) and (Pos(Value, s) > 0 ) then
+ begin
+ t := SeparateRight(s, Value);
+ t := SeparateLeft(t, ')');
+ t := trim(t);
+ Result := StrToIntDef(t, -1);
+ Break;
+ end;
+ end;
+ end;
+end;
+
+function TIMAPSend.ExpungeFolder: Boolean;
+begin
+ Result := IMAPcommand('EXPUNGE') = 'OK';
+end;
+
+function TIMAPSend.CheckFolder: Boolean;
+begin
+ Result := IMAPcommand('CHECK') = 'OK';
+end;
+
+function TIMAPSend.AppendMess(ToFolder: string; const Mess: TStrings): Boolean;
+begin
+ Result := IMAPuploadCommand('APPEND "' + ToFolder + '"', Mess) = 'OK';
+end;
+
+function TIMAPSend.DeleteMess(MessID: integer): boolean;
+var
+ s: string;
+begin
+ s := 'STORE ' + IntToStr(MessID) + ' +FLAGS.SILENT (\Deleted)';
+ if FUID then
+ s := 'UID ' + s;
+ Result := IMAPcommand(s) = 'OK';
+end;
+
+function TIMAPSend.FetchMess(MessID: integer; const Mess: TStrings): Boolean;
+var
+ s: string;
+begin
+ s := 'FETCH ' + IntToStr(MessID) + ' (RFC822)';
+ if FUID then
+ s := 'UID ' + s;
+ Result := IMAPcommand(s) = 'OK';
+ ParseMess(Mess);
+end;
+
+function TIMAPSend.FetchHeader(MessID: integer; const Headers: TStrings): Boolean;
+var
+ s: string;
+begin
+ s := 'FETCH ' + IntToStr(MessID) + ' (RFC822.HEADER)';
+ if FUID then
+ s := 'UID ' + s;
+ Result := IMAPcommand(s) = 'OK';
+ ParseMess(Headers);
+end;
+
+function TIMAPSend.MessageSize(MessID: integer): integer;
+var
+ n: integer;
+ s, t: string;
+begin
+ Result := -1;
+ s := 'FETCH ' + IntToStr(MessID) + ' (RFC822.SIZE)';
+ if FUID then
+ s := 'UID ' + s;
+ if IMAPcommand(s) = 'OK' then
+ begin
+ ProcessLiterals;
+ for n := 0 to FFullResult.Count - 1 do
+ begin
+ s := UpperCase(FFullResult[n]);
+ if (Pos('* ', s) = 1) and (Pos('RFC822.SIZE', s) > 0 ) then
+ begin
+ t := SeparateRight(s, 'RFC822.SIZE ');
+ t := Trim(SeparateLeft(t, ')'));
+ t := Trim(SeparateLeft(t, ' '));
+ Result := StrToIntDef(t, -1);
+ Break;
+ end;
+ end;
+ end;
+end;
+
+function TIMAPSend.CopyMess(MessID: integer; ToFolder: string): Boolean;
+var
+ s: string;
+begin
+ s := 'COPY ' + IntToStr(MessID) + ' "' + ToFolder + '"';
+ if FUID then
+ s := 'UID ' + s;
+ Result := IMAPcommand(s) = 'OK';
+end;
+
+function TIMAPSend.SearchMess(Criteria: string; const FoundMess: TStrings): Boolean;
+var
+ s: string;
+begin
+ s := 'SEARCH ' + Criteria;
+ if FUID then
+ s := 'UID ' + s;
+ Result := IMAPcommand(s) = 'OK';
+ ParseSearch(FoundMess);
+end;
+
+function TIMAPSend.SetFlagsMess(MessID: integer; Flags: string): Boolean;
+var
+ s: string;
+begin
+ s := 'STORE ' + IntToStr(MessID) + ' FLAGS.SILENT (' + Flags + ')';
+ if FUID then
+ s := 'UID ' + s;
+ Result := IMAPcommand(s) = 'OK';
+end;
+
+function TIMAPSend.AddFlagsMess(MessID: integer; Flags: string): Boolean;
+var
+ s: string;
+begin
+ s := 'STORE ' + IntToStr(MessID) + ' +FLAGS.SILENT (' + Flags + ')';
+ if FUID then
+ s := 'UID ' + s;
+ Result := IMAPcommand(s) = 'OK';
+end;
+
+function TIMAPSend.DelFlagsMess(MessID: integer; Flags: string): Boolean;
+var
+ s: string;
+begin
+ s := 'STORE ' + IntToStr(MessID) + ' -FLAGS.SILENT (' + Flags + ')';
+ if FUID then
+ s := 'UID ' + s;
+ Result := IMAPcommand(s) = 'OK';
+end;
+
+function TIMAPSend.GetFlagsMess(MessID: integer; var Flags: string): Boolean;
+var
+ s: string;
+ n: integer;
+begin
+ Flags := '';
+ s := 'FETCH ' + IntToStr(MessID) + ' (FLAGS)';
+ if FUID then
+ s := 'UID ' + s;
+ Result := IMAPcommand(s) = 'OK';
+ ProcessLiterals;
+ for n := 0 to FFullResult.Count - 1 do
+ begin
+ s := uppercase(FFullResult[n]);
+ if (Pos('* ', s) = 1) and (Pos('FLAGS', s) > 0 ) then
+ begin
+ s := SeparateRight(s, 'FLAGS');
+ s := Separateright(s, '(');
+ Flags := Trim(SeparateLeft(s, ')'));
+ end;
+ end;
+end;
+
+function TIMAPSend.StartTLS: Boolean;
+begin
+ Result := False;
+ if FindCap('STARTTLS') <> '' then
+ begin
+ if IMAPcommand('STARTTLS') = 'OK' then
+ begin
+ Fsock.SSLDoConnect;
+ Result := FSock.LastError = 0;
+ end;
+ end;
+end;
+
+//Paul Buskermolen
+function TIMAPSend.GetUID(MessID: integer; var UID : Integer): boolean;
+var
+ s, sUid: string;
+ n: integer;
+begin
+ sUID := '';
+ s := 'FETCH ' + IntToStr(MessID) + ' UID';
+ Result := IMAPcommand(s) = 'OK';
+ ProcessLiterals;
+ for n := 0 to FFullResult.Count - 1 do
+ begin
+ s := uppercase(FFullResult[n]);
+ if Pos('FETCH (UID', s) >= 1 then
+ begin
+ s := Separateright(s, '(UID ');
+ sUID := Trim(SeparateLeft(s, ')'));
+ end;
+ end;
+ UID := StrToIntDef(sUID, 0);
+end;
+
+{==============================================================================}
+
+end.
diff --git a/branches/script-component/Units/Synapse/ldapsend.pas b/branches/script-component/Units/Synapse/ldapsend.pas
new file mode 100644
index 0000000..1067d4a
--- /dev/null
+++ b/branches/script-component/Units/Synapse/ldapsend.pas
@@ -0,0 +1,1189 @@
+{==============================================================================|
+| Project : Ararat Synapse | 001.006.001 |
+|==============================================================================|
+| Content: LDAP client |
+|==============================================================================|
+| Copyright (c)1999-2009, Lukas Gebauer |
+| All rights reserved. |
+| |
+| Redistribution and use in source and binary forms, with or without |
+| modification, are permitted provided that the following conditions are met: |
+| |
+| Redistributions of source code must retain the above copyright notice, this |
+| list of conditions and the following disclaimer. |
+| |
+| Redistributions in binary form must reproduce the above copyright notice, |
+| this list of conditions and the following disclaimer in the documentation |
+| and/or other materials provided with the distribution. |
+| |
+| Neither the name of Lukas Gebauer nor the names of its contributors may |
+| be used to endorse or promote products derived from this software without |
+| specific prior written permission. |
+| |
+| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
+| AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
+| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
+| ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR |
+| ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
+| DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
+| SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
+| CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
+| LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
+| OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
+| DAMAGE. |
+|==============================================================================|
+| The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).|
+| Portions created by Lukas Gebauer are Copyright (c)2003-2009. |
+| All Rights Reserved. |
+|==============================================================================|
+| Contributor(s): |
+|==============================================================================|
+| History: see HISTORY.HTM from distribution package |
+| (Found at URL: http://www.ararat.cz/synapse/) |
+|==============================================================================}
+
+{:@abstract(LDAP client)
+
+Used RFC: RFC-2251, RFC-2254, RFC-2829, RFC-2830
+}
+
+{$IFDEF FPC}
+ {$MODE DELPHI}
+{$ENDIF}
+{$H+}
+
+unit ldapsend;
+
+interface
+
+uses
+ SysUtils, Classes,
+ blcksock, synautil, asn1util, synacode;
+
+const
+ cLDAPProtocol = '389';
+
+ LDAP_ASN1_BIND_REQUEST = $60;
+ LDAP_ASN1_BIND_RESPONSE = $61;
+ LDAP_ASN1_UNBIND_REQUEST = $42;
+ LDAP_ASN1_SEARCH_REQUEST = $63;
+ LDAP_ASN1_SEARCH_ENTRY = $64;
+ LDAP_ASN1_SEARCH_DONE = $65;
+ LDAP_ASN1_SEARCH_REFERENCE = $73;
+ LDAP_ASN1_MODIFY_REQUEST = $66;
+ LDAP_ASN1_MODIFY_RESPONSE = $67;
+ LDAP_ASN1_ADD_REQUEST = $68;
+ LDAP_ASN1_ADD_RESPONSE = $69;
+ LDAP_ASN1_DEL_REQUEST = $4A;
+ LDAP_ASN1_DEL_RESPONSE = $6B;
+ LDAP_ASN1_MODIFYDN_REQUEST = $6C;
+ LDAP_ASN1_MODIFYDN_RESPONSE = $6D;
+ LDAP_ASN1_COMPARE_REQUEST = $6E;
+ LDAP_ASN1_COMPARE_RESPONSE = $6F;
+ LDAP_ASN1_ABANDON_REQUEST = $70;
+ LDAP_ASN1_EXT_REQUEST = $77;
+ LDAP_ASN1_EXT_RESPONSE = $78;
+
+
+type
+
+ {:@abstract(LDAP attribute with list of their values)
+ This class holding name of LDAP attribute and list of their values. This is
+ descendant of TStringList class enhanced by some new properties.}
+ TLDAPAttribute = class(TStringList)
+ private
+ FAttributeName: AnsiString;
+ FIsBinary: Boolean;
+ protected
+ function Get(Index: integer): string; override;
+ procedure Put(Index: integer; const Value: string); override;
+ procedure SetAttributeName(Value: AnsiString);
+ published
+ {:Name of LDAP attribute.}
+ property AttributeName: AnsiString read FAttributeName Write SetAttributeName;
+ {:Return @true when attribute contains binary data.}
+ property IsBinary: Boolean read FIsBinary;
+ end;
+
+ {:@abstract(List of @link(TLDAPAttribute))
+ This object can hold list of TLDAPAttribute objects.}
+ TLDAPAttributeList = class(TObject)
+ private
+ FAttributeList: TList;
+ function GetAttribute(Index: integer): TLDAPAttribute;
+ public
+ constructor Create;
+ destructor Destroy; override;
+ {:Clear list.}
+ procedure Clear;
+ {:Return count of TLDAPAttribute objects in list.}
+ function Count: integer;
+ {:Add new TLDAPAttribute object to list.}
+ function Add: TLDAPAttribute;
+ {:Delete one TLDAPAttribute object from list.}
+ procedure Del(Index: integer);
+ {:Find and return attribute with requested name. Returns nil if not found.}
+ function Find(AttributeName: AnsiString): TLDAPAttribute;
+ {:List of TLDAPAttribute objects.}
+ property Items[Index: Integer]: TLDAPAttribute read GetAttribute; default;
+ end;
+
+ {:@abstract(LDAP result object)
+ This object can hold LDAP object. (their name and all their attributes with
+ values)}
+ TLDAPResult = class(TObject)
+ private
+ FObjectName: AnsiString;
+ FAttributes: TLDAPAttributeList;
+ public
+ constructor Create;
+ destructor Destroy; override;
+ published
+ {:Name of this LDAP object.}
+ property ObjectName: AnsiString read FObjectName write FObjectName;
+ {:Here is list of object attributes.}
+ property Attributes: TLDAPAttributeList read FAttributes;
+ end;
+
+ {:@abstract(List of LDAP result objects)
+ This object can hold list of LDAP objects. (for example result of LDAP SEARCH.)}
+ TLDAPResultList = class(TObject)
+ private
+ FResultList: TList;
+ function GetResult(Index: integer): TLDAPResult;
+ public
+ constructor Create;
+ destructor Destroy; override;
+ {:Clear all TLDAPResult objects in list.}
+ procedure Clear;
+ {:Return count of TLDAPResult objects in list.}
+ function Count: integer;
+ {:Create and add new TLDAPResult object to list.}
+ function Add: TLDAPResult;
+ {:List of TLDAPResult objects.}
+ property Items[Index: Integer]: TLDAPResult read GetResult; default;
+ end;
+
+ {:Define possible operations for LDAP MODIFY operations.}
+ TLDAPModifyOp = (
+ MO_Add,
+ MO_Delete,
+ MO_Replace
+ );
+
+ {:Specify possible values for search scope.}
+ TLDAPSearchScope = (
+ SS_BaseObject,
+ SS_SingleLevel,
+ SS_WholeSubtree
+ );
+
+ {:Specify possible values about alias dereferencing.}
+ TLDAPSearchAliases = (
+ SA_NeverDeref,
+ SA_InSearching,
+ SA_FindingBaseObj,
+ SA_Always
+ );
+
+ {:@abstract(Implementation of LDAP client)
+ (version 2 and 3)
+
+ Note: Are you missing properties for setting Username and Password? Look to
+ parent @link(TSynaClient) object!
+
+ Are you missing properties for specify server address and port? Look to
+ parent @link(TSynaClient) too!}
+ TLDAPSend = class(TSynaClient)
+ private
+ FSock: TTCPBlockSocket;
+ FResultCode: Integer;
+ FResultString: AnsiString;
+ FFullResult: AnsiString;
+ FAutoTLS: Boolean;
+ FFullSSL: Boolean;
+ FSeq: integer;
+ FResponseCode: integer;
+ FResponseDN: AnsiString;
+ FReferals: TStringList;
+ FVersion: integer;
+ FSearchScope: TLDAPSearchScope;
+ FSearchAliases: TLDAPSearchAliases;
+ FSearchSizeLimit: integer;
+ FSearchTimeLimit: integer;
+ FSearchResult: TLDAPResultList;
+ FExtName: AnsiString;
+ FExtValue: AnsiString;
+ function Connect: Boolean;
+ function BuildPacket(const Value: AnsiString): AnsiString;
+ function ReceiveResponse: AnsiString;
+ function DecodeResponse(const Value: AnsiString): AnsiString;
+ function LdapSasl(Value: AnsiString): AnsiString;
+ function TranslateFilter(Value: AnsiString): AnsiString;
+ function GetErrorString(Value: integer): AnsiString;
+ public
+ constructor Create;
+ destructor Destroy; override;
+
+ {:Try to connect to LDAP server and start secure channel, when it is required.}
+ function Login: Boolean;
+
+ {:Try to bind to LDAP server with @link(TSynaClient.Username) and
+ @link(TSynaClient.Password). If this is empty strings, then it do annonymous
+ Bind. When you not call Bind on LDAPv3, then is automaticly used anonymous
+ mode.
+
+ This method using plaintext transport of password! It is not secure!}
+ function Bind: Boolean;
+
+ {:Try to bind to LDAP server with @link(TSynaClient.Username) and
+ @link(TSynaClient.Password). If this is empty strings, then it do annonymous
+ Bind. When you not call Bind on LDAPv3, then is automaticly used anonymous
+ mode.
+
+ This method using SASL with DIGEST-MD5 method for secure transfer of your
+ password.}
+ function BindSasl: Boolean;
+
+ {:Close connection to LDAP server.}
+ function Logout: Boolean;
+
+ {:Modify content of LDAP attribute on this object.}
+ function Modify(obj: AnsiString; Op: TLDAPModifyOp; const Value: TLDAPAttribute): Boolean;
+
+ {:Add list of attributes to specified object.}
+ function Add(obj: AnsiString; const Value: TLDAPAttributeList): Boolean;
+
+ {:Delete this LDAP object from server.}
+ function Delete(obj: AnsiString): Boolean;
+
+ {:Modify object name of this LDAP object.}
+ function ModifyDN(obj, newRDN, newSuperior: AnsiString; DeleteoldRDN: Boolean): Boolean;
+
+ {:Try to compare Attribute value with this LDAP object.}
+ function Compare(obj, AttributeValue: AnsiString): Boolean;
+
+ {:Search LDAP base for LDAP objects by Filter.}
+ function Search(obj: AnsiString; TypesOnly: Boolean; Filter: AnsiString;
+ const Attributes: TStrings): Boolean;
+
+ {:Call any LDAPv3 extended command.}
+ function Extended(const Name, Value: AnsiString): Boolean;
+
+ {:Try to start SSL/TLS connection to LDAP server.}
+ function StartTLS: Boolean;
+ published
+ {:Specify version of used LDAP protocol. Default value is 3.}
+ property Version: integer read FVersion Write FVersion;
+
+ {:Result code of last LDAP operation.}
+ property ResultCode: Integer read FResultCode;
+
+ {:Human readable description of result code of last LDAP operation.}
+ property ResultString: AnsiString read FResultString;
+
+ {:Binary string with full last response of LDAP server. This string is
+ encoded by ASN.1 BER encoding! You need this only for debugging.}
+ property FullResult: AnsiString read FFullResult;
+
+ {:If @true, then try to start TSL mode in Login procedure.}
+ property AutoTLS: Boolean read FAutoTLS Write FAutoTLS;
+
+ {:If @true, then use connection to LDAP server through SSL/TLS tunnel.}
+ property FullSSL: Boolean read FFullSSL Write FFullSSL;
+
+ {:Sequence number of last LDAp command. It is incremented by any LDAP command.}
+ property Seq: integer read FSeq;
+
+ {:Specify what search scope is used in search command.}
+ property SearchScope: TLDAPSearchScope read FSearchScope Write FSearchScope;
+
+ {:Specify how to handle aliases in search command.}
+ property SearchAliases: TLDAPSearchAliases read FSearchAliases Write FSearchAliases;
+
+ {:Specify result size limit in search command. Value 0 means without limit.}
+ property SearchSizeLimit: integer read FSearchSizeLimit Write FSearchSizeLimit;
+
+ {:Specify search time limit in search command (seconds). Value 0 means
+ without limit.}
+ property SearchTimeLimit: integer read FSearchTimeLimit Write FSearchTimeLimit;
+
+ {:Here is result of search command.}
+ property SearchResult: TLDAPResultList read FSearchResult;
+
+ {:On each LDAP operation can LDAP server return some referals URLs. Here is
+ their list.}
+ property Referals: TStringList read FReferals;
+
+ {:When you call @link(Extended) operation, then here is result Name returned
+ by server.}
+ property ExtName: AnsiString read FExtName;
+
+ {:When you call @link(Extended) operation, then here is result Value returned
+ by server.}
+ property ExtValue: AnsiString read FExtValue;
+
+ {:TCP socket used by all LDAP operations.}
+ property Sock: TTCPBlockSocket read FSock;
+ end;
+
+{:Dump result of LDAP SEARCH into human readable form. Good for debugging.}
+function LDAPResultDump(const Value: TLDAPResultList): AnsiString;
+
+implementation
+
+{==============================================================================}
+function TLDAPAttribute.Get(Index: integer): string;
+begin
+ Result := inherited Get(Index);
+ if FIsbinary then
+ Result := DecodeBase64(Result);
+end;
+
+procedure TLDAPAttribute.Put(Index: integer; const Value: string);
+var
+ s: AnsiString;
+begin
+ s := Value;
+ if FIsbinary then
+ s := EncodeBase64(Value)
+ else
+ s :=UnquoteStr(s, '"');
+ inherited Put(Index, s);
+end;
+
+procedure TLDAPAttribute.SetAttributeName(Value: AnsiString);
+begin
+ FAttributeName := Value;
+ FIsBinary := Pos(';binary', Lowercase(value)) > 0;
+end;
+
+{==============================================================================}
+constructor TLDAPAttributeList.Create;
+begin
+ inherited Create;
+ FAttributeList := TList.Create;
+end;
+
+destructor TLDAPAttributeList.Destroy;
+begin
+ Clear;
+ FAttributeList.Free;
+ inherited Destroy;
+end;
+
+procedure TLDAPAttributeList.Clear;
+var
+ n: integer;
+ x: TLDAPAttribute;
+begin
+ for n := Count - 1 downto 0 do
+ begin
+ x := GetAttribute(n);
+ if Assigned(x) then
+ x.Free;
+ end;
+ FAttributeList.Clear;
+end;
+
+function TLDAPAttributeList.Count: integer;
+begin
+ Result := FAttributeList.Count;
+end;
+
+function TLDAPAttributeList.GetAttribute(Index: integer): TLDAPAttribute;
+begin
+ Result := nil;
+ if Index < Count then
+ Result := TLDAPAttribute(FAttributeList[Index]);
+end;
+
+function TLDAPAttributeList.Add: TLDAPAttribute;
+begin
+ Result := TLDAPAttribute.Create;
+ FAttributeList.Add(Result);
+end;
+
+procedure TLDAPAttributeList.Del(Index: integer);
+var
+ x: TLDAPAttribute;
+begin
+ x := GetAttribute(Index);
+ if Assigned(x) then
+ x.free;
+ FAttributeList.Delete(Index);
+end;
+
+function TLDAPAttributeList.Find(AttributeName: AnsiString): TLDAPAttribute;
+var
+ n: integer;
+ x: TLDAPAttribute;
+begin
+ Result := nil;
+ AttributeName := lowercase(AttributeName);
+ for n := 0 to Count - 1 do
+ begin
+ x := GetAttribute(n);
+ if Assigned(x) then
+ if lowercase(x.AttributeName) = Attributename then
+ begin
+ result := x;
+ break;
+ end;
+ end;
+end;
+
+{==============================================================================}
+constructor TLDAPResult.Create;
+begin
+ inherited Create;
+ FAttributes := TLDAPAttributeList.Create;
+end;
+
+destructor TLDAPResult.Destroy;
+begin
+ FAttributes.Free;
+ inherited Destroy;
+end;
+
+{==============================================================================}
+constructor TLDAPResultList.Create;
+begin
+ inherited Create;
+ FResultList := TList.Create;
+end;
+
+destructor TLDAPResultList.Destroy;
+begin
+ Clear;
+ FResultList.Free;
+ inherited Destroy;
+end;
+
+procedure TLDAPResultList.Clear;
+var
+ n: integer;
+ x: TLDAPResult;
+begin
+ for n := Count - 1 downto 0 do
+ begin
+ x := GetResult(n);
+ if Assigned(x) then
+ x.Free;
+ end;
+ FResultList.Clear;
+end;
+
+function TLDAPResultList.Count: integer;
+begin
+ Result := FResultList.Count;
+end;
+
+function TLDAPResultList.GetResult(Index: integer): TLDAPResult;
+begin
+ Result := nil;
+ if Index < Count then
+ Result := TLDAPResult(FResultList[Index]);
+end;
+
+function TLDAPResultList.Add: TLDAPResult;
+begin
+ Result := TLDAPResult.Create;
+ FResultList.Add(Result);
+end;
+
+{==============================================================================}
+constructor TLDAPSend.Create;
+begin
+ inherited Create;
+ FReferals := TStringList.Create;
+ FFullResult := '';
+ FSock := TTCPBlockSocket.Create;
+ FTimeout := 60000;
+ FTargetPort := cLDAPProtocol;
+ FAutoTLS := False;
+ FFullSSL := False;
+ FSeq := 0;
+ FVersion := 3;
+ FSearchScope := SS_WholeSubtree;
+ FSearchAliases := SA_Always;
+ FSearchSizeLimit := 0;
+ FSearchTimeLimit := 0;
+ FSearchResult := TLDAPResultList.Create;
+end;
+
+destructor TLDAPSend.Destroy;
+begin
+ FSock.Free;
+ FSearchResult.Free;
+ FReferals.Free;
+ inherited Destroy;
+end;
+
+function TLDAPSend.GetErrorString(Value: integer): AnsiString;
+begin
+ case Value of
+ 0:
+ Result := 'Success';
+ 1:
+ Result := 'Operations error';
+ 2:
+ Result := 'Protocol error';
+ 3:
+ Result := 'Time limit Exceeded';
+ 4:
+ Result := 'Size limit Exceeded';
+ 5:
+ Result := 'Compare FALSE';
+ 6:
+ Result := 'Compare TRUE';
+ 7:
+ Result := 'Auth method not supported';
+ 8:
+ Result := 'Strong auth required';
+ 9:
+ Result := '-- reserved --';
+ 10:
+ Result := 'Referal';
+ 11:
+ Result := 'Admin limit exceeded';
+ 12:
+ Result := 'Unavailable critical extension';
+ 13:
+ Result := 'Confidentality required';
+ 14:
+ Result := 'Sasl bind in progress';
+ 16:
+ Result := 'No such attribute';
+ 17:
+ Result := 'Undefined attribute type';
+ 18:
+ Result := 'Inappropriate matching';
+ 19:
+ Result := 'Constraint violation';
+ 20:
+ Result := 'Attribute or value exists';
+ 21:
+ Result := 'Invalid attribute syntax';
+ 32:
+ Result := 'No such object';
+ 33:
+ Result := 'Alias problem';
+ 34:
+ Result := 'Invalid DN syntax';
+ 36:
+ Result := 'Alias dereferencing problem';
+ 48:
+ Result := 'Inappropriate authentication';
+ 49:
+ Result := 'Invalid credentials';
+ 50:
+ Result := 'Insufficient access rights';
+ 51:
+ Result := 'Busy';
+ 52:
+ Result := 'Unavailable';
+ 53:
+ Result := 'Unwilling to perform';
+ 54:
+ Result := 'Loop detect';
+ 64:
+ Result := 'Naming violation';
+ 65:
+ Result := 'Object class violation';
+ 66:
+ Result := 'Not allowed on non leaf';
+ 67:
+ Result := 'Not allowed on RDN';
+ 68:
+ Result := 'Entry already exists';
+ 69:
+ Result := 'Object class mods prohibited';
+ 71:
+ Result := 'Affects multiple DSAs';
+ 80:
+ Result := 'Other';
+ else
+ Result := '--unknown--';
+ end;
+end;
+
+function TLDAPSend.Connect: Boolean;
+begin
+ // Do not call this function! It is calling by LOGIN method!
+ FSock.CloseSocket;
+ FSock.LineBuffer := '';
+ FSeq := 0;
+ FSock.Bind(FIPInterface, cAnyPort);
+ if FSock.LastError = 0 then
+ FSock.Connect(FTargetHost, FTargetPort);
+ if FSock.LastError = 0 then
+ if FFullSSL then
+ FSock.SSLDoConnect;
+ Result := FSock.LastError = 0;
+end;
+
+function TLDAPSend.BuildPacket(const Value: AnsiString): AnsiString;
+begin
+ Inc(FSeq);
+ Result := ASNObject(ASNObject(ASNEncInt(FSeq), ASN1_INT) + Value, ASN1_SEQ);
+end;
+
+function TLDAPSend.ReceiveResponse: AnsiString;
+var
+ x: Byte;
+ i,j: integer;
+begin
+ Result := '';
+ FFullResult := '';
+ x := FSock.RecvByte(FTimeout);
+ if x <> ASN1_SEQ then
+ Exit;
+ Result := AnsiChar(x);
+ x := FSock.RecvByte(FTimeout);
+ Result := Result + AnsiChar(x);
+ if x < $80 then
+ i := 0
+ else
+ i := x and $7F;
+ if i > 0 then
+ Result := Result + FSock.RecvBufferStr(i, Ftimeout);
+ if FSock.LastError <> 0 then
+ begin
+ Result := '';
+ Exit;
+ end;
+ //get length of LDAP packet
+ j := 2;
+ i := ASNDecLen(j, Result);
+ //retreive rest of LDAP packet
+ if i > 0 then
+ Result := Result + FSock.RecvBufferStr(i, Ftimeout);
+ if FSock.LastError <> 0 then
+ begin
+ Result := '';
+ Exit;
+ end;
+ FFullResult := Result;
+end;
+
+function TLDAPSend.DecodeResponse(const Value: AnsiString): AnsiString;
+var
+ i, x: integer;
+ Svt: Integer;
+ s, t: AnsiString;
+begin
+ Result := '';
+ FResultCode := -1;
+ FResultstring := '';
+ FResponseCode := -1;
+ FResponseDN := '';
+ FReferals.Clear;
+ i := 1;
+ ASNItem(i, Value, Svt);
+ x := StrToIntDef(ASNItem(i, Value, Svt), 0);
+ if (svt <> ASN1_INT) or (x <> FSeq) then
+ Exit;
+ s := ASNItem(i, Value, Svt);
+ FResponseCode := svt;
+ if FResponseCode in [LDAP_ASN1_BIND_RESPONSE, LDAP_ASN1_SEARCH_DONE,
+ LDAP_ASN1_MODIFY_RESPONSE, LDAP_ASN1_ADD_RESPONSE, LDAP_ASN1_DEL_RESPONSE,
+ LDAP_ASN1_MODIFYDN_RESPONSE, LDAP_ASN1_COMPARE_RESPONSE,
+ LDAP_ASN1_EXT_RESPONSE] then
+ begin
+ FResultCode := StrToIntDef(ASNItem(i, Value, Svt), -1);
+ FResponseDN := ASNItem(i, Value, Svt);
+ FResultString := ASNItem(i, Value, Svt);
+ if FResultString = '' then
+ FResultString := GetErrorString(FResultCode);
+ if FResultCode = 10 then
+ begin
+ s := ASNItem(i, Value, Svt);
+ if svt = $A3 then
+ begin
+ x := 1;
+ while x < Length(s) do
+ begin
+ t := ASNItem(x, s, Svt);
+ FReferals.Add(t);
+ end;
+ end;
+ end;
+ end;
+ Result := Copy(Value, i, Length(Value) - i + 1);
+end;
+
+function TLDAPSend.LdapSasl(Value: AnsiString): AnsiString;
+var
+ nonce, cnonce, nc, realm, qop, uri, response: AnsiString;
+ s: AnsiString;
+ a1, a2: AnsiString;
+ l: TStringList;
+ n: integer;
+begin
+ l := TStringList.Create;
+ try
+ nonce := '';
+ realm := '';
+ l.CommaText := Value;
+ n := IndexByBegin('nonce=', l);
+ if n >= 0 then
+ nonce := UnQuoteStr(Trim(SeparateRight(l[n], 'nonce=')), '"');
+ n := IndexByBegin('realm=', l);
+ if n >= 0 then
+ realm := UnQuoteStr(Trim(SeparateRight(l[n], 'realm=')), '"');
+ cnonce := IntToHex(GetTick, 8);
+ nc := '00000001';
+ qop := 'auth';
+ uri := 'ldap/' + FSock.ResolveIpToName(FSock.GetRemoteSinIP);
+ a1 := md5(FUsername + ':' + realm + ':' + FPassword)
+ + ':' + nonce + ':' + cnonce;
+ a2 := 'AUTHENTICATE:' + uri;
+ s := strtohex(md5(a1))+':' + nonce + ':' + nc + ':' + cnonce + ':'
+ + qop +':'+strtohex(md5(a2));
+ response := strtohex(md5(s));
+
+ Result := 'username="' + Fusername + '",realm="' + realm + '",nonce="';
+ Result := Result + nonce + '",cnonce="' + cnonce + '",nc=' + nc + ',qop=';
+ Result := Result + qop + ',digest-uri="' + uri + '",response=' + response;
+ finally
+ l.Free;
+ end;
+end;
+
+function TLDAPSend.TranslateFilter(Value: AnsiString): AnsiString;
+var
+ x: integer;
+ s, t, l: AnsiString;
+ r: string;
+ c: Ansichar;
+ attr, rule: AnsiString;
+ dn: Boolean;
+begin
+ Result := '';
+ if Value = '' then
+ Exit;
+ s := Value;
+ if Value[1] = '(' then
+ begin
+ x := RPos(')', Value);
+ s := Copy(Value, 2, x - 2);
+ end;
+ if s = '' then
+ Exit;
+ case s[1] of
+ '!':
+ // NOT rule (recursive call)
+ begin
+ Result := ASNOBject(TranslateFilter(GetBetween('(', ')', s)), $A2);
+ end;
+ '&':
+ // AND rule (recursive call)
+ begin
+ repeat
+ t := GetBetween('(', ')', s);
+ s := Trim(SeparateRight(s, t));
+ if s <> '' then
+ if s[1] = ')' then
+ {$IFDEF CIL}Borland.Delphi.{$ENDIF}System.Delete(s, 1, 1);
+ Result := Result + TranslateFilter(t);
+ until s = '';
+ Result := ASNOBject(Result, $A0);
+ end;
+ '|':
+ // OR rule (recursive call)
+ begin
+ repeat
+ t := GetBetween('(', ')', s);
+ s := Trim(SeparateRight(s, t));
+ if s <> '' then
+ if s[1] = ')' then
+ {$IFDEF CIL}Borland.Delphi.{$ENDIF}System.Delete(s, 1, 1);
+ Result := Result + TranslateFilter(t);
+ until s = '';
+ Result := ASNOBject(Result, $A1);
+ end;
+ else
+ begin
+ l := Trim(SeparateLeft(s, '='));
+ r := Trim(SeparateRight(s, '='));
+ if l <> '' then
+ begin
+ c := l[Length(l)];
+ case c of
+ ':':
+ // Extensible match
+ begin
+ {$IFDEF CIL}Borland.Delphi.{$ENDIF}System.Delete(l, Length(l), 1);
+ dn := False;
+ attr := '';
+ rule := '';
+ if Pos(':dn', l) > 0 then
+ begin
+ dn := True;
+ l := ReplaceString(l, ':dn', '');
+ end;
+ attr := Trim(SeparateLeft(l, ':'));
+ rule := Trim(SeparateRight(l, ':'));
+ if rule = l then
+ rule := '';
+ if rule <> '' then
+ Result := ASNObject(rule, $81);
+ if attr <> '' then
+ Result := Result + ASNObject(attr, $82);
+ Result := Result + ASNObject(DecodeTriplet(r, '\'), $83);
+ if dn then
+ Result := Result + ASNObject(AsnEncInt($ff), $84)
+ else
+ Result := Result + ASNObject(AsnEncInt(0), $84);
+ Result := ASNOBject(Result, $a9);
+ end;
+ '~':
+ // Approx match
+ begin
+ {$IFDEF CIL}Borland.Delphi.{$ENDIF}System.Delete(l, Length(l), 1);
+ Result := ASNOBject(l, ASN1_OCTSTR)
+ + ASNOBject(DecodeTriplet(r, '\'), ASN1_OCTSTR);
+ Result := ASNOBject(Result, $a8);
+ end;
+ '>':
+ // Greater or equal match
+ begin
+ {$IFDEF CIL}Borland.Delphi.{$ENDIF}System.Delete(l, Length(l), 1);
+ Result := ASNOBject(l, ASN1_OCTSTR)
+ + ASNOBject(DecodeTriplet(r, '\'), ASN1_OCTSTR);
+ Result := ASNOBject(Result, $a5);
+ end;
+ '<':
+ // Less or equal match
+ begin
+ {$IFDEF CIL}Borland.Delphi.{$ENDIF}System.Delete(l, Length(l), 1);
+ Result := ASNOBject(l, ASN1_OCTSTR)
+ + ASNOBject(DecodeTriplet(r, '\'), ASN1_OCTSTR);
+ Result := ASNOBject(Result, $a6);
+ end;
+ else
+ // present
+ if r = '*' then
+ Result := ASNOBject(l, $87)
+ else
+ if Pos('*', r) > 0 then
+ // substrings
+ begin
+ s := Fetch(r, '*');
+ if s <> '' then
+ Result := ASNOBject(DecodeTriplet(s, '\'), $80);
+ while r <> '' do
+ begin
+ if Pos('*', r) <= 0 then
+ break;
+ s := Fetch(r, '*');
+ Result := Result + ASNOBject(DecodeTriplet(s, '\'), $81);
+ end;
+ if r <> '' then
+ Result := Result + ASNOBject(DecodeTriplet(r, '\'), $82);
+ Result := ASNOBject(l, ASN1_OCTSTR)
+ + ASNOBject(Result, ASN1_SEQ);
+ Result := ASNOBject(Result, $a4);
+ end
+ else
+ begin
+ // Equality match
+ Result := ASNOBject(l, ASN1_OCTSTR)
+ + ASNOBject(DecodeTriplet(r, '\'), ASN1_OCTSTR);
+ Result := ASNOBject(Result, $a3);
+ end;
+ end;
+ end;
+ end;
+ end;
+end;
+
+function TLDAPSend.Login: Boolean;
+begin
+ Result := False;
+ if not Connect then
+ Exit;
+ Result := True;
+ if FAutoTLS then
+ Result := StartTLS;
+end;
+
+function TLDAPSend.Bind: Boolean;
+var
+ s: AnsiString;
+begin
+ s := ASNObject(ASNEncInt(FVersion), ASN1_INT)
+ + ASNObject(FUsername, ASN1_OCTSTR)
+ + ASNObject(FPassword, $80);
+ s := ASNObject(s, LDAP_ASN1_BIND_REQUEST);
+ Fsock.SendString(BuildPacket(s));
+ s := ReceiveResponse;
+ DecodeResponse(s);
+ Result := FResultCode = 0;
+end;
+
+function TLDAPSend.BindSasl: Boolean;
+var
+ s, t: AnsiString;
+ x, xt: integer;
+ digreq: AnsiString;
+begin
+ Result := False;
+ if FPassword = '' then
+ Result := Bind
+ else
+ begin
+ digreq := ASNObject(ASNEncInt(FVersion), ASN1_INT)
+ + ASNObject('', ASN1_OCTSTR)
+ + ASNObject(ASNObject('DIGEST-MD5', ASN1_OCTSTR), $A3);
+ digreq := ASNObject(digreq, LDAP_ASN1_BIND_REQUEST);
+ Fsock.SendString(BuildPacket(digreq));
+ s := ReceiveResponse;
+ t := DecodeResponse(s);
+ if FResultCode = 14 then
+ begin
+ s := t;
+ x := 1;
+ t := ASNItem(x, s, xt);
+ s := ASNObject(ASNEncInt(FVersion), ASN1_INT)
+ + ASNObject('', ASN1_OCTSTR)
+ + ASNObject(ASNObject('DIGEST-MD5', ASN1_OCTSTR)
+ + ASNObject(LdapSasl(t), ASN1_OCTSTR), $A3);
+ s := ASNObject(s, LDAP_ASN1_BIND_REQUEST);
+ Fsock.SendString(BuildPacket(s));
+ s := ReceiveResponse;
+ DecodeResponse(s);
+ if FResultCode = 14 then
+ begin
+ Fsock.SendString(BuildPacket(digreq));
+ s := ReceiveResponse;
+ DecodeResponse(s);
+ end;
+ Result := FResultCode = 0;
+ end;
+ end;
+end;
+
+function TLDAPSend.Logout: Boolean;
+begin
+ Fsock.SendString(BuildPacket(ASNObject('', LDAP_ASN1_UNBIND_REQUEST)));
+ FSock.CloseSocket;
+ Result := True;
+end;
+
+function TLDAPSend.Modify(obj: AnsiString; Op: TLDAPModifyOp; const Value: TLDAPAttribute): Boolean;
+var
+ s: AnsiString;
+ n: integer;
+begin
+ s := '';
+ for n := 0 to Value.Count -1 do
+ s := s + ASNObject(Value[n], ASN1_OCTSTR);
+ s := ASNObject(Value.AttributeName, ASN1_OCTSTR) + ASNObject(s, ASN1_SETOF);
+ s := ASNObject(ASNEncInt(Ord(Op)), ASN1_ENUM) + ASNObject(s, ASN1_SEQ);
+ s := ASNObject(s, ASN1_SEQ);
+ s := ASNObject(obj, ASN1_OCTSTR) + ASNObject(s, ASN1_SEQ);
+ s := ASNObject(s, LDAP_ASN1_MODIFY_REQUEST);
+ Fsock.SendString(BuildPacket(s));
+ s := ReceiveResponse;
+ DecodeResponse(s);
+ Result := FResultCode = 0;
+end;
+
+function TLDAPSend.Add(obj: AnsiString; const Value: TLDAPAttributeList): Boolean;
+var
+ s, t: AnsiString;
+ n, m: integer;
+begin
+ s := '';
+ for n := 0 to Value.Count - 1 do
+ begin
+ t := '';
+ for m := 0 to Value[n].Count - 1 do
+ t := t + ASNObject(Value[n][m], ASN1_OCTSTR);
+ t := ASNObject(Value[n].AttributeName, ASN1_OCTSTR)
+ + ASNObject(t, ASN1_SETOF);
+ s := s + ASNObject(t, ASN1_SEQ);
+ end;
+ s := ASNObject(obj, ASN1_OCTSTR) + ASNObject(s, ASN1_SEQ);
+ s := ASNObject(s, LDAP_ASN1_ADD_REQUEST);
+ Fsock.SendString(BuildPacket(s));
+ s := ReceiveResponse;
+ DecodeResponse(s);
+ Result := FResultCode = 0;
+end;
+
+function TLDAPSend.Delete(obj: AnsiString): Boolean;
+var
+ s: AnsiString;
+begin
+ s := ASNObject(obj, LDAP_ASN1_DEL_REQUEST);
+ Fsock.SendString(BuildPacket(s));
+ s := ReceiveResponse;
+ DecodeResponse(s);
+ Result := FResultCode = 0;
+end;
+
+function TLDAPSend.ModifyDN(obj, newRDN, newSuperior: AnsiString; DeleteOldRDN: Boolean): Boolean;
+var
+ s: AnsiString;
+begin
+ s := ASNObject(obj, ASN1_OCTSTR) + ASNObject(newRDN, ASN1_OCTSTR);
+ if DeleteOldRDN then
+ s := s + ASNObject(ASNEncInt($ff), ASN1_BOOL)
+ else
+ s := s + ASNObject(ASNEncInt(0), ASN1_BOOL);
+ if newSuperior <> '' then
+ s := s + ASNObject(newSuperior, $80);
+ s := ASNObject(s, LDAP_ASN1_MODIFYDN_REQUEST);
+ Fsock.SendString(BuildPacket(s));
+ s := ReceiveResponse;
+ DecodeResponse(s);
+ Result := FResultCode = 0;
+end;
+
+function TLDAPSend.Compare(obj, AttributeValue: AnsiString): Boolean;
+var
+ s: AnsiString;
+begin
+ s := ASNObject(Trim(SeparateLeft(AttributeValue, '=')), ASN1_OCTSTR)
+ + ASNObject(Trim(SeparateRight(AttributeValue, '=')), ASN1_OCTSTR);
+ s := ASNObject(obj, ASN1_OCTSTR) + ASNObject(s, ASN1_SEQ);
+ s := ASNObject(s, LDAP_ASN1_COMPARE_REQUEST);
+ Fsock.SendString(BuildPacket(s));
+ s := ReceiveResponse;
+ DecodeResponse(s);
+ Result := FResultCode = 0;
+end;
+
+function TLDAPSend.Search(obj: AnsiString; TypesOnly: Boolean; Filter: AnsiString;
+ const Attributes: TStrings): Boolean;
+var
+ s, t, u: AnsiString;
+ n, i, x: integer;
+ r: TLDAPResult;
+ a: TLDAPAttribute;
+begin
+ FSearchResult.Clear;
+ FReferals.Clear;
+ s := ASNObject(obj, ASN1_OCTSTR);
+ s := s + ASNObject(ASNEncInt(Ord(FSearchScope)), ASN1_ENUM);
+ s := s + ASNObject(ASNEncInt(Ord(FSearchAliases)), ASN1_ENUM);
+ s := s + ASNObject(ASNEncInt(FSearchSizeLimit), ASN1_INT);
+ s := s + ASNObject(ASNEncInt(FSearchTimeLimit), ASN1_INT);
+ if TypesOnly then
+ s := s + ASNObject(ASNEncInt($ff), ASN1_BOOL)
+ else
+ s := s + ASNObject(ASNEncInt(0), ASN1_BOOL);
+ if Filter = '' then
+ Filter := '(objectclass=*)';
+ t := TranslateFilter(Filter);
+ if t = '' then
+ s := s + ASNObject('', ASN1_NULL)
+ else
+ s := s + t;
+ t := '';
+ for n := 0 to Attributes.Count - 1 do
+ t := t + ASNObject(Attributes[n], ASN1_OCTSTR);
+ s := s + ASNObject(t, ASN1_SEQ);
+ s := ASNObject(s, LDAP_ASN1_SEARCH_REQUEST);
+ Fsock.SendString(BuildPacket(s));
+ repeat
+ s := ReceiveResponse;
+ t := DecodeResponse(s);
+ if FResponseCode = LDAP_ASN1_SEARCH_ENTRY then
+ begin
+ //dekoduj zaznam
+ r := FSearchResult.Add;
+ n := 1;
+ r.ObjectName := ASNItem(n, t, x);
+ ASNItem(n, t, x);
+ if x = ASN1_SEQ then
+ begin
+ while n < Length(t) do
+ begin
+ s := ASNItem(n, t, x);
+ if x = ASN1_SEQ then
+ begin
+ i := n + Length(s);
+ a := r.Attributes.Add;
+ u := ASNItem(n, t, x);
+ a.AttributeName := u;
+ ASNItem(n, t, x);
+ if x = ASN1_SETOF then
+ while n < i do
+ begin
+ u := ASNItem(n, t, x);
+ a.Add(u);
+ end;
+ end;
+ end;
+ end;
+ end;
+ if FResponseCode = LDAP_ASN1_SEARCH_REFERENCE then
+ begin
+ n := 1;
+ while n < Length(t) do
+ FReferals.Add(ASNItem(n, t, x));
+ end;
+ until FResponseCode = LDAP_ASN1_SEARCH_DONE;
+ Result := FResultCode = 0;
+end;
+
+function TLDAPSend.Extended(const Name, Value: AnsiString): Boolean;
+var
+ s, t: AnsiString;
+ x, xt: integer;
+begin
+ s := ASNObject(Name, $80);
+ if Value <> '' then
+ s := s + ASNObject(Value, $81);
+ s := ASNObject(s, LDAP_ASN1_EXT_REQUEST);
+ Fsock.SendString(BuildPacket(s));
+ s := ReceiveResponse;
+ t := DecodeResponse(s);
+ Result := FResultCode = 0;
+ if Result then
+ begin
+ x := 1;
+ FExtName := ASNItem(x, t, xt);
+ FExtValue := ASNItem(x, t, xt);
+ end;
+end;
+
+
+function TLDAPSend.StartTLS: Boolean;
+begin
+ Result := Extended('1.3.6.1.4.1.1466.20037', '');
+ if Result then
+ begin
+ Fsock.SSLDoConnect;
+ Result := FSock.LastError = 0;
+ end;
+end;
+
+{==============================================================================}
+function LDAPResultDump(const Value: TLDAPResultList): AnsiString;
+var
+ n, m, o: integer;
+ r: TLDAPResult;
+ a: TLDAPAttribute;
+begin
+ Result := 'Results: ' + IntToStr(Value.Count) + CRLF +CRLF;
+ for n := 0 to Value.Count - 1 do
+ begin
+ Result := Result + 'Result: ' + IntToStr(n) + CRLF;
+ r := Value[n];
+ Result := Result + ' Object: ' + r.ObjectName + CRLF;
+ for m := 0 to r.Attributes.Count - 1 do
+ begin
+ a := r.Attributes[m];
+ Result := Result + ' Attribute: ' + a.AttributeName + CRLF;
+ for o := 0 to a.Count - 1 do
+ Result := Result + ' ' + a[o] + CRLF;
+ end;
+ end;
+end;
+
+end.
diff --git a/branches/script-component/Units/Synapse/mimeinln.pas b/branches/script-component/Units/Synapse/mimeinln.pas
new file mode 100644
index 0000000..4f0331a
--- /dev/null
+++ b/branches/script-component/Units/Synapse/mimeinln.pas
@@ -0,0 +1,258 @@
+{==============================================================================|
+| Project : Ararat Synapse | 001.001.011 |
+|==============================================================================|
+| Content: Inline MIME support procedures and functions |
+|==============================================================================|
+| Copyright (c)1999-2006, Lukas Gebauer |
+| All rights reserved. |
+| |
+| Redistribution and use in source and binary forms, with or without |
+| modification, are permitted provided that the following conditions are met: |
+| |
+| Redistributions of source code must retain the above copyright notice, this |
+| list of conditions and the following disclaimer. |
+| |
+| Redistributions in binary form must reproduce the above copyright notice, |
+| this list of conditions and the following disclaimer in the documentation |
+| and/or other materials provided with the distribution. |
+| |
+| Neither the name of Lukas Gebauer nor the names of its contributors may |
+| be used to endorse or promote products derived from this software without |
+| specific prior written permission. |
+| |
+| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
+| AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
+| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
+| ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR |
+| ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
+| DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
+| SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
+| CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
+| LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
+| OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
+| DAMAGE. |
+|==============================================================================|
+| The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).|
+| Portions created by Lukas Gebauer are Copyright (c)2000-2006. |
+| All Rights Reserved. |
+|==============================================================================|
+| Contributor(s): |
+|==============================================================================|
+| History: see HISTORY.HTM from distribution package |
+| (Found at URL: http://www.ararat.cz/synapse/) |
+|==============================================================================}
+
+{:@abstract(Utilities for inline MIME)
+Support for Inline MIME encoding and decoding.
+
+Used RFC: RFC-2047, RFC-2231
+}
+
+{$IFDEF FPC}
+ {$MODE DELPHI}
+{$ENDIF}
+{$H+}
+
+unit mimeinln;
+
+interface
+
+uses
+ SysUtils, Classes,
+ synachar, synacode, synautil;
+
+{:Decodes mime inline encoding (i.e. in headers) uses target characterset "CP".}
+function InlineDecode(const Value: string; CP: TMimeChar): string;
+
+{:Encodes string to MIME inline encoding. The source characterset is "CP", and
+ the target charset is "MimeP".}
+function InlineEncode(const Value: string; CP, MimeP: TMimeChar): string;
+
+{:Returns @true, if "Value" contains characters needed for inline coding.}
+function NeedInline(const Value: AnsiString): boolean;
+
+{:Inline mime encoding similar to @link(InlineEncode), but you can specify
+ source charset, and the target characterset is automatically assigned.}
+function InlineCodeEx(const Value: string; FromCP: TMimeChar): string;
+
+{:Inline MIME encoding similar to @link(InlineEncode), but the source charset
+ is automatically set to the system default charset, and the target charset is
+ automatically assigned from set of allowed encoding for MIME.}
+function InlineCode(const Value: string): string;
+
+{:Converts e-mail address to canonical mime form. You can specify source charset.}
+function InlineEmailEx(const Value: string; FromCP: TMimeChar): string;
+
+{:Converts e-mail address to canonical mime form. Source charser it system
+ default charset.}
+function InlineEmail(const Value: string): string;
+
+implementation
+
+{==============================================================================}
+
+function InlineDecode(const Value: string; CP: TMimeChar): string;
+var
+ s, su, v: string;
+ x, y, z, n: Integer;
+ ichar: TMimeChar;
+ c: Char;
+
+ function SearchEndInline(const Value: string; be: Integer): Integer;
+ var
+ n, q: Integer;
+ begin
+ q := 0;
+ Result := 0;
+ for n := be + 2 to Length(Value) - 1 do
+ if Value[n] = '?' then
+ begin
+ Inc(q);
+ if (q > 2) and (Value[n + 1] = '=') then
+ begin
+ Result := n;
+ Break;
+ end;
+ end;
+ end;
+
+begin
+ Result := '';
+ v := Value;
+ x := Pos('=?', v);
+ y := SearchEndInline(v, x);
+ //fix for broken coding with begin, but not with end.
+ if (x > 0) and (y <= 0) then
+ y := Length(Result);
+ while (y > x) and (x > 0) do
+ begin
+ s := Copy(v, 1, x - 1);
+ if Trim(s) <> '' then
+ Result := Result + s;
+ s := Copy(v, x, y - x + 2);
+ Delete(v, 1, y + 1);
+ su := Copy(s, 3, Length(s) - 4);
+ z := Pos('?', su);
+ if (Length(su) >= (z + 2)) and (su[z + 2] = '?') then
+ begin
+ ichar := GetCPFromID(SeparateLeft(Copy(su, 1, z - 1), '*'));
+ c := UpperCase(su)[z + 1];
+ su := Copy(su, z + 3, Length(su) - z - 2);
+ if c = 'B' then
+ begin
+ s := DecodeBase64(su);
+ s := CharsetConversion(s, ichar, CP);
+ end;
+ if c = 'Q' then
+ begin
+ s := '';
+ for n := 1 to Length(su) do
+ if su[n] = '_' then
+ s := s + ' '
+ else
+ s := s + su[n];
+ s := DecodeQuotedPrintable(s);
+ s := CharsetConversion(s, ichar, CP);
+ end;
+ end;
+ Result := Result + s;
+ x := Pos('=?', v);
+ y := SearchEndInline(v, x);
+ end;
+ Result := Result + v;
+end;
+
+{==============================================================================}
+
+function InlineEncode(const Value: string; CP, MimeP: TMimeChar): string;
+var
+ s, s1, e: string;
+ n: Integer;
+begin
+ s := CharsetConversion(Value, CP, MimeP);
+ s := EncodeSafeQuotedPrintable(s);
+ e := GetIdFromCP(MimeP);
+ s1 := '';
+ Result := '';
+ for n := 1 to Length(s) do
+ if s[n] = ' ' then
+ begin
+// s1 := s1 + '=20';
+ s1 := s1 + '_';
+ if Length(s1) > 32 then
+ begin
+ if Result <> '' then
+ Result := Result + ' ';
+ Result := Result + '=?' + e + '?Q?' + s1 + '?=';
+ s1 := '';
+ end;
+ end
+ else
+ s1 := s1 + s[n];
+ if s1 <> '' then
+ begin
+ if Result <> '' then
+ Result := Result + ' ';
+ Result := Result + '=?' + e + '?Q?' + s1 + '?=';
+ end;
+end;
+
+{==============================================================================}
+
+function NeedInline(const Value: AnsiString): boolean;
+var
+ n: Integer;
+begin
+ Result := False;
+ for n := 1 to Length(Value) do
+ if Value[n] in (SpecialChar + NonAsciiChar - ['_']) then
+ begin
+ Result := True;
+ Break;
+ end;
+end;
+
+{==============================================================================}
+
+function InlineCodeEx(const Value: string; FromCP: TMimeChar): string;
+var
+ c: TMimeChar;
+begin
+ if NeedInline(Value) then
+ begin
+ c := IdealCharsetCoding(Value, FromCP, IdealCharsets);
+ Result := InlineEncode(Value, FromCP, c);
+ end
+ else
+ Result := Value;
+end;
+
+{==============================================================================}
+
+function InlineCode(const Value: string): string;
+begin
+ Result := InlineCodeEx(Value, GetCurCP);
+end;
+
+{==============================================================================}
+
+function InlineEmailEx(const Value: string; FromCP: TMimeChar): string;
+var
+ sd, se: string;
+begin
+ sd := GetEmailDesc(Value);
+ se := GetEmailAddr(Value);
+ if sd = '' then
+ Result := se
+ else
+ Result := '"' + InlineCodeEx(sd, FromCP) + '" <' + se + '>';
+end;
+
+{==============================================================================}
+
+function InlineEmail(const Value: string): string;
+begin
+ Result := InlineEmailEx(Value, GetCurCP);
+end;
+
+end.
diff --git a/branches/script-component/Units/Synapse/mimemess.pas b/branches/script-component/Units/Synapse/mimemess.pas
new file mode 100644
index 0000000..261c942
--- /dev/null
+++ b/branches/script-component/Units/Synapse/mimemess.pas
@@ -0,0 +1,824 @@
+{==============================================================================|
+| Project : Ararat Synapse | 002.005.002 |
+|==============================================================================|
+| Content: MIME message object |
+|==============================================================================|
+| Copyright (c)1999-2006, Lukas Gebauer |
+| All rights reserved. |
+| |
+| Redistribution and use in source and binary forms, with or without |
+| modification, are permitted provided that the following conditions are met: |
+| |
+| Redistributions of source code must retain the above copyright notice, this |
+| list of conditions and the following disclaimer. |
+| |
+| Redistributions in binary form must reproduce the above copyright notice, |
+| this list of conditions and the following disclaimer in the documentation |
+| and/or other materials provided with the distribution. |
+| |
+| Neither the name of Lukas Gebauer nor the names of its contributors may |
+| be used to endorse or promote products derived from this software without |
+| specific prior written permission. |
+| |
+| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
+| AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
+| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
+| ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR |
+| ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
+| DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
+| SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
+| CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
+| LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
+| OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
+| DAMAGE. |
+|==============================================================================|
+| The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).|
+| Portions created by Lukas Gebauer are Copyright (c)2000-2006. |
+| All Rights Reserved. |
+|==============================================================================|
+| Contributor(s): |
+|==============================================================================|
+| History: see HISTORY.HTM From distribution package |
+| (Found at URL: http://www.ararat.cz/synapse/) |
+|==============================================================================}
+
+{:@abstract(MIME message handling)
+Classes for easy handling with e-mail message.
+}
+
+{$IFDEF FPC}
+ {$MODE DELPHI}
+{$ENDIF}
+{$H+}
+
+unit mimemess;
+
+interface
+
+uses
+ Classes, SysUtils,
+ mimepart, synachar, synautil, mimeinln;
+
+type
+
+ {:Possible values for message priority}
+ TMessPriority = (MP_unknown, MP_low, MP_normal, MP_high);
+
+ {:@abstract(Object for basic e-mail header fields.)}
+ TMessHeader = class(TObject)
+ private
+ FFrom: string;
+ FToList: TStringList;
+ FCCList: TStringList;
+ FSubject: string;
+ FOrganization: string;
+ FCustomHeaders: TStringList;
+ FDate: TDateTime;
+ FXMailer: string;
+ FCharsetCode: TMimeChar;
+ FReplyTo: string;
+ FMessageID: string;
+ FPriority: TMessPriority;
+ Fpri: TMessPriority;
+ Fxpri: TMessPriority;
+ Fxmspri: TMessPriority;
+ protected
+ function ParsePriority(value: string): TMessPriority;
+ function DecodeHeader(value: string): boolean; virtual;
+ public
+ constructor Create; virtual;
+ destructor Destroy; override;
+
+ {:Clears all data fields.}
+ procedure Clear; virtual;
+
+ {Add headers from from this object to Value.}
+ procedure EncodeHeaders(const Value: TStrings); virtual;
+
+ {:Parse header from Value to this object.}
+ procedure DecodeHeaders(const Value: TStrings);
+
+ {:Try find specific header in CustomHeader. Search is case insensitive.
+ This is good for reading any non-parsed header.}
+ function FindHeader(Value: string): string;
+
+ {:Try find specific headers in CustomHeader. This metod is for repeatly used
+ headers like 'received' header, etc. Search is case insensitive.
+ This is good for reading ano non-parsed header.}
+ procedure FindHeaderList(Value: string; const HeaderList: TStrings);
+ published
+ {:Sender of message.}
+ property From: string read FFrom Write FFrom;
+
+ {:Stringlist with receivers of message. (one per line)}
+ property ToList: TStringList read FToList;
+
+ {:Stringlist with Carbon Copy receivers of message. (one per line)}
+ property CCList: TStringList read FCCList;
+
+ {:Subject of message.}
+ property Subject: string read FSubject Write FSubject;
+
+ {:Organization string.}
+ property Organization: string read FOrganization Write FOrganization;
+
+ {:After decoding contains all headers lines witch not have parsed to any
+ other structures in this object. It mean: this conatins all other headers
+ except:
+
+ X-MAILER, FROM, SUBJECT, ORGANIZATION, TO, CC, DATE, MIME-VERSION,
+ CONTENT-TYPE, CONTENT-DESCRIPTION, CONTENT-DISPOSITION, CONTENT-ID,
+ CONTENT-TRANSFER-ENCODING, REPLY-TO, MESSAGE-ID, X-MSMAIL-PRIORITY,
+ X-PRIORITY, PRIORITY
+
+ When you encode headers, all this lines is added as headers. Be carefull
+ for duplicites!}
+ property CustomHeaders: TStringList read FCustomHeaders;
+
+ {:Date and time of message.}
+ property Date: TDateTime read FDate Write FDate;
+
+ {:Mailer identification.}
+ property XMailer: string read FXMailer Write FXMailer;
+
+ {:Address for replies}
+ property ReplyTo: string read FReplyTo Write FReplyTo;
+
+ {:message indetifier}
+ property MessageID: string read FMessageID Write FMessageID;
+
+ {:message priority}
+ property Priority: TMessPriority read FPriority Write FPriority;
+
+ {:Specify base charset. By default is used system charset.}
+ property CharsetCode: TMimeChar read FCharsetCode Write FCharsetCode;
+ end;
+
+ TMessHeaderClass = class of TMessHeader;
+
+ {:@abstract(Object for handling of e-mail message.)}
+ TMimeMess = class(TObject)
+ private
+ FMessagePart: TMimePart;
+ FLines: TStringList;
+ FHeader: TMessHeader;
+ public
+ constructor Create;
+ {:create this object and assign your own descendant of @link(TMessHeader)
+ object to @link(header) property. So, you can create your own message
+ headers parser and use it by this object.}
+ constructor CreateAltHeaders(HeadClass: TMessHeaderClass);
+ destructor Destroy; override;
+
+ {:Reset component to default state.}
+ procedure Clear; virtual;
+
+ {:Add MIME part as subpart of PartParent. If you need set root MIME part,
+ then set as PartParent @NIL value. If you need set more then one subpart,
+ you must have PartParent of multipart type!}
+ function AddPart(const PartParent: TMimePart): TMimePart;
+
+ {:Add MIME part as subpart of PartParent. If you need set root MIME part,
+ then set as PartParent @NIL value. If you need set more then 1 subpart, you
+ must have PartParent of multipart type!
+
+ This part is marked as multipart with secondary MIME type specified by
+ MultipartType parameter. (typical value is 'mixed')
+
+ This part can be used as PartParent for another parts (include next
+ multipart). If you need only one part, then you not need Multipart part.}
+ function AddPartMultipart(const MultipartType: String; const PartParent: TMimePart): TMimePart;
+
+ {:Add MIME part as subpart of PartParent. If you need set root MIME part,
+ then set as PartParent @NIL value. If you need set more then 1 subpart, you
+ must have PartParent of multipart type!
+
+ After creation of part set type to text part and set all necessary
+ properties. Content of part is readed from value stringlist.}
+ function AddPartText(const Value: TStrings; const PartParent: TMimePart): TMimepart;
+
+ {:Add MIME part as subpart of PartParent. If you need set root MIME part,
+ then set as PartParent @NIL value. If you need set more then 1 subpart, you
+ must have PartParent of multipart type!
+
+ After creation of part set type to text part and set all necessary
+ properties. Content of part is readed from value stringlist. You can select
+ your charset and your encoding type. If Raw is @true, then it not doing
+ charset conversion!}
+ function AddPartTextEx(const Value: TStrings; const PartParent: TMimePart;
+ PartCharset: TMimeChar; Raw: Boolean; PartEncoding: TMimeEncoding): TMimepart;
+
+ {:Add MIME part as subpart of PartParent. If you need set root MIME part,
+ then set as PartParent @NIL value. If you need set more then 1 subpart, you
+ must have PartParent of multipart type!
+
+ After creation of part set type to text part to HTML type and set all
+ necessary properties. Content of HTML part is readed from Value stringlist.}
+ function AddPartHTML(const Value: TStrings; const PartParent: TMimePart): TMimepart;
+
+ {:Same as @link(AddPartText), but content is readed from file}
+ function AddPartTextFromFile(const FileName: String; const PartParent: TMimePart): TMimepart;
+
+ {:Same as @link(AddPartHTML), but content is readed from file}
+ function AddPartHTMLFromFile(const FileName: String; const PartParent: TMimePart): TMimepart;
+
+ {:Add MIME part as subpart of PartParent. If you need set root MIME part,
+ then set as PartParent @NIL value. If you need set more then 1 subpart,
+ you must have PartParent of multipart type!
+
+ After creation of part set type to binary and set all necessary properties.
+ MIME primary and secondary types defined automaticly by filename extension.
+ Content of binary part is readed from Stream. This binary part is encoded
+ as file attachment.}
+ function AddPartBinary(const Stream: TStream; const FileName: string; const PartParent: TMimePart): TMimepart;
+
+ {:Same as @link(AddPartBinary), but content is readed from file}
+ function AddPartBinaryFromFile(const FileName: string; const PartParent: TMimePart): TMimepart;
+
+ {:Add MIME part as subpart of PartParent. If you need set root MIME part,
+ then set as PartParent @NIL value. If you need set more then 1 subpart, you
+ must have PartParent of multipart type!
+
+ After creation of part set type to binary and set all necessary properties.
+ MIME primary and secondary types defined automaticly by filename extension.
+ Content of binary part is readed from Stream.
+
+ This binary part is encoded as inline data with given Conten ID (cid).
+ Content ID can be used as reference ID in HTML source in HTML part.}
+ function AddPartHTMLBinary(const Stream: TStream; const FileName, Cid: string; const PartParent: TMimePart): TMimepart;
+
+ {:Same as @link(AddPartHTMLBinary), but content is readed from file}
+ function AddPartHTMLBinaryFromFile(const FileName, Cid: string; const PartParent: TMimePart): TMimepart;
+
+ {:Add MIME part as subpart of PartParent. If you need set root MIME part,
+ then set as PartParent @NIL value. If you need set more then 1 subpart, you
+ must have PartParent of multipart type!
+
+ After creation of part set type to message and set all necessary properties.
+ MIME primary and secondary types are setted to 'message/rfc822'.
+ Content of raw RFC-822 message is readed from Stream.}
+ function AddPartMess(const Value: TStrings; const PartParent: TMimePart): TMimepart;
+
+ {:Same as @link(AddPartMess), but content is readed from file}
+ function AddPartMessFromFile(const FileName: string; const PartParent: TMimePart): TMimepart;
+
+ {:Compose message from @link(MessagePart) to @link(Lines). Headers from
+ @link(Header) object is added also.}
+ procedure EncodeMessage;
+
+ {:Decode message from @link(Lines) to @link(MessagePart). Massage headers
+ are parsed into @link(Header) object.}
+ procedure DecodeMessage;
+ published
+ {:@link(TMimePart) object with decoded MIME message. This object can handle
+ any number of nested @link(TMimePart) objects itself. It is used for handle
+ any tree of MIME subparts.}
+ property MessagePart: TMimePart read FMessagePart;
+
+ {:Raw MIME encoded message.}
+ property Lines: TStringList read FLines;
+
+ {:Object for e-mail header fields. This object is created automaticly.
+ Do not free this object!}
+ property Header: TMessHeader read FHeader;
+ end;
+
+implementation
+
+{==============================================================================}
+
+constructor TMessHeader.Create;
+begin
+ inherited Create;
+ FToList := TStringList.Create;
+ FCCList := TStringList.Create;
+ FCustomHeaders := TStringList.Create;
+ FCharsetCode := GetCurCP;
+end;
+
+destructor TMessHeader.Destroy;
+begin
+ FCustomHeaders.Free;
+ FCCList.Free;
+ FToList.Free;
+ inherited Destroy;
+end;
+
+{==============================================================================}
+
+procedure TMessHeader.Clear;
+begin
+ FFrom := '';
+ FToList.Clear;
+ FCCList.Clear;
+ FSubject := '';
+ FOrganization := '';
+ FCustomHeaders.Clear;
+ FDate := 0;
+ FXMailer := '';
+ FReplyTo := '';
+ FMessageID := '';
+ FPriority := MP_unknown;
+end;
+
+procedure TMessHeader.EncodeHeaders(const Value: TStrings);
+var
+ n: Integer;
+ s: string;
+begin
+ if FDate = 0 then
+ FDate := Now;
+ for n := FCustomHeaders.Count - 1 downto 0 do
+ if FCustomHeaders[n] <> '' then
+ Value.Insert(0, FCustomHeaders[n]);
+ if FPriority <> MP_unknown then
+ case FPriority of
+ MP_high:
+ begin
+ Value.Insert(0, 'X-MSMAIL-Priority: High');
+ Value.Insert(0, 'X-Priority: 1');
+ Value.Insert(0, 'Priority: urgent');
+ end;
+ MP_low:
+ begin
+ Value.Insert(0, 'X-MSMAIL-Priority: low');
+ Value.Insert(0, 'X-Priority: 5');
+ Value.Insert(0, 'Priority: non-urgent');
+ end;
+ end;
+ if FReplyTo <> '' then
+ Value.Insert(0, 'Reply-To: ' + GetEmailAddr(FReplyTo));
+ if FMessageID <> '' then
+ Value.Insert(0, 'Message-ID: <' + trim(FMessageID) + '>');
+ if FXMailer = '' then
+ Value.Insert(0, 'X-mailer: Synapse - Pascal TCP/IP library by Lukas Gebauer')
+ else
+ Value.Insert(0, 'X-mailer: ' + FXMailer);
+ Value.Insert(0, 'MIME-Version: 1.0 (produced by Synapse)');
+ if FOrganization <> '' then
+ Value.Insert(0, 'Organization: ' + InlineCodeEx(FOrganization, FCharsetCode));
+ s := '';
+ for n := 0 to FCCList.Count - 1 do
+ if s = '' then
+ s := InlineEmailEx(FCCList[n], FCharsetCode)
+ else
+ s := s + ', ' + InlineEmailEx(FCCList[n], FCharsetCode);
+ if s <> '' then
+ Value.Insert(0, 'CC: ' + s);
+ Value.Insert(0, 'Date: ' + Rfc822DateTime(FDate));
+ if FSubject <> '' then
+ Value.Insert(0, 'Subject: ' + InlineCodeEx(FSubject, FCharsetCode));
+ s := '';
+ for n := 0 to FToList.Count - 1 do
+ if s = '' then
+ s := InlineEmailEx(FToList[n], FCharsetCode)
+ else
+ s := s + ', ' + InlineEmailEx(FToList[n], FCharsetCode);
+ if s <> '' then
+ Value.Insert(0, 'To: ' + s);
+ Value.Insert(0, 'From: ' + InlineEmailEx(FFrom, FCharsetCode));
+end;
+
+function TMessHeader.ParsePriority(value: string): TMessPriority;
+var
+ s: string;
+ x: integer;
+begin
+ Result := MP_unknown;
+ s := Trim(separateright(value, ':'));
+ s := Separateleft(s, ' ');
+ x := StrToIntDef(s, -1);
+ if x >= 0 then
+ case x of
+ 1, 2:
+ Result := MP_High;
+ 3:
+ Result := MP_Normal;
+ 4, 5:
+ Result := MP_Low;
+ end
+ else
+ begin
+ s := lowercase(s);
+ if (s = 'urgent') or (s = 'high') or (s = 'highest') then
+ Result := MP_High;
+ if (s = 'normal') or (s = 'medium') then
+ Result := MP_Normal;
+ if (s = 'low') or (s = 'lowest')
+ or (s = 'no-priority') or (s = 'non-urgent') then
+ Result := MP_Low;
+ end;
+end;
+
+function TMessHeader.DecodeHeader(value: string): boolean;
+var
+ s, t: string;
+ cp: TMimeChar;
+begin
+ Result := True;
+ cp := FCharsetCode;
+ s := uppercase(value);
+ if Pos('X-MAILER:', s) = 1 then
+ begin
+ FXMailer := Trim(SeparateRight(Value, ':'));
+ Exit;
+ end;
+ if Pos('FROM:', s) = 1 then
+ begin
+ FFrom := InlineDecode(Trim(SeparateRight(Value, ':')), cp);
+ Exit;
+ end;
+ if Pos('SUBJECT:', s) = 1 then
+ begin
+ FSubject := InlineDecode(Trim(SeparateRight(Value, ':')), cp);
+ Exit;
+ end;
+ if Pos('ORGANIZATION:', s) = 1 then
+ begin
+ FOrganization := InlineDecode(Trim(SeparateRight(Value, ':')), cp);
+ Exit;
+ end;
+ if Pos('TO:', s) = 1 then
+ begin
+ s := Trim(SeparateRight(Value, ':'));
+ repeat
+ t := InlineDecode(Trim(FetchEx(s, ',', '"')), cp);
+ if t <> '' then
+ FToList.Add(t);
+ until s = '';
+ Exit;
+ end;
+ if Pos('CC:', s) = 1 then
+ begin
+ s := Trim(SeparateRight(Value, ':'));
+ repeat
+ t := InlineDecode(Trim(FetchEx(s, ',', '"')), cp);
+ if t <> '' then
+ FCCList.Add(t);
+ until s = '';
+ Exit;
+ end;
+ if Pos('DATE:', s) = 1 then
+ begin
+ FDate := DecodeRfcDateTime(Trim(SeparateRight(Value, ':')));
+ Exit;
+ end;
+ if Pos('REPLY-TO:', s) = 1 then
+ begin
+ FReplyTo := InlineDecode(Trim(SeparateRight(Value, ':')), cp);
+ Exit;
+ end;
+ if Pos('MESSAGE-ID:', s) = 1 then
+ begin
+ FMessageID := GetEmailAddr(Trim(SeparateRight(Value, ':')));
+ Exit;
+ end;
+ if Pos('PRIORITY:', s) = 1 then
+ begin
+ FPri := ParsePriority(value);
+ Exit;
+ end;
+ if Pos('X-PRIORITY:', s) = 1 then
+ begin
+ FXPri := ParsePriority(value);
+ Exit;
+ end;
+ if Pos('X-MSMAIL-PRIORITY:', s) = 1 then
+ begin
+ FXmsPri := ParsePriority(value);
+ Exit;
+ end;
+ if Pos('MIME-VERSION:', s) = 1 then
+ Exit;
+ if Pos('CONTENT-TYPE:', s) = 1 then
+ Exit;
+ if Pos('CONTENT-DESCRIPTION:', s) = 1 then
+ Exit;
+ if Pos('CONTENT-DISPOSITION:', s) = 1 then
+ Exit;
+ if Pos('CONTENT-ID:', s) = 1 then
+ Exit;
+ if Pos('CONTENT-TRANSFER-ENCODING:', s) = 1 then
+ Exit;
+ Result := False;
+end;
+
+procedure TMessHeader.DecodeHeaders(const Value: TStrings);
+var
+ s: string;
+ x: Integer;
+begin
+ Clear;
+ Fpri := MP_unknown;
+ Fxpri := MP_unknown;
+ Fxmspri := MP_unknown;
+ x := 0;
+ while Value.Count > x do
+ begin
+ s := NormalizeHeader(Value, x);
+ if s = '' then
+ Break;
+ if not DecodeHeader(s) then
+ FCustomHeaders.Add(s);
+ end;
+ if Fpri <> MP_unknown then
+ FPriority := Fpri
+ else
+ if Fxpri <> MP_unknown then
+ FPriority := Fxpri
+ else
+ if Fxmspri <> MP_unknown then
+ FPriority := Fxmspri
+end;
+
+function TMessHeader.FindHeader(Value: string): string;
+var
+ n: integer;
+begin
+ Result := '';
+ for n := 0 to FCustomHeaders.Count - 1 do
+ if Pos(UpperCase(Value), UpperCase(FCustomHeaders[n])) = 1 then
+ begin
+ Result := Trim(SeparateRight(FCustomHeaders[n], ':'));
+ break;
+ end;
+end;
+
+procedure TMessHeader.FindHeaderList(Value: string; const HeaderList: TStrings);
+var
+ n: integer;
+begin
+ HeaderList.Clear;
+ for n := 0 to FCustomHeaders.Count - 1 do
+ if Pos(UpperCase(Value), UpperCase(FCustomHeaders[n])) = 1 then
+ begin
+ HeaderList.Add(Trim(SeparateRight(FCustomHeaders[n], ':')));
+ end;
+end;
+
+{==============================================================================}
+
+constructor TMimeMess.Create;
+begin
+ CreateAltHeaders(TMessHeader);
+end;
+
+constructor TMimeMess.CreateAltHeaders(HeadClass: TMessHeaderClass);
+begin
+ inherited Create;
+ FMessagePart := TMimePart.Create;
+ FLines := TStringList.Create;
+ FHeader := HeadClass.Create;
+end;
+
+destructor TMimeMess.Destroy;
+begin
+ FMessagePart.Free;
+ FHeader.Free;
+ FLines.Free;
+ inherited Destroy;
+end;
+
+{==============================================================================}
+
+procedure TMimeMess.Clear;
+begin
+ FMessagePart.Clear;
+ FLines.Clear;
+ FHeader.Clear;
+end;
+
+{==============================================================================}
+
+function TMimeMess.AddPart(const PartParent: TMimePart): TMimePart;
+begin
+ if PartParent = nil then
+ Result := FMessagePart
+ else
+ Result := PartParent.AddSubPart;
+ Result.Clear;
+end;
+
+{==============================================================================}
+
+function TMimeMess.AddPartMultipart(const MultipartType: String; const PartParent: TMimePart): TMimePart;
+begin
+ Result := AddPart(PartParent);
+ with Result do
+ begin
+ Primary := 'Multipart';
+ Secondary := MultipartType;
+ Description := 'Multipart message';
+ Boundary := GenerateBoundary;
+ EncodePartHeader;
+ end;
+end;
+
+function TMimeMess.AddPartText(const Value: TStrings; const PartParent: TMimePart): TMimepart;
+begin
+ Result := AddPart(PartParent);
+ with Result do
+ begin
+ Value.SaveToStream(DecodedLines);
+ Primary := 'text';
+ Secondary := 'plain';
+ Description := 'Message text';
+ Disposition := 'inline';
+ CharsetCode := IdealCharsetCoding(Value.Text, TargetCharset, IdealCharsets);
+ EncodingCode := ME_QUOTED_PRINTABLE;
+ EncodePart;
+ EncodePartHeader;
+ end;
+end;
+
+function TMimeMess.AddPartTextEx(const Value: TStrings; const PartParent: TMimePart;
+ PartCharset: TMimeChar; Raw: Boolean; PartEncoding: TMimeEncoding): TMimepart;
+begin
+ Result := AddPart(PartParent);
+ with Result do
+ begin
+ Value.SaveToStream(DecodedLines);
+ Primary := 'text';
+ Secondary := 'plain';
+ Description := 'Message text';
+ Disposition := 'inline';
+ CharsetCode := PartCharset;
+ EncodingCode := PartEncoding;
+ ConvertCharset := not Raw;
+ EncodePart;
+ EncodePartHeader;
+ end;
+end;
+
+function TMimeMess.AddPartHTML(const Value: TStrings; const PartParent: TMimePart): TMimepart;
+begin
+ Result := AddPart(PartParent);
+ with Result do
+ begin
+ Value.SaveToStream(DecodedLines);
+ Primary := 'text';
+ Secondary := 'html';
+ Description := 'HTML text';
+ Disposition := 'inline';
+ CharsetCode := UTF_8;
+ EncodingCode := ME_QUOTED_PRINTABLE;
+ EncodePart;
+ EncodePartHeader;
+ end;
+end;
+
+function TMimeMess.AddPartTextFromFile(const FileName: String; const PartParent: TMimePart): TMimepart;
+var
+ tmp: TStrings;
+begin
+ tmp := TStringList.Create;
+ try
+ tmp.LoadFromFile(FileName);
+ Result := AddPartText(tmp, PartParent);
+ Finally
+ tmp.Free;
+ end;
+end;
+
+function TMimeMess.AddPartHTMLFromFile(const FileName: String; const PartParent: TMimePart): TMimepart;
+var
+ tmp: TStrings;
+begin
+ tmp := TStringList.Create;
+ try
+ tmp.LoadFromFile(FileName);
+ Result := AddPartHTML(tmp, PartParent);
+ Finally
+ tmp.Free;
+ end;
+end;
+
+function TMimeMess.AddPartBinary(const Stream: TStream; const FileName: string; const PartParent: TMimePart): TMimepart;
+begin
+ Result := AddPart(PartParent);
+ Result.DecodedLines.LoadFromStream(Stream);
+ Result.MimeTypeFromExt(FileName);
+ Result.Description := 'Attached file: ' + FileName;
+ Result.Disposition := 'attachment';
+ Result.FileName := FileName;
+ Result.EncodingCode := ME_BASE64;
+ Result.EncodePart;
+ Result.EncodePartHeader;
+end;
+
+function TMimeMess.AddPartBinaryFromFile(const FileName: string; const PartParent: TMimePart): TMimepart;
+var
+ tmp: TMemoryStream;
+begin
+ tmp := TMemoryStream.Create;
+ try
+ tmp.LoadFromFile(FileName);
+ Result := AddPartBinary(tmp, ExtractFileName(FileName), PartParent);
+ finally
+ tmp.Free;
+ end;
+end;
+
+function TMimeMess.AddPartHTMLBinary(const Stream: TStream; const FileName, Cid: string; const PartParent: TMimePart): TMimepart;
+begin
+ Result := AddPart(PartParent);
+ Result.DecodedLines.LoadFromStream(Stream);
+ Result.MimeTypeFromExt(FileName);
+ Result.Description := 'Included file: ' + FileName;
+ Result.Disposition := 'inline';
+ Result.ContentID := Cid;
+ Result.FileName := FileName;
+ Result.EncodingCode := ME_BASE64;
+ Result.EncodePart;
+ Result.EncodePartHeader;
+end;
+
+function TMimeMess.AddPartHTMLBinaryFromFile(const FileName, Cid: string; const PartParent: TMimePart): TMimepart;
+var
+ tmp: TMemoryStream;
+begin
+ tmp := TMemoryStream.Create;
+ try
+ tmp.LoadFromFile(FileName);
+ Result :=AddPartHTMLBinary(tmp, ExtractFileName(FileName), Cid, PartParent);
+ finally
+ tmp.Free;
+ end;
+end;
+
+function TMimeMess.AddPartMess(const Value: TStrings; const PartParent: TMimePart): TMimepart;
+var
+ part: Tmimepart;
+begin
+ Result := AddPart(PartParent);
+ part := AddPart(result);
+ part.lines.addstrings(Value);
+ part.DecomposeParts;
+ with Result do
+ begin
+ Primary := 'message';
+ Secondary := 'rfc822';
+ Description := 'E-mail Message';
+ EncodePart;
+ EncodePartHeader;
+ end;
+end;
+
+function TMimeMess.AddPartMessFromFile(const FileName: String; const PartParent: TMimePart): TMimepart;
+var
+ tmp: TStrings;
+begin
+ tmp := TStringList.Create;
+ try
+ tmp.LoadFromFile(FileName);
+ Result := AddPartMess(tmp, PartParent);
+ Finally
+ tmp.Free;
+ end;
+end;
+
+{==============================================================================}
+
+procedure TMimeMess.EncodeMessage;
+var
+ l: TStringList;
+ x: integer;
+begin
+ //merge headers from THeaders and header field from MessagePart
+ l := TStringList.Create;
+ try
+ FHeader.EncodeHeaders(l);
+ x := IndexByBegin('CONTENT-TYPE', FMessagePart.Headers);
+ if x >= 0 then
+ l.add(FMessagePart.Headers[x]);
+ x := IndexByBegin('CONTENT-DESCRIPTION', FMessagePart.Headers);
+ if x >= 0 then
+ l.add(FMessagePart.Headers[x]);
+ x := IndexByBegin('CONTENT-DISPOSITION', FMessagePart.Headers);
+ if x >= 0 then
+ l.add(FMessagePart.Headers[x]);
+ x := IndexByBegin('CONTENT-ID', FMessagePart.Headers);
+ if x >= 0 then
+ l.add(FMessagePart.Headers[x]);
+ x := IndexByBegin('CONTENT-TRANSFER-ENCODING', FMessagePart.Headers);
+ if x >= 0 then
+ l.add(FMessagePart.Headers[x]);
+ FMessagePart.Headers.Assign(l);
+ finally
+ l.Free;
+ end;
+ FMessagePart.ComposeParts;
+ FLines.Assign(FMessagePart.Lines);
+end;
+
+{==============================================================================}
+
+procedure TMimeMess.DecodeMessage;
+begin
+ FHeader.Clear;
+ FHeader.DecodeHeaders(FLines);
+ FMessagePart.Lines.Assign(FLines);
+ FMessagePart.DecomposeParts;
+end;
+
+end.
diff --git a/branches/script-component/Units/Synapse/mimepart.pas b/branches/script-component/Units/Synapse/mimepart.pas
new file mode 100644
index 0000000..5c29aaf
--- /dev/null
+++ b/branches/script-component/Units/Synapse/mimepart.pas
@@ -0,0 +1,1089 @@
+{==============================================================================|
+| Project : Ararat Synapse | 002.008.000 |
+|==============================================================================|
+| Content: MIME support procedures and functions |
+|==============================================================================|
+| Copyright (c)1999-2008, Lukas Gebauer |
+| All rights reserved. |
+| |
+| Redistribution and use in source and binary forms, with or without |
+| modification, are permitted provided that the following conditions are met: |
+| |
+| Redistributions of source code must retain the above copyright notice, this |
+| list of conditions and the following disclaimer. |
+| |
+| Redistributions in binary form must reproduce the above copyright notice, |
+| this list of conditions and the following disclaimer in the documentation |
+| and/or other materials provided with the distribution. |
+| |
+| Neither the name of Lukas Gebauer nor the names of its contributors may |
+| be used to endorse or promote products derived from this software without |
+| specific prior written permission. |
+| |
+| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
+| AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
+| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
+| ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR |
+| ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
+| DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
+| SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
+| CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
+| LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
+| OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
+| DAMAGE. |
+|==============================================================================|
+| The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).|
+| Portions created by Lukas Gebauer are Copyright (c)2000-2008. |
+| All Rights Reserved. |
+|==============================================================================|
+| Contributor(s): |
+|==============================================================================|
+| History: see HISTORY.HTM from distribution package |
+| (Found at URL: http://www.ararat.cz/synapse/) |
+|==============================================================================}
+
+{:@abstract(MIME part handling)
+Handling with MIME parts.
+
+Used RFC: RFC-2045
+}
+
+{$IFDEF FPC}
+ {$MODE DELPHI}
+{$ENDIF}
+{$H+}
+{$Q-}
+{$R-}
+
+unit mimepart;
+
+interface
+
+uses
+ SysUtils, Classes,
+ synafpc,
+ synachar, synacode, synautil, mimeinln;
+
+type
+
+ TMimePart = class;
+
+ {:@abstract(Procedural type for @link(TMimepart.Walkpart) hook). This hook is used for
+ easy walking through MIME subparts.}
+ THookWalkPart = procedure(const Sender: TMimePart) of object;
+
+ {:The four types of MIME parts. (textual, multipart, message or any other
+ binary data.)}
+ TMimePrimary = (MP_TEXT, MP_MULTIPART, MP_MESSAGE, MP_BINARY);
+
+ {:The various types of possible part encodings.}
+ TMimeEncoding = (ME_7BIT, ME_8BIT, ME_QUOTED_PRINTABLE,
+ ME_BASE64, ME_UU, ME_XX);
+
+ {:@abstract(Object for working with parts of MIME e-mail.)
+ Each TMimePart object can handle any number of nested subparts as new
+ TMimepart objects. It can handle any tree hierarchy structure of nested MIME
+ subparts itself.
+
+ Basic tasks are:
+
+ Decoding of MIME message:
+ - store message into Lines property
+ - call DecomposeParts. Now you have decomposed MIME parts in all nested levels!
+ - now you can explore all properties and subparts. (You can use WalkPart method)
+ - if you need decode part, call DecodePart.
+
+ Encoding of MIME message:
+
+ - if you need multipart message, you must create subpart by AddSubPart.
+ - set all properties of all parts.
+ - set content of part into DecodedLines stream
+ - encode this stream by EncodePart.
+ - compose full message by ComposeParts. (it build full MIME message from all subparts. Do not call this method for each subpart! It is needed on root part!)
+ - encoded MIME message is stored in Lines property.
+ }
+ TMimePart = class(TObject)
+ private
+ FPrimary: string;
+ FPrimaryCode: TMimePrimary;
+ FSecondary: string;
+ FEncoding: string;
+ FEncodingCode: TMimeEncoding;
+ FDefaultCharset: string;
+ FCharset: string;
+ FCharsetCode: TMimeChar;
+ FTargetCharset: TMimeChar;
+ FDescription: string;
+ FDisposition: string;
+ FContentID: string;
+ FBoundary: string;
+ FFileName: string;
+ FLines: TStringList;
+ FPartBody: TStringList;
+ FHeaders: TStringList;
+ FPrePart: TStringList;
+ FPostPart: TStringList;
+ FDecodedLines: TMemoryStream;
+ FSubParts: TList;
+ FOnWalkPart: THookWalkPart;
+ FMaxLineLength: integer;
+ FSubLevel: integer;
+ FMaxSubLevel: integer;
+ FAttachInside: boolean;
+ FConvertCharset: Boolean;
+ FForcedHTMLConvert: Boolean;
+ procedure SetPrimary(Value: string);
+ procedure SetEncoding(Value: string);
+ procedure SetCharset(Value: string);
+ function IsUUcode(Value: string): boolean;
+ public
+ constructor Create;
+ destructor Destroy; override;
+
+ {:Assign content of another object to this object. (Only this part,
+ not subparts!)}
+ procedure Assign(Value: TMimePart);
+
+ {:Assign content of another object to this object. (With all subparts!)}
+ procedure AssignSubParts(Value: TMimePart);
+
+ {:Clear all data values to default values. It also call @link(ClearSubparts).}
+ procedure Clear;
+
+ {:Decode Mime part from @link(Lines) to @link(DecodedLines).}
+ procedure DecodePart;
+
+ {:Parse header lines from Headers property into another properties.}
+ procedure DecodePartHeader;
+
+ {:Encode mime part from @link(DecodedLines) to @link(Lines) and build mime
+ headers.}
+ procedure EncodePart;
+
+ {:Build header lines in Headers property from another properties.}
+ procedure EncodePartHeader;
+
+ {:generate primary and secondary mime type from filename extension in value.
+ If type not recognised, it return 'Application/octet-string' type.}
+ procedure MimeTypeFromExt(Value: string);
+
+ {:Return number of decomposed subparts. (On this level! Each of this
+ subparts can hold any number of their own nested subparts!)}
+ function GetSubPartCount: integer;
+
+ {:Get nested subpart object as new TMimePart. For getting maximum possible
+ index you can use @link(GetSubPartCount) method.}
+ function GetSubPart(index: integer): TMimePart;
+
+ {:delete subpart on given index.}
+ procedure DeleteSubPart(index: integer);
+
+ {:Clear and destroy all subpart TMimePart objects.}
+ procedure ClearSubParts;
+
+ {:Add and create new subpart.}
+ function AddSubPart: TMimePart;
+
+ {:E-mail message in @link(Lines) property is parsed into this object.
+ E-mail headers are stored in @link(Headers) property and is parsed into
+ another properties automaticly. Not need call @link(DecodePartHeader)!
+ Content of message (part) is stored into @link(PartBody) property. This
+ part is in undecoded form! If you need decode it, then you must call
+ @link(DecodePart) method by your hands. Lot of another properties is filled
+ also.
+
+ Decoding of parts you must call separately due performance reasons. (Not
+ needed to decode all parts in all reasons.)
+
+ For each MIME subpart is created new TMimepart object (accessible via
+ method @link(GetSubPart)).}
+ procedure DecomposeParts;
+
+ {:This part and all subparts is composed into one MIME message stored in
+ @link(Lines) property.}
+ procedure ComposeParts;
+
+ {:By calling this method is called @link(OnWalkPart) event for each part
+ and their subparts. It is very good for calling some code for each part in
+ MIME message}
+ procedure WalkPart;
+
+ {:Return @true when is possible create next subpart. (@link(maxSublevel)
+ is still not reached)}
+ function CanSubPart: boolean;
+ published
+ {:Primary Mime type of part. (i.e. 'application') Writing to this property
+ automaticly generate value of @link(PrimaryCode).}
+ property Primary: string read FPrimary write SetPrimary;
+
+ {:String representation of used Mime encoding in part. (i.e. 'base64')
+ Writing to this property automaticly generate value of @link(EncodingCode).}
+ property Encoding: string read FEncoding write SetEncoding;
+
+ {:String representation of used Mime charset in part. (i.e. 'iso-8859-1')
+ Writing to this property automaticly generate value of @link(CharsetCode).
+ Charset is used only for text parts.}
+ property Charset: string read FCharset write SetCharset;
+
+ {:Define default charset for decoding text MIME parts without charset
+ specification. Default value is 'ISO-8859-1' by RCF documents.
+ But Microsoft Outlook use windows codings as default. This property allows
+ properly decode textual parts from some broken versions of Microsoft
+ Outlook. (this is bad software!)}
+ property DefaultCharset: string read FDefaultCharset write FDefaultCharset;
+
+ {:Decoded primary type. Possible values are: MP_TEXT, MP_MULTIPART,
+ MP_MESSAGE and MP_BINARY. If type not recognised, result is MP_BINARY.}
+ property PrimaryCode: TMimePrimary read FPrimaryCode Write FPrimaryCode;
+
+ {:Decoded encoding type. Possible values are: ME_7BIT, ME_8BIT,
+ ME_QUOTED_PRINTABLE and ME_BASE64. If type not recognised, result is
+ ME_7BIT.}
+ property EncodingCode: TMimeEncoding read FEncodingCode Write FEncodingCode;
+
+ {:Decoded charset type. Possible values are defined in @link(SynaChar) unit.}
+ property CharsetCode: TMimeChar read FCharsetCode Write FCharsetCode;
+
+ {:System charset type. Default value is charset used by default in your
+ operating system.}
+ property TargetCharset: TMimeChar read FTargetCharset Write FTargetCharset;
+
+ {:If @true, then do internal charset translation of part content between @link(CharsetCode)
+ and @link(TargetCharset)}
+ property ConvertCharset: Boolean read FConvertCharset Write FConvertCharset;
+
+ {:If @true, then allways do internal charset translation of HTML parts
+ by MIME even it have their own charset in META tag. Default is @false.}
+ property ForcedHTMLConvert: Boolean read FForcedHTMLConvert Write FForcedHTMLConvert;
+
+ {:Secondary Mime type of part. (i.e. 'mixed')}
+ property Secondary: string read FSecondary Write FSecondary;
+
+ {:Description of Mime part.}
+ property Description: string read FDescription Write FDescription;
+
+ {:Value of content disposition field. (i.e. 'inline' or 'attachment')}
+ property Disposition: string read FDisposition Write FDisposition;
+
+ {:Content ID.}
+ property ContentID: string read FContentID Write FContentID;
+
+ {:Boundary delimiter of multipart Mime part. Used only in multipart part.}
+ property Boundary: string read FBoundary Write FBoundary;
+
+ {:Filename of file in binary part.}
+ property FileName: string read FFileName Write FFileName;
+
+ {:String list with lines contains mime part (It can be a full message).}
+ property Lines: TStringList read FLines;
+
+ {:Encoded form of MIME part data.}
+ property PartBody: TStringList read FPartBody;
+
+ {:All header lines of MIME part.}
+ property Headers: TStringList read FHeaders;
+
+ {:On multipart this contains part of message between first line of message
+ and first boundary.}
+ property PrePart: TStringList read FPrePart;
+
+ {:On multipart this contains part of message between last boundary and end
+ of message.}
+ property PostPart: TStringList read FPostPart;
+
+ {:Stream with decoded form of budy part.}
+ property DecodedLines: TMemoryStream read FDecodedLines;
+
+ {:Show nested level in subpart tree. Value 0 means root part. 1 means
+ subpart from this root. etc.}
+ property SubLevel: integer read FSubLevel write FSubLevel;
+
+ {:Specify maximum sublevel value for decomposing.}
+ property MaxSubLevel: integer read FMaxSubLevel write FMaxSubLevel;
+
+ {:When is @true, then this part maybe(!) have included some uuencoded binary
+ data.}
+ property AttachInside: boolean read FAttachInside;
+
+ {:Here you can assign hook procedure for walking through all part and their
+ subparts.}
+ property OnWalkPart: THookWalkPart read FOnWalkPart write FOnWalkPart;
+
+ {:Here you can specify maximum line length for encoding of MIME part.
+ If line is longer, then is splitted by standard of MIME. Correct MIME
+ mailers can de-split this line into original length.}
+ property MaxLineLength: integer read FMaxLineLength Write FMaxLineLength;
+ end;
+
+const
+ MaxMimeType = 25;
+ MimeType: array[0..MaxMimeType, 0..2] of string =
+ (
+ ('AU', 'audio', 'basic'),
+ ('AVI', 'video', 'x-msvideo'),
+ ('BMP', 'image', 'BMP'),
+ ('DOC', 'application', 'MSWord'),
+ ('EPS', 'application', 'Postscript'),
+ ('GIF', 'image', 'GIF'),
+ ('JPEG', 'image', 'JPEG'),
+ ('JPG', 'image', 'JPEG'),
+ ('MID', 'audio', 'midi'),
+ ('MOV', 'video', 'quicktime'),
+ ('MPEG', 'video', 'MPEG'),
+ ('MPG', 'video', 'MPEG'),
+ ('MP2', 'audio', 'mpeg'),
+ ('MP3', 'audio', 'mpeg'),
+ ('PDF', 'application', 'PDF'),
+ ('PNG', 'image', 'PNG'),
+ ('PS', 'application', 'Postscript'),
+ ('QT', 'video', 'quicktime'),
+ ('RA', 'audio', 'x-realaudio'),
+ ('RTF', 'application', 'RTF'),
+ ('SND', 'audio', 'basic'),
+ ('TIF', 'image', 'TIFF'),
+ ('TIFF', 'image', 'TIFF'),
+ ('WAV', 'audio', 'x-wav'),
+ ('WPD', 'application', 'Wordperfect5.1'),
+ ('ZIP', 'application', 'ZIP')
+ );
+
+{:Generates a unique boundary string.}
+function GenerateBoundary: string;
+
+implementation
+
+{==============================================================================}
+
+constructor TMIMEPart.Create;
+begin
+ inherited Create;
+ FOnWalkPart := nil;
+ FLines := TStringList.Create;
+ FPartBody := TStringList.Create;
+ FHeaders := TStringList.Create;
+ FPrePart := TStringList.Create;
+ FPostPart := TStringList.Create;
+ FDecodedLines := TMemoryStream.Create;
+ FSubParts := TList.Create;
+ FTargetCharset := GetCurCP;
+ //was 'US-ASCII' before, but RFC-ignorant Outlook sometimes using default
+ //system charset instead.
+ FDefaultCharset := GetIDFromCP(GetCurCP);
+ FMaxLineLength := 78;
+ FSubLevel := 0;
+ FMaxSubLevel := -1;
+ FAttachInside := false;
+ FConvertCharset := true;
+ FForcedHTMLConvert := false;
+end;
+
+destructor TMIMEPart.Destroy;
+begin
+ ClearSubParts;
+ FSubParts.Free;
+ FDecodedLines.Free;
+ FPartBody.Free;
+ FLines.Free;
+ FHeaders.Free;
+ FPrePart.Free;
+ FPostPart.Free;
+ inherited Destroy;
+end;
+
+{==============================================================================}
+
+procedure TMIMEPart.Clear;
+begin
+ FPrimary := '';
+ FEncoding := '';
+ FCharset := '';
+ FPrimaryCode := MP_TEXT;
+ FEncodingCode := ME_7BIT;
+ FCharsetCode := ISO_8859_1;
+ FTargetCharset := GetCurCP;
+ FSecondary := '';
+ FDisposition := '';
+ FContentID := '';
+ FDescription := '';
+ FBoundary := '';
+ FFileName := '';
+ FAttachInside := False;
+ FPartBody.Clear;
+ FHeaders.Clear;
+ FPrePart.Clear;
+ FPostPart.Clear;
+ FDecodedLines.Clear;
+ FConvertCharset := true;
+ FForcedHTMLConvert := false;
+ ClearSubParts;
+end;
+
+{==============================================================================}
+
+procedure TMIMEPart.Assign(Value: TMimePart);
+begin
+ Primary := Value.Primary;
+ Encoding := Value.Encoding;
+ Charset := Value.Charset;
+ DefaultCharset := Value.DefaultCharset;
+ PrimaryCode := Value.PrimaryCode;
+ EncodingCode := Value.EncodingCode;
+ CharsetCode := Value.CharsetCode;
+ TargetCharset := Value.TargetCharset;
+ Secondary := Value.Secondary;
+ Description := Value.Description;
+ Disposition := Value.Disposition;
+ ContentID := Value.ContentID;
+ Boundary := Value.Boundary;
+ FileName := Value.FileName;
+ Lines.Assign(Value.Lines);
+ PartBody.Assign(Value.PartBody);
+ Headers.Assign(Value.Headers);
+ PrePart.Assign(Value.PrePart);
+ PostPart.Assign(Value.PostPart);
+ MaxLineLength := Value.MaxLineLength;
+ FAttachInside := Value.AttachInside;
+ FConvertCharset := Value.ConvertCharset;
+end;
+
+{==============================================================================}
+
+procedure TMIMEPart.AssignSubParts(Value: TMimePart);
+var
+ n: integer;
+ p: TMimePart;
+begin
+ Assign(Value);
+ for n := 0 to Value.GetSubPartCount - 1 do
+ begin
+ p := AddSubPart;
+ p.AssignSubParts(Value.GetSubPart(n));
+ end;
+end;
+
+{==============================================================================}
+
+function TMIMEPart.GetSubPartCount: integer;
+begin
+ Result := FSubParts.Count;
+end;
+
+{==============================================================================}
+
+function TMIMEPart.GetSubPart(index: integer): TMimePart;
+begin
+ Result := nil;
+ if Index < GetSubPartCount then
+ Result := TMimePart(FSubParts[Index]);
+end;
+
+{==============================================================================}
+
+procedure TMIMEPart.DeleteSubPart(index: integer);
+begin
+ if Index < GetSubPartCount then
+ begin
+ GetSubPart(Index).Free;
+ FSubParts.Delete(Index);
+ end;
+end;
+
+{==============================================================================}
+
+procedure TMIMEPart.ClearSubParts;
+var
+ n: integer;
+begin
+ for n := 0 to GetSubPartCount - 1 do
+ TMimePart(FSubParts[n]).Free;
+ FSubParts.Clear;
+end;
+
+{==============================================================================}
+
+function TMIMEPart.AddSubPart: TMimePart;
+begin
+ Result := TMimePart.Create;
+ Result.DefaultCharset := FDefaultCharset;
+ FSubParts.Add(Result);
+ Result.SubLevel := FSubLevel + 1;
+ Result.MaxSubLevel := FMaxSubLevel;
+end;
+
+{==============================================================================}
+
+procedure TMIMEPart.DecomposeParts;
+var
+ x: integer;
+ s: string;
+ Mime: TMimePart;
+
+ procedure SkipEmpty;
+ begin
+ while FLines.Count > x do
+ begin
+ s := TrimRight(FLines[x]);
+ if s <> '' then
+ Break;
+ Inc(x);
+ end;
+ end;
+
+begin
+ x := 0;
+ Clear;
+ //extract headers
+ while FLines.Count > x do
+ begin
+ s := NormalizeHeader(FLines, x);
+ if s = '' then
+ Break;
+ FHeaders.Add(s);
+ end;
+ DecodePartHeader;
+ //extract prepart
+ if FPrimaryCode = MP_MULTIPART then
+ begin
+ while FLines.Count > x do
+ begin
+ s := FLines[x];
+ Inc(x);
+ if TrimRight(s) = '--' + FBoundary then
+ Break;
+ FPrePart.Add(s);
+ if not FAttachInside then
+ FAttachInside := IsUUcode(s);
+ end;
+ end;
+ //extract body part
+ if FPrimaryCode = MP_MULTIPART then
+ begin
+ repeat
+ if CanSubPart then
+ begin
+ Mime := AddSubPart;
+ while FLines.Count > x do
+ begin
+ s := FLines[x];
+ Inc(x);
+ if Pos('--' + FBoundary, s) = 1 then
+ Break;
+ Mime.Lines.Add(s);
+ end;
+ Mime.DecomposeParts;
+ end
+ else
+ begin
+ s := FLines[x];
+ Inc(x);
+ FPartBody.Add(s);
+ end;
+ if x >= FLines.Count then
+ break;
+ until s = '--' + FBoundary + '--';
+ end;
+ if (FPrimaryCode = MP_MESSAGE) and CanSubPart then
+ begin
+ Mime := AddSubPart;
+ SkipEmpty;
+ while FLines.Count > x do
+ begin
+ s := TrimRight(FLines[x]);
+ Inc(x);
+ Mime.Lines.Add(s);
+ end;
+ Mime.DecomposeParts;
+ end
+ else
+ begin
+ while FLines.Count > x do
+ begin
+ s := FLines[x];
+ Inc(x);
+ FPartBody.Add(s);
+ if not FAttachInside then
+ FAttachInside := IsUUcode(s);
+ end;
+ end;
+ //extract postpart
+ if FPrimaryCode = MP_MULTIPART then
+ begin
+ while FLines.Count > x do
+ begin
+ s := TrimRight(FLines[x]);
+ Inc(x);
+ FPostPart.Add(s);
+ if not FAttachInside then
+ FAttachInside := IsUUcode(s);
+ end;
+ end;
+end;
+
+{==============================================================================}
+
+procedure TMIMEPart.ComposeParts;
+var
+ n: integer;
+ mime: TMimePart;
+ s, t: string;
+ d1, d2, d3: integer;
+ x: integer;
+begin
+ FLines.Clear;
+ //add headers
+ for n := 0 to FHeaders.Count -1 do
+ begin
+ s := FHeaders[n];
+ repeat
+ if Length(s) < FMaxLineLength then
+ begin
+ t := s;
+ s := '';
+ end
+ else
+ begin
+ d1 := RPosEx('; ', s, FMaxLineLength);
+ d2 := RPosEx(' ', s, FMaxLineLength);
+ d3 := RPosEx(', ', s, FMaxLineLength);
+ if (d1 <= 1) and (d2 <= 1) and (d3 <= 1) then
+ begin
+ x := Pos(' ', Copy(s, 2, Length(s) - 1));
+ if x < 1 then
+ x := Length(s);
+ end
+ else
+ if d1 > 0 then
+ x := d1
+ else
+ if d3 > 0 then
+ x := d3
+ else
+ x := d2 - 1;
+ t := Copy(s, 1, x);
+ Delete(s, 1, x);
+ end;
+ Flines.Add(t);
+ until s = '';
+ end;
+
+ Flines.Add('');
+ //add body
+ //if multipart
+ if FPrimaryCode = MP_MULTIPART then
+ begin
+ Flines.AddStrings(FPrePart);
+ for n := 0 to GetSubPartCount - 1 do
+ begin
+ Flines.Add('--' + FBoundary);
+ mime := GetSubPart(n);
+ mime.ComposeParts;
+ FLines.AddStrings(mime.Lines);
+ end;
+ Flines.Add('--' + FBoundary + '--');
+ Flines.AddStrings(FPostPart);
+ end;
+ //if message
+ if FPrimaryCode = MP_MESSAGE then
+ begin
+ if GetSubPartCount > 0 then
+ begin
+ mime := GetSubPart(0);
+ mime.ComposeParts;
+ FLines.AddStrings(mime.Lines);
+ end;
+ end
+ else
+ //if normal part
+ begin
+ FLines.AddStrings(FPartBody);
+ end;
+end;
+
+{==============================================================================}
+
+procedure TMIMEPart.DecodePart;
+var
+ n: Integer;
+ s, t, t2: string;
+ b: Boolean;
+begin
+ FDecodedLines.Clear;
+ case FEncodingCode of
+ ME_QUOTED_PRINTABLE:
+ s := DecodeQuotedPrintable(FPartBody.Text);
+ ME_BASE64:
+ s := DecodeBase64(FPartBody.Text);
+ ME_UU, ME_XX:
+ begin
+ s := '';
+ for n := 0 to FPartBody.Count - 1 do
+ if FEncodingCode = ME_UU then
+ s := s + DecodeUU(FPartBody[n])
+ else
+ s := s + DecodeXX(FPartBody[n]);
+ end;
+ else
+ s := FPartBody.Text;
+ end;
+ if FConvertCharset and (FPrimaryCode = MP_TEXT) then
+ if (not FForcedHTMLConvert) and (uppercase(FSecondary) = 'HTML') then
+ begin
+ b := false;
+ t2 := uppercase(s);
+ t := SeparateLeft(t2, '');
+ if length(t) <> length(s) then
+ begin
+ t := SeparateRight(t, '');
+ t := ReplaceString(t, '"', '');
+ t := ReplaceString(t, ' ', '');
+ b := Pos('HTTP-EQUIV=CONTENT-TYPE', t) > 0;
+ end;
+ //workaround for shitty M$ Outlook 11 which is placing this information
+ //outside section
+ if not b then
+ begin
+ t := Copy(t2, 1, 2048);
+ t := ReplaceString(t, '"', '');
+ t := ReplaceString(t, ' ', '');
+ b := Pos('HTTP-EQUIV=CONTENT-TYPE', t) > 0;
+ end;
+ if not b then
+ s := CharsetConversion(s, FCharsetCode, FTargetCharset);
+ end
+ else
+ s := CharsetConversion(s, FCharsetCode, FTargetCharset);
+ WriteStrToStream(FDecodedLines, s);
+ FDecodedLines.Seek(0, soFromBeginning);
+end;
+
+{==============================================================================}
+
+procedure TMIMEPart.DecodePartHeader;
+var
+ n: integer;
+ s, su, fn: string;
+ st, st2: string;
+begin
+ Primary := 'text';
+ FSecondary := 'plain';
+ FDescription := '';
+ Charset := FDefaultCharset;
+ FFileName := '';
+ //was 7bit before, but this is more compatible with RFC-ignorant outlook
+ Encoding := '8BIT';
+ FDisposition := '';
+ FContentID := '';
+ fn := '';
+ for n := 0 to FHeaders.Count - 1 do
+ if FHeaders[n] <> '' then
+ begin
+ s := FHeaders[n];
+ su := UpperCase(s);
+ if Pos('CONTENT-TYPE:', su) = 1 then
+ begin
+ st := Trim(SeparateRight(su, ':'));
+ st2 := Trim(SeparateLeft(st, ';'));
+ Primary := Trim(SeparateLeft(st2, '/'));
+ FSecondary := Trim(SeparateRight(st2, '/'));
+ if (FSecondary = Primary) and (Pos('/', st2) < 1) then
+ FSecondary := '';
+ case FPrimaryCode of
+ MP_TEXT:
+ begin
+ Charset := UpperCase(GetParameter(s, 'charset'));
+ FFileName := GetParameter(s, 'name');
+ end;
+ MP_MULTIPART:
+ FBoundary := GetParameter(s, 'Boundary');
+ MP_MESSAGE:
+ begin
+ end;
+ MP_BINARY:
+ FFileName := GetParameter(s, 'name');
+ end;
+ end;
+ if Pos('CONTENT-TRANSFER-ENCODING:', su) = 1 then
+ Encoding := Trim(SeparateRight(su, ':'));
+ if Pos('CONTENT-DESCRIPTION:', su) = 1 then
+ FDescription := Trim(SeparateRight(s, ':'));
+ if Pos('CONTENT-DISPOSITION:', su) = 1 then
+ begin
+ FDisposition := SeparateRight(su, ':');
+ FDisposition := Trim(SeparateLeft(FDisposition, ';'));
+ fn := GetParameter(s, 'FileName');
+ end;
+ if Pos('CONTENT-ID:', su) = 1 then
+ FContentID := Trim(SeparateRight(s, ':'));
+ end;
+ if fn <> '' then
+ FFileName := fn;
+ FFileName := InlineDecode(FFileName, FTargetCharset);
+ FFileName := ExtractFileName(FFileName);
+end;
+
+{==============================================================================}
+
+procedure TMIMEPart.EncodePart;
+var
+ l: TStringList;
+ s, t: string;
+ n, x: Integer;
+ d1, d2: integer;
+begin
+ if (FEncodingCode = ME_UU) or (FEncodingCode = ME_XX) then
+ Encoding := 'base64';
+ l := TStringList.Create;
+ FPartBody.Clear;
+ FDecodedLines.Seek(0, soFromBeginning);
+ try
+ case FPrimaryCode of
+ MP_MULTIPART, MP_MESSAGE:
+ FPartBody.LoadFromStream(FDecodedLines);
+ MP_TEXT, MP_BINARY:
+ begin
+ s := ReadStrFromStream(FDecodedLines, FDecodedLines.Size);
+ if FConvertCharset and (FPrimaryCode = MP_TEXT) and (FEncodingCode <> ME_7BIT) then
+ s := GetBOM(FCharSetCode) + CharsetConversion(s, FTargetCharset, FCharsetCode);
+ if FEncodingCode = ME_BASE64 then
+ begin
+ x := 1;
+ while x <= length(s) do
+ begin
+ t := copy(s, x, 54);
+ x := x + length(t);
+ t := EncodeBase64(t);
+ FPartBody.Add(t);
+ end;
+ end
+ else
+ begin
+ if FPrimaryCode = MP_BINARY then
+ l.Add(s)
+ else
+ l.Text := s;
+ for n := 0 to l.Count - 1 do
+ begin
+ s := l[n];
+ if FEncodingCode = ME_QUOTED_PRINTABLE then
+ begin
+ s := EncodeQuotedPrintable(s);
+ repeat
+ if Length(s) < FMaxLineLength then
+ begin
+ t := s;
+ s := '';
+ end
+ else
+ begin
+ d1 := RPosEx('=', s, FMaxLineLength);
+ d2 := RPosEx(' ', s, FMaxLineLength);
+ if (d1 = 0) and (d2 = 0) then
+ x := FMaxLineLength
+ else
+ if d1 > d2 then
+ x := d1 - 1
+ else
+ x := d2 - 1;
+ if x = 0 then
+ x := FMaxLineLength;
+ t := Copy(s, 1, x);
+ Delete(s, 1, x);
+ if s <> '' then
+ t := t + '=';
+ end;
+ FPartBody.Add(t);
+ until s = '';
+ end
+ else
+ FPartBody.Add(s);
+ end;
+ if (FPrimaryCode = MP_BINARY)
+ and (FEncodingCode = ME_QUOTED_PRINTABLE) then
+ FPartBody[FPartBody.Count - 1] := FPartBody[FPartBody.Count - 1] + '=';
+ end;
+ end;
+ end;
+ finally
+ l.Free;
+ end;
+end;
+
+{==============================================================================}
+
+procedure TMIMEPart.EncodePartHeader;
+var
+ s: string;
+begin
+ FHeaders.Clear;
+ if FSecondary = '' then
+ case FPrimaryCode of
+ MP_TEXT:
+ FSecondary := 'plain';
+ MP_MULTIPART:
+ FSecondary := 'mixed';
+ MP_MESSAGE:
+ FSecondary := 'rfc822';
+ MP_BINARY:
+ FSecondary := 'octet-stream';
+ end;
+ if FDescription <> '' then
+ FHeaders.Insert(0, 'Content-Description: ' + FDescription);
+ if FDisposition <> '' then
+ begin
+ s := '';
+ if FFileName <> '' then
+ s := '; FileName=' + QuoteStr(InlineCodeEx(FileName, FTargetCharset), '"');
+ FHeaders.Insert(0, 'Content-Disposition: ' + LowerCase(FDisposition) + s);
+ end;
+ if FContentID <> '' then
+ FHeaders.Insert(0, 'Content-ID: ' + FContentID);
+
+ case FEncodingCode of
+ ME_7BIT:
+ s := '7bit';
+ ME_8BIT:
+ s := '8bit';
+ ME_QUOTED_PRINTABLE:
+ s := 'Quoted-printable';
+ ME_BASE64:
+ s := 'Base64';
+ end;
+ case FPrimaryCode of
+ MP_TEXT,
+ MP_BINARY: FHeaders.Insert(0, 'Content-Transfer-Encoding: ' + s);
+ end;
+ case FPrimaryCode of
+ MP_TEXT:
+ s := FPrimary + '/' + FSecondary + '; charset=' + GetIDfromCP(FCharsetCode);
+ MP_MULTIPART:
+ s := FPrimary + '/' + FSecondary + '; boundary="' + FBoundary + '"';
+ MP_MESSAGE, MP_BINARY:
+ s := FPrimary + '/' + FSecondary;
+ end;
+ if FFileName <> '' then
+ s := s + '; name=' + QuoteStr(InlineCodeEx(FileName, FTargetCharset), '"');
+ FHeaders.Insert(0, 'Content-type: ' + s);
+end;
+
+{==============================================================================}
+
+procedure TMIMEPart.MimeTypeFromExt(Value: string);
+var
+ s: string;
+ n: Integer;
+begin
+ Primary := '';
+ FSecondary := '';
+ s := UpperCase(ExtractFileExt(Value));
+ if s = '' then
+ s := UpperCase(Value);
+ s := SeparateRight(s, '.');
+ for n := 0 to MaxMimeType do
+ if MimeType[n, 0] = s then
+ begin
+ Primary := MimeType[n, 1];
+ FSecondary := MimeType[n, 2];
+ Break;
+ end;
+ if Primary = '' then
+ Primary := 'application';
+ if FSecondary = '' then
+ FSecondary := 'octet-stream';
+end;
+
+{==============================================================================}
+
+procedure TMIMEPart.WalkPart;
+var
+ n: integer;
+ m: TMimepart;
+begin
+ if assigned(OnWalkPart) then
+ begin
+ OnWalkPart(self);
+ for n := 0 to GetSubPartCount - 1 do
+ begin
+ m := GetSubPart(n);
+ m.OnWalkPart := OnWalkPart;
+ m.WalkPart;
+ end;
+ end;
+end;
+
+{==============================================================================}
+
+procedure TMIMEPart.SetPrimary(Value: string);
+var
+ s: string;
+begin
+ FPrimary := Value;
+ s := UpperCase(Value);
+ FPrimaryCode := MP_BINARY;
+ if Pos('TEXT', s) = 1 then
+ FPrimaryCode := MP_TEXT;
+ if Pos('MULTIPART', s) = 1 then
+ FPrimaryCode := MP_MULTIPART;
+ if Pos('MESSAGE', s) = 1 then
+ FPrimaryCode := MP_MESSAGE;
+end;
+
+procedure TMIMEPart.SetEncoding(Value: string);
+var
+ s: string;
+begin
+ FEncoding := Value;
+ s := UpperCase(Value);
+ FEncodingCode := ME_7BIT;
+ if Pos('8BIT', s) = 1 then
+ FEncodingCode := ME_8BIT;
+ if Pos('QUOTED-PRINTABLE', s) = 1 then
+ FEncodingCode := ME_QUOTED_PRINTABLE;
+ if Pos('BASE64', s) = 1 then
+ FEncodingCode := ME_BASE64;
+ if Pos('X-UU', s) = 1 then
+ FEncodingCode := ME_UU;
+ if Pos('X-XX', s) = 1 then
+ FEncodingCode := ME_XX;
+end;
+
+procedure TMIMEPart.SetCharset(Value: string);
+begin
+ if value <> '' then
+ begin
+ FCharset := Value;
+ FCharsetCode := GetCPFromID(Value);
+ end;
+end;
+
+function TMIMEPart.CanSubPart: boolean;
+begin
+ Result := True;
+ if FMaxSubLevel <> -1 then
+ Result := FMaxSubLevel > FSubLevel;
+end;
+
+function TMIMEPart.IsUUcode(Value: string): boolean;
+begin
+ Value := UpperCase(Value);
+ Result := (pos('BEGIN ', Value) = 1) and (Trim(SeparateRight(Value, ' ')) <> '');
+end;
+
+{==============================================================================}
+
+function GenerateBoundary: string;
+var
+ x, y: Integer;
+begin
+ y := GetTick;
+ x := y;
+ while TickDelta(y, x) = 0 do
+ begin
+ Sleep(1);
+ x := GetTick;
+ end;
+ Randomize;
+ y := Random(MaxInt);
+ Result := IntToHex(x, 8) + '_' + IntToHex(y, 8) + '_Synapse_boundary';
+end;
+
+end.
diff --git a/branches/script-component/Units/Synapse/nntpsend.pas b/branches/script-component/Units/Synapse/nntpsend.pas
new file mode 100644
index 0000000..ef35f77
--- /dev/null
+++ b/branches/script-component/Units/Synapse/nntpsend.pas
@@ -0,0 +1,474 @@
+{==============================================================================|
+| Project : Ararat Synapse | 001.005.001 |
+|==============================================================================|
+| Content: NNTP client |
+|==============================================================================|
+| Copyright (c)1999-2007, Lukas Gebauer |
+| All rights reserved. |
+| |
+| Redistribution and use in source and binary forms, with or without |
+| modification, are permitted provided that the following conditions are met: |
+| |
+| Redistributions of source code must retain the above copyright notice, this |
+| list of conditions and the following disclaimer. |
+| |
+| Redistributions in binary form must reproduce the above copyright notice, |
+| this list of conditions and the following disclaimer in the documentation |
+| and/or other materials provided with the distribution. |
+| |
+| Neither the name of Lukas Gebauer nor the names of its contributors may |
+| be used to endorse or promote products derived from this software without |
+| specific prior written permission. |
+| |
+| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
+| AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
+| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
+| ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR |
+| ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
+| DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
+| SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
+| CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
+| LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
+| OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
+| DAMAGE. |
+|==============================================================================|
+| The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).|
+| Portions created by Lukas Gebauer are Copyright (c) 1999-2007. |
+| All Rights Reserved. |
+|==============================================================================|
+| Contributor(s): |
+|==============================================================================|
+| History: see HISTORY.HTM from distribution package |
+| (Found at URL: http://www.ararat.cz/synapse/) |
+|==============================================================================}
+
+{:@abstract(NNTP client)
+NNTP (network news transfer protocol)
+
+Used RFC: RFC-977, RFC-2980
+}
+
+{$IFDEF FPC}
+ {$MODE DELPHI}
+{$ENDIF}
+{$H+}
+
+unit nntpsend;
+
+interface
+
+uses
+ SysUtils, Classes,
+ blcksock, synautil;
+
+const
+ cNNTPProtocol = '119';
+
+type
+
+ {:abstract(Implementation of Network News Transfer Protocol.
+
+ Note: Are you missing properties for setting Username and Password? Look to
+ parent @link(TSynaClient) object!
+
+ Are you missing properties for specify server address and port? Look to
+ parent @link(TSynaClient) too!}
+ TNNTPSend = class(TSynaClient)
+ private
+ FSock: TTCPBlockSocket;
+ FResultCode: Integer;
+ FResultString: string;
+ FData: TStringList;
+ FDataToSend: TStringList;
+ FAutoTLS: Boolean;
+ FFullSSL: Boolean;
+ FNNTPcap: TStringList;
+ function ReadResult: Integer;
+ function ReadData: boolean;
+ function SendData: boolean;
+ function Connect: Boolean;
+ public
+ constructor Create;
+ destructor Destroy; override;
+
+ {:Connects to NNTP server and begin session.}
+ function Login: Boolean;
+
+ {:Logout from NNTP server and terminate session.}
+ function Logout: Boolean;
+
+ {:By this you can call any NNTP command.}
+ function DoCommand(const Command: string): boolean;
+
+ {:by this you can call any NNTP command. This variant is used for commands
+ for download information from server.}
+ function DoCommandRead(const Command: string): boolean;
+
+ {:by this you can call any NNTP command. This variant is used for commands
+ for upload information to server.}
+ function DoCommandWrite(const Command: string): boolean;
+
+ {:Download full message to @link(data) property. Value can be number of
+ message or message-id (in brackets).}
+ function GetArticle(const Value: string): Boolean;
+
+ {:Download only body of message to @link(data) property. Value can be number
+ of message or message-id (in brackets).}
+ function GetBody(const Value: string): Boolean;
+
+ {:Download only headers of message to @link(data) property. Value can be
+ number of message or message-id (in brackets).}
+ function GetHead(const Value: string): Boolean;
+
+ {:Get message status. Value can be number of message or message-id
+ (in brackets).}
+ function GetStat(const Value: string): Boolean;
+
+ {:Select given group.}
+ function SelectGroup(const Value: string): Boolean;
+
+ {:Tell to server 'I have mesage with given message-ID.' If server need this
+ message, message is uploaded to server.}
+ function IHave(const MessID: string): Boolean;
+
+ {:Move message pointer to last item in group.}
+ function GotoLast: Boolean;
+
+ {:Move message pointer to next item in group.}
+ function GotoNext: Boolean;
+
+ {:Download to @link(data) property list of all groups on NNTP server.}
+ function ListGroups: Boolean;
+
+ {:Download to @link(data) property list of all groups created after given time.}
+ function ListNewGroups(Since: TDateTime): Boolean;
+
+ {:Download to @link(data) property list of message-ids in given group since
+ given time.}
+ function NewArticles(const Group: string; Since: TDateTime): Boolean;
+
+ {:Upload new article to server. (for new messages by you)}
+ function PostArticle: Boolean;
+
+ {:Tells to remote NNTP server 'I am not NNTP client, but I am another NNTP
+ server'.}
+ function SwitchToSlave: Boolean;
+
+ {:Call NNTP XOVER command.}
+ function Xover(xoStart, xoEnd: string): boolean;
+
+ {:Call STARTTLS command for upgrade connection to SSL/TLS mode.}
+ function StartTLS: Boolean;
+
+ {:Try to find given capability in extension list. This list is getted after
+ successful login to NNTP server. If extension capability is not found,
+ then return is empty string.}
+ function FindCap(const Value: string): string;
+
+ {:Try get list of server extensions. List is returned in @link(data) property.}
+ function ListExtensions: Boolean;
+ published
+ {:Result code number of last operation.}
+ property ResultCode: Integer read FResultCode;
+
+ {:String description of last result code from NNTP server.}
+ property ResultString: string read FResultString;
+
+ {:Readed data. (message, etc.)}
+ property Data: TStringList read FData;
+
+ {:If is set to @true, then upgrade to SSL/TLS mode after login if remote
+ server support it.}
+ property AutoTLS: Boolean read FAutoTLS Write FAutoTLS;
+
+ {:SSL/TLS mode is used from first contact to server. Servers with full
+ SSL/TLS mode usualy using non-standard TCP port!}
+ property FullSSL: Boolean read FFullSSL Write FFullSSL;
+
+ {:Socket object used for TCP/IP operation. Good for seting OnStatus hook, etc.}
+ property Sock: TTCPBlockSocket read FSock;
+ end;
+
+implementation
+
+constructor TNNTPSend.Create;
+begin
+ inherited Create;
+ FSock := TTCPBlockSocket.Create;
+ FData := TStringList.Create;
+ FDataToSend := TStringList.Create;
+ FNNTPcap := TStringList.Create;
+ FSock.ConvertLineEnd := True;
+ FTimeout := 60000;
+ FTargetPort := cNNTPProtocol;
+ FAutoTLS := False;
+ FFullSSL := False;
+end;
+
+destructor TNNTPSend.Destroy;
+begin
+ FSock.Free;
+ FDataToSend.Free;
+ FData.Free;
+ FNNTPcap.Free;
+ inherited Destroy;
+end;
+
+function TNNTPSend.ReadResult: Integer;
+var
+ s: string;
+begin
+ Result := 0;
+ FData.Clear;
+ s := FSock.RecvString(FTimeout);
+ FResultString := Copy(s, 5, Length(s) - 4);
+ if FSock.LastError <> 0 then
+ Exit;
+ if Length(s) >= 3 then
+ Result := StrToIntDef(Copy(s, 1, 3), 0);
+ FResultCode := Result;
+end;
+
+function TNNTPSend.ReadData: boolean;
+var
+ s: string;
+begin
+ repeat
+ s := FSock.RecvString(FTimeout);
+ if s = '.' then
+ break;
+ if (s <> '') and (s[1] = '.') then
+ s := Copy(s, 2, Length(s) - 1);
+ FData.Add(s);
+ until FSock.LastError <> 0;
+ Result := FSock.LastError = 0;
+end;
+
+function TNNTPSend.SendData: boolean;
+var
+ s: string;
+ n: integer;
+begin
+ for n := 0 to FDataToSend.Count - 1 do
+ begin
+ s := FDataToSend[n];
+ if (s <> '') and (s[1] = '.') then
+ s := s + '.';
+ FSock.SendString(s + CRLF);
+ if FSock.LastError <> 0 then
+ break;
+ end;
+ if FDataToSend.Count = 0 then
+ FSock.SendString(CRLF);
+ if FSock.LastError = 0 then
+ FSock.SendString('.' + CRLF);
+ FDataToSend.Clear;
+ Result := FSock.LastError = 0;
+end;
+
+function TNNTPSend.Connect: Boolean;
+begin
+ FSock.CloseSocket;
+ FSock.Bind(FIPInterface, cAnyPort);
+ if FSock.LastError = 0 then
+ FSock.Connect(FTargetHost, FTargetPort);
+ if FSock.LastError = 0 then
+ if FFullSSL then
+ FSock.SSLDoConnect;
+ Result := FSock.LastError = 0;
+end;
+
+function TNNTPSend.Login: Boolean;
+begin
+ Result := False;
+ FNNTPcap.Clear;
+ if not Connect then
+ Exit;
+ Result := (ReadResult div 100) = 2;
+ ListExtensions;
+ FNNTPcap.Assign(Fdata);
+ if Result then
+ if (not FullSSL) and FAutoTLS and (FindCap('STARTTLS') <> '') then
+ Result := StartTLS;
+ if (FUsername <> '') and Result then
+ begin
+ FSock.SendString('AUTHINFO USER ' + FUsername + CRLF);
+ if (ReadResult div 100) = 3 then
+ begin
+ FSock.SendString('AUTHINFO PASS ' + FPassword + CRLF);
+ Result := (ReadResult div 100) = 2;
+ end;
+ end;
+end;
+
+function TNNTPSend.Logout: Boolean;
+begin
+ FSock.SendString('QUIT' + CRLF);
+ Result := (ReadResult div 100) = 2;
+ FSock.CloseSocket;
+end;
+
+function TNNTPSend.DoCommand(const Command: string): Boolean;
+begin
+ FSock.SendString(Command + CRLF);
+ Result := (ReadResult div 100) = 2;
+ Result := Result and (FSock.LastError = 0);
+end;
+
+function TNNTPSend.DoCommandRead(const Command: string): Boolean;
+begin
+ Result := DoCommand(Command);
+ if Result then
+ begin
+ Result := ReadData;
+ Result := Result and (FSock.LastError = 0);
+ end;
+end;
+
+function TNNTPSend.DoCommandWrite(const Command: string): Boolean;
+var
+ x: integer;
+begin
+ FDataToSend.Assign(FData);
+ FSock.SendString(Command + CRLF);
+ x := (ReadResult div 100);
+ if x = 3 then
+ begin
+ SendData;
+ x := (ReadResult div 100);
+ end;
+ Result := x = 2;
+ Result := Result and (FSock.LastError = 0);
+end;
+
+function TNNTPSend.GetArticle(const Value: string): Boolean;
+var
+ s: string;
+begin
+ s := 'ARTICLE';
+ if Value <> '' then
+ s := s + ' ' + Value;
+ Result := DoCommandRead(s);
+end;
+
+function TNNTPSend.GetBody(const Value: string): Boolean;
+var
+ s: string;
+begin
+ s := 'BODY';
+ if Value <> '' then
+ s := s + ' ' + Value;
+ Result := DoCommandRead(s);
+end;
+
+function TNNTPSend.GetHead(const Value: string): Boolean;
+var
+ s: string;
+begin
+ s := 'HEAD';
+ if Value <> '' then
+ s := s + ' ' + Value;
+ Result := DoCommandRead(s);
+end;
+
+function TNNTPSend.GetStat(const Value: string): Boolean;
+var
+ s: string;
+begin
+ s := 'STAT';
+ if Value <> '' then
+ s := s + ' ' + Value;
+ Result := DoCommand(s);
+end;
+
+function TNNTPSend.SelectGroup(const Value: string): Boolean;
+begin
+ Result := DoCommand('GROUP ' + Value);
+end;
+
+function TNNTPSend.IHave(const MessID: string): Boolean;
+begin
+ Result := DoCommandWrite('IHAVE ' + MessID);
+end;
+
+function TNNTPSend.GotoLast: Boolean;
+begin
+ Result := DoCommand('LAST');
+end;
+
+function TNNTPSend.GotoNext: Boolean;
+begin
+ Result := DoCommand('NEXT');
+end;
+
+function TNNTPSend.ListGroups: Boolean;
+begin
+ Result := DoCommandRead('LIST');
+end;
+
+function TNNTPSend.ListNewGroups(Since: TDateTime): Boolean;
+begin
+ Result := DoCommandRead('NEWGROUPS ' + SimpleDateTime(Since) + ' GMT');
+end;
+
+function TNNTPSend.NewArticles(const Group: string; Since: TDateTime): Boolean;
+begin
+ Result := DoCommandRead('NEWNEWS ' + Group + ' ' + SimpleDateTime(Since) + ' GMT');
+end;
+
+function TNNTPSend.PostArticle: Boolean;
+begin
+ Result := DoCommandWrite('POST');
+end;
+
+function TNNTPSend.SwitchToSlave: Boolean;
+begin
+ Result := DoCommand('SLAVE');
+end;
+
+function TNNTPSend.Xover(xoStart, xoEnd: string): Boolean;
+var
+ s: string;
+begin
+ s := 'XOVER ' + xoStart;
+ if xoEnd <> xoStart then
+ s := s + '-' + xoEnd;
+ Result := DoCommandRead(s);
+end;
+
+function TNNTPSend.StartTLS: Boolean;
+begin
+ Result := False;
+ if FindCap('STARTTLS') <> '' then
+ begin
+ if DoCommand('STARTTLS') then
+ begin
+ Fsock.SSLDoConnect;
+ Result := FSock.LastError = 0;
+ end;
+ end;
+end;
+
+function TNNTPSend.ListExtensions: Boolean;
+begin
+ Result := DoCommandRead('LIST EXTENSIONS');
+end;
+
+function TNNTPSend.FindCap(const Value: string): string;
+var
+ n: Integer;
+ s: string;
+begin
+ s := UpperCase(Value);
+ Result := '';
+ for n := 0 to FNNTPcap.Count - 1 do
+ if Pos(s, UpperCase(FNNTPcap[n])) = 1 then
+ begin
+ Result := FNNTPcap[n];
+ Break;
+ end;
+end;
+
+{==============================================================================}
+
+end.
diff --git a/branches/script-component/Units/Synapse/pingsend.pas b/branches/script-component/Units/Synapse/pingsend.pas
new file mode 100644
index 0000000..ddab79e
--- /dev/null
+++ b/branches/script-component/Units/Synapse/pingsend.pas
@@ -0,0 +1,708 @@
+{==============================================================================|
+| Project : Ararat Synapse | 004.000.000 |
+|==============================================================================|
+| Content: PING sender |
+|==============================================================================|
+| Copyright (c)1999-2007, Lukas Gebauer |
+| All rights reserved. |
+| |
+| Redistribution and use in source and binary forms, with or without |
+| modification, are permitted provided that the following conditions are met: |
+| |
+| Redistributions of source code must retain the above copyright notice, this |
+| list of conditions and the following disclaimer. |
+| |
+| Redistributions in binary form must reproduce the above copyright notice, |
+| this list of conditions and the following disclaimer in the documentation |
+| and/or other materials provided with the distribution. |
+| |
+| Neither the name of Lukas Gebauer nor the names of its contributors may |
+| be used to endorse or promote products derived from this software without |
+| specific prior written permission. |
+| |
+| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
+| AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
+| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
+| ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR |
+| ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
+| DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
+| SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
+| CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
+| LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
+| OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
+| DAMAGE. |
+|==============================================================================|
+| The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).|
+| Portions created by Lukas Gebauer are Copyright (c)2000-2007. |
+| All Rights Reserved. |
+|==============================================================================|
+| Contributor(s): |
+|==============================================================================|
+| History: see HISTORY.HTM from distribution package |
+| (Found at URL: http://www.ararat.cz/synapse/) |
+|==============================================================================}
+
+{:@abstract(ICMP PING implementation.)
+Allows create PING and TRACEROUTE. Or you can diagnose your network.
+
+This unit using IpHlpApi (on WinXP or higher) if available. Otherwise it trying
+ to use RAW sockets.
+
+Warning: For use of RAW sockets you must have some special rights on some
+ systems. So, it working allways when you have administator/root rights.
+ Otherwise you can have problems!
+
+Note: This unit is NOT portable to .NET!
+ Use native .NET classes for Ping instead.
+}
+
+{$IFDEF FPC}
+ {$MODE DELPHI}
+{$ENDIF}
+{$Q-}
+{$R-}
+{$H+}
+
+{$IFDEF CIL}
+ Sorry, this unit is not for .NET!
+{$ENDIF}
+
+unit pingsend;
+
+interface
+
+uses
+ SysUtils,
+ synsock, blcksock, synautil, synafpc, synaip
+{$IFDEF WIN32}
+ , windows
+{$ENDIF}
+ ;
+
+const
+ ICMP_ECHO = 8;
+ ICMP_ECHOREPLY = 0;
+ ICMP_UNREACH = 3;
+ ICMP_TIME_EXCEEDED = 11;
+//rfc-2292
+ ICMP6_ECHO = 128;
+ ICMP6_ECHOREPLY = 129;
+ ICMP6_UNREACH = 1;
+ ICMP6_TIME_EXCEEDED = 3;
+
+type
+ {:List of possible ICMP reply packet types.}
+ TICMPError = (
+ IE_NoError,
+ IE_Other,
+ IE_TTLExceed,
+ IE_UnreachOther,
+ IE_UnreachRoute,
+ IE_UnreachAdmin,
+ IE_UnreachAddr,
+ IE_UnreachPort
+ );
+
+ {:@abstract(Implementation of ICMP PING and ICMPv6 PING.)}
+ TPINGSend = class(TSynaClient)
+ private
+ FSock: TICMPBlockSocket;
+ FBuffer: string;
+ FSeq: Integer;
+ FId: Integer;
+ FPacketSize: Integer;
+ FPingTime: Integer;
+ FIcmpEcho: Byte;
+ FIcmpEchoReply: Byte;
+ FIcmpUnreach: Byte;
+ FReplyFrom: string;
+ FReplyType: byte;
+ FReplyCode: byte;
+ FReplyError: TICMPError;
+ FReplyErrorDesc: string;
+ FTTL: Byte;
+ Fsin: TVarSin;
+ function Checksum(Value: string): Word;
+ function Checksum6(Value: string): Word;
+ function ReadPacket: Boolean;
+ procedure TranslateError;
+ procedure TranslateErrorIpHlp(value: integer);
+ function InternalPing(const Host: string): Boolean;
+ function InternalPingIpHlp(const Host: string): Boolean;
+ function IsHostIP6(const Host: string): Boolean;
+ procedure GenErrorDesc;
+ public
+ {:Send ICMP ping to host and count @link(pingtime). If ping OK, result is
+ @true.}
+ function Ping(const Host: string): Boolean;
+ constructor Create;
+ destructor Destroy; override;
+ published
+ {:Size of PING packet. Default size is 32 bytes.}
+ property PacketSize: Integer read FPacketSize Write FPacketSize;
+
+ {:Time between request and reply.}
+ property PingTime: Integer read FPingTime;
+
+ {:From this address is sended reply for your PING request. It maybe not your
+ requested destination, when some error occured!}
+ property ReplyFrom: string read FReplyFrom;
+
+ {:ICMP type of PING reply. Each protocol using another values! For IPv4 and
+ IPv6 are used different values!}
+ property ReplyType: byte read FReplyType;
+
+ {:ICMP code of PING reply. Each protocol using another values! For IPv4 and
+ IPv6 are used different values! For protocol independent value look to
+ @link(ReplyError)}
+ property ReplyCode: byte read FReplyCode;
+
+ {:Return type of returned ICMP message. This value is independent on used
+ protocol!}
+ property ReplyError: TICMPError read FReplyError;
+
+ {:Return human readable description of returned packet type.}
+ property ReplyErrorDesc: string read FReplyErrorDesc;
+
+ {:Socket object used for TCP/IP operation. Good for seting OnStatus hook, etc.}
+ property Sock: TICMPBlockSocket read FSock;
+
+ {:TTL value for ICMP query}
+ property TTL: byte read FTTL write FTTL;
+ end;
+
+{:A very useful function and example of its use would be found in the TPINGSend
+ object. Use it to ping to any host. If successful, returns the ping time in
+ milliseconds. Returns -1 if an error occurred.}
+function PingHost(const Host: string): Integer;
+
+{:A very useful function and example of its use would be found in the TPINGSend
+ object. Use it to TraceRoute to any host.}
+function TraceRouteHost(const Host: string): string;
+
+implementation
+
+type
+ {:Record for ICMP ECHO packet header.}
+ TIcmpEchoHeader = record
+ i_type: Byte;
+ i_code: Byte;
+ i_checkSum: Word;
+ i_Id: Word;
+ i_seq: Word;
+ TimeStamp: integer;
+ end;
+
+ {:record used internally by TPingSend for compute checksum of ICMPv6 packet
+ pseudoheader.}
+ TICMP6Packet = record
+ in_source: TInAddr6;
+ in_dest: TInAddr6;
+ Length: integer;
+ free0: Byte;
+ free1: Byte;
+ free2: Byte;
+ proto: Byte;
+ end;
+
+{$IFDEF WIN32}
+const
+ DLLIcmpName = 'iphlpapi.dll';
+type
+ TIP_OPTION_INFORMATION = packed record
+ TTL: Byte;
+ TOS: Byte;
+ Flags: Byte;
+ OptionsSize: Byte;
+ OptionsData: PChar;
+ end;
+ PIP_OPTION_INFORMATION = ^TIP_OPTION_INFORMATION;
+
+ TICMP_ECHO_REPLY = packed record
+ Address: TInAddr;
+ Status: integer;
+ RoundTripTime: integer;
+ DataSize: Word;
+ Reserved: Word;
+ Data: pointer;
+ Options: TIP_OPTION_INFORMATION;
+ end;
+ PICMP_ECHO_REPLY = ^TICMP_ECHO_REPLY;
+
+ TICMPV6_ECHO_REPLY = packed record
+ Address: TSockAddrIn6;
+ Status: integer;
+ RoundTripTime: integer;
+ end;
+ PICMPV6_ECHO_REPLY = ^TICMPV6_ECHO_REPLY;
+
+ TIcmpCreateFile = function: integer; stdcall;
+ TIcmpCloseHandle = function(handle: integer): boolean; stdcall;
+ TIcmpSendEcho2 = function(handle: integer; Event: pointer; ApcRoutine: pointer;
+ ApcContext: pointer; DestinationAddress: TInAddr; RequestData: pointer;
+ RequestSize: integer; RequestOptions: PIP_OPTION_INFORMATION;
+ ReplyBuffer: pointer; ReplySize: integer; Timeout: Integer): integer; stdcall;
+ TIcmp6CreateFile = function: integer; stdcall;
+ TIcmp6SendEcho2 = function(handle: integer; Event: pointer; ApcRoutine: pointer;
+ ApcContext: pointer; SourceAddress: PSockAddrIn6; DestinationAddress: PSockAddrIn6;
+ RequestData: pointer; RequestSize: integer; RequestOptions: PIP_OPTION_INFORMATION;
+ ReplyBuffer: pointer; ReplySize: integer; Timeout: Integer): integer; stdcall;
+
+var
+ IcmpDllHandle: TLibHandle = 0;
+ IcmpHelper4: boolean = false;
+ IcmpHelper6: boolean = false;
+ IcmpCreateFile: TIcmpCreateFile = nil;
+ IcmpCloseHandle: TIcmpCloseHandle = nil;
+ IcmpSendEcho2: TIcmpSendEcho2 = nil;
+ Icmp6CreateFile: TIcmp6CreateFile = nil;
+ Icmp6SendEcho2: TIcmp6SendEcho2 = nil;
+{$ENDIF}
+{==============================================================================}
+
+constructor TPINGSend.Create;
+begin
+ inherited Create;
+ FSock := TICMPBlockSocket.Create;
+ FTimeout := 5000;
+ FPacketSize := 32;
+ FSeq := 0;
+ Randomize;
+ FTTL := 128;
+end;
+
+destructor TPINGSend.Destroy;
+begin
+ FSock.Free;
+ inherited Destroy;
+end;
+
+function TPINGSend.ReadPacket: Boolean;
+begin
+ FBuffer := FSock.RecvPacket(Ftimeout);
+ Result := FSock.LastError = 0;
+end;
+
+procedure TPINGSend.GenErrorDesc;
+begin
+ case FReplyError of
+ IE_NoError:
+ FReplyErrorDesc := '';
+ IE_Other:
+ FReplyErrorDesc := 'Unknown error';
+ IE_TTLExceed:
+ FReplyErrorDesc := 'TTL Exceeded';
+ IE_UnreachOther:
+ FReplyErrorDesc := 'Unknown unreachable';
+ IE_UnreachRoute:
+ FReplyErrorDesc := 'No route to destination';
+ IE_UnreachAdmin:
+ FReplyErrorDesc := 'Administratively prohibited';
+ IE_UnreachAddr:
+ FReplyErrorDesc := 'Address unreachable';
+ IE_UnreachPort:
+ FReplyErrorDesc := 'Port unreachable';
+ end;
+end;
+
+function TPINGSend.IsHostIP6(const Host: string): Boolean;
+var
+ f: integer;
+begin
+ f := AF_UNSPEC;
+ if IsIp(Host) then
+ f := AF_INET
+ else
+ if IsIp6(Host) then
+ f := AF_INET6;
+ synsock.SetVarSin(Fsin, host, '0', f,
+ IPPROTO_UDP, SOCK_DGRAM, Fsock.PreferIP4);
+ result := Fsin.sin_family = AF_INET6;
+end;
+
+function TPINGSend.Ping(const Host: string): Boolean;
+var
+ b: boolean;
+begin
+ FPingTime := -1;
+ FReplyFrom := '';
+ FReplyType := 0;
+ FReplyCode := 0;
+ FReplyError := IE_Other;
+ GenErrorDesc;
+ FBuffer := StringOfChar(#55, SizeOf(TICMPEchoHeader) + FPacketSize);
+{$IFDEF WIN32}
+ b := IsHostIP6(host);
+ if not(b) and IcmpHelper4 then
+ result := InternalPingIpHlp(host)
+ else
+ if b and IcmpHelper6 then
+ result := InternalPingIpHlp(host)
+ else
+ result := InternalPing(host);
+{$ELSE}
+ result := InternalPing(host);
+{$ENDIF}
+end;
+
+function TPINGSend.InternalPing(const Host: string): Boolean;
+var
+ IPHeadPtr: ^TIPHeader;
+ IpHdrLen: Integer;
+ IcmpEchoHeaderPtr: ^TICMPEchoHeader;
+ t: Boolean;
+ x: cardinal;
+ IcmpReqHead: string;
+begin
+ Result := False;
+ FSock.TTL := FTTL;
+ FSock.Bind(FIPInterface, cAnyPort);
+ FSock.Connect(Host, '0');
+ if FSock.LastError <> 0 then
+ Exit;
+ FSock.SizeRecvBuffer := 60 * 1024;
+ if FSock.IP6used then
+ begin
+ FIcmpEcho := ICMP6_ECHO;
+ FIcmpEchoReply := ICMP6_ECHOREPLY;
+ FIcmpUnreach := ICMP6_UNREACH;
+ end
+ else
+ begin
+ FIcmpEcho := ICMP_ECHO;
+ FIcmpEchoReply := ICMP_ECHOREPLY;
+ FIcmpUnreach := ICMP_UNREACH;
+ end;
+ IcmpEchoHeaderPtr := Pointer(FBuffer);
+ with IcmpEchoHeaderPtr^ do
+ begin
+ i_type := FIcmpEcho;
+ i_code := 0;
+ i_CheckSum := 0;
+ FId := System.Random(32767);
+ i_Id := FId;
+ TimeStamp := GetTick;
+ Inc(FSeq);
+ i_Seq := FSeq;
+ if fSock.IP6used then
+ i_CheckSum := CheckSum6(FBuffer)
+ else
+ i_CheckSum := CheckSum(FBuffer);
+ end;
+ FSock.SendString(FBuffer);
+ // remember first 8 bytes of ICMP packet
+ IcmpReqHead := Copy(FBuffer, 1, 8);
+ x := GetTick;
+ repeat
+ t := ReadPacket;
+ if not t then
+ break;
+ if fSock.IP6used then
+ begin
+{$IFNDEF WIN32}
+ IcmpEchoHeaderPtr := Pointer(FBuffer);
+{$ELSE}
+//WinXP SP1 with networking update doing this think by another way ;-O
+// FBuffer := StringOfChar(#0, 4) + FBuffer;
+ IcmpEchoHeaderPtr := Pointer(FBuffer);
+// IcmpEchoHeaderPtr^.i_type := FIcmpEchoReply;
+{$ENDIF}
+ end
+ else
+ begin
+ IPHeadPtr := Pointer(FBuffer);
+ IpHdrLen := (IPHeadPtr^.VerLen and $0F) * 4;
+ IcmpEchoHeaderPtr := @FBuffer[IpHdrLen + 1];
+ end;
+ //check for timeout
+ if TickDelta(x, GetTick) > FTimeout then
+ begin
+ t := false;
+ Break;
+ end;
+ //it discard sometimes possible 'echoes' of previosly sended packet
+ //or other unwanted ICMP packets...
+ until (IcmpEchoHeaderPtr^.i_type <> FIcmpEcho)
+ and ((IcmpEchoHeaderPtr^.i_id = FId)
+ or (Pos(IcmpReqHead, FBuffer) > 0));
+ if t then
+ begin
+ FPingTime := TickDelta(x, GetTick);
+ FReplyFrom := FSock.GetRemoteSinIP;
+ FReplyType := IcmpEchoHeaderPtr^.i_type;
+ FReplyCode := IcmpEchoHeaderPtr^.i_code;
+ TranslateError;
+ Result := True;
+ end;
+end;
+
+function TPINGSend.Checksum(Value: string): Word;
+var
+ CkSum: integer;
+ Num, Remain: Integer;
+ n, i: Integer;
+begin
+ Num := Length(Value) div 2;
+ Remain := Length(Value) mod 2;
+ CkSum := 0;
+ i := 1;
+ for n := 0 to Num - 1 do
+ begin
+ CkSum := CkSum + Synsock.HtoNs(DecodeInt(Value, i));
+ inc(i, 2);
+ end;
+ if Remain <> 0 then
+ CkSum := CkSum + Ord(Value[Length(Value)]);
+ CkSum := (CkSum shr 16) + (CkSum and $FFFF);
+ CkSum := CkSum + (CkSum shr 16);
+ Result := Word(not CkSum);
+end;
+
+function TPINGSend.Checksum6(Value: string): Word;
+const
+ IOC_OUT = $40000000;
+ IOC_IN = $80000000;
+ IOC_INOUT = (IOC_IN or IOC_OUT);
+ IOC_WS2 = $08000000;
+ SIO_ROUTING_INTERFACE_QUERY = 20 or IOC_WS2 or IOC_INOUT;
+var
+ ICMP6Ptr: ^TICMP6Packet;
+ s: string;
+ b: integer;
+ ip6: TSockAddrIn6;
+ x: integer;
+begin
+ Result := 0;
+{$IFDEF WIN32}
+ s := StringOfChar(#0, SizeOf(TICMP6Packet)) + Value;
+ ICMP6Ptr := Pointer(s);
+ x := synsock.WSAIoctl(FSock.Socket, SIO_ROUTING_INTERFACE_QUERY,
+ @FSock.RemoteSin, SizeOf(FSock.RemoteSin),
+ @ip6, SizeOf(ip6), @b, nil, nil);
+ if x <> -1 then
+ ICMP6Ptr^.in_dest := ip6.sin6_addr
+ else
+ ICMP6Ptr^.in_dest := FSock.LocalSin.sin6_addr;
+ ICMP6Ptr^.in_source := FSock.RemoteSin.sin6_addr;
+ ICMP6Ptr^.Length := synsock.htonl(Length(Value));
+ ICMP6Ptr^.proto := IPPROTO_ICMPV6;
+ Result := Checksum(s);
+{$ENDIF}
+end;
+
+procedure TPINGSend.TranslateError;
+begin
+ if fSock.IP6used then
+ begin
+ case FReplyType of
+ ICMP6_ECHOREPLY:
+ FReplyError := IE_NoError;
+ ICMP6_TIME_EXCEEDED:
+ FReplyError := IE_TTLExceed;
+ ICMP6_UNREACH:
+ case FReplyCode of
+ 0:
+ FReplyError := IE_UnreachRoute;
+ 3:
+ FReplyError := IE_UnreachAddr;
+ 4:
+ FReplyError := IE_UnreachPort;
+ 1:
+ FReplyError := IE_UnreachAdmin;
+ else
+ FReplyError := IE_UnreachOther;
+ end;
+ else
+ FReplyError := IE_Other;
+ end;
+ end
+ else
+ begin
+ case FReplyType of
+ ICMP_ECHOREPLY:
+ FReplyError := IE_NoError;
+ ICMP_TIME_EXCEEDED:
+ FReplyError := IE_TTLExceed;
+ ICMP_UNREACH:
+ case FReplyCode of
+ 0:
+ FReplyError := IE_UnreachRoute;
+ 1:
+ FReplyError := IE_UnreachAddr;
+ 3:
+ FReplyError := IE_UnreachPort;
+ 13:
+ FReplyError := IE_UnreachAdmin;
+ else
+ FReplyError := IE_UnreachOther;
+ end;
+ else
+ FReplyError := IE_Other;
+ end;
+ end;
+ GenErrorDesc;
+end;
+
+procedure TPINGSend.TranslateErrorIpHlp(value: integer);
+begin
+ case value of
+ 11000, 0:
+ FReplyError := IE_NoError;
+ 11013:
+ FReplyError := IE_TTLExceed;
+ 11002:
+ FReplyError := IE_UnreachRoute;
+ 11003:
+ FReplyError := IE_UnreachAddr;
+ 11005:
+ FReplyError := IE_UnreachPort;
+ 11004:
+ FReplyError := IE_UnreachAdmin;
+ else
+ FReplyError := IE_Other;
+ end;
+ GenErrorDesc;
+end;
+
+function TPINGSend.InternalPingIpHlp(const Host: string): Boolean;
+{$IFDEF WIN32}
+var
+ PingIp6: boolean;
+ PingHandle: integer;
+ r: integer;
+ ipo: TIP_OPTION_INFORMATION;
+ RBuff: string;
+ ip4reply: PICMP_ECHO_REPLY;
+ ip6reply: PICMPV6_ECHO_REPLY;
+ ip6: TSockAddrIn6;
+begin
+ Result := False;
+ PingIp6 := Fsin.sin_family = AF_INET6;
+ if pingIp6 then
+ PingHandle := Icmp6CreateFile
+ else
+ PingHandle := IcmpCreateFile;
+ if PingHandle <> -1 then
+ begin
+ try
+ ipo.TTL := FTTL;
+ ipo.TOS := 0;
+ ipo.Flags := 0;
+ ipo.OptionsSize := 0;
+ ipo.OptionsData := nil;
+ setlength(RBuff, 4096);
+ if pingIp6 then
+ begin
+ FillChar(ip6, sizeof(ip6), 0);
+ r := Icmp6SendEcho2(PingHandle, nil, nil, nil, @ip6, @Fsin,
+ Pchar(FBuffer), length(FBuffer), @ipo, pchar(RBuff), length(RBuff), FTimeout);
+ if r > 0 then
+ begin
+ RBuff := #0 + #0 + RBuff;
+ ip6reply := PICMPV6_ECHO_REPLY(pointer(RBuff));
+ FPingTime := ip6reply^.RoundTripTime;
+ ip6reply^.Address.sin6_family := AF_INET6;
+ FReplyFrom := GetSinIp(TVarSin(ip6reply^.Address));
+ TranslateErrorIpHlp(ip6reply^.Status);
+ Result := True;
+ end;
+ end
+ else
+ begin
+ r := IcmpSendEcho2(PingHandle, nil, nil, nil, Fsin.sin_addr,
+ Pchar(FBuffer), length(FBuffer), @ipo, pchar(RBuff), length(RBuff), FTimeout);
+ if r > 0 then
+ begin
+ ip4reply := PICMP_ECHO_REPLY(pointer(RBuff));
+ FPingTime := ip4reply^.RoundTripTime;
+ FReplyFrom := IpToStr(swapbytes(ip4reply^.Address.S_addr));
+ TranslateErrorIpHlp(ip4reply^.Status);
+ Result := True;
+ end;
+ end
+ finally
+ IcmpCloseHandle(PingHandle);
+ end;
+ end;
+end;
+{$ELSE}
+begin
+ result := false;
+end;
+{$ENDIF}
+
+{==============================================================================}
+
+function PingHost(const Host: string): Integer;
+begin
+ with TPINGSend.Create do
+ try
+ Result := -1;
+ if Ping(Host) then
+ if ReplyError = IE_NoError then
+ Result := PingTime;
+ finally
+ Free;
+ end;
+end;
+
+function TraceRouteHost(const Host: string): string;
+var
+ Ping: TPingSend;
+ ttl : byte;
+begin
+ Result := '';
+ Ping := TPINGSend.Create;
+ try
+ ttl := 1;
+ repeat
+ ping.TTL := ttl;
+ inc(ttl);
+ if ttl > 30 then
+ Break;
+ if not ping.Ping(Host) then
+ begin
+ Result := Result + cAnyHost+ ' Timeout' + CRLF;
+ continue;
+ end;
+ if (ping.ReplyError <> IE_NoError)
+ and (ping.ReplyError <> IE_TTLExceed) then
+ begin
+ Result := Result + Ping.ReplyFrom + ' ' + Ping.ReplyErrorDesc + CRLF;
+ break;
+ end;
+ Result := Result + Ping.ReplyFrom + ' ' + IntToStr(Ping.PingTime) + CRLF;
+ until ping.ReplyError = IE_NoError;
+ finally
+ Ping.Free;
+ end;
+end;
+
+{$IFDEF WIN32}
+initialization
+begin
+ IcmpHelper4 := false;
+ IcmpHelper6 := false;
+ IcmpDllHandle := LoadLibrary(DLLIcmpName);
+ if IcmpDllHandle <> 0 then
+ begin
+ IcmpCreateFile := GetProcAddress(IcmpDLLHandle, 'IcmpCreateFile');
+ IcmpCloseHandle := GetProcAddress(IcmpDLLHandle, 'IcmpCloseHandle');
+ IcmpSendEcho2 := GetProcAddress(IcmpDLLHandle, 'IcmpSendEcho2');
+ Icmp6CreateFile := GetProcAddress(IcmpDLLHandle, 'Icmp6CreateFile');
+ Icmp6SendEcho2 := GetProcAddress(IcmpDLLHandle, 'Icmp6SendEcho2');
+ IcmpHelper4 := assigned(IcmpCreateFile)
+ and assigned(IcmpCloseHandle)
+ and assigned(IcmpSendEcho2);
+ IcmpHelper6 := assigned(Icmp6CreateFile)
+ and assigned(Icmp6SendEcho2);
+ end;
+end;
+
+finalization
+begin
+ FreeLibrary(IcmpDllHandle);
+end;
+{$ENDIF}
+
+end.
diff --git a/branches/script-component/Units/Synapse/pop3send.pas b/branches/script-component/Units/Synapse/pop3send.pas
new file mode 100644
index 0000000..a261c56
--- /dev/null
+++ b/branches/script-component/Units/Synapse/pop3send.pas
@@ -0,0 +1,476 @@
+{==============================================================================|
+| Project : Ararat Synapse | 002.006.000 |
+|==============================================================================|
+| Content: POP3 client |
+|==============================================================================|
+| Copyright (c)1999-2007, Lukas Gebauer |
+| All rights reserved. |
+| |
+| Redistribution and use in source and binary forms, with or without |
+| modification, are permitted provided that the following conditions are met: |
+| |
+| Redistributions of source code must retain the above copyright notice, this |
+| list of conditions and the following disclaimer. |
+| |
+| Redistributions in binary form must reproduce the above copyright notice, |
+| this list of conditions and the following disclaimer in the documentation |
+| and/or other materials provided with the distribution. |
+| |
+| Neither the name of Lukas Gebauer nor the names of its contributors may |
+| be used to endorse or promote products derived from this software without |
+| specific prior written permission. |
+| |
+| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
+| AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
+| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
+| ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR |
+| ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
+| DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
+| SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
+| CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
+| LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
+| OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
+| DAMAGE. |
+|==============================================================================|
+| The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).|
+| Portions created by Lukas Gebauer are Copyright (c)2001-2007. |
+| All Rights Reserved. |
+|==============================================================================|
+| Contributor(s): |
+|==============================================================================|
+| History: see HISTORY.HTM from distribution package |
+| (Found at URL: http://www.ararat.cz/synapse/) |
+|==============================================================================}
+
+{:@abstract(POP3 protocol client)
+
+Used RFC: RFC-1734, RFC-1939, RFC-2195, RFC-2449, RFC-2595
+}
+
+{$IFDEF FPC}
+ {$MODE DELPHI}
+{$ENDIF}
+{$H+}
+
+unit pop3send;
+
+interface
+
+uses
+ SysUtils, Classes,
+ blcksock, synautil, synacode;
+
+const
+ cPop3Protocol = '110';
+
+type
+
+ {:The three types of possible authorization methods for "logging in" to a POP3
+ server.}
+ TPOP3AuthType = (POP3AuthAll, POP3AuthLogin, POP3AuthAPOP);
+
+ {:@abstract(Implementation of POP3 client protocol.)
+
+ Note: Are you missing properties for setting Username and Password? Look to
+ parent @link(TSynaClient) object!
+
+ Are you missing properties for specify server address and port? Look to
+ parent @link(TSynaClient) too!}
+ TPOP3Send = class(TSynaClient)
+ private
+ FSock: TTCPBlockSocket;
+ FResultCode: Integer;
+ FResultString: string;
+ FFullResult: TStringList;
+ FStatCount: Integer;
+ FStatSize: Integer;
+ FListSize: Integer;
+ FTimeStamp: string;
+ FAuthType: TPOP3AuthType;
+ FPOP3cap: TStringList;
+ FAutoTLS: Boolean;
+ FFullSSL: Boolean;
+ function ReadResult(Full: Boolean): Integer;
+ function Connect: Boolean;
+ function AuthLogin: Boolean;
+ function AuthApop: Boolean;
+ public
+ constructor Create;
+ destructor Destroy; override;
+
+ {:You can call any custom by this method. Call Command without trailing CRLF.
+ If MultiLine parameter is @true, multilined response are expected.
+ Result is @true on sucess.}
+ function CustomCommand(const Command: string; MultiLine: Boolean): boolean;
+
+ {:Call CAPA command for get POP3 server capabilites.
+ note: not all servers support this command!}
+ function Capability: Boolean;
+
+ {:Connect to remote POP3 host. If all OK, result is @true.}
+ function Login: Boolean;
+
+ {:Disconnects from POP3 server.}
+ function Logout: Boolean;
+
+ {:Send RSET command. If all OK, result is @true.}
+ function Reset: Boolean;
+
+ {:Send NOOP command. If all OK, result is @true.}
+ function NoOp: Boolean;
+
+ {:Send STAT command and fill @link(StatCount) and @link(StatSize) property.
+ If all OK, result is @true.}
+ function Stat: Boolean;
+
+ {:Send LIST command. If Value is 0, LIST is for all messages. After
+ successful operation is listing in FullResult. If all OK, result is @True.}
+ function List(Value: Integer): Boolean;
+
+ {:Send RETR command. After successful operation dowloaded message in
+ @link(FullResult). If all OK, result is @true.}
+ function Retr(Value: Integer): Boolean;
+
+ {:Send RETR command. After successful operation dowloaded message in
+ @link(Stream). If all OK, result is @true.}
+ function RetrStream(Value: Integer; Stream: TStream): Boolean;
+
+ {:Send DELE command for delete specified message. If all OK, result is @true.}
+ function Dele(Value: Integer): Boolean;
+
+ {:Send TOP command. After successful operation dowloaded headers of message
+ and maxlines count of message in @link(FullResult). If all OK, result is
+ @true.}
+ function Top(Value, Maxlines: Integer): Boolean;
+
+ {:Send UIDL command. If Value is 0, UIDL is for all messages. After
+ successful operation is listing in FullResult. If all OK, result is @True.}
+ function Uidl(Value: Integer): Boolean;
+
+ {:Call STLS command for upgrade connection to SSL/TLS mode.}
+ function StartTLS: Boolean;
+
+ {:Try to find given capabily in capabilty string returned from POP3 server
+ by CAPA command.}
+ function FindCap(const Value: string): string;
+ published
+ {:Result code of last POP3 operation. 0 - error, 1 - OK.}
+ property ResultCode: Integer read FResultCode;
+
+ {:Result string of last POP3 operation.}
+ property ResultString: string read FResultString;
+
+ {:Stringlist with full lines returned as result of POP3 operation. I.e. if
+ operation is LIST, this property is filled by list of messages. If
+ operation is RETR, this property have downloaded message.}
+ property FullResult: TStringList read FFullResult;
+
+ {:After STAT command is there count of messages in inbox.}
+ property StatCount: Integer read FStatCount;
+
+ {:After STAT command is there size of all messages in inbox.}
+ property StatSize: Integer read FStatSize;
+
+ {:After LIST 0 command size of all messages on server, After LIST x size of message x on server}
+ property ListSize: Integer read FListSize;
+
+ {:If server support this, after comnnect is in this property timestamp of
+ remote server.}
+ property TimeStamp: string read FTimeStamp;
+
+ {:Type of authorisation for login to POP3 server. Dafault is autodetect one
+ of possible authorisation. Autodetect do this:
+
+ If remote POP3 server support APOP, try login by APOP method. If APOP is
+ not supported, or if APOP login failed, try classic USER+PASS login method.}
+ property AuthType: TPOP3AuthType read FAuthType Write FAuthType;
+
+ {:If is set to @true, then upgrade to SSL/TLS mode if remote server support it.}
+ property AutoTLS: Boolean read FAutoTLS Write FAutoTLS;
+
+ {:SSL/TLS mode is used from first contact to server. Servers with full
+ SSL/TLS mode usualy using non-standard TCP port!}
+ property FullSSL: Boolean read FFullSSL Write FFullSSL;
+ {:Socket object used for TCP/IP operation. Good for seting OnStatus hook, etc.}
+ property Sock: TTCPBlockSocket read FSock;
+ end;
+
+implementation
+
+constructor TPOP3Send.Create;
+begin
+ inherited Create;
+ FFullResult := TStringList.Create;
+ FPOP3cap := TStringList.Create;
+ FSock := TTCPBlockSocket.Create;
+ FSock.ConvertLineEnd := true;
+ FTimeout := 60000;
+ FTargetPort := cPop3Protocol;
+ FStatCount := 0;
+ FStatSize := 0;
+ FListSize := 0;
+ FAuthType := POP3AuthAll;
+ FAutoTLS := False;
+ FFullSSL := False;
+end;
+
+destructor TPOP3Send.Destroy;
+begin
+ FSock.Free;
+ FPOP3cap.Free;
+ FullResult.Free;
+ inherited Destroy;
+end;
+
+function TPOP3Send.ReadResult(Full: Boolean): Integer;
+var
+ s: string;
+begin
+ Result := 0;
+ FFullResult.Clear;
+ s := FSock.RecvString(FTimeout);
+ if Pos('+OK', s) = 1 then
+ Result := 1;
+ FResultString := s;
+ if Full and (Result = 1) then
+ repeat
+ s := FSock.RecvString(FTimeout);
+ if s = '.' then
+ Break;
+ if s <> '' then
+ if s[1] = '.' then
+ Delete(s, 1, 1);
+ FFullResult.Add(s);
+ until FSock.LastError <> 0;
+ if not Full and (Result = 1) then
+ FFullResult.Add(SeparateRight(FResultString, ' '));
+ if FSock.LastError <> 0 then
+ Result := 0;
+ FResultCode := Result;
+end;
+
+function TPOP3Send.CustomCommand(const Command: string; MultiLine: Boolean): boolean;
+begin
+ FSock.SendString(Command + CRLF);
+ Result := ReadResult(MultiLine) <> 0;
+end;
+
+function TPOP3Send.AuthLogin: Boolean;
+begin
+ Result := False;
+ if not CustomCommand('USER ' + FUserName, False) then
+ exit;
+ Result := CustomCommand('PASS ' + FPassword, False)
+end;
+
+function TPOP3Send.AuthAPOP: Boolean;
+var
+ s: string;
+begin
+ s := StrToHex(MD5(FTimeStamp + FPassWord));
+ Result := CustomCommand('APOP ' + FUserName + ' ' + s, False);
+end;
+
+function TPOP3Send.Connect: Boolean;
+begin
+ // Do not call this function! It is calling by LOGIN method!
+ FStatCount := 0;
+ FStatSize := 0;
+ FSock.CloseSocket;
+ FSock.LineBuffer := '';
+ FSock.Bind(FIPInterface, cAnyPort);
+ if FSock.LastError = 0 then
+ FSock.Connect(FTargetHost, FTargetPort);
+ if FSock.LastError = 0 then
+ if FFullSSL then
+ FSock.SSLDoConnect;
+ Result := FSock.LastError = 0;
+end;
+
+function TPOP3Send.Capability: Boolean;
+begin
+ FPOP3cap.Clear;
+ Result := CustomCommand('CAPA', True);
+ if Result then
+ FPOP3cap.AddStrings(FFullResult);
+end;
+
+function TPOP3Send.Login: Boolean;
+var
+ s, s1: string;
+begin
+ Result := False;
+ FTimeStamp := '';
+ if not Connect then
+ Exit;
+ if ReadResult(False) <> 1 then
+ Exit;
+ s := SeparateRight(FResultString, '<');
+ if s <> FResultString then
+ begin
+ s1 := Trim(SeparateLeft(s, '>'));
+ if s1 <> s then
+ FTimeStamp := '<' + s1 + '>';
+ end;
+ Result := False;
+ if Capability then
+ if FAutoTLS and (Findcap('STLS') <> '') then
+ if StartTLS then
+ Capability
+ else
+ begin
+ Result := False;
+ Exit;
+ end;
+ if (FTimeStamp <> '') and not (FAuthType = POP3AuthLogin) then
+ begin
+ Result := AuthApop;
+ if not Result then
+ begin
+ if not Connect then
+ Exit;
+ if ReadResult(False) <> 1 then
+ Exit;
+ end;
+ end;
+ if not Result and not (FAuthType = POP3AuthAPOP) then
+ Result := AuthLogin;
+end;
+
+function TPOP3Send.Logout: Boolean;
+begin
+ Result := CustomCommand('QUIT', False);
+ FSock.CloseSocket;
+end;
+
+function TPOP3Send.Reset: Boolean;
+begin
+ Result := CustomCommand('RSET', False);
+end;
+
+function TPOP3Send.NoOp: Boolean;
+begin
+ Result := CustomCommand('NOOP', False);
+end;
+
+function TPOP3Send.Stat: Boolean;
+var
+ s: string;
+begin
+ Result := CustomCommand('STAT', False);
+ if Result then
+ begin
+ s := SeparateRight(ResultString, '+OK ');
+ FStatCount := StrToIntDef(Trim(SeparateLeft(s, ' ')), 0);
+ FStatSize := StrToIntDef(Trim(SeparateRight(s, ' ')), 0);
+ end;
+end;
+
+function TPOP3Send.List(Value: Integer): Boolean;
+var
+ s: string;
+ n: integer;
+begin
+ if Value = 0 then
+ s := 'LIST'
+ else
+ s := 'LIST ' + IntToStr(Value);
+ Result := CustomCommand(s, Value = 0);
+ FListSize := 0;
+ if Result then
+ if Value <> 0 then
+ begin
+ s := SeparateRight(ResultString, '+OK ');
+ FListSize := StrToIntDef(SeparateLeft(SeparateRight(s, ' '), ' '), 0);
+ end
+ else
+ for n := 0 to FFullResult.Count - 1 do
+ FListSize := FListSize + StrToIntDef(SeparateLeft(SeparateRight(s, ' '), ' '), 0);
+end;
+
+function TPOP3Send.Retr(Value: Integer): Boolean;
+begin
+ Result := CustomCommand('RETR ' + IntToStr(Value), True);
+end;
+
+//based on code by Miha Vrhovnik
+function TPOP3Send.RetrStream(Value: Integer; Stream: TStream): Boolean;
+var
+ s: string;
+begin
+ Result := False;
+ FFullResult.Clear;
+ Stream.Size := 0;
+ FSock.SendString('RETR ' + IntToStr(Value) + CRLF);
+
+ s := FSock.RecvString(FTimeout);
+ if Pos('+OK', s) = 1 then
+ Result := True;
+ FResultString := s;
+ if Result then begin
+ repeat
+ s := FSock.RecvString(FTimeout);
+ if s = '.' then
+ Break;
+ if s <> '' then begin
+ if s[1] = '.' then
+ Delete(s, 1, 1);
+ end;
+ WriteStrToStream(Stream, s);
+ WriteStrToStream(Stream, CRLF);
+ until FSock.LastError <> 0;
+ end;
+
+ if Result then
+ FResultCode := 1
+ else
+ FResultCode := 0;
+end;
+
+function TPOP3Send.Dele(Value: Integer): Boolean;
+begin
+ Result := CustomCommand('DELE ' + IntToStr(Value), False);
+end;
+
+function TPOP3Send.Top(Value, Maxlines: Integer): Boolean;
+begin
+ Result := CustomCommand('TOP ' + IntToStr(Value) + ' ' + IntToStr(Maxlines), True);
+end;
+
+function TPOP3Send.Uidl(Value: Integer): Boolean;
+var
+ s: string;
+begin
+ if Value = 0 then
+ s := 'UIDL'
+ else
+ s := 'UIDL ' + IntToStr(Value);
+ Result := CustomCommand(s, Value = 0);
+end;
+
+function TPOP3Send.StartTLS: Boolean;
+begin
+ Result := False;
+ if CustomCommand('STLS', False) then
+ begin
+ Fsock.SSLDoConnect;
+ Result := FSock.LastError = 0;
+ end;
+end;
+
+function TPOP3Send.FindCap(const Value: string): string;
+var
+ n: Integer;
+ s: string;
+begin
+ s := UpperCase(Value);
+ Result := '';
+ for n := 0 to FPOP3cap.Count - 1 do
+ if Pos(s, UpperCase(FPOP3cap[n])) = 1 then
+ begin
+ Result := FPOP3cap[n];
+ Break;
+ end;
+end;
+
+end.
diff --git a/branches/script-component/Units/Synapse/slogsend.pas b/branches/script-component/Units/Synapse/slogsend.pas
new file mode 100644
index 0000000..9c0625d
--- /dev/null
+++ b/branches/script-component/Units/Synapse/slogsend.pas
@@ -0,0 +1,319 @@
+{==============================================================================|
+| Project : Ararat Synapse | 001.002.002 |
+|==============================================================================|
+| Content: SysLog client |
+|==============================================================================|
+| Copyright (c)1999-2003, Lukas Gebauer |
+| All rights reserved. |
+| |
+| Redistribution and use in source and binary forms, with or without |
+| modification, are permitted provided that the following conditions are met: |
+| |
+| Redistributions of source code must retain the above copyright notice, this |
+| list of conditions and the following disclaimer. |
+| |
+| Redistributions in binary form must reproduce the above copyright notice, |
+| this list of conditions and the following disclaimer in the documentation |
+| and/or other materials provided with the distribution. |
+| |
+| Neither the name of Lukas Gebauer nor the names of its contributors may |
+| be used to endorse or promote products derived from this software without |
+| specific prior written permission. |
+| |
+| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
+| AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
+| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
+| ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR |
+| ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
+| DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
+| SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
+| CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
+| LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
+| OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
+| DAMAGE. |
+|==============================================================================|
+| The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).|
+| Portions created by Lukas Gebauer are Copyright (c)2001-2003. |
+| All Rights Reserved. |
+|==============================================================================|
+| Contributor(s): |
+| Christian Brosius |
+|==============================================================================|
+| History: see HISTORY.HTM from distribution package |
+| (Found at URL: http://www.ararat.cz/synapse/) |
+|==============================================================================}
+
+{:@abstract(BSD SYSLOG protocol)
+
+Used RFC: RFC-3164
+}
+
+{$IFDEF FPC}
+ {$MODE DELPHI}
+{$ENDIF}
+{$Q-}
+{$H+}
+
+unit slogsend;
+
+interface
+
+uses
+ SysUtils, Classes,
+ blcksock, synautil;
+
+const
+ cSysLogProtocol = '514';
+
+ FCL_Kernel = 0;
+ FCL_UserLevel = 1;
+ FCL_MailSystem = 2;
+ FCL_System = 3;
+ FCL_Security = 4;
+ FCL_Syslogd = 5;
+ FCL_Printer = 6;
+ FCL_News = 7;
+ FCL_UUCP = 8;
+ FCL_Clock = 9;
+ FCL_Authorization = 10;
+ FCL_FTP = 11;
+ FCL_NTP = 12;
+ FCL_LogAudit = 13;
+ FCL_LogAlert = 14;
+ FCL_Time = 15;
+ FCL_Local0 = 16;
+ FCL_Local1 = 17;
+ FCL_Local2 = 18;
+ FCL_Local3 = 19;
+ FCL_Local4 = 20;
+ FCL_Local5 = 21;
+ FCL_Local6 = 22;
+ FCL_Local7 = 23;
+
+type
+ {:@abstract(Define possible priority of Syslog message)}
+ TSyslogSeverity = (Emergency, Alert, Critical, Error, Warning, Notice, Info,
+ Debug);
+
+ {:@abstract(encoding or decoding of SYSLOG message)}
+ TSyslogMessage = class(TObject)
+ private
+ FFacility:Byte;
+ FSeverity:TSyslogSeverity;
+ FDateTime:TDateTime;
+ FTag:String;
+ FMessage:String;
+ FLocalIP:String;
+ function GetPacketBuf:String;
+ procedure SetPacketBuf(Value:String);
+ public
+ {:Reset values to defaults}
+ procedure Clear;
+ published
+ {:Define facilicity of Syslog message. For specify you may use predefined
+ FCL_* constants. Default is "FCL_Local0".}
+ property Facility:Byte read FFacility write FFacility;
+
+ {:Define possible priority of Syslog message. Default is "Debug".}
+ property Severity:TSyslogSeverity read FSeverity write FSeverity;
+
+ {:date and time of Syslog message}
+ property DateTime:TDateTime read FDateTime write FDateTime;
+
+ {:This is used for identify process of this message. Default is filename
+ of your executable file.}
+ property Tag:String read FTag write FTag;
+
+ {:Text of your message for log.}
+ property LogMessage:String read FMessage write FMessage;
+
+ {:IP address of message sender.}
+ property LocalIP:String read FLocalIP write FLocalIP;
+
+ {:This property holds encoded binary SYSLOG packet}
+ property PacketBuf:String read GetPacketBuf write SetPacketBuf;
+ end;
+
+ {:@abstract(This object implement BSD SysLog client)
+
+ Note: Are you missing properties for specify server address and port? Look to
+ parent @link(TSynaClient) too!}
+ TSyslogSend = class(TSynaClient)
+ private
+ FSock: TUDPBlockSocket;
+ FSysLogMessage: TSysLogMessage;
+ public
+ constructor Create;
+ destructor Destroy; override;
+ {:Send Syslog UDP packet defined by @link(SysLogMessage).}
+ function DoIt: Boolean;
+ published
+ {:Syslog message for send}
+ property SysLogMessage:TSysLogMessage read FSysLogMessage write FSysLogMessage;
+ end;
+
+{:Simply send packet to specified Syslog server.}
+function ToSysLog(const SyslogServer: string; Facil: Byte;
+ Sever: TSyslogSeverity; const Content: string): Boolean;
+
+implementation
+
+function TSyslogMessage.GetPacketBuf:String;
+begin
+ Result := '<' + IntToStr((FFacility * 8) + Ord(FSeverity)) + '>';
+ Result := Result + CDateTime(FDateTime) + ' ';
+ Result := Result + FLocalIP + ' ';
+ Result := Result + FTag + ': ' + FMessage;
+end;
+
+procedure TSyslogMessage.SetPacketBuf(Value:String);
+var StrBuf:String;
+ IntBuf,Pos:Integer;
+begin
+ if Length(Value) < 1 then exit;
+ Pos := 1;
+ if Value[Pos] <> '<' then exit;
+ Inc(Pos);
+ // Facility and Severity
+ StrBuf := '';
+ while (Value[Pos] <> '>')do
+ begin
+ StrBuf := StrBuf + Value[Pos];
+ Inc(Pos);
+ end;
+ IntBuf := StrToInt(StrBuf);
+ FFacility := IntBuf div 8;
+ case (IntBuf mod 8)of
+ 0:FSeverity := Emergency;
+ 1:FSeverity := Alert;
+ 2:FSeverity := Critical;
+ 3:FSeverity := Error;
+ 4:FSeverity := Warning;
+ 5:FSeverity := Notice;
+ 6:FSeverity := Info;
+ 7:FSeverity := Debug;
+ end;
+ // DateTime
+ Inc(Pos);
+ StrBuf := '';
+ // Month
+ while (Value[Pos] <> ' ')do
+ begin
+ StrBuf := StrBuf + Value[Pos];
+ Inc(Pos);
+ end;
+ StrBuf := StrBuf + Value[Pos];
+ Inc(Pos);
+ // Day
+ while (Value[Pos] <> ' ')do
+ begin
+ StrBuf := StrBuf + Value[Pos];
+ Inc(Pos);
+ end;
+ StrBuf := StrBuf + Value[Pos];
+ Inc(Pos);
+ // Time
+ while (Value[Pos] <> ' ')do
+ begin
+ StrBuf := StrBuf + Value[Pos];
+ Inc(Pos);
+ end;
+ FDateTime := DecodeRFCDateTime(StrBuf);
+ Inc(Pos);
+
+ // LocalIP
+ StrBuf := '';
+ while (Value[Pos] <> ' ')do
+ begin
+ StrBuf := StrBuf + Value[Pos];
+ Inc(Pos);
+ end;
+ FLocalIP := StrBuf;
+ Inc(Pos);
+ // Tag
+ StrBuf := '';
+ while (Value[Pos] <> ':')do
+ begin
+ StrBuf := StrBuf + Value[Pos];
+ Inc(Pos);
+ end;
+ FTag := StrBuf;
+ // LogMessage
+ Inc(Pos);
+ StrBuf := '';
+ while (Pos <= Length(Value))do
+ begin
+ StrBuf := StrBuf + Value[Pos];
+ Inc(Pos);
+ end;
+ FMessage := TrimSP(StrBuf);
+end;
+
+procedure TSysLogMessage.Clear;
+begin
+ FFacility := FCL_Local0;
+ FSeverity := Debug;
+ FTag := ExtractFileName(ParamStr(0));
+ FMessage := '';
+ FLocalIP := '0.0.0.0';
+end;
+
+//------------------------------------------------------------------------------
+
+constructor TSyslogSend.Create;
+begin
+ inherited Create;
+ FSock := TUDPBlockSocket.Create;
+ FSysLogMessage := TSysLogMessage.Create;
+ FTargetPort := cSysLogProtocol;
+end;
+
+destructor TSyslogSend.Destroy;
+begin
+ FSock.Free;
+ FSysLogMessage.Free;
+ inherited Destroy;
+end;
+
+function TSyslogSend.DoIt: Boolean;
+var
+ L: TStringList;
+begin
+ Result := False;
+ L := TStringList.Create;
+ try
+ FSock.ResolveNameToIP(FSock.Localname, L);
+ if L.Count < 1 then
+ FSysLogMessage.LocalIP := '0.0.0.0'
+ else
+ FSysLogMessage.LocalIP := L[0];
+ finally
+ L.Free;
+ end;
+ FSysLogMessage.DateTime := Now;
+ if Length(FSysLogMessage.PacketBuf) <= 1024 then
+ begin
+ FSock.Connect(FTargetHost, FTargetPort);
+ FSock.SendString(FSysLogMessage.PacketBuf);
+ Result := FSock.LastError = 0;
+ end;
+end;
+
+{==============================================================================}
+
+function ToSysLog(const SyslogServer: string; Facil: Byte;
+ Sever: TSyslogSeverity; const Content: string): Boolean;
+begin
+ with TSyslogSend.Create do
+ try
+ TargetHost :=SyslogServer;
+ SysLogMessage.Facility := Facil;
+ SysLogMessage.Severity := Sever;
+ SysLogMessage.LogMessage := Content;
+ Result := DoIt;
+ finally
+ Free;
+ end;
+end;
+
+end.
diff --git a/branches/script-component/Units/Synapse/smtpsend.pas b/branches/script-component/Units/Synapse/smtpsend.pas
new file mode 100644
index 0000000..f597ef9
--- /dev/null
+++ b/branches/script-component/Units/Synapse/smtpsend.pas
@@ -0,0 +1,719 @@
+{==============================================================================|
+| Project : Ararat Synapse | 003.005.000 |
+|==============================================================================|
+| Content: SMTP client |
+|==============================================================================|
+| Copyright (c)1999-2009, Lukas Gebauer |
+| All rights reserved. |
+| |
+| Redistribution and use in source and binary forms, with or without |
+| modification, are permitted provided that the following conditions are met: |
+| |
+| Redistributions of source code must retain the above copyright notice, this |
+| list of conditions and the following disclaimer. |
+| |
+| Redistributions in binary form must reproduce the above copyright notice, |
+| this list of conditions and the following disclaimer in the documentation |
+| and/or other materials provided with the distribution. |
+| |
+| Neither the name of Lukas Gebauer nor the names of its contributors may |
+| be used to endorse or promote products derived from this software without |
+| specific prior written permission. |
+| |
+| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
+| AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
+| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
+| ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR |
+| ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
+| DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
+| SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
+| CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
+| LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
+| OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
+| DAMAGE. |
+|==============================================================================|
+| The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).|
+| Portions created by Lukas Gebauer are Copyright (c) 1999-2009. |
+| All Rights Reserved. |
+|==============================================================================|
+| Contributor(s): |
+|==============================================================================|
+| History: see HISTORY.HTM from distribution package |
+| (Found at URL: http://www.ararat.cz/synapse/) |
+|==============================================================================}
+
+{:@abstract(SMTP client)
+
+Used RFC: RFC-1869, RFC-1870, RFC-1893, RFC-2034, RFC-2104, RFC-2195, RFC-2487,
+ RFC-2554, RFC-2821
+}
+
+{$IFDEF FPC}
+ {$MODE DELPHI}
+{$ENDIF}
+{$H+}
+
+unit smtpsend;
+
+interface
+
+uses
+ SysUtils, Classes,
+ blcksock, synautil, synacode;
+
+const
+ cSmtpProtocol = '25';
+
+type
+ {:@abstract(Implementation of SMTP and ESMTP procotol),
+ include some ESMTP extensions, include SSL/TLS too.
+
+ Note: Are you missing properties for setting Username and Password for ESMTP?
+ Look to parent @link(TSynaClient) object!
+
+ Are you missing properties for specify server address and port? Look to
+ parent @link(TSynaClient) too!}
+ TSMTPSend = class(TSynaClient)
+ private
+ FSock: TTCPBlockSocket;
+ FResultCode: Integer;
+ FResultString: string;
+ FFullResult: TStringList;
+ FESMTPcap: TStringList;
+ FESMTP: Boolean;
+ FAuthDone: Boolean;
+ FESMTPSize: Boolean;
+ FMaxSize: Integer;
+ FEnhCode1: Integer;
+ FEnhCode2: Integer;
+ FEnhCode3: Integer;
+ FSystemName: string;
+ FAutoTLS: Boolean;
+ FFullSSL: Boolean;
+ procedure EnhancedCode(const Value: string);
+ function ReadResult: Integer;
+ function AuthLogin: Boolean;
+ function AuthCram: Boolean;
+ function AuthPlain: Boolean;
+ function Helo: Boolean;
+ function Ehlo: Boolean;
+ function Connect: Boolean;
+ public
+ constructor Create;
+ destructor Destroy; override;
+
+ {:Connects to SMTP server (defined in @link(TSynaClient.TargetHost)) and
+ begin SMTP session. (First try ESMTP EHLO, next old HELO handshake). Parses
+ ESMTP capabilites and if you specified Username and password and remote
+ server can handle AUTH command, try login by AUTH command. Preffered login
+ method is CRAM-MD5 (if safer!). If all OK, result is @true, else result is
+ @false.}
+ function Login: Boolean;
+
+ {:Close SMTP session (QUIT command) and disconnect from SMTP server.}
+ function Logout: Boolean;
+
+ {:Send RSET SMTP command for reset SMTP session. If all OK, result is @true,
+ else result is @false.}
+ function Reset: Boolean;
+
+ {:Send NOOP SMTP command for keep SMTP session. If all OK, result is @true,
+ else result is @false.}
+ function NoOp: Boolean;
+
+ {:Send MAIL FROM SMTP command for set sender e-mail address. If sender's
+ e-mail address is empty string, transmited message is error message.
+
+ If size not 0 and remote server can handle SIZE parameter, append SIZE
+ parameter to request. If all OK, result is @true, else result is @false.}
+ function MailFrom(const Value: string; Size: Integer): Boolean;
+
+ {:Send RCPT TO SMTP command for set receiver e-mail address. It cannot be an
+ empty string. If all OK, result is @true, else result is @false.}
+ function MailTo(const Value: string): Boolean;
+
+ {:Send DATA SMTP command and transmit message data. If all OK, result is
+ @true, else result is @false.}
+ function MailData(const Value: Tstrings): Boolean;
+
+ {:Send ETRN SMTP command for start sending of remote queue for domain in
+ Value. If all OK, result is @true, else result is @false.}
+ function Etrn(const Value: string): Boolean;
+
+ {:Send VRFY SMTP command for check receiver e-mail address. It cannot be
+ an empty string. If all OK, result is @true, else result is @false.}
+ function Verify(const Value: string): Boolean;
+
+ {:Call STARTTLS command for upgrade connection to SSL/TLS mode.}
+ function StartTLS: Boolean;
+
+ {:Return string descriptive text for enhanced result codes stored in
+ @link(EnhCode1), @link(EnhCode2) and @link(EnhCode3).}
+ function EnhCodeString: string;
+
+ {:Try to find specified capability in ESMTP response.}
+ function FindCap(const Value: string): string;
+ published
+ {:result code of last SMTP command.}
+ property ResultCode: Integer read FResultCode;
+
+ {:result string of last SMTP command (begin with string representation of
+ result code).}
+ property ResultString: string read FResultString;
+
+ {:All result strings of last SMTP command (result is maybe multiline!).}
+ property FullResult: TStringList read FFullResult;
+
+ {:List of ESMTP capabilites of remote ESMTP server. (If you connect to ESMTP
+ server only!).}
+ property ESMTPcap: TStringList read FESMTPcap;
+
+ {:@TRUE if you successfuly logged to ESMTP server.}
+ property ESMTP: Boolean read FESMTP;
+
+ {:@TRUE if you successfuly pass authorisation to remote server.}
+ property AuthDone: Boolean read FAuthDone;
+
+ {:@TRUE if remote server can handle SIZE parameter.}
+ property ESMTPSize: Boolean read FESMTPSize;
+
+ {:When @link(ESMTPsize) is @TRUE, contains max length of message that remote
+ server can handle.}
+ property MaxSize: Integer read FMaxSize;
+
+ {:First digit of Enhanced result code. If last operation does not have
+ enhanced result code, values is 0.}
+ property EnhCode1: Integer read FEnhCode1;
+
+ {:Second digit of Enhanced result code. If last operation does not have
+ enhanced result code, values is 0.}
+ property EnhCode2: Integer read FEnhCode2;
+
+ {:Third digit of Enhanced result code. If last operation does not have
+ enhanced result code, values is 0.}
+ property EnhCode3: Integer read FEnhCode3;
+
+ {:name of our system used in HELO and EHLO command. Implicit value is
+ internet address of your machine.}
+ property SystemName: string read FSystemName Write FSystemName;
+
+ {:If is set to true, then upgrade to SSL/TLS mode if remote server support it.}
+ property AutoTLS: Boolean read FAutoTLS Write FAutoTLS;
+
+ {:SSL/TLS mode is used from first contact to server. Servers with full
+ SSL/TLS mode usualy using non-standard TCP port!}
+ property FullSSL: Boolean read FFullSSL Write FFullSSL;
+
+ {:Socket object used for TCP/IP operation. Good for seting OnStatus hook, etc.}
+ property Sock: TTCPBlockSocket read FSock;
+ end;
+
+{:A very useful function and example of its use would be found in the TSMTPsend
+ object. Send maildata (text of e-mail with all SMTP headers! For example when
+ text of message is created by @link(TMimemess) object) from "MailFrom" e-mail
+ address to "MailTo" e-mail address (If you need more then one receiver, then
+ separate their addresses by comma).
+
+ Function sends e-mail to a SMTP server defined in "SMTPhost" parameter.
+ Username and password are used for authorization to the "SMTPhost". If you
+ don't want authorization, set "Username" and "Password" to empty strings. If
+ e-mail message is successfully sent, the result returns @true.
+
+ If you need use different port number then standard, then add this port number
+ to SMTPhost after colon. (i.e. '127.0.0.1:1025')}
+function SendToRaw(const MailFrom, MailTo, SMTPHost: string;
+ const MailData: TStrings; const Username, Password: string): Boolean;
+
+{:A very useful function and example of its use would be found in the TSMTPsend
+ object. Send "Maildata" (text of e-mail without any SMTP headers!) from
+ "MailFrom" e-mail address to "MailTo" e-mail address with "Subject". (If you
+ need more then one receiver, then separate their addresses by comma).
+
+ This function constructs all needed SMTP headers (with DATE header) and sends
+ the e-mail to the SMTP server defined in the "SMTPhost" parameter. If the
+ e-mail message is successfully sent, the result will be @TRUE.
+
+ If you need use different port number then standard, then add this port number
+ to SMTPhost after colon. (i.e. '127.0.0.1:1025')}
+function SendTo(const MailFrom, MailTo, Subject, SMTPHost: string;
+ const MailData: TStrings): Boolean;
+
+{:A very useful function and example of its use would be found in the TSMTPsend
+ object. Sends "MailData" (text of e-mail without any SMTP headers!) from
+ "MailFrom" e-mail address to "MailTo" e-mail address (If you need more then one
+ receiver, then separate their addresses by comma).
+
+ This function sends the e-mail to the SMTP server defined in the "SMTPhost"
+ parameter. Username and password are used for authorization to the "SMTPhost".
+ If you dont want authorization, set "Username" and "Password" to empty Strings.
+ If the e-mail message is successfully sent, the result will be @TRUE.
+
+ If you need use different port number then standard, then add this port number
+ to SMTPhost after colon. (i.e. '127.0.0.1:1025')}
+function SendToEx(const MailFrom, MailTo, Subject, SMTPHost: string;
+ const MailData: TStrings; const Username, Password: string): Boolean;
+
+implementation
+
+constructor TSMTPSend.Create;
+begin
+ inherited Create;
+ FFullResult := TStringList.Create;
+ FESMTPcap := TStringList.Create;
+ FSock := TTCPBlockSocket.Create;
+ FSock.ConvertLineEnd := true;
+ FTimeout := 60000;
+ FTargetPort := cSmtpProtocol;
+ FSystemName := FSock.LocalName;
+ FAutoTLS := False;
+ FFullSSL := False;
+end;
+
+destructor TSMTPSend.Destroy;
+begin
+ FSock.Free;
+ FESMTPcap.Free;
+ FFullResult.Free;
+ inherited Destroy;
+end;
+
+procedure TSMTPSend.EnhancedCode(const Value: string);
+var
+ s, t: string;
+ e1, e2, e3: Integer;
+begin
+ FEnhCode1 := 0;
+ FEnhCode2 := 0;
+ FEnhCode3 := 0;
+ s := Copy(Value, 5, Length(Value) - 4);
+ t := Trim(SeparateLeft(s, '.'));
+ s := Trim(SeparateRight(s, '.'));
+ if t = '' then
+ Exit;
+ if Length(t) > 1 then
+ Exit;
+ e1 := StrToIntDef(t, 0);
+ if e1 = 0 then
+ Exit;
+ t := Trim(SeparateLeft(s, '.'));
+ s := Trim(SeparateRight(s, '.'));
+ if t = '' then
+ Exit;
+ if Length(t) > 3 then
+ Exit;
+ e2 := StrToIntDef(t, 0);
+ t := Trim(SeparateLeft(s, ' '));
+ if t = '' then
+ Exit;
+ if Length(t) > 3 then
+ Exit;
+ e3 := StrToIntDef(t, 0);
+ FEnhCode1 := e1;
+ FEnhCode2 := e2;
+ FEnhCode3 := e3;
+end;
+
+function TSMTPSend.ReadResult: Integer;
+var
+ s: string;
+begin
+ Result := 0;
+ FFullResult.Clear;
+ repeat
+ s := FSock.RecvString(FTimeout);
+ FResultString := s;
+ FFullResult.Add(s);
+ if FSock.LastError <> 0 then
+ Break;
+ until Pos('-', s) <> 4;
+ s := FFullResult[0];
+ if Length(s) >= 3 then
+ Result := StrToIntDef(Copy(s, 1, 3), 0);
+ FResultCode := Result;
+ EnhancedCode(s);
+end;
+
+function TSMTPSend.AuthLogin: Boolean;
+begin
+ Result := False;
+ FSock.SendString('AUTH LOGIN' + CRLF);
+ if ReadResult <> 334 then
+ Exit;
+ FSock.SendString(EncodeBase64(FUsername) + CRLF);
+ if ReadResult <> 334 then
+ Exit;
+ FSock.SendString(EncodeBase64(FPassword) + CRLF);
+ Result := ReadResult = 235;
+end;
+
+function TSMTPSend.AuthCram: Boolean;
+var
+ s: ansistring;
+begin
+ Result := False;
+ FSock.SendString('AUTH CRAM-MD5' + CRLF);
+ if ReadResult <> 334 then
+ Exit;
+ s := Copy(FResultString, 5, Length(FResultString) - 4);
+ s := DecodeBase64(s);
+ s := HMAC_MD5(s, FPassword);
+ s := FUsername + ' ' + StrToHex(s);
+ FSock.SendString(EncodeBase64(s) + CRLF);
+ Result := ReadResult = 235;
+end;
+
+function TSMTPSend.AuthPlain: Boolean;
+var
+ s: ansistring;
+begin
+ Result := False;
+ s := ansichar(0) + FUsername + ansichar(0) + FPassword;
+ FSock.SendString('AUTH PLAIN ' + EncodeBase64(s) + CRLF);
+ Result := ReadResult = 235;
+end;
+
+function TSMTPSend.Connect: Boolean;
+begin
+ FSock.CloseSocket;
+ FSock.Bind(FIPInterface, cAnyPort);
+ if FSock.LastError = 0 then
+ FSock.Connect(FTargetHost, FTargetPort);
+ if FSock.LastError = 0 then
+ if FFullSSL then
+ FSock.SSLDoConnect;
+ Result := FSock.LastError = 0;
+end;
+
+function TSMTPSend.Helo: Boolean;
+var
+ x: Integer;
+begin
+ FSock.SendString('HELO ' + FSystemName + CRLF);
+ x := ReadResult;
+ Result := (x >= 250) and (x <= 259);
+end;
+
+function TSMTPSend.Ehlo: Boolean;
+var
+ x: Integer;
+begin
+ FSock.SendString('EHLO ' + FSystemName + CRLF);
+ x := ReadResult;
+ Result := (x >= 250) and (x <= 259);
+end;
+
+function TSMTPSend.Login: Boolean;
+var
+ n: Integer;
+ auths: string;
+ s: string;
+begin
+ Result := False;
+ FESMTP := True;
+ FAuthDone := False;
+ FESMTPcap.clear;
+ FESMTPSize := False;
+ FMaxSize := 0;
+ if not Connect then
+ Exit;
+ if ReadResult <> 220 then
+ Exit;
+ if not Ehlo then
+ begin
+ FESMTP := False;
+ if not Helo then
+ Exit;
+ end;
+ Result := True;
+ if FESMTP then
+ begin
+ for n := 1 to FFullResult.Count - 1 do
+ FESMTPcap.Add(Copy(FFullResult[n], 5, Length(FFullResult[n]) - 4));
+ if (not FullSSL) and FAutoTLS and (FindCap('STARTTLS') <> '') then
+ if StartTLS then
+ begin
+ Ehlo;
+ FESMTPcap.Clear;
+ for n := 1 to FFullResult.Count - 1 do
+ FESMTPcap.Add(Copy(FFullResult[n], 5, Length(FFullResult[n]) - 4));
+ end
+ else
+ begin
+ Result := False;
+ Exit;
+ end;
+ if not ((FUsername = '') and (FPassword = '')) then
+ begin
+ s := FindCap('AUTH ');
+ if s = '' then
+ s := FindCap('AUTH=');
+ auths := UpperCase(s);
+ if s <> '' then
+ begin
+ if Pos('CRAM-MD5', auths) > 0 then
+ FAuthDone := AuthCram;
+ if (not FauthDone) and (Pos('PLAIN', auths) > 0) then
+ FAuthDone := AuthPlain;
+ if (not FauthDone) and (Pos('LOGIN', auths) > 0) then
+ FAuthDone := AuthLogin;
+ end;
+ end;
+ s := FindCap('SIZE');
+ if s <> '' then
+ begin
+ FESMTPsize := True;
+ FMaxSize := StrToIntDef(Copy(s, 6, Length(s) - 5), 0);
+ end;
+ end;
+end;
+
+function TSMTPSend.Logout: Boolean;
+begin
+ FSock.SendString('QUIT' + CRLF);
+ Result := ReadResult = 221;
+ FSock.CloseSocket;
+end;
+
+function TSMTPSend.Reset: Boolean;
+begin
+ FSock.SendString('RSET' + CRLF);
+ Result := ReadResult div 100 = 2;
+end;
+
+function TSMTPSend.NoOp: Boolean;
+begin
+ FSock.SendString('NOOP' + CRLF);
+ Result := ReadResult div 100 = 2;
+end;
+
+function TSMTPSend.MailFrom(const Value: string; Size: Integer): Boolean;
+var
+ s: string;
+begin
+ s := 'MAIL FROM:<' + Value + '>';
+ if FESMTPsize and (Size > 0) then
+ s := s + ' SIZE=' + IntToStr(Size);
+ FSock.SendString(s + CRLF);
+ Result := ReadResult div 100 = 2;
+end;
+
+function TSMTPSend.MailTo(const Value: string): Boolean;
+begin
+ FSock.SendString('RCPT TO:<' + Value + '>' + CRLF);
+ Result := ReadResult div 100 = 2;
+end;
+
+function TSMTPSend.MailData(const Value: TStrings): Boolean;
+var
+ n: Integer;
+ s: string;
+ t: string;
+ x: integer;
+begin
+ Result := False;
+ FSock.SendString('DATA' + CRLF);
+ if ReadResult <> 354 then
+ Exit;
+ t := '';
+ x := 1500;
+ for n := 0 to Value.Count - 1 do
+ begin
+ s := Value[n];
+ if Length(s) >= 1 then
+ if s[1] = '.' then
+ s := '.' + s;
+ if Length(t) + Length(s) >= x then
+ begin
+ FSock.SendString(t);
+ t := '';
+ end;
+ t := t + s + CRLF;
+ end;
+ if t <> '' then
+ FSock.SendString(t);
+ FSock.SendString('.' + CRLF);
+ Result := ReadResult div 100 = 2;
+end;
+
+function TSMTPSend.Etrn(const Value: string): Boolean;
+var
+ x: Integer;
+begin
+ FSock.SendString('ETRN ' + Value + CRLF);
+ x := ReadResult;
+ Result := (x >= 250) and (x <= 259);
+end;
+
+function TSMTPSend.Verify(const Value: string): Boolean;
+var
+ x: Integer;
+begin
+ FSock.SendString('VRFY ' + Value + CRLF);
+ x := ReadResult;
+ Result := (x >= 250) and (x <= 259);
+end;
+
+function TSMTPSend.StartTLS: Boolean;
+begin
+ Result := False;
+ if FindCap('STARTTLS') <> '' then
+ begin
+ FSock.SendString('STARTTLS' + CRLF);
+ if (ReadResult = 220) and (FSock.LastError = 0) then
+ begin
+ Fsock.SSLDoConnect;
+ Result := FSock.LastError = 0;
+ end;
+ end;
+end;
+
+function TSMTPSend.EnhCodeString: string;
+var
+ s, t: string;
+begin
+ s := IntToStr(FEnhCode2) + '.' + IntToStr(FEnhCode3);
+ t := '';
+ if s = '0.0' then t := 'Other undefined Status';
+ if s = '1.0' then t := 'Other address status';
+ if s = '1.1' then t := 'Bad destination mailbox address';
+ if s = '1.2' then t := 'Bad destination system address';
+ if s = '1.3' then t := 'Bad destination mailbox address syntax';
+ if s = '1.4' then t := 'Destination mailbox address ambiguous';
+ if s = '1.5' then t := 'Destination mailbox address valid';
+ if s = '1.6' then t := 'Mailbox has moved';
+ if s = '1.7' then t := 'Bad sender''s mailbox address syntax';
+ if s = '1.8' then t := 'Bad sender''s system address';
+ if s = '2.0' then t := 'Other or undefined mailbox status';
+ if s = '2.1' then t := 'Mailbox disabled, not accepting messages';
+ if s = '2.2' then t := 'Mailbox full';
+ if s = '2.3' then t := 'Message Length exceeds administrative limit';
+ if s = '2.4' then t := 'Mailing list expansion problem';
+ if s = '3.0' then t := 'Other or undefined mail system status';
+ if s = '3.1' then t := 'Mail system full';
+ if s = '3.2' then t := 'System not accepting network messages';
+ if s = '3.3' then t := 'System not capable of selected features';
+ if s = '3.4' then t := 'Message too big for system';
+ if s = '3.5' then t := 'System incorrectly configured';
+ if s = '4.0' then t := 'Other or undefined network or routing status';
+ if s = '4.1' then t := 'No answer from host';
+ if s = '4.2' then t := 'Bad connection';
+ if s = '4.3' then t := 'Routing server failure';
+ if s = '4.4' then t := 'Unable to route';
+ if s = '4.5' then t := 'Network congestion';
+ if s = '4.6' then t := 'Routing loop detected';
+ if s = '4.7' then t := 'Delivery time expired';
+ if s = '5.0' then t := 'Other or undefined protocol status';
+ if s = '5.1' then t := 'Invalid command';
+ if s = '5.2' then t := 'Syntax error';
+ if s = '5.3' then t := 'Too many recipients';
+ if s = '5.4' then t := 'Invalid command arguments';
+ if s = '5.5' then t := 'Wrong protocol version';
+ if s = '6.0' then t := 'Other or undefined media error';
+ if s = '6.1' then t := 'Media not supported';
+ if s = '6.2' then t := 'Conversion required and prohibited';
+ if s = '6.3' then t := 'Conversion required but not supported';
+ if s = '6.4' then t := 'Conversion with loss performed';
+ if s = '6.5' then t := 'Conversion failed';
+ if s = '7.0' then t := 'Other or undefined security status';
+ if s = '7.1' then t := 'Delivery not authorized, message refused';
+ if s = '7.2' then t := 'Mailing list expansion prohibited';
+ if s = '7.3' then t := 'Security conversion required but not possible';
+ if s = '7.4' then t := 'Security features not supported';
+ if s = '7.5' then t := 'Cryptographic failure';
+ if s = '7.6' then t := 'Cryptographic algorithm not supported';
+ if s = '7.7' then t := 'Message integrity failure';
+ s := '???-';
+ if FEnhCode1 = 2 then s := 'Success-';
+ if FEnhCode1 = 4 then s := 'Persistent Transient Failure-';
+ if FEnhCode1 = 5 then s := 'Permanent Failure-';
+ Result := s + t;
+end;
+
+function TSMTPSend.FindCap(const Value: string): string;
+var
+ n: Integer;
+ s: string;
+begin
+ s := UpperCase(Value);
+ Result := '';
+ for n := 0 to FESMTPcap.Count - 1 do
+ if Pos(s, UpperCase(FESMTPcap[n])) = 1 then
+ begin
+ Result := FESMTPcap[n];
+ Break;
+ end;
+end;
+
+{==============================================================================}
+
+function SendToRaw(const MailFrom, MailTo, SMTPHost: string;
+ const MailData: TStrings; const Username, Password: string): Boolean;
+var
+ SMTP: TSMTPSend;
+ s, t: string;
+begin
+ Result := False;
+ SMTP := TSMTPSend.Create;
+ try
+// if you need SOCKS5 support, uncomment next lines:
+ // SMTP.Sock.SocksIP := '127.0.0.1';
+ // SMTP.Sock.SocksPort := '1080';
+// if you need support for upgrade session to TSL/SSL, uncomment next lines:
+ // SMTP.AutoTLS := True;
+// if you need support for TSL/SSL tunnel, uncomment next lines:
+ // SMTP.FullSSL := True;
+ SMTP.TargetHost := Trim(SeparateLeft(SMTPHost, ':'));
+ s := Trim(SeparateRight(SMTPHost, ':'));
+ if (s <> '') and (s <> SMTPHost) then
+ SMTP.TargetPort := s;
+ SMTP.Username := Username;
+ SMTP.Password := Password;
+ if SMTP.Login then
+ begin
+ if SMTP.MailFrom(GetEmailAddr(MailFrom), Length(MailData.Text)) then
+ begin
+ s := MailTo;
+ repeat
+ t := GetEmailAddr(Trim(FetchEx(s, ',', '"')));
+ if t <> '' then
+ Result := SMTP.MailTo(t);
+ if not Result then
+ Break;
+ until s = '';
+ if Result then
+ Result := SMTP.MailData(MailData);
+ end;
+ SMTP.Logout;
+ end;
+ finally
+ SMTP.Free;
+ end;
+end;
+
+function SendToEx(const MailFrom, MailTo, Subject, SMTPHost: string;
+ const MailData: TStrings; const Username, Password: string): Boolean;
+var
+ t: TStrings;
+begin
+ t := TStringList.Create;
+ try
+ t.Assign(MailData);
+ t.Insert(0, '');
+ t.Insert(0, 'X-mailer: Synapse - Delphi & Kylix TCP/IP library by Lukas Gebauer');
+ t.Insert(0, 'Subject: ' + Subject);
+ t.Insert(0, 'Date: ' + Rfc822DateTime(now));
+ t.Insert(0, 'To: ' + MailTo);
+ t.Insert(0, 'From: ' + MailFrom);
+ Result := SendToRaw(MailFrom, MailTo, SMTPHost, t, Username, Password);
+ finally
+ t.Free;
+ end;
+end;
+
+function SendTo(const MailFrom, MailTo, Subject, SMTPHost: string;
+ const MailData: TStrings): Boolean;
+begin
+ Result := SendToEx(MailFrom, MailTo, Subject, SMTPHost, MailData, '', '');
+end;
+
+end.
diff --git a/branches/script-component/Units/Synapse/snmpsend.pas b/branches/script-component/Units/Synapse/snmpsend.pas
new file mode 100644
index 0000000..d8909cf
--- /dev/null
+++ b/branches/script-component/Units/Synapse/snmpsend.pas
@@ -0,0 +1,1083 @@
+{==============================================================================|
+| Project : Ararat Synapse | 003.000.009 |
+|==============================================================================|
+| Content: SNMP client |
+|==============================================================================|
+| Copyright (c)1999-2007, Lukas Gebauer |
+| All rights reserved. |
+| |
+| Redistribution and use in source and binary forms, with or without |
+| modification, are permitted provided that the following conditions are met: |
+| |
+| Redistributions of source code must retain the above copyright notice, this |
+| list of conditions and the following disclaimer. |
+| |
+| Redistributions in binary form must reproduce the above copyright notice, |
+| this list of conditions and the following disclaimer in the documentation |
+| and/or other materials provided with the distribution. |
+| |
+| Neither the name of Lukas Gebauer nor the names of its contributors may |
+| be used to endorse or promote products derived from this software without |
+| specific prior written permission. |
+| |
+| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
+| AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
+| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
+| ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR |
+| ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
+| DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
+| SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
+| CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
+| LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
+| OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
+| DAMAGE. |
+|==============================================================================|
+| The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).|
+| Portions created by Lukas Gebauer are Copyright (c)2000-2007. |
+| All Rights Reserved. |
+|==============================================================================|
+| Contributor(s): |
+| Jean-Fabien Connault (cycocrew@worldnet.fr) |
+|==============================================================================|
+| History: see HISTORY.HTM from distribution package |
+| (Found at URL: http://www.ararat.cz/synapse/) |
+|==============================================================================}
+
+{:@abstract(SNMP client)
+Supports SNMPv1 include traps, SNMPv2c and SNMPv3 include authorization
+ (encryption not yet supported!)
+
+Used RFC: RFC-1157, RFC-1901, RFC-3412, RFC-3414, RFC-3416
+}
+
+{$IFDEF FPC}
+ {$MODE DELPHI}
+{$ENDIF}
+{$Q-}
+{$H+}
+
+unit snmpsend;
+
+interface
+
+uses
+ Classes, SysUtils,
+ blcksock, synautil, asn1util, synaip, synacode;
+
+const
+ cSnmpProtocol = '161';
+ cSnmpTrapProtocol = '162';
+
+ SNMP_V1 = 0;
+ SNMP_V2C = 1;
+ SNMP_V3 = 3;
+
+ //PDU type
+ PDUGetRequest = $A0;
+ PDUGetNextRequest = $A1;
+ PDUGetResponse = $A2;
+ PDUSetRequest = $A3;
+ PDUTrap = $A4; //Obsolete
+ //for SNMPv2
+ PDUGetBulkRequest = $A5;
+ PDUInformRequest = $A6;
+ PDUTrapV2 = $A7;
+ PDUReport = $A8;
+
+ //errors
+ ENoError = 0;
+ ETooBig = 1;
+ ENoSuchName = 2;
+ EBadValue = 3;
+ EReadOnly = 4;
+ EGenErr = 5;
+ //errors SNMPv2
+ ENoAccess = 6;
+ EWrongType = 7;
+ EWrongLength = 8;
+ EWrongEncoding = 9;
+ EWrongValue = 10;
+ ENoCreation = 11;
+ EInconsistentValue = 12;
+ EResourceUnavailable = 13;
+ ECommitFailed = 14;
+ EUndoFailed = 15;
+ EAuthorizationError = 16;
+ ENotWritable = 17;
+ EInconsistentName = 18;
+
+type
+
+ {:@abstract(Possible values for SNMPv3 flags.)
+ This flags specify level of authorization and encryption.}
+ TV3Flags = (
+ NoAuthNoPriv,
+ AuthNoPriv,
+ AuthPriv);
+
+ {:@abstract(Type of SNMPv3 authorization)}
+ TV3Auth = (
+ AuthMD5,
+ AuthSHA1);
+
+ {:@abstract(Data object with one record of MIB OID and corresponding values.)}
+ TSNMPMib = class(TObject)
+ protected
+ FOID: AnsiString;
+ FValue: AnsiString;
+ FValueType: Integer;
+ published
+ {:OID number in string format.}
+ property OID: AnsiString read FOID write FOID;
+
+ {:Value of OID object in string format.}
+ property Value: AnsiString read FValue write FValue;
+
+ {:Define type of Value. Supported values are defined in @link(asn1util).
+ For queries use ASN1_NULL, becouse you don't know type in response!}
+ property ValueType: Integer read FValueType write FValueType;
+ end;
+
+ {:@abstract(It holding all information for SNMPv3 agent synchronization)
+ Used internally.}
+ TV3Sync = record
+ EngineID: AnsiString;
+ EngineBoots: integer;
+ EngineTime: integer;
+ EngineStamp: Cardinal;
+ end;
+
+ {:@abstract(Data object abstracts SNMP data packet)}
+ TSNMPRec = class(TObject)
+ protected
+ FVersion: Integer;
+ FPDUType: Integer;
+ FID: Integer;
+ FErrorStatus: Integer;
+ FErrorIndex: Integer;
+ FCommunity: AnsiString;
+ FSNMPMibList: TList;
+ FMaxSize: Integer;
+ FFlags: TV3Flags;
+ FFlagReportable: Boolean;
+ FContextEngineID: AnsiString;
+ FContextName: AnsiString;
+ FAuthMode: TV3Auth;
+ FAuthEngineID: AnsiString;
+ FAuthEngineBoots: integer;
+ FAuthEngineTime: integer;
+ FAuthEngineTimeStamp: cardinal;
+ FUserName: AnsiString;
+ FPassword: AnsiString;
+ FAuthKey: AnsiString;
+ FPrivKey: AnsiString;
+ FOldTrapEnterprise: AnsiString;
+ FOldTrapHost: AnsiString;
+ FOldTrapGen: Integer;
+ FOldTrapSpec: Integer;
+ FOldTrapTimeTicks: Integer;
+ function Pass2Key(const Value: AnsiString): AnsiString;
+ public
+ constructor Create;
+ destructor Destroy; override;
+
+ {:Decode SNMP packet in buffer to object properties.}
+ function DecodeBuf(const Buffer: AnsiString): Boolean;
+
+ {:Encode obeject properties to SNMP packet.}
+ function EncodeBuf: AnsiString;
+
+ {:Clears all object properties to default values.}
+ procedure Clear;
+
+ {:Add entry to @link(SNMPMibList). For queries use value as empty string,
+ and ValueType as ASN1_NULL.}
+ procedure MIBAdd(const MIB, Value: AnsiString; ValueType: Integer);
+
+ {:Delete entry from @link(SNMPMibList).}
+ procedure MIBDelete(Index: Integer);
+
+ {:Search @link(SNMPMibList) list for MIB and return correspond value.}
+ function MIBGet(const MIB: AnsiString): AnsiString;
+
+ {:return number of entries in MIB array.}
+ function MIBCount: integer;
+
+ {:Return MIB information from given row of MIB array.}
+ function MIBByIndex(Index: Integer): TSNMPMib;
+
+ {:List of @link(TSNMPMib) objects.}
+ property SNMPMibList: TList read FSNMPMibList;
+ published
+ {:Version of SNMP packet. Default value is 0 (SNMP ver. 1). You can use
+ value 1 for SNMPv2c or value 3 for SNMPv3.}
+ property Version: Integer read FVersion write FVersion;
+
+ {:Community string for autorize access to SNMP server. (Case sensitive!)
+ Community string is not used in SNMPv3! Use @link(Username) and
+ @link(password) instead!}
+ property Community: AnsiString read FCommunity write FCommunity;
+
+ {:Define type of SNMP operation.}
+ property PDUType: Integer read FPDUType write FPDUType;
+
+ {:Contains ID number. Not need to use.}
+ property ID: Integer read FID write FID;
+
+ {:When packet is reply, contains error code. Supported values are defined by
+ E* constants.}
+ property ErrorStatus: Integer read FErrorStatus write FErrorStatus;
+
+ {:Point to error position in reply packet. Not usefull for users. It only
+ good for debugging!}
+ property ErrorIndex: Integer read FErrorIndex write FErrorIndex;
+
+ {:special value for GetBulkRequest of SNMPv2 and v3.}
+ property NonRepeaters: Integer read FErrorStatus write FErrorStatus;
+
+ {:special value for GetBulkRequest of SNMPv2 and v3.}
+ property MaxRepetitions: Integer read FErrorIndex write FErrorIndex;
+
+ {:Maximum message size in bytes for SNMPv3. For sending is default 1472 bytes.}
+ property MaxSize: Integer read FMaxSize write FMaxSize;
+
+ {:Specify if message is authorised or encrypted. Used only in SNMPv3, and
+ encryption is not yet supported!}
+ property Flags: TV3Flags read FFlags write FFlags;
+
+ {:For SNMPv3.... If is @true, SNMP agent must send reply (at least with some
+ error).}
+ property FlagReportable: Boolean read FFlagReportable write FFlagReportable;
+
+ {:For SNMPv3. If not specified, is used value from @link(AuthEngineID)}
+ property ContextEngineID: AnsiString read FContextEngineID write FContextEngineID;
+
+ {:For SNMPv3.}
+ property ContextName: AnsiString read FContextName write FContextName;
+
+ {:For SNMPv3. Specify Authorization mode. (specify used hash for
+ authorization)}
+ property AuthMode: TV3Auth read FAuthMode write FAuthMode;
+
+ {:value used by SNMPv3 authorisation for synchronization with SNMP agent.}
+ property AuthEngineID: AnsiString read FAuthEngineID write FAuthEngineID;
+
+ {:value used by SNMPv3 authorisation for synchronization with SNMP agent.}
+ property AuthEngineBoots: Integer read FAuthEngineBoots write FAuthEngineBoots;
+
+ {:value used by SNMPv3 authorisation for synchronization with SNMP agent.}
+ property AuthEngineTime: Integer read FAuthEngineTime write FAuthEngineTime;
+
+ {:value used by SNMPv3 authorisation for synchronization with SNMP agent.}
+ property AuthEngineTimeStamp: Cardinal read FAuthEngineTimeStamp Write FAuthEngineTimeStamp;
+
+ {:SNMPv3 authorization username}
+ property UserName: AnsiString read FUserName write FUserName;
+
+ {:SNMPv3 authorization password}
+ property Password: AnsiString read FPassword write FPassword;
+
+ {:For SNMPv3. Computed Athorization key from @link(password).}
+ property AuthKey: AnsiString read FAuthKey write FAuthKey;
+
+ {:For SNMPv3. Encryption key for message encryption. Not yet used!}
+ property PrivKey: AnsiString read FPrivKey write FPrivKey;
+
+ {:MIB value to identify the object that sent the TRAPv1.}
+ property OldTrapEnterprise: AnsiString read FOldTrapEnterprise write FOldTrapEnterprise;
+
+ {:Address of TRAPv1 sender (IP address).}
+ property OldTrapHost: AnsiString read FOldTrapHost write FOldTrapHost;
+
+ {:Generic TRAPv1 identification.}
+ property OldTrapGen: Integer read FOldTrapGen write FOldTrapGen;
+
+ {:Specific TRAPv1 identification.}
+ property OldTrapSpec: Integer read FOldTrapSpec write FOldTrapSpec;
+
+ {:Number of 1/100th of seconds since last reboot or power up. (for TRAPv1)}
+ property OldTrapTimeTicks: Integer read FOldTrapTimeTicks write FOldTrapTimeTicks;
+ end;
+
+ {:@abstract(Implementation of SNMP protocol.)
+
+ Note: Are you missing properties for specify server address and port? Look to
+ parent @link(TSynaClient) too!}
+ TSNMPSend = class(TSynaClient)
+ protected
+ FSock: TUDPBlockSocket;
+ FBuffer: AnsiString;
+ FHostIP: AnsiString;
+ FQuery: TSNMPRec;
+ FReply: TSNMPRec;
+ function InternalSendSnmp(const Value: TSNMPRec): Boolean;
+ function InternalRecvSnmp(const Value: TSNMPRec): Boolean;
+ function InternalSendRequest(const QValue, RValue: TSNMPRec): Boolean;
+ function GetV3EngineID: AnsiString;
+ function GetV3Sync: TV3Sync;
+ public
+ constructor Create;
+ destructor Destroy; override;
+
+ {:Connects to a Host and send there query. If in timeout SNMP server send
+ back query, result is @true. If is used SNMPv3, then it synchronize self
+ with SNMPv3 agent first. (It is needed for SNMPv3 auhorization!)}
+ function SendRequest: Boolean;
+
+ {:Send SNMP packet only, but not waits for reply. Good for sending traps.}
+ function SendTrap: Boolean;
+
+ {:Receive SNMP packet only. Good for receiving traps.}
+ function RecvTrap: Boolean;
+
+ {:Mapped to @link(SendRequest) internally. This function is only for
+ backward compatibility.}
+ function DoIt: Boolean;
+ published
+ {:contains raw binary form of SNMP packet. Good for debugging.}
+ property Buffer: AnsiString read FBuffer write FBuffer;
+
+ {:After SNMP operation hold IP address of remote side.}
+ property HostIP: AnsiString read FHostIP;
+
+ {:Data object contains SNMP query.}
+ property Query: TSNMPRec read FQuery;
+
+ {:Data object contains SNMP reply.}
+ property Reply: TSNMPRec read FReply;
+
+ {:Socket object used for TCP/IP operation. Good for seting OnStatus hook, etc.}
+ property Sock: TUDPBlockSocket read FSock;
+ end;
+
+{:A very useful function and example of its use would be found in the TSNMPSend
+ object. It implements basic GET method of the SNMP protocol. The MIB value is
+ located in the "OID" variable, and is sent to the requested "SNMPHost" with
+ the proper "Community" access identifier. Upon a successful retrieval, "Value"
+ will contain the information requested. If the SNMP operation is successful,
+ the result returns @true.}
+function SNMPGet(const OID, Community, SNMPHost: AnsiString; var Value: AnsiString): Boolean;
+
+{:This is useful function and example of use TSNMPSend object. It implements
+ the basic SET method of the SNMP protocol. If the SNMP operation is successful,
+ the result is @true. "Value" is value of MIB Oid for "SNMPHost" with "Community"
+ access identifier. You must specify "ValueType" too.}
+function SNMPSet(const OID, Community, SNMPHost, Value: AnsiString; ValueType: Integer): Boolean;
+
+{:A very useful function and example of its use would be found in the TSNMPSend
+ object. It implements basic GETNEXT method of the SNMP protocol. The MIB value
+ is located in the "OID" variable, and is sent to the requested "SNMPHost" with
+ the proper "Community" access identifier. Upon a successful retrieval, "Value"
+ will contain the information requested. If the SNMP operation is successful,
+ the result returns @true.}
+function SNMPGetNext(var OID: AnsiString; const Community, SNMPHost: AnsiString; var Value: AnsiString): Boolean;
+
+{:A very useful function and example of its use would be found in the TSNMPSend
+ object. It implements basic read of SNMP MIB tables. As BaseOID you must
+ specify basic MIB OID of requested table (base IOD is OID without row and
+ column specificator!)
+ Table is readed into stringlist, where each string is comma delimited string.
+
+ Warning: this function is not have best performance. For better performance
+ you must write your own function. best performace you can get by knowledge
+ of structuture of table and by more then one MIB on one query. }
+function SNMPGetTable(const BaseOID, Community, SNMPHost: AnsiString; const Value: TStrings): Boolean;
+
+{:A very useful function and example of its use would be found in the TSNMPSend
+ object. It implements basic read of SNMP MIB table element. As BaseOID you must
+ specify basic MIB OID of requested table (base IOD is OID without row and
+ column specificator!)
+ As next you must specify identificator of row and column for specify of needed
+ field of table.}
+function SNMPGetTableElement(const BaseOID, RowID, ColID, Community, SNMPHost: AnsiString; var Value: AnsiString): Boolean;
+
+{:A very useful function and example of its use would be found in the TSNMPSend
+ object. It implements a TRAPv1 to send with all data in the parameters.}
+function SendTrap(const Dest, Source, Enterprise, Community: AnsiString;
+ Generic, Specific, Seconds: Integer; const MIBName, MIBValue: AnsiString;
+ MIBtype: Integer): Integer;
+
+{:A very useful function and example of its use would be found in the TSNMPSend
+ object. It receives a TRAPv1 and returns all the data that comes with it.}
+function RecvTrap(var Dest, Source, Enterprise, Community: AnsiString;
+ var Generic, Specific, Seconds: Integer; const MIBName,
+ MIBValue: TStringList): Integer;
+
+implementation
+
+{==============================================================================}
+
+constructor TSNMPRec.Create;
+begin
+ inherited Create;
+ FSNMPMibList := TList.Create;
+ Clear;
+ FID := 1;
+ FMaxSize := 1472;
+end;
+
+destructor TSNMPRec.Destroy;
+var
+ i: Integer;
+begin
+ for i := 0 to FSNMPMibList.Count - 1 do
+ TSNMPMib(FSNMPMibList[i]).Free;
+ FSNMPMibList.Clear;
+ FSNMPMibList.Free;
+ inherited Destroy;
+end;
+
+function TSNMPRec.Pass2Key(const Value: AnsiString): AnsiString;
+var
+ key: AnsiString;
+begin
+ case FAuthMode of
+ AuthMD5:
+ begin
+ key := MD5LongHash(Value, 1048576);
+ Result := MD5(key + FAuthEngineID + key);
+ end;
+ AuthSHA1:
+ begin
+ key := SHA1LongHash(Value, 1048576);
+ Result := SHA1(key + FAuthEngineID + key);
+ end;
+ else
+ Result := '';
+ end;
+end;
+
+
+function TSNMPRec.DecodeBuf(const Buffer: AnsiString): Boolean;
+var
+ Pos: Integer;
+ EndPos: Integer;
+ sm, sv: AnsiString;
+ Svt: Integer;
+ s: AnsiString;
+ Spos: integer;
+ x: Byte;
+begin
+ Clear;
+ Result := False;
+ if Length(Buffer) < 2 then
+ Exit;
+ if (Ord(Buffer[1]) and $20) = 0 then
+ Exit;
+ Pos := 2;
+ EndPos := ASNDecLen(Pos, Buffer);
+ if Length(Buffer) < (EndPos + 2) then
+ Exit;
+ Self.FVersion := StrToIntDef(ASNItem(Pos, Buffer, Svt), 0);
+
+ if FVersion = 3 then
+ begin
+ ASNItem(Pos, Buffer, Svt); //header data seq
+ ASNItem(Pos, Buffer, Svt); //ID
+ FMaxSize := StrToIntDef(ASNItem(Pos, Buffer, Svt), 0);
+ s := ASNItem(Pos, Buffer, Svt);
+ x := 0;
+ if s <> '' then
+ x := Ord(s[1]);
+ FFlagReportable := (x and 4) > 0;
+ x := x and 3;
+ case x of
+ 1:
+ FFlags := AuthNoPriv;
+ 3:
+ FFlags := AuthPriv;
+ else
+ FFlags := NoAuthNoPriv;
+ end;
+
+ x := StrToIntDef(ASNItem(Pos, Buffer, Svt), 0);
+ s := ASNItem(Pos, Buffer, Svt); //SecurityParameters
+ //if SecurityModel is USM, then try to decode SecurityParameters
+ if (x = 3) and (s <> '') then
+ begin
+ spos := 1;
+ ASNItem(SPos, s, Svt);
+ FAuthEngineID := ASNItem(SPos, s, Svt);
+ FAuthEngineBoots := StrToIntDef(ASNItem(SPos, s, Svt), 0);
+ FAuthEngineTime := StrToIntDef(ASNItem(SPos, s, Svt), 0);
+ FAuthEngineTimeStamp := GetTick;
+ FUserName := ASNItem(SPos, s, Svt);
+ FAuthKey := ASNItem(SPos, s, Svt);
+ FPrivKey := ASNItem(SPos, s, Svt);
+ end;
+ //scopedPDU
+ s := ASNItem(Pos, Buffer, Svt);
+ if Svt = ASN1_OCTSTR then
+ begin
+ //decrypt!
+ end;
+ FContextEngineID := ASNItem(Pos, Buffer, Svt);
+ FContextName := ASNItem(Pos, Buffer, Svt);
+ end
+ else
+ begin
+ //old packet
+ Self.FCommunity := ASNItem(Pos, Buffer, Svt);
+ end;
+
+ ASNItem(Pos, Buffer, Svt);
+ Self.FPDUType := Svt;
+ if Self.FPDUType = PDUTrap then
+ begin
+ FOldTrapEnterprise := ASNItem(Pos, Buffer, Svt);
+ FOldTrapHost := ASNItem(Pos, Buffer, Svt);
+ FOldTrapGen := StrToIntDef(ASNItem(Pos, Buffer, Svt), 0);
+ FOldTrapSpec := StrToIntDef(ASNItem(Pos, Buffer, Svt), 0);
+ FOldTrapTimeTicks := StrToIntDef(ASNItem(Pos, Buffer, Svt), 0);
+ end
+ else
+ begin
+ Self.FID := StrToIntDef(ASNItem(Pos, Buffer, Svt), 0);
+ Self.FErrorStatus := StrToIntDef(ASNItem(Pos, Buffer, Svt), 0);
+ Self.FErrorIndex := StrToIntDef(ASNItem(Pos, Buffer, Svt), 0);
+ end;
+ ASNItem(Pos, Buffer, Svt);
+ while Pos < EndPos do
+ begin
+ ASNItem(Pos, Buffer, Svt);
+ Sm := ASNItem(Pos, Buffer, Svt);
+ Sv := ASNItem(Pos, Buffer, Svt);
+ Self.MIBAdd(sm, sv, Svt);
+ end;
+ Result := True;
+end;
+
+function TSNMPRec.EncodeBuf: AnsiString;
+var
+ s: AnsiString;
+ SNMPMib: TSNMPMib;
+ n: Integer;
+ pdu, head, auth, authbeg: AnsiString;
+ x: Byte;
+begin
+ pdu := '';
+ for n := 0 to FSNMPMibList.Count - 1 do
+ begin
+ SNMPMib := TSNMPMib(FSNMPMibList[n]);
+ case SNMPMib.ValueType of
+ ASN1_INT:
+ s := ASNObject(MibToID(SNMPMib.OID), ASN1_OBJID) +
+ ASNObject(ASNEncInt(StrToIntDef(SNMPMib.Value, 0)), SNMPMib.ValueType);
+ ASN1_COUNTER, ASN1_GAUGE, ASN1_TIMETICKS:
+ s := ASNObject(MibToID(SNMPMib.OID), ASN1_OBJID) +
+ ASNObject(ASNEncUInt(StrToIntDef(SNMPMib.Value, 0)), SNMPMib.ValueType);
+ ASN1_OBJID:
+ s := ASNObject(MibToID(SNMPMib.OID), ASN1_OBJID) +
+ ASNObject(MibToID(SNMPMib.Value), SNMPMib.ValueType);
+ ASN1_IPADDR:
+ s := ASNObject(MibToID(SNMPMib.OID), ASN1_OBJID) +
+ ASNObject(IPToID(SNMPMib.Value), SNMPMib.ValueType);
+ ASN1_NULL:
+ s := ASNObject(MibToID(SNMPMib.OID), ASN1_OBJID) +
+ ASNObject('', ASN1_NULL);
+ else
+ s := ASNObject(MibToID(SNMPMib.OID), ASN1_OBJID) +
+ ASNObject(SNMPMib.Value, SNMPMib.ValueType);
+ end;
+ pdu := pdu + ASNObject(s, ASN1_SEQ);
+ end;
+ pdu := ASNObject(pdu, ASN1_SEQ);
+
+ if Self.FPDUType = PDUTrap then
+ pdu := ASNObject(MibToID(FOldTrapEnterprise), ASN1_OBJID) +
+ ASNObject(IPToID(FOldTrapHost), ASN1_IPADDR) +
+ ASNObject(ASNEncInt(FOldTrapGen), ASN1_INT) +
+ ASNObject(ASNEncInt(FOldTrapSpec), ASN1_INT) +
+ ASNObject(ASNEncUInt(FOldTrapTimeTicks), ASN1_TIMETICKS) +
+ pdu
+ else
+ pdu := ASNObject(ASNEncInt(Self.FID), ASN1_INT) +
+ ASNObject(ASNEncInt(Self.FErrorStatus), ASN1_INT) +
+ ASNObject(ASNEncInt(Self.FErrorIndex), ASN1_INT) +
+ pdu;
+ pdu := ASNObject(pdu, Self.FPDUType);
+
+ if FVersion = 3 then
+ begin
+ if FContextEngineID = '' then
+ FContextEngineID := FAuthEngineID;
+ //complete PDUv3...
+ pdu := ASNObject(FContextEngineID, ASN1_OCTSTR)
+ + ASNObject(FContextName, ASN1_OCTSTR)
+ + pdu;
+ //maybe encrypt pdu... in future
+ pdu := ASNObject(pdu, ASN1_SEQ);
+
+ //prepare flags
+ case FFlags of
+ AuthNoPriv:
+ x := 1;
+ AuthPriv:
+ x := 3;
+ else
+ x := 0;
+ end;
+ if FFlagReportable then
+ x := x or 4;
+ head := ASNObject(ASNEncInt(Self.FVersion), ASN1_INT);
+ s := ASNObject(ASNEncInt(FID), ASN1_INT)
+ + ASNObject(ASNEncInt(FMaxSize), ASN1_INT)
+ + ASNObject(AnsiChar(x), ASN1_OCTSTR)
+ //encode security model USM
+ + ASNObject(ASNEncInt(3), ASN1_INT);
+ head := head + ASNObject(s, ASN1_SEQ);
+
+ //compute engine time difference
+ x := TickDelta(FAuthEngineTimeStamp, GetTick) div 1000;
+
+ authbeg := ASNObject(FAuthEngineID, ASN1_OCTSTR)
+ + ASNObject(ASNEncInt(FAuthEngineBoots), ASN1_INT)
+ + ASNObject(ASNEncInt(FAuthEngineTime + x), ASN1_INT)
+ + ASNObject(FUserName, ASN1_OCTSTR);
+
+
+ case FFlags of
+ AuthNoPriv,
+ AuthPriv:
+ begin
+ s := authbeg + ASNObject(StringOfChar(#0, 12), ASN1_OCTSTR)
+ + ASNObject(FPrivKey, ASN1_OCTSTR);
+ s := ASNObject(s, ASN1_SEQ);
+ s := head + ASNObject(s, ASN1_OCTSTR);
+ s := ASNObject(s + pdu, ASN1_SEQ);
+ //in s is entire packet without auth info...
+ case FAuthMode of
+ AuthMD5:
+ begin
+ s := HMAC_MD5(s, Pass2Key(FPassword) + StringOfChar(#0, 48));
+ //strip to HMAC-MD5-96
+ delete(s, 13, 4);
+ end;
+ AuthSHA1:
+ begin
+ s := HMAC_SHA1(s, Pass2Key(FPassword) + StringOfChar(#0, 44));
+ //strip to HMAC-SHA-96
+ delete(s, 13, 8);
+ end;
+ else
+ s := '';
+ end;
+ FAuthKey := s;
+ end;
+ end;
+
+ auth := authbeg + ASNObject(FAuthKey, ASN1_OCTSTR)
+ + ASNObject(FPrivKey, ASN1_OCTSTR);
+ auth := ASNObject(auth, ASN1_SEQ);
+
+ head := head + ASNObject(auth, ASN1_OCTSTR);
+ Result := ASNObject(head + pdu, ASN1_SEQ);
+ end
+ else
+ begin
+ head := ASNObject(ASNEncInt(Self.FVersion), ASN1_INT) +
+ ASNObject(Self.FCommunity, ASN1_OCTSTR);
+ Result := ASNObject(head + pdu, ASN1_SEQ);
+ end;
+ inc(self.FID);
+end;
+
+procedure TSNMPRec.Clear;
+var
+ i: Integer;
+begin
+ FVersion := SNMP_V1;
+ FCommunity := 'public';
+ FUserName := '';
+ FPassword := '';
+ FPDUType := 0;
+ FErrorStatus := 0;
+ FErrorIndex := 0;
+ for i := 0 to FSNMPMibList.Count - 1 do
+ TSNMPMib(FSNMPMibList[i]).Free;
+ FSNMPMibList.Clear;
+ FOldTrapEnterprise := '';
+ FOldTrapHost := '';
+ FOldTrapGen := 0;
+ FOldTrapSpec := 0;
+ FOldTrapTimeTicks := 0;
+ FFlags := NoAuthNoPriv;
+ FFlagReportable := false;
+ FContextEngineID := '';
+ FContextName := '';
+ FAuthMode := AuthMD5;
+ FAuthEngineID := '';
+ FAuthEngineBoots := 0;
+ FAuthEngineTime := 0;
+ FAuthEngineTimeStamp := 0;
+ FAuthKey := '';
+ FPrivKey := '';
+end;
+
+procedure TSNMPRec.MIBAdd(const MIB, Value: AnsiString; ValueType: Integer);
+var
+ SNMPMib: TSNMPMib;
+begin
+ SNMPMib := TSNMPMib.Create;
+ SNMPMib.OID := MIB;
+ SNMPMib.Value := Value;
+ SNMPMib.ValueType := ValueType;
+ FSNMPMibList.Add(SNMPMib);
+end;
+
+procedure TSNMPRec.MIBDelete(Index: Integer);
+begin
+ if (Index >= 0) and (Index < MIBCount) then
+ begin
+ TSNMPMib(FSNMPMibList[Index]).Free;
+ FSNMPMibList.Delete(Index);
+ end;
+end;
+
+function TSNMPRec.MIBCount: integer;
+begin
+ Result := FSNMPMibList.Count;
+end;
+
+function TSNMPRec.MIBByIndex(Index: Integer): TSNMPMib;
+begin
+ Result := nil;
+ if (Index >= 0) and (Index < MIBCount) then
+ Result := TSNMPMib(FSNMPMibList[Index]);
+end;
+
+function TSNMPRec.MIBGet(const MIB: AnsiString): AnsiString;
+var
+ i: Integer;
+begin
+ Result := '';
+ for i := 0 to MIBCount - 1 do
+ begin
+ if ((TSNMPMib(FSNMPMibList[i])).OID = MIB) then
+ begin
+ Result := (TSNMPMib(FSNMPMibList[i])).Value;
+ Break;
+ end;
+ end;
+end;
+
+{==============================================================================}
+
+constructor TSNMPSend.Create;
+begin
+ inherited Create;
+ FQuery := TSNMPRec.Create;
+ FReply := TSNMPRec.Create;
+ FQuery.Clear;
+ FReply.Clear;
+ FSock := TUDPBlockSocket.Create;
+ FTimeout := 5000;
+ FTargetPort := cSnmpProtocol;
+ FHostIP := '';
+end;
+
+destructor TSNMPSend.Destroy;
+begin
+ FSock.Free;
+ FReply.Free;
+ FQuery.Free;
+ inherited Destroy;
+end;
+
+function TSNMPSend.InternalSendSnmp(const Value: TSNMPRec): Boolean;
+begin
+ FBuffer := Value.EncodeBuf;
+ FSock.SendString(FBuffer);
+ Result := FSock.LastError = 0;
+end;
+
+function TSNMPSend.InternalRecvSnmp(const Value: TSNMPRec): Boolean;
+begin
+ Result := False;
+ FReply.Clear;
+ FHostIP := cAnyHost;
+ FBuffer := FSock.RecvPacket(FTimeout);
+ if FSock.LastError = 0 then
+ begin
+ FHostIP := FSock.GetRemoteSinIP;
+ Result := Value.DecodeBuf(FBuffer);
+ end;
+end;
+
+function TSNMPSend.InternalSendRequest(const QValue, RValue: TSNMPRec): Boolean;
+begin
+ Result := False;
+ FSock.Bind(FIPInterface, cAnyPort);
+ FSock.Connect(FTargetHost, FTargetPort);
+ if InternalSendSnmp(QValue) then
+ Result := InternalRecvSnmp(RValue);
+end;
+
+function TSNMPSend.SendRequest: Boolean;
+var
+ sync: TV3Sync;
+begin
+ Result := False;
+ if FQuery.FVersion = 3 then
+ begin
+ sync := GetV3Sync;
+ FQuery.AuthEngineBoots := Sync.EngineBoots;
+ FQuery.AuthEngineTime := Sync.EngineTime;
+ FQuery.AuthEngineTimeStamp := Sync.EngineStamp;
+ FQuery.AuthEngineID := Sync.EngineID;
+ end;
+ FSock.Bind(FIPInterface, cAnyPort);
+ FSock.Connect(FTargetHost, FTargetPort);
+ if InternalSendSnmp(FQuery) then
+ Result := InternalRecvSnmp(FReply);
+end;
+
+function TSNMPSend.SendTrap: Boolean;
+begin
+ FSock.Bind(FIPInterface, cAnyPort);
+ FSock.Connect(FTargetHost, FTargetPort);
+ Result := InternalSendSnmp(FQuery);
+end;
+
+function TSNMPSend.RecvTrap: Boolean;
+begin
+ FSock.Bind(FIPInterface, FTargetPort);
+ Result := InternalRecvSnmp(FReply);
+end;
+
+function TSNMPSend.DoIt: Boolean;
+begin
+ Result := SendRequest;
+end;
+
+function TSNMPSend.GetV3EngineID: AnsiString;
+var
+ DisQuery: TSNMPRec;
+begin
+ Result := '';
+ DisQuery := TSNMPRec.Create;
+ try
+ DisQuery.Version := 3;
+ DisQuery.UserName := '';
+ DisQuery.FlagReportable := True;
+ DisQuery.PDUType := PDUGetRequest;
+ if InternalSendRequest(DisQuery, FReply) then
+ Result := FReply.FAuthEngineID;
+ finally
+ DisQuery.Free;
+ end;
+end;
+
+function TSNMPSend.GetV3Sync: TV3Sync;
+var
+ SyncQuery: TSNMPRec;
+begin
+ Result.EngineID := GetV3EngineID;
+ Result.EngineBoots := FReply.AuthEngineBoots;
+ Result.EngineTime := FReply.AuthEngineTime;
+ Result.EngineStamp := FReply.AuthEngineTimeStamp;
+ if Result.EngineTime = 0 then
+ begin
+ //still not have sync...
+ SyncQuery := TSNMPRec.Create;
+ try
+ SyncQuery.Version := 3;
+ SyncQuery.UserName := FQuery.UserName;
+ SyncQuery.Password := FQuery.Password;
+ SyncQuery.FlagReportable := True;
+ SyncQuery.Flags := FQuery.Flags;
+ SyncQuery.PDUType := PDUGetRequest;
+ SyncQuery.AuthEngineID := FReply.FAuthEngineID;
+ if InternalSendRequest(SyncQuery, FReply) then
+ begin
+ Result.EngineBoots := FReply.AuthEngineBoots;
+ Result.EngineTime := FReply.AuthEngineTime;
+ Result.EngineStamp := FReply.AuthEngineTimeStamp;
+ end;
+ finally
+ SyncQuery.Free;
+ end;
+ end;
+end;
+
+{==============================================================================}
+
+function SNMPGet(const OID, Community, SNMPHost: AnsiString; var Value: AnsiString): Boolean;
+var
+ SNMPSend: TSNMPSend;
+begin
+ SNMPSend := TSNMPSend.Create;
+ try
+ SNMPSend.Query.Clear;
+ SNMPSend.Query.Community := Community;
+ SNMPSend.Query.PDUType := PDUGetRequest;
+ SNMPSend.Query.MIBAdd(OID, '', ASN1_NULL);
+ SNMPSend.TargetHost := SNMPHost;
+ Result := SNMPSend.SendRequest;
+ Value := '';
+ if Result then
+ Value := SNMPSend.Reply.MIBGet(OID);
+ finally
+ SNMPSend.Free;
+ end;
+end;
+
+function SNMPSet(const OID, Community, SNMPHost, Value: AnsiString; ValueType: Integer): Boolean;
+var
+ SNMPSend: TSNMPSend;
+begin
+ SNMPSend := TSNMPSend.Create;
+ try
+ SNMPSend.Query.Clear;
+ SNMPSend.Query.Community := Community;
+ SNMPSend.Query.PDUType := PDUSetRequest;
+ SNMPSend.Query.MIBAdd(OID, Value, ValueType);
+ SNMPSend.TargetHost := SNMPHost;
+ Result := SNMPSend.Sendrequest = True;
+ finally
+ SNMPSend.Free;
+ end;
+end;
+
+function InternalGetNext(const SNMPSend: TSNMPSend; var OID: AnsiString;
+ const Community: AnsiString; var Value: AnsiString): Boolean;
+begin
+ SNMPSend.Query.Clear;
+ SNMPSend.Query.ID := SNMPSend.Query.ID + 1;
+ SNMPSend.Query.Community := Community;
+ SNMPSend.Query.PDUType := PDUGetNextRequest;
+ SNMPSend.Query.MIBAdd(OID, '', ASN1_NULL);
+ Result := SNMPSend.Sendrequest;
+ Value := '';
+ if Result then
+ if SNMPSend.Reply.SNMPMibList.Count > 0 then
+ begin
+ OID := TSNMPMib(SNMPSend.Reply.SNMPMibList[0]).OID;
+ Value := TSNMPMib(SNMPSend.Reply.SNMPMibList[0]).Value;
+ end;
+end;
+
+function SNMPGetNext(var OID: AnsiString; const Community, SNMPHost: AnsiString; var Value: AnsiString): Boolean;
+var
+ SNMPSend: TSNMPSend;
+begin
+ SNMPSend := TSNMPSend.Create;
+ try
+ SNMPSend.TargetHost := SNMPHost;
+ Result := InternalGetNext(SNMPSend, OID, Community, Value);
+ finally
+ SNMPSend.Free;
+ end;
+end;
+
+function SNMPGetTable(const BaseOID, Community, SNMPHost: AnsiString; const Value: TStrings): Boolean;
+var
+ OID: AnsiString;
+ s: AnsiString;
+ col,row: String;
+ x: integer;
+ SNMPSend: TSNMPSend;
+ RowList: TStringList;
+begin
+ Value.Clear;
+ SNMPSend := TSNMPSend.Create;
+ RowList := TStringList.Create;
+ try
+ SNMPSend.TargetHost := SNMPHost;
+ OID := BaseOID;
+ repeat
+ Result := InternalGetNext(SNMPSend, OID, Community, s);
+ if Pos(BaseOID, OID) <> 1 then
+ break;
+ row := separateright(oid, baseoid + '.');
+ col := fetch(row, '.');
+
+ if IsBinaryString(s) then
+ s := StrToHex(s);
+ x := RowList.indexOf(Row);
+ if x < 0 then
+ begin
+ x := RowList.add(Row);
+ Value.Add('');
+ end;
+ if (Value[x] <> '') then
+ Value[x] := Value[x] + ',';
+ Value[x] := Value[x] + AnsiQuotedStr(s, '"');
+ until not result;
+ finally
+ SNMPSend.Free;
+ RowList.Free;
+ end;
+end;
+
+function SNMPGetTableElement(const BaseOID, RowID, ColID, Community, SNMPHost: AnsiString; var Value: AnsiString): Boolean;
+var
+ s: AnsiString;
+begin
+ s := BaseOID + '.' + ColID + '.' + RowID;
+ Result := SnmpGet(s, Community, SNMPHost, Value);
+end;
+
+function SendTrap(const Dest, Source, Enterprise, Community: AnsiString;
+ Generic, Specific, Seconds: Integer; const MIBName, MIBValue: AnsiString;
+ MIBtype: Integer): Integer;
+var
+ SNMPSend: TSNMPSend;
+begin
+ SNMPSend := TSNMPSend.Create;
+ try
+ SNMPSend.TargetHost := Dest;
+ SNMPSend.TargetPort := cSnmpTrapProtocol;
+ SNMPSend.Query.Community := Community;
+ SNMPSend.Query.Version := SNMP_V1;
+ SNMPSend.Query.PDUType := PDUTrap;
+ SNMPSend.Query.OldTrapHost := Source;
+ SNMPSend.Query.OldTrapEnterprise := Enterprise;
+ SNMPSend.Query.OldTrapGen := Generic;
+ SNMPSend.Query.OldTrapSpec := Specific;
+ SNMPSend.Query.OldTrapTimeTicks := Seconds;
+ SNMPSend.Query.MIBAdd(MIBName, MIBValue, MIBType);
+ Result := Ord(SNMPSend.SendTrap);
+ finally
+ SNMPSend.Free;
+ end;
+end;
+
+function RecvTrap(var Dest, Source, Enterprise, Community: AnsiString;
+ var Generic, Specific, Seconds: Integer;
+ const MIBName, MIBValue: TStringList): Integer;
+var
+ SNMPSend: TSNMPSend;
+ i: Integer;
+begin
+ SNMPSend := TSNMPSend.Create;
+ try
+ Result := 0;
+ SNMPSend.TargetPort := cSnmpTrapProtocol;
+ if SNMPSend.RecvTrap then
+ begin
+ Result := 1;
+ Dest := SNMPSend.HostIP;
+ Community := SNMPSend.Reply.Community;
+ Source := SNMPSend.Reply.OldTrapHost;
+ Enterprise := SNMPSend.Reply.OldTrapEnterprise;
+ Generic := SNMPSend.Reply.OldTrapGen;
+ Specific := SNMPSend.Reply.OldTrapSpec;
+ Seconds := SNMPSend.Reply.OldTrapTimeTicks;
+ MIBName.Clear;
+ MIBValue.Clear;
+ for i := 0 to SNMPSend.Reply.SNMPMibList.Count - 1 do
+ begin
+ MIBName.Add(TSNMPMib(SNMPSend.Reply.SNMPMibList[i]).OID);
+ MIBValue.Add(TSNMPMib(SNMPSend.Reply.SNMPMibList[i]).Value);
+ end;
+ end;
+ finally
+ SNMPSend.Free;
+ end;
+end;
+
+
+end.
+
+
diff --git a/branches/script-component/Units/Synapse/sntpsend.pas b/branches/script-component/Units/Synapse/sntpsend.pas
new file mode 100644
index 0000000..c4958b2
--- /dev/null
+++ b/branches/script-component/Units/Synapse/sntpsend.pas
@@ -0,0 +1,373 @@
+{==============================================================================|
+| Project : Ararat Synapse | 003.000.002 |
+|==============================================================================|
+| Content: SNTP client |
+|==============================================================================|
+| Copyright (c)1999-2007, Lukas Gebauer |
+| All rights reserved. |
+| |
+| Redistribution and use in source and binary forms, with or without |
+| modification, are permitted provided that the following conditions are met: |
+| |
+| Redistributions of source code must retain the above copyright notice, this |
+| list of conditions and the following disclaimer. |
+| |
+| Redistributions in binary form must reproduce the above copyright notice, |
+| this list of conditions and the following disclaimer in the documentation |
+| and/or other materials provided with the distribution. |
+| |
+| Neither the name of Lukas Gebauer nor the names of its contributors may |
+| be used to endorse or promote products derived from this software without |
+| specific prior written permission. |
+| |
+| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
+| AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
+| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
+| ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR |
+| ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
+| DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
+| SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
+| CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
+| LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
+| OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
+| DAMAGE. |
+|==============================================================================|
+| The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).|
+| Portions created by Lukas Gebauer are Copyright (c)2000-2007. |
+| All Rights Reserved. |
+|==============================================================================|
+| Contributor(s): |
+| Patrick Chevalley |
+|==============================================================================|
+| History: see HISTORY.HTM from distribution package |
+| (Found at URL: http://www.ararat.cz/synapse/) |
+|==============================================================================}
+
+{:@abstract( NTP and SNTP client)
+
+Used RFC: RFC-1305, RFC-2030
+}
+
+{$IFDEF FPC}
+ {$MODE DELPHI}
+{$ENDIF}
+{$Q-}
+{$H+}
+
+unit sntpsend;
+
+interface
+
+uses
+ SysUtils,
+ synsock, blcksock, synautil;
+
+const
+ cNtpProtocol = '123';
+
+type
+
+ {:@abstract(Record containing the NTP packet.)}
+ TNtp = packed record
+ mode: Byte;
+ stratum: Byte;
+ poll: Byte;
+ Precision: Byte;
+ RootDelay: Longint;
+ RootDisperson: Longint;
+ RefID: Longint;
+ Ref1: Longint;
+ Ref2: Longint;
+ Org1: Longint;
+ Org2: Longint;
+ Rcv1: Longint;
+ Rcv2: Longint;
+ Xmit1: Longint;
+ Xmit2: Longint;
+ end;
+
+ {:@abstract(Implementation of NTP and SNTP client protocol),
+ include time synchronisation. It can send NTP or SNTP time queries, or it
+ can receive NTP broadcasts too.
+
+ Note: Are you missing properties for specify server address and port? Look to
+ parent @link(TSynaClient) too!}
+ TSNTPSend = class(TSynaClient)
+ private
+ FNTPReply: TNtp;
+ FNTPTime: TDateTime;
+ FNTPOffset: double;
+ FNTPDelay: double;
+ FMaxSyncDiff: double;
+ FSyncTime: Boolean;
+ FSock: TUDPBlockSocket;
+ FBuffer: string;
+ FLi, FVn, Fmode : byte;
+ function StrToNTP(const Value: AnsiString): TNtp;
+ function NTPtoStr(const Value: Tntp): AnsiString;
+ procedure ClearNTP(var Value: Tntp);
+ public
+ constructor Create;
+ destructor Destroy; override;
+
+ {:Decode 128 bit timestamp used in NTP packet to TDateTime type.}
+ function DecodeTs(Nsec, Nfrac: Longint): TDateTime;
+
+ {:Decode TDateTime type to 128 bit timestamp used in NTP packet.}
+ procedure EncodeTs(dt: TDateTime; var Nsec, Nfrac: Longint);
+
+ {:Send request to @link(TSynaClient.TargetHost) and wait for reply. If all
+ is OK, then result is @true and @link(NTPReply) and @link(NTPTime) are
+ valid.}
+ function GetSNTP: Boolean;
+
+ {:Send request to @link(TSynaClient.TargetHost) and wait for reply. If all
+ is OK, then result is @true and @link(NTPReply) and @link(NTPTime) are
+ valid. Result time is after all needed corrections.}
+ function GetNTP: Boolean;
+
+ {:Wait for broadcast NTP packet. If all OK, result is @true and
+ @link(NTPReply) and @link(NTPTime) are valid.}
+ function GetBroadcastNTP: Boolean;
+
+ {:Holds last received NTP packet.}
+ property NTPReply: TNtp read FNTPReply;
+ published
+ {:Date and time of remote NTP or SNTP server. (UTC time!!!)}
+ property NTPTime: TDateTime read FNTPTime;
+
+ {:Offset between your computer and remote NTP or SNTP server.}
+ property NTPOffset: Double read FNTPOffset;
+
+ {:Delay between your computer and remote NTP or SNTP server.}
+ property NTPDelay: Double read FNTPDelay;
+
+ {:Define allowed maximum difference between your time and remote time for
+ synchronising time. If difference is bigger, your system time is not
+ changed!}
+ property MaxSyncDiff: double read FMaxSyncDiff write FMaxSyncDiff;
+
+ {:If @true, after successfull getting time is local computer clock
+ synchronised to given time.
+ For synchronising time you must have proper rights! (Usually Administrator)}
+ property SyncTime: Boolean read FSyncTime write FSyncTime;
+
+ {:Socket object used for TCP/IP operation. Good for seting OnStatus hook, etc.}
+ property Sock: TUDPBlockSocket read FSock;
+ end;
+
+implementation
+
+constructor TSNTPSend.Create;
+begin
+ inherited Create;
+ FSock := TUDPBlockSocket.Create;
+ FTimeout := 5000;
+ FTargetPort := cNtpProtocol;
+ FMaxSyncDiff := 3600;
+ FSyncTime := False;
+end;
+
+destructor TSNTPSend.Destroy;
+begin
+ FSock.Free;
+ inherited Destroy;
+end;
+
+function TSNTPSend.StrToNTP(const Value: AnsiString): TNtp;
+begin
+ if length(FBuffer) >= SizeOf(Result) then
+ begin
+ Result.mode := ord(Value[1]);
+ Result.stratum := ord(Value[2]);
+ Result.poll := ord(Value[3]);
+ Result.Precision := ord(Value[4]);
+ Result.RootDelay := DecodeLongInt(value, 5);
+ Result.RootDisperson := DecodeLongInt(value, 9);
+ Result.RefID := DecodeLongInt(value, 13);
+ Result.Ref1 := DecodeLongInt(value, 17);
+ Result.Ref2 := DecodeLongInt(value, 21);
+ Result.Org1 := DecodeLongInt(value, 25);
+ Result.Org2 := DecodeLongInt(value, 29);
+ Result.Rcv1 := DecodeLongInt(value, 33);
+ Result.Rcv2 := DecodeLongInt(value, 37);
+ Result.Xmit1 := DecodeLongInt(value, 41);
+ Result.Xmit2 := DecodeLongInt(value, 45);
+ end;
+
+end;
+
+function TSNTPSend.NTPtoStr(const Value: Tntp): AnsiString;
+begin
+ SetLength(Result, 4);
+ Result[1] := AnsiChar(Value.mode);
+ Result[2] := AnsiChar(Value.stratum);
+ Result[3] := AnsiChar(Value.poll);
+ Result[4] := AnsiChar(Value.precision);
+ Result := Result + CodeLongInt(Value.RootDelay);
+ Result := Result + CodeLongInt(Value.RootDisperson);
+ Result := Result + CodeLongInt(Value.RefID);
+ Result := Result + CodeLongInt(Value.Ref1);
+ Result := Result + CodeLongInt(Value.Ref2);
+ Result := Result + CodeLongInt(Value.Org1);
+ Result := Result + CodeLongInt(Value.Org2);
+ Result := Result + CodeLongInt(Value.Rcv1);
+ Result := Result + CodeLongInt(Value.Rcv2);
+ Result := Result + CodeLongInt(Value.Xmit1);
+ Result := Result + CodeLongInt(Value.Xmit2);
+end;
+
+procedure TSNTPSend.ClearNTP(var Value: Tntp);
+begin
+ Value.mode := 0;
+ Value.stratum := 0;
+ Value.poll := 0;
+ Value.Precision := 0;
+ Value.RootDelay := 0;
+ Value.RootDisperson := 0;
+ Value.RefID := 0;
+ Value.Ref1 := 0;
+ Value.Ref2 := 0;
+ Value.Org1 := 0;
+ Value.Org2 := 0;
+ Value.Rcv1 := 0;
+ Value.Rcv2 := 0;
+ Value.Xmit1 := 0;
+ Value.Xmit2 := 0;
+end;
+
+function TSNTPSend.DecodeTs(Nsec, Nfrac: Longint): TDateTime;
+const
+ maxi = 4294967295.0;
+var
+ d, d1: Double;
+begin
+ d := Nsec;
+ if d < 0 then
+ d := maxi + d + 1;
+ d1 := Nfrac;
+ if d1 < 0 then
+ d1 := maxi + d1 + 1;
+ d1 := d1 / maxi;
+ d1 := Trunc(d1 * 10000) / 10000;
+ Result := (d + d1) / 86400;
+ Result := Result + 2;
+end;
+
+procedure TSNTPSend.EncodeTs(dt: TDateTime; var Nsec, Nfrac: Longint);
+const
+ maxi = 4294967295.0;
+ maxilongint = 2147483647;
+var
+ d, d1: Double;
+begin
+ d := (dt - 2) * 86400;
+ d1 := frac(d);
+ if d > maxilongint then
+ d := d - maxi - 1;
+ d := trunc(d);
+ d1 := Trunc(d1 * 10000) / 10000;
+ d1 := d1 * maxi;
+ if d1 > maxilongint then
+ d1 := d1 - maxi - 1;
+ Nsec:=trunc(d);
+ Nfrac:=trunc(d1);
+end;
+
+function TSNTPSend.GetBroadcastNTP: Boolean;
+var
+ x: Integer;
+begin
+ Result := False;
+ FSock.Bind(FIPInterface, FTargetPort);
+ FBuffer := FSock.RecvPacket(FTimeout);
+ if FSock.LastError = 0 then
+ begin
+ x := Length(FBuffer);
+ if (FTargetHost = '0.0.0.0') or (FSock.GetRemoteSinIP = FSock.ResolveName(FTargetHost)) then
+ if x >= SizeOf(NTPReply) then
+ begin
+ FNTPReply := StrToNTP(FBuffer);
+ FNTPTime := DecodeTs(NTPReply.Xmit1, NTPReply.Xmit2);
+ if FSyncTime and ((abs(FNTPTime - GetUTTime) * 86400) <= FMaxSyncDiff) then
+ SetUTTime(FNTPTime);
+ Result := True;
+ end;
+ end;
+end;
+
+function TSNTPSend.GetSNTP: Boolean;
+var
+ q: TNtp;
+ x: Integer;
+begin
+ Result := False;
+ FSock.CloseSocket;
+ FSock.Bind(FIPInterface, cAnyPort);
+ FSock.Connect(FTargetHost, FTargetPort);
+ ClearNtp(q);
+ q.mode := $1B;
+ FBuffer := NTPtoStr(q);
+ FSock.SendString(FBuffer);
+ FBuffer := FSock.RecvPacket(FTimeout);
+ if FSock.LastError = 0 then
+ begin
+ x := Length(FBuffer);
+ if x >= SizeOf(NTPReply) then
+ begin
+ FNTPReply := StrToNTP(FBuffer);
+ FNTPTime := DecodeTs(NTPReply.Xmit1, NTPReply.Xmit2);
+ if FSyncTime and ((abs(FNTPTime - GetUTTime) * 86400) <= FMaxSyncDiff) then
+ SetUTTime(FNTPTime);
+ Result := True;
+ end;
+ end;
+end;
+
+function TSNTPSend.GetNTP: Boolean;
+var
+ q: TNtp;
+ x: Integer;
+ t1, t2, t3, t4 : TDateTime;
+begin
+ Result := False;
+ FSock.CloseSocket;
+ FSock.Bind(FIPInterface, cAnyPort);
+ FSock.Connect(FTargetHost, FTargetPort);
+ ClearNtp(q);
+ q.mode := $1B;
+ t1 := GetUTTime;
+ EncodeTs(t1, q.org1, q.org2);
+ FBuffer := NTPtoStr(q);
+ FSock.SendString(FBuffer);
+ FBuffer := FSock.RecvPacket(FTimeout);
+ if FSock.LastError = 0 then
+ begin
+ x := Length(FBuffer);
+ t4 := GetUTTime;
+ if x >= SizeOf(NTPReply) then
+ begin
+ FNTPReply := StrToNTP(FBuffer);
+ FLi := (NTPReply.mode and $C0) shr 6;
+ FVn := (NTPReply.mode and $38) shr 3;
+ Fmode := NTPReply.mode and $07;
+ if (Fli < 3) and (Fmode = 4) and
+ (NTPReply.stratum >= 1) and (NTPReply.stratum <= 15) and
+ (NTPReply.Rcv1 <> 0) and (NTPReply.Xmit1 <> 0)
+ then begin
+ t2 := DecodeTs(NTPReply.Rcv1, NTPReply.Rcv2);
+ t3 := DecodeTs(NTPReply.Xmit1, NTPReply.Xmit2);
+ FNTPDelay := (T4 - T1) - (T2 - T3);
+ FNTPTime := t3 + FNTPDelay / 2;
+ FNTPOffset := (((T2 - T1) + (T3 - T4)) / 2) * 86400;
+ FNTPDelay := FNTPDelay * 86400;
+ if FSyncTime and ((abs(FNTPTime - t1) * 86400) <= FMaxSyncDiff) then
+ SetUTTime(FNTPTime);
+ Result := True;
+ end
+ else result:=false;
+ end;
+ end;
+end;
+
+end.
diff --git a/branches/script-component/Units/Synapse/ssdotnet.pas b/branches/script-component/Units/Synapse/ssdotnet.pas
new file mode 100644
index 0000000..8a54cd8
--- /dev/null
+++ b/branches/script-component/Units/Synapse/ssdotnet.pas
@@ -0,0 +1,1099 @@
+{==============================================================================|
+| Project : Ararat Synapse | 001.000.002 |
+|==============================================================================|
+| Content: Socket Independent Platform Layer - .NET definition include |
+|==============================================================================|
+| Copyright (c)2004, Lukas Gebauer |
+| All rights reserved. |
+| |
+| Redistribution and use in source and binary forms, with or without |
+| modification, are permitted provided that the following conditions are met: |
+| |
+| Redistributions of source code must retain the above copyright notice, this |
+| list of conditions and the following disclaimer. |
+| |
+| Redistributions in binary form must reproduce the above copyright notice, |
+| this list of conditions and the following disclaimer in the documentation |
+| and/or other materials provided with the distribution. |
+| |
+| Neither the name of Lukas Gebauer nor the names of its contributors may |
+| be used to endorse or promote products derived from this software without |
+| specific prior written permission. |
+| |
+| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
+| AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
+| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
+| ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR |
+| ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
+| DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
+| SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
+| CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
+| LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
+| OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
+| DAMAGE. |
+|==============================================================================|
+| The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).|
+| Portions created by Lukas Gebauer are Copyright (c)2004. |
+| All Rights Reserved. |
+|==============================================================================|
+| Contributor(s): |
+|==============================================================================|
+| History: see HISTORY.HTM from distribution package |
+| (Found at URL: http://www.ararat.cz/synapse/) |
+|==============================================================================}
+
+{:@exclude}
+
+{$IFDEF CIL}
+
+interface
+
+uses
+ SyncObjs, SysUtils, Classes,
+ System.Net,
+ System.Net.Sockets;
+
+const
+ DLLStackName = '';
+ WinsockLevel = $0202;
+
+function InitSocketInterface(stack: string): Boolean;
+function DestroySocketInterface: Boolean;
+
+type
+ u_char = Char;
+ u_short = Word;
+ u_int = Integer;
+ u_long = Longint;
+ pu_long = ^u_long;
+ pu_short = ^u_short;
+ PSockAddr = IPEndPoint;
+ DWORD = integer;
+ ULong = cardinal;
+ TMemory = Array of byte;
+ TLinger = LingerOption;
+ TSocket = socket;
+ TAddrFamily = AddressFamily;
+
+const
+ WSADESCRIPTION_LEN = 256;
+ WSASYS_STATUS_LEN = 128;
+type
+ PWSAData = ^TWSAData;
+ TWSAData = packed record
+ wVersion: Word;
+ wHighVersion: Word;
+ szDescription: array[0..WSADESCRIPTION_LEN] of Char;
+ szSystemStatus: array[0..WSASYS_STATUS_LEN] of Char;
+ iMaxSockets: Word;
+ iMaxUdpDg: Word;
+// lpVendorInfo: PChar;
+ end;
+
+const
+ MSG_NOSIGNAL = 0;
+ INVALID_SOCKET = nil;
+ AF_UNSPEC = AddressFamily.Unspecified;
+ AF_INET = AddressFamily.InterNetwork;
+ AF_INET6 = AddressFamily.InterNetworkV6;
+ SOCKET_ERROR = integer(-1);
+
+ FIONREAD = integer($4004667f);
+ FIONBIO = integer($8004667e);
+ FIOASYNC = integer($8004667d);
+
+ SOMAXCONN = integer($7fffffff);
+
+ IPPROTO_IP = ProtocolType.IP;
+ IPPROTO_ICMP = ProtocolType.Icmp;
+ IPPROTO_IGMP = ProtocolType.Igmp;
+ IPPROTO_TCP = ProtocolType.Tcp;
+ IPPROTO_UDP = ProtocolType.Udp;
+ IPPROTO_RAW = ProtocolType.Raw;
+ IPPROTO_IPV6 = ProtocolType.IPV6;
+//
+ IPPROTO_ICMPV6 = ProtocolType.Icmp; //??
+
+ SOCK_STREAM = SocketType.Stream;
+ SOCK_DGRAM = SocketType.Dgram;
+ SOCK_RAW = SocketType.Raw;
+ SOCK_RDM = SocketType.Rdm;
+ SOCK_SEQPACKET = SocketType.Seqpacket;
+
+ SOL_SOCKET = SocketOptionLevel.Socket;
+ SOL_IP = SocketOptionLevel.Ip;
+
+
+ IP_OPTIONS = SocketOptionName.IPOptions;
+ IP_HDRINCL = SocketOptionName.HeaderIncluded;
+ IP_TOS = SocketOptionName.TypeOfService; { set/get IP Type Of Service }
+ IP_TTL = SocketOptionName.IpTimeToLive; { set/get IP Time To Live }
+ IP_MULTICAST_IF = SocketOptionName.MulticastInterface; { set/get IP multicast interface }
+ IP_MULTICAST_TTL = SocketOptionName.MulticastTimeToLive; { set/get IP multicast timetolive }
+ IP_MULTICAST_LOOP = SocketOptionName.MulticastLoopback; { set/get IP multicast loopback }
+ IP_ADD_MEMBERSHIP = SocketOptionName.AddMembership; { add an IP group membership }
+ IP_DROP_MEMBERSHIP = SocketOptionName.DropMembership; { drop an IP group membership }
+ IP_DONTFRAGMENT = SocketOptionName.DontFragment; { set/get IP Don't Fragment flag }
+
+ IPV6_UNICAST_HOPS = 8; // TTL
+ IPV6_MULTICAST_IF = 9; // set/get IP multicast i/f
+ IPV6_MULTICAST_HOPS = 10; // set/get IP multicast ttl
+ IPV6_MULTICAST_LOOP = 11; // set/get IP multicast loopback
+ IPV6_JOIN_GROUP = 12; // add an IP group membership
+ IPV6_LEAVE_GROUP = 13; // drop an IP group membership
+
+ SO_DEBUG = SocketOptionName.Debug; { turn on debugging info recording }
+ SO_ACCEPTCONN = SocketOptionName.AcceptConnection; { socket has had listen() }
+ SO_REUSEADDR = SocketOptionName.ReuseAddress; { allow local address reuse }
+ SO_KEEPALIVE = SocketOptionName.KeepAlive; { keep connections alive }
+ SO_DONTROUTE = SocketOptionName.DontRoute; { just use interface addresses }
+ SO_BROADCAST = SocketOptionName.Broadcast; { permit sending of broadcast msgs }
+ SO_USELOOPBACK = SocketOptionName.UseLoopback; { bypass hardware when possible }
+ SO_LINGER = SocketOptionName.Linger; { linger on close if data present }
+ SO_OOBINLINE = SocketOptionName.OutOfBandInline; { leave received OOB data in line }
+ SO_DONTLINGER = SocketOptionName.DontLinger;
+{ Additional options. }
+ SO_SNDBUF = SocketOptionName.SendBuffer; { send buffer size }
+ SO_RCVBUF = SocketOptionName.ReceiveBuffer; { receive buffer size }
+ SO_SNDLOWAT = SocketOptionName.SendLowWater; { send low-water mark }
+ SO_RCVLOWAT = SocketOptionName.ReceiveLowWater; { receive low-water mark }
+ SO_SNDTIMEO = SocketOptionName.SendTimeout; { send timeout }
+ SO_RCVTIMEO = SocketOptionName.ReceiveTimeout; { receive timeout }
+ SO_ERROR = SocketOptionName.Error; { get error status and clear }
+ SO_TYPE = SocketOptionName.Type; { get socket type }
+
+{ WinSock 2 extension -- new options }
+// SO_GROUP_ID = $2001; { ID of a socket group}
+// SO_GROUP_PRIORITY = $2002; { the relative priority within a group}
+// SO_MAX_MSG_SIZE = $2003; { maximum message size }
+// SO_PROTOCOL_INFOA = $2004; { WSAPROTOCOL_INFOA structure }
+// SO_PROTOCOL_INFOW = $2005; { WSAPROTOCOL_INFOW structure }
+// SO_PROTOCOL_INFO = SO_PROTOCOL_INFOA;
+// PVD_CONFIG = $3001; {configuration info for service provider }
+{ Option for opening sockets for synchronous access. }
+// SO_OPENTYPE = $7008;
+// SO_SYNCHRONOUS_ALERT = $10;
+// SO_SYNCHRONOUS_NONALERT = $20;
+{ Other NT-specific options. }
+// SO_MAXDG = $7009;
+// SO_MAXPATHDG = $700A;
+// SO_UPDATE_ACCEPT_CONTEXT = $700B;
+// SO_CONNECT_TIME = $700C;
+
+
+ { All Windows Sockets error constants are biased by WSABASEERR from the "normal" }
+ WSABASEERR = 10000;
+
+{ Windows Sockets definitions of regular Microsoft C error constants }
+
+ WSAEINTR = (WSABASEERR+4);
+ WSAEBADF = (WSABASEERR+9);
+ WSAEACCES = (WSABASEERR+13);
+ WSAEFAULT = (WSABASEERR+14);
+ WSAEINVAL = (WSABASEERR+22);
+ WSAEMFILE = (WSABASEERR+24);
+
+{ Windows Sockets definitions of regular Berkeley error constants }
+
+ WSAEWOULDBLOCK = (WSABASEERR+35);
+ WSAEINPROGRESS = (WSABASEERR+36);
+ WSAEALREADY = (WSABASEERR+37);
+ WSAENOTSOCK = (WSABASEERR+38);
+ WSAEDESTADDRREQ = (WSABASEERR+39);
+ WSAEMSGSIZE = (WSABASEERR+40);
+ WSAEPROTOTYPE = (WSABASEERR+41);
+ WSAENOPROTOOPT = (WSABASEERR+42);
+ WSAEPROTONOSUPPORT = (WSABASEERR+43);
+ WSAESOCKTNOSUPPORT = (WSABASEERR+44);
+ WSAEOPNOTSUPP = (WSABASEERR+45);
+ WSAEPFNOSUPPORT = (WSABASEERR+46);
+ WSAEAFNOSUPPORT = (WSABASEERR+47);
+ WSAEADDRINUSE = (WSABASEERR+48);
+ WSAEADDRNOTAVAIL = (WSABASEERR+49);
+ WSAENETDOWN = (WSABASEERR+50);
+ WSAENETUNREACH = (WSABASEERR+51);
+ WSAENETRESET = (WSABASEERR+52);
+ WSAECONNABORTED = (WSABASEERR+53);
+ WSAECONNRESET = (WSABASEERR+54);
+ WSAENOBUFS = (WSABASEERR+55);
+ WSAEISCONN = (WSABASEERR+56);
+ WSAENOTCONN = (WSABASEERR+57);
+ WSAESHUTDOWN = (WSABASEERR+58);
+ WSAETOOMANYREFS = (WSABASEERR+59);
+ WSAETIMEDOUT = (WSABASEERR+60);
+ WSAECONNREFUSED = (WSABASEERR+61);
+ WSAELOOP = (WSABASEERR+62);
+ WSAENAMETOOLONG = (WSABASEERR+63);
+ WSAEHOSTDOWN = (WSABASEERR+64);
+ WSAEHOSTUNREACH = (WSABASEERR+65);
+ WSAENOTEMPTY = (WSABASEERR+66);
+ WSAEPROCLIM = (WSABASEERR+67);
+ WSAEUSERS = (WSABASEERR+68);
+ WSAEDQUOT = (WSABASEERR+69);
+ WSAESTALE = (WSABASEERR+70);
+ WSAEREMOTE = (WSABASEERR+71);
+
+{ Extended Windows Sockets error constant definitions }
+
+ WSASYSNOTREADY = (WSABASEERR+91);
+ WSAVERNOTSUPPORTED = (WSABASEERR+92);
+ WSANOTINITIALISED = (WSABASEERR+93);
+ WSAEDISCON = (WSABASEERR+101);
+ WSAENOMORE = (WSABASEERR+102);
+ WSAECANCELLED = (WSABASEERR+103);
+ WSAEEINVALIDPROCTABLE = (WSABASEERR+104);
+ WSAEINVALIDPROVIDER = (WSABASEERR+105);
+ WSAEPROVIDERFAILEDINIT = (WSABASEERR+106);
+ WSASYSCALLFAILURE = (WSABASEERR+107);
+ WSASERVICE_NOT_FOUND = (WSABASEERR+108);
+ WSATYPE_NOT_FOUND = (WSABASEERR+109);
+ WSA_E_NO_MORE = (WSABASEERR+110);
+ WSA_E_CANCELLED = (WSABASEERR+111);
+ WSAEREFUSED = (WSABASEERR+112);
+
+{ Error return codes from gethostbyname() and gethostbyaddr()
+ (when using the resolver). Note that these errors are
+ retrieved via WSAGetLastError() and must therefore follow
+ the rules for avoiding clashes with error numbers from
+ specific implementations or language run-time systems.
+ For this reason the codes are based at WSABASEERR+1001.
+ Note also that [WSA]NO_ADDRESS is defined only for
+ compatibility purposes. }
+
+{ Authoritative Answer: Host not found }
+ WSAHOST_NOT_FOUND = (WSABASEERR+1001);
+ HOST_NOT_FOUND = WSAHOST_NOT_FOUND;
+{ Non-Authoritative: Host not found, or SERVERFAIL }
+ WSATRY_AGAIN = (WSABASEERR+1002);
+ TRY_AGAIN = WSATRY_AGAIN;
+{ Non recoverable errors, FORMERR, REFUSED, NOTIMP }
+ WSANO_RECOVERY = (WSABASEERR+1003);
+ NO_RECOVERY = WSANO_RECOVERY;
+{ Valid name, no data record of requested type }
+ WSANO_DATA = (WSABASEERR+1004);
+ NO_DATA = WSANO_DATA;
+{ no address, look for MX record }
+ WSANO_ADDRESS = WSANO_DATA;
+ NO_ADDRESS = WSANO_ADDRESS;
+
+ EWOULDBLOCK = WSAEWOULDBLOCK;
+ EINPROGRESS = WSAEINPROGRESS;
+ EALREADY = WSAEALREADY;
+ ENOTSOCK = WSAENOTSOCK;
+ EDESTADDRREQ = WSAEDESTADDRREQ;
+ EMSGSIZE = WSAEMSGSIZE;
+ EPROTOTYPE = WSAEPROTOTYPE;
+ ENOPROTOOPT = WSAENOPROTOOPT;
+ EPROTONOSUPPORT = WSAEPROTONOSUPPORT;
+ ESOCKTNOSUPPORT = WSAESOCKTNOSUPPORT;
+ EOPNOTSUPP = WSAEOPNOTSUPP;
+ EPFNOSUPPORT = WSAEPFNOSUPPORT;
+ EAFNOSUPPORT = WSAEAFNOSUPPORT;
+ EADDRINUSE = WSAEADDRINUSE;
+ EADDRNOTAVAIL = WSAEADDRNOTAVAIL;
+ ENETDOWN = WSAENETDOWN;
+ ENETUNREACH = WSAENETUNREACH;
+ ENETRESET = WSAENETRESET;
+ ECONNABORTED = WSAECONNABORTED;
+ ECONNRESET = WSAECONNRESET;
+ ENOBUFS = WSAENOBUFS;
+ EISCONN = WSAEISCONN;
+ ENOTCONN = WSAENOTCONN;
+ ESHUTDOWN = WSAESHUTDOWN;
+ ETOOMANYREFS = WSAETOOMANYREFS;
+ ETIMEDOUT = WSAETIMEDOUT;
+ ECONNREFUSED = WSAECONNREFUSED;
+ ELOOP = WSAELOOP;
+ ENAMETOOLONG = WSAENAMETOOLONG;
+ EHOSTDOWN = WSAEHOSTDOWN;
+ EHOSTUNREACH = WSAEHOSTUNREACH;
+ ENOTEMPTY = WSAENOTEMPTY;
+ EPROCLIM = WSAEPROCLIM;
+ EUSERS = WSAEUSERS;
+ EDQUOT = WSAEDQUOT;
+ ESTALE = WSAESTALE;
+ EREMOTE = WSAEREMOTE;
+
+
+type
+ TVarSin = IPEndpoint;
+
+{ function IN6_IS_ADDR_UNSPECIFIED(const a: PInAddr6): boolean;
+ function IN6_IS_ADDR_LOOPBACK(const a: PInAddr6): boolean;
+ function IN6_IS_ADDR_LINKLOCAL(const a: PInAddr6): boolean;
+ function IN6_IS_ADDR_SITELOCAL(const a: PInAddr6): boolean;
+ function IN6_IS_ADDR_MULTICAST(const a: PInAddr6): boolean;
+ function IN6_ADDR_EQUAL(const a: PInAddr6; const b: PInAddr6):boolean;
+ procedure SET_IN6_IF_ADDR_ANY (const a: PInAddr6);
+ procedure SET_LOOPBACK_ADDR6 (const a: PInAddr6);
+var
+ in6addr_any, in6addr_loopback : TInAddr6;
+}
+
+{procedure FD_CLR(Socket: TSocket; var FDSet: TFDSet);
+function FD_ISSET(Socket: TSocket; var FDSet: TFDSet): Boolean;
+procedure FD_SET(Socket: TSocket; var FDSet: TFDSet);
+procedure FD_ZERO(var FDSet: TFDSet);
+}
+{=============================================================================}
+
+ function WSAStartup(wVersionRequired: Word; var WSData: TWSAData): Integer;
+ function WSACleanup: Integer;
+ function WSAGetLastError: Integer;
+ function WSAGetLastErrorDesc: String;
+ function GetHostName: string;
+ function Shutdown(s: TSocket; how: Integer): Integer;
+// function SetSockOpt(s: TSocket; level, optname: Integer; optval: PChar;
+// optlen: Integer): Integer;
+ function SetSockOpt(s: TSocket; level, optname: Integer; optval: TMemory;
+ optlen: Integer): Integer;
+ function SetSockOptObj(s: TSocket; level, optname: Integer; optval: TObject): Integer;
+ function GetSockOpt(s: TSocket; level, optname: Integer; optval: TMemory;
+ var optlen: Integer): Integer;
+// function SendTo(s: TSocket; const Buf; len, flags: Integer; addrto: PSockAddr;
+// tolen: Integer): Integer;
+/// function SendTo(s: TSocket; const Buf; len, flags: Integer; addrto: TVarSin): Integer;
+/// function Send(s: TSocket; const Buf; len, flags: Integer): Integer;
+/// function Recv(s: TSocket; var Buf; len, flags: Integer): Integer;
+// function RecvFrom(s: TSocket; var Buf; len, flags: Integer; from: PSockAddr;
+// var fromlen: Integer): Integer;
+/// function RecvFrom(s: TSocket; var Buf; len, flags: Integer; from: TVarSin): Integer;
+function Send(s: TSocket; Buf: TMemory; len, flags: Integer): Integer;
+function Recv(s: TSocket; Buf: TMemory; len, flags: Integer): Integer;
+function SendTo(s: TSocket; Buf: TMemory; len, flags: Integer; addrto: TVarSin): Integer;
+function RecvFrom(s: TSocket; Buf: TMemory; len, flags: Integer; var from: TVarSin): Integer;
+ function ntohs(netshort: u_short): u_short;
+ function ntohl(netlong: u_long): u_long;
+ function Listen(s: TSocket; backlog: Integer): Integer;
+ function IoctlSocket(s: TSocket; cmd: DWORD; var arg: integer): Integer;
+ function htons(hostshort: u_short): u_short;
+ function htonl(hostlong: u_long): u_long;
+// function GetSockName(s: TSocket; name: PSockAddr; var namelen: Integer): Integer;
+ function GetSockName(s: TSocket; var name: TVarSin): Integer;
+// function GetPeerName(s: TSocket; name: PSockAddr; var namelen: Integer): Integer;
+ function GetPeerName(s: TSocket; var name: TVarSin): Integer;
+// function Connect(s: TSocket; name: PSockAddr; namelen: Integer): Integer;
+ function Connect(s: TSocket; const name: TVarSin): Integer;
+ function CloseSocket(s: TSocket): Integer;
+// function Bind(s: TSocket; addr: PSockAddr; namelen: Integer): Integer;
+ function Bind(s: TSocket; const addr: TVarSin): Integer;
+// function Accept(s: TSocket; addr: PSockAddr; var addrlen: Integer): TSocket;
+ function Accept(s: TSocket; var addr: TVarSin): TSocket;
+ function Socket(af, Struc, Protocol: Integer): TSocket;
+// Select = function(nfds: Integer; readfds, writefds, exceptfds: PFDSet;
+// timeout: PTimeVal): Longint;
+// {$IFDEF LINUX}cdecl{$ELSE}stdcall{$ENDIF};
+
+// TWSAIoctl = function (s: TSocket; dwIoControlCode: DWORD; lpvInBuffer: Pointer;
+// cbInBuffer: DWORD; lpvOutBuffer: Pointer; cbOutBuffer: DWORD;
+// lpcbBytesReturned: PDWORD; lpOverlapped: Pointer;
+// lpCompletionRoutine: pointer): u_int;
+// stdcall;
+
+ function GetPortService(value: string): integer;
+
+function IsNewApi(Family: TAddrFamily): Boolean;
+function SetVarSin(var Sin: TVarSin; IP, Port: string; Family: TAddrFamily; SockProtocol, SockType: integer; PreferIP4: Boolean): integer;
+function GetSinIP(Sin: TVarSin): string;
+function GetSinPort(Sin: TVarSin): Integer;
+procedure ResolveNameToIP(Name: string; Family: TAddrFamily; SockProtocol, SockType: integer; const IPList: TStrings);
+function ResolveIPToName(IP: string; Family: TAddrFamily; SockProtocol, SockType: integer): string;
+function ResolvePort(Port: string; Family: TAddrFamily; SockProtocol, SockType: integer): Word;
+
+var
+ SynSockCS: SyncObjs.TCriticalSection;
+ SockEnhancedApi: Boolean;
+ SockWship6Api: Boolean;
+
+{==============================================================================}
+implementation
+
+threadvar
+ WSALastError: integer;
+ WSALastErrorDesc: string;
+
+var
+ services: Array [0..139, 0..1] of string =
+ (
+ ('echo', '7'),
+ ('discard', '9'),
+ ('sink', '9'),
+ ('null', '9'),
+ ('systat', '11'),
+ ('users', '11'),
+ ('daytime', '13'),
+ ('qotd', '17'),
+ ('quote', '17'),
+ ('chargen', '19'),
+ ('ttytst', '19'),
+ ('source', '19'),
+ ('ftp-data', '20'),
+ ('ftp', '21'),
+ ('telnet', '23'),
+ ('smtp', '25'),
+ ('mail', '25'),
+ ('time', '37'),
+ ('timeserver', '37'),
+ ('rlp', '39'),
+ ('nameserver', '42'),
+ ('name', '42'),
+ ('nickname', '43'),
+ ('whois', '43'),
+ ('domain', '53'),
+ ('bootps', '67'),
+ ('dhcps', '67'),
+ ('bootpc', '68'),
+ ('dhcpc', '68'),
+ ('tftp', '69'),
+ ('gopher', '70'),
+ ('finger', '79'),
+ ('http', '80'),
+ ('www', '80'),
+ ('www-http', '80'),
+ ('kerberos', '88'),
+ ('hostname', '101'),
+ ('hostnames', '101'),
+ ('iso-tsap', '102'),
+ ('rtelnet', '107'),
+ ('pop2', '109'),
+ ('postoffice', '109'),
+ ('pop3', '110'),
+ ('sunrpc', '111'),
+ ('rpcbind', '111'),
+ ('portmap', '111'),
+ ('auth', '113'),
+ ('ident', '113'),
+ ('tap', '113'),
+ ('uucp-path', '117'),
+ ('nntp', '119'),
+ ('usenet', '119'),
+ ('ntp', '123'),
+ ('epmap', '135'),
+ ('loc-srv', '135'),
+ ('netbios-ns', '137'),
+ ('nbname', '137'),
+ ('netbios-dgm', '138'),
+ ('nbdatagram', '138'),
+ ('netbios-ssn', '139'),
+ ('nbsession', '139'),
+ ('imap', '143'),
+ ('imap4', '143'),
+ ('pcmail-srv', '158'),
+ ('snmp', '161'),
+ ('snmptrap', '162'),
+ ('snmp-trap', '162'),
+ ('print-srv', '170'),
+ ('bgp', '179'),
+ ('irc', '194'),
+ ('ipx', '213'),
+ ('ldap', '389'),
+ ('https', '443'),
+ ('mcom', '443'),
+ ('microsoft-ds', '445'),
+ ('kpasswd', '464'),
+ ('isakmp', '500'),
+ ('ike', '500'),
+ ('exec', '512'),
+ ('biff', '512'),
+ ('comsat', '512'),
+ ('login', '513'),
+ ('who', '513'),
+ ('whod', '513'),
+ ('cmd', '514'),
+ ('shell', '514'),
+ ('syslog', '514'),
+ ('printer', '515'),
+ ('spooler', '515'),
+ ('talk', '517'),
+ ('ntalk', '517'),
+ ('efs', '520'),
+ ('router', '520'),
+ ('route', '520'),
+ ('routed', '520'),
+ ('timed', '525'),
+ ('timeserver', '525'),
+ ('tempo', '526'),
+ ('newdate', '526'),
+ ('courier', '530'),
+ ('rpc', '530'),
+ ('conference', '531'),
+ ('chat', '531'),
+ ('netnews', '532'),
+ ('readnews', '532'),
+ ('netwall', '533'),
+ ('uucp', '540'),
+ ('uucpd', '540'),
+ ('klogin', '543'),
+ ('kshell', '544'),
+ ('krcmd', '544'),
+ ('new-rwho', '550'),
+ ('new-who', '550'),
+ ('remotefs', '556'),
+ ('rfs', '556'),
+ ('rfs_server', '556'),
+ ('rmonitor', '560'),
+ ('rmonitord', '560'),
+ ('monitor', '561'),
+ ('ldaps', '636'),
+ ('sldap', '636'),
+ ('doom', '666'),
+ ('kerberos-adm', '749'),
+ ('kerberos-iv', '750'),
+ ('kpop', '1109'),
+ ('phone', '1167'),
+ ('ms-sql-s', '1433'),
+ ('ms-sql-m', '1434'),
+ ('wins', '1512'),
+ ('ingreslock', '1524'),
+ ('ingres', '1524'),
+ ('l2tp', '1701'),
+ ('pptp', '1723'),
+ ('radius', '1812'),
+ ('radacct', '1813'),
+ ('nfsd', '2049'),
+ ('nfs', '2049'),
+ ('knetd', '2053'),
+ ('gds_db', '3050'),
+ ('man', '9535')
+ );
+
+{function IN6_IS_ADDR_UNSPECIFIED(const a: PInAddr6): boolean;
+begin
+ Result := ((a^.s_un_dw.s_dw1 = 0) and (a^.s_un_dw.s_dw2 = 0) and
+ (a^.s_un_dw.s_dw3 = 0) and (a^.s_un_dw.s_dw4 = 0));
+end;
+
+function IN6_IS_ADDR_LOOPBACK(const a: PInAddr6): boolean;
+begin
+ Result := ((a^.s_un_dw.s_dw1 = 0) and (a^.s_un_dw.s_dw2 = 0) and
+ (a^.s_un_dw.s_dw3 = 0) and
+ (a^.s_un_b.s_b13 = char(0)) and (a^.s_un_b.s_b14 = char(0)) and
+ (a^.s_un_b.s_b15 = char(0)) and (a^.s_un_b.s_b16 = char(1)));
+end;
+
+function IN6_IS_ADDR_LINKLOCAL(const a: PInAddr6): boolean;
+begin
+ Result := ((a^.s_un_b.s_b1 = u_char($FE)) and (a^.s_un_b.s_b2 = u_char($80)));
+end;
+
+function IN6_IS_ADDR_SITELOCAL(const a: PInAddr6): boolean;
+begin
+ Result := ((a^.s_un_b.s_b1 = u_char($FE)) and (a^.s_un_b.s_b2 = u_char($C0)));
+end;
+
+function IN6_IS_ADDR_MULTICAST(const a: PInAddr6): boolean;
+begin
+ Result := (a^.s_un_b.s_b1 = char($FF));
+end;
+
+function IN6_ADDR_EQUAL(const a: PInAddr6; const b: PInAddr6): boolean;
+begin
+ Result := (CompareMem( a, b, sizeof(TInAddr6)));
+end;
+
+procedure SET_IN6_IF_ADDR_ANY (const a: PInAddr6);
+begin
+ FillChar(a^, sizeof(TInAddr6), 0);
+end;
+
+procedure SET_LOOPBACK_ADDR6 (const a: PInAddr6);
+begin
+ FillChar(a^, sizeof(TInAddr6), 0);
+ a^.s_un_b.s_b16 := char(1);
+end;
+}
+
+{=============================================================================}
+
+procedure NullErr;
+begin
+ WSALastError := 0;
+ WSALastErrorDesc := '';
+end;
+
+procedure GetErrCode(E: System.Exception);
+var
+ SE: System.Net.Sockets.SocketException;
+begin
+ if E is System.Net.Sockets.SocketException then
+ begin
+ SE := E as System.Net.Sockets.SocketException;
+ WSALastError := SE.ErrorCode;
+ WSALastErrorDesc := SE.Message;
+ end
+end;
+
+function WSAStartup(wVersionRequired: Word; var WSData: TWSAData): Integer;
+begin
+ NullErr;
+ with WSData do
+ begin
+ wVersion := wVersionRequired;
+ wHighVersion := $202;
+ szDescription := 'Synsock - Synapse Platform Independent Socket Layer';
+ szSystemStatus := 'Running on .NET';
+ iMaxSockets := 32768;
+ iMaxUdpDg := 8192;
+ end;
+ Result := 0;
+end;
+
+function WSACleanup: Integer;
+begin
+ NullErr;
+ Result := 0;
+end;
+
+function WSAGetLastError: Integer;
+begin
+ Result := WSALastError;
+end;
+
+function WSAGetLastErrorDesc: String;
+begin
+ Result := WSALastErrorDesc;
+end;
+
+function GetHostName: string;
+begin
+ Result := System.Net.DNS.GetHostName;
+end;
+
+function Shutdown(s: TSocket; how: Integer): Integer;
+begin
+ Result := 0;
+ NullErr;
+ try
+ s.ShutDown(SocketShutdown(how));
+ except
+ on e: System.Net.Sockets.SocketException do
+ begin
+ GetErrCode(e);
+ Result := integer(SOCKET_ERROR);
+ end;
+ end;
+end;
+
+function SetSockOpt(s: TSocket; level, optname: Integer; optval: Tmemory;
+ optlen: Integer): Integer;
+begin
+ Result := 0;
+ NullErr;
+ try
+ s.SetSocketOption(SocketOptionLevel(level), SocketOptionName(optname), optval);
+ except
+ on e: System.Net.Sockets.SocketException do
+ begin
+ GetErrCode(e);
+ Result := integer(SOCKET_ERROR);
+ end;
+ end;
+end;
+
+function SetSockOptObj(s: TSocket; level, optname: Integer; optval: TObject): Integer;
+begin
+ Result := 0;
+ NullErr;
+ try
+ s.SetSocketOption(SocketOptionLevel(level), SocketOptionName(optname), optval);
+ except
+ on e: System.Net.Sockets.SocketException do
+ begin
+ GetErrCode(e);
+ Result := integer(SOCKET_ERROR);
+ end;
+ end;
+end;
+
+function GetSockOpt(s: TSocket; level, optname: Integer; optval: Tmemory;
+ var optlen: Integer): Integer;
+begin
+ Result := 0;
+ NullErr;
+ try
+ s.GetSocketOption(SocketOptionLevel(level), SocketOptionName(optname), optval);
+ except
+ on e: System.Net.Sockets.SocketException do
+ begin
+ GetErrCode(e);
+ Result := integer(SOCKET_ERROR);
+ end;
+ end;
+end;
+
+function SendTo(s: TSocket; Buf: TMemory; len, flags: Integer; addrto: TVarSin): Integer;
+//function SendTo(s: TSocket; const Buf; len, flags: Integer; addrto: TVarSin): Integer;
+begin
+ NullErr;
+ try
+ result := s.SendTo(Buf, len, SocketFlags(flags), addrto);
+ except
+ on e: System.Net.Sockets.SocketException do
+ begin
+ GetErrCode(e);
+ Result := integer(SOCKET_ERROR);
+ end;
+ end;
+end;
+
+function Send(s: TSocket; Buf: TMemory; len, flags: Integer): Integer;
+//function Send(s: TSocket; const Buf; len, flags: Integer): Integer;
+begin
+ NullErr;
+ try
+ result := s.Send(Buf, len, SocketFlags(flags));
+ except
+ on e: System.Net.Sockets.SocketException do
+ begin
+ GetErrCode(e);
+ Result := integer(SOCKET_ERROR);
+ end;
+ end;
+end;
+
+function Recv(s: TSocket; Buf: TMemory; len, flags: Integer): Integer;
+//function Recv(s: TSocket; var Buf; len, flags: Integer): Integer;
+begin
+ NullErr;
+ try
+ result := s.Receive(Buf, len, SocketFlags(flags));
+ except
+ on e: System.Net.Sockets.SocketException do
+ begin
+ GetErrCode(e);
+ Result := integer(SOCKET_ERROR);
+ end;
+ end;
+end;
+
+//function RecvFrom(s: TSocket; var Buf; len, flags: Integer; from: PSockAddr;
+// var fromlen: Integer): Integer;
+function RecvFrom(s: TSocket; Buf: TMemory; len, flags: Integer; var from: TVarSin): Integer;
+//function RecvFrom(s: TSocket; var Buf; len, flags: Integer; from: TVarSin): Integer;
+var
+ EP: EndPoint;
+begin
+ NullErr;
+ try
+ EP := from;
+ result := s.ReceiveFrom(Buf, len, SocketFlags(flags), EndPoint(EP));
+ from := EP as IPEndPoint;
+ except
+ on e: System.Net.Sockets.SocketException do
+ begin
+ GetErrCode(e);
+ Result := integer(SOCKET_ERROR);
+ end;
+ end;
+end;
+
+function ntohs(netshort: u_short): u_short;
+begin
+ Result := IPAddress.NetworkToHostOrder(NetShort);
+end;
+
+function ntohl(netlong: u_long): u_long;
+begin
+ Result := IPAddress.NetworkToHostOrder(NetLong);
+end;
+
+function Listen(s: TSocket; backlog: Integer): Integer;
+begin
+ Result := 0;
+ NullErr;
+ try
+ s.Listen(backlog);
+ except
+ on e: System.Net.Sockets.SocketException do
+ begin
+ GetErrCode(e);
+ Result := integer(SOCKET_ERROR);
+ end;
+ end;
+end;
+
+function IoctlSocket(s: TSocket; cmd: DWORD; var arg: integer): Integer;
+var
+ inv, outv: TMemory;
+begin
+ Result := 0;
+ NullErr;
+ try
+ if cmd = DWORD(FIONBIO) then
+ s.Blocking := arg = 0
+ else
+ begin
+ inv := BitConverter.GetBytes(arg);
+ outv := BitConverter.GetBytes(integer(0));
+ s.IOControl(cmd, inv, outv);
+ arg := BitConverter.ToInt32(outv, 0);
+ end;
+ except
+ on e: System.Net.Sockets.SocketException do
+ begin
+ GetErrCode(e);
+ Result := integer(SOCKET_ERROR);
+ end;
+ end;
+end;
+
+function htons(hostshort: u_short): u_short;
+begin
+ Result := IPAddress.HostToNetworkOrder(Hostshort);
+end;
+
+function htonl(hostlong: u_long): u_long;
+begin
+ Result := IPAddress.HostToNetworkOrder(HostLong);
+end;
+
+//function GetSockName(s: TSocket; name: PSockAddr; var namelen: Integer): Integer;
+function GetSockName(s: TSocket; var name: TVarSin): Integer;
+begin
+ Result := 0;
+ NullErr;
+ try
+ Name := s.localEndPoint as IPEndpoint;
+ except
+ on e: System.Net.Sockets.SocketException do
+ begin
+ GetErrCode(e);
+ Result := integer(SOCKET_ERROR);
+ end;
+ end;
+end;
+
+//function GetPeerName(s: TSocket; name: PSockAddr; var namelen: Integer): Integer;
+function GetPeerName(s: TSocket; var name: TVarSin): Integer;
+begin
+ Result := 0;
+ NullErr;
+ try
+ Name := s.RemoteEndPoint as IPEndpoint;
+ except
+ on e: System.Net.Sockets.SocketException do
+ begin
+ GetErrCode(e);
+ Result := integer(SOCKET_ERROR);
+ end;
+ end;
+end;
+
+//function Connect(s: TSocket; name: PSockAddr; namelen: Integer): Integer;
+function Connect(s: TSocket; const name: TVarSin): Integer;
+begin
+ Result := 0;
+ NullErr;
+ try
+ s.Connect(name);
+ except
+ on e: System.Net.Sockets.SocketException do
+ begin
+ GetErrCode(e);
+ Result := integer(SOCKET_ERROR);
+ end;
+ end;
+end;
+
+function CloseSocket(s: TSocket): Integer;
+begin
+ Result := 0;
+ NullErr;
+ try
+ s.Close;
+ except
+ on e: System.Net.Sockets.SocketException do
+ begin
+ Result := integer(SOCKET_ERROR);
+ end;
+ end;
+end;
+
+//function Bind(s: TSocket; addr: PSockAddr; namelen: Integer): Integer;
+function Bind(s: TSocket; const addr: TVarSin): Integer;
+begin
+ Result := 0;
+ NullErr;
+ try
+ s.Bind(addr);
+ except
+ on e: System.Net.Sockets.SocketException do
+ begin
+ GetErrCode(e);
+ Result := integer(SOCKET_ERROR);
+ end;
+ end;
+end;
+
+//function Accept(s: TSocket; addr: PSockAddr; var addrlen: Integer): TSocket;
+function Accept(s: TSocket; var addr: TVarSin): TSocket;
+begin
+ NullErr;
+ try
+ result := s.Accept();
+ except
+ on e: System.Net.Sockets.SocketException do
+ begin
+ GetErrCode(e);
+ Result := nil;
+ end;
+ end;
+end;
+
+function Socket(af, Struc, Protocol: Integer): TSocket;
+begin
+ NullErr;
+ try
+ result := TSocket.Create(AddressFamily(af), SocketType(Struc), ProtocolType(Protocol));
+ except
+ on e: System.Net.Sockets.SocketException do
+ begin
+ GetErrCode(e);
+ Result := nil;
+ end;
+ end;
+end;
+
+{=============================================================================}
+function GetPortService(value: string): integer;
+var
+ n: integer;
+begin
+ Result := 0;
+ value := Lowercase(value);
+ for n := 0 to High(Services) do
+ if services[n, 0] = value then
+ begin
+ Result := strtointdef(services[n, 1], 0);
+ break;
+ end;
+ if Result = 0 then
+ Result := StrToIntDef(value, 0);
+end;
+
+{=============================================================================}
+function IsNewApi(Family: TAddrFamily): Boolean;
+begin
+ Result := true;
+end;
+
+function SetVarSin(var Sin: TVarSin; IP, Port: string; Family: TAddrFamily; SockProtocol, SockType: integer; PreferIP4: Boolean): integer;
+var
+ IPs: array of IPAddress;
+ n: integer;
+ ip4, ip6: string;
+ sip: string;
+begin
+ sip := '';
+ ip4 := '';
+ ip6 := '';
+ IPs := Dns.Resolve(IP).AddressList;
+ for n :=low(IPs) to high(IPs) do begin
+ if (ip4 = '') and (IPs[n].AddressFamily = AF_INET) then
+ ip4 := IPs[n].toString;
+ if (ip6 = '') and (IPs[n].AddressFamily = AF_INET6) then
+ ip6 := IPs[n].toString;
+ if (ip4 <> '') and (ip6 <> '') then
+ break;
+ end;
+ case Family of
+ AF_UNSPEC:
+ begin
+ if (ip4 <> '') and (ip6 <> '') then
+ begin
+ if PreferIP4 then
+ sip := ip4
+ else
+ Sip := ip6;
+ end
+ else
+ begin
+ sip := ip4;
+ if (ip6 <> '') then
+ sip := ip6;
+ end;
+ end;
+ AF_INET:
+ sip := ip4;
+ AF_INET6:
+ sip := ip6;
+ end;
+ sin := TVarSin.Create(IPAddress.Parse(sip), GetPortService(Port));
+end;
+
+function GetSinIP(Sin: TVarSin): string;
+begin
+ Result := Sin.Address.ToString;
+end;
+
+function GetSinPort(Sin: TVarSin): Integer;
+begin
+ Result := Sin.Port;
+end;
+
+procedure ResolveNameToIP(Name: string; Family: TAddrFamily; SockProtocol, SockType: integer; const IPList: TStrings);
+var
+ IPs :array of IPAddress;
+ n: integer;
+begin
+ IPList.Clear;
+ IPs := Dns.Resolve(Name).AddressList;
+ for n := low(IPs) to high(IPs) do
+ begin
+ if not(((Family = AF_INET6) and (IPs[n].AddressFamily = AF_INET))
+ or ((Family = AF_INET) and (IPs[n].AddressFamily = AF_INET6))) then
+ begin
+ IPList.Add(IPs[n].toString);
+ end;
+ end;
+end;
+
+function ResolvePort(Port: string; Family: TAddrFamily; SockProtocol, SockType: integer): Word;
+var
+ n: integer;
+begin
+ Result := StrToIntDef(port, 0);
+ if Result = 0 then
+ begin
+ port := Lowercase(port);
+ for n := 0 to High(Services) do
+ if services[n, 0] = port then
+ begin
+ Result := strtointdef(services[n, 1], 0);
+ break;
+ end;
+ end;
+end;
+
+function ResolveIPToName(IP: string; Family: TAddrFamily; SockProtocol, SockType: integer): string;
+begin
+ Result := Dns.GetHostByAddress(IP).HostName;
+end;
+
+
+{=============================================================================}
+function InitSocketInterface(stack: string): Boolean;
+begin
+ Result := True;
+end;
+
+function DestroySocketInterface: Boolean;
+begin
+ NullErr;
+ Result := True;
+end;
+
+initialization
+begin
+ SynSockCS := SyncObjs.TCriticalSection.Create;
+// SET_IN6_IF_ADDR_ANY (@in6addr_any);
+// SET_LOOPBACK_ADDR6 (@in6addr_loopback);
+end;
+
+finalization
+begin
+ NullErr;
+ SynSockCS.Free;
+end;
+
+{$ENDIF}
diff --git a/branches/script-component/Units/Synapse/ssfpc.pas b/branches/script-component/Units/Synapse/ssfpc.pas
new file mode 100644
index 0000000..072d7c7
--- /dev/null
+++ b/branches/script-component/Units/Synapse/ssfpc.pas
@@ -0,0 +1,891 @@
+{==============================================================================|
+| Project : Ararat Synapse | 001.001.000 |
+|==============================================================================|
+| Content: Socket Independent Platform Layer - FreePascal definition include |
+|==============================================================================|
+| Copyright (c)2006-2009, Lukas Gebauer |
+| All rights reserved. |
+| |
+| Redistribution and use in source and binary forms, with or without |
+| modification, are permitted provided that the following conditions are met: |
+| |
+| Redistributions of source code must retain the above copyright notice, this |
+| list of conditions and the following disclaimer. |
+| |
+| Redistributions in binary form must reproduce the above copyright notice, |
+| this list of conditions and the following disclaimer in the documentation |
+| and/or other materials provided with the distribution. |
+| |
+| Neither the name of Lukas Gebauer nor the names of its contributors may |
+| be used to endorse or promote products derived from this software without |
+| specific prior written permission. |
+| |
+| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
+| AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
+| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
+| ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR |
+| ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
+| DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
+| SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
+| CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
+| LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
+| OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
+| DAMAGE. |
+|==============================================================================|
+| The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).|
+| Portions created by Lukas Gebauer are Copyright (c)2006-2009. |
+| All Rights Reserved. |
+|==============================================================================|
+| Contributor(s): |
+|==============================================================================|
+| History: see HISTORY.HTM from distribution package |
+| (Found at URL: http://www.ararat.cz/synapse/) |
+|==============================================================================}
+
+{:@exclude}
+
+{$IFDEF FPC}
+{For FreePascal 2.x.x}
+
+//{$DEFINE FORCEOLDAPI}
+{Note about define FORCEOLDAPI:
+If you activate this compiler directive, then is allways used old socket API
+for name resolution. If you leave this directive inactive, then the new API
+is used, when running system allows it.
+
+For IPv6 support you must have new API!
+}
+
+{$IFDEF FPC}
+ {$MODE DELPHI}
+{$ENDIF}
+{$H+}
+
+{$ifdef FreeBSD}
+{$DEFINE SOCK_HAS_SINLEN} // BSD definition of scoketaddr
+{$endif}
+{$ifdef darwin}
+{$DEFINE SOCK_HAS_SINLEN} // BSD definition of scoketaddr
+{$endif}
+
+interface
+
+uses
+ SyncObjs, SysUtils, Classes,
+ synafpc, BaseUnix, Unix, termio, sockets, netdb;
+
+function InitSocketInterface(stack: string): Boolean;
+function DestroySocketInterface: Boolean;
+
+const
+ DLLStackName = '';
+ WinsockLevel = $0202;
+
+ cLocalHost = '127.0.0.1';
+ cAnyHost = '0.0.0.0';
+ c6AnyHost = '::0';
+ c6Localhost = '::1';
+ cLocalHostStr = 'localhost';
+
+type
+ TSocket = longint;
+ TAddrFamily = integer;
+
+ TMemory = pointer;
+
+
+type
+ TFDSet = Baseunix.TFDSet;
+ PFDSet = ^TFDSet;
+ Ptimeval = Baseunix.ptimeval;
+ Ttimeval = Baseunix.ttimeval;
+
+const
+ FIONREAD = termio.FIONREAD;
+ FIONBIO = termio.FIONBIO;
+ FIOASYNC = termio.FIOASYNC;
+
+const
+ IPPROTO_IP = 0; { Dummy }
+ IPPROTO_ICMP = 1; { Internet Control Message Protocol }
+ IPPROTO_IGMP = 2; { Internet Group Management Protocol}
+ IPPROTO_TCP = 6; { TCP }
+ IPPROTO_UDP = 17; { User Datagram Protocol }
+ IPPROTO_IPV6 = 41;
+ IPPROTO_ICMPV6 = 58;
+
+ IPPROTO_RAW = 255;
+ IPPROTO_MAX = 256;
+
+type
+ PInAddr = ^TInAddr;
+ TInAddr = sockets.in_addr;
+
+ PSockAddrIn = ^TSockAddrIn;
+ TSockAddrIn = sockets.TInetSockAddr;
+
+
+ TIP_mreq = record
+ imr_multiaddr: TInAddr; // IP multicast address of group
+ imr_interface: TInAddr; // local IP address of interface
+ end;
+
+
+ PInAddr6 = ^TInAddr6;
+ TInAddr6 = sockets.Tin6_addr;
+
+ PSockAddrIn6 = ^TSockAddrIn6;
+ TSockAddrIn6 = sockets.TInetSockAddr6;
+
+
+ TIPv6_mreq = record
+ ipv6mr_multiaddr: TInAddr6; // IPv6 multicast address.
+ ipv6mr_interface: integer; // Interface index.
+ end;
+
+const
+ INADDR_ANY = $00000000;
+ INADDR_LOOPBACK = $7F000001;
+ INADDR_BROADCAST = $FFFFFFFF;
+ INADDR_NONE = $FFFFFFFF;
+ ADDR_ANY = INADDR_ANY;
+ INVALID_SOCKET = TSocket(NOT(0));
+ SOCKET_ERROR = -1;
+
+Const
+ IP_TOS = sockets.IP_TOS; { int; IP type of service and precedence. }
+ IP_TTL = sockets.IP_TTL; { int; IP time to live. }
+ IP_HDRINCL = sockets.IP_HDRINCL; { int; Header is included with data. }
+ IP_OPTIONS = sockets.IP_OPTIONS; { ip_opts; IP per-packet options. }
+// IP_ROUTER_ALERT = sockets.IP_ROUTER_ALERT; { bool }
+ IP_RECVOPTS = sockets.IP_RECVOPTS; { bool }
+ IP_RETOPTS = sockets.IP_RETOPTS; { bool }
+// IP_PKTINFO = sockets.IP_PKTINFO; { bool }
+// IP_PKTOPTIONS = sockets.IP_PKTOPTIONS;
+// IP_PMTUDISC = sockets.IP_PMTUDISC; { obsolete name? }
+// IP_MTU_DISCOVER = sockets.IP_MTU_DISCOVER; { int; see below }
+// IP_RECVERR = sockets.IP_RECVERR; { bool }
+// IP_RECVTTL = sockets.IP_RECVTTL; { bool }
+// IP_RECVTOS = sockets.IP_RECVTOS; { bool }
+ IP_MULTICAST_IF = sockets.IP_MULTICAST_IF; { in_addr; set/get IP multicast i/f }
+ IP_MULTICAST_TTL = sockets.IP_MULTICAST_TTL; { u_char; set/get IP multicast ttl }
+ IP_MULTICAST_LOOP = sockets.IP_MULTICAST_LOOP; { i_char; set/get IP multicast loopback }
+ IP_ADD_MEMBERSHIP = sockets.IP_ADD_MEMBERSHIP; { ip_mreq; add an IP group membership }
+ IP_DROP_MEMBERSHIP = sockets.IP_DROP_MEMBERSHIP; { ip_mreq; drop an IP group membership }
+
+ SOL_SOCKET = sockets.SOL_SOCKET;
+
+ SO_DEBUG = sockets.SO_DEBUG;
+ SO_REUSEADDR = sockets.SO_REUSEADDR;
+ SO_TYPE = sockets.SO_TYPE;
+ SO_ERROR = sockets.SO_ERROR;
+ SO_DONTROUTE = sockets.SO_DONTROUTE;
+ SO_BROADCAST = sockets.SO_BROADCAST;
+ SO_SNDBUF = sockets.SO_SNDBUF;
+ SO_RCVBUF = sockets.SO_RCVBUF;
+ SO_KEEPALIVE = sockets.SO_KEEPALIVE;
+ SO_OOBINLINE = sockets.SO_OOBINLINE;
+// SO_NO_CHECK = sockets.SO_NO_CHECK;
+// SO_PRIORITY = sockets.SO_PRIORITY;
+ SO_LINGER = sockets.SO_LINGER;
+// SO_BSDCOMPAT = sockets.SO_BSDCOMPAT;
+// SO_REUSEPORT = sockets.SO_REUSEPORT;
+// SO_PASSCRED = sockets.SO_PASSCRED;
+// SO_PEERCRED = sockets.SO_PEERCRED;
+ SO_RCVLOWAT = sockets.SO_RCVLOWAT;
+ SO_SNDLOWAT = sockets.SO_SNDLOWAT;
+ SO_RCVTIMEO = sockets.SO_RCVTIMEO;
+ SO_SNDTIMEO = sockets.SO_SNDTIMEO;
+{ Security levels - as per NRL IPv6 - don't actually do anything }
+// SO_SECURITY_AUTHENTICATION = sockets.SO_SECURITY_AUTHENTICATION;
+// SO_SECURITY_ENCRYPTION_TRANSPORT = sockets.SO_SECURITY_ENCRYPTION_TRANSPORT;
+// SO_SECURITY_ENCRYPTION_NETWORK = sockets.SO_SECURITY_ENCRYPTION_NETWORK;
+// SO_BINDTODEVICE = sockets.SO_BINDTODEVICE;
+{ Socket filtering }
+// SO_ATTACH_FILTER = sockets.SO_ATTACH_FILTER;
+// SO_DETACH_FILTER = sockets.SO_DETACH_FILTER;
+
+ SOMAXCONN = 1024;
+
+ IPV6_UNICAST_HOPS = sockets.IPV6_UNICAST_HOPS;
+ IPV6_MULTICAST_IF = sockets.IPV6_MULTICAST_IF;
+ IPV6_MULTICAST_HOPS = sockets.IPV6_MULTICAST_HOPS;
+ IPV6_MULTICAST_LOOP = sockets.IPV6_MULTICAST_LOOP;
+ IPV6_JOIN_GROUP = sockets.IPV6_JOIN_GROUP;
+ IPV6_LEAVE_GROUP = sockets.IPV6_LEAVE_GROUP;
+
+const
+ SOCK_STREAM = 1; { stream socket }
+ SOCK_DGRAM = 2; { datagram socket }
+ SOCK_RAW = 3; { raw-protocol interface }
+ SOCK_RDM = 4; { reliably-delivered message }
+ SOCK_SEQPACKET = 5; { sequenced packet stream }
+
+{ TCP options. }
+ TCP_NODELAY = $0001;
+
+{ Address families. }
+
+ AF_UNSPEC = 0; { unspecified }
+ AF_INET = 2; { internetwork: UDP, TCP, etc. }
+ AF_INET6 = 10; { Internetwork Version 6 }
+ AF_MAX = 24;
+
+{ Protocol families, same as address families for now. }
+ PF_UNSPEC = AF_UNSPEC;
+ PF_INET = AF_INET;
+ PF_INET6 = AF_INET6;
+ PF_MAX = AF_MAX;
+
+type
+{ Structure used for manipulating linger option. }
+ PLinger = ^TLinger;
+ TLinger = packed record
+ l_onoff: integer;
+ l_linger: integer;
+ end;
+
+const
+
+ MSG_OOB = sockets.MSG_OOB; // Process out-of-band data.
+ MSG_PEEK = sockets.MSG_PEEK; // Peek at incoming messages.
+ MSG_NOSIGNAL = sockets.MSG_NOSIGNAL; // Do not generate SIGPIPE.
+
+const
+ WSAEINTR = ESysEINTR;
+ WSAEBADF = ESysEBADF;
+ WSAEACCES = ESysEACCES;
+ WSAEFAULT = ESysEFAULT;
+ WSAEINVAL = ESysEINVAL;
+ WSAEMFILE = ESysEMFILE;
+ WSAEWOULDBLOCK = ESysEWOULDBLOCK;
+ WSAEINPROGRESS = ESysEINPROGRESS;
+ WSAEALREADY = ESysEALREADY;
+ WSAENOTSOCK = ESysENOTSOCK;
+ WSAEDESTADDRREQ = ESysEDESTADDRREQ;
+ WSAEMSGSIZE = ESysEMSGSIZE;
+ WSAEPROTOTYPE = ESysEPROTOTYPE;
+ WSAENOPROTOOPT = ESysENOPROTOOPT;
+ WSAEPROTONOSUPPORT = ESysEPROTONOSUPPORT;
+ WSAESOCKTNOSUPPORT = ESysESOCKTNOSUPPORT;
+ WSAEOPNOTSUPP = ESysEOPNOTSUPP;
+ WSAEPFNOSUPPORT = ESysEPFNOSUPPORT;
+ WSAEAFNOSUPPORT = ESysEAFNOSUPPORT;
+ WSAEADDRINUSE = ESysEADDRINUSE;
+ WSAEADDRNOTAVAIL = ESysEADDRNOTAVAIL;
+ WSAENETDOWN = ESysENETDOWN;
+ WSAENETUNREACH = ESysENETUNREACH;
+ WSAENETRESET = ESysENETRESET;
+ WSAECONNABORTED = ESysECONNABORTED;
+ WSAECONNRESET = ESysECONNRESET;
+ WSAENOBUFS = ESysENOBUFS;
+ WSAEISCONN = ESysEISCONN;
+ WSAENOTCONN = ESysENOTCONN;
+ WSAESHUTDOWN = ESysESHUTDOWN;
+ WSAETOOMANYREFS = ESysETOOMANYREFS;
+ WSAETIMEDOUT = ESysETIMEDOUT;
+ WSAECONNREFUSED = ESysECONNREFUSED;
+ WSAELOOP = ESysELOOP;
+ WSAENAMETOOLONG = ESysENAMETOOLONG;
+ WSAEHOSTDOWN = ESysEHOSTDOWN;
+ WSAEHOSTUNREACH = ESysEHOSTUNREACH;
+ WSAENOTEMPTY = ESysENOTEMPTY;
+ WSAEPROCLIM = -1;
+ WSAEUSERS = ESysEUSERS;
+ WSAEDQUOT = ESysEDQUOT;
+ WSAESTALE = ESysESTALE;
+ WSAEREMOTE = ESysEREMOTE;
+ WSASYSNOTREADY = -2;
+ WSAVERNOTSUPPORTED = -3;
+ WSANOTINITIALISED = -4;
+ WSAEDISCON = -5;
+ WSAHOST_NOT_FOUND = 1;
+ WSATRY_AGAIN = 2;
+ WSANO_RECOVERY = 3;
+ WSANO_DATA = -6;
+
+const
+ WSADESCRIPTION_LEN = 256;
+ WSASYS_STATUS_LEN = 128;
+type
+ PWSAData = ^TWSAData;
+ TWSAData = packed record
+ wVersion: Word;
+ wHighVersion: Word;
+ szDescription: array[0..WSADESCRIPTION_LEN] of Char;
+ szSystemStatus: array[0..WSASYS_STATUS_LEN] of Char;
+ iMaxSockets: Word;
+ iMaxUdpDg: Word;
+ lpVendorInfo: PChar;
+ end;
+
+ function IN6_IS_ADDR_UNSPECIFIED(const a: PInAddr6): boolean;
+ function IN6_IS_ADDR_LOOPBACK(const a: PInAddr6): boolean;
+ function IN6_IS_ADDR_LINKLOCAL(const a: PInAddr6): boolean;
+ function IN6_IS_ADDR_SITELOCAL(const a: PInAddr6): boolean;
+ function IN6_IS_ADDR_MULTICAST(const a: PInAddr6): boolean;
+ function IN6_ADDR_EQUAL(const a: PInAddr6; const b: PInAddr6):boolean;
+ procedure SET_IN6_IF_ADDR_ANY (const a: PInAddr6);
+ procedure SET_LOOPBACK_ADDR6 (const a: PInAddr6);
+
+var
+ in6addr_any, in6addr_loopback : TInAddr6;
+
+procedure FD_CLR(Socket: TSocket; var FDSet: TFDSet);
+function FD_ISSET(Socket: TSocket; var FDSet: TFDSet): Boolean;
+procedure FD_SET(Socket: TSocket; var FDSet: TFDSet);
+procedure FD_ZERO(var FDSet: TFDSet);
+
+{=============================================================================}
+
+var
+ SynSockCS: SyncObjs.TCriticalSection;
+ SockEnhancedApi: Boolean;
+ SockWship6Api: Boolean;
+
+type
+ TVarSin = packed record
+ {$ifdef SOCK_HAS_SINLEN}
+ sin_len : cuchar;
+ {$endif}
+ case integer of
+ 0: (AddressFamily: sa_family_t);
+ 1: (
+ case sin_family: sa_family_t of
+ AF_INET: (sin_port: word;
+ sin_addr: TInAddr;
+ sin_zero: array[0..7] of Char);
+ AF_INET6: (sin6_port: word;
+ sin6_flowinfo: longword;
+ sin6_addr: TInAddr6;
+ sin6_scope_id: longword);
+ );
+ end;
+
+function SizeOfVarSin(sin: TVarSin): integer;
+
+ function WSAStartup(wVersionRequired: Word; var WSData: TWSAData): Integer;
+ function WSACleanup: Integer;
+ function WSAGetLastError: Integer;
+ function GetHostName: string;
+ function Shutdown(s: TSocket; how: Integer): Integer;
+ function SetSockOpt(s: TSocket; level, optname: Integer; optval: TMemory;
+ optlen: Integer): Integer;
+ function GetSockOpt(s: TSocket; level, optname: Integer; optval: TMemory;
+ var optlen: Integer): Integer;
+ function Send(s: TSocket; Buf: TMemory; len, flags: Integer): Integer;
+ function Recv(s: TSocket; Buf: TMemory; len, flags: Integer): Integer;
+ function SendTo(s: TSocket; Buf: TMemory; len, flags: Integer; addrto: TVarSin): Integer;
+ function RecvFrom(s: TSocket; Buf: TMemory; len, flags: Integer; var from: TVarSin): Integer;
+ function ntohs(netshort: word): word;
+ function ntohl(netlong: longword): longword;
+ function Listen(s: TSocket; backlog: Integer): Integer;
+ function IoctlSocket(s: TSocket; cmd: DWORD; var arg: integer): Integer;
+ function htons(hostshort: word): word;
+ function htonl(hostlong: longword): longword;
+ function GetSockName(s: TSocket; var name: TVarSin): Integer;
+ function GetPeerName(s: TSocket; var name: TVarSin): Integer;
+ function Connect(s: TSocket; const name: TVarSin): Integer;
+ function CloseSocket(s: TSocket): Integer;
+ function Bind(s: TSocket; const addr: TVarSin): Integer;
+ function Accept(s: TSocket; var addr: TVarSin): TSocket;
+ function Socket(af, Struc, Protocol: Integer): TSocket;
+ function Select(nfds: Integer; readfds, writefds, exceptfds: PFDSet;
+ timeout: PTimeVal): Longint;
+
+function IsNewApi(Family: integer): Boolean;
+function SetVarSin(var Sin: TVarSin; IP, Port: string; Family, SockProtocol, SockType: integer; PreferIP4: Boolean): integer;
+function GetSinIP(Sin: TVarSin): string;
+function GetSinPort(Sin: TVarSin): Integer;
+procedure ResolveNameToIP(Name: string; Family, SockProtocol, SockType: integer; const IPList: TStrings);
+function ResolveIPToName(IP: string; Family, SockProtocol, SockType: integer): string;
+function ResolvePort(Port: string; Family, SockProtocol, SockType: integer): Word;
+
+
+{==============================================================================}
+implementation
+
+
+function IN6_IS_ADDR_UNSPECIFIED(const a: PInAddr6): boolean;
+begin
+ Result := ((a^.u6_addr32[0] = 0) and (a^.u6_addr32[1] = 0) and
+ (a^.u6_addr32[2] = 0) and (a^.u6_addr32[3] = 0));
+end;
+
+function IN6_IS_ADDR_LOOPBACK(const a: PInAddr6): boolean;
+begin
+ Result := ((a^.u6_addr32[0] = 0) and (a^.u6_addr32[1] = 0) and
+ (a^.u6_addr32[2] = 0) and
+ (a^.u6_addr8[12] = 0) and (a^.u6_addr8[13] = 0) and
+ (a^.u6_addr8[14] = 0) and (a^.u6_addr8[15] = 1));
+end;
+
+function IN6_IS_ADDR_LINKLOCAL(const a: PInAddr6): boolean;
+begin
+ Result := ((a^.u6_addr8[0] = $FE) and (a^.u6_addr8[1] = $80));
+end;
+
+function IN6_IS_ADDR_SITELOCAL(const a: PInAddr6): boolean;
+begin
+ Result := ((a^.u6_addr8[0] = $FE) and (a^.u6_addr8[1] = $C0));
+end;
+
+function IN6_IS_ADDR_MULTICAST(const a: PInAddr6): boolean;
+begin
+ Result := (a^.u6_addr8[0] = $FF);
+end;
+
+function IN6_ADDR_EQUAL(const a: PInAddr6; const b: PInAddr6): boolean;
+begin
+ Result := (CompareMem( a, b, sizeof(TInAddr6)));
+end;
+
+procedure SET_IN6_IF_ADDR_ANY (const a: PInAddr6);
+begin
+ FillChar(a^, sizeof(TInAddr6), 0);
+end;
+
+procedure SET_LOOPBACK_ADDR6 (const a: PInAddr6);
+begin
+ FillChar(a^, sizeof(TInAddr6), 0);
+ a^.u6_addr8[15] := 1;
+end;
+
+{=============================================================================}
+
+function WSAStartup(wVersionRequired: Word; var WSData: TWSAData): Integer;
+begin
+ with WSData do
+ begin
+ wVersion := wVersionRequired;
+ wHighVersion := $202;
+ szDescription := 'Synsock - Synapse Platform Independent Socket Layer';
+ szSystemStatus := 'Running on Unix/Linux by FreePascal';
+ iMaxSockets := 32768;
+ iMaxUdpDg := 8192;
+ end;
+ Result := 0;
+end;
+
+function WSACleanup: Integer;
+begin
+ Result := 0;
+end;
+
+function WSAGetLastError: Integer;
+begin
+ Result := fpGetErrno;
+end;
+
+function FD_ISSET(Socket: TSocket; var fdset: TFDSet): Boolean;
+begin
+ Result := fpFD_ISSET(socket, fdset) <> 0;
+end;
+
+procedure FD_SET(Socket: TSocket; var fdset: TFDSet);
+begin
+ fpFD_SET(Socket, fdset);
+end;
+
+procedure FD_CLR(Socket: TSocket; var fdset: TFDSet);
+begin
+ fpFD_CLR(Socket, fdset);
+end;
+
+procedure FD_ZERO(var fdset: TFDSet);
+begin
+ fpFD_ZERO(fdset);
+end;
+
+{=============================================================================}
+
+function SizeOfVarSin(sin: TVarSin): integer;
+begin
+ case sin.sin_family of
+ AF_INET:
+ Result := SizeOf(TSockAddrIn);
+ AF_INET6:
+ Result := SizeOf(TSockAddrIn6);
+ else
+ Result := 0;
+ end;
+end;
+
+{=============================================================================}
+
+function Bind(s: TSocket; const addr: TVarSin): Integer;
+begin
+ if fpBind(s, @addr, SizeOfVarSin(addr)) = 0 then
+ Result := 0
+ else
+ Result := SOCKET_ERROR;
+end;
+
+function Connect(s: TSocket; const name: TVarSin): Integer;
+begin
+ if fpConnect(s, @name, SizeOfVarSin(name)) = 0 then
+ Result := 0
+ else
+ Result := SOCKET_ERROR;
+end;
+
+function GetSockName(s: TSocket; var name: TVarSin): Integer;
+var
+ len: integer;
+begin
+ len := SizeOf(name);
+ FillChar(name, len, 0);
+ Result := fpGetSockName(s, @name, @Len);
+end;
+
+function GetPeerName(s: TSocket; var name: TVarSin): Integer;
+var
+ len: integer;
+begin
+ len := SizeOf(name);
+ FillChar(name, len, 0);
+ Result := fpGetPeerName(s, @name, @Len);
+end;
+
+function GetHostName: string;
+begin
+ Result := unix.GetHostName;
+end;
+
+function Send(s: TSocket; Buf: TMemory; len, flags: Integer): Integer;
+begin
+ Result := fpSend(s, pointer(Buf), len, flags);
+end;
+
+function Recv(s: TSocket; Buf: TMemory; len, flags: Integer): Integer;
+begin
+ Result := fpRecv(s, pointer(Buf), len, flags);
+end;
+
+function SendTo(s: TSocket; Buf: TMemory; len, flags: Integer; addrto: TVarSin): Integer;
+begin
+ Result := fpSendTo(s, pointer(Buf), len, flags, @addrto, SizeOfVarSin(addrto));
+end;
+
+function RecvFrom(s: TSocket; Buf: TMemory; len, flags: Integer; var from: TVarSin): Integer;
+var
+ x: integer;
+begin
+ x := SizeOf(from);
+ Result := fpRecvFrom(s, pointer(Buf), len, flags, @from, @x);
+end;
+
+function Accept(s: TSocket; var addr: TVarSin): TSocket;
+var
+ x: integer;
+begin
+ x := SizeOf(addr);
+ Result := fpAccept(s, @addr, @x);
+end;
+
+function Shutdown(s: TSocket; how: Integer): Integer;
+begin
+ Result := fpShutdown(s, how);
+end;
+
+function SetSockOpt(s: TSocket; level, optname: Integer; optval: Tmemory;
+ optlen: Integer): Integer;
+begin
+ Result := fpsetsockopt(s, level, optname, pointer(optval), optlen);
+end;
+
+function GetSockOpt(s: TSocket; level, optname: Integer; optval: Tmemory;
+ var optlen: Integer): Integer;
+begin
+ Result := fpgetsockopt(s, level, optname, pointer(optval), @optlen);
+end;
+
+function ntohs(netshort: word): word;
+begin
+ Result := sockets.ntohs(NetShort);
+end;
+
+function ntohl(netlong: longword): longword;
+begin
+ Result := sockets.ntohl(NetLong);
+end;
+
+function Listen(s: TSocket; backlog: Integer): Integer;
+begin
+ if fpListen(s, backlog) = 0 then
+ Result := 0
+ else
+ Result := SOCKET_ERROR;
+end;
+
+function IoctlSocket(s: TSocket; cmd: DWORD; var arg: integer): Integer;
+begin
+ Result := fpIoctl(s, cmd, @arg);
+end;
+
+function htons(hostshort: word): word;
+begin
+ Result := sockets.htons(Hostshort);
+end;
+
+function htonl(hostlong: longword): longword;
+begin
+ Result := sockets.htonl(HostLong);
+end;
+
+function CloseSocket(s: TSocket): Integer;
+begin
+ Result := sockets.CloseSocket(s);
+end;
+
+function Socket(af, Struc, Protocol: Integer): TSocket;
+begin
+ Result := fpSocket(af, struc, protocol);
+end;
+
+function Select(nfds: Integer; readfds, writefds, exceptfds: PFDSet;
+ timeout: PTimeVal): Longint;
+begin
+ Result := fpSelect(nfds, readfds, writefds, exceptfds, timeout);
+end;
+
+{=============================================================================}
+function IsNewApi(Family: integer): Boolean;
+begin
+ Result := SockEnhancedApi;
+ if not Result then
+ Result := (Family = AF_INET6) and SockWship6Api;
+end;
+
+function SetVarSin(var Sin: TVarSin; IP, Port: string; Family, SockProtocol, SockType: integer; PreferIP4: Boolean): integer;
+var
+ TwoPass: boolean;
+ f1, f2: integer;
+
+ function GetAddr(f:integer): integer;
+ var
+ a4: array [1..1] of in_addr;
+ a6: array [1..1] of Tin6_addr;
+ begin
+ Result := WSAEPROTONOSUPPORT;
+ case f of
+ AF_INET:
+ begin
+ if IP = cAnyHost then
+ begin
+ Sin.sin_family := AF_INET;
+ Result := 0;
+ end
+ else
+ begin
+ if lowercase(IP) = cLocalHostStr then
+ a4[1].s_addr := htonl(INADDR_LOOPBACK)
+ else
+ begin
+ a4[1].s_addr := 0;
+ Result := WSAHOST_NOT_FOUND;
+ a4[1] := StrTonetAddr(IP);
+ if a4[1].s_addr = INADDR_ANY then
+ Resolvename(ip, a4);
+ end;
+ if a4[1].s_addr <> INADDR_ANY then
+ begin
+ Sin.sin_family := AF_INET;
+ sin.sin_addr := a4[1];
+ Result := 0;
+ end;
+ end;
+ end;
+ AF_INET6:
+ begin
+ if IP = c6AnyHost then
+ begin
+ Sin.sin_family := AF_INET6;
+ Result := 0;
+ end
+ else
+ begin
+ if lowercase(IP) = cLocalHostStr then
+ SET_LOOPBACK_ADDR6(@a6[1])
+ else
+ begin
+ Result := WSAHOST_NOT_FOUND;
+ SET_IN6_IF_ADDR_ANY(@a6[1]);
+ a6[1] := StrTonetAddr6(IP);
+ if IN6_IS_ADDR_UNSPECIFIED(@a6[1]) then
+ Resolvename6(ip, a6);
+ end;
+ if IN6_IS_ADDR_UNSPECIFIED(@a6[1]) then
+ begin
+ Sin.sin_family := AF_INET6;
+ sin.sin6_addr := a6[1];
+ Result := 0;
+ end;
+ end;
+ end;
+ end;
+ end;
+begin
+ Result := 0;
+ FillChar(Sin, Sizeof(Sin), 0);
+ Sin.sin_port := Resolveport(port, family, SockProtocol, SockType);
+ TwoPass := False;
+ if Family = AF_UNSPEC then
+ begin
+ if PreferIP4 then
+ begin
+ f1 := AF_INET;
+ f2 := AF_INET6;
+ TwoPass := True;
+ end
+ else
+ begin
+ f2 := AF_INET;
+ f1 := AF_INET6;
+ TwoPass := True;
+ end;
+ end
+ else
+ f1 := Family;
+ Result := GetAddr(f1);
+ if Result <> 0 then
+ if TwoPass then
+ Result := GetAddr(f2);
+end;
+
+function GetSinIP(Sin: TVarSin): string;
+begin
+ Result := '';
+ case sin.AddressFamily of
+ AF_INET:
+ begin
+ result := NetAddrToStr(sin.sin_addr);
+ end;
+ AF_INET6:
+ begin
+ result := NetAddrToStr6(sin.sin6_addr);
+ end;
+ end;
+end;
+
+function GetSinPort(Sin: TVarSin): Integer;
+begin
+ if (Sin.sin_family = AF_INET6) then
+ Result := synsock.ntohs(Sin.sin6_port)
+ else
+ Result := synsock.ntohs(Sin.sin_port);
+end;
+
+procedure ResolveNameToIP(Name: string; Family, SockProtocol, SockType: integer; const IPList: TStrings);
+var
+ x, n: integer;
+ a4: array [1..255] of in_addr;
+ a6: array [1..255] of Tin6_addr;
+begin
+ IPList.Clear;
+ if (family = AF_INET) or (family = AF_UNSPEC) then
+ begin
+ if lowercase(name) = cLocalHostStr then
+ IpList.Add(cLocalHost)
+ else
+ begin
+ a4[1] := StrTonetAddr(name);
+ if a4[1].s_addr = INADDR_ANY then
+ x := Resolvename(name, a4)
+ else
+ x := 1;
+ for n := 1 to x do
+ IpList.Add(netaddrToStr(a4[n]));
+ end;
+ end;
+
+ if (family = AF_INET6) or (family = AF_UNSPEC) then
+ begin
+ if lowercase(name) = cLocalHostStr then
+ IpList.Add(c6LocalHost)
+ else
+ begin
+ a6[1] := StrTonetAddr6(name);
+ if IN6_IS_ADDR_UNSPECIFIED(@a6[1]) then
+ x := Resolvename6(name, a6)
+ else
+ x := 1;
+ for n := 1 to x do
+ IpList.Add(netaddrToStr6(a6[n]));
+ end;
+ end;
+
+ if IPList.Count = 0 then
+ IPList.Add(cLocalHost);
+end;
+
+function ResolvePort(Port: string; Family, SockProtocol, SockType: integer): Word;
+var
+ ProtoEnt: TProtocolEntry;
+ ServEnt: TServiceEntry;
+begin
+ Result := synsock.htons(StrToIntDef(Port, 0));
+ if Result = 0 then
+ begin
+ ProtoEnt.Name := '';
+ GetProtocolByNumber(SockProtocol, ProtoEnt);
+ ServEnt.port := 0;
+ GetServiceByName(Port, ProtoEnt.Name, ServEnt);
+ Result := ServEnt.port;
+ end;
+end;
+
+function ResolveIPToName(IP: string; Family, SockProtocol, SockType: integer): string;
+var
+ n: integer;
+ a4: array [1..1] of in_addr;
+ a6: array [1..1] of Tin6_addr;
+ a: array [1..1] of string;
+begin
+ Result := IP;
+ a4[1] := StrToNetAddr(IP);
+ if a4[1].s_addr <> INADDR_ANY then
+ begin
+//why ResolveAddress need address in HOST order? :-O
+ n := ResolveAddress(nettohost(a4[1]), a);
+ if n > 0 then
+ Result := a[1];
+ end
+ else
+ begin
+ a6[1] := StrToNetAddr6(IP);
+ n := ResolveAddress6(a6[1], a);
+ if n > 0 then
+ Result := a[1];
+ end;
+end;
+
+{=============================================================================}
+
+function InitSocketInterface(stack: string): Boolean;
+begin
+ SockEnhancedApi := False;
+ SockWship6Api := False;
+// Libc.Signal(Libc.SIGPIPE, TSignalHandler(Libc.SIG_IGN));
+ Result := True;
+end;
+
+function DestroySocketInterface: Boolean;
+begin
+ Result := True;
+end;
+
+initialization
+begin
+ SynSockCS := SyncObjs.TCriticalSection.Create;
+ SET_IN6_IF_ADDR_ANY (@in6addr_any);
+ SET_LOOPBACK_ADDR6 (@in6addr_loopback);
+end;
+
+finalization
+begin
+ SynSockCS.Free;
+end;
+
+{$ENDIF}
+
diff --git a/branches/script-component/Units/Synapse/ssl_cryptlib.pas b/branches/script-component/Units/Synapse/ssl_cryptlib.pas
new file mode 100644
index 0000000..84dd4d8
--- /dev/null
+++ b/branches/script-component/Units/Synapse/ssl_cryptlib.pas
@@ -0,0 +1,569 @@
+{==============================================================================|
+| Project : Ararat Synapse | 001.001.000 |
+|==============================================================================|
+| Content: SSL/SSH support by Peter Gutmann's CryptLib |
+|==============================================================================|
+| Copyright (c)1999-2005, Lukas Gebauer |
+| All rights reserved. |
+| |
+| Redistribution and use in source and binary forms, with or without |
+| modification, are permitted provided that the following conditions are met: |
+| |
+| Redistributions of source code must retain the above copyright notice, this |
+| list of conditions and the following disclaimer. |
+| |
+| Redistributions in binary form must reproduce the above copyright notice, |
+| this list of conditions and the following disclaimer in the documentation |
+| and/or other materials provided with the distribution. |
+| |
+| Neither the name of Lukas Gebauer nor the names of its contributors may |
+| be used to endorse or promote products derived from this software without |
+| specific prior written permission. |
+| |
+| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
+| AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
+| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
+| ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR |
+| ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
+| DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
+| SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
+| CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
+| LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
+| OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
+| DAMAGE. |
+|==============================================================================|
+| The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).|
+| Portions created by Lukas Gebauer are Copyright (c)2005. |
+| All Rights Reserved. |
+|==============================================================================|
+| Contributor(s): |
+|==============================================================================|
+| History: see HISTORY.HTM from distribution package |
+| (Found at URL: http://www.ararat.cz/synapse/) |
+|==============================================================================}
+
+{:@abstract(SSL/SSH plugin for CryptLib)
+
+This plugin requires cl32.dll at least version 3.2.0! It can be used on Win32
+and Linux. This library is staticly linked - when you compile your application
+with this plugin, you MUST distribute it with Cryptib library, otherwise you
+cannot run your application!
+
+It can work with keys and certificates stored as PKCS#15 only! It must be stored
+as disk file only, you cannot load them from memory! Each file can hold multiple
+keys and certificates. You must identify it by 'label' stored in
+@link(TSSLCryptLib.PrivateKeyLabel).
+
+If you need to use secure connection and authorize self by certificate
+(each SSL/TLS server or client with client authorization), then use
+@link(TCustomSSL.PrivateKeyFile), @link(TSSLCryptLib.PrivateKeyLabel) and
+@link(TCustomSSL.KeyPassword) properties.
+
+If you need to use server what verifying client certificates, then use
+@link(TCustomSSL.CertCAFile) as PKCS#15 file with public keyas of allowed clients. Clients
+with non-matching certificates will be rejected by cryptLib.
+
+This plugin is capable to create Ad-Hoc certificates. When you start SSL/TLS
+server without explicitly assigned key and certificate, then this plugin create
+Ad-Hoc key and certificate for each incomming connection by self. It slowdown
+accepting of new connections!
+
+You can use this plugin for SSHv2 connections too! You must explicitly set
+@link(TCustomSSL.SSLType) to value LT_SSHv2 and set @link(TCustomSSL.username)
+and @link(TCustomSSL.password). You can use special SSH channels too, see
+@link(TCustomSSL).
+}
+
+{$IFDEF FPC}
+ {$MODE DELPHI}
+{$ENDIF}
+{$H+}
+
+unit ssl_cryptlib;
+
+interface
+
+uses
+ SysUtils,
+ blcksock, synsock, synautil, synacode,
+ cryptlib;
+
+type
+ {:@abstract(class implementing CryptLib SSL/SSH plugin.)
+ Instance of this class will be created for each @link(TTCPBlockSocket).
+ You not need to create instance of this class, all is done by Synapse itself!}
+ TSSLCryptLib = class(TCustomSSL)
+ protected
+ FCryptSession: CRYPT_SESSION;
+ FPrivateKeyLabel: string;
+ FDelCert: Boolean;
+ FReadBuffer: string;
+ function SSLCheck(Value: integer): Boolean;
+ function Init(server:Boolean): Boolean;
+ function DeInit: Boolean;
+ function Prepare(server:Boolean): Boolean;
+ function GetString(const cryptHandle: CRYPT_HANDLE; const attributeType: CRYPT_ATTRIBUTE_TYPE): string;
+ function CreateSelfSignedCert(Host: string): Boolean; override;
+ function PopAll: string;
+ public
+ {:See @inherited}
+ constructor Create(const Value: TTCPBlockSocket); override;
+ destructor Destroy; override;
+ {:See @inherited}
+ function LibVersion: String; override;
+ {:See @inherited}
+ function LibName: String; override;
+ {:See @inherited}
+ procedure Assign(const Value: TCustomSSL); override;
+ {:See @inherited and @link(ssl_cryptlib) for more details.}
+ function Connect: boolean; override;
+ {:See @inherited and @link(ssl_cryptlib) for more details.}
+ function Accept: boolean; override;
+ {:See @inherited}
+ function Shutdown: boolean; override;
+ {:See @inherited}
+ function BiShutdown: boolean; override;
+ {:See @inherited}
+ function SendBuffer(Buffer: TMemory; Len: Integer): Integer; override;
+ {:See @inherited}
+ function RecvBuffer(Buffer: TMemory; Len: Integer): Integer; override;
+ {:See @inherited}
+ function WaitingData: Integer; override;
+ {:See @inherited}
+ function GetSSLVersion: string; override;
+ {:See @inherited}
+ function GetPeerSubject: string; override;
+ {:See @inherited}
+ function GetPeerIssuer: string; override;
+ {:See @inherited}
+ function GetPeerName: string; override;
+ {:See @inherited}
+ function GetPeerFingerprint: string; override;
+ published
+ {:name of certificate/key within PKCS#15 file. It can hold more then one
+ certificate/key and each certificate/key must have unique label within one file.}
+ property PrivateKeyLabel: string read FPrivateKeyLabel Write FPrivateKeyLabel;
+ end;
+
+implementation
+
+{==============================================================================}
+
+constructor TSSLCryptLib.Create(const Value: TTCPBlockSocket);
+begin
+ inherited Create(Value);
+ FcryptSession := CRYPT_SESSION(CRYPT_SESSION_NONE);
+ FPrivateKeyLabel := 'synapse';
+ FDelCert := false;
+end;
+
+destructor TSSLCryptLib.Destroy;
+begin
+ DeInit;
+ inherited Destroy;
+end;
+
+procedure TSSLCryptLib.Assign(const Value: TCustomSSL);
+begin
+ inherited Assign(Value);
+ if Value is TSSLCryptLib then
+ begin
+ FPrivateKeyLabel := TSSLCryptLib(Value).privatekeyLabel;
+ end;
+end;
+
+function TSSLCryptLib.GetString(const cryptHandle: CRYPT_HANDLE; const attributeType: CRYPT_ATTRIBUTE_TYPE): string;
+var
+ l: integer;
+begin
+ l := 0;
+ cryptGetAttributeString(cryptHandle, attributeType, nil, l);
+ setlength(Result, l);
+ cryptGetAttributeString(cryptHandle, attributeType, pointer(Result), l);
+ setlength(Result, l);
+end;
+
+function TSSLCryptLib.LibVersion: String;
+var
+ x: integer;
+begin
+ Result := GetString(CRYPT_UNUSED, CRYPT_OPTION_INFO_DESCRIPTION);
+ cryptGetAttribute(CRYPT_UNUSED, CRYPT_OPTION_INFO_MAJORVERSION, x);
+ Result := Result + ' v' + IntToStr(x);
+ cryptGetAttribute(CRYPT_UNUSED, CRYPT_OPTION_INFO_MINORVERSION, x);
+ Result := Result + '.' + IntToStr(x);
+ cryptGetAttribute(CRYPT_UNUSED, CRYPT_OPTION_INFO_STEPPING, x);
+ Result := Result + '.' + IntToStr(x);
+end;
+
+function TSSLCryptLib.LibName: String;
+begin
+ Result := 'ssl_cryptlib';
+end;
+
+function TSSLCryptLib.SSLCheck(Value: integer): Boolean;
+begin
+ Result := true;
+ FLastErrorDesc := '';
+ if Value = CRYPT_ERROR_COMPLETE then
+ Value := 0;
+ FLastError := Value;
+ if FLastError <> 0 then
+ begin
+ Result := False;
+ FLastErrorDesc := GetString(FCryptSession, CRYPT_ATTRIBUTE_INT_ERRORMESSAGE);
+ end;
+end;
+
+function TSSLCryptLib.CreateSelfSignedCert(Host: string): Boolean;
+var
+ privateKey: CRYPT_CONTEXT;
+ keyset: CRYPT_KEYSET;
+ cert: CRYPT_CERTIFICATE;
+ publicKey: CRYPT_CONTEXT;
+begin
+ Result := False;
+ if FPrivatekeyFile = '' then
+ FPrivatekeyFile := GetTempFile('', 'key');
+ cryptCreateContext(privateKey, CRYPT_UNUSED, CRYPT_ALGO_RSA);
+ cryptSetAttributeString(privateKey, CRYPT_CTXINFO_LABEL, Pointer(FPrivatekeyLabel),
+ Length(FPrivatekeyLabel));
+ cryptSetAttribute(privateKey, CRYPT_CTXINFO_KEYSIZE, 1024);
+ cryptGenerateKey(privateKey);
+ cryptKeysetOpen(keyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE, PChar(FPrivatekeyFile), CRYPT_KEYOPT_CREATE);
+ FDelCert := True;
+ cryptAddPrivateKey(keyset, privateKey, PChar(FKeyPassword));
+ cryptCreateCert(cert, CRYPT_UNUSED, CRYPT_CERTTYPE_CERTIFICATE);
+ cryptSetAttribute(cert, CRYPT_CERTINFO_XYZZY, 1);
+ cryptGetPublicKey(keyset, publicKey, CRYPT_KEYID_NAME, PChar(FPrivatekeyLabel));
+ cryptSetAttribute(cert, CRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, publicKey);
+ cryptSetAttributeString(cert, CRYPT_CERTINFO_COMMONNAME, Pointer(host), Length(host));
+ cryptSignCert(cert, privateKey);
+ cryptAddPublicKey(keyset, cert);
+ cryptKeysetClose(keyset);
+ cryptDestroyCert(cert);
+ cryptDestroyContext(privateKey);
+ cryptDestroyContext(publicKey);
+ Result := True;
+end;
+
+function TSSLCryptLib.PopAll: string;
+const
+ BufferMaxSize = 32768;
+var
+ Outbuffer: string;
+ WriteLen: integer;
+begin
+ Result := '';
+ repeat
+ setlength(outbuffer, BufferMaxSize);
+ Writelen := 0;
+ SSLCheck(CryptPopData(FCryptSession, @OutBuffer[1], BufferMaxSize, Writelen));
+ if FLastError <> 0 then
+ Break;
+ if WriteLen > 0 then
+ begin
+ setlength(outbuffer, WriteLen);
+ Result := Result + outbuffer;
+ end;
+ until WriteLen = 0;
+end;
+
+function TSSLCryptLib.Init(server:Boolean): Boolean;
+var
+ st: CRYPT_SESSION_TYPE;
+ keysetobj: CRYPT_KEYSET;
+ cryptContext: CRYPT_CONTEXT;
+ x: integer;
+begin
+ Result := False;
+ FLastErrorDesc := '';
+ FLastError := 0;
+ FDelCert := false;
+ FcryptSession := CRYPT_SESSION(CRYPT_SESSION_NONE);
+ if server then
+ case FSSLType of
+ LT_all, LT_SSLv3, LT_TLSv1, LT_TLSv1_1:
+ st := CRYPT_SESSION_SSL_SERVER;
+ LT_SSHv2:
+ st := CRYPT_SESSION_SSH_SERVER;
+ else
+ Exit;
+ end
+ else
+ case FSSLType of
+ LT_all, LT_SSLv3, LT_TLSv1, LT_TLSv1_1:
+ st := CRYPT_SESSION_SSL;
+ LT_SSHv2:
+ st := CRYPT_SESSION_SSH;
+ else
+ Exit;
+ end;
+ if not SSLCheck(cryptCreateSession(FcryptSession, CRYPT_UNUSED, st)) then
+ Exit;
+ x := -1;
+ case FSSLType of
+ LT_SSLv3:
+ x := 0;
+ LT_TLSv1:
+ x := 1;
+ LT_TLSv1_1:
+ x := 2;
+ end;
+ if x >= 0 then
+ if not SSLCheck(cryptSetAttribute(FCryptSession, CRYPT_SESSINFO_VERSION, x)) then
+ Exit;
+ if FUsername <> '' then
+ begin
+ cryptSetAttributeString(FcryptSession, CRYPT_SESSINFO_USERNAME,
+ Pointer(FUsername), Length(FUsername));
+ cryptSetAttributeString(FcryptSession, CRYPT_SESSINFO_PASSWORD,
+ Pointer(FPassword), Length(FPassword));
+ end;
+ if FSSLType = LT_SSHv2 then
+ if FSSHChannelType <> '' then
+ begin
+ cryptSetAttribute(FCryptSession, CRYPT_SESSINFO_SSH_CHANNEL, CRYPT_UNUSED);
+ cryptSetAttributeString(FCryptSession, CRYPT_SESSINFO_SSH_CHANNEL_TYPE,
+ Pointer(FSSHChannelType), Length(FSSHChannelType));
+ if FSSHChannelArg1 <> '' then
+ cryptSetAttributeString(FCryptSession, CRYPT_SESSINFO_SSH_CHANNEL_ARG1,
+ Pointer(FSSHChannelArg1), Length(FSSHChannelArg1));
+ if FSSHChannelArg2 <> '' then
+ cryptSetAttributeString(FCryptSession, CRYPT_SESSINFO_SSH_CHANNEL_ARG2,
+ Pointer(FSSHChannelArg2), Length(FSSHChannelArg2));
+ end;
+
+
+ if server and (FPrivatekeyFile = '') then
+ begin
+ if FPrivatekeyLabel = '' then
+ FPrivatekeyLabel := 'synapse';
+ if FkeyPassword = '' then
+ FkeyPassword := 'synapse';
+ CreateSelfSignedcert(FSocket.ResolveIPToName(FSocket.GetRemoteSinIP));
+ end;
+
+ if (FPrivatekeyLabel <> '') and (FPrivatekeyFile <> '') then
+ begin
+ if not SSLCheck(cryptKeysetOpen(KeySetObj, CRYPT_UNUSED, CRYPT_KEYSET_FILE,
+ PChar(FPrivatekeyFile), CRYPT_KEYOPT_READONLY)) then
+ Exit;
+ try
+ if not SSLCheck(cryptGetPrivateKey(KeySetObj, cryptcontext, CRYPT_KEYID_NAME,
+ PChar(FPrivatekeyLabel), PChar(FKeyPassword))) then
+ Exit;
+ if not SSLCheck(cryptSetAttribute(FcryptSession, CRYPT_SESSINFO_PRIVATEKEY,
+ cryptcontext)) then
+ Exit;
+ finally
+ cryptKeysetClose(keySetObj);
+ cryptDestroyContext(cryptcontext);
+ end;
+ end;
+ if server and FVerifyCert then
+ begin
+ if not SSLCheck(cryptKeysetOpen(KeySetObj, CRYPT_UNUSED, CRYPT_KEYSET_FILE,
+ PChar(FCertCAFile), CRYPT_KEYOPT_READONLY)) then
+ Exit;
+ try
+ if not SSLCheck(cryptSetAttribute(FcryptSession, CRYPT_SESSINFO_KEYSET,
+ keySetObj)) then
+ Exit;
+ finally
+ cryptKeysetClose(keySetObj);
+ end;
+ end;
+ Result := true;
+end;
+
+function TSSLCryptLib.DeInit: Boolean;
+begin
+ Result := True;
+ if FcryptSession <> CRYPT_SESSION(CRYPT_SESSION_NONE) then
+ CryptDestroySession(FcryptSession);
+ FcryptSession := CRYPT_SESSION(CRYPT_SESSION_NONE);
+ FSSLEnabled := False;
+ if FDelCert then
+ Deletefile(FPrivatekeyFile);
+end;
+
+function TSSLCryptLib.Prepare(server:Boolean): Boolean;
+begin
+ Result := false;
+ DeInit;
+ if Init(server) then
+ Result := true
+ else
+ DeInit;
+end;
+
+function TSSLCryptLib.Connect: boolean;
+begin
+ Result := False;
+ if FSocket.Socket = INVALID_SOCKET then
+ Exit;
+ if Prepare(false) then
+ begin
+ if not SSLCheck(cryptSetAttribute(FCryptSession, CRYPT_SESSINFO_NETWORKSOCKET, FSocket.Socket)) then
+ Exit;
+ if not SSLCheck(cryptSetAttribute(FCryptSession, CRYPT_SESSINFO_ACTIVE, 1)) then
+ Exit;
+ FSSLEnabled := True;
+ Result := True;
+ FReadBuffer := '';
+ end;
+end;
+
+function TSSLCryptLib.Accept: boolean;
+begin
+ Result := False;
+ if FSocket.Socket = INVALID_SOCKET then
+ Exit;
+ if Prepare(true) then
+ begin
+ if not SSLCheck(cryptSetAttribute(FCryptSession, CRYPT_SESSINFO_NETWORKSOCKET, FSocket.Socket)) then
+ Exit;
+ if not SSLCheck(cryptSetAttribute(FCryptSession, CRYPT_SESSINFO_ACTIVE, 1)) then
+ Exit;
+ FSSLEnabled := True;
+ Result := True;
+ FReadBuffer := '';
+ end;
+end;
+
+function TSSLCryptLib.Shutdown: boolean;
+begin
+ Result := BiShutdown;
+end;
+
+function TSSLCryptLib.BiShutdown: boolean;
+begin
+ if FcryptSession <> CRYPT_SESSION(CRYPT_SESSION_NONE) then
+ cryptSetAttribute(FCryptSession, CRYPT_SESSINFO_ACTIVE, 0);
+ DeInit;
+ FReadBuffer := '';
+ Result := True;
+end;
+
+function TSSLCryptLib.SendBuffer(Buffer: TMemory; Len: Integer): Integer;
+var
+ l: integer;
+begin
+ FLastError := 0;
+ FLastErrorDesc := '';
+ SSLCheck(cryptPushData(FCryptSession, Buffer, Len, L));
+ cryptFlushData(FcryptSession);
+ Result := l;
+end;
+
+function TSSLCryptLib.RecvBuffer(Buffer: TMemory; Len: Integer): Integer;
+var
+ l: integer;
+begin
+ FLastError := 0;
+ FLastErrorDesc := '';
+ if Length(FReadBuffer) = 0 then
+ FReadBuffer := PopAll;
+ if Len > Length(FReadBuffer) then
+ Len := Length(FReadBuffer);
+ Move(Pointer(FReadBuffer)^, buffer^, Len);
+ Delete(FReadBuffer, 1, Len);
+ Result := Len;
+end;
+
+function TSSLCryptLib.WaitingData: Integer;
+begin
+ Result := Length(FReadBuffer);
+end;
+
+function TSSLCryptLib.GetSSLVersion: string;
+var
+ x: integer;
+begin
+ Result := '';
+ if FcryptSession = CRYPT_SESSION(CRYPT_SESSION_NONE) then
+ Exit;
+ cryptGetAttribute(FCryptSession, CRYPT_SESSINFO_VERSION, x);
+ if FSSLType in [LT_SSLv3, LT_TLSv1, LT_TLSv1_1, LT_all] then
+ case x of
+ 0:
+ Result := 'SSLv3';
+ 1:
+ Result := 'TLSv1';
+ 2:
+ Result := 'TLSv1.1';
+ end;
+ if FSSLType in [LT_SSHv2] then
+ case x of
+ 0:
+ Result := 'SSHv1';
+ 1:
+ Result := 'SSHv2';
+ end;
+end;
+
+function TSSLCryptLib.GetPeerSubject: string;
+var
+ cert: CRYPT_CERTIFICATE;
+begin
+ Result := '';
+ if FcryptSession = CRYPT_SESSION(CRYPT_SESSION_NONE) then
+ Exit;
+ cryptGetAttribute(FCryptSession, CRYPT_SESSINFO_RESPONSE, cert);
+ cryptSetAttribute(cert, CRYPT_CERTINFO_SUBJECTNAME, CRYPT_UNUSED);
+ Result := GetString(cert, CRYPT_CERTINFO_DN);
+ cryptDestroyCert(cert);
+end;
+
+function TSSLCryptLib.GetPeerName: string;
+var
+ cert: CRYPT_CERTIFICATE;
+begin
+ Result := '';
+ if FcryptSession = CRYPT_SESSION(CRYPT_SESSION_NONE) then
+ Exit;
+ cryptGetAttribute(FCryptSession, CRYPT_SESSINFO_RESPONSE, cert);
+ cryptSetAttribute(cert, CRYPT_CERTINFO_ISSUERNAME, CRYPT_UNUSED);
+ Result := GetString(cert, CRYPT_CERTINFO_COMMONNAME);
+ cryptDestroyCert(cert);
+end;
+
+function TSSLCryptLib.GetPeerIssuer: string;
+var
+ cert: CRYPT_CERTIFICATE;
+begin
+ Result := '';
+ if FcryptSession = CRYPT_SESSION(CRYPT_SESSION_NONE) then
+ Exit;
+ cryptGetAttribute(FCryptSession, CRYPT_SESSINFO_RESPONSE, cert);
+ cryptSetAttribute(cert, CRYPT_CERTINFO_ISSUERNAME, CRYPT_UNUSED);
+ Result := GetString(cert, CRYPT_CERTINFO_DN);
+ cryptDestroyCert(cert);
+end;
+
+function TSSLCryptLib.GetPeerFingerprint: string;
+var
+ cert: CRYPT_CERTIFICATE;
+begin
+ Result := '';
+ if FcryptSession = CRYPT_SESSION(CRYPT_SESSION_NONE) then
+ Exit;
+ cryptGetAttribute(FCryptSession, CRYPT_SESSINFO_RESPONSE, cert);
+ Result := GetString(cert, CRYPT_CERTINFO_FINGERPRINT);
+ Result := MD5(Result);
+ cryptDestroyCert(cert);
+end;
+
+{==============================================================================}
+
+initialization
+ if cryptInit = CRYPT_OK then
+ SSLImplementation := TSSLCryptLib;
+ cryptAddRandom(nil, CRYPT_RANDOM_SLOWPOLL);
+
+finalization
+ cryptEnd;
+
+end.
+
diff --git a/branches/script-component/Units/Synapse/ssl_openssl.pas b/branches/script-component/Units/Synapse/ssl_openssl.pas
new file mode 100644
index 0000000..b3659f5
--- /dev/null
+++ b/branches/script-component/Units/Synapse/ssl_openssl.pas
@@ -0,0 +1,821 @@
+{==============================================================================|
+| Project : Ararat Synapse | 001.001.000 |
+|==============================================================================|
+| Content: SSL support by OpenSSL |
+|==============================================================================|
+| Copyright (c)1999-2008, Lukas Gebauer |
+| All rights reserved. |
+| |
+| Redistribution and use in source and binary forms, with or without |
+| modification, are permitted provided that the following conditions are met: |
+| |
+| Redistributions of source code must retain the above copyright notice, this |
+| list of conditions and the following disclaimer. |
+| |
+| Redistributions in binary form must reproduce the above copyright notice, |
+| this list of conditions and the following disclaimer in the documentation |
+| and/or other materials provided with the distribution. |
+| |
+| Neither the name of Lukas Gebauer nor the names of its contributors may |
+| be used to endorse or promote products derived from this software without |
+| specific prior written permission. |
+| |
+| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
+| AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
+| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
+| ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR |
+| ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
+| DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
+| SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
+| CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
+| LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
+| OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
+| DAMAGE. |
+|==============================================================================|
+| The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).|
+| Portions created by Lukas Gebauer are Copyright (c)2005-2008. |
+| All Rights Reserved. |
+|==============================================================================|
+| Contributor(s): |
+|==============================================================================|
+| History: see HISTORY.HTM from distribution package |
+| (Found at URL: http://www.ararat.cz/synapse/) |
+|==============================================================================}
+
+//requires OpenSSL libraries!
+
+{:@abstract(SSL plugin for OpenSSL)
+
+You need OpenSSL libraries version 0.9.7. It can work with 0.9.6 too, but
+application mysteriously crashing when you are using freePascal on Linux.
+Use Kylix on Linux is OK! If you have version 0.9.7 on Linux, then I not see
+any problems with FreePascal.
+
+OpenSSL libraries are loaded dynamicly - you not need OpenSSl librares even you
+compile your application with this unit. SSL just not working when you not have
+OpenSSL libraries.
+
+This plugin have limited support for .NET too! Because is not possible to use
+callbacks with CDECL calling convention under .NET, is not supported
+key/certificate passwords and multithread locking. :-(
+
+For handling keys and certificates you can use this properties:
+
+@link(TCustomSSL.CertificateFile) for PEM or ASN1 DER (cer) format. @br
+@link(TCustomSSL.Certificate) for ASN1 DER format only. @br
+@link(TCustomSSL.PrivateKeyFile) for PEM or ASN1 DER (key) format. @br
+@link(TCustomSSL.PrivateKey) for ASN1 DER format only. @br
+@link(TCustomSSL.CertCAFile) for PEM CA certificate bundle. @br
+@link(TCustomSSL.PFXFile) for PFX format. @br
+@link(TCustomSSL.PFX) for PFX format from binary string. @br
+
+This plugin is capable to create Ad-Hoc certificates. When you start SSL/TLS
+server without explicitly assigned key and certificate, then this plugin create
+Ad-Hoc key and certificate for each incomming connection by self. It slowdown
+accepting of new connections!
+}
+
+{$IFDEF FPC}
+ {$MODE DELPHI}
+{$ENDIF}
+{$H+}
+
+unit ssl_openssl;
+
+interface
+
+uses
+ SysUtils, Classes,
+ blcksock, synsock, synautil,
+{$IFDEF CIL}
+ System.Text,
+{$ENDIF}
+ ssl_openssl_lib;
+
+type
+ {:@abstract(class implementing OpenSSL SSL plugin.)
+ Instance of this class will be created for each @link(TTCPBlockSocket).
+ You not need to create instance of this class, all is done by Synapse itself!}
+ TSSLOpenSSL = class(TCustomSSL)
+ protected
+ FSsl: PSSL;
+ Fctx: PSSL_CTX;
+ function SSLCheck: Boolean;
+ function SetSslKeys: boolean;
+ function Init(server:Boolean): Boolean;
+ function DeInit: Boolean;
+ function Prepare(server:Boolean): Boolean;
+ function LoadPFX(pfxdata: ansistring): Boolean;
+ function CreateSelfSignedCert(Host: string): Boolean; override;
+ public
+ {:See @inherited}
+ constructor Create(const Value: TTCPBlockSocket); override;
+ destructor Destroy; override;
+ {:See @inherited}
+ function LibVersion: String; override;
+ {:See @inherited}
+ function LibName: String; override;
+ {:See @inherited and @link(ssl_cryptlib) for more details.}
+ function Connect: boolean; override;
+ {:See @inherited and @link(ssl_cryptlib) for more details.}
+ function Accept: boolean; override;
+ {:See @inherited}
+ function Shutdown: boolean; override;
+ {:See @inherited}
+ function BiShutdown: boolean; override;
+ {:See @inherited}
+ function SendBuffer(Buffer: TMemory; Len: Integer): Integer; override;
+ {:See @inherited}
+ function RecvBuffer(Buffer: TMemory; Len: Integer): Integer; override;
+ {:See @inherited}
+ function WaitingData: Integer; override;
+ {:See @inherited}
+ function GetSSLVersion: string; override;
+ {:See @inherited}
+ function GetPeerSubject: string; override;
+ {:See @inherited}
+ function GetPeerIssuer: string; override;
+ {:See @inherited}
+ function GetPeerName: string; override;
+ {:See @inherited}
+ function GetPeerFingerprint: string; override;
+ {:See @inherited}
+ function GetCertInfo: string; override;
+ {:See @inherited}
+ function GetCipherName: string; override;
+ {:See @inherited}
+ function GetCipherBits: integer; override;
+ {:See @inherited}
+ function GetCipherAlgBits: integer; override;
+ {:See @inherited}
+ function GetVerifyCert: integer; override;
+ end;
+
+implementation
+
+{==============================================================================}
+
+{$IFNDEF CIL}
+function PasswordCallback(buf:PAnsiChar; size:Integer; rwflag:Integer; userdata: Pointer):Integer; cdecl;
+var
+ Password: AnsiString;
+begin
+ Password := '';
+ if TCustomSSL(userdata) is TCustomSSL then
+ Password := TCustomSSL(userdata).KeyPassword;
+ if Length(Password) > (Size - 1) then
+ SetLength(Password, Size - 1);
+ Result := Length(Password);
+ StrLCopy(buf, PAnsiChar(Password + #0), Result + 1);
+end;
+{$ENDIF}
+
+{==============================================================================}
+
+constructor TSSLOpenSSL.Create(const Value: TTCPBlockSocket);
+begin
+ inherited Create(Value);
+ FCiphers := 'DEFAULT';
+ FSsl := nil;
+ Fctx := nil;
+end;
+
+destructor TSSLOpenSSL.Destroy;
+begin
+ DeInit;
+ inherited Destroy;
+end;
+
+function TSSLOpenSSL.LibVersion: String;
+begin
+ Result := SSLeayversion(0);
+end;
+
+function TSSLOpenSSL.LibName: String;
+begin
+ Result := 'ssl_openssl';
+end;
+
+function TSSLOpenSSL.SSLCheck: Boolean;
+var
+{$IFDEF CIL}
+ sb: StringBuilder;
+{$ENDIF}
+ s : AnsiString;
+begin
+ Result := true;
+ FLastErrorDesc := '';
+ FLastError := ErrGetError;
+ ErrClearError;
+ if FLastError <> 0 then
+ begin
+ Result := False;
+{$IFDEF CIL}
+ sb := StringBuilder.Create(256);
+ ErrErrorString(FLastError, sb, 256);
+ FLastErrorDesc := Trim(sb.ToString);
+{$ELSE}
+ s := StringOfChar(#0, 256);
+ ErrErrorString(FLastError, s, Length(s));
+ FLastErrorDesc := s;
+{$ENDIF}
+ end;
+end;
+
+function TSSLOpenSSL.CreateSelfSignedCert(Host: string): Boolean;
+var
+ pk: EVP_PKEY;
+ x: PX509;
+ rsa: PRSA;
+ t: PASN1_UTCTIME;
+ name: PX509_NAME;
+ b: PBIO;
+ xn, y: integer;
+ s: AnsiString;
+{$IFDEF CIL}
+ sb: StringBuilder;
+{$ENDIF}
+begin
+ Result := True;
+ pk := EvpPkeynew;
+ x := X509New;
+ try
+ rsa := RsaGenerateKey(1024, $10001, nil, nil);
+ EvpPkeyAssign(pk, EVP_PKEY_RSA, rsa);
+ X509SetVersion(x, 2);
+ Asn1IntegerSet(X509getSerialNumber(x), 0);
+ t := Asn1UtctimeNew;
+ try
+ X509GmtimeAdj(t, -60 * 60 *24);
+ X509SetNotBefore(x, t);
+ X509GmtimeAdj(t, 60 * 60 * 60 *24);
+ X509SetNotAfter(x, t);
+ finally
+ Asn1UtctimeFree(t);
+ end;
+ X509SetPubkey(x, pk);
+ Name := X509GetSubjectName(x);
+ X509NameAddEntryByTxt(Name, 'C', $1001, 'CZ', -1, -1, 0);
+ X509NameAddEntryByTxt(Name, 'CN', $1001, host, -1, -1, 0);
+ x509SetIssuerName(x, Name);
+ x509Sign(x, pk, EvpGetDigestByName('SHA1'));
+ b := BioNew(BioSMem);
+ try
+ i2dX509Bio(b, x);
+ xn := bioctrlpending(b);
+{$IFDEF CIL}
+ sb := StringBuilder.Create(xn);
+ y := bioread(b, sb, xn);
+ if y > 0 then
+ begin
+ sb.Length := y;
+ s := sb.ToString;
+ end;
+{$ELSE}
+ setlength(s, xn);
+ y := bioread(b, s, xn);
+ if y > 0 then
+ setlength(s, y);
+{$ENDIF}
+ finally
+ BioFreeAll(b);
+ end;
+ FCertificate := s;
+ b := BioNew(BioSMem);
+ try
+ i2dPrivatekeyBio(b, pk);
+ xn := bioctrlpending(b);
+{$IFDEF CIL}
+ sb := StringBuilder.Create(xn);
+ y := bioread(b, sb, xn);
+ if y > 0 then
+ begin
+ sb.Length := y;
+ s := sb.ToString;
+ end;
+{$ELSE}
+ setlength(s, xn);
+ y := bioread(b, s, xn);
+ if y > 0 then
+ setlength(s, y);
+{$ENDIF}
+ finally
+ BioFreeAll(b);
+ end;
+ FPrivatekey := s;
+ finally
+ X509free(x);
+ EvpPkeyFree(pk);
+ end;
+end;
+
+function TSSLOpenSSL.LoadPFX(pfxdata: Ansistring): Boolean;
+var
+ cert, pkey, ca: SslPtr;
+ b: PBIO;
+ p12: SslPtr;
+begin
+ Result := False;
+ b := BioNew(BioSMem);
+ try
+ BioWrite(b, pfxdata, Length(PfxData));
+ p12 := d2iPKCS12bio(b, nil);
+ if not Assigned(p12) then
+ Exit;
+ try
+ cert := nil;
+ pkey := nil;
+ ca := nil;
+ if PKCS12parse(p12, FKeyPassword, pkey, cert, ca) > 0 then
+ if SSLCTXusecertificate(Fctx, cert) > 0 then
+ if SSLCTXusePrivateKey(Fctx, pkey) > 0 then
+ Result := True;
+ finally
+ PKCS12free(p12);
+ end;
+ finally
+ BioFreeAll(b);
+ end;
+end;
+
+function TSSLOpenSSL.SetSslKeys: boolean;
+var
+ st: TFileStream;
+ s: string;
+begin
+ Result := False;
+ if not assigned(FCtx) then
+ Exit;
+ try
+ if FCertificateFile <> '' then
+ if SslCtxUseCertificateChainFile(FCtx, FCertificateFile) <> 1 then
+ if SslCtxUseCertificateFile(FCtx, FCertificateFile, SSL_FILETYPE_PEM) <> 1 then
+ if SslCtxUseCertificateFile(FCtx, FCertificateFile, SSL_FILETYPE_ASN1) <> 1 then
+ Exit;
+ if FCertificate <> '' then
+ if SslCtxUseCertificateASN1(FCtx, length(FCertificate), FCertificate) <> 1 then
+ Exit;
+ SSLCheck;
+ if FPrivateKeyFile <> '' then
+ if SslCtxUsePrivateKeyFile(FCtx, FPrivateKeyFile, SSL_FILETYPE_PEM) <> 1 then
+ if SslCtxUsePrivateKeyFile(FCtx, FPrivateKeyFile, SSL_FILETYPE_ASN1) <> 1 then
+ Exit;
+ if FPrivateKey <> '' then
+ if SslCtxUsePrivateKeyASN1(EVP_PKEY_RSA, FCtx, FPrivateKey, length(FPrivateKey)) <> 1 then
+ Exit;
+ SSLCheck;
+ if FCertCAFile <> '' then
+ if SslCtxLoadVerifyLocations(FCtx, FCertCAFile, '') <> 1 then
+ Exit;
+ if FPFXfile <> '' then
+ begin
+ try
+ st := TFileStream.Create(FPFXfile, fmOpenRead or fmShareDenyNone);
+ try
+ s := ReadStrFromStream(st, st.Size);
+ finally
+ st.Free;
+ end;
+ if not LoadPFX(s) then
+ Exit;
+ except
+ on Exception do
+ Exit;
+ end;
+ end;
+ if FPFX <> '' then
+ if not LoadPFX(FPfx) then
+ Exit;
+ SSLCheck;
+ Result := True;
+ finally
+ SSLCheck;
+ end;
+end;
+
+function TSSLOpenSSL.Init(server:Boolean): Boolean;
+var
+ s: AnsiString;
+begin
+ Result := False;
+ FLastErrorDesc := '';
+ FLastError := 0;
+ Fctx := nil;
+ case FSSLType of
+ LT_SSLv2:
+ Fctx := SslCtxNew(SslMethodV2);
+ LT_SSLv3:
+ Fctx := SslCtxNew(SslMethodV3);
+ LT_TLSv1:
+ Fctx := SslCtxNew(SslMethodTLSV1);
+ LT_all:
+ Fctx := SslCtxNew(SslMethodV23);
+ else
+ Exit;
+ end;
+ if Fctx = nil then
+ begin
+ SSLCheck;
+ Exit;
+ end
+ else
+ begin
+ s := FCiphers;
+ SslCtxSetCipherList(Fctx, s);
+ if FVerifyCert then
+ SslCtxSetVerify(FCtx, SSL_VERIFY_PEER, nil)
+ else
+ SslCtxSetVerify(FCtx, SSL_VERIFY_NONE, nil);
+{$IFNDEF CIL}
+ SslCtxSetDefaultPasswdCb(FCtx, @PasswordCallback);
+ SslCtxSetDefaultPasswdCbUserdata(FCtx, self);
+{$ENDIF}
+
+ if server and (FCertificateFile = '') and (FCertificate = '')
+ and (FPFXfile = '') and (FPFX = '') then
+ begin
+ CreateSelfSignedcert(FSocket.ResolveIPToName(FSocket.GetRemoteSinIP));
+ end;
+
+ if not SetSSLKeys then
+ Exit
+ else
+ begin
+ Fssl := nil;
+ Fssl := SslNew(Fctx);
+ if Fssl = nil then
+ begin
+ SSLCheck;
+ exit;
+ end;
+ end;
+ end;
+ Result := true;
+end;
+
+function TSSLOpenSSL.DeInit: Boolean;
+begin
+ Result := True;
+ if assigned (Fssl) then
+ sslfree(Fssl);
+ Fssl := nil;
+ if assigned (Fctx) then
+ begin
+ SslCtxFree(Fctx);
+ Fctx := nil;
+ ErrRemoveState(0);
+ end;
+ FSSLEnabled := False;
+end;
+
+function TSSLOpenSSL.Prepare(server:Boolean): Boolean;
+begin
+ Result := false;
+ DeInit;
+ if Init(server) then
+ Result := true
+ else
+ DeInit;
+end;
+
+function TSSLOpenSSL.Connect: boolean;
+var
+ x: integer;
+begin
+ Result := False;
+ if FSocket.Socket = INVALID_SOCKET then
+ Exit;
+ if Prepare(False) then
+ begin
+{$IFDEF CIL}
+ if sslsetfd(FSsl, FSocket.Socket.Handle.ToInt32) < 1 then
+{$ELSE}
+ if sslsetfd(FSsl, FSocket.Socket) < 1 then
+{$ENDIF}
+ begin
+ SSLCheck;
+ Exit;
+ end;
+ x := sslconnect(FSsl);
+ if x < 1 then
+ begin
+ SSLcheck;
+ Exit;
+ end;
+ if FverifyCert then
+ if GetVerifyCert <> 0 then
+ Exit;
+ FSSLEnabled := True;
+ Result := True;
+ end;
+end;
+
+function TSSLOpenSSL.Accept: boolean;
+var
+ x: integer;
+begin
+ Result := False;
+ if FSocket.Socket = INVALID_SOCKET then
+ Exit;
+ if Prepare(True) then
+ begin
+{$IFDEF CIL}
+ if sslsetfd(FSsl, FSocket.Socket.Handle.ToInt32) < 1 then
+{$ELSE}
+ if sslsetfd(FSsl, FSocket.Socket) < 1 then
+{$ENDIF}
+ begin
+ SSLCheck;
+ Exit;
+ end;
+ x := sslAccept(FSsl);
+ if x < 1 then
+ begin
+ SSLcheck;
+ Exit;
+ end;
+ FSSLEnabled := True;
+ Result := True;
+ end;
+end;
+
+function TSSLOpenSSL.Shutdown: boolean;
+begin
+ if assigned(FSsl) then
+ sslshutdown(FSsl);
+ DeInit;
+ Result := True;
+end;
+
+function TSSLOpenSSL.BiShutdown: boolean;
+var
+ x: integer;
+begin
+ if assigned(FSsl) then
+ begin
+ x := sslshutdown(FSsl);
+ if x = 0 then
+ begin
+ Synsock.Shutdown(FSocket.Socket, 1);
+ sslshutdown(FSsl);
+ end;
+ end;
+ DeInit;
+ Result := True;
+end;
+
+function TSSLOpenSSL.SendBuffer(Buffer: TMemory; Len: Integer): Integer;
+var
+ err: integer;
+{$IFDEF CIL}
+ s: ansistring;
+{$ENDIF}
+begin
+ FLastError := 0;
+ FLastErrorDesc := '';
+ repeat
+{$IFDEF CIL}
+ s := StringOf(Buffer);
+ Result := SslWrite(FSsl, s, Len);
+{$ELSE}
+ Result := SslWrite(FSsl, Buffer , Len);
+{$ENDIF}
+ err := SslGetError(FSsl, Result);
+ until (err <> SSL_ERROR_WANT_READ) and (err <> SSL_ERROR_WANT_WRITE);
+ if err = SSL_ERROR_ZERO_RETURN then
+ Result := 0
+ else
+ if (err <> 0) then
+ FLastError := err;
+end;
+
+function TSSLOpenSSL.RecvBuffer(Buffer: TMemory; Len: Integer): Integer;
+var
+ err: integer;
+{$IFDEF CIL}
+ sb: stringbuilder;
+ s: ansistring;
+{$ENDIF}
+begin
+ FLastError := 0;
+ FLastErrorDesc := '';
+ repeat
+{$IFDEF CIL}
+ sb := StringBuilder.Create(Len);
+ Result := SslRead(FSsl, sb, Len);
+ if Result > 0 then
+ begin
+ sb.Length := Result;
+ s := sb.ToString;
+ System.Array.Copy(BytesOf(s), Buffer, length(s));
+ end;
+{$ELSE}
+ Result := SslRead(FSsl, Buffer , Len);
+{$ENDIF}
+ err := SslGetError(FSsl, Result);
+ until (err <> SSL_ERROR_WANT_READ) and (err <> SSL_ERROR_WANT_WRITE);
+ if err = SSL_ERROR_ZERO_RETURN then
+ Result := 0
+ else
+ if (err <> 0) then
+ FLastError := err;
+end;
+
+function TSSLOpenSSL.WaitingData: Integer;
+begin
+ Result := sslpending(Fssl);
+end;
+
+function TSSLOpenSSL.GetSSLVersion: string;
+begin
+ if not assigned(FSsl) then
+ Result := ''
+ else
+ Result := SSlGetVersion(FSsl);
+end;
+
+function TSSLOpenSSL.GetPeerSubject: string;
+var
+ cert: PX509;
+ s: ansistring;
+{$IFDEF CIL}
+ sb: StringBuilder;
+{$ENDIF}
+begin
+ if not assigned(FSsl) then
+ begin
+ Result := '';
+ Exit;
+ end;
+ cert := SSLGetPeerCertificate(Fssl);
+ if not assigned(cert) then
+ begin
+ Result := '';
+ Exit;
+ end;
+{$IFDEF CIL}
+ sb := StringBuilder.Create(4096);
+ Result := X509NameOneline(X509GetSubjectName(cert), sb, 4096);
+{$ELSE}
+ setlength(s, 4096);
+ Result := X509NameOneline(X509GetSubjectName(cert), s, Length(s));
+{$ENDIF}
+ X509Free(cert);
+end;
+
+function TSSLOpenSSL.GetPeerName: string;
+var
+ s: ansistring;
+begin
+ s := GetPeerSubject;
+ s := SeparateRight(s, '/CN=');
+ Result := Trim(SeparateLeft(s, '/'));
+end;
+
+function TSSLOpenSSL.GetPeerIssuer: string;
+var
+ cert: PX509;
+ s: ansistring;
+{$IFDEF CIL}
+ sb: StringBuilder;
+{$ENDIF}
+begin
+ if not assigned(FSsl) then
+ begin
+ Result := '';
+ Exit;
+ end;
+ cert := SSLGetPeerCertificate(Fssl);
+ if not assigned(cert) then
+ begin
+ Result := '';
+ Exit;
+ end;
+{$IFDEF CIL}
+ sb := StringBuilder.Create(4096);
+ Result := X509NameOneline(X509GetIssuerName(cert), sb, 4096);
+{$ELSE}
+ setlength(s, 4096);
+ Result := X509NameOneline(X509GetIssuerName(cert), s, Length(s));
+{$ENDIF}
+ X509Free(cert);
+end;
+
+function TSSLOpenSSL.GetPeerFingerprint: string;
+var
+ cert: PX509;
+ x: integer;
+{$IFDEF CIL}
+ sb: StringBuilder;
+{$ENDIF}
+begin
+ if not assigned(FSsl) then
+ begin
+ Result := '';
+ Exit;
+ end;
+ cert := SSLGetPeerCertificate(Fssl);
+ if not assigned(cert) then
+ begin
+ Result := '';
+ Exit;
+ end;
+{$IFDEF CIL}
+ sb := StringBuilder.Create(EVP_MAX_MD_SIZE);
+ X509Digest(cert, EvpGetDigestByName('MD5'), sb, x);
+ sb.Length := x;
+ Result := sb.ToString;
+{$ELSE}
+ setlength(Result, EVP_MAX_MD_SIZE);
+ X509Digest(cert, EvpGetDigestByName('MD5'), Result, x);
+ SetLength(Result, x);
+{$ENDIF}
+ X509Free(cert);
+end;
+
+function TSSLOpenSSL.GetCertInfo: string;
+var
+ cert: PX509;
+ x, y: integer;
+ b: PBIO;
+ s: AnsiString;
+{$IFDEF CIL}
+ sb: stringbuilder;
+{$ENDIF}
+begin
+ if not assigned(FSsl) then
+ begin
+ Result := '';
+ Exit;
+ end;
+ cert := SSLGetPeerCertificate(Fssl);
+ if not assigned(cert) then
+ begin
+ Result := '';
+ Exit;
+ end;
+ b := BioNew(BioSMem);
+ try
+ X509Print(b, cert);
+ x := bioctrlpending(b);
+{$IFDEF CIL}
+ sb := StringBuilder.Create(x);
+ y := bioread(b, sb, x);
+ if y > 0 then
+ begin
+ sb.Length := y;
+ s := sb.ToString;
+ end;
+{$ELSE}
+ setlength(s,x);
+ y := bioread(b,s,x);
+ if y > 0 then
+ setlength(s, y);
+{$ENDIF}
+ Result := ReplaceString(s, LF, CRLF);
+ finally
+ BioFreeAll(b);
+ end;
+end;
+
+function TSSLOpenSSL.GetCipherName: string;
+begin
+ if not assigned(FSsl) then
+ Result := ''
+ else
+ Result := SslCipherGetName(SslGetCurrentCipher(FSsl));
+end;
+
+function TSSLOpenSSL.GetCipherBits: integer;
+var
+ x: integer;
+begin
+ if not assigned(FSsl) then
+ Result := 0
+ else
+ Result := SSLCipherGetBits(SslGetCurrentCipher(FSsl), x);
+end;
+
+function TSSLOpenSSL.GetCipherAlgBits: integer;
+begin
+ if not assigned(FSsl) then
+ Result := 0
+ else
+ SSLCipherGetBits(SslGetCurrentCipher(FSsl), Result);
+end;
+
+function TSSLOpenSSL.GetVerifyCert: integer;
+begin
+ if not assigned(FSsl) then
+ Result := 1
+ else
+ Result := SslGetVerifyResult(FSsl);
+end;
+
+{==============================================================================}
+
+initialization
+ if InitSSLInterface then
+ SSLImplementation := TSSLOpenSSL;
+
+end.
diff --git a/branches/script-component/Units/Synapse/ssl_openssl_lib.pas b/branches/script-component/Units/Synapse/ssl_openssl_lib.pas
new file mode 100644
index 0000000..23d33ec
--- /dev/null
+++ b/branches/script-component/Units/Synapse/ssl_openssl_lib.pas
@@ -0,0 +1,2018 @@
+{==============================================================================|
+| Project : Ararat Synapse | 003.005.000 |
+|==============================================================================|
+| Content: SSL support by OpenSSL |
+|==============================================================================|
+| Copyright (c)1999-2008, Lukas Gebauer |
+| All rights reserved. |
+| |
+| Redistribution and use in source and binary forms, with or without |
+| modification, are permitted provided that the following conditions are met: |
+| |
+| Redistributions of source code must retain the above copyright notice, this |
+| list of conditions and the following disclaimer. |
+| |
+| Redistributions in binary form must reproduce the above copyright notice, |
+| this list of conditions and the following disclaimer in the documentation |
+| and/or other materials provided with the distribution. |
+| |
+| Neither the name of Lukas Gebauer nor the names of its contributors may |
+| be used to endorse or promote products derived from this software without |
+| specific prior written permission. |
+| |
+| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
+| AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
+| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
+| ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR |
+| ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
+| DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
+| SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
+| CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
+| LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
+| OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
+| DAMAGE. |
+|==============================================================================|
+| The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).|
+| Portions created by Lukas Gebauer are Copyright (c)2002-2008. |
+| All Rights Reserved. |
+|==============================================================================|
+| Contributor(s): |
+|==============================================================================|
+| History: see HISTORY.HTM from distribution package |
+| (Found at URL: http://www.ararat.cz/synapse/) |
+|==============================================================================}
+
+{
+Special thanks to Gregor Ibic
+ (Intelicom d.o.o., http://www.intelicom.si)
+ for good inspiration about begin with SSL programming.
+}
+
+{$IFDEF FPC}
+ {$MODE DELPHI}
+{$ENDIF}
+{$H+}
+{$IFDEF VER125}
+ {$DEFINE BCB}
+{$ENDIF}
+{$IFDEF BCB}
+ {$ObjExportAll On}
+ (*$HPPEMIT 'namespace ssl_openssl_lib { using System::Shortint; }' *)
+{$ENDIF}
+
+{:@abstract(OpenSSL support)
+
+This unit is Pascal interface to OpenSSL library (used by @link(ssl_openssl) unit).
+OpenSSL is loaded dynamicly on-demand. If this library is not found in system,
+requested OpenSSL function just return errorcode.
+}
+unit ssl_openssl_lib;
+
+interface
+
+uses
+{$IFDEF CIL}
+ System.Runtime.InteropServices,
+ System.Text,
+{$ENDIF}
+ Classes,
+ synafpc,
+{$IFNDEF WIN32}
+ Libc, SysUtils;
+{$ELSE}
+ Windows;
+{$ENDIF}
+
+
+{$IFDEF CIL}
+const
+ {$IFDEF LINUX}
+ DLLSSLName = 'libssl.so';
+ DLLUtilName = 'libcrypto.so';
+ {$ELSE}
+ DLLSSLName = 'ssleay32.dll';
+ DLLUtilName = 'libeay32.dll';
+ {$ENDIF}
+{$ELSE}
+var
+ {$IFNDEF WIN32}
+ DLLSSLName: string = 'libssl.so';
+ DLLUtilName: string = 'libcrypto.so';
+ {$ELSE}
+ DLLSSLName: string = 'ssleay32.dll';
+ DLLSSLName2: string = 'libssl32.dll';
+ DLLUtilName: string = 'libeay32.dll';
+ {$ENDIF}
+{$ENDIF}
+
+type
+{$IFDEF CIL}
+ SslPtr = IntPtr;
+{$ELSE}
+ SslPtr = Pointer;
+{$ENDIF}
+ PSslPtr = ^SslPtr;
+ PSSL_CTX = SslPtr;
+ PSSL = SslPtr;
+ PSSL_METHOD = SslPtr;
+ PX509 = SslPtr;
+ PX509_NAME = SslPtr;
+ PEVP_MD = SslPtr;
+ PInteger = ^Integer;
+ PBIO_METHOD = SslPtr;
+ PBIO = SslPtr;
+ EVP_PKEY = SslPtr;
+ PRSA = SslPtr;
+ PASN1_UTCTIME = SslPtr;
+ PASN1_INTEGER = SslPtr;
+ PPasswdCb = SslPtr;
+ PFunction = procedure;
+
+ DES_cblock = array[0..7] of Byte;
+ PDES_cblock = ^DES_cblock;
+ des_ks_struct = packed record
+ ks: DES_cblock;
+ weak_key: Integer;
+ end;
+ des_key_schedule = array[1..16] of des_ks_struct;
+
+const
+ EVP_MAX_MD_SIZE = 16 + 20;
+
+ SSL_ERROR_NONE = 0;
+ SSL_ERROR_SSL = 1;
+ SSL_ERROR_WANT_READ = 2;
+ SSL_ERROR_WANT_WRITE = 3;
+ SSL_ERROR_WANT_X509_LOOKUP = 4;
+ SSL_ERROR_SYSCALL = 5; //look at error stack/return value/errno
+ SSL_ERROR_ZERO_RETURN = 6;
+ SSL_ERROR_WANT_CONNECT = 7;
+ SSL_ERROR_WANT_ACCEPT = 8;
+
+ SSL_OP_NO_SSLv2 = $01000000;
+ SSL_OP_NO_SSLv3 = $02000000;
+ SSL_OP_NO_TLSv1 = $04000000;
+ SSL_OP_ALL = $000FFFFF;
+ SSL_VERIFY_NONE = $00;
+ SSL_VERIFY_PEER = $01;
+
+ OPENSSL_DES_DECRYPT = 0;
+ OPENSSL_DES_ENCRYPT = 1;
+
+ X509_V_OK = 0;
+ X509_V_ILLEGAL = 1;
+ X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT = 2;
+ X509_V_ERR_UNABLE_TO_GET_CRL = 3;
+ X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE = 4;
+ X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE = 5;
+ X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY = 6;
+ X509_V_ERR_CERT_SIGNATURE_FAILURE = 7;
+ X509_V_ERR_CRL_SIGNATURE_FAILURE = 8;
+ X509_V_ERR_CERT_NOT_YET_VALID = 9;
+ X509_V_ERR_CERT_HAS_EXPIRED = 10;
+ X509_V_ERR_CRL_NOT_YET_VALID = 11;
+ X509_V_ERR_CRL_HAS_EXPIRED = 12;
+ X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD = 13;
+ X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD = 14;
+ X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD = 15;
+ X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD = 16;
+ X509_V_ERR_OUT_OF_MEM = 17;
+ X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT = 18;
+ X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN = 19;
+ X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY = 20;
+ X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE = 21;
+ X509_V_ERR_CERT_CHAIN_TOO_LONG = 22;
+ X509_V_ERR_CERT_REVOKED = 23;
+ X509_V_ERR_INVALID_CA = 24;
+ X509_V_ERR_PATH_LENGTH_EXCEEDED = 25;
+ X509_V_ERR_INVALID_PURPOSE = 26;
+ X509_V_ERR_CERT_UNTRUSTED = 27;
+ X509_V_ERR_CERT_REJECTED = 28;
+ //These are 'informational' when looking for issuer cert
+ X509_V_ERR_SUBJECT_ISSUER_MISMATCH = 29;
+ X509_V_ERR_AKID_SKID_MISMATCH = 30;
+ X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH = 31;
+ X509_V_ERR_KEYUSAGE_NO_CERTSIGN = 32;
+ X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER = 33;
+ X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION = 34;
+ //The application is not happy
+ X509_V_ERR_APPLICATION_VERIFICATION = 50;
+
+ SSL_FILETYPE_ASN1 = 2;
+ SSL_FILETYPE_PEM = 1;
+ EVP_PKEY_RSA = 6;
+
+var
+ SSLLibHandle: TLibHandle = 0;
+ SSLUtilHandle: TLibHandle = 0;
+ SSLLibFile: string = '';
+ SSLUtilFile: string = '';
+
+{$IFDEF CIL}
+ [DllImport(DLLSSLName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'SSL_get_error')]
+ function SslGetError(s: PSSL; ret_code: Integer): Integer; external;
+
+ [DllImport(DLLSSLName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'SSL_library_init')]
+ function SslLibraryInit: Integer; external;
+
+ [DllImport(DLLSSLName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'SSL_load_error_strings')]
+ procedure SslLoadErrorStrings; external;
+
+ [DllImport(DLLSSLName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'SSL_CTX_set_cipher_list')]
+ function SslCtxSetCipherList(arg0: PSSL_CTX; var str: String): Integer; external;
+
+ [DllImport(DLLSSLName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'SSL_CTX_new')]
+ function SslCtxNew(meth: PSSL_METHOD):PSSL_CTX; external;
+
+ [DllImport(DLLSSLName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'SSL_CTX_free')]
+ procedure SslCtxFree (arg0: PSSL_CTX); external;
+
+ [DllImport(DLLSSLName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'SSL_set_fd')]
+ function SslSetFd(s: PSSL; fd: Integer):Integer; external;
+
+ [DllImport(DLLSSLName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'SSLv2_method')]
+ function SslMethodV2 : PSSL_METHOD; external;
+
+ [DllImport(DLLSSLName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'SSLv3_method')]
+ function SslMethodV3 : PSSL_METHOD; external;
+
+ [DllImport(DLLSSLName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'TLSv1_method')]
+ function SslMethodTLSV1:PSSL_METHOD; external;
+
+ [DllImport(DLLSSLName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'SSLv23_method')]
+ function SslMethodV23 : PSSL_METHOD; external;
+
+ [DllImport(DLLSSLName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'SSL_CTX_use_PrivateKey')]
+ function SslCtxUsePrivateKey(ctx: PSSL_CTX; pkey: SslPtr):Integer; external;
+
+ [DllImport(DLLSSLName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'SSL_CTX_use_PrivateKey_ASN1')]
+ function SslCtxUsePrivateKeyASN1(pk: integer; ctx: PSSL_CTX; d: String; len: integer):Integer; external;
+
+ [DllImport(DLLSSLName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'SSL_CTX_use_RSAPrivateKey_file')]
+ function SslCtxUsePrivateKeyFile(ctx: PSSL_CTX; const _file: String; _type: Integer):Integer; external;
+
+ [DllImport(DLLSSLName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'SSL_CTX_use_certificate')]
+ function SslCtxUseCertificate(ctx: PSSL_CTX; x: SslPtr):Integer; external;
+
+ [DllImport(DLLSSLName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'SSL_CTX_use_certificate_ASN1')]
+ function SslCtxUseCertificateASN1(ctx: PSSL_CTX; len: integer; d: String):Integer; external;
+
+ [DllImport(DLLSSLName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'SSL_CTX_use_certificate_file')]
+ function SslCtxUseCertificateFile(ctx: PSSL_CTX; const _file: String; _type: Integer):Integer;external;
+
+ [DllImport(DLLSSLName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'SSL_CTX_use_certificate_chain_file')]
+ function SslCtxUseCertificateChainFile(ctx: PSSL_CTX; const _file: String):Integer;external;
+
+ [DllImport(DLLSSLName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'SSL_CTX_check_private_key')]
+ function SslCtxCheckPrivateKeyFile(ctx: PSSL_CTX):Integer; external;
+
+ [DllImport(DLLSSLName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'SSL_CTX_set_default_passwd_cb')]
+ procedure SslCtxSetDefaultPasswdCb(ctx: PSSL_CTX; cb: PPasswdCb); external;
+
+ [DllImport(DLLSSLName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'SSL_CTX_set_default_passwd_cb_userdata')]
+ procedure SslCtxSetDefaultPasswdCbUserdata(ctx: PSSL_CTX; u: IntPtr); external;
+
+ [DllImport(DLLSSLName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'SSL_CTX_load_verify_locations')]
+ function SslCtxLoadVerifyLocations(ctx: PSSL_CTX; CAfile: string; CApath: String):Integer; external;
+
+ [DllImport(DLLSSLName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'SSL_new')]
+ function SslNew(ctx: PSSL_CTX):PSSL; external;
+
+ [DllImport(DLLSSLName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'SSL_free')]
+ procedure SslFree(ssl: PSSL); external;
+
+ [DllImport(DLLSSLName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'SSL_accept')]
+ function SslAccept(ssl: PSSL):Integer; external;
+
+ [DllImport(DLLSSLName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'SSL_connect')]
+ function SslConnect(ssl: PSSL):Integer; external;
+
+ [DllImport(DLLSSLName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'SSL_shutdown')]
+ function SslShutdown(s: PSSL):Integer; external;
+
+ [DllImport(DLLSSLName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'SSL_read')]
+ function SslRead(ssl: PSSL; buf: StringBuilder; num: Integer):Integer; external;
+
+ [DllImport(DLLSSLName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'SSL_peek')]
+ function SslPeek(ssl: PSSL; buf: StringBuilder; num: Integer):Integer; external;
+
+ [DllImport(DLLSSLName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'SSL_write')]
+ function SslWrite(ssl: PSSL; buf: String; num: Integer):Integer; external;
+
+ [DllImport(DLLSSLName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'SSL_pending')]
+ function SslPending(ssl: PSSL):Integer; external;
+
+ [DllImport(DLLSSLName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'SSL_get_version')]
+ function SslGetVersion(ssl: PSSL):String; external;
+
+ [DllImport(DLLSSLName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'SSL_get_peer_certificate')]
+ function SslGetPeerCertificate(s: PSSL):PX509; external;
+
+ [DllImport(DLLSSLName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'SSL_CTX_set_verify')]
+ procedure SslCtxSetVerify(ctx: PSSL_CTX; mode: Integer; arg2: PFunction); external;
+
+ [DllImport(DLLSSLName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'SSL_get_current_cipher')]
+ function SSLGetCurrentCipher(s: PSSL): SslPtr; external;
+
+ [DllImport(DLLSSLName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'SSL_CIPHER_get_name')]
+ function SSLCipherGetName(c: SslPtr):String; external;
+
+ [DllImport(DLLSSLName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'SSL_CIPHER_get_bits')]
+ function SSLCipherGetBits(c: SslPtr; var alg_bits: Integer):Integer; external;
+
+ [DllImport(DLLSSLName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'SSL_get_verify_result')]
+ function SSLGetVerifyResult(ssl: PSSL):Integer;external;
+
+ [DllImport(DLLUtilName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'X509_new')]
+ function X509New: PX509; external;
+
+ [DllImport(DLLUtilName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'X509_free')]
+ procedure X509Free(x: PX509); external;
+
+ [DllImport(DLLUtilName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'X509_NAME_oneline')]
+ function X509NameOneline(a: PX509_NAME; buf: StringBuilder; size: Integer): String; external;
+
+ [DllImport(DLLUtilName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'X509_get_subject_name')]
+ function X509GetSubjectName(a: PX509):PX509_NAME; external;
+
+ [DllImport(DLLUtilName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'X509_get_issuer_name')]
+ function X509GetIssuerName(a: PX509):PX509_NAME; external;
+
+ [DllImport(DLLUtilName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'X509_NAME_hash')]
+ function X509NameHash(x: PX509_NAME):Cardinal; external;
+
+ [DllImport(DLLUtilName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'X509_digest')]
+ function X509Digest (data: PX509; _type: PEVP_MD; md: StringBuilder; var len: Integer):Integer; external;
+
+ [DllImport(DLLUtilName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'X509_set_version')]
+ function X509SetVersion(x: PX509; version: integer): integer; external;
+
+ [DllImport(DLLUtilName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'X509_set_pubkey')]
+ function X509SetPubkey(x: PX509; pkey: EVP_PKEY): integer; external;
+
+ [DllImport(DLLUtilName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'X509_set_issuer_name')]
+ function X509SetIssuerName(x: PX509; name: PX509_NAME): integer; external;
+
+ [DllImport(DLLUtilName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'X509_NAME_add_entry_by_txt')]
+ function X509NameAddEntryByTxt(name: PX509_NAME; field: string; _type: integer;
+ bytes: string; len, loc, _set: integer): integer; external;
+
+ [DllImport(DLLUtilName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'X509_sign')]
+ function X509Sign(x: PX509; pkey: EVP_PKEY; const md: PEVP_MD): integer; external;
+
+ [DllImport(DLLUtilName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'X509_print')]
+ function X509print(b: PBIO; a: PX509): integer; external;
+
+ [DllImport(DLLUtilName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'X509_gmtime_adj')]
+ function X509GmtimeAdj(s: PASN1_UTCTIME; adj: integer): PASN1_UTCTIME; external;
+
+ [DllImport(DLLUtilName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'X509_set_notBefore')]
+ function X509SetNotBefore(x: PX509; tm: PASN1_UTCTIME): integer; external;
+
+ [DllImport(DLLUtilName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'X509_set_notAfter')]
+ function X509SetNotAfter(x: PX509; tm: PASN1_UTCTIME): integer; external;
+
+ [DllImport(DLLUtilName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'X509_get_serialNumber')]
+ function X509GetSerialNumber(x: PX509): PASN1_INTEGER; external;
+
+ [DllImport(DLLUtilName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'EVP_PKEY_new')]
+ function EvpPkeyNew: EVP_PKEY; external;
+
+ [DllImport(DLLUtilName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'EVP_PKEY_free')]
+ procedure EvpPkeyFree(pk: EVP_PKEY); external;
+
+ [DllImport(DLLUtilName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'EVP_PKEY_assign')]
+ function EvpPkeyAssign(pkey: EVP_PKEY; _type: integer; key: Prsa): integer; external;
+
+ [DllImport(DLLUtilName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'EVP_get_digestbyname')]
+ function EvpGetDigestByName(Name: String): PEVP_MD; external;
+
+ [DllImport(DLLUtilName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'EVP_cleanup')]
+ procedure EVPcleanup; external;
+
+ [DllImport(DLLUtilName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'SSLeay_version')]
+ function SSLeayversion(t: integer): String; external;
+
+ [DllImport(DLLUtilName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'ERR_error_string_n')]
+ procedure ErrErrorString(e: integer; buf: StringBuilder; len: integer); external;
+
+ [DllImport(DLLUtilName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'ERR_get_error')]
+ function ErrGetError: integer; external;
+
+ [DllImport(DLLUtilName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'ERR_clear_error')]
+ procedure ErrClearError; external;
+
+ [DllImport(DLLUtilName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'ERR_free_strings')]
+ procedure ErrFreeStrings; external;
+
+ [DllImport(DLLUtilName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'ERR_remove_state')]
+ procedure ErrRemoveState(pid: integer); external;
+
+ [DllImport(DLLUtilName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'OPENSSL_add_all_algorithms_noconf')]
+ procedure OPENSSLaddallalgorithms; external;
+
+ [DllImport(DLLUtilName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'CRYPTO_cleanup_all_ex_data')]
+ procedure CRYPTOcleanupAllExData; external;
+
+ [DllImport(DLLUtilName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'RAND_screen')]
+ procedure RandScreen; external;
+
+ [DllImport(DLLUtilName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'BIO_new')]
+ function BioNew(b: PBIO_METHOD): PBIO; external;
+
+ [DllImport(DLLUtilName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'BIO_free_all')]
+ procedure BioFreeAll(b: PBIO); external;
+
+ [DllImport(DLLUtilName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'BIO_s_mem')]
+ function BioSMem: PBIO_METHOD; external;
+
+ [DllImport(DLLUtilName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'BIO_ctrl_pending')]
+ function BioCtrlPending(b: PBIO): integer; external;
+
+ [DllImport(DLLUtilName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'BIO_read')]
+ function BioRead(b: PBIO; Buf: StringBuilder; Len: integer): integer; external;
+
+ [DllImport(DLLUtilName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'BIO_write')]
+ function BioWrite(b: PBIO; var Buf: String; Len: integer): integer; external;
+
+ [DllImport(DLLUtilName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'd2i_PKCS12_bio')]
+ function d2iPKCS12bio(b:PBIO; Pkcs12: SslPtr): SslPtr; external;
+
+ [DllImport(DLLUtilName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'PKCS12_parse')]
+ function PKCS12parse(p12: SslPtr; pass: string; var pkey, cert, ca: SslPtr): integer; external;
+
+ [DllImport(DLLUtilName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'PKCS12_free')]
+ procedure PKCS12free(p12: SslPtr); external;
+
+ [DllImport(DLLUtilName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'RSA_generate_key')]
+ function RsaGenerateKey(bits, e: integer; callback: PFunction; cb_arg: SslPtr): PRSA; external;
+
+ [DllImport(DLLUtilName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'ASN1_UTCTIME_new')]
+ function Asn1UtctimeNew: PASN1_UTCTIME; external;
+
+ [DllImport(DLLUtilName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'ASN1_UTCTIME_free')]
+ procedure Asn1UtctimeFree(a: PASN1_UTCTIME); external;
+
+ [DllImport(DLLUtilName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'ASN1_INTEGER_set')]
+ function Asn1IntegerSet(a: PASN1_INTEGER; v: integer): integer; external;
+
+ [DllImport(DLLUtilName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'i2d_X509_bio')]
+ function i2dX509bio(b: PBIO; x: PX509): integer; external;
+
+ [DllImport(DLLUtilName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'i2d_PrivateKey_bio')]
+ function i2dPrivateKeyBio(b: PBIO; pkey: EVP_PKEY): integer; external;
+
+ // 3DES functions
+ [DllImport(DLLUtilName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'DES_set_odd_parity')]
+ procedure DESsetoddparity(Key: des_cblock); external;
+
+ [DllImport(DLLUtilName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'DES_set_key_checked')]
+ function DESsetkeychecked(key: des_cblock; schedule: des_key_schedule): Integer; external;
+
+ [DllImport(DLLUtilName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'DES_ecb_encrypt')]
+ procedure DESecbencrypt(Input: des_cblock; output: des_cblock; ks: des_key_schedule; enc: Integer); external;
+
+{$ELSE}
+// libssl.dll
+ function SslGetError(s: PSSL; ret_code: Integer):Integer;
+ function SslLibraryInit:Integer;
+ procedure SslLoadErrorStrings;
+// function SslCtxSetCipherList(arg0: PSSL_CTX; str: PChar):Integer;
+ function SslCtxSetCipherList(arg0: PSSL_CTX; var str: AnsiString):Integer;
+ function SslCtxNew(meth: PSSL_METHOD):PSSL_CTX;
+ procedure SslCtxFree(arg0: PSSL_CTX);
+ function SslSetFd(s: PSSL; fd: Integer):Integer;
+ function SslMethodV2:PSSL_METHOD;
+ function SslMethodV3:PSSL_METHOD;
+ function SslMethodTLSV1:PSSL_METHOD;
+ function SslMethodV23:PSSL_METHOD;
+ function SslCtxUsePrivateKey(ctx: PSSL_CTX; pkey: SslPtr):Integer;
+ function SslCtxUsePrivateKeyASN1(pk: integer; ctx: PSSL_CTX; d: AnsiString; len: integer):Integer;
+// function SslCtxUsePrivateKeyFile(ctx: PSSL_CTX; const _file: PChar; _type: Integer):Integer;
+ function SslCtxUsePrivateKeyFile(ctx: PSSL_CTX; const _file: AnsiString; _type: Integer):Integer;
+ function SslCtxUseCertificate(ctx: PSSL_CTX; x: SslPtr):Integer;
+ function SslCtxUseCertificateASN1(ctx: PSSL_CTX; len: integer; d: AnsiString):Integer;
+ function SslCtxUseCertificateFile(ctx: PSSL_CTX; const _file: AnsiString; _type: Integer):Integer;
+// function SslCtxUseCertificateChainFile(ctx: PSSL_CTX; const _file: PChar):Integer;
+ function SslCtxUseCertificateChainFile(ctx: PSSL_CTX; const _file: AnsiString):Integer;
+ function SslCtxCheckPrivateKeyFile(ctx: PSSL_CTX):Integer;
+ procedure SslCtxSetDefaultPasswdCb(ctx: PSSL_CTX; cb: PPasswdCb);
+ procedure SslCtxSetDefaultPasswdCbUserdata(ctx: PSSL_CTX; u: SslPtr);
+// function SslCtxLoadVerifyLocations(ctx: PSSL_CTX; const CAfile: PChar; const CApath: PChar):Integer;
+ function SslCtxLoadVerifyLocations(ctx: PSSL_CTX; const CAfile: AnsiString; const CApath: AnsiString):Integer;
+ function SslNew(ctx: PSSL_CTX):PSSL;
+ procedure SslFree(ssl: PSSL);
+ function SslAccept(ssl: PSSL):Integer;
+ function SslConnect(ssl: PSSL):Integer;
+ function SslShutdown(ssl: PSSL):Integer;
+ function SslRead(ssl: PSSL; buf: SslPtr; num: Integer):Integer;
+ function SslPeek(ssl: PSSL; buf: SslPtr; num: Integer):Integer;
+ function SslWrite(ssl: PSSL; buf: SslPtr; num: Integer):Integer;
+ function SslPending(ssl: PSSL):Integer;
+ function SslGetVersion(ssl: PSSL):AnsiString;
+ function SslGetPeerCertificate(ssl: PSSL):PX509;
+ procedure SslCtxSetVerify(ctx: PSSL_CTX; mode: Integer; arg2: PFunction);
+ function SSLGetCurrentCipher(s: PSSL):SslPtr;
+ function SSLCipherGetName(c: SslPtr): AnsiString;
+ function SSLCipherGetBits(c: SslPtr; var alg_bits: Integer):Integer;
+ function SSLGetVerifyResult(ssl: PSSL):Integer;
+
+// libeay.dll
+ function X509New: PX509;
+ procedure X509Free(x: PX509);
+ function X509NameOneline(a: PX509_NAME; var buf: AnsiString; size: Integer):AnsiString;
+ function X509GetSubjectName(a: PX509):PX509_NAME;
+ function X509GetIssuerName(a: PX509):PX509_NAME;
+ function X509NameHash(x: PX509_NAME):Cardinal;
+// function SslX509Digest(data: PX509; _type: PEVP_MD; md: PChar; len: PInteger):Integer;
+ function X509Digest(data: PX509; _type: PEVP_MD; md: AnsiString; var len: Integer):Integer;
+ function X509print(b: PBIO; a: PX509): integer;
+ function X509SetVersion(x: PX509; version: integer): integer;
+ function X509SetPubkey(x: PX509; pkey: EVP_PKEY): integer;
+ function X509SetIssuerName(x: PX509; name: PX509_NAME): integer;
+ function X509NameAddEntryByTxt(name: PX509_NAME; field: Ansistring; _type: integer;
+ bytes: Ansistring; len, loc, _set: integer): integer;
+ function X509Sign(x: PX509; pkey: EVP_PKEY; const md: PEVP_MD): integer;
+ function X509GmtimeAdj(s: PASN1_UTCTIME; adj: integer): PASN1_UTCTIME;
+ function X509SetNotBefore(x: PX509; tm: PASN1_UTCTIME): integer;
+ function X509SetNotAfter(x: PX509; tm: PASN1_UTCTIME): integer;
+ function X509GetSerialNumber(x: PX509): PASN1_INTEGER;
+ function EvpPkeyNew: EVP_PKEY;
+ procedure EvpPkeyFree(pk: EVP_PKEY);
+ function EvpPkeyAssign(pkey: EVP_PKEY; _type: integer; key: Prsa): integer;
+ function EvpGetDigestByName(Name: AnsiString): PEVP_MD;
+ procedure EVPcleanup;
+// function ErrErrorString(e: integer; buf: PChar): PChar;
+ function SSLeayversion(t: integer): Ansistring;
+ procedure ErrErrorString(e: integer; var buf: Ansistring; len: integer);
+ function ErrGetError: integer;
+ procedure ErrClearError;
+ procedure ErrFreeStrings;
+ procedure ErrRemoveState(pid: integer);
+ procedure OPENSSLaddallalgorithms;
+ procedure CRYPTOcleanupAllExData;
+ procedure RandScreen;
+ function BioNew(b: PBIO_METHOD): PBIO;
+ procedure BioFreeAll(b: PBIO);
+ function BioSMem: PBIO_METHOD;
+ function BioCtrlPending(b: PBIO): integer;
+ function BioRead(b: PBIO; var Buf: AnsiString; Len: integer): integer;
+ function BioWrite(b: PBIO; Buf: AnsiString; Len: integer): integer;
+ function d2iPKCS12bio(b:PBIO; Pkcs12: SslPtr): SslPtr;
+ function PKCS12parse(p12: SslPtr; pass: Ansistring; var pkey, cert, ca: SslPtr): integer;
+ procedure PKCS12free(p12: SslPtr);
+ function RsaGenerateKey(bits, e: integer; callback: PFunction; cb_arg: SslPtr): PRSA;
+ function Asn1UtctimeNew: PASN1_UTCTIME;
+ procedure Asn1UtctimeFree(a: PASN1_UTCTIME);
+ function Asn1IntegerSet(a: PASN1_INTEGER; v: integer): integer;
+ function i2dX509bio(b: PBIO; x: PX509): integer;
+ function i2dPrivateKeyBio(b: PBIO; pkey: EVP_PKEY): integer;
+
+ // 3DES functions
+ procedure DESsetoddparity(Key: des_cblock);
+ function DESsetkeychecked(key: des_cblock; schedule: des_key_schedule): Integer;
+ procedure DESecbencrypt(Input: des_cblock; output: des_cblock; ks: des_key_schedule; enc: Integer);
+
+{$ENDIF}
+
+function IsSSLloaded: Boolean;
+function InitSSLInterface: Boolean;
+function DestroySSLInterface: Boolean;
+
+implementation
+
+uses SyncObjs;
+
+{$IFNDEF CIL}
+type
+// libssl.dll
+ TSslGetError = function(s: PSSL; ret_code: Integer):Integer; cdecl;
+ TSslLibraryInit = function:Integer; cdecl;
+ TSslLoadErrorStrings = procedure; cdecl;
+ TSslCtxSetCipherList = function(arg0: PSSL_CTX; str: PAnsiChar):Integer; cdecl;
+ TSslCtxNew = function(meth: PSSL_METHOD):PSSL_CTX; cdecl;
+ TSslCtxFree = procedure(arg0: PSSL_CTX); cdecl;
+ TSslSetFd = function(s: PSSL; fd: Integer):Integer; cdecl;
+ TSslMethodV2 = function:PSSL_METHOD; cdecl;
+ TSslMethodV3 = function:PSSL_METHOD; cdecl;
+ TSslMethodTLSV1 = function:PSSL_METHOD; cdecl;
+ TSslMethodV23 = function:PSSL_METHOD; cdecl;
+ TSslCtxUsePrivateKey = function(ctx: PSSL_CTX; pkey: sslptr):Integer; cdecl;
+ TSslCtxUsePrivateKeyASN1 = function(pk: integer; ctx: PSSL_CTX; d: sslptr; len: integer):Integer; cdecl;
+ TSslCtxUsePrivateKeyFile = function(ctx: PSSL_CTX; const _file: PAnsiChar; _type: Integer):Integer; cdecl;
+ TSslCtxUseCertificate = function(ctx: PSSL_CTX; x: SslPtr):Integer; cdecl;
+ TSslCtxUseCertificateASN1 = function(ctx: PSSL_CTX; len: Integer; d: SslPtr):Integer; cdecl;
+ TSslCtxUseCertificateFile = function(ctx: PSSL_CTX; const _file: PAnsiChar; _type: Integer):Integer; cdecl;
+ TSslCtxUseCertificateChainFile = function(ctx: PSSL_CTX; const _file: PAnsiChar):Integer; cdecl;
+ TSslCtxCheckPrivateKeyFile = function(ctx: PSSL_CTX):Integer; cdecl;
+ TSslCtxSetDefaultPasswdCb = procedure(ctx: PSSL_CTX; cb: SslPtr); cdecl;
+ TSslCtxSetDefaultPasswdCbUserdata = procedure(ctx: PSSL_CTX; u: SslPtr); cdecl;
+ TSslCtxLoadVerifyLocations = function(ctx: PSSL_CTX; const CAfile: PAnsiChar; const CApath: PAnsiChar):Integer; cdecl;
+ TSslNew = function(ctx: PSSL_CTX):PSSL; cdecl;
+ TSslFree = procedure(ssl: PSSL); cdecl;
+ TSslAccept = function(ssl: PSSL):Integer; cdecl;
+ TSslConnect = function(ssl: PSSL):Integer; cdecl;
+ TSslShutdown = function(ssl: PSSL):Integer; cdecl;
+ TSslRead = function(ssl: PSSL; buf: PAnsiChar; num: Integer):Integer; cdecl;
+ TSslPeek = function(ssl: PSSL; buf: PAnsiChar; num: Integer):Integer; cdecl;
+ TSslWrite = function(ssl: PSSL; const buf: PAnsiChar; num: Integer):Integer; cdecl;
+ TSslPending = function(ssl: PSSL):Integer; cdecl;
+ TSslGetVersion = function(ssl: PSSL):PAnsiChar; cdecl;
+ TSslGetPeerCertificate = function(ssl: PSSL):PX509; cdecl;
+ TSslCtxSetVerify = procedure(ctx: PSSL_CTX; mode: Integer; arg2: SslPtr); cdecl;
+ TSSLGetCurrentCipher = function(s: PSSL):SslPtr; cdecl;
+ TSSLCipherGetName = function(c: Sslptr):PAnsiChar; cdecl;
+ TSSLCipherGetBits = function(c: SslPtr; alg_bits: PInteger):Integer; cdecl;
+ TSSLGetVerifyResult = function(ssl: PSSL):Integer; cdecl;
+
+// libeay.dll
+ TX509New = function: PX509; cdecl;
+ TX509Free = procedure(x: PX509); cdecl;
+ TX509NameOneline = function(a: PX509_NAME; buf: PAnsiChar; size: Integer):PAnsiChar; cdecl;
+ TX509GetSubjectName = function(a: PX509):PX509_NAME; cdecl;
+ TX509GetIssuerName = function(a: PX509):PX509_NAME; cdecl;
+ TX509NameHash = function(x: PX509_NAME):Cardinal; cdecl;
+ TX509Digest = function(data: PX509; _type: PEVP_MD; md: PAnsiChar; len: PInteger):Integer; cdecl;
+ TX509print = function(b: PBIO; a: PX509): integer; cdecl;
+ TX509SetVersion = function(x: PX509; version: integer): integer; cdecl;
+ TX509SetPubkey = function(x: PX509; pkey: EVP_PKEY): integer; cdecl;
+ TX509SetIssuerName = function(x: PX509; name: PX509_NAME): integer; cdecl;
+ TX509NameAddEntryByTxt = function(name: PX509_NAME; field: PAnsiChar; _type: integer;
+ bytes: PAnsiChar; len, loc, _set: integer): integer; cdecl;
+ TX509Sign = function(x: PX509; pkey: EVP_PKEY; const md: PEVP_MD): integer; cdecl;
+ TX509GmtimeAdj = function(s: PASN1_UTCTIME; adj: integer): PASN1_UTCTIME; cdecl;
+ TX509SetNotBefore = function(x: PX509; tm: PASN1_UTCTIME): integer; cdecl;
+ TX509SetNotAfter = function(x: PX509; tm: PASN1_UTCTIME): integer; cdecl;
+ TX509GetSerialNumber = function(x: PX509): PASN1_INTEGER; cdecl;
+ TEvpPkeyNew = function: EVP_PKEY; cdecl;
+ TEvpPkeyFree = procedure(pk: EVP_PKEY); cdecl;
+ TEvpPkeyAssign = function(pkey: EVP_PKEY; _type: integer; key: Prsa): integer; cdecl;
+ TEvpGetDigestByName = function(Name: PAnsiChar): PEVP_MD; cdecl;
+ TEVPcleanup = procedure; cdecl;
+ TSSLeayversion = function(t: integer): PAnsiChar; cdecl;
+ TErrErrorString = procedure(e: integer; buf: PAnsiChar; len: integer); cdecl;
+ TErrGetError = function: integer; cdecl;
+ TErrClearError = procedure; cdecl;
+ TErrFreeStrings = procedure; cdecl;
+ TErrRemoveState = procedure(pid: integer); cdecl;
+ TOPENSSLaddallalgorithms = procedure; cdecl;
+ TCRYPTOcleanupAllExData = procedure; cdecl;
+ TRandScreen = procedure; cdecl;
+ TBioNew = function(b: PBIO_METHOD): PBIO; cdecl;
+ TBioFreeAll = procedure(b: PBIO); cdecl;
+ TBioSMem = function: PBIO_METHOD; cdecl;
+ TBioCtrlPending = function(b: PBIO): integer; cdecl;
+ TBioRead = function(b: PBIO; Buf: PAnsiChar; Len: integer): integer; cdecl;
+ TBioWrite = function(b: PBIO; Buf: PAnsiChar; Len: integer): integer; cdecl;
+ Td2iPKCS12bio = function(b:PBIO; Pkcs12: SslPtr): SslPtr; cdecl;
+ TPKCS12parse = function(p12: SslPtr; pass: PAnsiChar; var pkey, cert, ca: SslPtr): integer; cdecl;
+ TPKCS12free = procedure(p12: SslPtr); cdecl;
+ TRsaGenerateKey = function(bits, e: integer; callback: PFunction; cb_arg: SslPtr): PRSA; cdecl;
+ TAsn1UtctimeNew = function: PASN1_UTCTIME; cdecl;
+ TAsn1UtctimeFree = procedure(a: PASN1_UTCTIME); cdecl;
+ TAsn1IntegerSet = function(a: PASN1_INTEGER; v: integer): integer; cdecl;
+ Ti2dX509bio = function(b: PBIO; x: PX509): integer; cdecl;
+ Ti2dPrivateKeyBio= function(b: PBIO; pkey: EVP_PKEY): integer; cdecl;
+
+ // 3DES functions
+ TDESsetoddparity = procedure(Key: des_cblock); cdecl;
+ TDESsetkeychecked = function(key: des_cblock; schedule: des_key_schedule): Integer; cdecl;
+ TDESecbencrypt = procedure(Input: des_cblock; output: des_cblock; ks: des_key_schedule; enc: Integer); cdecl;
+ //thread lock functions
+ TCRYPTOnumlocks = function: integer; cdecl;
+ TCRYPTOSetLockingCallback = procedure(cb: Sslptr); cdecl;
+
+var
+// libssl.dll
+ _SslGetError: TSslGetError = nil;
+ _SslLibraryInit: TSslLibraryInit = nil;
+ _SslLoadErrorStrings: TSslLoadErrorStrings = nil;
+ _SslCtxSetCipherList: TSslCtxSetCipherList = nil;
+ _SslCtxNew: TSslCtxNew = nil;
+ _SslCtxFree: TSslCtxFree = nil;
+ _SslSetFd: TSslSetFd = nil;
+ _SslMethodV2: TSslMethodV2 = nil;
+ _SslMethodV3: TSslMethodV3 = nil;
+ _SslMethodTLSV1: TSslMethodTLSV1 = nil;
+ _SslMethodV23: TSslMethodV23 = nil;
+ _SslCtxUsePrivateKey: TSslCtxUsePrivateKey = nil;
+ _SslCtxUsePrivateKeyASN1: TSslCtxUsePrivateKeyASN1 = nil;
+ _SslCtxUsePrivateKeyFile: TSslCtxUsePrivateKeyFile = nil;
+ _SslCtxUseCertificate: TSslCtxUseCertificate = nil;
+ _SslCtxUseCertificateASN1: TSslCtxUseCertificateASN1 = nil;
+ _SslCtxUseCertificateFile: TSslCtxUseCertificateFile = nil;
+ _SslCtxUseCertificateChainFile: TSslCtxUseCertificateChainFile = nil;
+ _SslCtxCheckPrivateKeyFile: TSslCtxCheckPrivateKeyFile = nil;
+ _SslCtxSetDefaultPasswdCb: TSslCtxSetDefaultPasswdCb = nil;
+ _SslCtxSetDefaultPasswdCbUserdata: TSslCtxSetDefaultPasswdCbUserdata = nil;
+ _SslCtxLoadVerifyLocations: TSslCtxLoadVerifyLocations = nil;
+ _SslNew: TSslNew = nil;
+ _SslFree: TSslFree = nil;
+ _SslAccept: TSslAccept = nil;
+ _SslConnect: TSslConnect = nil;
+ _SslShutdown: TSslShutdown = nil;
+ _SslRead: TSslRead = nil;
+ _SslPeek: TSslPeek = nil;
+ _SslWrite: TSslWrite = nil;
+ _SslPending: TSslPending = nil;
+ _SslGetVersion: TSslGetVersion = nil;
+ _SslGetPeerCertificate: TSslGetPeerCertificate = nil;
+ _SslCtxSetVerify: TSslCtxSetVerify = nil;
+ _SSLGetCurrentCipher: TSSLGetCurrentCipher = nil;
+ _SSLCipherGetName: TSSLCipherGetName = nil;
+ _SSLCipherGetBits: TSSLCipherGetBits = nil;
+ _SSLGetVerifyResult: TSSLGetVerifyResult = nil;
+
+// libeay.dll
+ _X509New: TX509New = nil;
+ _X509Free: TX509Free = nil;
+ _X509NameOneline: TX509NameOneline = nil;
+ _X509GetSubjectName: TX509GetSubjectName = nil;
+ _X509GetIssuerName: TX509GetIssuerName = nil;
+ _X509NameHash: TX509NameHash = nil;
+ _X509Digest: TX509Digest = nil;
+ _X509print: TX509print = nil;
+ _X509SetVersion: TX509SetVersion = nil;
+ _X509SetPubkey: TX509SetPubkey = nil;
+ _X509SetIssuerName: TX509SetIssuerName = nil;
+ _X509NameAddEntryByTxt: TX509NameAddEntryByTxt = nil;
+ _X509Sign: TX509Sign = nil;
+ _X509GmtimeAdj: TX509GmtimeAdj = nil;
+ _X509SetNotBefore: TX509SetNotBefore = nil;
+ _X509SetNotAfter: TX509SetNotAfter = nil;
+ _X509GetSerialNumber: TX509GetSerialNumber = nil;
+ _EvpPkeyNew: TEvpPkeyNew = nil;
+ _EvpPkeyFree: TEvpPkeyFree = nil;
+ _EvpPkeyAssign: TEvpPkeyAssign = nil;
+ _EvpGetDigestByName: TEvpGetDigestByName = nil;
+ _EVPcleanup: TEVPcleanup = nil;
+ _SSLeayversion: TSSLeayversion = nil;
+ _ErrErrorString: TErrErrorString = nil;
+ _ErrGetError: TErrGetError = nil;
+ _ErrClearError: TErrClearError = nil;
+ _ErrFreeStrings: TErrFreeStrings = nil;
+ _ErrRemoveState: TErrRemoveState = nil;
+ _OPENSSLaddallalgorithms: TOPENSSLaddallalgorithms = nil;
+ _CRYPTOcleanupAllExData: TCRYPTOcleanupAllExData = nil;
+ _RandScreen: TRandScreen = nil;
+ _BioNew: TBioNew = nil;
+ _BioFreeAll: TBioFreeAll = nil;
+ _BioSMem: TBioSMem = nil;
+ _BioCtrlPending: TBioCtrlPending = nil;
+ _BioRead: TBioRead = nil;
+ _BioWrite: TBioWrite = nil;
+ _d2iPKCS12bio: Td2iPKCS12bio = nil;
+ _PKCS12parse: TPKCS12parse = nil;
+ _PKCS12free: TPKCS12free = nil;
+ _RsaGenerateKey: TRsaGenerateKey = nil;
+ _Asn1UtctimeNew: TAsn1UtctimeNew = nil;
+ _Asn1UtctimeFree: TAsn1UtctimeFree = nil;
+ _Asn1IntegerSet: TAsn1IntegerSet = nil;
+ _i2dX509bio: Ti2dX509bio = nil;
+ _i2dPrivateKeyBio: Ti2dPrivateKeyBio = nil;
+
+ // 3DES functions
+ _DESsetoddparity: TDESsetoddparity = nil;
+ _DESsetkeychecked: TDESsetkeychecked = nil;
+ _DESecbencrypt: TDESecbencrypt = nil;
+ //thread lock functions
+ _CRYPTOnumlocks: TCRYPTOnumlocks = nil;
+ _CRYPTOSetLockingCallback: TCRYPTOSetLockingCallback = nil;
+{$ENDIF}
+
+var
+ SSLCS: TCriticalSection;
+ SSLloaded: boolean = false;
+{$IFNDEF CIL}
+ Locks: TList;
+{$ENDIF}
+
+{$IFNDEF CIL}
+// libssl.dll
+function SslGetError(s: PSSL; ret_code: Integer):Integer;
+begin
+ if InitSSLInterface and Assigned(_SslGetError) then
+ Result := _SslGetError(s, ret_code)
+ else
+ Result := SSL_ERROR_SSL;
+end;
+
+function SslLibraryInit:Integer;
+begin
+ if InitSSLInterface and Assigned(_SslLibraryInit) then
+ Result := _SslLibraryInit
+ else
+ Result := 1;
+end;
+
+procedure SslLoadErrorStrings;
+begin
+ if InitSSLInterface and Assigned(_SslLoadErrorStrings) then
+ _SslLoadErrorStrings;
+end;
+
+//function SslCtxSetCipherList(arg0: PSSL_CTX; str: PChar):Integer;
+function SslCtxSetCipherList(arg0: PSSL_CTX; var str: AnsiString):Integer;
+begin
+ if InitSSLInterface and Assigned(_SslCtxSetCipherList) then
+ Result := _SslCtxSetCipherList(arg0, PAnsiChar(str))
+ else
+ Result := 0;
+end;
+
+function SslCtxNew(meth: PSSL_METHOD):PSSL_CTX;
+begin
+ if InitSSLInterface and Assigned(_SslCtxNew) then
+ Result := _SslCtxNew(meth)
+ else
+ Result := nil;
+end;
+
+procedure SslCtxFree(arg0: PSSL_CTX);
+begin
+ if InitSSLInterface and Assigned(_SslCtxFree) then
+ _SslCtxFree(arg0);
+end;
+
+function SslSetFd(s: PSSL; fd: Integer):Integer;
+begin
+ if InitSSLInterface and Assigned(_SslSetFd) then
+ Result := _SslSetFd(s, fd)
+ else
+ Result := 0;
+end;
+
+function SslMethodV2:PSSL_METHOD;
+begin
+ if InitSSLInterface and Assigned(_SslMethodV2) then
+ Result := _SslMethodV2
+ else
+ Result := nil;
+end;
+
+function SslMethodV3:PSSL_METHOD;
+begin
+ if InitSSLInterface and Assigned(_SslMethodV3) then
+ Result := _SslMethodV3
+ else
+ Result := nil;
+end;
+
+function SslMethodTLSV1:PSSL_METHOD;
+begin
+ if InitSSLInterface and Assigned(_SslMethodTLSV1) then
+ Result := _SslMethodTLSV1
+ else
+ Result := nil;
+end;
+
+function SslMethodV23:PSSL_METHOD;
+begin
+ if InitSSLInterface and Assigned(_SslMethodV23) then
+ Result := _SslMethodV23
+ else
+ Result := nil;
+end;
+
+function SslCtxUsePrivateKey(ctx: PSSL_CTX; pkey: SslPtr):Integer;
+begin
+ if InitSSLInterface and Assigned(_SslCtxUsePrivateKey) then
+ Result := _SslCtxUsePrivateKey(ctx, pkey)
+ else
+ Result := 0;
+end;
+
+function SslCtxUsePrivateKeyASN1(pk: integer; ctx: PSSL_CTX; d: AnsiString; len: integer):Integer;
+begin
+ if InitSSLInterface and Assigned(_SslCtxUsePrivateKeyASN1) then
+ Result := _SslCtxUsePrivateKeyASN1(pk, ctx, Sslptr(d), len)
+ else
+ Result := 0;
+end;
+
+//function SslCtxUsePrivateKeyFile(ctx: PSSL_CTX; const _file: PChar; _type: Integer):Integer;
+function SslCtxUsePrivateKeyFile(ctx: PSSL_CTX; const _file: AnsiString; _type: Integer):Integer;
+begin
+ if InitSSLInterface and Assigned(_SslCtxUsePrivateKeyFile) then
+ Result := _SslCtxUsePrivateKeyFile(ctx, PAnsiChar(_file), _type)
+ else
+ Result := 0;
+end;
+
+function SslCtxUseCertificate(ctx: PSSL_CTX; x: SslPtr):Integer;
+begin
+ if InitSSLInterface and Assigned(_SslCtxUseCertificate) then
+ Result := _SslCtxUseCertificate(ctx, x)
+ else
+ Result := 0;
+end;
+
+function SslCtxUseCertificateASN1(ctx: PSSL_CTX; len: integer; d: AnsiString):Integer;
+begin
+ if InitSSLInterface and Assigned(_SslCtxUseCertificateASN1) then
+ Result := _SslCtxUseCertificateASN1(ctx, len, SslPtr(d))
+ else
+ Result := 0;
+end;
+
+function SslCtxUseCertificateFile(ctx: PSSL_CTX; const _file: AnsiString; _type: Integer):Integer;
+begin
+ if InitSSLInterface and Assigned(_SslCtxUseCertificateFile) then
+ Result := _SslCtxUseCertificateFile(ctx, PAnsiChar(_file), _type)
+ else
+ Result := 0;
+end;
+
+//function SslCtxUseCertificateChainFile(ctx: PSSL_CTX; const _file: PChar):Integer;
+function SslCtxUseCertificateChainFile(ctx: PSSL_CTX; const _file: AnsiString):Integer;
+begin
+ if InitSSLInterface and Assigned(_SslCtxUseCertificateChainFile) then
+ Result := _SslCtxUseCertificateChainFile(ctx, PAnsiChar(_file))
+ else
+ Result := 0;
+end;
+
+function SslCtxCheckPrivateKeyFile(ctx: PSSL_CTX):Integer;
+begin
+ if InitSSLInterface and Assigned(_SslCtxCheckPrivateKeyFile) then
+ Result := _SslCtxCheckPrivateKeyFile(ctx)
+ else
+ Result := 0;
+end;
+
+procedure SslCtxSetDefaultPasswdCb(ctx: PSSL_CTX; cb: PPasswdCb);
+begin
+ if InitSSLInterface and Assigned(_SslCtxSetDefaultPasswdCb) then
+ _SslCtxSetDefaultPasswdCb(ctx, cb);
+end;
+
+procedure SslCtxSetDefaultPasswdCbUserdata(ctx: PSSL_CTX; u: SslPtr);
+begin
+ if InitSSLInterface and Assigned(_SslCtxSetDefaultPasswdCbUserdata) then
+ _SslCtxSetDefaultPasswdCbUserdata(ctx, u);
+end;
+
+//function SslCtxLoadVerifyLocations(ctx: PSSL_CTX; const CAfile: PChar; const CApath: PChar):Integer;
+function SslCtxLoadVerifyLocations(ctx: PSSL_CTX; const CAfile: AnsiString; const CApath: AnsiString):Integer;
+begin
+ if InitSSLInterface and Assigned(_SslCtxLoadVerifyLocations) then
+ Result := _SslCtxLoadVerifyLocations(ctx, SslPtr(CAfile), SslPtr(CApath))
+ else
+ Result := 0;
+end;
+
+function SslNew(ctx: PSSL_CTX):PSSL;
+begin
+ if InitSSLInterface and Assigned(_SslNew) then
+ Result := _SslNew(ctx)
+ else
+ Result := nil;
+end;
+
+procedure SslFree(ssl: PSSL);
+begin
+ if InitSSLInterface and Assigned(_SslFree) then
+ _SslFree(ssl);
+end;
+
+function SslAccept(ssl: PSSL):Integer;
+begin
+ if InitSSLInterface and Assigned(_SslAccept) then
+ Result := _SslAccept(ssl)
+ else
+ Result := -1;
+end;
+
+function SslConnect(ssl: PSSL):Integer;
+begin
+ if InitSSLInterface and Assigned(_SslConnect) then
+ Result := _SslConnect(ssl)
+ else
+ Result := -1;
+end;
+
+function SslShutdown(ssl: PSSL):Integer;
+begin
+ if InitSSLInterface and Assigned(_SslShutdown) then
+ Result := _SslShutdown(ssl)
+ else
+ Result := -1;
+end;
+
+//function SslRead(ssl: PSSL; buf: PChar; num: Integer):Integer;
+function SslRead(ssl: PSSL; buf: SslPtr; num: Integer):Integer;
+begin
+ if InitSSLInterface and Assigned(_SslRead) then
+ Result := _SslRead(ssl, PAnsiChar(buf), num)
+ else
+ Result := -1;
+end;
+
+//function SslPeek(ssl: PSSL; buf: PChar; num: Integer):Integer;
+function SslPeek(ssl: PSSL; buf: SslPtr; num: Integer):Integer;
+begin
+ if InitSSLInterface and Assigned(_SslPeek) then
+ Result := _SslPeek(ssl, PAnsiChar(buf), num)
+ else
+ Result := -1;
+end;
+
+//function SslWrite(ssl: PSSL; const buf: PChar; num: Integer):Integer;
+function SslWrite(ssl: PSSL; buf: SslPtr; num: Integer):Integer;
+begin
+ if InitSSLInterface and Assigned(_SslWrite) then
+ Result := _SslWrite(ssl, PAnsiChar(buf), num)
+ else
+ Result := -1;
+end;
+
+function SslPending(ssl: PSSL):Integer;
+begin
+ if InitSSLInterface and Assigned(_SslPending) then
+ Result := _SslPending(ssl)
+ else
+ Result := 0;
+end;
+
+//function SslGetVersion(ssl: PSSL):PChar;
+function SslGetVersion(ssl: PSSL):AnsiString;
+begin
+ if InitSSLInterface and Assigned(_SslGetVersion) then
+ Result := _SslGetVersion(ssl)
+ else
+ Result := '';
+end;
+
+function SslGetPeerCertificate(ssl: PSSL):PX509;
+begin
+ if InitSSLInterface and Assigned(_SslGetPeerCertificate) then
+ Result := _SslGetPeerCertificate(ssl)
+ else
+ Result := nil;
+end;
+
+//procedure SslCtxSetVerify(ctx: PSSL_CTX; mode: Integer; arg2: SslPtr);
+procedure SslCtxSetVerify(ctx: PSSL_CTX; mode: Integer; arg2: PFunction);
+begin
+ if InitSSLInterface and Assigned(_SslCtxSetVerify) then
+ _SslCtxSetVerify(ctx, mode, @arg2);
+end;
+
+function SSLGetCurrentCipher(s: PSSL):SslPtr;
+begin
+ if InitSSLInterface and Assigned(_SSLGetCurrentCipher) then
+{$IFDEF CIL}
+{$ELSE}
+ Result := _SSLGetCurrentCipher(s)
+{$ENDIF}
+ else
+ Result := nil;
+end;
+
+//function SSLCipherGetName(c: SslPtr):PChar;
+function SSLCipherGetName(c: SslPtr):AnsiString;
+begin
+ if InitSSLInterface and Assigned(_SSLCipherGetName) then
+ Result := _SSLCipherGetName(c)
+ else
+ Result := '';
+end;
+
+//function SSLCipherGetBits(c: SslPtr; alg_bits: PInteger):Integer;
+function SSLCipherGetBits(c: SslPtr; var alg_bits: Integer):Integer;
+begin
+ if InitSSLInterface and Assigned(_SSLCipherGetBits) then
+ Result := _SSLCipherGetBits(c, @alg_bits)
+ else
+ Result := 0;
+end;
+
+function SSLGetVerifyResult(ssl: PSSL):Integer;
+begin
+ if InitSSLInterface and Assigned(_SSLGetVerifyResult) then
+ Result := _SSLGetVerifyResult(ssl)
+ else
+ Result := X509_V_ERR_APPLICATION_VERIFICATION;
+end;
+
+// libeay.dll
+function X509New: PX509;
+begin
+ if InitSSLInterface and Assigned(_X509New) then
+ Result := _X509New
+ else
+ Result := nil;
+end;
+
+procedure X509Free(x: PX509);
+begin
+ if InitSSLInterface and Assigned(_X509Free) then
+ _X509Free(x);
+end;
+
+//function SslX509NameOneline(a: PX509_NAME; buf: PChar; size: Integer):PChar;
+function X509NameOneline(a: PX509_NAME; var buf: AnsiString; size: Integer):AnsiString;
+begin
+ if InitSSLInterface and Assigned(_X509NameOneline) then
+ Result := _X509NameOneline(a, PAnsiChar(buf),size)
+ else
+ Result := '';
+end;
+
+function X509GetSubjectName(a: PX509):PX509_NAME;
+begin
+ if InitSSLInterface and Assigned(_X509GetSubjectName) then
+ Result := _X509GetSubjectName(a)
+ else
+ Result := nil;
+end;
+
+function X509GetIssuerName(a: PX509):PX509_NAME;
+begin
+ if InitSSLInterface and Assigned(_X509GetIssuerName) then
+ Result := _X509GetIssuerName(a)
+ else
+ Result := nil;
+end;
+
+function X509NameHash(x: PX509_NAME):Cardinal;
+begin
+ if InitSSLInterface and Assigned(_X509NameHash) then
+ Result := _X509NameHash(x)
+ else
+ Result := 0;
+end;
+
+//function SslX509Digest(data: PX509; _type: PEVP_MD; md: PChar; len: PInteger):Integer;
+function X509Digest(data: PX509; _type: PEVP_MD; md: AnsiString; var len: Integer):Integer;
+begin
+ if InitSSLInterface and Assigned(_X509Digest) then
+ Result := _X509Digest(data, _type, PAnsiChar(md), @len)
+ else
+ Result := 0;
+end;
+
+function EvpPkeyNew: EVP_PKEY;
+begin
+ if InitSSLInterface and Assigned(_EvpPkeyNew) then
+ Result := _EvpPkeyNew
+ else
+ Result := nil;
+end;
+
+procedure EvpPkeyFree(pk: EVP_PKEY);
+begin
+ if InitSSLInterface and Assigned(_EvpPkeyFree) then
+ _EvpPkeyFree(pk);
+end;
+
+function SSLeayversion(t: integer): Ansistring;
+begin
+ if InitSSLInterface and Assigned(_SSLeayversion) then
+ Result := PAnsiChar(_SSLeayversion(t))
+ else
+ Result := '';
+end;
+
+procedure ErrErrorString(e: integer; var buf: Ansistring; len: integer);
+begin
+ if InitSSLInterface and Assigned(_ErrErrorString) then
+ _ErrErrorString(e, Pointer(buf), len);
+ buf := PChar(Buf);
+end;
+
+function ErrGetError: integer;
+begin
+ if InitSSLInterface and Assigned(_ErrGetError) then
+ Result := _ErrGetError
+ else
+ Result := SSL_ERROR_SSL;
+end;
+
+procedure ErrClearError;
+begin
+ if InitSSLInterface and Assigned(_ErrClearError) then
+ _ErrClearError;
+end;
+
+procedure ErrFreeStrings;
+begin
+ if InitSSLInterface and Assigned(_ErrFreeStrings) then
+ _ErrFreeStrings;
+end;
+
+procedure ErrRemoveState(pid: integer);
+begin
+ if InitSSLInterface and Assigned(_ErrRemoveState) then
+ _ErrRemoveState(pid);
+end;
+
+procedure OPENSSLaddallalgorithms;
+begin
+ if InitSSLInterface and Assigned(_OPENSSLaddallalgorithms) then
+ _OPENSSLaddallalgorithms;
+end;
+
+procedure EVPcleanup;
+begin
+ if InitSSLInterface and Assigned(_EVPcleanup) then
+ _EVPcleanup;
+end;
+
+procedure CRYPTOcleanupAllExData;
+begin
+ if InitSSLInterface and Assigned(_CRYPTOcleanupAllExData) then
+ _CRYPTOcleanupAllExData;
+end;
+
+procedure RandScreen;
+begin
+ if InitSSLInterface and Assigned(_RandScreen) then
+ _RandScreen;
+end;
+
+function BioNew(b: PBIO_METHOD): PBIO;
+begin
+ if InitSSLInterface and Assigned(_BioNew) then
+ Result := _BioNew(b)
+ else
+ Result := nil;
+end;
+
+procedure BioFreeAll(b: PBIO);
+begin
+ if InitSSLInterface and Assigned(_BioFreeAll) then
+ _BioFreeAll(b);
+end;
+
+function BioSMem: PBIO_METHOD;
+begin
+ if InitSSLInterface and Assigned(_BioSMem) then
+ Result := _BioSMem
+ else
+ Result := nil;
+end;
+
+function BioCtrlPending(b: PBIO): integer;
+begin
+ if InitSSLInterface and Assigned(_BioCtrlPending) then
+ Result := _BioCtrlPending(b)
+ else
+ Result := 0;
+end;
+
+//function BioRead(b: PBIO; Buf: PChar; Len: integer): integer;
+function BioRead(b: PBIO; var Buf: AnsiString; Len: integer): integer;
+begin
+ if InitSSLInterface and Assigned(_BioRead) then
+ Result := _BioRead(b, PAnsiChar(Buf), Len)
+ else
+ Result := -2;
+end;
+
+//function BioWrite(b: PBIO; Buf: PChar; Len: integer): integer;
+function BioWrite(b: PBIO; Buf: AnsiString; Len: integer): integer;
+begin
+ if InitSSLInterface and Assigned(_BioWrite) then
+ Result := _BioWrite(b, PAnsiChar(Buf), Len)
+ else
+ Result := -2;
+end;
+
+function X509print(b: PBIO; a: PX509): integer;
+begin
+ if InitSSLInterface and Assigned(_X509print) then
+ Result := _X509print(b, a)
+ else
+ Result := 0;
+end;
+
+function d2iPKCS12bio(b:PBIO; Pkcs12: SslPtr): SslPtr;
+begin
+ if InitSSLInterface and Assigned(_d2iPKCS12bio) then
+ Result := _d2iPKCS12bio(b, Pkcs12)
+ else
+ Result := nil;
+end;
+
+function PKCS12parse(p12: SslPtr; pass: Ansistring; var pkey, cert, ca: SslPtr): integer;
+begin
+ if InitSSLInterface and Assigned(_PKCS12parse) then
+ Result := _PKCS12parse(p12, SslPtr(pass), pkey, cert, ca)
+ else
+ Result := 0;
+end;
+
+procedure PKCS12free(p12: SslPtr);
+begin
+ if InitSSLInterface and Assigned(_PKCS12free) then
+ _PKCS12free(p12);
+end;
+
+function RsaGenerateKey(bits, e: integer; callback: PFunction; cb_arg: SslPtr): PRSA;
+begin
+ if InitSSLInterface and Assigned(_RsaGenerateKey) then
+ Result := _RsaGenerateKey(bits, e, callback, cb_arg)
+ else
+ Result := nil;
+end;
+
+function EvpPkeyAssign(pkey: EVP_PKEY; _type: integer; key: Prsa): integer;
+begin
+ if InitSSLInterface and Assigned(_EvpPkeyAssign) then
+ Result := _EvpPkeyAssign(pkey, _type, key)
+ else
+ Result := 0;
+end;
+
+function X509SetVersion(x: PX509; version: integer): integer;
+begin
+ if InitSSLInterface and Assigned(_X509SetVersion) then
+ Result := _X509SetVersion(x, version)
+ else
+ Result := 0;
+end;
+
+function X509SetPubkey(x: PX509; pkey: EVP_PKEY): integer;
+begin
+ if InitSSLInterface and Assigned(_X509SetPubkey) then
+ Result := _X509SetPubkey(x, pkey)
+ else
+ Result := 0;
+end;
+
+function X509SetIssuerName(x: PX509; name: PX509_NAME): integer;
+begin
+ if InitSSLInterface and Assigned(_X509SetIssuerName) then
+ Result := _X509SetIssuerName(x, name)
+ else
+ Result := 0;
+end;
+
+function X509NameAddEntryByTxt(name: PX509_NAME; field: Ansistring; _type: integer;
+ bytes: Ansistring; len, loc, _set: integer): integer;
+begin
+ if InitSSLInterface and Assigned(_X509NameAddEntryByTxt) then
+ Result := _X509NameAddEntryByTxt(name, PAnsiChar(field), _type, PAnsiChar(Bytes), len, loc, _set)
+ else
+ Result := 0;
+end;
+
+function X509Sign(x: PX509; pkey: EVP_PKEY; const md: PEVP_MD): integer;
+begin
+ if InitSSLInterface and Assigned(_X509Sign) then
+ Result := _X509Sign(x, pkey, md)
+ else
+ Result := 0;
+end;
+
+function Asn1UtctimeNew: PASN1_UTCTIME;
+begin
+ if InitSSLInterface and Assigned(_Asn1UtctimeNew) then
+ Result := _Asn1UtctimeNew
+ else
+ Result := nil;
+end;
+
+procedure Asn1UtctimeFree(a: PASN1_UTCTIME);
+begin
+ if InitSSLInterface and Assigned(_Asn1UtctimeFree) then
+ _Asn1UtctimeFree(a);
+end;
+
+function X509GmtimeAdj(s: PASN1_UTCTIME; adj: integer): PASN1_UTCTIME;
+begin
+ if InitSSLInterface and Assigned(_X509GmtimeAdj) then
+ Result := _X509GmtimeAdj(s, adj)
+ else
+ Result := nil;
+end;
+
+function X509SetNotBefore(x: PX509; tm: PASN1_UTCTIME): integer;
+begin
+ if InitSSLInterface and Assigned(_X509SetNotBefore) then
+ Result := _X509SetNotBefore(x, tm)
+ else
+ Result := 0;
+end;
+
+function X509SetNotAfter(x: PX509; tm: PASN1_UTCTIME): integer;
+begin
+ if InitSSLInterface and Assigned(_X509SetNotAfter) then
+ Result := _X509SetNotAfter(x, tm)
+ else
+ Result := 0;
+end;
+
+function i2dX509bio(b: PBIO; x: PX509): integer;
+begin
+ if InitSSLInterface and Assigned(_i2dX509bio) then
+ Result := _i2dX509bio(b, x)
+ else
+ Result := 0;
+end;
+
+function i2dPrivateKeyBio(b: PBIO; pkey: EVP_PKEY): integer;
+begin
+ if InitSSLInterface and Assigned(_i2dPrivateKeyBio) then
+ Result := _i2dPrivateKeyBio(b, pkey)
+ else
+ Result := 0;
+end;
+
+function EvpGetDigestByName(Name: AnsiString): PEVP_MD;
+begin
+ if InitSSLInterface and Assigned(_EvpGetDigestByName) then
+ Result := _EvpGetDigestByName(PAnsiChar(Name))
+ else
+ Result := nil;
+end;
+
+function Asn1IntegerSet(a: PASN1_INTEGER; v: integer): integer;
+begin
+ if InitSSLInterface and Assigned(_Asn1IntegerSet) then
+ Result := _Asn1IntegerSet(a, v)
+ else
+ Result := 0;
+end;
+
+function X509GetSerialNumber(x: PX509): PASN1_INTEGER;
+begin
+ if InitSSLInterface and Assigned(_X509GetSerialNumber) then
+ Result := _X509GetSerialNumber(x)
+ else
+ Result := nil;
+end;
+
+// 3DES functions
+procedure DESsetoddparity(Key: des_cblock);
+begin
+ if InitSSLInterface and Assigned(_DESsetoddparity) then
+ _DESsetoddparity(Key);
+end;
+
+function DESsetkeychecked(key: des_cblock; schedule: des_key_schedule): Integer;
+begin
+ if InitSSLInterface and Assigned(_DESsetkeychecked) then
+ Result := _DESsetkeychecked(key, schedule)
+ else
+ Result := -1;
+end;
+
+procedure DESecbencrypt(Input: des_cblock; output: des_cblock; ks: des_key_schedule; enc: Integer);
+begin
+ if InitSSLInterface and Assigned(_DESecbencrypt) then
+ _DESecbencrypt(Input, output, ks, enc);
+end;
+
+procedure locking_callback(mode, ltype: integer; lfile: PChar; line: integer); cdecl;
+begin
+ if (mode and 1) > 0 then
+ TCriticalSection(Locks[ltype]).Enter
+ else
+ TCriticalSection(Locks[ltype]).Leave;
+end;
+
+procedure InitLocks;
+var
+ n: integer;
+ max: integer;
+begin
+ Locks := TList.Create;
+ max := _CRYPTOnumlocks;
+ for n := 1 to max do
+ Locks.Add(TCriticalSection.Create);
+ _CRYPTOsetlockingcallback(@locking_callback);
+end;
+
+procedure FreeLocks;
+var
+ n: integer;
+begin
+ _CRYPTOsetlockingcallback(nil);
+ for n := 0 to Locks.Count - 1 do
+ TCriticalSection(Locks[n]).Free;
+ Locks.Free;
+end;
+
+{$ENDIF}
+
+function LoadLib(const Value: String): HModule;
+begin
+{$IFDEF CIL}
+ Result := LoadLibrary(Value);
+{$ELSE}
+ Result := LoadLibrary(PChar(Value));
+{$ENDIF}
+end;
+
+function GetProcAddr(module: HModule; const ProcName: string): SslPtr;
+begin
+{$IFDEF CIL}
+ Result := GetProcAddress(module, ProcName);
+{$ELSE}
+ Result := GetProcAddress(module, PChar(ProcName));
+{$ENDIF}
+end;
+
+function InitSSLInterface: Boolean;
+var
+ s: string;
+ x: integer;
+begin
+ SSLCS.Enter;
+ try
+ if not IsSSLloaded then
+ begin
+{$IFDEF CIL}
+ SSLLibHandle := 1;
+ SSLUtilHandle := 1;
+{$ELSE}
+ SSLLibHandle := LoadLib(DLLSSLName);
+ SSLUtilHandle := LoadLib(DLLUtilName);
+ {$IFNDEF LINUX}
+ if (SSLLibHandle = 0) then
+ SSLLibHandle := LoadLib(DLLSSLName2);
+ {$ENDIF}
+{$ENDIF}
+ if (SSLLibHandle <> 0) and (SSLUtilHandle <> 0) then
+ begin
+{$IFNDEF CIL}
+ _SslGetError := GetProcAddr(SSLLibHandle, 'SSL_get_error');
+ _SslLibraryInit := GetProcAddr(SSLLibHandle, 'SSL_library_init');
+ _SslLoadErrorStrings := GetProcAddr(SSLLibHandle, 'SSL_load_error_strings');
+ _SslCtxSetCipherList := GetProcAddr(SSLLibHandle, 'SSL_CTX_set_cipher_list');
+ _SslCtxNew := GetProcAddr(SSLLibHandle, 'SSL_CTX_new');
+ _SslCtxFree := GetProcAddr(SSLLibHandle, 'SSL_CTX_free');
+ _SslSetFd := GetProcAddr(SSLLibHandle, 'SSL_set_fd');
+ _SslMethodV2 := GetProcAddr(SSLLibHandle, 'SSLv2_method');
+ _SslMethodV3 := GetProcAddr(SSLLibHandle, 'SSLv3_method');
+ _SslMethodTLSV1 := GetProcAddr(SSLLibHandle, 'TLSv1_method');
+ _SslMethodV23 := GetProcAddr(SSLLibHandle, 'SSLv23_method');
+ _SslCtxUsePrivateKey := GetProcAddr(SSLLibHandle, 'SSL_CTX_use_PrivateKey');
+ _SslCtxUsePrivateKeyASN1 := GetProcAddr(SSLLibHandle, 'SSL_CTX_use_PrivateKey_ASN1');
+ //use SSL_CTX_use_RSAPrivateKey_file instead SSL_CTX_use_PrivateKey_file,
+ //because SSL_CTX_use_PrivateKey_file not support DER format. :-O
+ _SslCtxUsePrivateKeyFile := GetProcAddr(SSLLibHandle, 'SSL_CTX_use_RSAPrivateKey_file');
+ _SslCtxUseCertificate := GetProcAddr(SSLLibHandle, 'SSL_CTX_use_certificate');
+ _SslCtxUseCertificateASN1 := GetProcAddr(SSLLibHandle, 'SSL_CTX_use_certificate_ASN1');
+ _SslCtxUseCertificateFile := GetProcAddr(SSLLibHandle, 'SSL_CTX_use_certificate_file');
+ _SslCtxUseCertificateChainFile := GetProcAddr(SSLLibHandle, 'SSL_CTX_use_certificate_chain_file');
+ _SslCtxCheckPrivateKeyFile := GetProcAddr(SSLLibHandle, 'SSL_CTX_check_private_key');
+ _SslCtxSetDefaultPasswdCb := GetProcAddr(SSLLibHandle, 'SSL_CTX_set_default_passwd_cb');
+ _SslCtxSetDefaultPasswdCbUserdata := GetProcAddr(SSLLibHandle, 'SSL_CTX_set_default_passwd_cb_userdata');
+ _SslCtxLoadVerifyLocations := GetProcAddr(SSLLibHandle, 'SSL_CTX_load_verify_locations');
+ _SslNew := GetProcAddr(SSLLibHandle, 'SSL_new');
+ _SslFree := GetProcAddr(SSLLibHandle, 'SSL_free');
+ _SslAccept := GetProcAddr(SSLLibHandle, 'SSL_accept');
+ _SslConnect := GetProcAddr(SSLLibHandle, 'SSL_connect');
+ _SslShutdown := GetProcAddr(SSLLibHandle, 'SSL_shutdown');
+ _SslRead := GetProcAddr(SSLLibHandle, 'SSL_read');
+ _SslPeek := GetProcAddr(SSLLibHandle, 'SSL_peek');
+ _SslWrite := GetProcAddr(SSLLibHandle, 'SSL_write');
+ _SslPending := GetProcAddr(SSLLibHandle, 'SSL_pending');
+ _SslGetPeerCertificate := GetProcAddr(SSLLibHandle, 'SSL_get_peer_certificate');
+ _SslGetVersion := GetProcAddr(SSLLibHandle, 'SSL_get_version');
+ _SslCtxSetVerify := GetProcAddr(SSLLibHandle, 'SSL_CTX_set_verify');
+ _SslGetCurrentCipher := GetProcAddr(SSLLibHandle, 'SSL_get_current_cipher');
+ _SslCipherGetName := GetProcAddr(SSLLibHandle, 'SSL_CIPHER_get_name');
+ _SslCipherGetBits := GetProcAddr(SSLLibHandle, 'SSL_CIPHER_get_bits');
+ _SslGetVerifyResult := GetProcAddr(SSLLibHandle, 'SSL_get_verify_result');
+
+ _X509New := GetProcAddr(SSLUtilHandle, 'X509_new');
+ _X509Free := GetProcAddr(SSLUtilHandle, 'X509_free');
+ _X509NameOneline := GetProcAddr(SSLUtilHandle, 'X509_NAME_oneline');
+ _X509GetSubjectName := GetProcAddr(SSLUtilHandle, 'X509_get_subject_name');
+ _X509GetIssuerName := GetProcAddr(SSLUtilHandle, 'X509_get_issuer_name');
+ _X509NameHash := GetProcAddr(SSLUtilHandle, 'X509_NAME_hash');
+ _X509Digest := GetProcAddr(SSLUtilHandle, 'X509_digest');
+ _X509print := GetProcAddr(SSLUtilHandle, 'X509_print');
+ _X509SetVersion := GetProcAddr(SSLUtilHandle, 'X509_set_version');
+ _X509SetPubkey := GetProcAddr(SSLUtilHandle, 'X509_set_pubkey');
+ _X509SetIssuerName := GetProcAddr(SSLUtilHandle, 'X509_set_issuer_name');
+ _X509NameAddEntryByTxt := GetProcAddr(SSLUtilHandle, 'X509_NAME_add_entry_by_txt');
+ _X509Sign := GetProcAddr(SSLUtilHandle, 'X509_sign');
+ _X509GmtimeAdj := GetProcAddr(SSLUtilHandle, 'X509_gmtime_adj');
+ _X509SetNotBefore := GetProcAddr(SSLUtilHandle, 'X509_set_notBefore');
+ _X509SetNotAfter := GetProcAddr(SSLUtilHandle, 'X509_set_notAfter');
+ _X509GetSerialNumber := GetProcAddr(SSLUtilHandle, 'X509_get_serialNumber');
+ _EvpPkeyNew := GetProcAddr(SSLUtilHandle, 'EVP_PKEY_new');
+ _EvpPkeyFree := GetProcAddr(SSLUtilHandle, 'EVP_PKEY_free');
+ _EvpPkeyAssign := GetProcAddr(SSLUtilHandle, 'EVP_PKEY_assign');
+ _EVPCleanup := GetProcAddr(SSLUtilHandle, 'EVP_cleanup');
+ _EvpGetDigestByName := GetProcAddr(SSLUtilHandle, 'EVP_get_digestbyname');
+ _SSLeayversion := GetProcAddr(SSLUtilHandle, 'SSLeay_version');
+ _ErrErrorString := GetProcAddr(SSLUtilHandle, 'ERR_error_string_n');
+ _ErrGetError := GetProcAddr(SSLUtilHandle, 'ERR_get_error');
+ _ErrClearError := GetProcAddr(SSLUtilHandle, 'ERR_clear_error');
+ _ErrFreeStrings := GetProcAddr(SSLUtilHandle, 'ERR_free_strings');
+ _ErrRemoveState := GetProcAddr(SSLUtilHandle, 'ERR_remove_state');
+ _OPENSSLaddallalgorithms := GetProcAddr(SSLUtilHandle, 'OPENSSL_add_all_algorithms_noconf');
+ _CRYPTOcleanupAllExData := GetProcAddr(SSLUtilHandle, 'CRYPTO_cleanup_all_ex_data');
+ _RandScreen := GetProcAddr(SSLUtilHandle, 'RAND_screen');
+ _BioNew := GetProcAddr(SSLUtilHandle, 'BIO_new');
+ _BioFreeAll := GetProcAddr(SSLUtilHandle, 'BIO_free_all');
+ _BioSMem := GetProcAddr(SSLUtilHandle, 'BIO_s_mem');
+ _BioCtrlPending := GetProcAddr(SSLUtilHandle, 'BIO_ctrl_pending');
+ _BioRead := GetProcAddr(SSLUtilHandle, 'BIO_read');
+ _BioWrite := GetProcAddr(SSLUtilHandle, 'BIO_write');
+ _d2iPKCS12bio := GetProcAddr(SSLUtilHandle, 'd2i_PKCS12_bio');
+ _PKCS12parse := GetProcAddr(SSLUtilHandle, 'PKCS12_parse');
+ _PKCS12free := GetProcAddr(SSLUtilHandle, 'PKCS12_free');
+ _RsaGenerateKey := GetProcAddr(SSLUtilHandle, 'RSA_generate_key');
+ _Asn1UtctimeNew := GetProcAddr(SSLUtilHandle, 'ASN1_UTCTIME_new');
+ _Asn1UtctimeFree := GetProcAddr(SSLUtilHandle, 'ASN1_UTCTIME_free');
+ _Asn1IntegerSet := GetProcAddr(SSLUtilHandle, 'ASN1_INTEGER_set');
+ _i2dX509bio := GetProcAddr(SSLUtilHandle, 'i2d_X509_bio');
+ _i2dPrivateKeyBio := GetProcAddr(SSLUtilHandle, 'i2d_PrivateKey_bio');
+
+ // 3DES functions
+ _DESsetoddparity := GetProcAddr(SSLUtilHandle, 'DES_set_odd_parity');
+ _DESsetkeychecked := GetProcAddr(SSLUtilHandle, 'DES_set_key_checked');
+ _DESecbencrypt := GetProcAddr(SSLUtilHandle, 'DES_ecb_encrypt');
+ //
+ _CRYPTOnumlocks := GetProcAddr(SSLUtilHandle, 'CRYPTO_num_locks');
+ _CRYPTOsetlockingcallback := GetProcAddr(SSLUtilHandle, 'CRYPTO_set_locking_callback');
+{$ENDIF}
+{$IFDEF CIL}
+ SslLibraryInit;
+ SslLoadErrorStrings;
+ OPENSSLaddallalgorithms;
+ RandScreen;
+{$ELSE}
+ SetLength(s, 1024);
+ x := GetModuleFilename(SSLLibHandle,PChar(s),Length(s));
+ SetLength(s, x);
+ SSLLibFile := s;
+ SetLength(s, 1024);
+ x := GetModuleFilename(SSLUtilHandle,PChar(s),Length(s));
+ SetLength(s, x);
+ SSLUtilFile := s;
+ //init library
+ if assigned(_SslLibraryInit) then
+ _SslLibraryInit;
+ if assigned(_SslLoadErrorStrings) then
+ _SslLoadErrorStrings;
+ if assigned(_OPENSSLaddallalgorithms) then
+ _OPENSSLaddallalgorithms;
+ if assigned(_RandScreen) then
+ _RandScreen;
+ if assigned(_CRYPTOnumlocks) and assigned(_CRYPTOsetlockingcallback) then
+ InitLocks;
+{$ENDIF}
+ Result := True;
+ SSLloaded := True;
+ end
+ else
+ begin
+ //load failed!
+ if SSLLibHandle <> 0 then
+ begin
+{$IFNDEF CIL}
+ FreeLibrary(SSLLibHandle);
+{$ENDIF}
+ SSLLibHandle := 0;
+ end;
+ if SSLUtilHandle <> 0 then
+ begin
+{$IFNDEF CIL}
+ FreeLibrary(SSLUtilHandle);
+{$ENDIF}
+ SSLLibHandle := 0;
+ end;
+ Result := False;
+ end;
+ end
+ else
+ //loaded before...
+ Result := true;
+ finally
+ SSLCS.Leave;
+ end;
+end;
+
+function DestroySSLInterface: Boolean;
+begin
+ SSLCS.Enter;
+ try
+ if IsSSLLoaded then
+ begin
+ //deinit library
+{$IFNDEF CIL}
+ if assigned(_CRYPTOnumlocks) and assigned(_CRYPTOsetlockingcallback) then
+ FreeLocks;
+{$ENDIF}
+ EVPCleanup;
+ CRYPTOcleanupAllExData;
+ ErrRemoveState(0);
+ end;
+ SSLloaded := false;
+ if SSLLibHandle <> 0 then
+ begin
+{$IFNDEF CIL}
+ FreeLibrary(SSLLibHandle);
+{$ENDIF}
+ SSLLibHandle := 0;
+ end;
+ if SSLUtilHandle <> 0 then
+ begin
+{$IFNDEF CIL}
+ FreeLibrary(SSLUtilHandle);
+{$ENDIF}
+ SSLLibHandle := 0;
+ end;
+
+{$IFNDEF CIL}
+ _SslGetError := nil;
+ _SslLibraryInit := nil;
+ _SslLoadErrorStrings := nil;
+ _SslCtxSetCipherList := nil;
+ _SslCtxNew := nil;
+ _SslCtxFree := nil;
+ _SslSetFd := nil;
+ _SslMethodV2 := nil;
+ _SslMethodV3 := nil;
+ _SslMethodTLSV1 := nil;
+ _SslMethodV23 := nil;
+ _SslCtxUsePrivateKey := nil;
+ _SslCtxUsePrivateKeyASN1 := nil;
+ _SslCtxUsePrivateKeyFile := nil;
+ _SslCtxUseCertificate := nil;
+ _SslCtxUseCertificateASN1 := nil;
+ _SslCtxUseCertificateFile := nil;
+ _SslCtxUseCertificateChainFile := nil;
+ _SslCtxCheckPrivateKeyFile := nil;
+ _SslCtxSetDefaultPasswdCb := nil;
+ _SslCtxSetDefaultPasswdCbUserdata := nil;
+ _SslCtxLoadVerifyLocations := nil;
+ _SslNew := nil;
+ _SslFree := nil;
+ _SslAccept := nil;
+ _SslConnect := nil;
+ _SslShutdown := nil;
+ _SslRead := nil;
+ _SslPeek := nil;
+ _SslWrite := nil;
+ _SslPending := nil;
+ _SslGetPeerCertificate := nil;
+ _SslGetVersion := nil;
+ _SslCtxSetVerify := nil;
+ _SslGetCurrentCipher := nil;
+ _SslCipherGetName := nil;
+ _SslCipherGetBits := nil;
+ _SslGetVerifyResult := nil;
+
+ _X509New := nil;
+ _X509Free := nil;
+ _X509NameOneline := nil;
+ _X509GetSubjectName := nil;
+ _X509GetIssuerName := nil;
+ _X509NameHash := nil;
+ _X509Digest := nil;
+ _X509print := nil;
+ _X509SetVersion := nil;
+ _X509SetPubkey := nil;
+ _X509SetIssuerName := nil;
+ _X509NameAddEntryByTxt := nil;
+ _X509Sign := nil;
+ _X509GmtimeAdj := nil;
+ _X509SetNotBefore := nil;
+ _X509SetNotAfter := nil;
+ _X509GetSerialNumber := nil;
+ _EvpPkeyNew := nil;
+ _EvpPkeyFree := nil;
+ _EvpPkeyAssign := nil;
+ _EVPCleanup := nil;
+ _EvpGetDigestByName := nil;
+ _SSLeayversion := nil;
+ _ErrErrorString := nil;
+ _ErrGetError := nil;
+ _ErrClearError := nil;
+ _ErrFreeStrings := nil;
+ _ErrRemoveState := nil;
+ _OPENSSLaddallalgorithms := nil;
+ _CRYPTOcleanupAllExData := nil;
+ _RandScreen := nil;
+ _BioNew := nil;
+ _BioFreeAll := nil;
+ _BioSMem := nil;
+ _BioCtrlPending := nil;
+ _BioRead := nil;
+ _BioWrite := nil;
+ _d2iPKCS12bio := nil;
+ _PKCS12parse := nil;
+ _PKCS12free := nil;
+ _RsaGenerateKey := nil;
+ _Asn1UtctimeNew := nil;
+ _Asn1UtctimeFree := nil;
+ _Asn1IntegerSet := nil;
+ _i2dX509bio := nil;
+ _i2dPrivateKeyBio := nil;
+
+ // 3DES functions
+ _DESsetoddparity := nil;
+ _DESsetkeychecked := nil;
+ _DESecbencrypt := nil;
+ //
+ _CRYPTOnumlocks := nil;
+ _CRYPTOsetlockingcallback := nil;
+{$ENDIF}
+ finally
+ SSLCS.Leave;
+ end;
+ Result := True;
+end;
+
+function IsSSLloaded: Boolean;
+begin
+ Result := SSLLoaded;
+end;
+
+initialization
+begin
+ SSLCS:= TCriticalSection.Create;
+end;
+
+finalization
+begin
+{$IFNDEF CIL}
+ DestroySSLInterface;
+{$ENDIF}
+ SSLCS.Free;
+end;
+
+end.
diff --git a/branches/script-component/Units/Synapse/ssl_sbb.pas b/branches/script-component/Units/Synapse/ssl_sbb.pas
new file mode 100644
index 0000000..c9380a4
--- /dev/null
+++ b/branches/script-component/Units/Synapse/ssl_sbb.pas
@@ -0,0 +1,697 @@
+{==============================================================================|
+| Project : Ararat Synapse | 001.000.003 |
+|==============================================================================|
+| Content: SSL support for SecureBlackBox |
+|==============================================================================|
+| Copyright (c)1999-2005, Lukas Gebauer |
+| All rights reserved. |
+| |
+| Redistribution and use in source and binary forms, with or without |
+| modification, are permitted provided that the following conditions are met: |
+| |
+| Redistributions of source code must retain the above copyright notice, this |
+| list of conditions and the following disclaimer. |
+| |
+| Redistributions in binary form must reproduce the above copyright notice, |
+| this list of conditions and the following disclaimer in the documentation |
+| and/or other materials provided with the distribution. |
+| |
+| Neither the name of Lukas Gebauer nor the names of its contributors may |
+| be used to endorse or promote products derived from this software without |
+| specific prior written permission. |
+| |
+| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
+| AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
+| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
+| ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR |
+| ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
+| DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
+| SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
+| CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
+| LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
+| OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
+| DAMAGE. |
+|==============================================================================|
+| The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).|
+| Portions created by Lukas Gebauer are Copyright (c)2005. |
+| All Rights Reserved. |
+|==============================================================================|
+| Contributor(s): |
+| Allen Drennan (adrennan@wiredred.com) |
+|==============================================================================|
+| History: see HISTORY.HTM from distribution package |
+| (Found at URL: http://www.ararat.cz/synapse/) |
+|==============================================================================}
+
+{:@abstract(SSL plugin for Eldos SecureBlackBox)
+
+For handling keys and certificates you can use this properties:
+@link(TCustomSSL.CertCAFile), @link(TCustomSSL.CertCA),
+@link(TCustomSSL.TrustCertificateFile), @link(TCustomSSL.TrustCertificate),
+@link(TCustomSSL.PrivateKeyFile), @link(TCustomSSL.PrivateKey),
+@link(TCustomSSL.CertificateFile), @link(TCustomSSL.Certificate),
+@link(TCustomSSL.PFXFile). For usage of this properties and for possible formats
+of keys and certificates refer to SecureBlackBox documentation.
+}
+
+{$IFDEF FPC}
+ {$MODE DELPHI}
+{$ENDIF}
+{$H+}
+
+unit ssl_sbb;
+
+interface
+
+uses
+ SysUtils, Classes, Windows, blcksock, synsock, synautil, synacode,
+ SBClient, SBServer, SBX509, SBWinCertStorage, SBCustomCertStorage,
+ SBUtils, SBConstants, SBSessionPool;
+
+const
+ DEFAULT_RECV_BUFFER=32768;
+
+type
+ {:@abstract(class implementing SecureBlackbox SSL plugin.)
+ Instance of this class will be created for each @link(TTCPBlockSocket).
+ You not need to create instance of this class, all is done by Synapse itself!}
+ TSSLSBB=class(TCustomSSL)
+ protected
+ FServer: Boolean;
+ FElSecureClient:TElSecureClient;
+ FElSecureServer:TElSecureServer;
+ FElCertStorage:TElMemoryCertStorage;
+ FElX509Certificate:TElX509Certificate;
+ FElX509CACertificate:TElX509Certificate;
+ FCipherSuites:TBits;
+ private
+ FRecvBuffer:String;
+ FRecvBuffers:String;
+ FRecvBuffersLock:TRTLCriticalSection;
+ FRecvDecodedBuffers:String;
+ function GetCipherSuite:Integer;
+ procedure Reset;
+ function Prepare(Server:Boolean):Boolean;
+ procedure OnError(Sender:TObject; ErrorCode:Integer; Fatal:Boolean; Remote:Boolean);
+ procedure OnSend(Sender:TObject;Buffer:Pointer;Size:LongInt);
+ procedure OnReceive(Sender:TObject;Buffer:Pointer;MaxSize:LongInt;var Written:LongInt);
+ procedure OnData(Sender:TObject;Buffer:Pointer;Size:LongInt);
+ public
+ constructor Create(const Value: TTCPBlockSocket); override;
+ destructor Destroy; override;
+ {:See @inherited}
+ function LibVersion: String; override;
+ {:See @inherited}
+ function LibName: String; override;
+ {:See @inherited and @link(ssl_sbb) for more details.}
+ function Connect: boolean; override;
+ {:See @inherited and @link(ssl_sbb) for more details.}
+ function Accept: boolean; override;
+ {:See @inherited}
+ function Shutdown: boolean; override;
+ {:See @inherited}
+ function BiShutdown: boolean; override;
+ {:See @inherited}
+ function SendBuffer(Buffer: TMemory; Len: Integer): Integer; override;
+ {:See @inherited}
+ function RecvBuffer(Buffer: TMemory; Len: Integer): Integer; override;
+ {:See @inherited}
+ function WaitingData: Integer; override;
+ {:See @inherited}
+ function GetSSLVersion: string; override;
+ {:See @inherited}
+ function GetPeerSubject: string; override;
+ {:See @inherited}
+ function GetPeerIssuer: string; override;
+ {:See @inherited}
+ function GetPeerName: string; override;
+ {:See @inherited}
+ function GetPeerFingerprint: string; override;
+ {:See @inherited}
+ function GetCertInfo: string; override;
+ published
+ property ElSecureClient:TElSecureClient read FElSecureClient write FElSecureClient;
+ property ElSecureServer:TElSecureServer read FElSecureServer write FElSecureServer;
+ property CipherSuites:TBits read FCipherSuites write FCipherSuites;
+ property CipherSuite:Integer read GetCipherSuite;
+ end;
+
+implementation
+
+var
+ FAcceptThread:THandle=0;
+
+// on error
+procedure TSSLSBB.OnError(Sender:TObject; ErrorCode:Integer; Fatal:Boolean; Remote:Boolean);
+
+begin
+ FLastErrorDesc:='';
+ FLastError:=ErrorCode;
+end;
+
+// on send
+procedure TSSLSBB.OnSend(Sender:TObject;Buffer:Pointer;Size:LongInt);
+
+var
+ lResult:Integer;
+
+begin
+ if FSocket.Socket=INVALID_SOCKET then
+ Exit;
+ lResult:=Send(FSocket.Socket,Buffer,Size,0);
+ if lResult=SOCKET_ERROR then
+ begin
+ FLastErrorDesc:='';
+ FLastError:=WSAGetLastError;
+ end;
+end;
+
+// on receive
+procedure TSSLSBB.OnReceive(Sender:TObject;Buffer:Pointer;MaxSize:LongInt;var Written:LongInt);
+
+begin
+ if GetCurrentThreadId<>FAcceptThread then EnterCriticalSection(FRecvBuffersLock);
+ try
+ if Length(FRecvBuffers)<=MaxSize then
+ begin
+ Written:=Length(FRecvBuffers);
+ Move(FRecvBuffers[1],Buffer^,Written);
+ FRecvBuffers:='';
+ end
+ else
+ begin
+ Written:=MaxSize;
+ Move(FRecvBuffers[1],Buffer^,Written);
+ Delete(FRecvBuffers,1,Written);
+ end;
+ finally
+ if GetCurrentThreadId<>FAcceptThread then LeaveCriticalSection(FRecvBuffersLock);
+ end;
+end;
+
+// on data
+procedure TSSLSBB.OnData(Sender:TObject;Buffer:Pointer;Size:LongInt);
+
+var
+ lString:String;
+
+begin
+ SetLength(lString,Size);
+ Move(Buffer^,lString[1],Size);
+ FRecvDecodedBuffers:=FRecvDecodedBuffers+lString;
+end;
+
+{ inherited }
+
+constructor TSSLSBB.Create(const Value: TTCPBlockSocket);
+
+var
+ loop1:Integer;
+
+begin
+ inherited Create(Value);
+ FServer:=FALSE;
+ FElSecureClient:=NIL;
+ FElSecureServer:=NIL;
+ FElCertStorage:=NIL;
+ FElX509Certificate:=NIL;
+ FElX509CACertificate:=NIL;
+ SetLength(FRecvBuffer,DEFAULT_RECV_BUFFER);
+ FRecvBuffers:='';
+ InitializeCriticalSection(FRecvBuffersLock);
+ FRecvDecodedBuffers:='';
+ FCipherSuites:=TBits.Create;
+ if FCipherSuites<>NIL then
+ begin
+ FCipherSuites.Size:=SB_SUITE_LAST+1;
+ for loop1:=SB_SUITE_FIRST to SB_SUITE_LAST do
+ FCipherSuites[loop1]:=TRUE;
+ end;
+end;
+
+destructor TSSLSBB.Destroy;
+
+begin
+ Reset;
+ inherited Destroy;
+ if FCipherSuites<>NIL then
+ FreeAndNIL(FCipherSuites);
+ DeleteCriticalSection(FRecvBuffersLock);
+end;
+
+function TSSLSBB.LibVersion: String;
+
+begin
+ Result:='SecureBlackBox';
+end;
+
+function TSSLSBB.LibName: String;
+
+begin
+ Result:='ssl_sbb';
+end;
+
+function FileToString(lFile:String):String;
+
+var
+ lStream:TMemoryStream;
+
+begin
+ Result:='';
+ lStream:=TMemoryStream.Create;
+ if lStream<>NIL then
+ begin
+ lStream.LoadFromFile(lFile);
+ if lStream.Size>0 then
+ begin
+ lStream.Position:=0;
+ SetLength(Result,lStream.Size);
+ Move(lStream.Memory^,Result[1],lStream.Size);
+ end;
+ lStream.Free;
+ end;
+end;
+
+function TSSLSBB.GetCipherSuite:Integer;
+
+begin
+ if FServer then
+ Result:=FElSecureServer.CipherSuite
+ else
+ Result:=FElSecureClient.CipherSuite;
+end;
+
+procedure TSSLSBB.Reset;
+
+begin
+ if FElSecureServer<>NIL then
+ FreeAndNIL(FElSecureServer);
+ if FElSecureClient<>NIL then
+ FreeAndNIL(FElSecureClient);
+ if FElX509Certificate<>NIL then
+ FreeAndNIL(FElX509Certificate);
+ if FElX509CACertificate<>NIL then
+ FreeAndNIL(FElX509CACertificate);
+ if FElCertStorage<>NIL then
+ FreeAndNIL(FElCertStorage);
+ FSSLEnabled:=FALSE;
+end;
+
+function TSSLSBB.Prepare(Server:Boolean): Boolean;
+
+var
+ loop1:Integer;
+ lStream:TMemoryStream;
+ lCertificate,lPrivateKey,lCertCA:String;
+
+begin
+ Result:=FALSE;
+ FServer:=Server;
+
+ // reset, if necessary
+ Reset;
+
+ // init, certificate
+ if FCertificateFile<>'' then
+ lCertificate:=FileToString(FCertificateFile)
+ else
+ lCertificate:=FCertificate;
+ if FPrivateKeyFile<>'' then
+ lPrivateKey:=FileToString(FPrivateKeyFile)
+ else
+ lPrivateKey:=FPrivateKey;
+ if FCertCAFile<>'' then
+ lCertCA:=FileToString(FCertCAFile)
+ else
+ lCertCA:=FCertCA;
+ if (lCertificate<>'') and (lPrivateKey<>'') then
+ begin
+ FElCertStorage:=TElMemoryCertStorage.Create(NIL);
+ if FElCertStorage<>NIL then
+ FElCertStorage.Clear;
+
+ // apply ca certificate
+ if lCertCA<>'' then
+ begin
+ FElX509CACertificate:=TElX509Certificate.Create(NIL);
+ if FElX509CACertificate<>NIL then
+ begin
+ with FElX509CACertificate do
+ begin
+ lStream:=TMemoryStream.Create;
+ try
+ WriteStrToStream(lStream,lCertCA);
+ lStream.Seek(0,soFromBeginning);
+ LoadFromStream(lStream);
+ finally
+ lStream.Free;
+ end;
+ end;
+ if FElCertStorage<>NIL then
+ FElCertStorage.Add(FElX509CACertificate);
+ end;
+ end;
+
+ // apply certificate
+ FElX509Certificate:=TElX509Certificate.Create(NIL);
+ if FElX509Certificate<>NIL then
+ begin
+ with FElX509Certificate do
+ begin
+ lStream:=TMemoryStream.Create;
+ try
+ WriteStrToStream(lStream,lCertificate);
+ lStream.Seek(0,soFromBeginning);
+ LoadFromStream(lStream);
+ finally
+ lStream.Free;
+ end;
+ lStream:=TMemoryStream.Create;
+ try
+ WriteStrToStream(lStream,lPrivateKey);
+ lStream.Seek(0,soFromBeginning);
+ LoadKeyFromStream(lStream);
+ finally
+ lStream.Free;
+ end;
+ if FElCertStorage<>NIL then
+ FElCertStorage.Add(FElX509Certificate);
+ end;
+ end;
+ end;
+
+ // init, as server
+ if FServer then
+ begin
+ FElSecureServer:=TElSecureServer.Create(NIL);
+ if FElSecureServer<>NIL then
+ begin
+ // init, ciphers
+ for loop1:=SB_SUITE_FIRST to SB_SUITE_LAST do
+ FElSecureServer.CipherSuites[loop1]:=FCipherSuites[loop1];
+ FElSecureServer.Versions:=[sbSSL2,sbSSL3,sbTLS1];
+ FElSecureServer.ClientAuthentication:=FALSE;
+ FElSecureServer.OnError:=OnError;
+ FElSecureServer.OnSend:=OnSend;
+ FElSecureServer.OnReceive:=OnReceive;
+ FElSecureServer.OnData:=OnData;
+ FElSecureServer.CertStorage:=FElCertStorage;
+ Result:=TRUE;
+ end;
+ end
+ else
+ // init, as client
+ begin
+ FElSecureClient:=TElSecureClient.Create(NIL);
+ if FElSecureClient<>NIL then
+ begin
+ // init, ciphers
+ for loop1:=SB_SUITE_FIRST to SB_SUITE_LAST do
+ FElSecureClient.CipherSuites[loop1]:=FCipherSuites[loop1];
+ FElSecureClient.Versions:=[sbSSL3,sbTLS1];
+ FElSecureClient.OnError:=OnError;
+ FElSecureClient.OnSend:=OnSend;
+ FElSecureClient.OnReceive:=OnReceive;
+ FElSecureClient.OnData:=OnData;
+ FElSecureClient.CertStorage:=FElCertStorage;
+ Result:=TRUE;
+ end;
+ end;
+end;
+
+function TSSLSBB.Connect:Boolean;
+
+var
+ lResult:Integer;
+
+begin
+ Result:=FALSE;
+ if FSocket.Socket=INVALID_SOCKET then
+ Exit;
+ if Prepare(FALSE) then
+ begin
+ FElSecureClient.Open;
+
+ // reset
+ FRecvBuffers:='';
+ FRecvDecodedBuffers:='';
+
+ // wait for open or error
+ while (not FElSecureClient.Active) and
+ (FLastError=0) do
+ begin
+ // data available?
+ if FRecvBuffers<>'' then
+ FElSecureClient.DataAvailable
+ else
+ begin
+ // socket recv
+ lResult:=Recv(FSocket.Socket,@FRecvBuffer[1],Length(FRecvBuffer),0);
+ if lResult=SOCKET_ERROR then
+ begin
+ FLastErrorDesc:='';
+ FLastError:=WSAGetLastError;
+ end
+ else
+ begin
+ if lResult>0 then
+ FRecvBuffers:=FRecvBuffers+Copy(FRecvBuffer,1,lResult)
+ else
+ Break;
+ end;
+ end;
+ end;
+ if FLastError<>0 then
+ Exit;
+ FSSLEnabled:=FElSecureClient.Active;
+ Result:=FSSLEnabled;
+ end;
+end;
+
+function TSSLSBB.Accept:Boolean;
+
+var
+ lResult:Integer;
+
+begin
+ Result:=FALSE;
+ if FSocket.Socket=INVALID_SOCKET then
+ Exit;
+ if Prepare(TRUE) then
+ begin
+ FAcceptThread:=GetCurrentThreadId;
+ FElSecureServer.Open;
+
+ // reset
+ FRecvBuffers:='';
+ FRecvDecodedBuffers:='';
+
+ // wait for open or error
+ while (not FElSecureServer.Active) and
+ (FLastError=0) do
+ begin
+ // data available?
+ if FRecvBuffers<>'' then
+ FElSecureServer.DataAvailable
+ else
+ begin
+ // socket recv
+ lResult:=Recv(FSocket.Socket,@FRecvBuffer[1],Length(FRecvBuffer),0);
+ if lResult=SOCKET_ERROR then
+ begin
+ FLastErrorDesc:='';
+ FLastError:=WSAGetLastError;
+ end
+ else
+ begin
+ if lResult>0 then
+ FRecvBuffers:=FRecvBuffers+Copy(FRecvBuffer,1,lResult)
+ else
+ Break;
+ end;
+ end;
+ end;
+ if FLastError<>0 then
+ Exit;
+ FSSLEnabled:=FElSecureServer.Active;
+ Result:=FSSLEnabled;
+ end;
+end;
+
+function TSSLSBB.Shutdown:Boolean;
+
+begin
+ Result:=BiShutdown;
+end;
+
+function TSSLSBB.BiShutdown: boolean;
+
+begin
+ Reset;
+ Result:=TRUE;
+end;
+
+function TSSLSBB.SendBuffer(Buffer: TMemory; Len: Integer): Integer;
+
+begin
+ if FServer then
+ FElSecureServer.SendData(Buffer,Len)
+ else
+ FElSecureClient.SendData(Buffer,Len);
+ Result:=Len;
+end;
+
+function TSSLSBB.RecvBuffer(Buffer: TMemory; Len: Integer): Integer;
+
+begin
+ Result:=0;
+ try
+ // recv waiting, if necessary
+ if FRecvDecodedBuffers='' then
+ WaitingData;
+
+ // received
+ if Length(FRecvDecodedBuffers)FAcceptThread then EnterCriticalSection(FRecvBuffersLock);
+ try
+ lRecvBuffers:=FRecvBuffers<>'';
+ finally
+ if GetCurrentThreadId<>FAcceptThread then LeaveCriticalSection(FRecvBuffersLock);
+ end;
+ if lRecvBuffers then
+ begin
+ if FServer then
+ FElSecureServer.DataAvailable
+ else
+ FElSecureClient.DataAvailable;
+ end
+ else
+ begin
+ // socket recv
+ lResult:=Recv(FSocket.Socket,@FRecvBuffer[1],Length(FRecvBuffer),0);
+ if lResult=SOCKET_ERROR then
+ begin
+ FLastErrorDesc:='';
+ FLastError:=WSAGetLastError;
+ end
+ else
+ begin
+ if GetCurrentThreadId<>FAcceptThread then EnterCriticalSection(FRecvBuffersLock);
+ try
+ FRecvBuffers:=FRecvBuffers+Copy(FRecvBuffer,1,lResult);
+ finally
+ if GetCurrentThreadId<>FAcceptThread then LeaveCriticalSection(FRecvBuffersLock);
+ end;
+
+ // data available?
+ if GetCurrentThreadId<>FAcceptThread then EnterCriticalSection(FRecvBuffersLock);
+ try
+ lRecvBuffers:=FRecvBuffers<>'';
+ finally
+ if GetCurrentThreadId<>FAcceptThread then LeaveCriticalSection(FRecvBuffersLock);
+ end;
+ if lRecvBuffers then
+ begin
+ if FServer then
+ FElSecureServer.DataAvailable
+ else
+ FElSecureClient.DataAvailable;
+ end;
+ end;
+ end;
+
+ // decoded buffers result
+ Result:=Length(FRecvDecodedBuffers);
+end;
+
+function TSSLSBB.GetSSLVersion: string;
+
+begin
+ Result:='SSLv3 or TLSv1';
+end;
+
+function TSSLSBB.GetPeerSubject: string;
+
+begin
+ Result := '';
+// if FServer then
+ // must return subject of the client certificate
+// else
+ // must return subject of the server certificate
+end;
+
+function TSSLSBB.GetPeerName: string;
+
+begin
+ Result := '';
+// if FServer then
+ // must return commonname of the client certificate
+// else
+ // must return commonname of the server certificate
+end;
+
+function TSSLSBB.GetPeerIssuer: string;
+
+begin
+ Result := '';
+// if FServer then
+ // must return issuer of the client certificate
+// else
+ // must return issuer of the server certificate
+end;
+
+function TSSLSBB.GetPeerFingerprint: string;
+
+begin
+ Result := '';
+// if FServer then
+ // must return a unique hash string of the client certificate
+// else
+ // must return a unique hash string of the server certificate
+end;
+
+function TSSLSBB.GetCertInfo: string;
+
+begin
+ Result := '';
+// if FServer then
+ // must return a text representation of the ASN of the client certificate
+// else
+ // must return a text representation of the ASN of the server certificate
+end;
+
+{==============================================================================}
+
+initialization
+ SSLImplementation := TSSLSBB;
+
+finalization
+
+end.
diff --git a/branches/script-component/Units/Synapse/ssl_streamsec.pas b/branches/script-component/Units/Synapse/ssl_streamsec.pas
new file mode 100644
index 0000000..8c36ac8
--- /dev/null
+++ b/branches/script-component/Units/Synapse/ssl_streamsec.pas
@@ -0,0 +1,539 @@
+{==============================================================================|
+| Project : Ararat Synapse | 001.000.006 |
+|==============================================================================|
+| Content: SSL support by StreamSecII |
+|==============================================================================|
+| Copyright (c)1999-2005, Lukas Gebauer |
+| All rights reserved. |
+| |
+| Redistribution and use in source and binary forms, with or without |
+| modification, are permitted provided that the following conditions are met: |
+| |
+| Redistributions of source code must retain the above copyright notice, this |
+| list of conditions and the following disclaimer. |
+| |
+| Redistributions in binary form must reproduce the above copyright notice, |
+| this list of conditions and the following disclaimer in the documentation |
+| and/or other materials provided with the distribution. |
+| |
+| Neither the name of Lukas Gebauer nor the names of its contributors may |
+| be used to endorse or promote products derived from this software without |
+| specific prior written permission. |
+| |
+| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
+| AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
+| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
+| ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR |
+| ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
+| DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
+| SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
+| CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
+| LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
+| OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
+| DAMAGE. |
+|==============================================================================|
+| The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).|
+| Portions created by Lukas Gebauer are Copyright (c)2005. |
+| All Rights Reserved. |
+|==============================================================================|
+| Contributor(s): |
+| Henrick Hellström |
+|==============================================================================|
+| History: see HISTORY.HTM from distribution package |
+| (Found at URL: http://www.ararat.cz/synapse/) |
+|==============================================================================}
+
+{:@abstract(SSL plugin for StreamSecII or OpenStreamSecII)
+
+StreamSecII is native pascal library, you not need any external libraries!
+
+You can tune lot of StreamSecII properties by using your GlobalServer. If you not
+using your GlobalServer, then this plugin create own TSimpleTLSInternalServer
+instance for each TCP connection. Formore information about GlobalServer usage
+refer StreamSecII documentation.
+
+If you are not using key and certificate by GlobalServer, then you can use
+properties of this plugin instead, but this have limited features and
+@link(TCustomSSL.KeyPassword) not working properly yet!
+
+For handling keys and certificates you can use this properties:
+@link(TCustomSSL.CertCAFile), @link(TCustomSSL.CertCA),
+@link(TCustomSSL.TrustCertificateFile), @link(TCustomSSL.TrustCertificate),
+@link(TCustomSSL.PrivateKeyFile), @link(TCustomSSL.PrivateKey),
+@link(TCustomSSL.CertificateFile), @link(TCustomSSL.Certificate),
+@link(TCustomSSL.PFXFile). For usage of this properties and for possible formats
+of keys and certificates refer to StreamSecII documentation.
+}
+
+{$IFDEF FPC}
+ {$MODE DELPHI}
+{$ENDIF}
+{$H+}
+
+unit ssl_streamsec;
+
+interface
+
+uses
+ SysUtils, Classes,
+ blcksock, synsock, synautil, synacode,
+ TlsInternalServer, TlsSynaSock, TlsConst, StreamSecII, Asn1, X509Base,
+ SecUtils;
+
+type
+ {:@exclude}
+ TMyTLSSynSockSlave = class(TTLSSynSockSlave)
+ protected
+ procedure SetMyTLSServer(const Value: TCustomTLSInternalServer);
+ function GetMyTLSServer: TCustomTLSInternalServer;
+ published
+ property MyTLSServer: TCustomTLSInternalServer read GetMyTLSServer write SetMyTLSServer;
+ end;
+
+ {:@abstract(class implementing StreamSecII SSL plugin.)
+ Instance of this class will be created for each @link(TTCPBlockSocket).
+ You not need to create instance of this class, all is done by Synapse itself!}
+ TSSLStreamSec = class(TCustomSSL)
+ protected
+ FSlave: TMyTLSSynSockSlave;
+ FIsServer: Boolean;
+ FTLSServer: TCustomTLSInternalServer;
+ FServerCreated: Boolean;
+ function SSLCheck: Boolean;
+ function Init(server:Boolean): Boolean;
+ function DeInit: Boolean;
+ function Prepare(server:Boolean): Boolean;
+ procedure NotTrustEvent(Sender: TObject; Cert: TASN1Struct; var ExplicitTrust: Boolean);
+ function X500StrToStr(const Prefix: string; const Value: TX500String): string;
+ function X501NameToStr(const Value: TX501Name): string;
+ function GetCert: PASN1Struct;
+ public
+ constructor Create(const Value: TTCPBlockSocket); override;
+ destructor Destroy; override;
+ {:See @inherited}
+ function LibVersion: String; override;
+ {:See @inherited}
+ function LibName: String; override;
+ {:See @inherited and @link(ssl_streamsec) for more details.}
+ function Connect: boolean; override;
+ {:See @inherited and @link(ssl_streamsec) for more details.}
+ function Accept: boolean; override;
+ {:See @inherited}
+ function Shutdown: boolean; override;
+ {:See @inherited}
+ function BiShutdown: boolean; override;
+ {:See @inherited}
+ function SendBuffer(Buffer: TMemory; Len: Integer): Integer; override;
+ {:See @inherited}
+ function RecvBuffer(Buffer: TMemory; Len: Integer): Integer; override;
+ {:See @inherited}
+ function WaitingData: Integer; override;
+ {:See @inherited}
+ function GetSSLVersion: string; override;
+ {:See @inherited}
+ function GetPeerSubject: string; override;
+ {:See @inherited}
+ function GetPeerIssuer: string; override;
+ {:See @inherited}
+ function GetPeerName: string; override;
+ {:See @inherited}
+ function GetPeerFingerprint: string; override;
+ {:See @inherited}
+ function GetCertInfo: string; override;
+ published
+ {:TLS server for tuning of StreamSecII.}
+ property TLSServer: TCustomTLSInternalServer read FTLSServer write FTLSServer;
+ end;
+
+implementation
+
+{==============================================================================}
+procedure TMyTLSSynSockSlave.SetMyTLSServer(const Value: TCustomTLSInternalServer);
+begin
+ TLSServer := Value;
+end;
+
+function TMyTLSSynSockSlave.GetMyTLSServer: TCustomTLSInternalServer;
+begin
+ Result := TLSServer;
+end;
+
+{==============================================================================}
+
+constructor TSSLStreamSec.Create(const Value: TTCPBlockSocket);
+begin
+ inherited Create(Value);
+ FSlave := nil;
+ FIsServer := False;
+ FTLSServer := nil;
+end;
+
+destructor TSSLStreamSec.Destroy;
+begin
+ DeInit;
+ inherited Destroy;
+end;
+
+function TSSLStreamSec.LibVersion: String;
+begin
+ Result := 'StreamSecII';
+end;
+
+function TSSLStreamSec.LibName: String;
+begin
+ Result := 'ssl_streamsec';
+end;
+
+function TSSLStreamSec.SSLCheck: Boolean;
+begin
+ Result := true;
+ FLastErrorDesc := '';
+ if not Assigned(FSlave) then
+ Exit;
+ FLastError := FSlave.ErrorCode;
+ if FLastError <> 0 then
+ begin
+ FLastErrorDesc := TlsConst.AlertMsg(FLastError);
+ end;
+end;
+
+procedure TSSLStreamSec.NotTrustEvent(Sender: TObject; Cert: TASN1Struct; var ExplicitTrust: Boolean);
+begin
+ ExplicitTrust := true;
+end;
+
+function TSSLStreamSec.Init(server:Boolean): Boolean;
+var
+ st: TMemoryStream;
+ pass: ISecretKey;
+ ws: WideString;
+begin
+ Result := False;
+ ws := FKeyPassword;
+ pass := TSecretKey.CreateBmpStr(PWideChar(ws), length(ws));
+ try
+ FIsServer := Server;
+ FSlave := TMyTLSSynSockSlave.CreateSocket(FSocket.Socket);
+ if Assigned(FTLSServer) then
+ FSlave.MyTLSServer := FTLSServer
+ else
+ if Assigned(TLSInternalServer.GlobalServer) then
+ FSlave.MyTLSServer := TLSInternalServer.GlobalServer
+ else begin
+ FSlave.MyTLSServer := TSimpleTLSInternalServer.Create(nil);
+ FServerCreated := True;
+ end;
+ if server then
+ FSlave.MyTLSServer.ClientOrServer := cosServerSide
+ else
+ FSlave.MyTLSServer.ClientOrServer := cosClientSide;
+ if not FVerifyCert then
+ begin
+ FSlave.MyTLSServer.OnCertNotTrusted := NotTrustEvent;
+ end;
+ FSlave.MyTLSServer.Options.VerifyServerName := [];
+ FSlave.MyTLSServer.Options.Export40Bit := prAllowed;
+ FSlave.MyTLSServer.Options.Export56Bit := prAllowed;
+ FSlave.MyTLSServer.Options.RequestClientCertificate := False;
+ FSlave.MyTLSServer.Options.RequireClientCertificate := False;
+ if server and FVerifyCert then
+ begin
+ FSlave.MyTLSServer.Options.RequestClientCertificate := True;
+ FSlave.MyTLSServer.Options.RequireClientCertificate := True;
+ end;
+ if FCertCAFile <> '' then
+ FSlave.MyTLSServer.LoadRootCertsFromFile(CertCAFile);
+ if FCertCA <> '' then
+ begin
+ st := TMemoryStream.Create;
+ try
+ WriteStrToStream(st, FCertCA);
+ st.Seek(0, soFromBeginning);
+ FSlave.MyTLSServer.LoadRootCertsFromStream(st);
+ finally
+ st.free;
+ end;
+ end;
+ if FTrustCertificateFile <> '' then
+ FSlave.MyTLSServer.LoadTrustedCertsFromFile(FTrustCertificateFile);
+ if FTrustCertificate <> '' then
+ begin
+ st := TMemoryStream.Create;
+ try
+ WriteStrToStream(st, FTrustCertificate);
+ st.Seek(0, soFromBeginning);
+ FSlave.MyTLSServer.LoadTrustedCertsFromStream(st);
+ finally
+ st.free;
+ end;
+ end;
+ if FPrivateKeyFile <> '' then
+ FSlave.MyTLSServer.LoadPrivateKeyRingFromFile(FPrivateKeyFile, pass);
+// FSlave.MyTLSServer.PrivateKeyRing.LoadPrivateKeyFromFile(FPrivateKeyFile, pass);
+ if FPrivateKey <> '' then
+ begin
+ st := TMemoryStream.Create;
+ try
+ WriteStrToStream(st, FPrivateKey);
+ st.Seek(0, soFromBeginning);
+ FSlave.MyTLSServer.LoadPrivateKeyRingFromStream(st, pass);
+ finally
+ st.free;
+ end;
+ end;
+ if FCertificateFile <> '' then
+ FSlave.MyTLSServer.LoadMyCertsFromFile(FCertificateFile);
+ if FCertificate <> '' then
+ begin
+ st := TMemoryStream.Create;
+ try
+ WriteStrToStream(st, FCertificate);
+ st.Seek(0, soFromBeginning);
+ FSlave.MyTLSServer.LoadMyCertsFromStream(st);
+ finally
+ st.free;
+ end;
+ end;
+ if FPFXfile <> '' then
+ FSlave.MyTLSServer.ImportFromPFX(FPFXfile, pass);
+ if server and FServerCreated then
+ begin
+ FSlave.MyTLSServer.Options.BulkCipherAES128 := prPrefer;
+ FSlave.MyTLSServer.Options.BulkCipherAES256 := prAllowed;
+ FSlave.MyTLSServer.Options.EphemeralECDHKeySize := ecs256;
+ FSlave.MyTLSServer.Options.SignatureRSA := prPrefer;
+ FSlave.MyTLSServer.Options.KeyAgreementRSA := prAllowed;
+ FSlave.MyTLSServer.Options.KeyAgreementECDHE := prAllowed;
+ FSlave.MyTLSServer.Options.KeyAgreementDHE := prPrefer;
+ FSlave.MyTLSServer.TLSSetupServer;
+ end;
+ Result := true;
+ finally
+ pass := nil;
+ end;
+end;
+
+function TSSLStreamSec.DeInit: Boolean;
+var
+ obj: TObject;
+begin
+ Result := True;
+ if assigned(FSlave) then
+ begin
+ FSlave.Close;
+ if FServerCreated then
+ obj := FSlave.TLSServer
+ else
+ obj := nil;
+ FSlave.Free;
+ obj.Free;
+ FSlave := nil;
+ end;
+ FSSLEnabled := false;
+end;
+
+function TSSLStreamSec.Prepare(server:Boolean): Boolean;
+begin
+ Result := false;
+ DeInit;
+ if Init(server) then
+ Result := true
+ else
+ DeInit;
+end;
+
+function TSSLStreamSec.Connect: boolean;
+begin
+ Result := False;
+ if FSocket.Socket = INVALID_SOCKET then
+ Exit;
+ if Prepare(false) then
+ begin
+ FSlave.Open;
+ SSLCheck;
+ if FLastError <> 0 then
+ Exit;
+ FSSLEnabled := True;
+ Result := True;
+ end;
+end;
+
+function TSSLStreamSec.Accept: boolean;
+begin
+ Result := False;
+ if FSocket.Socket = INVALID_SOCKET then
+ Exit;
+ if Prepare(true) then
+ begin
+ FSlave.DoConnect;
+ SSLCheck;
+ if FLastError <> 0 then
+ Exit;
+ FSSLEnabled := True;
+ Result := True;
+ end;
+end;
+
+function TSSLStreamSec.Shutdown: boolean;
+begin
+ Result := BiShutdown;
+end;
+
+function TSSLStreamSec.BiShutdown: boolean;
+begin
+ DeInit;
+ Result := True;
+end;
+
+function TSSLStreamSec.SendBuffer(Buffer: TMemory; Len: Integer): Integer;
+var
+ l: integer;
+begin
+ l := len;
+ FSlave.SendBuf(Buffer^, l, true);
+ Result := l;
+ SSLCheck;
+end;
+
+function TSSLStreamSec.RecvBuffer(Buffer: TMemory; Len: Integer): Integer;
+var
+ l: integer;
+begin
+ l := Len;
+ Result := FSlave.ReceiveBuf(Buffer^, l);
+ SSLCheck;
+end;
+
+function TSSLStreamSec.WaitingData: Integer;
+begin
+ Result := 0;
+ while FSlave.Connected do begin
+ Result := FSlave.ReceiveLength;
+ if Result > 0 then
+ Break;
+ Sleep(1);
+ end;
+end;
+
+function TSSLStreamSec.GetSSLVersion: string;
+begin
+ Result := 'SSLv3 or TLSv1';
+end;
+
+function TSSLStreamSec.GetCert: PASN1Struct;
+begin
+ if FIsServer then
+ Result := FSlave.GetClientCert
+ else
+ Result := FSlave.GetServerCert;
+end;
+
+function TSSLStreamSec.GetPeerSubject: string;
+var
+ XName: TX501Name;
+ Cert: PASN1Struct;
+begin
+ Result := '';
+ Cert := GetCert;
+ if Assigned(cert) then
+ begin
+ ExtractSubject(Cert^,XName, false);
+ Result := X501NameToStr(XName);
+ end;
+end;
+
+function TSSLStreamSec.GetPeerName: string;
+var
+ XName: TX501Name;
+ Cert: PASN1Struct;
+begin
+ Result := '';
+ Cert := GetCert;
+ if Assigned(cert) then
+ begin
+ ExtractSubject(Cert^,XName, false);
+ Result := XName.commonName.Str;
+ end;
+end;
+
+function TSSLStreamSec.GetPeerIssuer: string;
+var
+ XName: TX501Name;
+ Cert: PASN1Struct;
+begin
+ Result := '';
+ Cert := GetCert;
+ if Assigned(cert) then
+ begin
+ ExtractIssuer(Cert^, XName, false);
+ Result := X501NameToStr(XName);
+ end;
+end;
+
+function TSSLStreamSec.GetPeerFingerprint: string;
+var
+ Cert: PASN1Struct;
+begin
+ Result := '';
+ Cert := GetCert;
+ if Assigned(cert) then
+ Result := MD5(Cert.ContentAsOctetString);
+end;
+
+function TSSLStreamSec.GetCertInfo: string;
+var
+ Cert: PASN1Struct;
+ l: Tstringlist;
+begin
+ Result := '';
+ Cert := GetCert;
+ if Assigned(cert) then
+ begin
+ l := TStringList.Create;
+ try
+ Asn1.RenderAsText(cert^, l, true, true, true, 2);
+ Result := l.Text;
+ finally
+ l.free;
+ end;
+ end;
+end;
+
+function TSSLStreamSec.X500StrToStr(const Prefix: string;
+ const Value: TX500String): string;
+begin
+ if Value.Str = '' then
+ Result := ''
+ else
+ Result := '/' + Prefix + '=' + Value.Str;
+end;
+
+function TSSLStreamSec.X501NameToStr(const Value: TX501Name): string;
+begin
+ Result := X500StrToStr('CN',Value.commonName) +
+ X500StrToStr('C',Value.countryName) +
+ X500StrToStr('L',Value.localityName) +
+ X500StrToStr('ST',Value.stateOrProvinceName) +
+ X500StrToStr('O',Value.organizationName) +
+ X500StrToStr('OU',Value.organizationalUnitName) +
+ X500StrToStr('T',Value.title) +
+ X500StrToStr('N',Value.name) +
+ X500StrToStr('G',Value.givenName) +
+ X500StrToStr('I',Value.initials) +
+ X500StrToStr('SN',Value.surname) +
+ X500StrToStr('GQ',Value.generationQualifier) +
+ X500StrToStr('DNQ',Value.dnQualifier) +
+ X500StrToStr('E',Value.emailAddress);
+end;
+
+
+{==============================================================================}
+
+initialization
+ SSLImplementation := TSSLStreamSec;
+
+finalization
+
+end.
+
+
diff --git a/branches/script-component/Units/Synapse/sslinux.pas b/branches/script-component/Units/Synapse/sslinux.pas
new file mode 100644
index 0000000..c337281
--- /dev/null
+++ b/branches/script-component/Units/Synapse/sslinux.pas
@@ -0,0 +1,1313 @@
+{==============================================================================|
+| Project : Ararat Synapse | 002.000.008 |
+|==============================================================================|
+| Content: Socket Independent Platform Layer - Linux definition include |
+|==============================================================================|
+| Copyright (c)1999-2003, Lukas Gebauer |
+| All rights reserved. |
+| |
+| Redistribution and use in source and binary forms, with or without |
+| modification, are permitted provided that the following conditions are met: |
+| |
+| Redistributions of source code must retain the above copyright notice, this |
+| list of conditions and the following disclaimer. |
+| |
+| Redistributions in binary form must reproduce the above copyright notice, |
+| this list of conditions and the following disclaimer in the documentation |
+| and/or other materials provided with the distribution. |
+| |
+| Neither the name of Lukas Gebauer nor the names of its contributors may |
+| be used to endorse or promote products derived from this software without |
+| specific prior written permission. |
+| |
+| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
+| AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
+| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
+| ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR |
+| ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
+| DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
+| SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
+| CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
+| LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
+| OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
+| DAMAGE. |
+|==============================================================================|
+| The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).|
+| Portions created by Lukas Gebauer are Copyright (c)2003. |
+| All Rights Reserved. |
+|==============================================================================|
+| Contributor(s): |
+|==============================================================================|
+| History: see HISTORY.HTM from distribution package |
+| (Found at URL: http://www.ararat.cz/synapse/) |
+|==============================================================================}
+
+{:@exclude}
+
+{$IFDEF LINUX}
+
+//{$DEFINE FORCEOLDAPI}
+{Note about define FORCEOLDAPI:
+If you activate this compiler directive, then is allways used old socket API
+for name resolution. If you leave this directive inactive, then the new API
+is used, when running system allows it.
+
+For IPv6 support you must have new API!
+}
+
+{$IFDEF FPC}
+ {$MODE DELPHI}
+{$ENDIF}
+{$H+}
+interface
+
+uses
+ SyncObjs, SysUtils, Classes,
+ synafpc,
+ Libc;
+
+function InitSocketInterface(stack: string): Boolean;
+function DestroySocketInterface: Boolean;
+
+const
+ WinsockLevel = $0202;
+
+type
+ u_char = Char;
+ u_short = Word;
+ u_int = Integer;
+ u_long = Longint;
+ pu_long = ^u_long;
+ pu_short = ^u_short;
+ TSocket = u_int;
+ TAddrFamily = integer;
+
+ TMemory = pointer;
+
+
+const
+ DLLStackName = 'libc.so.6';
+
+ cLocalhost = '127.0.0.1';
+ cAnyHost = '0.0.0.0';
+ cBroadcast = '255.255.255.255';
+ c6Localhost = '::1';
+ c6AnyHost = '::0';
+ c6Broadcast = 'ffff::1';
+ cAnyPort = '0';
+
+type
+ DWORD = Integer;
+ __fd_mask = LongWord;
+const
+ __FD_SETSIZE = 1024;
+ __NFDBITS = 8 * sizeof(__fd_mask);
+type
+ __fd_set = {packed} record
+ fds_bits: packed array[0..(__FD_SETSIZE div __NFDBITS)-1] of __fd_mask;
+ end;
+ TFDSet = __fd_set;
+ PFDSet = ^TFDSet;
+
+const
+ FIONREAD = $541B;
+ FIONBIO = $5421;
+ FIOASYNC = $5452;
+
+type
+ PTimeVal = ^TTimeVal;
+ TTimeVal = packed record
+ tv_sec: Longint;
+ tv_usec: Longint;
+ end;
+
+const
+ IPPROTO_IP = 0; { Dummy }
+ IPPROTO_ICMP = 1; { Internet Control Message Protocol }
+ IPPROTO_IGMP = 2; { Internet Group Management Protocol}
+ IPPROTO_TCP = 6; { TCP }
+ IPPROTO_UDP = 17; { User Datagram Protocol }
+ IPPROTO_IPV6 = 41;
+ IPPROTO_ICMPV6 = 58;
+
+ IPPROTO_RAW = 255;
+ IPPROTO_MAX = 256;
+
+type
+ PInAddr = ^TInAddr;
+ TInAddr = packed record
+ case integer of
+ 0: (S_bytes: packed array [0..3] of byte);
+ 1: (S_addr: u_long);
+ end;
+
+ PSockAddrIn = ^TSockAddrIn;
+ TSockAddrIn = packed record
+ case Integer of
+ 0: (sin_family: u_short;
+ sin_port: u_short;
+ sin_addr: TInAddr;
+ sin_zero: array[0..7] of Char);
+ 1: (sa_family: u_short;
+ sa_data: array[0..13] of Char)
+ end;
+
+ TIP_mreq = record
+ imr_multiaddr: TInAddr; { IP multicast address of group }
+ imr_interface: TInAddr; { local IP address of interface }
+ end;
+
+ PInAddr6 = ^TInAddr6;
+ TInAddr6 = packed record
+ case integer of
+ 0: (S6_addr: packed array [0..15] of byte);
+ 1: (u6_addr8: packed array [0..15] of byte);
+ 2: (u6_addr16: packed array [0..7] of word);
+ 3: (u6_addr32: packed array [0..3] of integer);
+ end;
+
+ PSockAddrIn6 = ^TSockAddrIn6;
+ TSockAddrIn6 = packed record
+ sin6_family: u_short; // AF_INET6
+ sin6_port: u_short; // Transport level port number
+ sin6_flowinfo: u_long; // IPv6 flow information
+ sin6_addr: TInAddr6; // IPv6 address
+ sin6_scope_id: u_long; // Scope Id: IF number for link-local
+ // SITE id for site-local
+ end;
+
+ TIPv6_mreq = record
+ ipv6mr_multiaddr: TInAddr6; // IPv6 multicast address.
+ ipv6mr_interface: integer; // Interface index.
+ padding: u_long;
+ end;
+
+ PHostEnt = ^THostEnt;
+ THostent = record
+ h_name: PChar;
+ h_aliases: PPChar;
+ h_addrtype: Integer;
+ h_length: Cardinal;
+ case Byte of
+ 0: (h_addr_list: PPChar);
+ 1: (h_addr: PPChar);
+ end;
+
+ PNetEnt = ^TNetEnt;
+ TNetEnt = record
+ n_name: PChar;
+ n_aliases: PPChar;
+ n_addrtype: Integer;
+ n_net: uint32_t;
+ end;
+
+ PServEnt = ^TServEnt;
+ TServEnt = record
+ s_name: PChar;
+ s_aliases: PPChar;
+ s_port: Integer;
+ s_proto: PChar;
+ end;
+
+ PProtoEnt = ^TProtoEnt;
+ TProtoEnt = record
+ p_name: PChar;
+ p_aliases: ^PChar;
+ p_proto: u_short;
+ end;
+
+const
+ INADDR_ANY = $00000000;
+ INADDR_LOOPBACK = $7F000001;
+ INADDR_BROADCAST = $FFFFFFFF;
+ INADDR_NONE = $FFFFFFFF;
+ ADDR_ANY = INADDR_ANY;
+ INVALID_SOCKET = TSocket(NOT(0));
+ SOCKET_ERROR = -1;
+
+Const
+ IP_TOS = 1; { int; IP type of service and precedence. }
+ IP_TTL = 2; { int; IP time to live. }
+ IP_HDRINCL = 3; { int; Header is included with data. }
+ IP_OPTIONS = 4; { ip_opts; IP per-packet options. }
+ IP_ROUTER_ALERT = 5; { bool }
+ IP_RECVOPTS = 6; { bool }
+ IP_RETOPTS = 7; { bool }
+ IP_PKTINFO = 8; { bool }
+ IP_PKTOPTIONS = 9;
+ IP_PMTUDISC = 10; { obsolete name? }
+ IP_MTU_DISCOVER = 10; { int; see below }
+ IP_RECVERR = 11; { bool }
+ IP_RECVTTL = 12; { bool }
+ IP_RECVTOS = 13; { bool }
+ IP_MULTICAST_IF = 32; { in_addr; set/get IP multicast i/f }
+ IP_MULTICAST_TTL = 33; { u_char; set/get IP multicast ttl }
+ IP_MULTICAST_LOOP = 34; { i_char; set/get IP multicast loopback }
+ IP_ADD_MEMBERSHIP = 35; { ip_mreq; add an IP group membership }
+ IP_DROP_MEMBERSHIP = 36; { ip_mreq; drop an IP group membership }
+
+ SOL_SOCKET = 1;
+
+ SO_DEBUG = 1;
+ SO_REUSEADDR = 2;
+ SO_TYPE = 3;
+ SO_ERROR = 4;
+ SO_DONTROUTE = 5;
+ SO_BROADCAST = 6;
+ SO_SNDBUF = 7;
+ SO_RCVBUF = 8;
+ SO_KEEPALIVE = 9;
+ SO_OOBINLINE = 10;
+ SO_NO_CHECK = 11;
+ SO_PRIORITY = 12;
+ SO_LINGER = 13;
+ SO_BSDCOMPAT = 14;
+ SO_REUSEPORT = 15;
+ SO_PASSCRED = 16;
+ SO_PEERCRED = 17;
+ SO_RCVLOWAT = 18;
+ SO_SNDLOWAT = 19;
+ SO_RCVTIMEO = 20;
+ SO_SNDTIMEO = 21;
+{ Security levels - as per NRL IPv6 - don't actually do anything }
+ SO_SECURITY_AUTHENTICATION = 22;
+ SO_SECURITY_ENCRYPTION_TRANSPORT = 23;
+ SO_SECURITY_ENCRYPTION_NETWORK = 24;
+ SO_BINDTODEVICE = 25;
+{ Socket filtering }
+ SO_ATTACH_FILTER = 26;
+ SO_DETACH_FILTER = 27;
+
+ SOMAXCONN = 128;
+
+ IPV6_UNICAST_HOPS = 16;
+ IPV6_MULTICAST_IF = 17;
+ IPV6_MULTICAST_HOPS = 18;
+ IPV6_MULTICAST_LOOP = 19;
+ IPV6_JOIN_GROUP = 20;
+ IPV6_LEAVE_GROUP = 21;
+
+ MSG_NOSIGNAL = $4000; // Do not generate SIGPIPE.
+
+ // getnameinfo constants
+ NI_MAXHOST = 1025;
+ NI_MAXSERV = 32;
+ NI_NOFQDN = $4;
+ NI_NUMERICHOST = $1;
+ NI_NAMEREQD = $8;
+ NI_NUMERICSERV = $2;
+ NI_DGRAM = $10;
+
+const
+ SOCK_STREAM = 1; { stream socket }
+ SOCK_DGRAM = 2; { datagram socket }
+ SOCK_RAW = 3; { raw-protocol interface }
+ SOCK_RDM = 4; { reliably-delivered message }
+ SOCK_SEQPACKET = 5; { sequenced packet stream }
+
+{ TCP options. }
+ TCP_NODELAY = $0001;
+
+{ Address families. }
+
+ AF_UNSPEC = 0; { unspecified }
+ AF_INET = 2; { internetwork: UDP, TCP, etc. }
+ AF_INET6 = 10; { Internetwork Version 6 }
+ AF_MAX = 24;
+
+{ Protocol families, same as address families for now. }
+ PF_UNSPEC = AF_UNSPEC;
+ PF_INET = AF_INET;
+ PF_INET6 = AF_INET6;
+ PF_MAX = AF_MAX;
+
+type
+ { Structure used by kernel to store most addresses. }
+ PSockAddr = ^TSockAddr;
+ TSockAddr = TSockAddrIn;
+
+ { Structure used by kernel to pass protocol information in raw sockets. }
+ PSockProto = ^TSockProto;
+ TSockProto = packed record
+ sp_family: u_short;
+ sp_protocol: u_short;
+ end;
+
+type
+ PAddrInfo = ^TAddrInfo;
+ TAddrInfo = record
+ ai_flags: integer; // AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST.
+ ai_family: integer; // PF_xxx.
+ ai_socktype: integer; // SOCK_xxx.
+ ai_protocol: integer; // 0 or IPPROTO_xxx for IPv4 and IPv6.
+ ai_addrlen: u_int; // Length of ai_addr.
+ ai_addr: PSockAddr; // Binary address.
+ ai_canonname: PChar; // Canonical name for nodename.
+ ai_next: PAddrInfo; // Next structure in linked list.
+ end;
+
+const
+ // Flags used in "hints" argument to getaddrinfo().
+ AI_PASSIVE = $1; // Socket address will be used in bind() call.
+ AI_CANONNAME = $2; // Return canonical name in first ai_canonname.
+ AI_NUMERICHOST = $4; // Nodename must be a numeric address string.
+
+type
+{ Structure used for manipulating linger option. }
+ PLinger = ^TLinger;
+ TLinger = packed record
+ l_onoff: integer;
+ l_linger: integer;
+ end;
+
+const
+
+ MSG_OOB = $01; // Process out-of-band data.
+ MSG_PEEK = $02; // Peek at incoming messages.
+
+const
+ WSAEINTR = EINTR;
+ WSAEBADF = EBADF;
+ WSAEACCES = EACCES;
+ WSAEFAULT = EFAULT;
+ WSAEINVAL = EINVAL;
+ WSAEMFILE = EMFILE;
+ WSAEWOULDBLOCK = EWOULDBLOCK;
+ WSAEINPROGRESS = EINPROGRESS;
+ WSAEALREADY = EALREADY;
+ WSAENOTSOCK = ENOTSOCK;
+ WSAEDESTADDRREQ = EDESTADDRREQ;
+ WSAEMSGSIZE = EMSGSIZE;
+ WSAEPROTOTYPE = EPROTOTYPE;
+ WSAENOPROTOOPT = ENOPROTOOPT;
+ WSAEPROTONOSUPPORT = EPROTONOSUPPORT;
+ WSAESOCKTNOSUPPORT = ESOCKTNOSUPPORT;
+ WSAEOPNOTSUPP = EOPNOTSUPP;
+ WSAEPFNOSUPPORT = EPFNOSUPPORT;
+ WSAEAFNOSUPPORT = EAFNOSUPPORT;
+ WSAEADDRINUSE = EADDRINUSE;
+ WSAEADDRNOTAVAIL = EADDRNOTAVAIL;
+ WSAENETDOWN = ENETDOWN;
+ WSAENETUNREACH = ENETUNREACH;
+ WSAENETRESET = ENETRESET;
+ WSAECONNABORTED = ECONNABORTED;
+ WSAECONNRESET = ECONNRESET;
+ WSAENOBUFS = ENOBUFS;
+ WSAEISCONN = EISCONN;
+ WSAENOTCONN = ENOTCONN;
+ WSAESHUTDOWN = ESHUTDOWN;
+ WSAETOOMANYREFS = ETOOMANYREFS;
+ WSAETIMEDOUT = ETIMEDOUT;
+ WSAECONNREFUSED = ECONNREFUSED;
+ WSAELOOP = ELOOP;
+ WSAENAMETOOLONG = ENAMETOOLONG;
+ WSAEHOSTDOWN = EHOSTDOWN;
+ WSAEHOSTUNREACH = EHOSTUNREACH;
+ WSAENOTEMPTY = ENOTEMPTY;
+ WSAEPROCLIM = -1;
+ WSAEUSERS = EUSERS;
+ WSAEDQUOT = EDQUOT;
+ WSAESTALE = ESTALE;
+ WSAEREMOTE = EREMOTE;
+ WSASYSNOTREADY = -2;
+ WSAVERNOTSUPPORTED = -3;
+ WSANOTINITIALISED = -4;
+ WSAEDISCON = -5;
+ WSAHOST_NOT_FOUND = HOST_NOT_FOUND;
+ WSATRY_AGAIN = TRY_AGAIN;
+ WSANO_RECOVERY = NO_RECOVERY;
+ WSANO_DATA = -6;
+
+ EAI_BADFLAGS = -1; { Invalid value for `ai_flags' field. }
+ EAI_NONAME = -2; { NAME or SERVICE is unknown. }
+ EAI_AGAIN = -3; { Temporary failure in name resolution. }
+ EAI_FAIL = -4; { Non-recoverable failure in name res. }
+ EAI_NODATA = -5; { No address associated with NAME. }
+ EAI_FAMILY = -6; { `ai_family' not supported. }
+ EAI_SOCKTYPE = -7; { `ai_socktype' not supported. }
+ EAI_SERVICE = -8; { SERVICE not supported for `ai_socktype'. }
+ EAI_ADDRFAMILY = -9; { Address family for NAME not supported. }
+ EAI_MEMORY = -10; { Memory allocation failure. }
+ EAI_SYSTEM = -11; { System error returned in `errno'. }
+
+const
+ WSADESCRIPTION_LEN = 256;
+ WSASYS_STATUS_LEN = 128;
+type
+ PWSAData = ^TWSAData;
+ TWSAData = packed record
+ wVersion: Word;
+ wHighVersion: Word;
+ szDescription: array[0..WSADESCRIPTION_LEN] of Char;
+ szSystemStatus: array[0..WSASYS_STATUS_LEN] of Char;
+ iMaxSockets: Word;
+ iMaxUdpDg: Word;
+ lpVendorInfo: PChar;
+ end;
+
+ function IN6_IS_ADDR_UNSPECIFIED(const a: PInAddr6): boolean;
+ function IN6_IS_ADDR_LOOPBACK(const a: PInAddr6): boolean;
+ function IN6_IS_ADDR_LINKLOCAL(const a: PInAddr6): boolean;
+ function IN6_IS_ADDR_SITELOCAL(const a: PInAddr6): boolean;
+ function IN6_IS_ADDR_MULTICAST(const a: PInAddr6): boolean;
+ function IN6_ADDR_EQUAL(const a: PInAddr6; const b: PInAddr6):boolean;
+ procedure SET_IN6_IF_ADDR_ANY (const a: PInAddr6);
+ procedure SET_LOOPBACK_ADDR6 (const a: PInAddr6);
+var
+ in6addr_any, in6addr_loopback : TInAddr6;
+
+procedure FD_CLR(Socket: TSocket; var FDSet: TFDSet);
+function FD_ISSET(Socket: TSocket; var FDSet: TFDSet): Boolean;
+procedure FD_SET(Socket: TSocket; var FDSet: TFDSet);
+procedure FD_ZERO(var FDSet: TFDSet);
+
+{=============================================================================}
+
+type
+ TWSAStartup = function(wVersionRequired: Word; var WSData: TWSAData): Integer;
+ cdecl;
+ TWSACleanup = function: Integer;
+ cdecl;
+ TWSAGetLastError = function: Integer;
+ cdecl;
+ TGetServByName = function(name, proto: PChar): PServEnt;
+ cdecl;
+ TGetServByPort = function(port: Integer; proto: PChar): PServEnt;
+ cdecl;
+ TGetProtoByName = function(name: PChar): PProtoEnt;
+ cdecl;
+ TGetProtoByNumber = function(proto: Integer): PProtoEnt;
+ cdecl;
+ TGetHostByName = function(name: PChar): PHostEnt;
+ cdecl;
+ TGetHostByAddr = function(addr: Pointer; len, Struc: Integer): PHostEnt;
+ cdecl;
+ TGetHostName = function(name: PChar; len: Integer): Integer;
+ cdecl;
+ TShutdown = function(s: TSocket; how: Integer): Integer;
+ cdecl;
+ TSetSockOpt = function(s: TSocket; level, optname: Integer; optval: PChar;
+ optlen: Integer): Integer;
+ cdecl;
+ TGetSockOpt = function(s: TSocket; level, optname: Integer; optval: PChar;
+ var optlen: Integer): Integer;
+ cdecl;
+ TSendTo = function(s: TSocket; const Buf; len, flags: Integer; addrto: PSockAddr;
+ tolen: Integer): Integer;
+ cdecl;
+ TSend = function(s: TSocket; const Buf; len, flags: Integer): Integer;
+ cdecl;
+ TRecv = function(s: TSocket; var Buf; len, flags: Integer): Integer;
+ cdecl;
+ TRecvFrom = function(s: TSocket; var Buf; len, flags: Integer; from: PSockAddr;
+ var fromlen: Integer): Integer;
+ cdecl;
+ Tntohs = function(netshort: u_short): u_short;
+ cdecl;
+ Tntohl = function(netlong: u_long): u_long;
+ cdecl;
+ TListen = function(s: TSocket; backlog: Integer): Integer;
+ cdecl;
+ TIoctlSocket = function(s: TSocket; cmd: DWORD; var arg: integer): Integer;
+ cdecl;
+ TInet_ntoa = function(inaddr: TInAddr): PChar;
+ cdecl;
+ TInet_addr = function(cp: PChar): u_long;
+ cdecl;
+ Thtons = function(hostshort: u_short): u_short;
+ cdecl;
+ Thtonl = function(hostlong: u_long): u_long;
+ cdecl;
+ TGetSockName = function(s: TSocket; name: PSockAddr; var namelen: Integer): Integer;
+ cdecl;
+ TGetPeerName = function(s: TSocket; name: PSockAddr; var namelen: Integer): Integer;
+ cdecl;
+ TConnect = function(s: TSocket; name: PSockAddr; namelen: Integer): Integer;
+ cdecl;
+ TCloseSocket = function(s: TSocket): Integer;
+ cdecl;
+ TBind = function(s: TSocket; addr: PSockAddr; namelen: Integer): Integer;
+ cdecl;
+ TAccept = function(s: TSocket; addr: PSockAddr; var addrlen: Integer): TSocket;
+ cdecl;
+ TTSocket = function(af, Struc, Protocol: Integer): TSocket;
+ cdecl;
+ TSelect = function(nfds: Integer; readfds, writefds, exceptfds: PFDSet;
+ timeout: PTimeVal): Longint;
+ cdecl;
+
+ TGetAddrInfo = function(NodeName: PChar; ServName: PChar; Hints: PAddrInfo;
+ var Addrinfo: PAddrInfo): integer;
+ cdecl;
+ TFreeAddrInfo = procedure(ai: PAddrInfo);
+ cdecl;
+ TGetNameInfo = function( addr: PSockAddr; namelen: Integer; host: PChar;
+ hostlen: DWORD; serv: PChar; servlen: DWORD; flags: integer): integer;
+ cdecl;
+
+var
+ WSAStartup: TWSAStartup = nil;
+ WSACleanup: TWSACleanup = nil;
+ WSAGetLastError: TWSAGetLastError = nil;
+ GetServByName: TGetServByName = nil;
+ GetServByPort: TGetServByPort = nil;
+ GetProtoByName: TGetProtoByName = nil;
+ GetProtoByNumber: TGetProtoByNumber = nil;
+ GetHostByName: TGetHostByName = nil;
+ GetHostByAddr: TGetHostByAddr = nil;
+ ssGetHostName: TGetHostName = nil;
+ Shutdown: TShutdown = nil;
+ SetSockOpt: TSetSockOpt = nil;
+ GetSockOpt: TGetSockOpt = nil;
+ ssSendTo: TSendTo = nil;
+ ssSend: TSend = nil;
+ ssRecv: TRecv = nil;
+ ssRecvFrom: TRecvFrom = nil;
+ ntohs: Tntohs = nil;
+ ntohl: Tntohl = nil;
+ Listen: TListen = nil;
+ IoctlSocket: TIoctlSocket = nil;
+ Inet_ntoa: TInet_ntoa = nil;
+ Inet_addr: TInet_addr = nil;
+ htons: Thtons = nil;
+ htonl: Thtonl = nil;
+ ssGetSockName: TGetSockName = nil;
+ ssGetPeerName: TGetPeerName = nil;
+ ssConnect: TConnect = nil;
+ CloseSocket: TCloseSocket = nil;
+ ssBind: TBind = nil;
+ ssAccept: TAccept = nil;
+ Socket: TTSocket = nil;
+ Select: TSelect = nil;
+
+ GetAddrInfo: TGetAddrInfo = nil;
+ FreeAddrInfo: TFreeAddrInfo = nil;
+ GetNameInfo: TGetNameInfo = nil;
+
+function LSWSAStartup(wVersionRequired: Word; var WSData: TWSAData): Integer; cdecl;
+function LSWSACleanup: Integer; cdecl;
+function LSWSAGetLastError: Integer; cdecl;
+
+var
+ SynSockCS: SyncObjs.TCriticalSection;
+ SockEnhancedApi: Boolean;
+ SockWship6Api: Boolean;
+
+type
+ TVarSin = packed record
+ case integer of
+ 0: (AddressFamily: u_short);
+ 1: (
+ case sin_family: u_short of
+ AF_INET: (sin_port: u_short;
+ sin_addr: TInAddr;
+ sin_zero: array[0..7] of Char);
+ AF_INET6: (sin6_port: u_short;
+ sin6_flowinfo: u_long;
+ sin6_addr: TInAddr6;
+ sin6_scope_id: u_long);
+ );
+ end;
+
+function SizeOfVarSin(sin: TVarSin): integer;
+
+function Bind(s: TSocket; const addr: TVarSin): Integer;
+function Connect(s: TSocket; const name: TVarSin): Integer;
+function GetSockName(s: TSocket; var name: TVarSin): Integer;
+function GetPeerName(s: TSocket; var name: TVarSin): Integer;
+function GetHostName: string;
+function Send(s: TSocket; Buf: TMemory; len, flags: Integer): Integer;
+function Recv(s: TSocket; Buf: TMemory; len, flags: Integer): Integer;
+function SendTo(s: TSocket; Buf: TMemory; len, flags: Integer; addrto: TVarSin): Integer;
+function RecvFrom(s: TSocket; Buf: TMemory; len, flags: Integer; var from: TVarSin): Integer;
+function Accept(s: TSocket; var addr: TVarSin): TSocket;
+
+function IsNewApi(Family: integer): Boolean;
+function SetVarSin(var Sin: TVarSin; IP, Port: string; Family, SockProtocol, SockType: integer; PreferIP4: Boolean): integer;
+function GetSinIP(Sin: TVarSin): string;
+function GetSinPort(Sin: TVarSin): Integer;
+procedure ResolveNameToIP(Name: string; Family, SockProtocol, SockType: integer; const IPList: TStrings);
+function ResolveIPToName(IP: string; Family, SockProtocol, SockType: integer): string;
+function ResolvePort(Port: string; Family, SockProtocol, SockType: integer): Word;
+
+{==============================================================================}
+implementation
+
+var
+ SynSockCount: Integer = 0;
+ LibHandle: TLibHandle = 0;
+ Libwship6Handle: TLibHandle = 0;
+
+function IN6_IS_ADDR_UNSPECIFIED(const a: PInAddr6): boolean;
+begin
+ Result := ((a^.u6_addr32[0] = 0) and (a^.u6_addr32[1] = 0) and
+ (a^.u6_addr32[2] = 0) and (a^.u6_addr32[3] = 0));
+end;
+
+function IN6_IS_ADDR_LOOPBACK(const a: PInAddr6): boolean;
+begin
+ Result := ((a^.u6_addr32[0] = 0) and (a^.u6_addr32[1] = 0) and
+ (a^.u6_addr32[2] = 0) and
+ (a^.u6_addr8[12] = 0) and (a^.u6_addr8[13] = 0) and
+ (a^.u6_addr8[14] = 0) and (a^.u6_addr8[15] = 1));
+end;
+
+function IN6_IS_ADDR_LINKLOCAL(const a: PInAddr6): boolean;
+begin
+ Result := ((a^.u6_addr8[0] = $FE) and (a^.u6_addr8[1] = $80));
+end;
+
+function IN6_IS_ADDR_SITELOCAL(const a: PInAddr6): boolean;
+begin
+ Result := ((a^.u6_addr8[0] = $FE) and (a^.u6_addr8[1] = $C0));
+end;
+
+function IN6_IS_ADDR_MULTICAST(const a: PInAddr6): boolean;
+begin
+ Result := (a^.u6_addr8[0] = $FF);
+end;
+
+function IN6_ADDR_EQUAL(const a: PInAddr6; const b: PInAddr6): boolean;
+begin
+ Result := (CompareMem( a, b, sizeof(TInAddr6)));
+end;
+
+procedure SET_IN6_IF_ADDR_ANY (const a: PInAddr6);
+begin
+ FillChar(a^, sizeof(TInAddr6), 0);
+end;
+
+procedure SET_LOOPBACK_ADDR6 (const a: PInAddr6);
+begin
+ FillChar(a^, sizeof(TInAddr6), 0);
+ a^.u6_addr8[15] := 1;
+end;
+
+{=============================================================================}
+var
+{$IFNDEF VER1_0} //FTP version 1.0.x
+ errno_loc: function: PInteger cdecl = nil;
+{$ELSE}
+ errno_loc: function: PInteger = nil; cdecl;
+{$ENDIF}
+
+function LSWSAStartup(wVersionRequired: Word; var WSData: TWSAData): Integer;
+begin
+ with WSData do
+ begin
+ wVersion := wVersionRequired;
+ wHighVersion := $202;
+ szDescription := 'Synsock - Synapse Platform Independent Socket Layer';
+ szSystemStatus := 'Running on Linux';
+ iMaxSockets := 32768;
+ iMaxUdpDg := 8192;
+ end;
+ Result := 0;
+end;
+
+function LSWSACleanup: Integer;
+begin
+ Result := 0;
+end;
+
+function LSWSAGetLastError: Integer;
+var
+ p: PInteger;
+begin
+ p := errno_loc;
+ Result := p^;
+end;
+
+function __FDELT(Socket: TSocket): Integer;
+begin
+ Result := Socket div __NFDBITS;
+end;
+
+function __FDMASK(Socket: TSocket): __fd_mask;
+begin
+ Result := LongWord(1) shl (Socket mod __NFDBITS);
+end;
+
+function FD_ISSET(Socket: TSocket; var fdset: TFDSet): Boolean;
+begin
+ Result := (fdset.fds_bits[__FDELT(Socket)] and __FDMASK(Socket)) <> 0;
+end;
+
+procedure FD_SET(Socket: TSocket; var fdset: TFDSet);
+begin
+ fdset.fds_bits[__FDELT(Socket)] := fdset.fds_bits[__FDELT(Socket)] or __FDMASK(Socket);
+end;
+
+procedure FD_CLR(Socket: TSocket; var fdset: TFDSet);
+begin
+ fdset.fds_bits[__FDELT(Socket)] := fdset.fds_bits[__FDELT(Socket)] and (not __FDMASK(Socket));
+end;
+
+procedure FD_ZERO(var fdset: TFDSet);
+var
+ I: Integer;
+begin
+ with fdset do
+ for I := Low(fds_bits) to High(fds_bits) do
+ fds_bits[I] := 0;
+end;
+
+{=============================================================================}
+
+function SizeOfVarSin(sin: TVarSin): integer;
+begin
+ case sin.sin_family of
+ AF_INET:
+ Result := SizeOf(TSockAddrIn);
+ AF_INET6:
+ Result := SizeOf(TSockAddrIn6);
+ else
+ Result := 0;
+ end;
+end;
+
+{=============================================================================}
+
+function Bind(s: TSocket; const addr: TVarSin): Integer;
+begin
+ Result := ssBind(s, @addr, SizeOfVarSin(addr));
+end;
+
+function Connect(s: TSocket; const name: TVarSin): Integer;
+begin
+ Result := ssConnect(s, @name, SizeOfVarSin(name));
+end;
+
+function GetSockName(s: TSocket; var name: TVarSin): Integer;
+var
+ len: integer;
+begin
+ len := SizeOf(name);
+ FillChar(name, len, 0);
+ Result := ssGetSockName(s, @name, Len);
+end;
+
+function GetPeerName(s: TSocket; var name: TVarSin): Integer;
+var
+ len: integer;
+begin
+ len := SizeOf(name);
+ FillChar(name, len, 0);
+ Result := ssGetPeerName(s, @name, Len);
+end;
+
+function GetHostName: string;
+var
+ s: string;
+begin
+ Result := '';
+ setlength(s, 255);
+ ssGetHostName(pchar(s), Length(s) - 1);
+ Result := Pchar(s);
+end;
+
+function Send(s: TSocket; Buf: TMemory; len, flags: Integer): Integer;
+begin
+ Result := ssSend(s, Buf^, len, flags);
+end;
+
+function Recv(s: TSocket; Buf: TMemory; len, flags: Integer): Integer;
+begin
+ Result := ssRecv(s, Buf^, len, flags);
+end;
+
+function SendTo(s: TSocket; Buf: TMemory; len, flags: Integer; addrto: TVarSin): Integer;
+begin
+ Result := ssSendTo(s, Buf^, len, flags, @addrto, SizeOfVarSin(addrto));
+end;
+
+function RecvFrom(s: TSocket; Buf: TMemory; len, flags: Integer; var from: TVarSin): Integer;
+var
+ x: integer;
+begin
+ x := SizeOf(from);
+ Result := ssRecvFrom(s, Buf^, len, flags, @from, x);
+end;
+
+function Accept(s: TSocket; var addr: TVarSin): TSocket;
+var
+ x: integer;
+begin
+ x := SizeOf(addr);
+ Result := ssAccept(s, @addr, x);
+end;
+
+{=============================================================================}
+function IsNewApi(Family: integer): Boolean;
+begin
+ Result := SockEnhancedApi;
+ if not Result then
+ Result := (Family = AF_INET6) and SockWship6Api;
+end;
+
+function SetVarSin(var Sin: TVarSin; IP, Port: string; Family, SockProtocol, SockType: integer; PreferIP4: Boolean): integer;
+type
+ pu_long = ^u_long;
+var
+ ProtoEnt: PProtoEnt;
+ ServEnt: PServEnt;
+ HostEnt: PHostEnt;
+ r: integer;
+ Hints1, Hints2: TAddrInfo;
+ Sin1, Sin2: TVarSin;
+ TwoPass: boolean;
+
+ function GetAddr(const IP, port: string; Hints: TAddrInfo; var Sin: TVarSin): integer;
+ var
+ Addr: PAddrInfo;
+ begin
+ Addr := nil;
+ try
+ FillChar(Sin, Sizeof(Sin), 0);
+ if Hints.ai_socktype = SOCK_RAW then
+ begin
+ Hints.ai_socktype := 0;
+ Hints.ai_protocol := 0;
+ Result := synsock.GetAddrInfo(PChar(IP), nil, @Hints, Addr);
+ end
+ else
+ begin
+ if (IP = cAnyHost) or (IP = c6AnyHost) then
+ begin
+ Hints.ai_flags := AI_PASSIVE;
+ Result := synsock.GetAddrInfo(nil, PChar(Port), @Hints, Addr);
+ end
+ else
+ if (IP = cLocalhost) or (IP = c6Localhost) then
+ begin
+ Result := synsock.GetAddrInfo(nil, PChar(Port), @Hints, Addr);
+ end
+ else
+ begin
+ Result := synsock.GetAddrInfo(PChar(IP), PChar(Port), @Hints, Addr);
+ end;
+ end;
+ if Result = 0 then
+ if (Addr <> nil) then
+ Move(Addr^.ai_addr^, Sin, Addr^.ai_addrlen);
+ finally
+ if Assigned(Addr) then
+ synsock.FreeAddrInfo(Addr);
+ end;
+ end;
+
+begin
+ Result := 0;
+ FillChar(Sin, Sizeof(Sin), 0);
+ if not IsNewApi(family) then
+ begin
+ SynSockCS.Enter;
+ try
+ Sin.sin_family := AF_INET;
+ ProtoEnt := synsock.GetProtoByNumber(SockProtocol);
+ ServEnt := nil;
+ if ProtoEnt <> nil then
+ ServEnt := synsock.GetServByName(PChar(Port), ProtoEnt^.p_name);
+ if ServEnt = nil then
+ Sin.sin_port := synsock.htons(StrToIntDef(Port, 0))
+ else
+ Sin.sin_port := ServEnt^.s_port;
+ if IP = cBroadcast then
+ Sin.sin_addr.s_addr := u_long(INADDR_BROADCAST)
+ else
+ begin
+ Sin.sin_addr.s_addr := synsock.inet_addr(PChar(IP));
+ if Sin.sin_addr.s_addr = u_long(INADDR_NONE) then
+ begin
+ HostEnt := synsock.GetHostByName(PChar(IP));
+ Result := synsock.WSAGetLastError;
+ if HostEnt <> nil then
+ Sin.sin_addr.S_addr := u_long(Pu_long(HostEnt^.h_addr_list^)^);
+ end;
+ end;
+ finally
+ SynSockCS.Leave;
+ end;
+ end
+ else
+ begin
+ FillChar(Hints1, Sizeof(Hints1), 0);
+ FillChar(Hints2, Sizeof(Hints2), 0);
+ TwoPass := False;
+ if Family = AF_UNSPEC then
+ begin
+ if PreferIP4 then
+ begin
+ Hints1.ai_family := AF_INET;
+ Hints2.ai_family := AF_INET6;
+ TwoPass := True;
+ end
+ else
+ begin
+ Hints2.ai_family := AF_INET;
+ Hints1.ai_family := AF_INET6;
+ TwoPass := True;
+ end;
+ end
+ else
+ Hints1.ai_family := Family;
+
+ Hints1.ai_socktype := SockType;
+ Hints1.ai_protocol := SockProtocol;
+ Hints2.ai_socktype := Hints1.ai_socktype;
+ Hints2.ai_protocol := Hints1.ai_protocol;
+
+ r := GetAddr(IP, Port, Hints1, Sin1);
+ Result := r;
+ sin := sin1;
+ if r <> 0 then
+ if TwoPass then
+ begin
+ r := GetAddr(IP, Port, Hints2, Sin2);
+ Result := r;
+ if r = 0 then
+ sin := sin2;
+ end;
+ end;
+end;
+
+function GetSinIP(Sin: TVarSin): string;
+var
+ p: PChar;
+ host, serv: string;
+ hostlen, servlen: integer;
+ r: integer;
+begin
+ Result := '';
+ if not IsNewApi(Sin.AddressFamily) then
+ begin
+ p := synsock.inet_ntoa(Sin.sin_addr);
+ if p <> nil then
+ Result := p;
+ end
+ else
+ begin
+ hostlen := NI_MAXHOST;
+ servlen := NI_MAXSERV;
+ setlength(host, hostlen);
+ setlength(serv, servlen);
+ r := getnameinfo(@sin, SizeOfVarSin(sin), PChar(host), hostlen,
+ PChar(serv), servlen, NI_NUMERICHOST + NI_NUMERICSERV);
+ if r = 0 then
+ Result := PChar(host);
+ end;
+end;
+
+function GetSinPort(Sin: TVarSin): Integer;
+begin
+ if (Sin.sin_family = AF_INET6) then
+ Result := synsock.ntohs(Sin.sin6_port)
+ else
+ Result := synsock.ntohs(Sin.sin_port);
+end;
+
+procedure ResolveNameToIP(Name: string; Family, SockProtocol, SockType: integer; const IPList: TStrings);
+type
+ TaPInAddr = array[0..250] of PInAddr;
+ PaPInAddr = ^TaPInAddr;
+var
+ Hints: TAddrInfo;
+ Addr: PAddrInfo;
+ AddrNext: PAddrInfo;
+ r: integer;
+ host, serv: string;
+ hostlen, servlen: integer;
+ RemoteHost: PHostEnt;
+ IP: u_long;
+ PAdrPtr: PaPInAddr;
+ i: Integer;
+ s: string;
+ InAddr: TInAddr;
+begin
+ IPList.Clear;
+ if not IsNewApi(Family) then
+ begin
+ IP := synsock.inet_addr(PChar(Name));
+ if IP = u_long(INADDR_NONE) then
+ begin
+ SynSockCS.Enter;
+ try
+ RemoteHost := synsock.GetHostByName(PChar(Name));
+ if RemoteHost <> nil then
+ begin
+ PAdrPtr := PAPInAddr(RemoteHost^.h_addr_list);
+ i := 0;
+ while PAdrPtr^[i] <> nil do
+ begin
+ InAddr := PAdrPtr^[i]^;
+ s := Format('%d.%d.%d.%d', [InAddr.S_bytes[0], InAddr.S_bytes[1],
+ InAddr.S_bytes[2], InAddr.S_bytes[3]]);
+ IPList.Add(s);
+ Inc(i);
+ end;
+ end;
+ finally
+ SynSockCS.Leave;
+ end;
+ end
+ else
+ IPList.Add(Name);
+ end
+ else
+ begin
+ Addr := nil;
+ try
+ FillChar(Hints, Sizeof(Hints), 0);
+ Hints.ai_family := AF_UNSPEC;
+ Hints.ai_socktype := SockType;
+ Hints.ai_protocol := SockProtocol;
+ Hints.ai_flags := 0;
+ r := synsock.GetAddrInfo(PChar(Name), nil, @Hints, Addr);
+ if r = 0 then
+ begin
+ AddrNext := Addr;
+ while not(AddrNext = nil) do
+ begin
+ if not(((Family = AF_INET6) and (AddrNext^.ai_family = AF_INET))
+ or ((Family = AF_INET) and (AddrNext^.ai_family = AF_INET6))) then
+ begin
+ hostlen := NI_MAXHOST;
+ servlen := NI_MAXSERV;
+ setlength(host, hostlen);
+ setlength(serv, servlen);
+ r := getnameinfo(AddrNext^.ai_addr, AddrNext^.ai_addrlen,
+ PChar(host), hostlen, PChar(serv), servlen,
+ NI_NUMERICHOST + NI_NUMERICSERV);
+ if r = 0 then
+ begin
+ host := PChar(host);
+ IPList.Add(host);
+ end;
+ end;
+ AddrNext := AddrNext^.ai_next;
+ end;
+ end;
+ finally
+ if Assigned(Addr) then
+ synsock.FreeAddrInfo(Addr);
+ end;
+ end;
+ if IPList.Count = 0 then
+ IPList.Add(cAnyHost);
+end;
+
+function ResolvePort(Port: string; Family, SockProtocol, SockType: integer): Word;
+var
+ ProtoEnt: PProtoEnt;
+ ServEnt: PServEnt;
+ Hints: TAddrInfo;
+ Addr: PAddrInfo;
+ r: integer;
+begin
+ Result := 0;
+ if not IsNewApi(Family) then
+ begin
+ SynSockCS.Enter;
+ try
+ ProtoEnt := synsock.GetProtoByNumber(SockProtocol);
+ ServEnt := nil;
+ if ProtoEnt <> nil then
+ ServEnt := synsock.GetServByName(PChar(Port), ProtoEnt^.p_name);
+ if ServEnt = nil then
+ Result := StrToIntDef(Port, 0)
+ else
+ Result := synsock.htons(ServEnt^.s_port);
+ finally
+ SynSockCS.Leave;
+ end;
+ end
+ else
+ begin
+ Addr := nil;
+ try
+ FillChar(Hints, Sizeof(Hints), 0);
+ Hints.ai_family := AF_UNSPEC;
+ Hints.ai_socktype := SockType;
+ Hints.ai_protocol := Sockprotocol;
+ Hints.ai_flags := AI_PASSIVE;
+ r := synsock.GetAddrInfo(nil, PChar(Port), @Hints, Addr);
+ if (r = 0) and Assigned(Addr) then
+ begin
+ if Addr^.ai_family = AF_INET then
+ Result := synsock.htons(Addr^.ai_addr^.sin_port);
+ if Addr^.ai_family = AF_INET6 then
+ Result := synsock.htons(PSockAddrIn6(Addr^.ai_addr)^.sin6_port);
+ end;
+ finally
+ if Assigned(Addr) then
+ synsock.FreeAddrInfo(Addr);
+ end;
+ end;
+end;
+
+function ResolveIPToName(IP: string; Family, SockProtocol, SockType: integer): string;
+var
+ Hints: TAddrInfo;
+ Addr: PAddrInfo;
+ r: integer;
+ host, serv: string;
+ hostlen, servlen: integer;
+ RemoteHost: PHostEnt;
+ IPn: u_long;
+begin
+ Result := IP;
+ if not IsNewApi(Family) then
+ begin
+ IPn := synsock.inet_addr(PChar(IP));
+ if IPn <> u_long(INADDR_NONE) then
+ begin
+ SynSockCS.Enter;
+ try
+ RemoteHost := GetHostByAddr(@IPn, SizeOf(IPn), AF_INET);
+ if RemoteHost <> nil then
+ Result := RemoteHost^.h_name;
+ finally
+ SynSockCS.Leave;
+ end;
+ end;
+ end
+ else
+ begin
+ Addr := nil;
+ try
+ FillChar(Hints, Sizeof(Hints), 0);
+ Hints.ai_family := AF_UNSPEC;
+ Hints.ai_socktype := SockType;
+ Hints.ai_protocol := SockProtocol;
+ Hints.ai_flags := 0;
+ r := synsock.GetAddrInfo(PChar(IP), nil, @Hints, Addr);
+ if (r = 0) and Assigned(Addr)then
+ begin
+ hostlen := NI_MAXHOST;
+ servlen := NI_MAXSERV;
+ setlength(host, hostlen);
+ setlength(serv, servlen);
+ r := getnameinfo(Addr^.ai_addr, Addr^.ai_addrlen,
+ PChar(host), hostlen, PChar(serv), servlen,
+ NI_NUMERICSERV);
+ if r = 0 then
+ Result := PChar(host);
+ end;
+ finally
+ if Assigned(Addr) then
+ synsock.FreeAddrInfo(Addr);
+ end;
+ end;
+end;
+
+{=============================================================================}
+
+function InitSocketInterface(stack: string): Boolean;
+begin
+ Result := False;
+ SockEnhancedApi := False;
+ if stack = '' then
+ stack := DLLStackName;
+ SynSockCS.Enter;
+ try
+ if SynSockCount = 0 then
+ begin
+ SockEnhancedApi := False;
+ SockWship6Api := False;
+ Libc.Signal(Libc.SIGPIPE, TSignalHandler(Libc.SIG_IGN));
+ LibHandle := LoadLibrary(PChar(Stack));
+ if LibHandle <> 0 then
+ begin
+ errno_loc := GetProcAddress(LibHandle, PChar('__errno_location'));
+ CloseSocket := GetProcAddress(LibHandle, PChar('close'));
+ IoctlSocket := GetProcAddress(LibHandle, PChar('ioctl'));
+ WSAGetLastError := LSWSAGetLastError;
+ WSAStartup := LSWSAStartup;
+ WSACleanup := LSWSACleanup;
+ ssAccept := GetProcAddress(LibHandle, PChar('accept'));
+ ssBind := GetProcAddress(LibHandle, PChar('bind'));
+ ssConnect := GetProcAddress(LibHandle, PChar('connect'));
+ ssGetPeerName := GetProcAddress(LibHandle, PChar('getpeername'));
+ ssGetSockName := GetProcAddress(LibHandle, PChar('getsockname'));
+ GetSockOpt := GetProcAddress(LibHandle, PChar('getsockopt'));
+ Htonl := GetProcAddress(LibHandle, PChar('htonl'));
+ Htons := GetProcAddress(LibHandle, PChar('htons'));
+ Inet_Addr := GetProcAddress(LibHandle, PChar('inet_addr'));
+ Inet_Ntoa := GetProcAddress(LibHandle, PChar('inet_ntoa'));
+ Listen := GetProcAddress(LibHandle, PChar('listen'));
+ Ntohl := GetProcAddress(LibHandle, PChar('ntohl'));
+ Ntohs := GetProcAddress(LibHandle, PChar('ntohs'));
+ ssRecv := GetProcAddress(LibHandle, PChar('recv'));
+ ssRecvFrom := GetProcAddress(LibHandle, PChar('recvfrom'));
+ Select := GetProcAddress(LibHandle, PChar('select'));
+ ssSend := GetProcAddress(LibHandle, PChar('send'));
+ ssSendTo := GetProcAddress(LibHandle, PChar('sendto'));
+ SetSockOpt := GetProcAddress(LibHandle, PChar('setsockopt'));
+ ShutDown := GetProcAddress(LibHandle, PChar('shutdown'));
+ Socket := GetProcAddress(LibHandle, PChar('socket'));
+ GetHostByAddr := GetProcAddress(LibHandle, PChar('gethostbyaddr'));
+ GetHostByName := GetProcAddress(LibHandle, PChar('gethostbyname'));
+ GetProtoByName := GetProcAddress(LibHandle, PChar('getprotobyname'));
+ GetProtoByNumber := GetProcAddress(LibHandle, PChar('getprotobynumber'));
+ GetServByName := GetProcAddress(LibHandle, PChar('getservbyname'));
+ GetServByPort := GetProcAddress(LibHandle, PChar('getservbyport'));
+ ssGetHostName := GetProcAddress(LibHandle, PChar('gethostname'));
+
+{$IFNDEF FORCEOLDAPI}
+ GetAddrInfo := GetProcAddress(LibHandle, PChar('getaddrinfo'));
+ FreeAddrInfo := GetProcAddress(LibHandle, PChar('freeaddrinfo'));
+ GetNameInfo := GetProcAddress(LibHandle, PChar('getnameinfo'));
+ SockEnhancedApi := Assigned(GetAddrInfo) and Assigned(FreeAddrInfo)
+ and Assigned(GetNameInfo);
+{$ENDIF}
+ Result := True;
+ end;
+ end
+ else Result := True;
+ if Result then
+ Inc(SynSockCount);
+ finally
+ SynSockCS.Leave;
+ end;
+end;
+
+function DestroySocketInterface: Boolean;
+begin
+ SynSockCS.Enter;
+ try
+ Dec(SynSockCount);
+ if SynSockCount < 0 then
+ SynSockCount := 0;
+ if SynSockCount = 0 then
+ begin
+ if LibHandle <> 0 then
+ begin
+ FreeLibrary(libHandle);
+ LibHandle := 0;
+ end;
+ if LibWship6Handle <> 0 then
+ begin
+ FreeLibrary(LibWship6Handle);
+ LibWship6Handle := 0;
+ end;
+ end;
+ finally
+ SynSockCS.Leave;
+ end;
+ Result := True;
+end;
+
+initialization
+begin
+ SynSockCS := SyncObjs.TCriticalSection.Create;
+ SET_IN6_IF_ADDR_ANY (@in6addr_any);
+ SET_LOOPBACK_ADDR6 (@in6addr_loopback);
+end;
+
+finalization
+begin
+ SynSockCS.Free;
+end;
+
+{$ENDIF}
+
diff --git a/branches/script-component/Units/Synapse/sswin32.pas b/branches/script-component/Units/Synapse/sswin32.pas
new file mode 100644
index 0000000..9661ef4
--- /dev/null
+++ b/branches/script-component/Units/Synapse/sswin32.pas
@@ -0,0 +1,1585 @@
+{==============================================================================|
+| Project : Ararat Synapse | 002.002.000 |
+|==============================================================================|
+| Content: Socket Independent Platform Layer - Win32 definition include |
+|==============================================================================|
+| Copyright (c)1999-2008, Lukas Gebauer |
+| All rights reserved. |
+| |
+| Redistribution and use in source and binary forms, with or without |
+| modification, are permitted provided that the following conditions are met: |
+| |
+| Redistributions of source code must retain the above copyright notice, this |
+| list of conditions and the following disclaimer. |
+| |
+| Redistributions in binary form must reproduce the above copyright notice, |
+| this list of conditions and the following disclaimer in the documentation |
+| and/or other materials provided with the distribution. |
+| |
+| Neither the name of Lukas Gebauer nor the names of its contributors may |
+| be used to endorse or promote products derived from this software without |
+| specific prior written permission. |
+| |
+| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
+| AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
+| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
+| ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR |
+| ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
+| DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
+| SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
+| CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
+| LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
+| OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
+| DAMAGE. |
+|==============================================================================|
+| The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).|
+| Portions created by Lukas Gebauer are Copyright (c)2003. |
+| All Rights Reserved. |
+|==============================================================================|
+| Contributor(s): |
+|==============================================================================|
+| History: see HISTORY.HTM from distribution package |
+| (Found at URL: http://www.ararat.cz/synapse/) |
+|==============================================================================}
+
+{:@exclude}
+
+{$IFDEF WIN32}
+
+//{$DEFINE WINSOCK1}
+{Note about define WINSOCK1:
+If you activate this compiler directive, then socket interface level 1.1 is
+used instead default level 2.2. Level 2.2 is not available on old W95, however
+you can install update.
+}
+
+//{$DEFINE FORCEOLDAPI}
+{Note about define FORCEOLDAPI:
+If you activate this compiler directive, then is allways used old socket API
+for name resolution. If you leave this directive inactive, then the new API
+is used, when running system allows it.
+
+For IPv6 support you must have new API!
+}
+
+{$IFDEF FPC}
+ {$MODE DELPHI}
+{$ENDIF}
+{$H+}
+{$IFDEF VER125}
+ {$DEFINE BCB}
+{$ENDIF}
+{$IFDEF BCB}
+ {$ObjExportAll On}
+ (*$HPPEMIT '/* EDE 2003-02-19 */' *)
+ (*$HPPEMIT 'namespace Synsock { using System::Shortint; }' *)
+ (*$HPPEMIT '#undef h_addr' *)
+ (*$HPPEMIT '#undef IOCPARM_MASK' *)
+ (*$HPPEMIT '#undef FD_SETSIZE' *)
+ (*$HPPEMIT '#undef IOC_VOID' *)
+ (*$HPPEMIT '#undef IOC_OUT' *)
+ (*$HPPEMIT '#undef IOC_IN' *)
+ (*$HPPEMIT '#undef IOC_INOUT' *)
+ (*$HPPEMIT '#undef FIONREAD' *)
+ (*$HPPEMIT '#undef FIONBIO' *)
+ (*$HPPEMIT '#undef FIOASYNC' *)
+ (*$HPPEMIT '#undef IPPROTO_IP' *)
+ (*$HPPEMIT '#undef IPPROTO_ICMP' *)
+ (*$HPPEMIT '#undef IPPROTO_IGMP' *)
+ (*$HPPEMIT '#undef IPPROTO_TCP' *)
+ (*$HPPEMIT '#undef IPPROTO_UDP' *)
+ (*$HPPEMIT '#undef IPPROTO_RAW' *)
+ (*$HPPEMIT '#undef IPPROTO_MAX' *)
+ (*$HPPEMIT '#undef INADDR_ANY' *)
+ (*$HPPEMIT '#undef INADDR_LOOPBACK' *)
+ (*$HPPEMIT '#undef INADDR_BROADCAST' *)
+ (*$HPPEMIT '#undef INADDR_NONE' *)
+ (*$HPPEMIT '#undef INVALID_SOCKET' *)
+ (*$HPPEMIT '#undef SOCKET_ERROR' *)
+ (*$HPPEMIT '#undef WSADESCRIPTION_LEN' *)
+ (*$HPPEMIT '#undef WSASYS_STATUS_LEN' *)
+ (*$HPPEMIT '#undef IP_OPTIONS' *)
+ (*$HPPEMIT '#undef IP_TOS' *)
+ (*$HPPEMIT '#undef IP_TTL' *)
+ (*$HPPEMIT '#undef IP_MULTICAST_IF' *)
+ (*$HPPEMIT '#undef IP_MULTICAST_TTL' *)
+ (*$HPPEMIT '#undef IP_MULTICAST_LOOP' *)
+ (*$HPPEMIT '#undef IP_ADD_MEMBERSHIP' *)
+ (*$HPPEMIT '#undef IP_DROP_MEMBERSHIP' *)
+ (*$HPPEMIT '#undef IP_DONTFRAGMENT' *)
+ (*$HPPEMIT '#undef IP_DEFAULT_MULTICAST_TTL' *)
+ (*$HPPEMIT '#undef IP_DEFAULT_MULTICAST_LOOP' *)
+ (*$HPPEMIT '#undef IP_MAX_MEMBERSHIPS' *)
+ (*$HPPEMIT '#undef SOL_SOCKET' *)
+ (*$HPPEMIT '#undef SO_DEBUG' *)
+ (*$HPPEMIT '#undef SO_ACCEPTCONN' *)
+ (*$HPPEMIT '#undef SO_REUSEADDR' *)
+ (*$HPPEMIT '#undef SO_KEEPALIVE' *)
+ (*$HPPEMIT '#undef SO_DONTROUTE' *)
+ (*$HPPEMIT '#undef SO_BROADCAST' *)
+ (*$HPPEMIT '#undef SO_USELOOPBACK' *)
+ (*$HPPEMIT '#undef SO_LINGER' *)
+ (*$HPPEMIT '#undef SO_OOBINLINE' *)
+ (*$HPPEMIT '#undef SO_DONTLINGER' *)
+ (*$HPPEMIT '#undef SO_SNDBUF' *)
+ (*$HPPEMIT '#undef SO_RCVBUF' *)
+ (*$HPPEMIT '#undef SO_SNDLOWAT' *)
+ (*$HPPEMIT '#undef SO_RCVLOWAT' *)
+ (*$HPPEMIT '#undef SO_SNDTIMEO' *)
+ (*$HPPEMIT '#undef SO_RCVTIMEO' *)
+ (*$HPPEMIT '#undef SO_ERROR' *)
+ (*$HPPEMIT '#undef SO_OPENTYPE' *)
+ (*$HPPEMIT '#undef SO_SYNCHRONOUS_ALERT' *)
+ (*$HPPEMIT '#undef SO_SYNCHRONOUS_NONALERT' *)
+ (*$HPPEMIT '#undef SO_MAXDG' *)
+ (*$HPPEMIT '#undef SO_MAXPATHDG' *)
+ (*$HPPEMIT '#undef SO_UPDATE_ACCEPT_CONTEXT' *)
+ (*$HPPEMIT '#undef SO_CONNECT_TIME' *)
+ (*$HPPEMIT '#undef SO_TYPE' *)
+ (*$HPPEMIT '#undef SOCK_STREAM' *)
+ (*$HPPEMIT '#undef SOCK_DGRAM' *)
+ (*$HPPEMIT '#undef SOCK_RAW' *)
+ (*$HPPEMIT '#undef SOCK_RDM' *)
+ (*$HPPEMIT '#undef SOCK_SEQPACKET' *)
+ (*$HPPEMIT '#undef TCP_NODELAY' *)
+ (*$HPPEMIT '#undef AF_UNSPEC' *)
+ (*$HPPEMIT '#undef SOMAXCONN' *)
+ (*$HPPEMIT '#undef AF_INET' *)
+ (*$HPPEMIT '#undef AF_MAX' *)
+ (*$HPPEMIT '#undef PF_UNSPEC' *)
+ (*$HPPEMIT '#undef PF_INET' *)
+ (*$HPPEMIT '#undef PF_MAX' *)
+ (*$HPPEMIT '#undef MSG_OOB' *)
+ (*$HPPEMIT '#undef MSG_PEEK' *)
+ (*$HPPEMIT '#undef WSABASEERR' *)
+ (*$HPPEMIT '#undef WSAEINTR' *)
+ (*$HPPEMIT '#undef WSAEBADF' *)
+ (*$HPPEMIT '#undef WSAEACCES' *)
+ (*$HPPEMIT '#undef WSAEFAULT' *)
+ (*$HPPEMIT '#undef WSAEINVAL' *)
+ (*$HPPEMIT '#undef WSAEMFILE' *)
+ (*$HPPEMIT '#undef WSAEWOULDBLOCK' *)
+ (*$HPPEMIT '#undef WSAEINPROGRESS' *)
+ (*$HPPEMIT '#undef WSAEALREADY' *)
+ (*$HPPEMIT '#undef WSAENOTSOCK' *)
+ (*$HPPEMIT '#undef WSAEDESTADDRREQ' *)
+ (*$HPPEMIT '#undef WSAEMSGSIZE' *)
+ (*$HPPEMIT '#undef WSAEPROTOTYPE' *)
+ (*$HPPEMIT '#undef WSAENOPROTOOPT' *)
+ (*$HPPEMIT '#undef WSAEPROTONOSUPPORT' *)
+ (*$HPPEMIT '#undef WSAESOCKTNOSUPPORT' *)
+ (*$HPPEMIT '#undef WSAEOPNOTSUPP' *)
+ (*$HPPEMIT '#undef WSAEPFNOSUPPORT' *)
+ (*$HPPEMIT '#undef WSAEAFNOSUPPORT' *)
+ (*$HPPEMIT '#undef WSAEADDRINUSE' *)
+ (*$HPPEMIT '#undef WSAEADDRNOTAVAIL' *)
+ (*$HPPEMIT '#undef WSAENETDOWN' *)
+ (*$HPPEMIT '#undef WSAENETUNREACH' *)
+ (*$HPPEMIT '#undef WSAENETRESET' *)
+ (*$HPPEMIT '#undef WSAECONNABORTED' *)
+ (*$HPPEMIT '#undef WSAECONNRESET' *)
+ (*$HPPEMIT '#undef WSAENOBUFS' *)
+ (*$HPPEMIT '#undef WSAEISCONN' *)
+ (*$HPPEMIT '#undef WSAENOTCONN' *)
+ (*$HPPEMIT '#undef WSAESHUTDOWN' *)
+ (*$HPPEMIT '#undef WSAETOOMANYREFS' *)
+ (*$HPPEMIT '#undef WSAETIMEDOUT' *)
+ (*$HPPEMIT '#undef WSAECONNREFUSED' *)
+ (*$HPPEMIT '#undef WSAELOOP' *)
+ (*$HPPEMIT '#undef WSAENAMETOOLONG' *)
+ (*$HPPEMIT '#undef WSAEHOSTDOWN' *)
+ (*$HPPEMIT '#undef WSAEHOSTUNREACH' *)
+ (*$HPPEMIT '#undef WSAENOTEMPTY' *)
+ (*$HPPEMIT '#undef WSAEPROCLIM' *)
+ (*$HPPEMIT '#undef WSAEUSERS' *)
+ (*$HPPEMIT '#undef WSAEDQUOT' *)
+ (*$HPPEMIT '#undef WSAESTALE' *)
+ (*$HPPEMIT '#undef WSAEREMOTE' *)
+ (*$HPPEMIT '#undef WSASYSNOTREADY' *)
+ (*$HPPEMIT '#undef WSAVERNOTSUPPORTED' *)
+ (*$HPPEMIT '#undef WSANOTINITIALISED' *)
+ (*$HPPEMIT '#undef WSAEDISCON' *)
+ (*$HPPEMIT '#undef WSAENOMORE' *)
+ (*$HPPEMIT '#undef WSAECANCELLED' *)
+ (*$HPPEMIT '#undef WSAEEINVALIDPROCTABLE' *)
+ (*$HPPEMIT '#undef WSAEINVALIDPROVIDER' *)
+ (*$HPPEMIT '#undef WSAEPROVIDERFAILEDINIT' *)
+ (*$HPPEMIT '#undef WSASYSCALLFAILURE' *)
+ (*$HPPEMIT '#undef WSASERVICE_NOT_FOUND' *)
+ (*$HPPEMIT '#undef WSATYPE_NOT_FOUND' *)
+ (*$HPPEMIT '#undef WSA_E_NO_MORE' *)
+ (*$HPPEMIT '#undef WSA_E_CANCELLED' *)
+ (*$HPPEMIT '#undef WSAEREFUSED' *)
+ (*$HPPEMIT '#undef WSAHOST_NOT_FOUND' *)
+ (*$HPPEMIT '#undef HOST_NOT_FOUND' *)
+ (*$HPPEMIT '#undef WSATRY_AGAIN' *)
+ (*$HPPEMIT '#undef TRY_AGAIN' *)
+ (*$HPPEMIT '#undef WSANO_RECOVERY' *)
+ (*$HPPEMIT '#undef NO_RECOVERY' *)
+ (*$HPPEMIT '#undef WSANO_DATA' *)
+ (*$HPPEMIT '#undef NO_DATA' *)
+ (*$HPPEMIT '#undef WSANO_ADDRESS' *)
+ (*$HPPEMIT '#undef ENAMETOOLONG' *)
+ (*$HPPEMIT '#undef ENOTEMPTY' *)
+ (*$HPPEMIT '#undef FD_CLR' *)
+ (*$HPPEMIT '#undef FD_ISSET' *)
+ (*$HPPEMIT '#undef FD_SET' *)
+ (*$HPPEMIT '#undef FD_ZERO' *)
+ (*$HPPEMIT '#undef NO_ADDRESS' *)
+ (*$HPPEMIT '#undef ADDR_ANY' *)
+ (*$HPPEMIT '#undef SO_GROUP_ID' *)
+ (*$HPPEMIT '#undef SO_GROUP_PRIORITY' *)
+ (*$HPPEMIT '#undef SO_MAX_MSG_SIZE' *)
+ (*$HPPEMIT '#undef SO_PROTOCOL_INFOA' *)
+ (*$HPPEMIT '#undef SO_PROTOCOL_INFOW' *)
+ (*$HPPEMIT '#undef SO_PROTOCOL_INFO' *)
+ (*$HPPEMIT '#undef PVD_CONFIG' *)
+ (*$HPPEMIT '#undef AF_INET6' *)
+ (*$HPPEMIT '#undef PF_INET6' *)
+{$ENDIF}
+
+interface
+
+uses
+ SyncObjs, SysUtils, Classes,
+ Windows;
+
+function InitSocketInterface(stack: String): Boolean;
+function DestroySocketInterface: Boolean;
+
+const
+{$IFDEF WINSOCK1}
+ WinsockLevel = $0101;
+{$ELSE}
+ WinsockLevel = $0202;
+{$ENDIF}
+
+type
+ u_short = Word;
+ u_int = Integer;
+ u_long = Longint;
+ pu_long = ^u_long;
+ pu_short = ^u_short;
+ TSocket = u_int;
+ TAddrFamily = integer;
+
+ TMemory = pointer;
+
+const
+ {$IFDEF WINSOCK1}
+ DLLStackName = 'wsock32.dll';
+ {$ELSE}
+ DLLStackName = 'ws2_32.dll';
+ {$ENDIF}
+ DLLwship6 = 'wship6.dll';
+
+ cLocalhost = '127.0.0.1';
+ cAnyHost = '0.0.0.0';
+ cBroadcast = '255.255.255.255';
+ c6Localhost = '::1';
+ c6AnyHost = '::0';
+ c6Broadcast = 'ffff::1';
+ cAnyPort = '0';
+
+
+const
+ FD_SETSIZE = 64;
+type
+ PFDSet = ^TFDSet;
+ TFDSet = packed record
+ fd_count: u_int;
+ fd_array: array[0..FD_SETSIZE-1] of TSocket;
+ end;
+
+const
+ FIONREAD = $4004667f;
+ FIONBIO = $8004667e;
+ FIOASYNC = $8004667d;
+
+type
+ PTimeVal = ^TTimeVal;
+ TTimeVal = packed record
+ tv_sec: Longint;
+ tv_usec: Longint;
+ end;
+
+const
+ IPPROTO_IP = 0; { Dummy }
+ IPPROTO_ICMP = 1; { Internet Control Message Protocol }
+ IPPROTO_IGMP = 2; { Internet Group Management Protocol}
+ IPPROTO_TCP = 6; { TCP }
+ IPPROTO_UDP = 17; { User Datagram Protocol }
+ IPPROTO_IPV6 = 41;
+ IPPROTO_ICMPV6 = 58;
+
+ IPPROTO_RAW = 255;
+ IPPROTO_MAX = 256;
+
+type
+
+ PInAddr = ^TInAddr;
+ TInAddr = packed record
+ case integer of
+ 0: (S_bytes: packed array [0..3] of byte);
+ 1: (S_addr: u_long);
+ end;
+
+ PSockAddrIn = ^TSockAddrIn;
+ TSockAddrIn = packed record
+ case Integer of
+ 0: (sin_family: u_short;
+ sin_port: u_short;
+ sin_addr: TInAddr;
+ sin_zero: array[0..7] of byte);
+ 1: (sa_family: u_short;
+ sa_data: array[0..13] of byte)
+ end;
+
+ TIP_mreq = record
+ imr_multiaddr: TInAddr; { IP multicast address of group }
+ imr_interface: TInAddr; { local IP address of interface }
+ end;
+
+ PInAddr6 = ^TInAddr6;
+ TInAddr6 = packed record
+ case integer of
+ 0: (S6_addr: packed array [0..15] of byte);
+ 1: (u6_addr8: packed array [0..15] of byte);
+ 2: (u6_addr16: packed array [0..7] of word);
+ 3: (u6_addr32: packed array [0..3] of integer);
+ end;
+
+ PSockAddrIn6 = ^TSockAddrIn6;
+ TSockAddrIn6 = packed record
+ sin6_family: u_short; // AF_INET6
+ sin6_port: u_short; // Transport level port number
+ sin6_flowinfo: u_long; // IPv6 flow information
+ sin6_addr: TInAddr6; // IPv6 address
+ sin6_scope_id: u_long; // Scope Id: IF number for link-local
+ // SITE id for site-local
+ end;
+
+ TIPv6_mreq = record
+ ipv6mr_multiaddr: TInAddr6; // IPv6 multicast address.
+ ipv6mr_interface: integer; // Interface index.
+ padding: integer;
+ end;
+
+ PHostEnt = ^THostEnt;
+ THostEnt = packed record
+ h_name: PAnsiChar;
+ h_aliases: ^PAnsiChar;
+ h_addrtype: Smallint;
+ h_length: Smallint;
+ case integer of
+ 0: (h_addr_list: ^PAnsiChar);
+ 1: (h_addr: ^PInAddr);
+ end;
+
+ PNetEnt = ^TNetEnt;
+ TNetEnt = packed record
+ n_name: PAnsiChar;
+ n_aliases: ^PAnsiChar;
+ n_addrtype: Smallint;
+ n_net: u_long;
+ end;
+
+ PServEnt = ^TServEnt;
+ TServEnt = packed record
+ s_name: PAnsiChar;
+ s_aliases: ^PAnsiChar;
+ s_port: Smallint;
+ s_proto: PAnsiChar;
+ end;
+
+ PProtoEnt = ^TProtoEnt;
+ TProtoEnt = packed record
+ p_name: PAnsiChar;
+ p_aliases: ^PAnsichar;
+ p_proto: Smallint;
+ end;
+
+const
+ INADDR_ANY = $00000000;
+ INADDR_LOOPBACK = $7F000001;
+ INADDR_BROADCAST = $FFFFFFFF;
+ INADDR_NONE = $FFFFFFFF;
+ ADDR_ANY = INADDR_ANY;
+ INVALID_SOCKET = TSocket(NOT(0));
+ SOCKET_ERROR = -1;
+
+Const
+ {$IFDEF WINSOCK1}
+ IP_OPTIONS = 1;
+ IP_MULTICAST_IF = 2; { set/get IP multicast interface }
+ IP_MULTICAST_TTL = 3; { set/get IP multicast timetolive }
+ IP_MULTICAST_LOOP = 4; { set/get IP multicast loopback }
+ IP_ADD_MEMBERSHIP = 5; { add an IP group membership }
+ IP_DROP_MEMBERSHIP = 6; { drop an IP group membership }
+ IP_TTL = 7; { set/get IP Time To Live }
+ IP_TOS = 8; { set/get IP Type Of Service }
+ IP_DONTFRAGMENT = 9; { set/get IP Don't Fragment flag }
+ {$ELSE}
+ IP_OPTIONS = 1;
+ IP_HDRINCL = 2;
+ IP_TOS = 3; { set/get IP Type Of Service }
+ IP_TTL = 4; { set/get IP Time To Live }
+ IP_MULTICAST_IF = 9; { set/get IP multicast interface }
+ IP_MULTICAST_TTL = 10; { set/get IP multicast timetolive }
+ IP_MULTICAST_LOOP = 11; { set/get IP multicast loopback }
+ IP_ADD_MEMBERSHIP = 12; { add an IP group membership }
+ IP_DROP_MEMBERSHIP = 13; { drop an IP group membership }
+ IP_DONTFRAGMENT = 14; { set/get IP Don't Fragment flag }
+ {$ENDIF}
+
+ IP_DEFAULT_MULTICAST_TTL = 1; { normally limit m'casts to 1 hop }
+ IP_DEFAULT_MULTICAST_LOOP = 1; { normally hear sends if a member }
+ IP_MAX_MEMBERSHIPS = 20; { per socket; must fit in one mbuf }
+
+ SOL_SOCKET = $ffff; {options for socket level }
+{ Option flags per-socket. }
+ SO_DEBUG = $0001; { turn on debugging info recording }
+ SO_ACCEPTCONN = $0002; { socket has had listen() }
+ SO_REUSEADDR = $0004; { allow local address reuse }
+ SO_KEEPALIVE = $0008; { keep connections alive }
+ SO_DONTROUTE = $0010; { just use interface addresses }
+ SO_BROADCAST = $0020; { permit sending of broadcast msgs }
+ SO_USELOOPBACK = $0040; { bypass hardware when possible }
+ SO_LINGER = $0080; { linger on close if data present }
+ SO_OOBINLINE = $0100; { leave received OOB data in line }
+ SO_DONTLINGER = $ff7f;
+{ Additional options. }
+ SO_SNDBUF = $1001; { send buffer size }
+ SO_RCVBUF = $1002; { receive buffer size }
+ SO_SNDLOWAT = $1003; { send low-water mark }
+ SO_RCVLOWAT = $1004; { receive low-water mark }
+ SO_SNDTIMEO = $1005; { send timeout }
+ SO_RCVTIMEO = $1006; { receive timeout }
+ SO_ERROR = $1007; { get error status and clear }
+ SO_TYPE = $1008; { get socket type }
+{ WinSock 2 extension -- new options }
+ SO_GROUP_ID = $2001; { ID of a socket group}
+ SO_GROUP_PRIORITY = $2002; { the relative priority within a group}
+ SO_MAX_MSG_SIZE = $2003; { maximum message size }
+ SO_PROTOCOL_INFOA = $2004; { WSAPROTOCOL_INFOA structure }
+ SO_PROTOCOL_INFOW = $2005; { WSAPROTOCOL_INFOW structure }
+ SO_PROTOCOL_INFO = SO_PROTOCOL_INFOA;
+ PVD_CONFIG = $3001; {configuration info for service provider }
+{ Option for opening sockets for synchronous access. }
+ SO_OPENTYPE = $7008;
+ SO_SYNCHRONOUS_ALERT = $10;
+ SO_SYNCHRONOUS_NONALERT = $20;
+{ Other NT-specific options. }
+ SO_MAXDG = $7009;
+ SO_MAXPATHDG = $700A;
+ SO_UPDATE_ACCEPT_CONTEXT = $700B;
+ SO_CONNECT_TIME = $700C;
+
+ SOMAXCONN = $7fffffff;
+
+ IPV6_UNICAST_HOPS = 8; // ???
+ IPV6_MULTICAST_IF = 9; // set/get IP multicast i/f
+ IPV6_MULTICAST_HOPS = 10; // set/get IP multicast ttl
+ IPV6_MULTICAST_LOOP = 11; // set/get IP multicast loopback
+ IPV6_JOIN_GROUP = 12; // add an IP group membership
+ IPV6_LEAVE_GROUP = 13; // drop an IP group membership
+
+ MSG_NOSIGNAL = 0;
+
+ // getnameinfo constants
+ NI_MAXHOST = 1025;
+ NI_MAXSERV = 32;
+ NI_NOFQDN = $1;
+ NI_NUMERICHOST = $2;
+ NI_NAMEREQD = $4;
+ NI_NUMERICSERV = $8;
+ NI_DGRAM = $10;
+
+
+const
+ SOCK_STREAM = 1; { stream socket }
+ SOCK_DGRAM = 2; { datagram socket }
+ SOCK_RAW = 3; { raw-protocol interface }
+ SOCK_RDM = 4; { reliably-delivered message }
+ SOCK_SEQPACKET = 5; { sequenced packet stream }
+
+{ TCP options. }
+ TCP_NODELAY = $0001;
+
+{ Address families. }
+
+ AF_UNSPEC = 0; { unspecified }
+ AF_INET = 2; { internetwork: UDP, TCP, etc. }
+ AF_INET6 = 23; { Internetwork Version 6 }
+ AF_MAX = 24;
+
+{ Protocol families, same as address families for now. }
+ PF_UNSPEC = AF_UNSPEC;
+ PF_INET = AF_INET;
+ PF_INET6 = AF_INET6;
+ PF_MAX = AF_MAX;
+
+type
+ { Structure used by kernel to store most addresses. }
+ PSockAddr = ^TSockAddr;
+ TSockAddr = TSockAddrIn;
+
+ { Structure used by kernel to pass protocol information in raw sockets. }
+ PSockProto = ^TSockProto;
+ TSockProto = packed record
+ sp_family: u_short;
+ sp_protocol: u_short;
+ end;
+
+type
+ PAddrInfo = ^TAddrInfo;
+ TAddrInfo = record
+ ai_flags: integer; // AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST.
+ ai_family: integer; // PF_xxx.
+ ai_socktype: integer; // SOCK_xxx.
+ ai_protocol: integer; // 0 or IPPROTO_xxx for IPv4 and IPv6.
+ ai_addrlen: u_int; // Length of ai_addr.
+ ai_canonname: PAnsiChar; // Canonical name for nodename.
+ ai_addr: PSockAddr; // Binary address.
+ ai_next: PAddrInfo; // Next structure in linked list.
+ end;
+
+const
+ // Flags used in "hints" argument to getaddrinfo().
+ AI_PASSIVE = $1; // Socket address will be used in bind() call.
+ AI_CANONNAME = $2; // Return canonical name in first ai_canonname.
+ AI_NUMERICHOST = $4; // Nodename must be a numeric address string.
+
+type
+{ Structure used for manipulating linger option. }
+ PLinger = ^TLinger;
+ TLinger = packed record
+ l_onoff: u_short;
+ l_linger: u_short;
+ end;
+
+const
+
+ MSG_OOB = $01; // Process out-of-band data.
+ MSG_PEEK = $02; // Peek at incoming messages.
+
+const
+
+{ All Windows Sockets error constants are biased by WSABASEERR from the "normal" }
+ WSABASEERR = 10000;
+
+{ Windows Sockets definitions of regular Microsoft C error constants }
+
+ WSAEINTR = (WSABASEERR+4);
+ WSAEBADF = (WSABASEERR+9);
+ WSAEACCES = (WSABASEERR+13);
+ WSAEFAULT = (WSABASEERR+14);
+ WSAEINVAL = (WSABASEERR+22);
+ WSAEMFILE = (WSABASEERR+24);
+
+{ Windows Sockets definitions of regular Berkeley error constants }
+
+ WSAEWOULDBLOCK = (WSABASEERR+35);
+ WSAEINPROGRESS = (WSABASEERR+36);
+ WSAEALREADY = (WSABASEERR+37);
+ WSAENOTSOCK = (WSABASEERR+38);
+ WSAEDESTADDRREQ = (WSABASEERR+39);
+ WSAEMSGSIZE = (WSABASEERR+40);
+ WSAEPROTOTYPE = (WSABASEERR+41);
+ WSAENOPROTOOPT = (WSABASEERR+42);
+ WSAEPROTONOSUPPORT = (WSABASEERR+43);
+ WSAESOCKTNOSUPPORT = (WSABASEERR+44);
+ WSAEOPNOTSUPP = (WSABASEERR+45);
+ WSAEPFNOSUPPORT = (WSABASEERR+46);
+ WSAEAFNOSUPPORT = (WSABASEERR+47);
+ WSAEADDRINUSE = (WSABASEERR+48);
+ WSAEADDRNOTAVAIL = (WSABASEERR+49);
+ WSAENETDOWN = (WSABASEERR+50);
+ WSAENETUNREACH = (WSABASEERR+51);
+ WSAENETRESET = (WSABASEERR+52);
+ WSAECONNABORTED = (WSABASEERR+53);
+ WSAECONNRESET = (WSABASEERR+54);
+ WSAENOBUFS = (WSABASEERR+55);
+ WSAEISCONN = (WSABASEERR+56);
+ WSAENOTCONN = (WSABASEERR+57);
+ WSAESHUTDOWN = (WSABASEERR+58);
+ WSAETOOMANYREFS = (WSABASEERR+59);
+ WSAETIMEDOUT = (WSABASEERR+60);
+ WSAECONNREFUSED = (WSABASEERR+61);
+ WSAELOOP = (WSABASEERR+62);
+ WSAENAMETOOLONG = (WSABASEERR+63);
+ WSAEHOSTDOWN = (WSABASEERR+64);
+ WSAEHOSTUNREACH = (WSABASEERR+65);
+ WSAENOTEMPTY = (WSABASEERR+66);
+ WSAEPROCLIM = (WSABASEERR+67);
+ WSAEUSERS = (WSABASEERR+68);
+ WSAEDQUOT = (WSABASEERR+69);
+ WSAESTALE = (WSABASEERR+70);
+ WSAEREMOTE = (WSABASEERR+71);
+
+{ Extended Windows Sockets error constant definitions }
+
+ WSASYSNOTREADY = (WSABASEERR+91);
+ WSAVERNOTSUPPORTED = (WSABASEERR+92);
+ WSANOTINITIALISED = (WSABASEERR+93);
+ WSAEDISCON = (WSABASEERR+101);
+ WSAENOMORE = (WSABASEERR+102);
+ WSAECANCELLED = (WSABASEERR+103);
+ WSAEEINVALIDPROCTABLE = (WSABASEERR+104);
+ WSAEINVALIDPROVIDER = (WSABASEERR+105);
+ WSAEPROVIDERFAILEDINIT = (WSABASEERR+106);
+ WSASYSCALLFAILURE = (WSABASEERR+107);
+ WSASERVICE_NOT_FOUND = (WSABASEERR+108);
+ WSATYPE_NOT_FOUND = (WSABASEERR+109);
+ WSA_E_NO_MORE = (WSABASEERR+110);
+ WSA_E_CANCELLED = (WSABASEERR+111);
+ WSAEREFUSED = (WSABASEERR+112);
+
+{ Error return codes from gethostbyname() and gethostbyaddr()
+ (when using the resolver). Note that these errors are
+ retrieved via WSAGetLastError() and must therefore follow
+ the rules for avoiding clashes with error numbers from
+ specific implementations or language run-time systems.
+ For this reason the codes are based at WSABASEERR+1001.
+ Note also that [WSA]NO_ADDRESS is defined only for
+ compatibility purposes. }
+
+{ Authoritative Answer: Host not found }
+ WSAHOST_NOT_FOUND = (WSABASEERR+1001);
+ HOST_NOT_FOUND = WSAHOST_NOT_FOUND;
+{ Non-Authoritative: Host not found, or SERVERFAIL }
+ WSATRY_AGAIN = (WSABASEERR+1002);
+ TRY_AGAIN = WSATRY_AGAIN;
+{ Non recoverable errors, FORMERR, REFUSED, NOTIMP }
+ WSANO_RECOVERY = (WSABASEERR+1003);
+ NO_RECOVERY = WSANO_RECOVERY;
+{ Valid name, no data record of requested type }
+ WSANO_DATA = (WSABASEERR+1004);
+ NO_DATA = WSANO_DATA;
+{ no address, look for MX record }
+ WSANO_ADDRESS = WSANO_DATA;
+ NO_ADDRESS = WSANO_ADDRESS;
+
+ EWOULDBLOCK = WSAEWOULDBLOCK;
+ EINPROGRESS = WSAEINPROGRESS;
+ EALREADY = WSAEALREADY;
+ ENOTSOCK = WSAENOTSOCK;
+ EDESTADDRREQ = WSAEDESTADDRREQ;
+ EMSGSIZE = WSAEMSGSIZE;
+ EPROTOTYPE = WSAEPROTOTYPE;
+ ENOPROTOOPT = WSAENOPROTOOPT;
+ EPROTONOSUPPORT = WSAEPROTONOSUPPORT;
+ ESOCKTNOSUPPORT = WSAESOCKTNOSUPPORT;
+ EOPNOTSUPP = WSAEOPNOTSUPP;
+ EPFNOSUPPORT = WSAEPFNOSUPPORT;
+ EAFNOSUPPORT = WSAEAFNOSUPPORT;
+ EADDRINUSE = WSAEADDRINUSE;
+ EADDRNOTAVAIL = WSAEADDRNOTAVAIL;
+ ENETDOWN = WSAENETDOWN;
+ ENETUNREACH = WSAENETUNREACH;
+ ENETRESET = WSAENETRESET;
+ ECONNABORTED = WSAECONNABORTED;
+ ECONNRESET = WSAECONNRESET;
+ ENOBUFS = WSAENOBUFS;
+ EISCONN = WSAEISCONN;
+ ENOTCONN = WSAENOTCONN;
+ ESHUTDOWN = WSAESHUTDOWN;
+ ETOOMANYREFS = WSAETOOMANYREFS;
+ ETIMEDOUT = WSAETIMEDOUT;
+ ECONNREFUSED = WSAECONNREFUSED;
+ ELOOP = WSAELOOP;
+ ENAMETOOLONG = WSAENAMETOOLONG;
+ EHOSTDOWN = WSAEHOSTDOWN;
+ EHOSTUNREACH = WSAEHOSTUNREACH;
+ ENOTEMPTY = WSAENOTEMPTY;
+ EPROCLIM = WSAEPROCLIM;
+ EUSERS = WSAEUSERS;
+ EDQUOT = WSAEDQUOT;
+ ESTALE = WSAESTALE;
+ EREMOTE = WSAEREMOTE;
+
+ EAI_ADDRFAMILY = 1; // Address family for nodename not supported.
+ EAI_AGAIN = 2; // Temporary failure in name resolution.
+ EAI_BADFLAGS = 3; // Invalid value for ai_flags.
+ EAI_FAIL = 4; // Non-recoverable failure in name resolution.
+ EAI_FAMILY = 5; // Address family ai_family not supported.
+ EAI_MEMORY = 6; // Memory allocation failure.
+ EAI_NODATA = 7; // No address associated with nodename.
+ EAI_NONAME = 8; // Nodename nor servname provided, or not known.
+ EAI_SERVICE = 9; // Servname not supported for ai_socktype.
+ EAI_SOCKTYPE = 10; // Socket type ai_socktype not supported.
+ EAI_SYSTEM = 11; // System error returned in errno.
+
+const
+ WSADESCRIPTION_LEN = 256;
+ WSASYS_STATUS_LEN = 128;
+type
+ PWSAData = ^TWSAData;
+ TWSAData = packed record
+ wVersion: Word;
+ wHighVersion: Word;
+ szDescription: array[0..WSADESCRIPTION_LEN] of AnsiChar;
+ szSystemStatus: array[0..WSASYS_STATUS_LEN] of AnsiChar;
+ iMaxSockets: Word;
+ iMaxUdpDg: Word;
+ lpVendorInfo: PAnsiChar;
+ end;
+
+ function IN6_IS_ADDR_UNSPECIFIED(const a: PInAddr6): boolean;
+ function IN6_IS_ADDR_LOOPBACK(const a: PInAddr6): boolean;
+ function IN6_IS_ADDR_LINKLOCAL(const a: PInAddr6): boolean;
+ function IN6_IS_ADDR_SITELOCAL(const a: PInAddr6): boolean;
+ function IN6_IS_ADDR_MULTICAST(const a: PInAddr6): boolean;
+ function IN6_ADDR_EQUAL(const a: PInAddr6; const b: PInAddr6):boolean;
+ procedure SET_IN6_IF_ADDR_ANY (const a: PInAddr6);
+ procedure SET_LOOPBACK_ADDR6 (const a: PInAddr6);
+var
+ in6addr_any, in6addr_loopback : TInAddr6;
+
+procedure FD_CLR(Socket: TSocket; var FDSet: TFDSet);
+function FD_ISSET(Socket: TSocket; var FDSet: TFDSet): Boolean;
+procedure FD_SET(Socket: TSocket; var FDSet: TFDSet);
+procedure FD_ZERO(var FDSet: TFDSet);
+
+{=============================================================================}
+
+type
+ TWSAStartup = function(wVersionRequired: Word; var WSData: TWSAData): Integer;
+ stdcall;
+ TWSACleanup = function: Integer;
+ stdcall;
+ TWSAGetLastError = function: Integer;
+ stdcall;
+ TGetServByName = function(name, proto: PAnsiChar): PServEnt;
+ stdcall;
+ TGetServByPort = function(port: Integer; proto: PAnsiChar): PServEnt;
+ stdcall;
+ TGetProtoByName = function(name: PAnsiChar): PProtoEnt;
+ stdcall;
+ TGetProtoByNumber = function(proto: Integer): PProtoEnt;
+ stdcall;
+ TGetHostByName = function(name: PAnsiChar): PHostEnt;
+ stdcall;
+ TGetHostByAddr = function(addr: Pointer; len, Struc: Integer): PHostEnt;
+ stdcall;
+ TGetHostName = function(name: PAnsiChar; len: Integer): Integer;
+ stdcall;
+ TShutdown = function(s: TSocket; how: Integer): Integer;
+ stdcall;
+ TSetSockOpt = function(s: TSocket; level, optname: Integer; optval: PAnsiChar;
+ optlen: Integer): Integer;
+ stdcall;
+ TGetSockOpt = function(s: TSocket; level, optname: Integer; optval: PAnsiChar;
+ var optlen: Integer): Integer;
+ stdcall;
+ TSendTo = function(s: TSocket; const Buf; len, flags: Integer; addrto: PSockAddr;
+ tolen: Integer): Integer;
+ stdcall;
+ TSend = function(s: TSocket; const Buf; len, flags: Integer): Integer;
+ stdcall;
+ TRecv = function(s: TSocket; var Buf; len, flags: Integer): Integer;
+ stdcall;
+ TRecvFrom = function(s: TSocket; var Buf; len, flags: Integer; from: PSockAddr;
+ var fromlen: Integer): Integer;
+ stdcall;
+ Tntohs = function(netshort: u_short): u_short;
+ stdcall;
+ Tntohl = function(netlong: u_long): u_long;
+ stdcall;
+ TListen = function(s: TSocket; backlog: Integer): Integer;
+ stdcall;
+ TIoctlSocket = function(s: TSocket; cmd: DWORD; var arg: Integer): Integer;
+ stdcall;
+ TInet_ntoa = function(inaddr: TInAddr): PAnsiChar;
+ stdcall;
+ TInet_addr = function(cp: PAnsiChar): u_long;
+ stdcall;
+ Thtons = function(hostshort: u_short): u_short;
+ stdcall;
+ Thtonl = function(hostlong: u_long): u_long;
+ stdcall;
+ TGetSockName = function(s: TSocket; name: PSockAddr; var namelen: Integer): Integer;
+ stdcall;
+ TGetPeerName = function(s: TSocket; name: PSockAddr; var namelen: Integer): Integer;
+ stdcall;
+ TConnect = function(s: TSocket; name: PSockAddr; namelen: Integer): Integer;
+ stdcall;
+ TCloseSocket = function(s: TSocket): Integer;
+ stdcall;
+ TBind = function(s: TSocket; addr: PSockAddr; namelen: Integer): Integer;
+ stdcall;
+ TAccept = function(s: TSocket; addr: PSockAddr; var addrlen: Integer): TSocket;
+ stdcall;
+ TTSocket = function(af, Struc, Protocol: Integer): TSocket;
+ stdcall;
+ TSelect = function(nfds: Integer; readfds, writefds, exceptfds: PFDSet;
+ timeout: PTimeVal): Longint;
+ stdcall;
+
+ TGetAddrInfo = function(NodeName: PAnsiChar; ServName: PAnsiChar; Hints: PAddrInfo;
+ var Addrinfo: PAddrInfo): integer;
+ stdcall;
+ TFreeAddrInfo = procedure(ai: PAddrInfo);
+ stdcall;
+ TGetNameInfo = function( addr: PSockAddr; namelen: Integer; host: PAnsiChar;
+ hostlen: DWORD; serv: PAnsiChar; servlen: DWORD; flags: integer): integer;
+ stdcall;
+
+ T__WSAFDIsSet = function (s: TSocket; var FDSet: TFDSet): Bool;
+ stdcall;
+
+ TWSAIoctl = function (s: TSocket; dwIoControlCode: DWORD; lpvInBuffer: Pointer;
+ cbInBuffer: DWORD; lpvOutBuffer: Pointer; cbOutBuffer: DWORD;
+ lpcbBytesReturned: PDWORD; lpOverlapped: Pointer;
+ lpCompletionRoutine: pointer): u_int;
+ stdcall;
+
+var
+ WSAStartup: TWSAStartup = nil;
+ WSACleanup: TWSACleanup = nil;
+ WSAGetLastError: TWSAGetLastError = nil;
+ GetServByName: TGetServByName = nil;
+ GetServByPort: TGetServByPort = nil;
+ GetProtoByName: TGetProtoByName = nil;
+ GetProtoByNumber: TGetProtoByNumber = nil;
+ GetHostByName: TGetHostByName = nil;
+ GetHostByAddr: TGetHostByAddr = nil;
+ ssGetHostName: TGetHostName = nil;
+ Shutdown: TShutdown = nil;
+ SetSockOpt: TSetSockOpt = nil;
+ GetSockOpt: TGetSockOpt = nil;
+ ssSendTo: TSendTo = nil;
+ ssSend: TSend = nil;
+ ssRecv: TRecv = nil;
+ ssRecvFrom: TRecvFrom = nil;
+ ntohs: Tntohs = nil;
+ ntohl: Tntohl = nil;
+ Listen: TListen = nil;
+ IoctlSocket: TIoctlSocket = nil;
+ Inet_ntoa: TInet_ntoa = nil;
+ Inet_addr: TInet_addr = nil;
+ htons: Thtons = nil;
+ htonl: Thtonl = nil;
+ ssGetSockName: TGetSockName = nil;
+ ssGetPeerName: TGetPeerName = nil;
+ ssConnect: TConnect = nil;
+ CloseSocket: TCloseSocket = nil;
+ ssBind: TBind = nil;
+ ssAccept: TAccept = nil;
+ Socket: TTSocket = nil;
+ Select: TSelect = nil;
+
+ GetAddrInfo: TGetAddrInfo = nil;
+ FreeAddrInfo: TFreeAddrInfo = nil;
+ GetNameInfo: TGetNameInfo = nil;
+
+ __WSAFDIsSet: T__WSAFDIsSet = nil;
+
+ WSAIoctl: TWSAIoctl = nil;
+
+var
+ SynSockCS: SyncObjs.TCriticalSection;
+ SockEnhancedApi: Boolean;
+ SockWship6Api: Boolean;
+
+type
+ TVarSin = packed record
+ case integer of
+ 0: (AddressFamily: u_short);
+ 1: (
+ case sin_family: u_short of
+ AF_INET: (sin_port: u_short;
+ sin_addr: TInAddr;
+ sin_zero: array[0..7] of byte);
+ AF_INET6: (sin6_port: u_short;
+ sin6_flowinfo: u_long;
+ sin6_addr: TInAddr6;
+ sin6_scope_id: u_long);
+ );
+ end;
+
+function SizeOfVarSin(sin: TVarSin): integer;
+
+function Bind(s: TSocket; const addr: TVarSin): Integer;
+function Connect(s: TSocket; const name: TVarSin): Integer;
+function GetSockName(s: TSocket; var name: TVarSin): Integer;
+function GetPeerName(s: TSocket; var name: TVarSin): Integer;
+function GetHostName: AnsiString;
+function Send(s: TSocket; Buf: TMemory; len, flags: Integer): Integer;
+function Recv(s: TSocket; Buf: TMemory; len, flags: Integer): Integer;
+function SendTo(s: TSocket; Buf: TMemory; len, flags: Integer; addrto: TVarSin): Integer;
+function RecvFrom(s: TSocket; Buf: TMemory; len, flags: Integer; var from: TVarSin): Integer;
+function Accept(s: TSocket; var addr: TVarSin): TSocket;
+
+function IsNewApi(Family: integer): Boolean;
+function SetVarSin(var Sin: TVarSin; IP, Port: AnsiString; Family, SockProtocol, SockType: integer; PreferIP4: Boolean): integer;
+function GetSinIP(Sin: TVarSin): AnsiString;
+function GetSinPort(Sin: TVarSin): Integer;
+procedure ResolveNameToIP(Name: AnsiString; Family, SockProtocol, SockType: integer; const IPList: TStrings);
+function ResolveIPToName(IP: AnsiString; Family, SockProtocol, SockType: integer): AnsiString;
+function ResolvePort(Port: AnsiString; Family, SockProtocol, SockType: integer): Word;
+
+{==============================================================================}
+implementation
+
+var
+ SynSockCount: Integer = 0;
+ LibHandle: THandle = 0;
+ Libwship6Handle: THandle = 0;
+
+function IN6_IS_ADDR_UNSPECIFIED(const a: PInAddr6): boolean;
+begin
+ Result := ((a^.u6_addr32[0] = 0) and (a^.u6_addr32[1] = 0) and
+ (a^.u6_addr32[2] = 0) and (a^.u6_addr32[3] = 0));
+end;
+
+function IN6_IS_ADDR_LOOPBACK(const a: PInAddr6): boolean;
+begin
+ Result := ((a^.u6_addr32[0] = 0) and (a^.u6_addr32[1] = 0) and
+ (a^.u6_addr32[2] = 0) and
+ (a^.u6_addr8[12] = 0) and (a^.u6_addr8[13] = 0) and
+ (a^.u6_addr8[14] = 0) and (a^.u6_addr8[15] = 1));
+end;
+
+function IN6_IS_ADDR_LINKLOCAL(const a: PInAddr6): boolean;
+begin
+ Result := ((a^.u6_addr8[0] = $FE) and (a^.u6_addr8[1] = $80));
+end;
+
+function IN6_IS_ADDR_SITELOCAL(const a: PInAddr6): boolean;
+begin
+ Result := ((a^.u6_addr8[0] = $FE) and (a^.u6_addr8[1] = $C0));
+end;
+
+function IN6_IS_ADDR_MULTICAST(const a: PInAddr6): boolean;
+begin
+ Result := (a^.u6_addr8[0] = $FF);
+end;
+
+function IN6_ADDR_EQUAL(const a: PInAddr6; const b: PInAddr6): boolean;
+begin
+ Result := (CompareMem( a, b, sizeof(TInAddr6)));
+end;
+
+procedure SET_IN6_IF_ADDR_ANY (const a: PInAddr6);
+begin
+ FillChar(a^, sizeof(TInAddr6), 0);
+end;
+
+procedure SET_LOOPBACK_ADDR6 (const a: PInAddr6);
+begin
+ FillChar(a^, sizeof(TInAddr6), 0);
+ a^.u6_addr8[15] := 1;
+end;
+
+{=============================================================================}
+procedure FD_CLR(Socket: TSocket; var FDSet: TFDSet);
+var
+ I: Integer;
+begin
+ I := 0;
+ while I < FDSet.fd_count do
+ begin
+ if FDSet.fd_array[I] = Socket then
+ begin
+ while I < FDSet.fd_count - 1 do
+ begin
+ FDSet.fd_array[I] := FDSet.fd_array[I + 1];
+ Inc(I);
+ end;
+ Dec(FDSet.fd_count);
+ Break;
+ end;
+ Inc(I);
+ end;
+end;
+
+function FD_ISSET(Socket: TSocket; var FDSet: TFDSet): Boolean;
+begin
+ Result := __WSAFDIsSet(Socket, FDSet);
+end;
+
+procedure FD_SET(Socket: TSocket; var FDSet: TFDSet);
+begin
+ if FDSet.fd_count < FD_SETSIZE then
+ begin
+ FDSet.fd_array[FDSet.fd_count] := Socket;
+ Inc(FDSet.fd_count);
+ end;
+end;
+
+procedure FD_ZERO(var FDSet: TFDSet);
+begin
+ FDSet.fd_count := 0;
+end;
+
+{=============================================================================}
+
+function SizeOfVarSin(sin: TVarSin): integer;
+begin
+ case sin.sin_family of
+ AF_INET:
+ Result := SizeOf(TSockAddrIn);
+ AF_INET6:
+ Result := SizeOf(TSockAddrIn6);
+ else
+ Result := 0;
+ end;
+end;
+
+{=============================================================================}
+
+function Bind(s: TSocket; const addr: TVarSin): Integer;
+begin
+ Result := ssBind(s, @addr, SizeOfVarSin(addr));
+end;
+
+function Connect(s: TSocket; const name: TVarSin): Integer;
+begin
+ Result := ssConnect(s, @name, SizeOfVarSin(name));
+end;
+
+function GetSockName(s: TSocket; var name: TVarSin): Integer;
+var
+ len: integer;
+begin
+ len := SizeOf(name);
+ FillChar(name, len, 0);
+ Result := ssGetSockName(s, @name, Len);
+end;
+
+function GetPeerName(s: TSocket; var name: TVarSin): Integer;
+var
+ len: integer;
+begin
+ len := SizeOf(name);
+ FillChar(name, len, 0);
+ Result := ssGetPeerName(s, @name, Len);
+end;
+
+function GetHostName: AnsiString;
+var
+ s: AnsiString;
+begin
+ Result := '';
+ setlength(s, 255);
+ ssGetHostName(pAnsichar(s), Length(s) - 1);
+ Result := PAnsichar(s);
+end;
+
+function Send(s: TSocket; Buf: TMemory; len, flags: Integer): Integer;
+begin
+ Result := ssSend(s, Buf^, len, flags);
+end;
+
+function Recv(s: TSocket; Buf: TMemory; len, flags: Integer): Integer;
+begin
+ Result := ssRecv(s, Buf^, len, flags);
+end;
+
+function SendTo(s: TSocket; Buf: TMemory; len, flags: Integer; addrto: TVarSin): Integer;
+begin
+ Result := ssSendTo(s, Buf^, len, flags, @addrto, SizeOfVarSin(addrto));
+end;
+
+function RecvFrom(s: TSocket; Buf: TMemory; len, flags: Integer; var from: TVarSin): Integer;
+var
+ x: integer;
+begin
+ x := SizeOf(from);
+ Result := ssRecvFrom(s, Buf^, len, flags, @from, x);
+end;
+
+function Accept(s: TSocket; var addr: TVarSin): TSocket;
+var
+ x: integer;
+begin
+ x := SizeOf(addr);
+ Result := ssAccept(s, @addr, x);
+end;
+
+{=============================================================================}
+function IsNewApi(Family: integer): Boolean;
+begin
+ Result := SockEnhancedApi;
+ if not Result then
+ Result := (Family = AF_INET6) and SockWship6Api;
+end;
+
+function SetVarSin(var Sin: TVarSin; IP, Port: AnsiString; Family, SockProtocol, SockType: integer; PreferIP4: Boolean): integer;
+type
+ pu_long = ^u_long;
+var
+ ProtoEnt: PProtoEnt;
+ ServEnt: PServEnt;
+ HostEnt: PHostEnt;
+ r: integer;
+ Hints1, Hints2: TAddrInfo;
+ Sin1, Sin2: TVarSin;
+ TwoPass: boolean;
+
+ function GetAddr(const IP, port: AnsiString; Hints: TAddrInfo; var Sin: TVarSin): integer;
+ var
+ Addr: PAddrInfo;
+ begin
+ Addr := nil;
+ try
+ FillChar(Sin, Sizeof(Sin), 0);
+ if Hints.ai_socktype = SOCK_RAW then
+ begin
+ Hints.ai_socktype := 0;
+ Hints.ai_protocol := 0;
+ Result := synsock.GetAddrInfo(PAnsiChar(IP), nil, @Hints, Addr);
+ end
+ else
+ begin
+ if (IP = cAnyHost) or (IP = c6AnyHost) then
+ begin
+ Hints.ai_flags := AI_PASSIVE;
+ Result := synsock.GetAddrInfo(nil, PAnsiChar(Port), @Hints, Addr);
+ end
+ else
+ if (IP = cLocalhost) or (IP = c6Localhost) then
+ begin
+ Result := synsock.GetAddrInfo(nil, PAnsiChar(Port), @Hints, Addr);
+ end
+ else
+ begin
+ Result := synsock.GetAddrInfo(PAnsiChar(IP), PAnsiChar(Port), @Hints, Addr);
+ end;
+ end;
+ if Result = 0 then
+ if (Addr <> nil) then
+ Move(Addr^.ai_addr^, Sin, Addr^.ai_addrlen);
+ finally
+ if Assigned(Addr) then
+ synsock.FreeAddrInfo(Addr);
+ end;
+ end;
+
+begin
+ Result := 0;
+ FillChar(Sin, Sizeof(Sin), 0);
+ if not IsNewApi(family) then
+ begin
+ SynSockCS.Enter;
+ try
+ Sin.sin_family := AF_INET;
+ ProtoEnt := synsock.GetProtoByNumber(SockProtocol);
+ ServEnt := nil;
+ if ProtoEnt <> nil then
+ ServEnt := synsock.GetServByName(PAnsiChar(Port), ProtoEnt^.p_name);
+ if ServEnt = nil then
+ Sin.sin_port := synsock.htons(StrToIntDef(Port, 0))
+ else
+ Sin.sin_port := ServEnt^.s_port;
+ if IP = cBroadcast then
+ Sin.sin_addr.s_addr := u_long(INADDR_BROADCAST)
+ else
+ begin
+ Sin.sin_addr.s_addr := synsock.inet_addr(PAnsiChar(IP));
+ if Sin.sin_addr.s_addr = u_long(INADDR_NONE) then
+ begin
+ HostEnt := synsock.GetHostByName(PAnsiChar(IP));
+ Result := synsock.WSAGetLastError;
+ if HostEnt <> nil then
+ Sin.sin_addr.S_addr := u_long(Pu_long(HostEnt^.h_addr_list^)^);
+ end;
+ end;
+ finally
+ SynSockCS.Leave;
+ end;
+ end
+ else
+ begin
+ FillChar(Hints1, Sizeof(Hints1), 0);
+ FillChar(Hints2, Sizeof(Hints2), 0);
+ TwoPass := False;
+ if Family = AF_UNSPEC then
+ begin
+ if PreferIP4 then
+ begin
+ Hints1.ai_family := AF_INET;
+ Hints2.ai_family := AF_INET6;
+ TwoPass := True;
+ end
+ else
+ begin
+ Hints2.ai_family := AF_INET;
+ Hints1.ai_family := AF_INET6;
+ TwoPass := True;
+ end;
+ end
+ else
+ Hints1.ai_family := Family;
+
+ Hints1.ai_socktype := SockType;
+ Hints1.ai_protocol := SockProtocol;
+ Hints2.ai_socktype := Hints1.ai_socktype;
+ Hints2.ai_protocol := Hints1.ai_protocol;
+
+ r := GetAddr(IP, Port, Hints1, Sin1);
+ Result := r;
+ sin := sin1;
+ if r <> 0 then
+ if TwoPass then
+ begin
+ r := GetAddr(IP, Port, Hints2, Sin2);
+ Result := r;
+ if r = 0 then
+ sin := sin2;
+ end;
+ end;
+end;
+
+function GetSinIP(Sin: TVarSin): AnsiString;
+var
+ p: PAnsiChar;
+ host, serv: AnsiString;
+ hostlen, servlen: integer;
+ r: integer;
+begin
+ Result := '';
+ if not IsNewApi(Sin.AddressFamily) then
+ begin
+ p := synsock.inet_ntoa(Sin.sin_addr);
+ if p <> nil then
+ Result := p;
+ end
+ else
+ begin
+ hostlen := NI_MAXHOST;
+ servlen := NI_MAXSERV;
+ setlength(host, hostlen);
+ setlength(serv, servlen);
+ r := getnameinfo(@sin, SizeOfVarSin(sin), PAnsiChar(host), hostlen,
+ PAnsiChar(serv), servlen, NI_NUMERICHOST + NI_NUMERICSERV);
+ if r = 0 then
+ Result := PAnsiChar(host);
+ end;
+end;
+
+function GetSinPort(Sin: TVarSin): Integer;
+begin
+ if (Sin.sin_family = AF_INET6) then
+ Result := synsock.ntohs(Sin.sin6_port)
+ else
+ Result := synsock.ntohs(Sin.sin_port);
+end;
+
+procedure ResolveNameToIP(Name: AnsiString; Family, SockProtocol, SockType: integer; const IPList: TStrings);
+type
+ TaPInAddr = array[0..250] of PInAddr;
+ PaPInAddr = ^TaPInAddr;
+var
+ Hints: TAddrInfo;
+ Addr: PAddrInfo;
+ AddrNext: PAddrInfo;
+ r: integer;
+ host, serv: AnsiString;
+ hostlen, servlen: integer;
+ RemoteHost: PHostEnt;
+ IP: u_long;
+ PAdrPtr: PaPInAddr;
+ i: Integer;
+ s: AnsiString;
+ InAddr: TInAddr;
+begin
+ IPList.Clear;
+ if not IsNewApi(Family) then
+ begin
+ IP := synsock.inet_addr(PAnsiChar(Name));
+ if IP = u_long(INADDR_NONE) then
+ begin
+ SynSockCS.Enter;
+ try
+ RemoteHost := synsock.GetHostByName(PAnsiChar(Name));
+ if RemoteHost <> nil then
+ begin
+ PAdrPtr := PAPInAddr(RemoteHost^.h_addr_list);
+ i := 0;
+ while PAdrPtr^[i] <> nil do
+ begin
+ InAddr := PAdrPtr^[i]^;
+ s := Format('%d.%d.%d.%d', [InAddr.S_bytes[0], InAddr.S_bytes[1],
+ InAddr.S_bytes[2], InAddr.S_bytes[3]]);
+ IPList.Add(s);
+ Inc(i);
+ end;
+ end;
+ finally
+ SynSockCS.Leave;
+ end;
+ end
+ else
+ IPList.Add(Name);
+ end
+ else
+ begin
+ Addr := nil;
+ try
+ FillChar(Hints, Sizeof(Hints), 0);
+ Hints.ai_family := AF_UNSPEC;
+ Hints.ai_socktype := SockType;
+ Hints.ai_protocol := SockProtocol;
+ Hints.ai_flags := 0;
+ r := synsock.GetAddrInfo(PAnsiChar(Name), nil, @Hints, Addr);
+ if r = 0 then
+ begin
+ AddrNext := Addr;
+ while not(AddrNext = nil) do
+ begin
+ if not(((Family = AF_INET6) and (AddrNext^.ai_family = AF_INET))
+ or ((Family = AF_INET) and (AddrNext^.ai_family = AF_INET6))) then
+ begin
+ hostlen := NI_MAXHOST;
+ servlen := NI_MAXSERV;
+ setlength(host, hostlen);
+ setlength(serv, servlen);
+ r := getnameinfo(AddrNext^.ai_addr, AddrNext^.ai_addrlen,
+ PAnsiChar(host), hostlen, PAnsiChar(serv), servlen,
+ NI_NUMERICHOST + NI_NUMERICSERV);
+ if r = 0 then
+ begin
+ host := PAnsiChar(host);
+ IPList.Add(host);
+ end;
+ end;
+ AddrNext := AddrNext^.ai_next;
+ end;
+ end;
+ finally
+ if Assigned(Addr) then
+ synsock.FreeAddrInfo(Addr);
+ end;
+ end;
+ if IPList.Count = 0 then
+ IPList.Add(cAnyHost);
+end;
+
+function ResolvePort(Port: AnsiString; Family, SockProtocol, SockType: integer): Word;
+var
+ ProtoEnt: PProtoEnt;
+ ServEnt: PServEnt;
+ Hints: TAddrInfo;
+ Addr: PAddrInfo;
+ r: integer;
+begin
+ Result := 0;
+ if not IsNewApi(Family) then
+ begin
+ SynSockCS.Enter;
+ try
+ ProtoEnt := synsock.GetProtoByNumber(SockProtocol);
+ ServEnt := nil;
+ if ProtoEnt <> nil then
+ ServEnt := synsock.GetServByName(PAnsiChar(Port), ProtoEnt^.p_name);
+ if ServEnt = nil then
+ Result := StrToIntDef(Port, 0)
+ else
+ Result := synsock.htons(ServEnt^.s_port);
+ finally
+ SynSockCS.Leave;
+ end;
+ end
+ else
+ begin
+ Addr := nil;
+ try
+ FillChar(Hints, Sizeof(Hints), 0);
+ Hints.ai_family := AF_UNSPEC;
+ Hints.ai_socktype := SockType;
+ Hints.ai_protocol := Sockprotocol;
+ Hints.ai_flags := AI_PASSIVE;
+ r := synsock.GetAddrInfo(nil, PAnsiChar(Port), @Hints, Addr);
+ if (r = 0) and Assigned(Addr) then
+ begin
+ if Addr^.ai_family = AF_INET then
+ Result := synsock.htons(Addr^.ai_addr^.sin_port);
+ if Addr^.ai_family = AF_INET6 then
+ Result := synsock.htons(PSockAddrIn6(Addr^.ai_addr)^.sin6_port);
+ end;
+ finally
+ if Assigned(Addr) then
+ synsock.FreeAddrInfo(Addr);
+ end;
+ end;
+end;
+
+function ResolveIPToName(IP: AnsiString; Family, SockProtocol, SockType: integer): AnsiString;
+var
+ Hints: TAddrInfo;
+ Addr: PAddrInfo;
+ r: integer;
+ host, serv: AnsiString;
+ hostlen, servlen: integer;
+ RemoteHost: PHostEnt;
+ IPn: u_long;
+begin
+ Result := IP;
+ if not IsNewApi(Family) then
+ begin
+ IPn := synsock.inet_addr(PAnsiChar(IP));
+ if IPn <> u_long(INADDR_NONE) then
+ begin
+ SynSockCS.Enter;
+ try
+ RemoteHost := GetHostByAddr(@IPn, SizeOf(IPn), AF_INET);
+ if RemoteHost <> nil then
+ Result := RemoteHost^.h_name;
+ finally
+ SynSockCS.Leave;
+ end;
+ end;
+ end
+ else
+ begin
+ Addr := nil;
+ try
+ FillChar(Hints, Sizeof(Hints), 0);
+ Hints.ai_family := AF_UNSPEC;
+ Hints.ai_socktype := SockType;
+ Hints.ai_protocol := SockProtocol;
+ Hints.ai_flags := 0;
+ r := synsock.GetAddrInfo(PAnsiChar(IP), nil, @Hints, Addr);
+ if (r = 0) and Assigned(Addr)then
+ begin
+ hostlen := NI_MAXHOST;
+ servlen := NI_MAXSERV;
+ setlength(host, hostlen);
+ setlength(serv, servlen);
+ r := getnameinfo(Addr^.ai_addr, Addr^.ai_addrlen,
+ PAnsiChar(host), hostlen, PAnsiChar(serv), servlen,
+ NI_NUMERICSERV);
+ if r = 0 then
+ Result := PAnsiChar(host);
+ end;
+ finally
+ if Assigned(Addr) then
+ synsock.FreeAddrInfo(Addr);
+ end;
+ end;
+end;
+
+{=============================================================================}
+
+function InitSocketInterface(stack: String): Boolean;
+begin
+ Result := False;
+ SockEnhancedApi := False;
+ if stack = '' then
+ stack := DLLStackName;
+ SynSockCS.Enter;
+ try
+ if SynSockCount = 0 then
+ begin
+ SockEnhancedApi := False;
+ SockWship6Api := False;
+ LibHandle := LoadLibrary(PChar(Stack));
+ if LibHandle <> 0 then
+ begin
+ WSAIoctl := GetProcAddress(LibHandle, PAnsiChar(AnsiString('WSAIoctl')));
+ __WSAFDIsSet := GetProcAddress(LibHandle, PAnsiChar(AnsiString('__WSAFDIsSet')));
+ CloseSocket := GetProcAddress(LibHandle, PAnsiChar(AnsiString('closesocket')));
+ IoctlSocket := GetProcAddress(LibHandle, PAnsiChar(AnsiString('ioctlsocket')));
+ WSAGetLastError := GetProcAddress(LibHandle, PAnsiChar(AnsiString('WSAGetLastError')));
+ WSAStartup := GetProcAddress(LibHandle, PAnsiChar(AnsiString('WSAStartup')));
+ WSACleanup := GetProcAddress(LibHandle, PAnsiChar(AnsiString('WSACleanup')));
+ ssAccept := GetProcAddress(LibHandle, PAnsiChar(AnsiString('accept')));
+ ssBind := GetProcAddress(LibHandle, PAnsiChar(AnsiString('bind')));
+ ssConnect := GetProcAddress(LibHandle, PAnsiChar(AnsiString('connect')));
+ ssGetPeerName := GetProcAddress(LibHandle, PAnsiChar(AnsiString('getpeername')));
+ ssGetSockName := GetProcAddress(LibHandle, PAnsiChar(AnsiString('getsockname')));
+ GetSockOpt := GetProcAddress(LibHandle, PAnsiChar(AnsiString('getsockopt')));
+ Htonl := GetProcAddress(LibHandle, PAnsiChar(AnsiString('htonl')));
+ Htons := GetProcAddress(LibHandle, PAnsiChar(AnsiString('htons')));
+ Inet_Addr := GetProcAddress(LibHandle, PAnsiChar(AnsiString('inet_addr')));
+ Inet_Ntoa := GetProcAddress(LibHandle, PAnsiChar(AnsiString('inet_ntoa')));
+ Listen := GetProcAddress(LibHandle, PAnsiChar(AnsiString('listen')));
+ Ntohl := GetProcAddress(LibHandle, PAnsiChar(AnsiString('ntohl')));
+ Ntohs := GetProcAddress(LibHandle, PAnsiChar(AnsiString('ntohs')));
+ ssRecv := GetProcAddress(LibHandle, PAnsiChar(AnsiString('recv')));
+ ssRecvFrom := GetProcAddress(LibHandle, PAnsiChar(AnsiString('recvfrom')));
+ Select := GetProcAddress(LibHandle, PAnsiChar(AnsiString('select')));
+ ssSend := GetProcAddress(LibHandle, PAnsiChar(AnsiString('send')));
+ ssSendTo := GetProcAddress(LibHandle, PAnsiChar(AnsiString('sendto')));
+ SetSockOpt := GetProcAddress(LibHandle, PAnsiChar(AnsiString('setsockopt')));
+ ShutDown := GetProcAddress(LibHandle, PAnsiChar(AnsiString('shutdown')));
+ Socket := GetProcAddress(LibHandle, PAnsiChar(AnsiString('socket')));
+ GetHostByAddr := GetProcAddress(LibHandle, PAnsiChar(AnsiString('gethostbyaddr')));
+ GetHostByName := GetProcAddress(LibHandle, PAnsiChar(AnsiString('gethostbyname')));
+ GetProtoByName := GetProcAddress(LibHandle, PAnsiChar(AnsiString('getprotobyname')));
+ GetProtoByNumber := GetProcAddress(LibHandle, PAnsiChar(AnsiString('getprotobynumber')));
+ GetServByName := GetProcAddress(LibHandle, PAnsiChar(AnsiString('getservbyname')));
+ GetServByPort := GetProcAddress(LibHandle, PAnsiChar(AnsiString('getservbyport')));
+ ssGetHostName := GetProcAddress(LibHandle, PAnsiChar(AnsiString('gethostname')));
+
+{$IFNDEF FORCEOLDAPI}
+ GetAddrInfo := GetProcAddress(LibHandle, PAnsiChar(AnsiString('getaddrinfo')));
+ FreeAddrInfo := GetProcAddress(LibHandle, PAnsiChar(AnsiString('freeaddrinfo')));
+ GetNameInfo := GetProcAddress(LibHandle, PAnsiChar(AnsiString('getnameinfo')));
+ SockEnhancedApi := Assigned(GetAddrInfo) and Assigned(FreeAddrInfo)
+ and Assigned(GetNameInfo);
+ if not SockEnhancedApi then
+ begin
+ LibWship6Handle := LoadLibrary(PChar(DLLWship6));
+ if LibWship6Handle <> 0 then
+ begin
+ GetAddrInfo := GetProcAddress(LibWship6Handle, PAnsiChar(AnsiString('getaddrinfo')));
+ FreeAddrInfo := GetProcAddress(LibWship6Handle, PAnsiChar(AnsiString('freeaddrinfo')));
+ GetNameInfo := GetProcAddress(LibWship6Handle, PAnsiChar(AnsiString('getnameinfo')));
+ SockWship6Api := Assigned(GetAddrInfo) and Assigned(FreeAddrInfo)
+ and Assigned(GetNameInfo);
+ end;
+ end;
+{$ENDIF}
+ Result := True;
+ end;
+ end
+ else Result := True;
+ if Result then
+ Inc(SynSockCount);
+ finally
+ SynSockCS.Leave;
+ end;
+end;
+
+function DestroySocketInterface: Boolean;
+begin
+ SynSockCS.Enter;
+ try
+ Dec(SynSockCount);
+ if SynSockCount < 0 then
+ SynSockCount := 0;
+ if SynSockCount = 0 then
+ begin
+ if LibHandle <> 0 then
+ begin
+ FreeLibrary(libHandle);
+ LibHandle := 0;
+ end;
+ if LibWship6Handle <> 0 then
+ begin
+ FreeLibrary(LibWship6Handle);
+ LibWship6Handle := 0;
+ end;
+ end;
+ finally
+ SynSockCS.Leave;
+ end;
+ Result := True;
+end;
+
+initialization
+begin
+ SynSockCS := SyncObjs.TCriticalSection.Create;
+ SET_IN6_IF_ADDR_ANY (@in6addr_any);
+ SET_LOOPBACK_ADDR6 (@in6addr_loopback);
+end;
+
+finalization
+begin
+ SynSockCS.Free;
+end;
+
+{$ENDIF}
\ No newline at end of file
diff --git a/branches/script-component/Units/Synapse/synachar.pas b/branches/script-component/Units/Synapse/synachar.pas
new file mode 100644
index 0000000..da7c7f7
--- /dev/null
+++ b/branches/script-component/Units/Synapse/synachar.pas
@@ -0,0 +1,2030 @@
+{==============================================================================|
+| Project : Ararat Synapse | 005.002.002 |
+|==============================================================================|
+| Content: Charset conversion support |
+|==============================================================================|
+| Copyright (c)1999-2004, Lukas Gebauer |
+| All rights reserved. |
+| |
+| Redistribution and use in source and binary forms, with or without |
+| modification, are permitted provided that the following conditions are met: |
+| |
+| Redistributions of source code must retain the above copyright notice, this |
+| list of conditions and the following disclaimer. |
+| |
+| Redistributions in binary form must reproduce the above copyright notice, |
+| this list of conditions and the following disclaimer in the documentation |
+| and/or other materials provided with the distribution. |
+| |
+| Neither the name of Lukas Gebauer nor the names of its contributors may |
+| be used to endorse or promote products derived from this software without |
+| specific prior written permission. |
+| |
+| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
+| AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
+| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
+| ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR |
+| ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
+| DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
+| SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
+| CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
+| LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
+| OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
+| DAMAGE. |
+|==============================================================================|
+| The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).|
+| Portions created by Lukas Gebauer are Copyright (c)2000-2004. |
+| All Rights Reserved. |
+|==============================================================================|
+| Contributor(s): |
+|==============================================================================|
+| History: see HISTORY.HTM from distribution package |
+| (Found at URL: http://www.ararat.cz/synapse/) |
+|==============================================================================}
+
+{: @abstract(Charset conversion support)
+This unit contains a routines for lot of charset conversions.
+
+It using built-in conversion tables or external Iconv library. Iconv is used
+ when needed conversion is known by Iconv library. When Iconv library is not
+ found or Iconv not know requested conversion, then are internal routines used
+ for conversion. (You can disable Iconv support from your program too!)
+
+Internal routines knows all major charsets for Europe or America. For East-Asian
+ charsets you must use Iconv library!
+}
+
+{$IFDEF FPC}
+ {$MODE DELPHI}
+{$ENDIF}
+{$Q-}
+{$H+}
+
+unit synachar;
+
+interface
+
+uses
+{$IFNDEF WIN32}
+ {$IFNDEF FPC}
+ Libc,
+ {$ELSE}
+ {$IFDEF FPC_USE_LIBC}
+ Libc,
+ {$ENDIF}
+ {$ENDIF}
+{$ELSE}
+ Windows,
+{$ENDIF}
+ SysUtils,
+ synautil, synacode, synaicnv;
+
+type
+ {:Type with all supported charsets.}
+ TMimeChar = (ISO_8859_1, ISO_8859_2, ISO_8859_3, ISO_8859_4, ISO_8859_5,
+ ISO_8859_6, ISO_8859_7, ISO_8859_8, ISO_8859_9, ISO_8859_10, ISO_8859_13,
+ ISO_8859_14, ISO_8859_15, CP1250, CP1251, CP1252, CP1253, CP1254, CP1255,
+ CP1256, CP1257, CP1258, KOI8_R, CP895, CP852, UCS_2, UCS_4, UTF_8, UTF_7,
+ UTF_7mod, UCS_2LE, UCS_4LE,
+ //next is supported by Iconv only...
+ UTF_16, UTF_16LE, UTF_32, UTF_32LE, C99, JAVA, ISO_8859_16, KOI8_U, KOI8_RU,
+ CP862, CP866, MAC, MACCE, MACICE, MACCRO, MACRO, MACCYR, MACUK, MACGR, MACTU,
+ MACHEB, MACAR, MACTH, ROMAN8, NEXTSTEP, ARMASCII, GEORGIAN_AC, GEORGIAN_PS,
+ KOI8_T, MULELAO, CP1133, TIS620, CP874, VISCII, TCVN, ISO_IR_14, JIS_X0201,
+ JIS_X0208, JIS_X0212, GB1988_80, GB2312_80, ISO_IR_165, ISO_IR_149, EUC_JP,
+ SHIFT_JIS, CP932, ISO_2022_JP, ISO_2022_JP1, ISO_2022_JP2, GB2312, CP936,
+ GB18030, ISO_2022_CN, ISO_2022_CNE, HZ, EUC_TW, BIG5, CP950, BIG5_HKSCS,
+ EUC_KR, CP949, CP1361, ISO_2022_KR, CP737, CP775, CP853, CP855, CP857,
+ CP858, CP860, CP861, CP863, CP864, CP865, CP869, CP1125);
+
+ {:Set of any charsets.}
+ TMimeSetChar = set of TMimeChar;
+
+const
+ {:Set of charsets supported by Iconv library only.}
+ IconvOnlyChars: set of TMimeChar = [UTF_16, UTF_16LE, UTF_32, UTF_32LE,
+ C99, JAVA, ISO_8859_16, KOI8_U, KOI8_RU, CP862, CP866, MAC, MACCE, MACICE,
+ MACCRO, MACRO, MACCYR, MACUK, MACGR, MACTU, MACHEB, MACAR, MACTH, ROMAN8,
+ NEXTSTEP, ARMASCII, GEORGIAN_AC, GEORGIAN_PS, KOI8_T, MULELAO, CP1133,
+ TIS620, CP874, VISCII, TCVN, ISO_IR_14, JIS_X0201, JIS_X0208, JIS_X0212,
+ GB1988_80, GB2312_80, ISO_IR_165, ISO_IR_149, EUC_JP, SHIFT_JIS, CP932,
+ ISO_2022_JP, ISO_2022_JP1, ISO_2022_JP2, GB2312, CP936, GB18030,
+ ISO_2022_CN, ISO_2022_CNE, HZ, EUC_TW, BIG5, CP950, BIG5_HKSCS, EUC_KR,
+ CP949, CP1361, ISO_2022_KR, CP737, CP775, CP853, CP855, CP857, CP858,
+ CP860, CP861, CP863, CP864, CP865, CP869, CP1125];
+
+ {:Set of charsets supported by internal routines only.}
+ NoIconvChars: set of TMimeChar = [CP895, UTF_7mod];
+
+ {:null character replace table. (Usable for disable charater replacing.)}
+ Replace_None: array[0..0] of Word =
+ (0);
+
+ {:Character replace table for remove Czech diakritics.}
+ Replace_Czech: array[0..59] of Word =
+ (
+ $00E1, $0061,
+ $010D, $0063,
+ $010F, $0064,
+ $010E, $0044,
+ $00E9, $0065,
+ $011B, $0065,
+ $00ED, $0069,
+ $0148, $006E,
+ $00F3, $006F,
+ $0159, $0072,
+ $0161, $0073,
+ $0165, $0074,
+ $00FA, $0075,
+ $016F, $0075,
+ $00FD, $0079,
+ $017E, $007A,
+ $00C1, $0041,
+ $010C, $0043,
+ $00C9, $0045,
+ $011A, $0045,
+ $00CD, $0049,
+ $0147, $004E,
+ $00D3, $004F,
+ $0158, $0052,
+ $0160, $0053,
+ $0164, $0054,
+ $00DA, $0055,
+ $016E, $0055,
+ $00DD, $0059,
+ $017D, $005A
+ );
+
+var
+ {:By this you can generally disable/enable Iconv support.}
+ DisableIconv: Boolean = False;
+
+ {:Default set of charsets for @link(IdealCharsetCoding) function.}
+ IdealCharsets: TMimeSetChar =
+ [ISO_8859_1, ISO_8859_2, ISO_8859_3, ISO_8859_4, ISO_8859_5,
+ ISO_8859_6, ISO_8859_7, ISO_8859_8, ISO_8859_9, ISO_8859_10,
+ KOI8_R, KOI8_U
+ {$IFNDEF CIL} //error URW778 ??? :-O
+ , GB2312, EUC_KR, ISO_2022_JP, EUC_TW
+ {$ENDIF}
+ ];
+
+{==============================================================================}
+{:Convert Value from one charset to another. See: @link(CharsetConversionEx)}
+function CharsetConversion(const Value: AnsiString; CharFrom: TMimeChar;
+ CharTo: TMimeChar): AnsiString;
+
+{:Convert Value from one charset to another with additional character conversion.
+see: @link(Replace_None) and @link(Replace_Czech)}
+function CharsetConversionEx(const Value: AnsiString; CharFrom: TMimeChar;
+ CharTo: TMimeChar; const TransformTable: array of Word): AnsiString;
+
+{:Convert Value from one charset to another with additional character conversion.
+ This funtion is similar to @link(CharsetConversionEx), but you can disable
+ transliteration of unconvertible characters.}
+function CharsetConversionTrans(Value: AnsiString; CharFrom: TMimeChar;
+ CharTo: TMimeChar; const TransformTable: array of Word; Translit: Boolean): AnsiString;
+
+{:Returns charset used by operating system.}
+function GetCurCP: TMimeChar;
+
+{:Returns charset used by operating system as OEM charset. (in Windows DOS box,
+ for example)}
+function GetCurOEMCP: TMimeChar;
+
+{:Converting string with charset name to TMimeChar.}
+function GetCPFromID(Value: AnsiString): TMimeChar;
+
+{:Converting TMimeChar to string with name of charset.}
+function GetIDFromCP(Value: TMimeChar): AnsiString;
+
+{:return @true when value need to be converted. (It is not 7-bit ASCII)}
+function NeedCharsetConversion(const Value: AnsiString): Boolean;
+
+{:Finding best target charset from set of TMimeChars with minimal count of
+ unconvertible characters.}
+function IdealCharsetCoding(const Value: AnsiString; CharFrom: TMimeChar;
+ CharTo: TMimeSetChar): TMimeChar;
+
+{:Return BOM (Byte Order Mark) for given unicode charset.}
+function GetBOM(Value: TMimeChar): AnsiString;
+
+{:Convert binary string with unicode content to WideString.}
+function StringToWide(const Value: AnsiString): WideString;
+
+{:Convert WideString to binary string with unicode content.}
+function WideToString(const Value: WideString): AnsiString;
+
+{==============================================================================}
+implementation
+
+//character transcoding tables X to UCS-2
+{
+//dummy table
+$0080, $0081, $0082, $0083, $0084, $0085, $0086, $0087,
+$0088, $0089, $008A, $008B, $008C, $008D, $008E, $008F,
+$0090, $0091, $0092, $0093, $0094, $0095, $0096, $0097,
+$0098, $0099, $009A, $009B, $009C, $009D, $009E, $009F,
+$00A0, $00A1, $00A2, $00A3, $00A4, $00A5, $00A6, $00A7,
+$00A8, $00A9, $00AA, $00AB, $00AC, $00AD, $00AE, $00AF,
+$00B0, $00B1, $00B2, $00B3, $00B4, $00B5, $00B6, $00B7,
+$00B8, $00B9, $00BA, $00BB, $00BC, $00BD, $00BE, $00BF,
+$00C0, $00C1, $00C2, $00C3, $00C4, $00C5, $00C6, $00C7,
+$00C8, $00C9, $00CA, $00CB, $00CC, $00CD, $00CE, $00CF,
+$00D0, $00D1, $00D2, $00D3, $00D4, $00D5, $00D6, $00D7,
+$00D8, $00D9, $00DA, $00DB, $00DC, $00DD, $00DE, $00DF,
+$00E0, $00E1, $00E2, $00E3, $00E4, $00E5, $00E6, $00E7,
+$00E8, $00E9, $00EA, $00EB, $00EC, $00ED, $00EE, $00EF,
+$00F0, $00F1, $00F2, $00F3, $00F4, $00F5, $00F6, $00F7,
+$00F8, $00F9, $00FA, $00FB, $00FC, $00FD, $00FE, $00FF
+}
+
+const
+
+{Latin-1
+ Danish, Dutch, English, Faeroese, Finnish, French, German, Icelandic,
+ Irish, Italian, Norwegian, Portuguese, Spanish and Swedish.
+}
+ CharISO_8859_1: array[128..255] of Word =
+ (
+ $0080, $0081, $0082, $0083, $0084, $0085, $0086, $0087,
+ $0088, $0089, $008A, $008B, $008C, $008D, $008E, $008F,
+ $0090, $0091, $0092, $0093, $0094, $0095, $0096, $0097,
+ $0098, $0099, $009A, $009B, $009C, $009D, $009E, $009F,
+ $00A0, $00A1, $00A2, $00A3, $00A4, $00A5, $00A6, $00A7,
+ $00A8, $00A9, $00AA, $00AB, $00AC, $00AD, $00AE, $00AF,
+ $00B0, $00B1, $00B2, $00B3, $00B4, $00B5, $00B6, $00B7,
+ $00B8, $00B9, $00BA, $00BB, $00BC, $00BD, $00BE, $00BF,
+ $00C0, $00C1, $00C2, $00C3, $00C4, $00C5, $00C6, $00C7,
+ $00C8, $00C9, $00CA, $00CB, $00CC, $00CD, $00CE, $00CF,
+ $00D0, $00D1, $00D2, $00D3, $00D4, $00D5, $00D6, $00D7,
+ $00D8, $00D9, $00DA, $00DB, $00DC, $00DD, $00DE, $00DF,
+ $00E0, $00E1, $00E2, $00E3, $00E4, $00E5, $00E6, $00E7,
+ $00E8, $00E9, $00EA, $00EB, $00EC, $00ED, $00EE, $00EF,
+ $00F0, $00F1, $00F2, $00F3, $00F4, $00F5, $00F6, $00F7,
+ $00F8, $00F9, $00FA, $00FB, $00FC, $00FD, $00FE, $00FF
+ );
+
+{Latin-2
+ Albanian, Czech, English, German, Hungarian, Polish, Rumanian,
+ Serbo-Croatian, Slovak, Slovene and Swedish.
+}
+ CharISO_8859_2: array[128..255] of Word =
+ (
+ $0080, $0081, $0082, $0083, $0084, $0085, $0086, $0087,
+ $0088, $0089, $008A, $008B, $008C, $008D, $008E, $008F,
+ $0090, $0091, $0092, $0093, $0094, $0095, $0096, $0097,
+ $0098, $0099, $009A, $009B, $009C, $009D, $009E, $009F,
+ $00A0, $0104, $02D8, $0141, $00A4, $013D, $015A, $00A7,
+ $00A8, $0160, $015E, $0164, $0179, $00AD, $017D, $017B,
+ $00B0, $0105, $02DB, $0142, $00B4, $013E, $015B, $02C7,
+ $00B8, $0161, $015F, $0165, $017A, $02DD, $017E, $017C,
+ $0154, $00C1, $00C2, $0102, $00C4, $0139, $0106, $00C7,
+ $010C, $00C9, $0118, $00CB, $011A, $00CD, $00CE, $010E,
+ $0110, $0143, $0147, $00D3, $00D4, $0150, $00D6, $00D7,
+ $0158, $016E, $00DA, $0170, $00DC, $00DD, $0162, $00DF,
+ $0155, $00E1, $00E2, $0103, $00E4, $013A, $0107, $00E7,
+ $010D, $00E9, $0119, $00EB, $011B, $00ED, $00EE, $010F,
+ $0111, $0144, $0148, $00F3, $00F4, $0151, $00F6, $00F7,
+ $0159, $016F, $00FA, $0171, $00FC, $00FD, $0163, $02D9
+ );
+
+{Latin-3
+ Afrikaans, Catalan, English, Esperanto, French, Galician,
+ German, Italian, Maltese and Turkish.
+}
+ CharISO_8859_3: array[128..255] of Word =
+ (
+ $0080, $0081, $0082, $0083, $0084, $0085, $0086, $0087,
+ $0088, $0089, $008A, $008B, $008C, $008D, $008E, $008F,
+ $0090, $0091, $0092, $0093, $0094, $0095, $0096, $0097,
+ $0098, $0099, $009A, $009B, $009C, $009D, $009E, $009F,
+ $00A0, $0126, $02D8, $00A3, $00A4, $FFFD, $0124, $00A7,
+ $00A8, $0130, $015E, $011E, $0134, $00AD, $FFFD, $017B,
+ $00B0, $0127, $00B2, $00B3, $00B4, $00B5, $0125, $00B7,
+ $00B8, $0131, $015F, $011F, $0135, $00BD, $FFFD, $017C,
+ $00C0, $00C1, $00C2, $FFFD, $00C4, $010A, $0108, $00C7,
+ $00C8, $00C9, $00CA, $00CB, $00CC, $00CD, $00CE, $00CF,
+ $FFFD, $00D1, $00D2, $00D3, $00D4, $0120, $00D6, $00D7,
+ $011C, $00D9, $00DA, $00DB, $00DC, $016C, $015C, $00DF,
+ $00E0, $00E1, $00E2, $FFFD, $00E4, $010B, $0109, $00E7,
+ $00E8, $00E9, $00EA, $00EB, $00EC, $00ED, $00EE, $00EF,
+ $FFFD, $00F1, $00F2, $00F3, $00F4, $0121, $00F6, $00F7,
+ $011D, $00F9, $00FA, $00FB, $00FC, $016D, $015D, $02D9
+ );
+
+{Latin-4
+ Danish, English, Estonian, Finnish, German, Greenlandic,
+ Lappish, Latvian, Lithuanian, Norwegian and Swedish.
+}
+ CharISO_8859_4: array[128..255] of Word =
+ (
+ $0080, $0081, $0082, $0083, $0084, $0085, $0086, $0087,
+ $0088, $0089, $008A, $008B, $008C, $008D, $008E, $008F,
+ $0090, $0091, $0092, $0093, $0094, $0095, $0096, $0097,
+ $0098, $0099, $009A, $009B, $009C, $009D, $009E, $009F,
+ $00A0, $0104, $0138, $0156, $00A4, $0128, $013B, $00A7,
+ $00A8, $0160, $0112, $0122, $0166, $00AD, $017D, $00AF,
+ $00B0, $0105, $02DB, $0157, $00B4, $0129, $013C, $02C7,
+ $00B8, $0161, $0113, $0123, $0167, $014A, $017E, $014B,
+ $0100, $00C1, $00C2, $00C3, $00C4, $00C5, $00C6, $012E,
+ $010C, $00C9, $0118, $00CB, $0116, $00CD, $00CE, $012A,
+ $0110, $0145, $014C, $0136, $00D4, $00D5, $00D6, $00D7,
+ $00D8, $0172, $00DA, $00DB, $00DC, $0168, $016A, $00DF,
+ $0101, $00E1, $00E2, $00E3, $00E4, $00E5, $00E6, $012F,
+ $010D, $00E9, $0119, $00EB, $0117, $00ED, $00EE, $012B,
+ $0111, $0146, $014D, $0137, $00F4, $00F5, $00F6, $00F7,
+ $00F8, $0173, $00FA, $00FB, $00FC, $0169, $016B, $02D9
+ );
+
+{CYRILLIC
+ Bulgarian, Bielorussian, English, Macedonian, Russian,
+ Serbo-Croatian and Ukrainian.
+}
+ CharISO_8859_5: array[128..255] of Word =
+ (
+ $0080, $0081, $0082, $0083, $0084, $0085, $0086, $0087,
+ $0088, $0089, $008A, $008B, $008C, $008D, $008E, $008F,
+ $0090, $0091, $0092, $0093, $0094, $0095, $0096, $0097,
+ $0098, $0099, $009A, $009B, $009C, $009D, $009E, $009F,
+ $00A0, $0401, $0402, $0403, $0404, $0405, $0406, $0407,
+ $0408, $0409, $040A, $040B, $040C, $00AD, $040E, $040F,
+ $0410, $0411, $0412, $0413, $0414, $0415, $0416, $0417,
+ $0418, $0419, $041A, $041B, $041C, $041D, $041E, $041F,
+ $0420, $0421, $0422, $0423, $0424, $0425, $0426, $0427,
+ $0428, $0429, $042A, $042B, $042C, $042D, $042E, $042F,
+ $0430, $0431, $0432, $0433, $0434, $0435, $0436, $0437,
+ $0438, $0439, $043A, $043B, $043C, $043D, $043E, $043F,
+ $0440, $0441, $0442, $0443, $0444, $0445, $0446, $0447,
+ $0448, $0449, $044A, $044B, $044C, $044D, $044E, $044F,
+ $2116, $0451, $0452, $0453, $0454, $0455, $0456, $0457,
+ $0458, $0459, $045A, $045B, $045C, $00A7, $045E, $045F
+ );
+
+{ARABIC
+}
+ CharISO_8859_6: array[128..255] of Word =
+ (
+ $0080, $0081, $0082, $0083, $0084, $0085, $0086, $0087,
+ $0088, $0089, $008A, $008B, $008C, $008D, $008E, $008F,
+ $0090, $0091, $0092, $0093, $0094, $0095, $0096, $0097,
+ $0098, $0099, $009A, $009B, $009C, $009D, $009E, $009F,
+ $00A0, $FFFD, $FFFD, $FFFD, $00A4, $FFFD, $FFFD, $FFFD,
+ $FFFD, $FFFD, $FFFD, $FFFD, $060C, $00AD, $FFFD, $FFFD,
+ $FFFD, $FFFD, $FFFD, $FFFD, $FFFD, $FFFD, $FFFD, $FFFD,
+ $FFFD, $FFFD, $FFFD, $061B, $FFFD, $FFFD, $FFFD, $061F,
+ $FFFD, $0621, $0622, $0623, $0624, $0625, $0626, $0627,
+ $0628, $0629, $062A, $062B, $062C, $062D, $062E, $062F,
+ $0630, $0631, $0632, $0633, $0634, $0635, $0636, $0637,
+ $0638, $0639, $063A, $FFFD, $FFFD, $FFFD, $FFFD, $FFFD,
+ $0640, $0641, $0642, $0643, $0644, $0645, $0646, $0647,
+ $0648, $0649, $064A, $064B, $064C, $064D, $064E, $064F,
+ $0650, $0651, $0652, $FFFD, $FFFD, $FFFD, $FFFD, $FFFD,
+ $FFFD, $FFFD, $FFFD, $FFFD, $FFFD, $FFFD, $FFFD, $FFFD
+ );
+
+{GREEK
+}
+ CharISO_8859_7: array[128..255] of Word =
+ (
+ $0080, $0081, $0082, $0083, $0084, $0085, $0086, $0087,
+ $0088, $0089, $008A, $008B, $008C, $008D, $008E, $008F,
+ $0090, $0091, $0092, $0093, $0094, $0095, $0096, $0097,
+ $0098, $0099, $009A, $009B, $009C, $009D, $009E, $009F,
+ $00A0, $2018, $2019, $00A3, $FFFD, $FFFD, $00A6, $00A7,
+ $00A8, $00A9, $FFFD, $00AB, $00AC, $00AD, $FFFD, $2015,
+ $00B0, $00B1, $00B2, $00B3, $0384, $0385, $0386, $00B7,
+ $0388, $0389, $038A, $00BB, $038C, $00BD, $038E, $038F,
+ $0390, $0391, $0392, $0393, $0394, $0395, $0396, $0397,
+ $0398, $0399, $039A, $039B, $039C, $039D, $039E, $039F,
+ $03A0, $03A1, $FFFD, $03A3, $03A4, $03A5, $03A6, $03A7,
+ $03A8, $03A9, $03AA, $03AB, $03AC, $03AD, $03AE, $03AF,
+ $03B0, $03B1, $03B2, $03B3, $03B4, $03B5, $03B6, $03B7,
+ $03B8, $03B9, $03BA, $03BB, $03BC, $03BD, $03BE, $03BF,
+ $03C0, $03C1, $03C2, $03C3, $03C4, $03C5, $03C6, $03C7,
+ $03C8, $03C9, $03CA, $03CB, $03CC, $03CD, $03CE, $FFFD
+ );
+
+{HEBREW
+}
+ CharISO_8859_8: array[128..255] of Word =
+ (
+ $0080, $0081, $0082, $0083, $0084, $0085, $0086, $0087,
+ $0088, $0089, $008A, $008B, $008C, $008D, $008E, $008F,
+ $0090, $0091, $0092, $0093, $0094, $0095, $0096, $0097,
+ $0098, $0099, $009A, $009B, $009C, $009D, $009E, $009F,
+ $00A0, $FFFD, $00A2, $00A3, $00A4, $00A5, $00A6, $00A7,
+ $00A8, $00A9, $00D7, $00AB, $00AC, $00AD, $00AE, $00AF,
+ $00B0, $00B1, $00B2, $00B3, $00B4, $00B5, $00B6, $00B7,
+ $00B8, $00B9, $00F7, $00BB, $00BC, $00BD, $00BE, $FFFD,
+ $FFFD, $FFFD, $FFFD, $FFFD, $FFFD, $FFFD, $FFFD, $FFFD,
+ $FFFD, $FFFD, $FFFD, $FFFD, $FFFD, $FFFD, $FFFD, $FFFD,
+ $FFFD, $FFFD, $FFFD, $FFFD, $FFFD, $FFFD, $FFFD, $FFFD,
+ $FFFD, $FFFD, $FFFD, $FFFD, $FFFD, $FFFD, $FFFD, $2017,
+ $05D0, $05D1, $05D2, $05D3, $05D4, $05D5, $05D6, $05D7,
+ $05D8, $05D9, $05DA, $05DB, $05DC, $05DD, $05DE, $05DF,
+ $05E0, $05E1, $05E2, $05E3, $05E4, $05E5, $05E6, $05E7,
+ $05E8, $05E9, $05EA, $FFFD, $FFFD, $200E, $200F, $FFFD
+ );
+
+{Latin-5
+ English, Finnish, French, German, Irish, Italian, Norwegian,
+ Portuguese, Spanish, Swedish and Turkish.
+}
+ CharISO_8859_9: array[128..255] of Word =
+ (
+ $0080, $0081, $0082, $0083, $0084, $0085, $0086, $0087,
+ $0088, $0089, $008A, $008B, $008C, $008D, $008E, $008F,
+ $0090, $0091, $0092, $0093, $0094, $0095, $0096, $0097,
+ $0098, $0099, $009A, $009B, $009C, $009D, $009E, $009F,
+ $00A0, $0104, $02D8, $0141, $00A4, $013D, $015A, $00A7,
+ $00A8, $0160, $015E, $0164, $0179, $00AD, $017D, $017B,
+ $00B0, $0105, $02DB, $0142, $00B4, $013E, $015B, $02C7,
+ $00B8, $0161, $015F, $0165, $017A, $02DD, $017E, $017C,
+ $0154, $00C1, $00C2, $0102, $00C4, $0139, $0106, $00C7,
+ $010C, $00C9, $0118, $00CB, $011A, $00CD, $00CE, $010E,
+ $011E, $00D1, $00D2, $00D3, $00D4, $00D5, $00D6, $00D7,
+ $00D8, $00D9, $00DA, $00DB, $00DC, $0130, $015E, $00DF,
+ $00E0, $00E1, $00E2, $00E3, $00E4, $00E5, $00E6, $00E7,
+ $00E8, $00E9, $00EA, $00EB, $00EC, $00ED, $00EE, $00EF,
+ $011F, $00F1, $00F2, $00F3, $00F4, $00F5, $00F6, $00F7,
+ $00F8, $00F9, $00FA, $00FB, $00FC, $0131, $015F, $00FF
+ );
+
+{Latin-6
+ Danish, English, Estonian, Faeroese, Finnish, German, Greenlandic,
+ Icelandic, Lappish, Latvian, Lithuanian, Norwegian and Swedish.
+}
+ CharISO_8859_10: array[128..255] of Word =
+ (
+ $0080, $0081, $0082, $0083, $0084, $0085, $0086, $0087,
+ $0088, $0089, $008A, $008B, $008C, $008D, $008E, $008F,
+ $0090, $0091, $0092, $0093, $0094, $0095, $0096, $0097,
+ $0098, $0099, $009A, $009B, $009C, $009D, $009E, $009F,
+ $00A0, $0104, $0112, $0122, $012A, $0128, $0136, $00A7,
+ $013B, $0110, $0160, $0166, $017D, $00AD, $016A, $014A,
+ $00B0, $0105, $0113, $0123, $012B, $0129, $0137, $00B7,
+ $013C, $0111, $0161, $0167, $017E, $2015, $016B, $014B,
+ $0100, $00C1, $00C2, $00C3, $00C4, $00C5, $00C6, $012E,
+ $010C, $00C9, $0118, $00CB, $0116, $00CD, $00CE, $00CF,
+ $00D0, $0145, $014C, $00D3, $00D4, $00D5, $00D6, $0168,
+ $00D8, $0172, $00DA, $00DB, $00DC, $00DD, $00DE, $00DF,
+ $0101, $00E1, $00E2, $00E3, $00E4, $00E5, $00E6, $012F,
+ $010D, $00E9, $0119, $00EB, $0117, $00ED, $00EE, $00EF,
+ $00F0, $0146, $014D, $00F3, $00F4, $00F5, $00F6, $0169,
+ $00F8, $0173, $00FA, $00FB, $00FC, $00FD, $00FE, $0138
+ );
+
+ CharISO_8859_13: array[128..255] of Word =
+ (
+ $0080, $0081, $0082, $0083, $0084, $0085, $0086, $0087,
+ $0088, $0089, $008A, $008B, $008C, $008D, $008E, $008F,
+ $0090, $0091, $0092, $0093, $0094, $0095, $0096, $0097,
+ $0098, $0099, $009A, $009B, $009C, $009D, $009E, $009F,
+ $00A0, $201D, $00A2, $00A3, $00A4, $201E, $00A6, $00A7,
+ $00D8, $00A9, $0156, $00AB, $00AC, $00AD, $00AE, $00C6,
+ $00B0, $00B1, $00B2, $00B3, $201C, $00B5, $00B6, $00B7,
+ $00F8, $00B9, $0157, $00BB, $00BC, $00BD, $00BE, $00E6,
+ $0104, $012E, $0100, $0106, $00C4, $00C5, $0118, $0112,
+ $010C, $00C9, $0179, $0116, $0122, $0136, $012A, $013B,
+ $0160, $0143, $0145, $00D3, $014C, $00D5, $00D6, $00D7,
+ $0172, $0141, $015A, $016A, $00DC, $017B, $017D, $00DF,
+ $0105, $012F, $0101, $0107, $00E4, $00E5, $0119, $0113,
+ $010D, $00E9, $017A, $0117, $0123, $0137, $012B, $013C,
+ $0161, $0144, $0146, $00F3, $014D, $00F5, $00F6, $00F7,
+ $0173, $0142, $015B, $016B, $00FC, $017C, $017E, $2019
+ );
+
+ CharISO_8859_14: array[128..255] of Word =
+ (
+ $0080, $0081, $0082, $0083, $0084, $0085, $0086, $0087,
+ $0088, $0089, $008A, $008B, $008C, $008D, $008E, $008F,
+ $0090, $0091, $0092, $0093, $0094, $0095, $0096, $0097,
+ $0098, $0099, $009A, $009B, $009C, $009D, $009E, $009F,
+ $00A0, $1E02, $1E03, $00A3, $010A, $010B, $1E0A, $00A7,
+ $1E80, $00A9, $1E82, $1E0B, $1EF2, $00AD, $00AE, $0178,
+ $1E1E, $1E1F, $0120, $0121, $1E40, $1E41, $00B6, $1E56,
+ $1E81, $1E57, $1E83, $1E60, $1EF3, $1E84, $1E85, $1E61,
+ $00C0, $00C1, $00C2, $00C3, $00C4, $00C5, $00C6, $00C7,
+ $00C8, $00C9, $00CA, $00CB, $00CC, $00CD, $00CE, $00CF,
+ $0174, $00D1, $00D2, $00D3, $00D4, $00D5, $00D6, $1E6A,
+ $00D8, $00D9, $00DA, $00DB, $00DC, $00DD, $0176, $00DF,
+ $00E0, $00E1, $00E2, $00E3, $00E4, $00E5, $00E6, $00E7,
+ $00E8, $00E9, $00EA, $00EB, $00EC, $00ED, $00EE, $00EF,
+ $0175, $00F1, $00F2, $00F3, $00F4, $00F5, $00F6, $1E6B,
+ $00F8, $00F9, $00FA, $00FB, $00FC, $00FD, $0177, $00FF
+ );
+
+ CharISO_8859_15: array[128..255] of Word =
+ (
+ $0080, $0081, $0082, $0083, $0084, $0085, $0086, $0087,
+ $0088, $0089, $008A, $008B, $008C, $008D, $008E, $008F,
+ $0090, $0091, $0092, $0093, $0094, $0095, $0096, $0097,
+ $0098, $0099, $009A, $009B, $009C, $009D, $009E, $009F,
+ $00A0, $00A1, $00A2, $00A3, $20AC, $00A5, $0160, $00A7,
+ $0161, $00A9, $00AA, $00AB, $00AC, $00AD, $00AE, $00AF,
+ $00B0, $00B1, $00B2, $00B3, $017D, $00B5, $00B6, $00B7,
+ $017E, $00B9, $00BA, $00BB, $0152, $0153, $0178, $00BF,
+ $00C0, $00C1, $00C2, $00C3, $00C4, $00C5, $00C6, $00C7,
+ $00C8, $00C9, $00CA, $00CB, $00CC, $00CD, $00CE, $00CF,
+ $00D0, $00D1, $00D2, $00D3, $00D4, $00D5, $00D6, $00D7,
+ $00D8, $00D9, $00DA, $00DB, $00DC, $00DD, $00DE, $00DF,
+ $00E0, $00E1, $00E2, $00E3, $00E4, $00E5, $00E6, $00E7,
+ $00E8, $00E9, $00EA, $00EB, $00EC, $00ED, $00EE, $00EF,
+ $00F0, $00F1, $00F2, $00F3, $00F4, $00F5, $00F6, $00F7,
+ $00F8, $00F9, $00FA, $00FB, $00FC, $00FD, $00FE, $00FF
+ );
+
+{Eastern European
+}
+ CharCP_1250: array[128..255] of Word =
+ (
+ $20AC, $FFFD, $201A, $FFFD, $201E, $2026, $2020, $2021,
+ $FFFD, $2030, $0160, $2039, $015A, $0164, $017D, $0179,
+ $FFFD, $2018, $2019, $201C, $201D, $2022, $2013, $2014,
+ $FFFD, $2122, $0161, $203A, $015B, $0165, $017E, $017A,
+ $00A0, $02C7, $02D8, $0141, $00A4, $0104, $00A6, $00A7,
+ $00A8, $00A9, $015E, $00AB, $00AC, $00AD, $00AE, $017B,
+ $00B0, $00B1, $02DB, $0142, $00B4, $00B5, $00B6, $00B7,
+ $00B8, $0105, $015F, $00BB, $013D, $02DD, $013E, $017C,
+ $0154, $00C1, $00C2, $0102, $00C4, $0139, $0106, $00C7,
+ $010C, $00C9, $0118, $00CB, $011A, $00CD, $00CE, $010E,
+ $0110, $0143, $0147, $00D3, $00D4, $0150, $00D6, $00D7,
+ $0158, $016E, $00DA, $0170, $00DC, $00DD, $0162, $00DF,
+ $0155, $00E1, $00E2, $0103, $00E4, $013A, $0107, $00E7,
+ $010D, $00E9, $0119, $00EB, $011B, $00ED, $00EE, $010F,
+ $0111, $0144, $0148, $00F3, $00F4, $0151, $00F6, $00F7,
+ $0159, $016F, $00FA, $0171, $00FC, $00FD, $0163, $02D9
+ );
+
+{Cyrillic
+}
+ CharCP_1251: array[128..255] of Word =
+ (
+ $0402, $0403, $201A, $0453, $201E, $2026, $2020, $2021,
+ $20AC, $2030, $0409, $2039, $040A, $040C, $040B, $040F,
+ $0452, $2018, $2019, $201C, $201D, $2022, $2013, $2014,
+ $FFFD, $2122, $0459, $203A, $045A, $045C, $045B, $045F,
+ $00A0, $040E, $045E, $0408, $00A4, $0490, $00A6, $00A7,
+ $0401, $00A9, $0404, $00AB, $00AC, $00AD, $00AE, $0407,
+ $00B0, $00B1, $0406, $0456, $0491, $00B5, $00B6, $00B7,
+ $0451, $2116, $0454, $00BB, $0458, $0405, $0455, $0457,
+ $0410, $0411, $0412, $0413, $0414, $0415, $0416, $0417,
+ $0418, $0419, $041A, $041B, $041C, $041D, $041E, $041F,
+ $0420, $0421, $0422, $0423, $0424, $0425, $0426, $0427,
+ $0428, $0429, $042A, $042B, $042C, $042D, $042E, $042F,
+ $0430, $0431, $0432, $0433, $0434, $0435, $0436, $0437,
+ $0438, $0439, $043A, $043B, $043C, $043D, $043E, $043F,
+ $0440, $0441, $0442, $0443, $0444, $0445, $0446, $0447,
+ $0448, $0449, $044A, $044B, $044C, $044D, $044E, $044F
+ );
+
+{Latin-1 (US, Western Europe)
+}
+ CharCP_1252: array[128..255] of Word =
+ (
+ $20AC, $FFFD, $201A, $0192, $201E, $2026, $2020, $2021,
+ $02C6, $2030, $0160, $2039, $0152, $FFFD, $017D, $FFFD,
+ $FFFD, $2018, $2019, $201C, $201D, $2022, $2013, $2014,
+ $02DC, $2122, $0161, $203A, $0153, $FFFD, $017E, $0178,
+ $00A0, $00A1, $00A2, $00A3, $00A4, $00A5, $00A6, $00A7,
+ $00A8, $00A9, $00AA, $00AB, $00AC, $00AD, $00AE, $00AF,
+ $00B0, $00B1, $00B2, $00B3, $00B4, $00B5, $00B6, $00B7,
+ $00B8, $00B9, $00BA, $00BB, $00BC, $00BD, $00BE, $00BF,
+ $00C0, $00C1, $00C2, $00C3, $00C4, $00C5, $00C6, $00C7,
+ $00C8, $00C9, $00CA, $00CB, $00CC, $00CD, $00CE, $00CF,
+ $00D0, $00D1, $00D2, $00D3, $00D4, $00D5, $00D6, $00D7,
+ $00D8, $00D9, $00DA, $00DB, $00DC, $00DD, $00DE, $00DF,
+ $00E0, $00E1, $00E2, $00E3, $00E4, $00E5, $00E6, $00E7,
+ $00E8, $00E9, $00EA, $00EB, $00EC, $00ED, $00EE, $00EF,
+ $00F0, $00F1, $00F2, $00F3, $00F4, $00F5, $00F6, $00F7,
+ $00F8, $00F9, $00FA, $00FB, $00FC, $00FD, $00FE, $00FF
+ );
+
+{Greek
+}
+ CharCP_1253: array[128..255] of Word =
+ (
+ $20AC, $FFFD, $201A, $0192, $201E, $2026, $2020, $2021,
+ $FFFD, $2030, $FFFD, $2039, $FFFD, $FFFD, $FFFD, $FFFD,
+ $FFFD, $2018, $2019, $201C, $201D, $2022, $2013, $2014,
+ $FFFD, $2122, $FFFD, $203A, $FFFD, $FFFD, $FFFD, $FFFD,
+ $00A0, $0385, $0386, $00A3, $00A4, $00A5, $00A6, $00A7,
+ $00A8, $00A9, $FFFD, $00AB, $00AC, $00AD, $00AE, $2015,
+ $00B0, $00B1, $00B2, $00B3, $0384, $00B5, $00B6, $00B7,
+ $0388, $0389, $038A, $00BB, $038C, $00BD, $038E, $038F,
+ $0390, $0391, $0392, $0393, $0394, $0395, $0396, $0397,
+ $0398, $0399, $039A, $039B, $039C, $039D, $039E, $039F,
+ $03A0, $03A1, $FFFD, $03A3, $03A4, $03A5, $03A6, $03A7,
+ $03A8, $03A9, $03AA, $03AB, $03AC, $03AD, $03AE, $03AF,
+ $03B0, $03B1, $03B2, $03B3, $03B4, $03B5, $03B6, $03B7,
+ $03B8, $03B9, $03BA, $03BB, $03BC, $03BD, $03BE, $03BF,
+ $03C0, $03C1, $03C2, $03C3, $03C4, $03C5, $03C6, $03C7,
+ $03C8, $03C9, $03CA, $03CB, $03CC, $03CD, $03CE, $FFFD
+ );
+
+{Turkish
+}
+ CharCP_1254: array[128..255] of Word =
+ (
+ $20AC, $FFFD, $201A, $0192, $201E, $2026, $2020, $2021,
+ $02C6, $2030, $0160, $2039, $0152, $FFFD, $FFFD, $FFFD,
+ $FFFD, $2018, $2019, $201C, $201D, $2022, $2013, $2014,
+ $02DC, $2122, $0161, $203A, $0153, $FFFD, $FFFD, $0178,
+ $00A0, $00A1, $00A2, $00A3, $00A4, $00A5, $00A6, $00A7,
+ $00A8, $00A9, $00AA, $00AB, $00AC, $00AD, $00AE, $00AF,
+ $00B0, $00B1, $00B2, $00B3, $00B4, $00B5, $00B6, $00B7,
+ $00B8, $00B9, $00BA, $00BB, $00BC, $00BD, $00BE, $00BF,
+ $00C0, $00C1, $00C2, $00C3, $00C4, $00C5, $00C6, $00C7,
+ $00C8, $00C9, $00CA, $00CB, $00CC, $00CD, $00CE, $00CF,
+ $011E, $00D1, $00D2, $00D3, $00D4, $00D5, $00D6, $00D7,
+ $00D8, $00D9, $00DA, $00DB, $00DC, $0130, $015E, $00DF,
+ $00E0, $00E1, $00E2, $00E3, $00E4, $00E5, $00E6, $00E7,
+ $00E8, $00E9, $00EA, $00EB, $00EC, $00ED, $00EE, $00EF,
+ $011F, $00F1, $00F2, $00F3, $00F4, $00F5, $00F6, $00F7,
+ $00F8, $00F9, $00FA, $00FB, $00FC, $0131, $015F, $00FF
+ );
+
+{Hebrew
+}
+ CharCP_1255: array[128..255] of Word =
+ (
+ $20AC, $FFFD, $201A, $0192, $201E, $2026, $2020, $2021,
+ $02C6, $2030, $FFFD, $2039, $FFFD, $FFFD, $FFFD, $FFFD,
+ $FFFD, $2018, $2019, $201C, $201D, $2022, $2013, $2014,
+ $02DC, $2122, $FFFD, $203A, $FFFD, $FFFD, $FFFD, $FFFD,
+ $00A0, $00A1, $00A2, $00A3, $20AA, $00A5, $00A6, $00A7,
+ $00A8, $00A9, $00D7, $00AB, $00AC, $00AD, $00AE, $00AF,
+ $00B0, $00B1, $00B2, $00B3, $00B4, $00B5, $00B6, $00B7,
+ $00B8, $00B9, $00F7, $00BB, $00BC, $00BD, $00BE, $00BF,
+ $05B0, $05B1, $05B2, $05B3, $05B4, $05B5, $05B6, $05B7,
+ $05B8, $05B9, $FFFD, $05BB, $05BC, $05BD, $05BE, $05BF,
+ $05C0, $05C1, $05C2, $05C3, $05F0, $05F1, $05F2, $05F3,
+ $05F4, $FFFD, $FFFD, $FFFD, $FFFD, $FFFD, $FFFD, $FFFD,
+ $05D0, $05D1, $05D2, $05D3, $05D4, $05D5, $05D6, $05D7,
+ $05D8, $05D9, $05DA, $05DB, $05DC, $05DD, $05DE, $05DF,
+ $05E0, $05E1, $05E2, $05E3, $05E4, $05E5, $05E6, $05E7,
+ $05E8, $05E9, $05EA, $FFFD, $FFFD, $200E, $200F, $FFFD
+ );
+
+{Arabic
+}
+ CharCP_1256: array[128..255] of Word =
+ (
+ $20AC, $067E, $201A, $0192, $201E, $2026, $2020, $2021,
+ $02C6, $2030, $0679, $2039, $0152, $0686, $0698, $0688,
+ $06AF, $2018, $2019, $201C, $201D, $2022, $2013, $2014,
+ $06A9, $2122, $0691, $203A, $0153, $200C, $200D, $06BA,
+ $00A0, $060C, $00A2, $00A3, $00A4, $00A5, $00A6, $00A7,
+ $00A8, $00A9, $06BE, $00AB, $00AC, $00AD, $00AE, $00AF,
+ $00B0, $00B1, $00B2, $00B3, $00B4, $00B5, $00B6, $00B7,
+ $00B8, $00B9, $061B, $00BB, $00BC, $00BD, $00BE, $061F,
+ $06C1, $0621, $0622, $0623, $0624, $0625, $0626, $0627,
+ $0628, $0629, $062A, $062B, $062C, $062D, $062E, $062F,
+ $0630, $0631, $0632, $0633, $0634, $0635, $0636, $00D7,
+ $0637, $0638, $0639, $063A, $0640, $0641, $0642, $0643,
+ $00E0, $0644, $00E2, $0645, $0646, $0647, $0648, $00E7,
+ $00E8, $00E9, $00EA, $00EB, $0649, $064A, $00EE, $00EF,
+ $064B, $064C, $064D, $064E, $00F4, $064F, $0650, $00F7,
+ $0651, $00F9, $0652, $00FB, $00FC, $200E, $200F, $06D2
+ );
+
+{Baltic
+}
+ CharCP_1257: array[128..255] of Word =
+ (
+ $20AC, $FFFD, $201A, $FFFD, $201E, $2026, $2020, $2021,
+ $FFFD, $2030, $FFFD, $2039, $FFFD, $00A8, $02C7, $00B8,
+ $FFFD, $2018, $2019, $201C, $201D, $2022, $2013, $2014,
+ $FFFD, $2122, $FFFD, $203A, $FFFD, $00AF, $02DB, $FFFD,
+ $00A0, $FFFD, $00A2, $00A3, $00A4, $FFFD, $00A6, $00A7,
+ $00D8, $00A9, $0156, $00AB, $00AC, $00AD, $00AE, $00C6,
+ $00B0, $00B1, $00B2, $00B3, $00B4, $00B5, $00B6, $00B7,
+ $00F8, $00B9, $0157, $00BB, $00BC, $00BD, $00BE, $00E6,
+ $0104, $012E, $0100, $0106, $00C4, $00C5, $0118, $0112,
+ $010C, $00C9, $0179, $0116, $0122, $0136, $012A, $013B,
+ $0160, $0143, $0145, $00D3, $014C, $00D5, $00D6, $00D7,
+ $0172, $0141, $015A, $016A, $00DC, $017B, $017D, $00DF,
+ $0105, $012F, $0101, $0107, $00E4, $00E5, $0119, $0113,
+ $010D, $00E9, $017A, $0117, $0123, $0137, $012B, $013C,
+ $0161, $0144, $0146, $00F3, $014D, $00F5, $00F6, $00F7,
+ $0173, $0142, $015B, $016B, $00FC, $017C, $017E, $02D9
+ );
+
+{Vietnamese
+}
+ CharCP_1258: array[128..255] of Word =
+ (
+ $20AC, $FFFD, $201A, $0192, $201E, $2026, $2020, $2021,
+ $02C6, $2030, $FFFD, $2039, $0152, $FFFD, $FFFD, $FFFD,
+ $FFFD, $2018, $2019, $201C, $201D, $2022, $2013, $2014,
+ $02DC, $2122, $FFFD, $203A, $0153, $FFFD, $FFFD, $0178,
+ $00A0, $00A1, $00A2, $00A3, $00A4, $00A5, $00A6, $00A7,
+ $00A8, $00A9, $00AA, $00AB, $00AC, $00AD, $00AE, $00AF,
+ $00B0, $00B1, $00B2, $00B3, $00B4, $00B5, $00B6, $00B7,
+ $00B8, $00B9, $00BA, $00BB, $00BC, $00BD, $00BE, $00BF,
+ $00C0, $00C1, $00C2, $0102, $00C4, $00C5, $00C6, $00C7,
+ $00C8, $00C9, $00CA, $00CB, $0300, $00CD, $00CE, $00CF,
+ $0110, $00D1, $0309, $00D3, $00D4, $01A0, $00D6, $00D7,
+ $00D8, $00D9, $00DA, $00DB, $00DC, $01AF, $0303, $00DF,
+ $00E0, $00E1, $00E2, $0103, $00E4, $00E5, $00E6, $00E7,
+ $00E8, $00E9, $00EA, $00EB, $0301, $00ED, $00EE, $00EF,
+ $0111, $00F1, $0323, $00F3, $00F4, $01A1, $00F6, $00F7,
+ $00F8, $00F9, $00FA, $00FB, $00FC, $01B0, $20AB, $00FF
+ );
+
+{Cyrillic
+}
+ CharKOI8_R: array[128..255] of Word =
+ (
+ $2500, $2502, $250C, $2510, $2514, $2518, $251C, $2524,
+ $252C, $2534, $253C, $2580, $2584, $2588, $258C, $2590,
+ $2591, $2592, $2593, $2320, $25A0, $2219, $221A, $2248,
+ $2264, $2265, $00A0, $2321, $00B0, $00B2, $00B7, $00F7,
+ $2550, $2551, $2552, $0451, $2553, $2554, $2555, $2556,
+ $2557, $2558, $2559, $255A, $255B, $255C, $255D, $255E,
+ $255F, $2560, $2561, $0401, $2562, $2563, $2564, $2565,
+ $2566, $2567, $2568, $2569, $256A, $256B, $256C, $00A9,
+ $044E, $0430, $0431, $0446, $0434, $0435, $0444, $0433,
+ $0445, $0438, $0439, $043A, $043B, $043C, $043D, $043E,
+ $043F, $044F, $0440, $0441, $0442, $0443, $0436, $0432,
+ $044C, $044B, $0437, $0448, $044D, $0449, $0447, $044A,
+ $042E, $0410, $0411, $0426, $0414, $0415, $0424, $0413,
+ $0425, $0418, $0419, $041A, $041B, $041C, $041D, $041E,
+ $041F, $042F, $0420, $0421, $0422, $0423, $0416, $0412,
+ $042C, $042B, $0417, $0428, $042D, $0429, $0427, $042A
+ );
+
+{Czech (Kamenicky)
+}
+ CharCP_895: array[128..255] of Word =
+ (
+ $010C, $00FC, $00E9, $010F, $00E4, $010E, $0164, $010D,
+ $011B, $011A, $0139, $00CD, $013E, $013A, $00C4, $00C1,
+ $00C9, $017E, $017D, $00F4, $00F6, $00D3, $016F, $00DA,
+ $00FD, $00D6, $00DC, $0160, $013D, $00DD, $0158, $0165,
+ $00E1, $00ED, $00F3, $00FA, $0148, $0147, $016E, $00D4,
+ $0161, $0159, $0155, $0154, $00BC, $00A7, $00AB, $00BB,
+ $2591, $2592, $2593, $2502, $2524, $2561, $2562, $2556,
+ $2555, $2563, $2551, $2557, $255D, $255C, $255B, $2510,
+ $2514, $2534, $252C, $251C, $2500, $253C, $255E, $255F,
+ $255A, $2554, $2569, $2566, $2560, $2550, $256C, $2567,
+ $2568, $2564, $2565, $2559, $2558, $2552, $2553, $256B,
+ $256A, $2518, $250C, $2588, $2584, $258C, $2590, $2580,
+ $03B1, $03B2, $0393, $03C0, $03A3, $03C3, $03BC, $03C4,
+ $03A6, $0398, $03A9, $03B4, $221E, $2205, $03B5, $2229,
+ $2261, $00B1, $2265, $2264, $2320, $2321, $00F7, $2248,
+ $2218, $00B7, $2219, $221A, $207F, $00B2, $25A0, $00A0
+ );
+
+{Eastern European
+}
+ CharCP_852: array[128..255] of Word =
+ (
+ $00C7, $00FC, $00E9, $00E2, $00E4, $016F, $0107, $00E7,
+ $0142, $00EB, $0150, $0151, $00EE, $0179, $00C4, $0106,
+ $00C9, $0139, $013A, $00F4, $00F6, $013D, $013E, $015A,
+ $015B, $00D6, $00DC, $0164, $0165, $0141, $00D7, $010D,
+ $00E1, $00ED, $00F3, $00FA, $0104, $0105, $017D, $017E,
+ $0118, $0119, $00AC, $017A, $010C, $015F, $00AB, $00BB,
+ $2591, $2592, $2593, $2502, $2524, $00C1, $00C2, $011A,
+ $015E, $2563, $2551, $2557, $255D, $017B, $017C, $2510,
+ $2514, $2534, $252C, $251C, $2500, $253C, $0102, $0103,
+ $255A, $2554, $2569, $2566, $2560, $2550, $256C, $00A4,
+ $0111, $0110, $010E, $00CB, $010F, $0147, $00CD, $00CE,
+ $011B, $2518, $250C, $2588, $2584, $0162, $016E, $2580,
+ $00D3, $00DF, $00D4, $0143, $0144, $0148, $0160, $0161,
+ $0154, $00DA, $0155, $0170, $00FD, $00DD, $0163, $00B4,
+ $00AD, $02DD, $02DB, $02C7, $02D8, $00A7, $00F7, $00B8,
+ $00B0, $00A8, $02D9, $0171, $0158, $0159, $25A0, $00A0
+ );
+
+{==============================================================================}
+type
+ TIconvChar = record
+ Charset: TMimeChar;
+ CharName: string;
+ end;
+ TIconvArr = array [0..112] of TIconvChar;
+
+const
+ NotFoundChar = '_';
+
+var
+ SetTwo: set of TMimeChar = [UCS_2, UCS_2LE, UTF_7, UTF_7mod];
+ SetFour: set of TMimeChar = [UCS_4, UCS_4LE, UTF_8];
+ SetLE: set of TMimeChar = [UCS_2LE, UCS_4LE];
+
+ IconvArr: TIconvArr;
+
+{==============================================================================}
+function FindIconvID(const Value, Charname: string): Boolean;
+var
+ s: string;
+begin
+ Result := True;
+ //exact match
+ if Value = Charname then
+ Exit;
+ //Value is on begin of charname
+ s := Value + ' ';
+ if s = Copy(Charname, 1, Length(s)) then
+ Exit;
+ //Value is on end of charname
+ s := ' ' + Value;
+ if s = Copy(Charname, Length(Charname) - Length(s) + 1, Length(s)) then
+ Exit;
+ //value is somewhere inside charname
+ if Pos( s + ' ', Charname) > 0 then
+ Exit;
+ Result := False;
+end;
+
+function GetCPFromIconvID(Value: AnsiString): TMimeChar;
+var
+ n: integer;
+begin
+ Result := ISO_8859_1;
+ Value := UpperCase(Value);
+ for n := 0 to High(IconvArr) do
+ if FindIconvID(Value, IconvArr[n].Charname) then
+ begin
+ Result := IconvArr[n].Charset;
+ Break;
+ end;
+end;
+
+{==============================================================================}
+function GetIconvIDFromCP(Value: TMimeChar): AnsiString;
+var
+ n: integer;
+begin
+ Result := 'ISO-8859-1';
+ for n := 0 to High(IconvArr) do
+ if IconvArr[n].Charset = Value then
+ begin
+ Result := Separateleft(IconvArr[n].Charname, ' ');
+ Break;
+ end;
+end;
+
+{==============================================================================}
+function ReplaceUnicode(Value: Word; const TransformTable: array of Word): Word;
+var
+ n: integer;
+begin
+ if High(TransformTable) <> 0 then
+ for n := 0 to High(TransformTable) do
+ if not odd(n) then
+ if TransformTable[n] = Value then
+ begin
+ Value := TransformTable[n+1];
+ break;
+ end;
+ Result := Value;
+end;
+
+{==============================================================================}
+procedure CopyArray(const SourceTable: array of Word;
+ var TargetTable: array of Word);
+var
+ n: Integer;
+begin
+ for n := 0 to 127 do
+ TargetTable[n] := SourceTable[n];
+end;
+
+{==============================================================================}
+procedure GetArray(CharSet: TMimeChar; var Result: array of Word);
+begin
+ case CharSet of
+ ISO_8859_2:
+ CopyArray(CharISO_8859_2, Result);
+ ISO_8859_3:
+ CopyArray(CharISO_8859_3, Result);
+ ISO_8859_4:
+ CopyArray(CharISO_8859_4, Result);
+ ISO_8859_5:
+ CopyArray(CharISO_8859_5, Result);
+ ISO_8859_6:
+ CopyArray(CharISO_8859_6, Result);
+ ISO_8859_7:
+ CopyArray(CharISO_8859_7, Result);
+ ISO_8859_8:
+ CopyArray(CharISO_8859_8, Result);
+ ISO_8859_9:
+ CopyArray(CharISO_8859_9, Result);
+ ISO_8859_10:
+ CopyArray(CharISO_8859_10, Result);
+ ISO_8859_13:
+ CopyArray(CharISO_8859_13, Result);
+ ISO_8859_14:
+ CopyArray(CharISO_8859_14, Result);
+ ISO_8859_15:
+ CopyArray(CharISO_8859_15, Result);
+ CP1250:
+ CopyArray(CharCP_1250, Result);
+ CP1251:
+ CopyArray(CharCP_1251, Result);
+ CP1252:
+ CopyArray(CharCP_1252, Result);
+ CP1253:
+ CopyArray(CharCP_1253, Result);
+ CP1254:
+ CopyArray(CharCP_1254, Result);
+ CP1255:
+ CopyArray(CharCP_1255, Result);
+ CP1256:
+ CopyArray(CharCP_1256, Result);
+ CP1257:
+ CopyArray(CharCP_1257, Result);
+ CP1258:
+ CopyArray(CharCP_1258, Result);
+ KOI8_R:
+ CopyArray(CharKOI8_R, Result);
+ CP895:
+ CopyArray(CharCP_895, Result);
+ CP852:
+ CopyArray(CharCP_852, Result);
+ else
+ CopyArray(CharISO_8859_1, Result);
+ end;
+end;
+
+{==============================================================================}
+procedure ReadMulti(const Value: AnsiString; var Index: Integer; mb: Byte;
+ var b1, b2, b3, b4: Byte; le: boolean);
+Begin
+ b1 := 0;
+ b2 := 0;
+ b3 := 0;
+ b4 := 0;
+ if Index < 0 then
+ Index := 1;
+ if mb > 4 then
+ mb := 1;
+ if (Index + mb - 1) <= Length(Value) then
+ begin
+ if le then
+ Case mb Of
+ 1:
+ b1 := Ord(Value[Index]);
+ 2:
+ Begin
+ b1 := Ord(Value[Index]);
+ b2 := Ord(Value[Index + 1]);
+ End;
+ 3:
+ Begin
+ b1 := Ord(Value[Index]);
+ b2 := Ord(Value[Index + 1]);
+ b3 := Ord(Value[Index + 2]);
+ End;
+ 4:
+ Begin
+ b1 := Ord(Value[Index]);
+ b2 := Ord(Value[Index + 1]);
+ b3 := Ord(Value[Index + 2]);
+ b4 := Ord(Value[Index + 3]);
+ End;
+ end
+ else
+ Case mb Of
+ 1:
+ b1 := Ord(Value[Index]);
+ 2:
+ Begin
+ b2 := Ord(Value[Index]);
+ b1 := Ord(Value[Index + 1]);
+ End;
+ 3:
+ Begin
+ b3 := Ord(Value[Index]);
+ b2 := Ord(Value[Index + 1]);
+ b1 := Ord(Value[Index + 2]);
+ End;
+ 4:
+ Begin
+ b4 := Ord(Value[Index]);
+ b3 := Ord(Value[Index + 1]);
+ b2 := Ord(Value[Index + 2]);
+ b1 := Ord(Value[Index + 3]);
+ End;
+ end;
+ end;
+ Inc(Index, mb);
+end;
+
+{==============================================================================}
+function WriteMulti(b1, b2, b3, b4: Byte; mb: Byte; le: boolean): AnsiString;
+begin
+ if mb > 4 then
+ mb := 1;
+ SetLength(Result, mb);
+ if le then
+ case mb Of
+ 1:
+ Result[1] := AnsiChar(b1);
+ 2:
+ begin
+ Result[1] := AnsiChar(b1);
+ Result[2] := AnsiChar(b2);
+ end;
+ 3:
+ begin
+ Result[1] := AnsiChar(b1);
+ Result[2] := AnsiChar(b2);
+ Result[3] := AnsiChar(b3);
+ end;
+ 4:
+ begin
+ Result[1] := AnsiChar(b1);
+ Result[2] := AnsiChar(b2);
+ Result[3] := AnsiChar(b3);
+ Result[4] := AnsiChar(b4);
+ end;
+ end
+ else
+ case mb Of
+ 1:
+ Result[1] := AnsiChar(b1);
+ 2:
+ begin
+ Result[2] := AnsiChar(b1);
+ Result[1] := AnsiChar(b2);
+ end;
+ 3:
+ begin
+ Result[3] := AnsiChar(b1);
+ Result[2] := AnsiChar(b2);
+ Result[1] := AnsiChar(b3);
+ end;
+ 4:
+ begin
+ Result[4] := AnsiChar(b1);
+ Result[3] := AnsiChar(b2);
+ Result[2] := AnsiChar(b3);
+ Result[1] := AnsiChar(b4);
+ end;
+ end;
+end;
+
+{==============================================================================}
+function UTF8toUCS4(const Value: AnsiString): AnsiString;
+var
+ n, x, ul, m: Integer;
+ s: AnsiString;
+ w1, w2: Word;
+begin
+ Result := '';
+ n := 1;
+ while Length(Value) >= n do
+ begin
+ x := Ord(Value[n]);
+ Inc(n);
+ if x < 128 then
+ Result := Result + WriteMulti(x, 0, 0, 0, 4, false)
+ else
+ begin
+ m := 0;
+ if (x and $E0) = $C0 then
+ m := $1F;
+ if (x and $F0) = $E0 then
+ m := $0F;
+ if (x and $F8) = $F0 then
+ m := $07;
+ if (x and $FC) = $F8 then
+ m := $03;
+ if (x and $FE) = $FC then
+ m := $01;
+ ul := x and m;
+ s := IntToBin(ul, 0);
+ while Length(Value) >= n do
+ begin
+ x := Ord(Value[n]);
+ Inc(n);
+ if (x and $C0) = $80 then
+ s := s + IntToBin(x and $3F, 6)
+ else
+ begin
+ Dec(n);
+ Break;
+ end;
+ end;
+ ul := BinToInt(s);
+ w1 := ul div 65536;
+ w2 := ul mod 65536;
+ Result := Result + WriteMulti(Lo(w2), Hi(w2), Lo(w1), Hi(w1), 4, false);
+ end;
+ end;
+end;
+
+{==============================================================================}
+function UCS4toUTF8(const Value: AnsiString): AnsiString;
+var
+ s, l, k: AnsiString;
+ b1, b2, b3, b4: Byte;
+ n, m, x, y: Integer;
+ b: Byte;
+begin
+ Result := '';
+ n := 1;
+ while Length(Value) >= n do
+ begin
+ ReadMulti(Value, n, 4, b1, b2, b3, b4, false);
+ if (b2 = 0) and (b3 = 0) and (b4 = 0) and (b1 < 128) then
+ Result := Result + AnsiChar(b1)
+ else
+ begin
+ x := (b1 + 256 * b2) + (b3 + 256 * b4) * 65536;
+ l := IntToBin(x, 0);
+ y := Length(l) div 6;
+ s := '';
+ for m := 1 to y do
+ begin
+ k := Copy(l, Length(l) - 5, 6);
+ l := Copy(l, 1, Length(l) - 6);
+ b := BinToInt(k) or $80;
+ s := AnsiChar(b) + s;
+ end;
+ b := BinToInt(l);
+ case y of
+ 5:
+ b := b or $FC;
+ 4:
+ b := b or $F8;
+ 3:
+ b := b or $F0;
+ 2:
+ b := b or $E0;
+ 1:
+ b := b or $C0;
+ end;
+ s := AnsiChar(b) + s;
+ Result := Result + s;
+ end;
+ end;
+end;
+
+{==============================================================================}
+function UTF7toUCS2(const Value: AnsiString; Modified: Boolean): AnsiString;
+var
+ n, i: Integer;
+ c: AnsiChar;
+ s, t: AnsiString;
+ shift: AnsiChar;
+ table: String;
+begin
+ Result := '';
+ n := 1;
+ if modified then
+ begin
+ shift := '&';
+ table := TableBase64mod;
+ end
+ else
+ begin
+ shift := '+';
+ table := TableBase64;
+ end;
+ while Length(Value) >= n do
+ begin
+ c := Value[n];
+ Inc(n);
+ if c <> shift then
+ Result := Result + WriteMulti(Ord(c), 0, 0, 0, 2, false)
+ else
+ begin
+ s := '';
+ while Length(Value) >= n do
+ begin
+ c := Value[n];
+ Inc(n);
+ if c = '-' then
+ Break;
+ if (c = '=') or (Pos(c, table) < 1) then
+ begin
+ Dec(n);
+ Break;
+ end;
+ s := s + c;
+ end;
+ if s = '' then
+ s := WriteMulti(Ord(shift), 0, 0, 0, 2, false)
+ else
+ begin
+ if modified then
+ t := DecodeBase64mod(s)
+ else
+ t := DecodeBase64(s);
+ if not odd(length(t)) then
+ s := t
+ else
+ begin //ill-formed sequence
+ t := s;
+ s := WriteMulti(Ord(shift), 0, 0, 0, 2, false);
+ for i := 1 to length(t) do
+ s := s + WriteMulti(Ord(t[i]), 0, 0, 0, 2, false);
+ end;
+ end;
+ Result := Result + s;
+ end;
+ end;
+end;
+
+{==============================================================================}
+function UCS2toUTF7(const Value: AnsiString; Modified: Boolean): AnsiString;
+var
+ s: AnsiString;
+ b1, b2, b3, b4: Byte;
+ n, m: Integer;
+ shift: AnsiChar;
+begin
+ Result := '';
+ n := 1;
+ if modified then
+ shift := '&'
+ else
+ shift := '+';
+ while Length(Value) >= n do
+ begin
+ ReadMulti(Value, n, 2, b1, b2, b3, b4, false);
+ if (b2 = 0) and (b1 < 128) then
+ if AnsiChar(b1) = shift then
+ Result := Result + shift + '-'
+ else
+ Result := Result + AnsiChar(b1)
+ else
+ begin
+ s := AnsiChar(b2) + AnsiChar(b1);
+ while Length(Value) >= n do
+ begin
+ ReadMulti(Value, n, 2, b1, b2, b3, b4, false);
+ if (b2 = 0) and (b1 < 128) then
+ begin
+ Dec(n, 2);
+ Break;
+ end;
+ s := s + AnsiChar(b2) + AnsiChar(b1);
+ end;
+ if modified then
+ s := EncodeBase64mod(s)
+ else
+ s := EncodeBase64(s);
+ m := Pos('=', s);
+ if m > 0 then
+ s := Copy(s, 1, m - 1);
+ Result := Result + shift + s + '-';
+ end;
+ end;
+end;
+
+{==============================================================================}
+function CharsetConversion(const Value: AnsiString; CharFrom: TMimeChar;
+ CharTo: TMimeChar): AnsiString;
+begin
+ Result := CharsetConversionEx(Value, CharFrom, CharTo, Replace_None);
+end;
+
+{==============================================================================}
+function CharsetConversionEx(const Value: AnsiString; CharFrom: TMimeChar;
+ CharTo: TMimeChar; const TransformTable: array of Word): AnsiString;
+begin
+ Result := CharsetConversionTrans(Value, CharFrom, CharTo, TransformTable, True);
+end;
+
+{==============================================================================}
+
+function InternalToUcs(const Value: AnsiString; Charfrom: TMimeChar): AnsiString;
+var
+ uni: Word;
+ n: Integer;
+ b1, b2, b3, b4: Byte;
+ SourceTable: array[128..255] of Word;
+ mbf: Byte;
+ lef: Boolean;
+ s: AnsiString;
+begin
+ if CharFrom = UTF_8 then
+ s := UTF8toUCS4(Value)
+ else
+ if CharFrom = UTF_7 then
+ s := UTF7toUCS2(Value, False)
+ else
+ if CharFrom = UTF_7mod then
+ s := UTF7toUCS2(Value, True)
+ else
+ s := Value;
+ GetArray(CharFrom, SourceTable);
+ mbf := 1;
+ if CharFrom in SetTwo then
+ mbf := 2;
+ if CharFrom in SetFour then
+ mbf := 4;
+ lef := CharFrom in SetLe;
+ Result := '';
+ n := 1;
+ while Length(s) >= n do
+ begin
+ ReadMulti(s, n, mbf, b1, b2, b3, b4, lef);
+ //handle BOM
+ if (b3 = 0) and (b4 = 0) then
+ begin
+ if (b1 = $FE) and (b2 = $FF) then
+ begin
+ lef := not lef;
+ continue;
+ end;
+ if (b1 = $FF) and (b2 = $FE) then
+ continue;
+ end;
+ if mbf = 1 then
+ if b1 > 127 then
+ begin
+ uni := SourceTable[b1];
+ b1 := Lo(uni);
+ b2 := Hi(uni);
+ end;
+ Result := Result + WriteMulti(b1, b2, b3, b4, 2, False);
+ end;
+end;
+
+function CharsetConversionTrans(Value: AnsiString; CharFrom: TMimeChar;
+ CharTo: TMimeChar; const TransformTable: array of Word; Translit: Boolean): AnsiString;
+var
+ uni: Word;
+ n, m: Integer;
+ b: Byte;
+ b1, b2, b3, b4: Byte;
+ TargetTable: array[128..255] of Word;
+ mbt: Byte;
+ let: Boolean;
+ ucsstring, s, t: AnsiString;
+ cd: iconv_t;
+ f: Boolean;
+ NotNeedTransform: Boolean;
+ FromID, ToID: string;
+begin
+ NotNeedTransform := (High(TransformTable) = 0);
+ if (CharFrom = CharTo) and NotNeedTransform then
+ begin
+ Result := Value;
+ Exit;
+ end;
+ FromID := GetIDFromCP(CharFrom);
+ ToID := GetIDFromCP(CharTo);
+ cd := Iconv_t(-1);
+ //do two-pass conversion. Transform to UCS-2 first.
+ if not DisableIconv then
+ cd := SynaIconvOpenIgnore('UCS-2BE', FromID);
+ try
+ if cd <> iconv_t(-1) then
+ SynaIconv(cd, Value, ucsstring)
+ else
+ ucsstring := InternalToUcs(Value, CharFrom);
+ finally
+ SynaIconvClose(cd);
+ end;
+ //here we allways have ucstring with UCS-2 encoding
+ //second pass... from UCS-2 to target encoding.
+ if not DisableIconv then
+ if translit then
+ cd := SynaIconvOpenTranslit(ToID, 'UCS-2BE')
+ else
+ cd := SynaIconvOpenIgnore(ToID, 'UCS-2BE');
+ try
+ if (cd <> iconv_t(-1)) and NotNeedTransform then
+ begin
+ if CharTo = UTF_7 then
+ ucsstring := ucsstring + #0 + '-';
+ //when transformtable is not needed and Iconv know target charset,
+ //do it fast by one call.
+ SynaIconv(cd, ucsstring, Result);
+ if CharTo = UTF_7 then
+ Delete(Result, Length(Result), 1);
+ end
+ else
+ begin
+ GetArray(CharTo, TargetTable);
+ mbt := 1;
+ if CharTo in SetTwo then
+ mbt := 2;
+ if CharTo in SetFour then
+ mbt := 4;
+ let := CharTo in SetLe;
+ b3 := 0;
+ b4 := 0;
+ Result := '';
+ for n:= 0 to (Length(ucsstring) div 2) - 1 do
+ begin
+ s := Copy(ucsstring, n * 2 + 1, 2);
+ b2 := Ord(s[1]);
+ b1 := Ord(s[2]);
+ uni := b2 * 256 + b1;
+ if not NotNeedTransform then
+ begin
+ uni := ReplaceUnicode(uni, TransformTable);
+ b1 := Lo(uni);
+ b2 := Hi(uni);
+ s[1] := AnsiChar(b2);
+ s[2] := AnsiChar(b1);
+ end;
+ if cd <> iconv_t(-1) then
+ begin
+ if CharTo = UTF_7 then
+ s := s + #0 + '-';
+ SynaIconv(cd, s, t);
+ if CharTo = UTF_7 then
+ Delete(t, Length(t), 1);
+ Result := Result + t;
+ end
+ else
+ begin
+ f := True;
+ if mbt = 1 then
+ if uni > 127 then
+ begin
+ f := False;
+ b := 0;
+ for m := 128 to 255 do
+ if TargetTable[m] = uni then
+ begin
+ b := m;
+ f := True;
+ Break;
+ end;
+ b1 := b;
+ b2 := 0;
+ end
+ else
+ b1 := Lo(uni);
+ if not f then
+ if translit then
+ begin
+ b1 := Ord(NotFoundChar);
+ b2 := 0;
+ f := True;
+ end;
+ if f then
+ Result := Result + WriteMulti(b1, b2, b3, b4, mbt, let)
+ end;
+ end;
+ if cd = iconv_t(-1) then
+ begin
+ if CharTo = UTF_7 then
+ Result := UCS2toUTF7(Result, false);
+ if CharTo = UTF_7mod then
+ Result := UCS2toUTF7(Result, true);
+ if CharTo = UTF_8 then
+ Result := UCS4toUTF8(Result);
+ end;
+ end;
+ finally
+ SynaIconvClose(cd);
+ end;
+end;
+
+{==============================================================================}
+{$IFNDEF WIN32}
+
+function GetCurCP: TMimeChar;
+begin
+ {$IFNDEF FPC}
+ Result := GetCPFromID(nl_langinfo(_NL_CTYPE_CODESET_NAME));
+ {$ELSE}
+ {$IFDEF FPC_USE_LIBC}
+ Result := GetCPFromID(nl_langinfo(_NL_CTYPE_CODESET_NAME));
+ {$ELSE}
+ //How to get system codepage without LIBC?
+ Result := UTF_8;
+ {$ENDIF}
+ {$ENDIF}
+end;
+
+function GetCurOEMCP: TMimeChar;
+begin
+ Result := GetCurCP;
+end;
+
+{$ELSE}
+
+function CPToMimeChar(Value: Integer): TMimeChar;
+begin
+ case Value of
+ 437, 850, 20127:
+ Result := ISO_8859_1; //I know, it is not ideal!
+ 737:
+ Result := CP737;
+ 775:
+ Result := CP775;
+ 852:
+ Result := CP852;
+ 855:
+ Result := CP855;
+ 857:
+ Result := CP857;
+ 858:
+ Result := CP858;
+ 860:
+ Result := CP860;
+ 861:
+ Result := CP861;
+ 862:
+ Result := CP862;
+ 863:
+ Result := CP863;
+ 864:
+ Result := CP864;
+ 865:
+ Result := CP865;
+ 866:
+ Result := CP866;
+ 869:
+ Result := CP869;
+ 874:
+ Result := ISO_8859_15;
+ 895:
+ Result := CP895;
+ 932:
+ Result := CP932;
+ 936:
+ Result := CP936;
+ 949:
+ Result := CP949;
+ 950:
+ Result := CP950;
+ 1200:
+ Result := UCS_2LE;
+ 1201:
+ Result := UCS_2;
+ 1250:
+ Result := CP1250;
+ 1251:
+ Result := CP1251;
+ 1253:
+ Result := CP1253;
+ 1254:
+ Result := CP1254;
+ 1255:
+ Result := CP1255;
+ 1256:
+ Result := CP1256;
+ 1257:
+ Result := CP1257;
+ 1258:
+ Result := CP1258;
+ 1361:
+ Result := CP1361;
+ 10000:
+ Result := MAC;
+ 10004:
+ Result := MACAR;
+ 10005:
+ Result := MACHEB;
+ 10006:
+ Result := MACGR;
+ 10007:
+ Result := MACCYR;
+ 10010:
+ Result := MACRO;
+ 10017:
+ Result := MACUK;
+ 10021:
+ Result := MACTH;
+ 10029:
+ Result := MACCE;
+ 10079:
+ Result := MACICE;
+ 10081:
+ Result := MACTU;
+ 10082:
+ Result := MACCRO;
+ 12000:
+ Result := UCS_4LE;
+ 12001:
+ Result := UCS_4;
+ 20866:
+ Result := KOI8_R;
+ 20932:
+ Result := JIS_X0208;
+ 20936:
+ Result := GB2312;
+ 21866:
+ Result := KOI8_U;
+ 28591:
+ Result := ISO_8859_1;
+ 28592:
+ Result := ISO_8859_2;
+ 28593:
+ Result := ISO_8859_3;
+ 28594:
+ Result := ISO_8859_4;
+ 28595:
+ Result := ISO_8859_5;
+ 28596, 708:
+ Result := ISO_8859_6;
+ 28597:
+ Result := ISO_8859_7;
+ 28598, 38598:
+ Result := ISO_8859_8;
+ 28599:
+ Result := ISO_8859_9;
+ 28605:
+ Result := ISO_8859_15;
+ 50220:
+ Result := ISO_2022_JP; //? ISO 2022 Japanese with no halfwidth Katakana
+ 50221:
+ Result := ISO_2022_JP1;//? Japanese with halfwidth Katakana
+ 50222:
+ Result := ISO_2022_JP2;//? Japanese JIS X 0201-1989
+ 50225:
+ Result := ISO_2022_KR;
+ 50227:
+ Result := ISO_2022_CN;//? ISO 2022 Simplified Chinese
+ 50229:
+ Result := ISO_2022_CNE;//? ISO 2022 Traditional Chinese
+ 51932:
+ Result := EUC_JP;
+ 51936:
+ Result := GB2312;
+ 51949:
+ Result := EUC_KR;
+ 52936:
+ Result := HZ;
+ 54936:
+ Result := GB18030;
+ 65000:
+ Result := UTF_7;
+ 65001:
+ Result := UTF_8;
+ 0:
+ Result := UCS_2LE;
+ else
+ Result := CP1252;
+ end;
+end;
+
+function GetCurCP: TMimeChar;
+begin
+ Result := CPToMimeChar(GetACP);
+end;
+
+function GetCurOEMCP: TMimeChar;
+begin
+ Result := CPToMimeChar(GetOEMCP);
+end;
+{$ENDIF}
+
+{==============================================================================}
+function NeedCharsetConversion(const Value: AnsiString): Boolean;
+var
+ n: Integer;
+begin
+ Result := False;
+ for n := 1 to Length(Value) do
+ if (Ord(Value[n]) > 127) or (Ord(Value[n]) = 0) then
+ begin
+ Result := True;
+ Break;
+ end;
+end;
+
+{==============================================================================}
+function IdealCharsetCoding(const Value: AnsiString; CharFrom: TMimeChar;
+ CharTo: TMimeSetChar): TMimeChar;
+var
+ n: Integer;
+ max: Integer;
+ s, t, u: AnsiString;
+ CharSet: TMimeChar;
+begin
+ Result := ISO_8859_1;
+ s := Copy(Value, 1, 1024); //max first 1KB for next procedure
+ max := 0;
+ for n := Ord(Low(TMimeChar)) to Ord(High(TMimeChar)) do
+ begin
+ CharSet := TMimeChar(n);
+ if CharSet in CharTo then
+ begin
+ t := CharsetConversionTrans(s, CharFrom, CharSet, Replace_None, False);
+ u := CharsetConversionTrans(t, CharSet, CharFrom, Replace_None, False);
+ if s = u then
+ begin
+ Result := CharSet;
+ Exit;
+ end;
+ if Length(u) > max then
+ begin
+ Result := CharSet;
+ max := Length(u);
+ end;
+ end;
+ end;
+end;
+
+{==============================================================================}
+function GetBOM(Value: TMimeChar): AnsiString;
+begin
+ Result := '';
+ case Value of
+ UCS_2:
+ Result := #$fe + #$ff;
+ UCS_4:
+ Result := #$00 + #$00 + #$fe + #$ff;
+ UCS_2LE:
+ Result := #$ff + #$fe;
+ UCS_4LE:
+ Result := #$ff + #$fe + #$00 + #$00;
+ UTF_8:
+ Result := #$ef + #$bb + #$bf;
+ end;
+end;
+
+{==============================================================================}
+function GetCPFromID(Value: AnsiString): TMimeChar;
+begin
+ Value := UpperCase(Value);
+ if (Pos('KAMENICKY', Value) > 0) or (Pos('895', Value) > 0) then
+ Result := CP895
+ else
+ if Pos('MUTF-7', Value) > 0 then
+ Result := UTF_7mod
+ else
+ Result := GetCPFromIconvID(Value);
+end;
+
+{==============================================================================}
+function GetIDFromCP(Value: TMimeChar): AnsiString;
+begin
+ case Value of
+ CP895:
+ Result := 'CP-895';
+ UTF_7mod:
+ Result := 'mUTF-7';
+ else
+ Result := GetIconvIDFromCP(Value);
+ end;
+end;
+
+{==============================================================================}
+function StringToWide(const Value: AnsiString): WideString;
+var
+ n: integer;
+ x, y: integer;
+begin
+ SetLength(Result, Length(Value) div 2);
+ for n := 1 to Length(Value) div 2 do
+ begin
+ x := Ord(Value[((n-1) * 2) + 1]);
+ y := Ord(Value[((n-1) * 2) + 2]);
+ Result[n] := WideChar(x * 256 + y);
+ end;
+end;
+
+{==============================================================================}
+function WideToString(const Value: WideString): AnsiString;
+var
+ n: integer;
+ x: integer;
+begin
+ SetLength(Result, Length(Value) * 2);
+ for n := 1 to Length(Value) do
+ begin
+ x := Ord(Value[n]);
+ Result[((n-1) * 2) + 1] := AnsiChar(x div 256);
+ Result[((n-1) * 2) + 2] := AnsiChar(x mod 256);
+ end;
+end;
+
+{==============================================================================}
+initialization
+begin
+ IconvArr[0].Charset := ISO_8859_1;
+ IconvArr[0].Charname := 'ISO-8859-1 CP819 IBM819 ISO-IR-100 ISO8859-1 ISO_8859-1 ISO_8859-1:1987 L1 LATIN1 CSISOLATIN1';
+ IconvArr[1].Charset := UTF_8;
+ IconvArr[1].Charname := 'UTF-8';
+ IconvArr[2].Charset := UCS_2;
+ IconvArr[2].Charname := 'ISO-10646-UCS-2 UCS-2 CSUNICODE';
+ IconvArr[3].Charset := UCS_2;
+ IconvArr[3].Charname := 'UCS-2BE UNICODE-1-1 UNICODEBIG CSUNICODE11';
+ IconvArr[4].Charset := UCS_2LE;
+ IconvArr[4].Charname := 'UCS-2LE UNICODELITTLE';
+ IconvArr[5].Charset := UCS_4;
+ IconvArr[5].Charname := 'ISO-10646-UCS-4 UCS-4 CSUCS4';
+ IconvArr[6].Charset := UCS_4;
+ IconvArr[6].Charname := 'UCS-4BE';
+ IconvArr[7].Charset := UCS_2LE;
+ IconvArr[7].Charname := 'UCS-4LE';
+ IconvArr[8].Charset := UTF_16;
+ IconvArr[8].Charname := 'UTF-16';
+ IconvArr[9].Charset := UTF_16;
+ IconvArr[9].Charname := 'UTF-16BE';
+ IconvArr[10].Charset := UTF_16LE;
+ IconvArr[10].Charname := 'UTF-16LE';
+ IconvArr[11].Charset := UTF_32;
+ IconvArr[11].Charname := 'UTF-32';
+ IconvArr[12].Charset := UTF_32;
+ IconvArr[12].Charname := 'UTF-32BE';
+ IconvArr[13].Charset := UTF_32;
+ IconvArr[13].Charname := 'UTF-32LE';
+ IconvArr[14].Charset := UTF_7;
+ IconvArr[14].Charname := 'UNICODE-1-1-UTF-7 UTF-7 CSUNICODE11UTF7';
+ IconvArr[15].Charset := C99;
+ IconvArr[15].Charname := 'C99';
+ IconvArr[16].Charset := JAVA;
+ IconvArr[16].Charname := 'JAVA';
+ IconvArr[17].Charset := ISO_8859_1;
+ IconvArr[17].Charname := 'US-ASCII ANSI_X3.4-1968 ANSI_X3.4-1986 ASCII CP367 IBM367 ISO-IR-6 ISO646-US ISO_646.IRV:1991 US CSASCII';
+ IconvArr[18].Charset := ISO_8859_2;
+ IconvArr[18].Charname := 'ISO-8859-2 ISO-IR-101 ISO8859-2 ISO_8859-2 ISO_8859-2:1987 L2 LATIN2 CSISOLATIN2';
+ IconvArr[19].Charset := ISO_8859_3;
+ IconvArr[19].Charname := 'ISO-8859-3 ISO-IR-109 ISO8859-3 ISO_8859-3 ISO_8859-3:1988 L3 LATIN3 CSISOLATIN3';
+ IconvArr[20].Charset := ISO_8859_4;
+ IconvArr[20].Charname := 'ISO-8859-4 ISO-IR-110 ISO8859-4 ISO_8859-4 ISO_8859-4:1988 L4 LATIN4 CSISOLATIN4';
+ IconvArr[21].Charset := ISO_8859_5;
+ IconvArr[21].Charname := 'ISO-8859-5 CYRILLIC ISO-IR-144 ISO8859-5 ISO_8859-5 ISO_8859-5:1988 CSISOLATINCYRILLIC';
+ IconvArr[22].Charset := ISO_8859_6;
+ IconvArr[22].Charname := 'ISO-8859-6 ARABIC ASMO-708 ECMA-114 ISO-IR-127 ISO8859-6 ISO_8859-6 ISO_8859-6:1987 CSISOLATINARABIC';
+ IconvArr[23].Charset := ISO_8859_7;
+ IconvArr[23].Charname := 'ISO-8859-7 ECMA-118 ELOT_928 GREEK GREEK8 ISO-IR-126 ISO8859-7 ISO_8859-7 ISO_8859-7:1987 CSISOLATINGREEK';
+ IconvArr[24].Charset := ISO_8859_8;
+ IconvArr[24].Charname := 'ISO-8859-8 HEBREW ISO_8859-8 ISO-IR-138 ISO8859-8 ISO_8859-8:1988 CSISOLATINHEBREW ISO-8859-8-I';
+ IconvArr[25].Charset := ISO_8859_9;
+ IconvArr[25].Charname := 'ISO-8859-9 ISO-IR-148 ISO8859-9 ISO_8859-9 ISO_8859-9:1989 L5 LATIN5 CSISOLATIN5';
+ IconvArr[26].Charset := ISO_8859_10;
+ IconvArr[26].Charname := 'ISO-8859-10 ISO-IR-157 ISO8859-10 ISO_8859-10 ISO_8859-10:1992 L6 LATIN6 CSISOLATIN6';
+ IconvArr[27].Charset := ISO_8859_13;
+ IconvArr[27].Charname := 'ISO-8859-13 ISO-IR-179 ISO8859-13 ISO_8859-13 L7 LATIN7';
+ IconvArr[28].Charset := ISO_8859_14;
+ IconvArr[28].Charname := 'ISO-8859-14 ISO-CELTIC ISO-IR-199 ISO8859-14 ISO_8859-14 ISO_8859-14:1998 L8 LATIN8';
+ IconvArr[29].Charset := ISO_8859_15;
+ IconvArr[29].Charname := 'ISO-8859-15 ISO-IR-203 ISO8859-15 ISO_8859-15 ISO_8859-15:1998';
+ IconvArr[30].Charset := ISO_8859_16;
+ IconvArr[30].Charname := 'ISO-8859-16 ISO-IR-226 ISO8859-16 ISO_8859-16 ISO_8859-16:2000';
+ IconvArr[31].Charset := KOI8_R;
+ IconvArr[31].Charname := 'KOI8-R CSKOI8R';
+ IconvArr[32].Charset := KOI8_U;
+ IconvArr[32].Charname := 'KOI8-U';
+ IconvArr[33].Charset := KOI8_RU;
+ IconvArr[33].Charname := 'KOI8-RU';
+ IconvArr[34].Charset := CP1250;
+ IconvArr[34].Charname := 'WINDOWS-1250 CP1250 MS-EE';
+ IconvArr[35].Charset := CP1251;
+ IconvArr[35].Charname := 'WINDOWS-1251 CP1251 MS-CYRL';
+ IconvArr[36].Charset := CP1252;
+ IconvArr[36].Charname := 'WINDOWS-1252 CP1252 MS-ANSI';
+ IconvArr[37].Charset := CP1253;
+ IconvArr[37].Charname := 'WINDOWS-1253 CP1253 MS-GREEK';
+ IconvArr[38].Charset := CP1254;
+ IconvArr[38].Charname := 'WINDOWS-1254 CP1254 MS-TURK';
+ IconvArr[39].Charset := CP1255;
+ IconvArr[39].Charname := 'WINDOWS-1255 CP1255 MS-HEBR';
+ IconvArr[40].Charset := CP1256;
+ IconvArr[40].Charname := 'WINDOWS-1256 CP1256 MS-ARAB';
+ IconvArr[41].Charset := CP1257;
+ IconvArr[41].Charname := 'WINDOWS-1257 CP1257 WINBALTRIM';
+ IconvArr[42].Charset := CP1258;
+ IconvArr[42].Charname := 'WINDOWS-1258 CP1258';
+ IconvArr[43].Charset := ISO_8859_1;
+ IconvArr[43].Charname := '850 CP850 IBM850 CSPC850MULTILINGUAL';
+ IconvArr[44].Charset := CP862;
+ IconvArr[44].Charname := '862 CP862 IBM862 CSPC862LATINHEBREW';
+ IconvArr[45].Charset := CP866;
+ IconvArr[45].Charname := '866 CP866 IBM866 CSIBM866';
+ IconvArr[46].Charset := MAC;
+ IconvArr[46].Charname := 'MAC MACINTOSH MACROMAN CSMACINTOSH';
+ IconvArr[47].Charset := MACCE;
+ IconvArr[47].Charname := 'MACCENTRALEUROPE';
+ IconvArr[48].Charset := MACICE;
+ IconvArr[48].Charname := 'MACICELAND';
+ IconvArr[49].Charset := MACCRO;
+ IconvArr[49].Charname := 'MACCROATIAN';
+ IconvArr[50].Charset := MACRO;
+ IconvArr[50].Charname := 'MACROMANIA';
+ IconvArr[51].Charset := MACCYR;
+ IconvArr[51].Charname := 'MACCYRILLIC';
+ IconvArr[52].Charset := MACUK;
+ IconvArr[52].Charname := 'MACUKRAINE';
+ IconvArr[53].Charset := MACGR;
+ IconvArr[53].Charname := 'MACGREEK';
+ IconvArr[54].Charset := MACTU;
+ IconvArr[54].Charname := 'MACTURKISH';
+ IconvArr[55].Charset := MACHEB;
+ IconvArr[55].Charname := 'MACHEBREW';
+ IconvArr[56].Charset := MACAR;
+ IconvArr[56].Charname := 'MACARABIC';
+ IconvArr[57].Charset := MACTH;
+ IconvArr[57].Charname := 'MACTHAI';
+ IconvArr[58].Charset := ROMAN8;
+ IconvArr[58].Charname := 'HP-ROMAN8 R8 ROMAN8 CSHPROMAN8';
+ IconvArr[59].Charset := NEXTSTEP;
+ IconvArr[59].Charname := 'NEXTSTEP';
+ IconvArr[60].Charset := ARMASCII;
+ IconvArr[60].Charname := 'ARMSCII-8';
+ IconvArr[61].Charset := GEORGIAN_AC;
+ IconvArr[61].Charname := 'GEORGIAN-ACADEMY';
+ IconvArr[62].Charset := GEORGIAN_PS;
+ IconvArr[62].Charname := 'GEORGIAN-PS';
+ IconvArr[63].Charset := KOI8_T;
+ IconvArr[63].Charname := 'KOI8-T';
+ IconvArr[64].Charset := MULELAO;
+ IconvArr[64].Charname := 'MULELAO-1';
+ IconvArr[65].Charset := CP1133;
+ IconvArr[65].Charname := 'CP1133 IBM-CP1133';
+ IconvArr[66].Charset := TIS620;
+ IconvArr[66].Charname := 'TIS-620 ISO-IR-166 TIS620 TIS620-0 TIS620.2529-1 TIS620.2533-0 TIS620.2533-1';
+ IconvArr[67].Charset := CP874;
+ IconvArr[67].Charname := 'CP874 WINDOWS-874';
+ IconvArr[68].Charset := VISCII;
+ IconvArr[68].Charname := 'VISCII VISCII1.1-1 CSVISCII';
+ IconvArr[69].Charset := TCVN;
+ IconvArr[69].Charname := 'TCVN TCVN-5712 TCVN5712-1 TCVN5712-1:1993';
+ IconvArr[70].Charset := ISO_IR_14;
+ IconvArr[70].Charname := 'ISO-IR-14 ISO646-JP JIS_C6220-1969-RO JP CSISO14JISC6220RO';
+ IconvArr[71].Charset := JIS_X0201;
+ IconvArr[71].Charname := 'JISX0201-1976 JIS_X0201 X0201 CSHALFWIDTHKATAKANA';
+ IconvArr[72].Charset := JIS_X0208;
+ IconvArr[72].Charname := 'ISO-IR-87 JIS0208 JIS_C6226-1983 JIS_X0208 JIS_X0208-1983 JIS_X0208-1990 X0208 CSISO87JISX0208';
+ IconvArr[73].Charset := JIS_X0212;
+ IconvArr[73].Charname := 'ISO-IR-159 JIS_X0212 JIS_X0212-1990 JIS_X0212.1990-0 X0212 CSISO159JISX02121990';
+ IconvArr[74].Charset := GB1988_80;
+ IconvArr[74].Charname := 'CN GB_1988-80 ISO-IR-57 ISO646-CN CSISO57GB1988';
+ IconvArr[75].Charset := GB2312_80;
+ IconvArr[75].Charname := 'CHINESE GB_2312-80 ISO-IR-58 CSISO58GB231280';
+ IconvArr[76].Charset := ISO_IR_165;
+ IconvArr[76].Charname := 'CN-GB-ISOIR165 ISO-IR-165';
+ IconvArr[77].Charset := ISO_IR_149;
+ IconvArr[77].Charname := 'ISO-IR-149 KOREAN KSC_5601 KS_C_5601-1987 KS_C_5601-1989 CSKSC56011987';
+ IconvArr[78].Charset := EUC_JP;
+ IconvArr[78].Charname := 'EUC-JP EUCJP EXTENDED_UNIX_CODE_PACKED_FORMAT_FOR_JAPANESE CSEUCPKDFMTJAPANESE';
+ IconvArr[79].Charset := SHIFT_JIS;
+ IconvArr[79].Charname := 'SHIFT-JIS MS_KANJI SHIFT_JIS SJIS CSSHIFTJIS';
+ IconvArr[80].Charset := CP932;
+ IconvArr[80].Charname := 'CP932';
+ IconvArr[81].Charset := ISO_2022_JP;
+ IconvArr[81].Charname := 'ISO-2022-JP CSISO2022JP';
+ IconvArr[82].Charset := ISO_2022_JP1;
+ IconvArr[82].Charname := 'ISO-2022-JP-1';
+ IconvArr[83].Charset := ISO_2022_JP2;
+ IconvArr[83].Charname := 'ISO-2022-JP-2 CSISO2022JP2';
+ IconvArr[84].Charset := GB2312;
+ IconvArr[84].Charname := 'CN-GB EUC-CN EUCCN GB2312 CSGB2312';
+ IconvArr[85].Charset := CP936;
+ IconvArr[85].Charname := 'CP936 GBK';
+ IconvArr[86].Charset := GB18030;
+ IconvArr[86].Charname := 'GB18030';
+ IconvArr[87].Charset := ISO_2022_CN;
+ IconvArr[87].Charname := 'ISO-2022-CN CSISO2022CN';
+ IconvArr[88].Charset := ISO_2022_CNE;
+ IconvArr[88].Charname := 'ISO-2022-CN-EXT';
+ IconvArr[89].Charset := HZ;
+ IconvArr[89].Charname := 'HZ HZ-GB-2312';
+ IconvArr[90].Charset := EUC_TW;
+ IconvArr[90].Charname := 'EUC-TW EUCTW CSEUCTW';
+ IconvArr[91].Charset := BIG5;
+ IconvArr[91].Charname := 'BIG5 BIG-5 BIG-FIVE BIGFIVE CN-BIG5 CSBIG5';
+ IconvArr[92].Charset := CP950;
+ IconvArr[92].Charname := 'CP950';
+ IconvArr[93].Charset := BIG5_HKSCS;
+ IconvArr[93].Charname := 'BIG5-HKSCS BIG5HKSCS';
+ IconvArr[94].Charset := EUC_KR;
+ IconvArr[94].Charname := 'EUC-KR EUCKR CSEUCKR';
+ IconvArr[95].Charset := CP949;
+ IconvArr[95].Charname := 'CP949 UHC';
+ IconvArr[96].Charset := CP1361;
+ IconvArr[96].Charname := 'CP1361 JOHAB';
+ IconvArr[97].Charset := ISO_2022_KR;
+ IconvArr[97].Charname := 'ISO-2022-KR CSISO2022KR';
+ IconvArr[98].Charset := ISO_8859_1;
+ IconvArr[98].Charname := '437 CP437 IBM437 CSPC8CODEPAGE437';
+ IconvArr[99].Charset := CP737;
+ IconvArr[99].Charname := 'CP737';
+ IconvArr[100].Charset := CP775;
+ IconvArr[100].Charname := 'CP775 IBM775 CSPC775BALTIC';
+ IconvArr[101].Charset := CP852;
+ IconvArr[101].Charname := '852 CP852 IBM852 CSPCP852';
+ IconvArr[102].Charset := CP853;
+ IconvArr[102].Charname := 'CP853';
+ IconvArr[103].Charset := CP855;
+ IconvArr[103].Charname := '855 CP855 IBM855 CSIBM855';
+ IconvArr[104].Charset := CP857;
+ IconvArr[104].Charname := '857 CP857 IBM857 CSIBM857';
+ IconvArr[105].Charset := CP858;
+ IconvArr[105].Charname := 'CP858';
+ IconvArr[106].Charset := CP860;
+ IconvArr[106].Charname := '860 CP860 IBM860 CSIBM860';
+ IconvArr[107].Charset := CP861;
+ IconvArr[107].Charname := '861 CP-IS CP861 IBM861 CSIBM861';
+ IconvArr[108].Charset := CP863;
+ IconvArr[108].Charname := '863 CP863 IBM863 CSIBM863';
+ IconvArr[109].Charset := CP864;
+ IconvArr[109].Charname := 'CP864 IBM864 CSIBM864';
+ IconvArr[110].Charset := CP865;
+ IconvArr[110].Charname := '865 CP865 IBM865 CSIBM865';
+ IconvArr[111].Charset := CP869;
+ IconvArr[111].Charname := '869 CP-GR CP869 IBM869 CSIBM869';
+ IconvArr[112].Charset := CP1125;
+ IconvArr[112].Charname := 'CP1125';
+end;
+
+end.
diff --git a/branches/script-component/Units/Synapse/synacode.pas b/branches/script-component/Units/Synapse/synacode.pas
new file mode 100644
index 0000000..f183c8c
--- /dev/null
+++ b/branches/script-component/Units/Synapse/synacode.pas
@@ -0,0 +1,1454 @@
+{==============================================================================|
+| Project : Ararat Synapse | 002.002.000 |
+|==============================================================================|
+| Content: Coding and decoding support |
+|==============================================================================|
+| Copyright (c)1999-2007, Lukas Gebauer |
+| All rights reserved. |
+| |
+| Redistribution and use in source and binary forms, with or without |
+| modification, are permitted provided that the following conditions are met: |
+| |
+| Redistributions of source code must retain the above copyright notice, this |
+| list of conditions and the following disclaimer. |
+| |
+| Redistributions in binary form must reproduce the above copyright notice, |
+| this list of conditions and the following disclaimer in the documentation |
+| and/or other materials provided with the distribution. |
+| |
+| Neither the name of Lukas Gebauer nor the names of its contributors may |
+| be used to endorse or promote products derived from this software without |
+| specific prior written permission. |
+| |
+| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
+| AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
+| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
+| ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR |
+| ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
+| DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
+| SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
+| CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
+| LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
+| OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
+| DAMAGE. |
+|==============================================================================|
+| The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).|
+| Portions created by Lukas Gebauer are Copyright (c)2000-2007. |
+| All Rights Reserved. |
+|==============================================================================|
+| Contributor(s): |
+|==============================================================================|
+| History: see HISTORY.HTM from distribution package |
+| (Found at URL: http://www.ararat.cz/synapse/) |
+|==============================================================================}
+
+{:@abstract(Various encoding and decoding support)}
+{$IFDEF FPC}
+ {$MODE DELPHI}
+{$ENDIF}
+{$Q-}
+{$R-}
+{$H+}
+
+unit synacode;
+
+interface
+
+uses
+ SysUtils;
+
+type
+ TSpecials = set of AnsiChar;
+
+const
+
+ SpecialChar: TSpecials =
+ ['=', '(', ')', '[', ']', '<', '>', ':', ';', ',', '@', '/', '?', '\',
+ '"', '_'];
+ NonAsciiChar: TSpecials =
+ [Char(0)..Char(31), Char(127)..Char(255)];
+ URLFullSpecialChar: TSpecials =
+ [';', '/', '?', ':', '@', '=', '&', '#', '+'];
+ URLSpecialChar: TSpecials =
+ [#$00..#$20, '_', '<', '>', '"', '%', '{', '}', '|', '\', '^', '~', '[', ']',
+ '`', #$7F..#$FF];
+ TableBase64 =
+ 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
+ TableBase64mod =
+ 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,=';
+ TableUU =
+ '`!"#$%&''()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_';
+ TableXX =
+ '+-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
+ ReTablebase64 =
+ #$40 +#$40 +#$40 +#$40 +#$40 +#$40 +#$40 +#$40 +#$40 +#$40 +#$3E +#$40
+ +#$40 +#$40 +#$3F +#$34 +#$35 +#$36 +#$37 +#$38 +#$39 +#$3A +#$3B +#$3C
+ +#$3D +#$40 +#$40 +#$40 +#$40 +#$40 +#$40 +#$40 +#$00 +#$01 +#$02 +#$03
+ +#$04 +#$05 +#$06 +#$07 +#$08 +#$09 +#$0A +#$0B +#$0C +#$0D +#$0E +#$0F
+ +#$10 +#$11 +#$12 +#$13 +#$14 +#$15 +#$16 +#$17 +#$18 +#$19 +#$40 +#$40
+ +#$40 +#$40 +#$40 +#$40 +#$1A +#$1B +#$1C +#$1D +#$1E +#$1F +#$20 +#$21
+ +#$22 +#$23 +#$24 +#$25 +#$26 +#$27 +#$28 +#$29 +#$2A +#$2B +#$2C +#$2D
+ +#$2E +#$2F +#$30 +#$31 +#$32 +#$33 +#$40 +#$40 +#$40 +#$40 +#$40 +#$40;
+ ReTableUU =
+ #$01 +#$02 +#$03 +#$04 +#$05 +#$06 +#$07 +#$08 +#$09 +#$0A +#$0B +#$0C
+ +#$0D +#$0E +#$0F +#$10 +#$11 +#$12 +#$13 +#$14 +#$15 +#$16 +#$17 +#$18
+ +#$19 +#$1A +#$1B +#$1C +#$1D +#$1E +#$1F +#$20 +#$21 +#$22 +#$23 +#$24
+ +#$25 +#$26 +#$27 +#$28 +#$29 +#$2A +#$2B +#$2C +#$2D +#$2E +#$2F +#$30
+ +#$31 +#$32 +#$33 +#$34 +#$35 +#$36 +#$37 +#$38 +#$39 +#$3A +#$3B +#$3C
+ +#$3D +#$3E +#$3F +#$00 +#$40 +#$40 +#$40 +#$40 +#$40 +#$40 +#$40 +#$40
+ +#$40 +#$40 +#$40 +#$40 +#$40 +#$40 +#$40 +#$40 +#$40 +#$40 +#$40 +#$40
+ +#$40 +#$40 +#$40 +#$40 +#$40 +#$40 +#$40 +#$40 +#$40 +#$40 +#$40 +#$40;
+ ReTableXX =
+ #$40 +#$40 +#$40 +#$40 +#$40 +#$40 +#$40 +#$40 +#$40 +#$40 +#$00 +#$40
+ +#$01 +#$40 +#$40 +#$02 +#$03 +#$04 +#$05 +#$06 +#$07 +#$08 +#$09 +#$0A
+ +#$0B +#$40 +#$40 +#$40 +#$40 +#$40 +#$40 +#$40 +#$0C +#$0D +#$0E +#$0F
+ +#$10 +#$11 +#$12 +#$13 +#$14 +#$15 +#$16 +#$17 +#$18 +#$19 +#$1A +#$1B
+ +#$1C +#$1D +#$1E +#$1F +#$20 +#$21 +#$22 +#$23 +#$24 +#$25 +#$40 +#$40
+ +#$40 +#$40 +#$40 +#$40 +#$26 +#$27 +#$28 +#$29 +#$2A +#$2B +#$2C +#$2D
+ +#$2E +#$2F +#$30 +#$31 +#$32 +#$33 +#$34 +#$35 +#$36 +#$37 +#$38 +#$39
+ +#$3A +#$3B +#$3C +#$3D +#$3E +#$3F +#$40 +#$40 +#$40 +#$40 +#$40 +#$40;
+
+{:Decodes triplet encoding with a given character delimiter. It is used for
+ decoding quoted-printable or URL encoding.}
+function DecodeTriplet(const Value: AnsiString; Delimiter: AnsiChar): AnsiString;
+
+{:Decodes a string from quoted printable form. (also decodes triplet sequences
+ like '=7F')}
+function DecodeQuotedPrintable(const Value: AnsiString): AnsiString;
+
+{:Decodes a string of URL encoding. (also decodes triplet sequences like '%7F')}
+function DecodeURL(const Value: AnsiString): AnsiString;
+
+{:Performs triplet encoding with a given character delimiter. Used for encoding
+ quoted-printable or URL encoding.}
+function EncodeTriplet(const Value: AnsiString; Delimiter: AnsiChar;
+ Specials: TSpecials): AnsiString;
+
+{:Encodes a string to triplet quoted printable form. All @link(NonAsciiChar)
+ are encoded.}
+function EncodeQuotedPrintable(const Value: AnsiString): AnsiString;
+
+{:Encodes a string to triplet quoted printable form. All @link(NonAsciiChar) and
+ @link(SpecialChar) are encoded.}
+function EncodeSafeQuotedPrintable(const Value: AnsiString): AnsiString;
+
+{:Encodes a string to URL format. Used for encoding data from a form field in
+ HTTP, etc. (Encodes all critical characters including characters used as URL
+ delimiters ('/',':', etc.)}
+function EncodeURLElement(const Value: AnsiString): AnsiString;
+
+{:Encodes a string to URL format. Used to encode critical characters in all
+ URLs.}
+function EncodeURL(const Value: AnsiString): AnsiString;
+
+{:Decode 4to3 encoding with given table. If some element is not found in table,
+ first item from table is used. This is good for buggy coded items by Microsoft
+ Outlook. This software sometimes using wrong table for UUcode, where is used
+ ' ' instead '`'.}
+function Decode4to3(const Value, Table: AnsiString): AnsiString;
+
+{:Decode 4to3 encoding with given REVERSE table. Using this function with
+reverse table is much faster then @link(Decode4to3). This function is used
+internally for Base64, UU or XX decoding.}
+function Decode4to3Ex(const Value, Table: AnsiString): AnsiString;
+
+{:Encode by system 3to4 (used by Base64, UU coding, etc) by given table.}
+function Encode3to4(const Value, Table: AnsiString): AnsiString;
+
+{:Decode string from base64 format.}
+function DecodeBase64(const Value: AnsiString): AnsiString;
+
+{:Encodes a string to base64 format.}
+function EncodeBase64(const Value: AnsiString): AnsiString;
+
+{:Decode string from modified base64 format. (used in IMAP, for example.)}
+function DecodeBase64mod(const Value: AnsiString): AnsiString;
+
+{:Encodes a string to modified base64 format. (used in IMAP, for example.)}
+function EncodeBase64mod(const Value: AnsiString): AnsiString;
+
+{:Decodes a string from UUcode format.}
+function DecodeUU(const Value: AnsiString): AnsiString;
+
+{:encode UUcode. it encode only datas, you must also add header and footer for
+ proper encode.}
+function EncodeUU(const Value: AnsiString): AnsiString;
+
+{:Decodes a string from XXcode format.}
+function DecodeXX(const Value: AnsiString): AnsiString;
+
+{:decode line with Yenc code. This code is sometimes used in newsgroups.}
+function DecodeYEnc(const Value: AnsiString): AnsiString;
+
+{:Returns a new CRC32 value after adding a new byte of data.}
+function UpdateCrc32(Value: Byte; Crc32: Integer): Integer;
+
+{:return CRC32 from a value string.}
+function Crc32(const Value: AnsiString): Integer;
+
+{:Returns a new CRC16 value after adding a new byte of data.}
+function UpdateCrc16(Value: Byte; Crc16: Word): Word;
+
+{:return CRC16 from a value string.}
+function Crc16(const Value: AnsiString): Word;
+
+{:Returns a binary string with a RSA-MD5 hashing of "Value" string.}
+function MD5(const Value: AnsiString): AnsiString;
+
+{:Returns a binary string with HMAC-MD5 hash.}
+function HMAC_MD5(Text, Key: AnsiString): AnsiString;
+
+{:Returns a binary string with a RSA-MD5 hashing of string what is constructed
+ by repeating "value" until length is "Len".}
+function MD5LongHash(const Value: AnsiString; Len: integer): AnsiString;
+
+{:Returns a binary string with a SHA-1 hashing of "Value" string.}
+function SHA1(const Value: AnsiString): AnsiString;
+
+{:Returns a binary string with HMAC-SHA1 hash.}
+function HMAC_SHA1(Text, Key: AnsiString): AnsiString;
+
+{:Returns a binary string with a SHA-1 hashing of string what is constructed
+ by repeating "value" until length is "Len".}
+function SHA1LongHash(const Value: AnsiString; Len: integer): AnsiString;
+
+{:Returns a binary string with a RSA-MD4 hashing of "Value" string.}
+function MD4(const Value: AnsiString): AnsiString;
+
+implementation
+
+const
+
+ Crc32Tab: array[0..255] of Integer = (
+ Integer($00000000), Integer($77073096), Integer($EE0E612C), Integer($990951BA),
+ Integer($076DC419), Integer($706AF48F), Integer($E963A535), Integer($9E6495A3),
+ Integer($0EDB8832), Integer($79DCB8A4), Integer($E0D5E91E), Integer($97D2D988),
+ Integer($09B64C2B), Integer($7EB17CBD), Integer($E7B82D07), Integer($90BF1D91),
+ Integer($1DB71064), Integer($6AB020F2), Integer($F3B97148), Integer($84BE41DE),
+ Integer($1ADAD47D), Integer($6DDDE4EB), Integer($F4D4B551), Integer($83D385C7),
+ Integer($136C9856), Integer($646BA8C0), Integer($FD62F97A), Integer($8A65C9EC),
+ Integer($14015C4F), Integer($63066CD9), Integer($FA0F3D63), Integer($8D080DF5),
+ Integer($3B6E20C8), Integer($4C69105E), Integer($D56041E4), Integer($A2677172),
+ Integer($3C03E4D1), Integer($4B04D447), Integer($D20D85FD), Integer($A50AB56B),
+ Integer($35B5A8FA), Integer($42B2986C), Integer($DBBBC9D6), Integer($ACBCF940),
+ Integer($32D86CE3), Integer($45DF5C75), Integer($DCD60DCF), Integer($ABD13D59),
+ Integer($26D930AC), Integer($51DE003A), Integer($C8D75180), Integer($BFD06116),
+ Integer($21B4F4B5), Integer($56B3C423), Integer($CFBA9599), Integer($B8BDA50F),
+ Integer($2802B89E), Integer($5F058808), Integer($C60CD9B2), Integer($B10BE924),
+ Integer($2F6F7C87), Integer($58684C11), Integer($C1611DAB), Integer($B6662D3D),
+ Integer($76DC4190), Integer($01DB7106), Integer($98D220BC), Integer($EFD5102A),
+ Integer($71B18589), Integer($06B6B51F), Integer($9FBFE4A5), Integer($E8B8D433),
+ Integer($7807C9A2), Integer($0F00F934), Integer($9609A88E), Integer($E10E9818),
+ Integer($7F6A0DBB), Integer($086D3D2D), Integer($91646C97), Integer($E6635C01),
+ Integer($6B6B51F4), Integer($1C6C6162), Integer($856530D8), Integer($F262004E),
+ Integer($6C0695ED), Integer($1B01A57B), Integer($8208F4C1), Integer($F50FC457),
+ Integer($65B0D9C6), Integer($12B7E950), Integer($8BBEB8EA), Integer($FCB9887C),
+ Integer($62DD1DDF), Integer($15DA2D49), Integer($8CD37CF3), Integer($FBD44C65),
+ Integer($4DB26158), Integer($3AB551CE), Integer($A3BC0074), Integer($D4BB30E2),
+ Integer($4ADFA541), Integer($3DD895D7), Integer($A4D1C46D), Integer($D3D6F4FB),
+ Integer($4369E96A), Integer($346ED9FC), Integer($AD678846), Integer($DA60B8D0),
+ Integer($44042D73), Integer($33031DE5), Integer($AA0A4C5F), Integer($DD0D7CC9),
+ Integer($5005713C), Integer($270241AA), Integer($BE0B1010), Integer($C90C2086),
+ Integer($5768B525), Integer($206F85B3), Integer($B966D409), Integer($CE61E49F),
+ Integer($5EDEF90E), Integer($29D9C998), Integer($B0D09822), Integer($C7D7A8B4),
+ Integer($59B33D17), Integer($2EB40D81), Integer($B7BD5C3B), Integer($C0BA6CAD),
+ Integer($EDB88320), Integer($9ABFB3B6), Integer($03B6E20C), Integer($74B1D29A),
+ Integer($EAD54739), Integer($9DD277AF), Integer($04DB2615), Integer($73DC1683),
+ Integer($E3630B12), Integer($94643B84), Integer($0D6D6A3E), Integer($7A6A5AA8),
+ Integer($E40ECF0B), Integer($9309FF9D), Integer($0A00AE27), Integer($7D079EB1),
+ Integer($F00F9344), Integer($8708A3D2), Integer($1E01F268), Integer($6906C2FE),
+ Integer($F762575D), Integer($806567CB), Integer($196C3671), Integer($6E6B06E7),
+ Integer($FED41B76), Integer($89D32BE0), Integer($10DA7A5A), Integer($67DD4ACC),
+ Integer($F9B9DF6F), Integer($8EBEEFF9), Integer($17B7BE43), Integer($60B08ED5),
+ Integer($D6D6A3E8), Integer($A1D1937E), Integer($38D8C2C4), Integer($4FDFF252),
+ Integer($D1BB67F1), Integer($A6BC5767), Integer($3FB506DD), Integer($48B2364B),
+ Integer($D80D2BDA), Integer($AF0A1B4C), Integer($36034AF6), Integer($41047A60),
+ Integer($DF60EFC3), Integer($A867DF55), Integer($316E8EEF), Integer($4669BE79),
+ Integer($CB61B38C), Integer($BC66831A), Integer($256FD2A0), Integer($5268E236),
+ Integer($CC0C7795), Integer($BB0B4703), Integer($220216B9), Integer($5505262F),
+ Integer($C5BA3BBE), Integer($B2BD0B28), Integer($2BB45A92), Integer($5CB36A04),
+ Integer($C2D7FFA7), Integer($B5D0CF31), Integer($2CD99E8B), Integer($5BDEAE1D),
+ Integer($9B64C2B0), Integer($EC63F226), Integer($756AA39C), Integer($026D930A),
+ Integer($9C0906A9), Integer($EB0E363F), Integer($72076785), Integer($05005713),
+ Integer($95BF4A82), Integer($E2B87A14), Integer($7BB12BAE), Integer($0CB61B38),
+ Integer($92D28E9B), Integer($E5D5BE0D), Integer($7CDCEFB7), Integer($0BDBDF21),
+ Integer($86D3D2D4), Integer($F1D4E242), Integer($68DDB3F8), Integer($1FDA836E),
+ Integer($81BE16CD), Integer($F6B9265B), Integer($6FB077E1), Integer($18B74777),
+ Integer($88085AE6), Integer($FF0F6A70), Integer($66063BCA), Integer($11010B5C),
+ Integer($8F659EFF), Integer($F862AE69), Integer($616BFFD3), Integer($166CCF45),
+ Integer($A00AE278), Integer($D70DD2EE), Integer($4E048354), Integer($3903B3C2),
+ Integer($A7672661), Integer($D06016F7), Integer($4969474D), Integer($3E6E77DB),
+ Integer($AED16A4A), Integer($D9D65ADC), Integer($40DF0B66), Integer($37D83BF0),
+ Integer($A9BCAE53), Integer($DEBB9EC5), Integer($47B2CF7F), Integer($30B5FFE9),
+ Integer($BDBDF21C), Integer($CABAC28A), Integer($53B39330), Integer($24B4A3A6),
+ Integer($BAD03605), Integer($CDD70693), Integer($54DE5729), Integer($23D967BF),
+ Integer($B3667A2E), Integer($C4614AB8), Integer($5D681B02), Integer($2A6F2B94),
+ Integer($B40BBE37), Integer($C30C8EA1), Integer($5A05DF1B), Integer($2D02EF8D)
+ );
+
+ Crc16Tab: array[0..255] of Word = (
+ $0000, $1189, $2312, $329B, $4624, $57AD, $6536, $74BF,
+ $8C48, $9DC1, $AF5A, $BED3, $CA6C, $DBE5, $E97E, $F8F7,
+ $1081, $0108, $3393, $221A, $56A5, $472C, $75B7, $643E,
+ $9CC9, $8D40, $BFDB, $AE52, $DAED, $CB64, $F9FF, $E876,
+ $2102, $308B, $0210, $1399, $6726, $76AF, $4434, $55BD,
+ $AD4A, $BCC3, $8E58, $9FD1, $EB6E, $FAE7, $C87C, $D9F5,
+ $3183, $200A, $1291, $0318, $77A7, $662E, $54B5, $453C,
+ $BDCB, $AC42, $9ED9, $8F50, $FBEF, $EA66, $D8FD, $C974,
+ $4204, $538D, $6116, $709F, $0420, $15A9, $2732, $36BB,
+ $CE4C, $DFC5, $ED5E, $FCD7, $8868, $99E1, $AB7A, $BAF3,
+ $5285, $430C, $7197, $601E, $14A1, $0528, $37B3, $263A,
+ $DECD, $CF44, $FDDF, $EC56, $98E9, $8960, $BBFB, $AA72,
+ $6306, $728F, $4014, $519D, $2522, $34AB, $0630, $17B9,
+ $EF4E, $FEC7, $CC5C, $DDD5, $A96A, $B8E3, $8A78, $9BF1,
+ $7387, $620E, $5095, $411C, $35A3, $242A, $16B1, $0738,
+ $FFCF, $EE46, $DCDD, $CD54, $B9EB, $A862, $9AF9, $8B70,
+ $8408, $9581, $A71A, $B693, $C22C, $D3A5, $E13E, $F0B7,
+ $0840, $19C9, $2B52, $3ADB, $4E64, $5FED, $6D76, $7CFF,
+ $9489, $8500, $B79B, $A612, $D2AD, $C324, $F1BF, $E036,
+ $18C1, $0948, $3BD3, $2A5A, $5EE5, $4F6C, $7DF7, $6C7E,
+ $A50A, $B483, $8618, $9791, $E32E, $F2A7, $C03C, $D1B5,
+ $2942, $38CB, $0A50, $1BD9, $6F66, $7EEF, $4C74, $5DFD,
+ $B58B, $A402, $9699, $8710, $F3AF, $E226, $D0BD, $C134,
+ $39C3, $284A, $1AD1, $0B58, $7FE7, $6E6E, $5CF5, $4D7C,
+ $C60C, $D785, $E51E, $F497, $8028, $91A1, $A33A, $B2B3,
+ $4A44, $5BCD, $6956, $78DF, $0C60, $1DE9, $2F72, $3EFB,
+ $D68D, $C704, $F59F, $E416, $90A9, $8120, $B3BB, $A232,
+ $5AC5, $4B4C, $79D7, $685E, $1CE1, $0D68, $3FF3, $2E7A,
+ $E70E, $F687, $C41C, $D595, $A12A, $B0A3, $8238, $93B1,
+ $6B46, $7ACF, $4854, $59DD, $2D62, $3CEB, $0E70, $1FF9,
+ $F78F, $E606, $D49D, $C514, $B1AB, $A022, $92B9, $8330,
+ $7BC7, $6A4E, $58D5, $495C, $3DE3, $2C6A, $1EF1, $0F78
+ );
+
+procedure ArrByteToLong(var ArByte: Array of byte; var ArLong: Array of Integer);
+{$IFDEF CIL}
+var
+ n: integer;
+{$ENDIF}
+begin
+ if (High(ArByte) + 1) > ((High(ArLong) + 1) * 4) then
+ Exit;
+ {$IFDEF CIL}
+ for n := 0 to ((high(ArByte) + 1) div 4) - 1 do
+ ArLong[n] := ArByte[n * 4 + 0]
+ + (ArByte[n * 4 + 1] shl 8)
+ + (ArByte[n * 4 + 2] shl 16)
+ + (ArByte[n * 4 + 3] shl 24);
+ {$ELSE}
+ Move(ArByte[0], ArLong[0], High(ArByte) + 1);
+ {$ENDIF}
+end;
+
+procedure ArrLongToByte(var ArLong: Array of Integer; var ArByte: Array of byte);
+{$IFDEF CIL}
+var
+ n: integer;
+{$ENDIF}
+begin
+ if (High(ArByte) + 1) < ((High(ArLong) + 1) * 4) then
+ Exit;
+ {$IFDEF CIL}
+ for n := 0 to high(ArLong) do
+ begin
+ ArByte[n * 4 + 0] := ArLong[n] and $000000FF;
+ ArByte[n * 4 + 1] := (ArLong[n] shr 8) and $000000FF;
+ ArByte[n * 4 + 2] := (ArLong[n] shr 16) and $000000FF;
+ ArByte[n * 4 + 3] := (ArLong[n] shr 24) and $000000FF;
+ end;
+ {$ELSE}
+ Move(ArLong[0], ArByte[0], High(ArByte) + 1);
+ {$ENDIF}
+end;
+
+type
+ TMDCtx = record
+ State: array[0..3] of Integer;
+ Count: array[0..1] of Integer;
+ BufAnsiChar: array[0..63] of Byte;
+ BufLong: array[0..15] of Integer;
+ end;
+ TSHA1Ctx= record
+ Hi, Lo: integer;
+ Buffer: array[0..63] of byte;
+ Index: integer;
+ Hash: array[0..4] of Integer;
+ HashByte: array[0..19] of byte;
+ end;
+
+ TMDTransform = procedure(var Buf: array of LongInt; const Data: array of LongInt);
+
+{==============================================================================}
+
+function DecodeTriplet(const Value: AnsiString; Delimiter: AnsiChar): AnsiString;
+var
+ x, l, lv: Integer;
+ c: AnsiChar;
+ b: Byte;
+ bad: Boolean;
+begin
+ lv := Length(Value);
+ SetLength(Result, lv);
+ x := 1;
+ l := 1;
+ while x <= lv do
+ begin
+ c := Value[x];
+ Inc(x);
+ if c <> Delimiter then
+ begin
+ Result[l] := c;
+ Inc(l);
+ end
+ else
+ if x < lv then
+ begin
+ Case Value[x] Of
+ #13:
+ if (Value[x + 1] = #10) then
+ Inc(x, 2)
+ else
+ Inc(x);
+ #10:
+ if (Value[x + 1] = #13) then
+ Inc(x, 2)
+ else
+ Inc(x);
+ else
+ begin
+ bad := False;
+ Case Value[x] Of
+ '0'..'9': b := (Byte(Value[x]) - 48) Shl 4;
+ 'a'..'f', 'A'..'F': b := ((Byte(Value[x]) And 7) + 9) shl 4;
+ else
+ begin
+ b := 0;
+ bad := True;
+ end;
+ end;
+ Case Value[x + 1] Of
+ '0'..'9': b := b Or (Byte(Value[x + 1]) - 48);
+ 'a'..'f', 'A'..'F': b := b Or ((Byte(Value[x + 1]) And 7) + 9);
+ else
+ bad := True;
+ end;
+ if bad then
+ begin
+ Result[l] := c;
+ Inc(l);
+ end
+ else
+ begin
+ Inc(x, 2);
+ Result[l] := AnsiChar(b);
+ Inc(l);
+ end;
+ end;
+ end;
+ end
+ else
+ break;
+ end;
+ Dec(l);
+ SetLength(Result, l);
+end;
+
+{==============================================================================}
+
+function DecodeQuotedPrintable(const Value: AnsiString): AnsiString;
+begin
+ Result := DecodeTriplet(Value, '=');
+end;
+
+{==============================================================================}
+
+function DecodeURL(const Value: AnsiString): AnsiString;
+begin
+ Result := DecodeTriplet(Value, '%');
+end;
+
+{==============================================================================}
+
+function EncodeTriplet(const Value: AnsiString; Delimiter: AnsiChar;
+ Specials: TSpecials): AnsiString;
+var
+ n, l: Integer;
+ s: AnsiString;
+ c: AnsiChar;
+begin
+ SetLength(Result, Length(Value) * 3);
+ l := 1;
+ for n := 1 to Length(Value) do
+ begin
+ c := Value[n];
+ if c in Specials then
+ begin
+ Result[l] := Delimiter;
+ Inc(l);
+ s := IntToHex(Ord(c), 2);
+ Result[l] := s[1];
+ Inc(l);
+ Result[l] := s[2];
+ Inc(l);
+ end
+ else
+ begin
+ Result[l] := c;
+ Inc(l);
+ end;
+ end;
+ Dec(l);
+ SetLength(Result, l);
+end;
+
+{==============================================================================}
+
+function EncodeQuotedPrintable(const Value: AnsiString): AnsiString;
+begin
+ Result := EncodeTriplet(Value, '=', ['='] + NonAsciiChar);
+end;
+
+{==============================================================================}
+
+function EncodeSafeQuotedPrintable(const Value: AnsiString): AnsiString;
+begin
+ Result := EncodeTriplet(Value, '=', SpecialChar + NonAsciiChar);
+end;
+
+{==============================================================================}
+
+function EncodeURLElement(const Value: AnsiString): AnsiString;
+begin
+ Result := EncodeTriplet(Value, '%', URLSpecialChar + URLFullSpecialChar);
+end;
+
+{==============================================================================}
+
+function EncodeURL(const Value: AnsiString): AnsiString;
+begin
+ Result := EncodeTriplet(Value, '%', URLSpecialChar);
+end;
+
+{==============================================================================}
+
+function Decode4to3(const Value, Table: AnsiString): AnsiString;
+var
+ x, y, n, l: Integer;
+ d: array[0..3] of Byte;
+begin
+ SetLength(Result, Length(Value));
+ x := 1;
+ l := 1;
+ while x <= Length(Value) do
+ begin
+ for n := 0 to 3 do
+ begin
+ if x > Length(Value) then
+ d[n] := 64
+ else
+ begin
+ y := Pos(Value[x], Table);
+ if y < 1 then
+ y := 1;
+ d[n] := y - 1;
+ end;
+ Inc(x);
+ end;
+ Result[l] := AnsiChar((D[0] and $3F) shl 2 + (D[1] and $30) shr 4);
+ Inc(l);
+ if d[2] <> 64 then
+ begin
+ Result[l] := AnsiChar((D[1] and $0F) shl 4 + (D[2] and $3C) shr 2);
+ Inc(l);
+ if d[3] <> 64 then
+ begin
+ Result[l] := AnsiChar((D[2] and $03) shl 6 + (D[3] and $3F));
+ Inc(l);
+ end;
+ end;
+ end;
+ Dec(l);
+ SetLength(Result, l);
+end;
+
+{==============================================================================}
+function Decode4to3Ex(const Value, Table: AnsiString): AnsiString;
+var
+ x, y, lv: Integer;
+ d: integer;
+ dl: integer;
+ c: byte;
+ p: integer;
+begin
+ lv := Length(Value);
+ SetLength(Result, lv);
+ x := 1;
+ dl := 4;
+ d := 0;
+ p := 1;
+ while x <= lv do
+ begin
+ y := Ord(Value[x]);
+ if y in [33..127] then
+ c := Ord(Table[y - 32])
+ else
+ c := 64;
+ Inc(x);
+ if c > 63 then
+ continue;
+ d := (d shl 6) or c;
+ dec(dl);
+ if dl <> 0 then
+ continue;
+ Result[p] := AnsiChar((d shr 16) and $ff);
+ inc(p);
+ Result[p] := AnsiChar((d shr 8) and $ff);
+ inc(p);
+ Result[p] := AnsiChar(d and $ff);
+ inc(p);
+ d := 0;
+ dl := 4;
+ end;
+ case dl of
+ 1:
+ begin
+ d := d shr 2;
+ Result[p] := AnsiChar((d shr 8) and $ff);
+ inc(p);
+ Result[p] := AnsiChar(d and $ff);
+ inc(p);
+ end;
+ 2:
+ begin
+ d := d shr 4;
+ Result[p] := AnsiChar(d and $ff);
+ inc(p);
+ end;
+ end;
+ SetLength(Result, p - 1);
+end;
+
+{==============================================================================}
+
+function Encode3to4(const Value, Table: AnsiString): AnsiString;
+var
+ c: Byte;
+ n, l: Integer;
+ Count: Integer;
+ DOut: array[0..3] of Byte;
+begin
+ setlength(Result, ((Length(Value) + 2) div 3) * 4);
+ l := 1;
+ Count := 1;
+ while Count <= Length(Value) do
+ begin
+ c := Ord(Value[Count]);
+ Inc(Count);
+ DOut[0] := (c and $FC) shr 2;
+ DOut[1] := (c and $03) shl 4;
+ if Count <= Length(Value) then
+ begin
+ c := Ord(Value[Count]);
+ Inc(Count);
+ DOut[1] := DOut[1] + (c and $F0) shr 4;
+ DOut[2] := (c and $0F) shl 2;
+ if Count <= Length(Value) then
+ begin
+ c := Ord(Value[Count]);
+ Inc(Count);
+ DOut[2] := DOut[2] + (c and $C0) shr 6;
+ DOut[3] := (c and $3F);
+ end
+ else
+ begin
+ DOut[3] := $40;
+ end;
+ end
+ else
+ begin
+ DOut[2] := $40;
+ DOut[3] := $40;
+ end;
+ for n := 0 to 3 do
+ begin
+ if (DOut[n] + 1) <= Length(Table) then
+ begin
+ Result[l] := Table[DOut[n] + 1];
+ Inc(l);
+ end;
+ end;
+ end;
+ SetLength(Result, l - 1);
+end;
+
+{==============================================================================}
+
+function DecodeBase64(const Value: AnsiString): AnsiString;
+begin
+ Result := Decode4to3Ex(Value, ReTableBase64);
+end;
+
+{==============================================================================}
+
+function EncodeBase64(const Value: AnsiString): AnsiString;
+begin
+ Result := Encode3to4(Value, TableBase64);
+end;
+
+{==============================================================================}
+
+function DecodeBase64mod(const Value: AnsiString): AnsiString;
+begin
+ Result := Decode4to3(Value, TableBase64mod);
+end;
+
+{==============================================================================}
+
+function EncodeBase64mod(const Value: AnsiString): AnsiString;
+begin
+ Result := Encode3to4(Value, TableBase64mod);
+end;
+
+{==============================================================================}
+
+function DecodeUU(const Value: AnsiString): AnsiString;
+var
+ s: AnsiString;
+ uut: AnsiString;
+ x: Integer;
+begin
+ Result := '';
+ uut := TableUU;
+ s := trim(UpperCase(Value));
+ if s = '' then Exit;
+ if Pos('BEGIN', s) = 1 then
+ Exit;
+ if Pos('END', s) = 1 then
+ Exit;
+ if Pos('TABLE', s) = 1 then
+ Exit; //ignore Table yet (set custom UUT)
+ //begin decoding
+ x := Pos(Value[1], uut) - 1;
+ case (x mod 3) of
+ 0: x :=(x div 3)* 4;
+ 1: x :=((x div 3) * 4) + 2;
+ 2: x :=((x div 3) * 4) + 3;
+ end;
+ //x - lenght UU line
+ s := Copy(Value, 2, x);
+ if s = '' then
+ Exit;
+ s := s + StringOfChar(' ', x - length(s));
+ Result := Decode4to3(s, uut);
+end;
+
+{==============================================================================}
+
+function EncodeUU(const Value: AnsiString): AnsiString;
+begin
+ Result := '';
+ if Length(Value) < Length(TableUU) then
+ Result := TableUU[Length(Value) + 1] + Encode3to4(Value, TableUU);
+end;
+
+{==============================================================================}
+
+function DecodeXX(const Value: AnsiString): AnsiString;
+var
+ s: AnsiString;
+ x: Integer;
+begin
+ Result := '';
+ s := trim(UpperCase(Value));
+ if s = '' then
+ Exit;
+ if Pos('BEGIN', s) = 1 then
+ Exit;
+ if Pos('END', s) = 1 then
+ Exit;
+ //begin decoding
+ x := Pos(Value[1], TableXX) - 1;
+ case (x mod 3) of
+ 0: x :=(x div 3)* 4;
+ 1: x :=((x div 3) * 4) + 2;
+ 2: x :=((x div 3) * 4) + 3;
+ end;
+ //x - lenght XX line
+ s := Copy(Value, 2, x);
+ if s = '' then
+ Exit;
+ s := s + StringOfChar(' ', x - length(s));
+ Result := Decode4to3(s, TableXX);
+end;
+
+{==============================================================================}
+
+function DecodeYEnc(const Value: AnsiString): AnsiString;
+var
+ C : Byte;
+ i: integer;
+begin
+ Result := '';
+ i := 1;
+ while i <= Length(Value) do
+ begin
+ c := Ord(Value[i]);
+ Inc(i);
+ if c = Ord('=') then
+ begin
+ c := Ord(Value[i]);
+ Inc(i);
+ Dec(c, 64);
+ end;
+ Dec(C, 42);
+ Result := Result + AnsiChar(C);
+ end;
+end;
+
+{==============================================================================}
+
+function UpdateCrc32(Value: Byte; Crc32: Integer): Integer;
+begin
+ Result := (Crc32 shr 8)
+ xor crc32tab[Byte(Value xor (Crc32 and Integer($000000FF)))];
+end;
+
+{==============================================================================}
+
+function Crc32(const Value: AnsiString): Integer;
+var
+ n: Integer;
+begin
+ Result := Integer($FFFFFFFF);
+ for n := 1 to Length(Value) do
+ Result := UpdateCrc32(Ord(Value[n]), Result);
+ Result := not Result;
+end;
+
+{==============================================================================}
+
+function UpdateCrc16(Value: Byte; Crc16: Word): Word;
+begin
+ Result := ((Crc16 shr 8) and $00FF) xor
+ crc16tab[Byte(Crc16 xor (Word(Value)) and $00FF)];
+end;
+
+{==============================================================================}
+
+function Crc16(const Value: AnsiString): Word;
+var
+ n: Integer;
+begin
+ Result := $FFFF;
+ for n := 1 to Length(Value) do
+ Result := UpdateCrc16(Ord(Value[n]), Result);
+end;
+
+{==============================================================================}
+
+procedure MDInit(var MDContext: TMDCtx);
+var
+ n: integer;
+begin
+ MDContext.Count[0] := 0;
+ MDContext.Count[1] := 0;
+ for n := 0 to high(MDContext.BufAnsiChar) do
+ MDContext.BufAnsiChar[n] := 0;
+ for n := 0 to high(MDContext.BufLong) do
+ MDContext.BufLong[n] := 0;
+ MDContext.State[0] := Integer($67452301);
+ MDContext.State[1] := Integer($EFCDAB89);
+ MDContext.State[2] := Integer($98BADCFE);
+ MDContext.State[3] := Integer($10325476);
+end;
+
+procedure MD5Transform(var Buf: array of LongInt; const Data: array of LongInt);
+var
+ A, B, C, D: LongInt;
+
+ procedure Round1(var W: LongInt; X, Y, Z, Data: LongInt; S: Byte);
+ begin
+ Inc(W, (Z xor (X and (Y xor Z))) + Data);
+ W := (W shl S) or (W shr (32 - S));
+ Inc(W, X);
+ end;
+
+ procedure Round2(var W: LongInt; X, Y, Z, Data: LongInt; S: Byte);
+ begin
+ Inc(W, (Y xor (Z and (X xor Y))) + Data);
+ W := (W shl S) or (W shr (32 - S));
+ Inc(W, X);
+ end;
+
+ procedure Round3(var W: LongInt; X, Y, Z, Data: LongInt; S: Byte);
+ begin
+ Inc(W, (X xor Y xor Z) + Data);
+ W := (W shl S) or (W shr (32 - S));
+ Inc(W, X);
+ end;
+
+ procedure Round4(var W: LongInt; X, Y, Z, Data: LongInt; S: Byte);
+ begin
+ Inc(W, (Y xor (X or not Z)) + Data);
+ W := (W shl S) or (W shr (32 - S));
+ Inc(W, X);
+ end;
+begin
+ A := Buf[0];
+ B := Buf[1];
+ C := Buf[2];
+ D := Buf[3];
+
+ Round1(A, B, C, D, Data[0] + Longint($D76AA478), 7);
+ Round1(D, A, B, C, Data[1] + Longint($E8C7B756), 12);
+ Round1(C, D, A, B, Data[2] + Longint($242070DB), 17);
+ Round1(B, C, D, A, Data[3] + Longint($C1BDCEEE), 22);
+ Round1(A, B, C, D, Data[4] + Longint($F57C0FAF), 7);
+ Round1(D, A, B, C, Data[5] + Longint($4787C62A), 12);
+ Round1(C, D, A, B, Data[6] + Longint($A8304613), 17);
+ Round1(B, C, D, A, Data[7] + Longint($FD469501), 22);
+ Round1(A, B, C, D, Data[8] + Longint($698098D8), 7);
+ Round1(D, A, B, C, Data[9] + Longint($8B44F7AF), 12);
+ Round1(C, D, A, B, Data[10] + Longint($FFFF5BB1), 17);
+ Round1(B, C, D, A, Data[11] + Longint($895CD7BE), 22);
+ Round1(A, B, C, D, Data[12] + Longint($6B901122), 7);
+ Round1(D, A, B, C, Data[13] + Longint($FD987193), 12);
+ Round1(C, D, A, B, Data[14] + Longint($A679438E), 17);
+ Round1(B, C, D, A, Data[15] + Longint($49B40821), 22);
+
+ Round2(A, B, C, D, Data[1] + Longint($F61E2562), 5);
+ Round2(D, A, B, C, Data[6] + Longint($C040B340), 9);
+ Round2(C, D, A, B, Data[11] + Longint($265E5A51), 14);
+ Round2(B, C, D, A, Data[0] + Longint($E9B6C7AA), 20);
+ Round2(A, B, C, D, Data[5] + Longint($D62F105D), 5);
+ Round2(D, A, B, C, Data[10] + Longint($02441453), 9);
+ Round2(C, D, A, B, Data[15] + Longint($D8A1E681), 14);
+ Round2(B, C, D, A, Data[4] + Longint($E7D3FBC8), 20);
+ Round2(A, B, C, D, Data[9] + Longint($21E1CDE6), 5);
+ Round2(D, A, B, C, Data[14] + Longint($C33707D6), 9);
+ Round2(C, D, A, B, Data[3] + Longint($F4D50D87), 14);
+ Round2(B, C, D, A, Data[8] + Longint($455A14ED), 20);
+ Round2(A, B, C, D, Data[13] + Longint($A9E3E905), 5);
+ Round2(D, A, B, C, Data[2] + Longint($FCEFA3F8), 9);
+ Round2(C, D, A, B, Data[7] + Longint($676F02D9), 14);
+ Round2(B, C, D, A, Data[12] + Longint($8D2A4C8A), 20);
+
+ Round3(A, B, C, D, Data[5] + Longint($FFFA3942), 4);
+ Round3(D, A, B, C, Data[8] + Longint($8771F681), 11);
+ Round3(C, D, A, B, Data[11] + Longint($6D9D6122), 16);
+ Round3(B, C, D, A, Data[14] + Longint($FDE5380C), 23);
+ Round3(A, B, C, D, Data[1] + Longint($A4BEEA44), 4);
+ Round3(D, A, B, C, Data[4] + Longint($4BDECFA9), 11);
+ Round3(C, D, A, B, Data[7] + Longint($F6BB4B60), 16);
+ Round3(B, C, D, A, Data[10] + Longint($BEBFBC70), 23);
+ Round3(A, B, C, D, Data[13] + Longint($289B7EC6), 4);
+ Round3(D, A, B, C, Data[0] + Longint($EAA127FA), 11);
+ Round3(C, D, A, B, Data[3] + Longint($D4EF3085), 16);
+ Round3(B, C, D, A, Data[6] + Longint($04881D05), 23);
+ Round3(A, B, C, D, Data[9] + Longint($D9D4D039), 4);
+ Round3(D, A, B, C, Data[12] + Longint($E6DB99E5), 11);
+ Round3(C, D, A, B, Data[15] + Longint($1FA27CF8), 16);
+ Round3(B, C, D, A, Data[2] + Longint($C4AC5665), 23);
+
+ Round4(A, B, C, D, Data[0] + Longint($F4292244), 6);
+ Round4(D, A, B, C, Data[7] + Longint($432AFF97), 10);
+ Round4(C, D, A, B, Data[14] + Longint($AB9423A7), 15);
+ Round4(B, C, D, A, Data[5] + Longint($FC93A039), 21);
+ Round4(A, B, C, D, Data[12] + Longint($655B59C3), 6);
+ Round4(D, A, B, C, Data[3] + Longint($8F0CCC92), 10);
+ Round4(C, D, A, B, Data[10] + Longint($FFEFF47D), 15);
+ Round4(B, C, D, A, Data[1] + Longint($85845DD1), 21);
+ Round4(A, B, C, D, Data[8] + Longint($6FA87E4F), 6);
+ Round4(D, A, B, C, Data[15] + Longint($FE2CE6E0), 10);
+ Round4(C, D, A, B, Data[6] + Longint($A3014314), 15);
+ Round4(B, C, D, A, Data[13] + Longint($4E0811A1), 21);
+ Round4(A, B, C, D, Data[4] + Longint($F7537E82), 6);
+ Round4(D, A, B, C, Data[11] + Longint($BD3AF235), 10);
+ Round4(C, D, A, B, Data[2] + Longint($2AD7D2BB), 15);
+ Round4(B, C, D, A, Data[9] + Longint($EB86D391), 21);
+
+ Inc(Buf[0], A);
+ Inc(Buf[1], B);
+ Inc(Buf[2], C);
+ Inc(Buf[3], D);
+end;
+
+//fixed by James McAdams
+procedure MDUpdate(var MDContext: TMDCtx; const Data: AnsiString; transform: TMDTransform);
+var
+ Index, partLen, InputLen, I: integer;
+{$IFDEF CIL}
+ n: integer;
+{$ENDIF}
+begin
+ InputLen := Length(Data);
+ with MDContext do
+ begin
+ Index := (Count[0] shr 3) and $3F;
+ Inc(Count[0], InputLen shl 3);
+ if Count[0] < (InputLen shl 3) then
+ Inc(Count[1]);
+ Inc(Count[1], InputLen shr 29);
+ partLen := 64 - Index;
+ if InputLen >= partLen then
+ begin
+ ArrLongToByte(BufLong, BufAnsiChar);
+ {$IFDEF CIL}
+ for n := 1 to partLen do
+ BufAnsiChar[index - 1 + n] := Ord(Data[n]);
+ {$ELSE}
+ Move(Data[1], BufAnsiChar[Index], partLen);
+ {$ENDIF}
+ ArrByteToLong(BufAnsiChar, BufLong);
+ Transform(State, Buflong);
+ I := partLen;
+ while I + 63 < InputLen do
+ begin
+ ArrLongToByte(BufLong, BufAnsiChar);
+ {$IFDEF CIL}
+ for n := 1 to 64 do
+ BufAnsiChar[n - 1] := Ord(Data[i + n]);
+ {$ELSE}
+ Move(Data[I+1], BufAnsiChar, 64);
+ {$ENDIF}
+ ArrByteToLong(BufAnsiChar, BufLong);
+ Transform(State, Buflong);
+ inc(I, 64);
+ end;
+ Index := 0;
+ end
+ else
+ I := 0;
+ ArrLongToByte(BufLong, BufAnsiChar);
+ {$IFDEF CIL}
+ for n := 1 to InputLen-I do
+ BufAnsiChar[Index + n - 1] := Ord(Data[i + n]);
+ {$ELSE}
+ Move(Data[I+1], BufAnsiChar[Index], InputLen-I);
+ {$ENDIF}
+ ArrByteToLong(BufAnsiChar, BufLong);
+ end
+end;
+
+function MDFinal(var MDContext: TMDCtx; transform: TMDTransform): AnsiString;
+var
+ Cnt: Word;
+ P: Byte;
+ digest: array[0..15] of Byte;
+ i: Integer;
+ n: integer;
+begin
+ for I := 0 to 15 do
+ Digest[I] := I + 1;
+ with MDContext do
+ begin
+ Cnt := (Count[0] shr 3) and $3F;
+ P := Cnt;
+ BufAnsiChar[P] := $80;
+ Inc(P);
+ Cnt := 64 - 1 - Cnt;
+ if Cnt < 8 then
+ begin
+ for n := 0 to cnt - 1 do
+ BufAnsiChar[P + n] := 0;
+ ArrByteToLong(BufAnsiChar, BufLong);
+// FillChar(BufAnsiChar[P], Cnt, #0);
+ Transform(State, BufLong);
+ ArrLongToByte(BufLong, BufAnsiChar);
+ for n := 0 to 55 do
+ BufAnsiChar[n] := 0;
+ ArrByteToLong(BufAnsiChar, BufLong);
+// FillChar(BufAnsiChar, 56, #0);
+ end
+ else
+ begin
+ for n := 0 to Cnt - 8 - 1 do
+ BufAnsiChar[p + n] := 0;
+ ArrByteToLong(BufAnsiChar, BufLong);
+// FillChar(BufAnsiChar[P], Cnt - 8, #0);
+ end;
+ BufLong[14] := Count[0];
+ BufLong[15] := Count[1];
+ Transform(State, BufLong);
+ ArrLongToByte(State, Digest);
+// Move(State, Digest, 16);
+ Result := '';
+ for i := 0 to 15 do
+ Result := Result + AnsiChar(digest[i]);
+ end;
+// FillChar(MD5Context, SizeOf(TMD5Ctx), #0)
+end;
+
+{==============================================================================}
+
+function MD5(const Value: AnsiString): AnsiString;
+var
+ MDContext: TMDCtx;
+begin
+ MDInit(MDContext);
+ MDUpdate(MDContext, Value, @MD5Transform);
+ Result := MDFinal(MDContext, @MD5Transform);
+end;
+
+{==============================================================================}
+
+function HMAC_MD5(Text, Key: AnsiString): AnsiString;
+var
+ ipad, opad, s: AnsiString;
+ n: Integer;
+ MDContext: TMDCtx;
+begin
+ if Length(Key) > 64 then
+ Key := md5(Key);
+ ipad := StringOfChar(#$36, 64);
+ opad := StringOfChar(#$5C, 64);
+ for n := 1 to Length(Key) do
+ begin
+ ipad[n] := AnsiChar(Byte(ipad[n]) xor Byte(Key[n]));
+ opad[n] := AnsiChar(Byte(opad[n]) xor Byte(Key[n]));
+ end;
+ MDInit(MDContext);
+ MDUpdate(MDContext, ipad, @MD5Transform);
+ MDUpdate(MDContext, Text, @MD5Transform);
+ s := MDFinal(MDContext, @MD5Transform);
+ MDInit(MDContext);
+ MDUpdate(MDContext, opad, @MD5Transform);
+ MDUpdate(MDContext, s, @MD5Transform);
+ Result := MDFinal(MDContext, @MD5Transform);
+end;
+
+{==============================================================================}
+
+function MD5LongHash(const Value: AnsiString; Len: integer): AnsiString;
+var
+ cnt, rest: integer;
+ l: integer;
+ n: integer;
+ MDContext: TMDCtx;
+begin
+ l := length(Value);
+ cnt := Len div l;
+ rest := Len mod l;
+ MDInit(MDContext);
+ for n := 1 to cnt do
+ MDUpdate(MDContext, Value, @MD5Transform);
+ if rest > 0 then
+ MDUpdate(MDContext, Copy(Value, 1, rest), @MD5Transform);
+ Result := MDFinal(MDContext, @MD5Transform);
+end;
+
+{==============================================================================}
+// SHA1 is based on sources by Dave Barton (davebarton@bigfoot.com)
+
+procedure SHA1init( var SHA1Context: TSHA1Ctx );
+var
+ n: integer;
+begin
+ SHA1Context.Hi := 0;
+ SHA1Context.Lo := 0;
+ SHA1Context.Index := 0;
+ for n := 0 to High(SHA1Context.Buffer) do
+ SHA1Context.Buffer[n] := 0;
+ for n := 0 to High(SHA1Context.HashByte) do
+ SHA1Context.HashByte[n] := 0;
+// FillChar(SHA1Context, SizeOf(TSHA1Ctx), #0);
+ SHA1Context.Hash[0] := integer($67452301);
+ SHA1Context.Hash[1] := integer($EFCDAB89);
+ SHA1Context.Hash[2] := integer($98BADCFE);
+ SHA1Context.Hash[3] := integer($10325476);
+ SHA1Context.Hash[4] := integer($C3D2E1F0);
+end;
+
+//******************************************************************************
+function RB(A: integer): integer;
+begin
+ Result := (A shr 24) or ((A shr 8) and $FF00) or ((A shl 8) and $FF0000) or (A shl 24);
+end;
+
+procedure SHA1Compress(var Data: TSHA1Ctx);
+var
+ A, B, C, D, E, T: integer;
+ W: array[0..79] of integer;
+ i: integer;
+ n: integer;
+
+ function F1(x, y, z: integer): integer;
+ begin
+ Result := z xor (x and (y xor z));
+ end;
+ function F2(x, y, z: integer): integer;
+ begin
+ Result := x xor y xor z;
+ end;
+ function F3(x, y, z: integer): integer;
+ begin
+ Result := (x and y) or (z and (x or y));
+ end;
+ function LRot32(X: integer; c: integer): integer;
+ begin
+ result := (x shl c) or (x shr (32 - c));
+ end;
+begin
+ ArrByteToLong(Data.Buffer, W);
+// Move(Data.Buffer, W, Sizeof(Data.Buffer));
+ for i := 0 to 15 do
+ W[i] := RB(W[i]);
+ for i := 16 to 79 do
+ W[i] := LRot32(W[i-3] xor W[i-8] xor W[i-14] xor W[i-16], 1);
+ A := Data.Hash[0];
+ B := Data.Hash[1];
+ C := Data.Hash[2];
+ D := Data.Hash[3];
+ E := Data.Hash[4];
+ for i := 0 to 19 do
+ begin
+ T := LRot32(A, 5) + F1(B, C, D) + E + W[i] + integer($5A827999);
+ E := D;
+ D := C;
+ C := LRot32(B, 30);
+ B := A;
+ A := T;
+ end;
+ for i := 20 to 39 do
+ begin
+ T := LRot32(A, 5) + F2(B, C, D) + E + W[i] + integer($6ED9EBA1);
+ E := D;
+ D := C;
+ C := LRot32(B, 30);
+ B := A;
+ A := T;
+ end;
+ for i := 40 to 59 do
+ begin
+ T := LRot32(A, 5) + F3(B, C, D) + E + W[i] + integer($8F1BBCDC);
+ E := D;
+ D := C;
+ C := LRot32(B, 30);
+ B := A;
+ A := T;
+ end;
+ for i := 60 to 79 do
+ begin
+ T := LRot32(A, 5) + F2(B, C, D) + E + W[i] + integer($CA62C1D6);
+ E := D;
+ D := C;
+ C := LRot32(B, 30);
+ B := A;
+ A := T;
+ end;
+ Data.Hash[0] := Data.Hash[0] + A;
+ Data.Hash[1] := Data.Hash[1] + B;
+ Data.Hash[2] := Data.Hash[2] + C;
+ Data.Hash[3] := Data.Hash[3] + D;
+ Data.Hash[4] := Data.Hash[4] + E;
+ for n := 0 to high(w) do
+ w[n] := 0;
+// FillChar(W, Sizeof(W), 0);
+ for n := 0 to high(Data.Buffer) do
+ Data.Buffer[n] := 0;
+// FillChar(Data.Buffer, Sizeof(Data.Buffer), 0);
+end;
+
+//******************************************************************************
+procedure SHA1Update(var Context: TSHA1Ctx; const Data: AnsiString);
+var
+ Len: integer;
+ n: integer;
+ i, k: integer;
+begin
+ Len := Length(data);
+ for k := 0 to 7 do
+ begin
+ i := Context.Lo;
+ Inc(Context.Lo, Len);
+ if Context.Lo < i then
+ Inc(Context.Hi);
+ end;
+ for n := 1 to len do
+ begin
+ Context.Buffer[Context.Index] := byte(Data[n]);
+ Inc(Context.Index);
+ if Context.Index = 64 then
+ begin
+ Context.Index := 0;
+ SHA1Compress(Context);
+ end;
+ end;
+end;
+
+//******************************************************************************
+function SHA1Final(var Context: TSHA1Ctx): AnsiString;
+type
+ Pinteger = ^integer;
+var
+ i: integer;
+ procedure ItoArr(var Ar: Array of byte; I, value: Integer);
+ begin
+ Ar[i + 0] := Value and $000000FF;
+ Ar[i + 1] := (Value shr 8) and $000000FF;
+ Ar[i + 2] := (Value shr 16) and $000000FF;
+ Ar[i + 3] := (Value shr 24) and $000000FF;
+ end;
+begin
+ Context.Buffer[Context.Index] := $80;
+ if Context.Index >= 56 then
+ SHA1Compress(Context);
+ ItoArr(Context.Buffer, 56, RB(Context.Hi));
+ ItoArr(Context.Buffer, 60, RB(Context.Lo));
+// Pinteger(@Context.Buffer[56])^ := RB(Context.Hi);
+// Pinteger(@Context.Buffer[60])^ := RB(Context.Lo);
+ SHA1Compress(Context);
+ Context.Hash[0] := RB(Context.Hash[0]);
+ Context.Hash[1] := RB(Context.Hash[1]);
+ Context.Hash[2] := RB(Context.Hash[2]);
+ Context.Hash[3] := RB(Context.Hash[3]);
+ Context.Hash[4] := RB(Context.Hash[4]);
+ ArrLongToByte(Context.Hash, Context.HashByte);
+ Result := '';
+ for i := 0 to 19 do
+ Result := Result + AnsiChar(Context.HashByte[i]);
+end;
+
+function SHA1(const Value: AnsiString): AnsiString;
+var
+ SHA1Context: TSHA1Ctx;
+begin
+ SHA1Init(SHA1Context);
+ SHA1Update(SHA1Context, Value);
+ Result := SHA1Final(SHA1Context);
+end;
+
+{==============================================================================}
+
+function HMAC_SHA1(Text, Key: AnsiString): AnsiString;
+var
+ ipad, opad, s: AnsiString;
+ n: Integer;
+ SHA1Context: TSHA1Ctx;
+begin
+ if Length(Key) > 64 then
+ Key := SHA1(Key);
+ ipad := StringOfChar(#$36, 64);
+ opad := StringOfChar(#$5C, 64);
+ for n := 1 to Length(Key) do
+ begin
+ ipad[n] := AnsiChar(Byte(ipad[n]) xor Byte(Key[n]));
+ opad[n] := AnsiChar(Byte(opad[n]) xor Byte(Key[n]));
+ end;
+ SHA1Init(SHA1Context);
+ SHA1Update(SHA1Context, ipad);
+ SHA1Update(SHA1Context, Text);
+ s := SHA1Final(SHA1Context);
+ SHA1Init(SHA1Context);
+ SHA1Update(SHA1Context, opad);
+ SHA1Update(SHA1Context, s);
+ Result := SHA1Final(SHA1Context);
+end;
+
+{==============================================================================}
+
+function SHA1LongHash(const Value: AnsiString; Len: integer): AnsiString;
+var
+ cnt, rest: integer;
+ l: integer;
+ n: integer;
+ SHA1Context: TSHA1Ctx;
+begin
+ l := length(Value);
+ cnt := Len div l;
+ rest := Len mod l;
+ SHA1Init(SHA1Context);
+ for n := 1 to cnt do
+ SHA1Update(SHA1Context, Value);
+ if rest > 0 then
+ SHA1Update(SHA1Context, Copy(Value, 1, rest));
+ Result := SHA1Final(SHA1Context);
+end;
+
+{==============================================================================}
+
+procedure MD4Transform(var Buf: array of LongInt; const Data: array of LongInt);
+var
+ A, B, C, D: LongInt;
+ function LRot32(a, b: longint): longint;
+ begin
+ Result:= (a shl b) or (a shr (32 - b));
+ end;
+begin
+ A := Buf[0];
+ B := Buf[1];
+ C := Buf[2];
+ D := Buf[3];
+
+ A:= LRot32(A + (D xor (B and (C xor D))) + Data[ 0], 3);
+ D:= LRot32(D + (C xor (A and (B xor C))) + Data[ 1], 7);
+ C:= LRot32(C + (B xor (D and (A xor B))) + Data[ 2], 11);
+ B:= LRot32(B + (A xor (C and (D xor A))) + Data[ 3], 19);
+ A:= LRot32(A + (D xor (B and (C xor D))) + Data[ 4], 3);
+ D:= LRot32(D + (C xor (A and (B xor C))) + Data[ 5], 7);
+ C:= LRot32(C + (B xor (D and (A xor B))) + Data[ 6], 11);
+ B:= LRot32(B + (A xor (C and (D xor A))) + Data[ 7], 19);
+ A:= LRot32(A + (D xor (B and (C xor D))) + Data[ 8], 3);
+ D:= LRot32(D + (C xor (A and (B xor C))) + Data[ 9], 7);
+ C:= LRot32(C + (B xor (D and (A xor B))) + Data[10], 11);
+ B:= LRot32(B + (A xor (C and (D xor A))) + Data[11], 19);
+ A:= LRot32(A + (D xor (B and (C xor D))) + Data[12], 3);
+ D:= LRot32(D + (C xor (A and (B xor C))) + Data[13], 7);
+ C:= LRot32(C + (B xor (D and (A xor B))) + Data[14], 11);
+ B:= LRot32(B + (A xor (C and (D xor A))) + Data[15], 19);
+
+ A:= LRot32(A + ((B and C) or (B and D) or (C and D)) + Data[ 0] + longint($5a827999), 3);
+ D:= LRot32(D + ((A and B) or (A and C) or (B and C)) + Data[ 4] + longint($5a827999), 5);
+ C:= LRot32(C + ((D and A) or (D and B) or (A and B)) + Data[ 8] + longint($5a827999), 9);
+ B:= LRot32(B + ((C and D) or (C and A) or (D and A)) + Data[12] + longint($5a827999), 13);
+ A:= LRot32(A + ((B and C) or (B and D) or (C and D)) + Data[ 1] + longint($5a827999), 3);
+ D:= LRot32(D + ((A and B) or (A and C) or (B and C)) + Data[ 5] + longint($5a827999), 5);
+ C:= LRot32(C + ((D and A) or (D and B) or (A and B)) + Data[ 9] + longint($5a827999), 9);
+ B:= LRot32(B + ((C and D) or (C and A) or (D and A)) + Data[13] + longint($5a827999), 13);
+ A:= LRot32(A + ((B and C) or (B and D) or (C and D)) + Data[ 2] + longint($5a827999), 3);
+ D:= LRot32(D + ((A and B) or (A and C) or (B and C)) + Data[ 6] + longint($5a827999), 5);
+ C:= LRot32(C + ((D and A) or (D and B) or (A and B)) + Data[10] + longint($5a827999), 9);
+ B:= LRot32(B + ((C and D) or (C and A) or (D and A)) + Data[14] + longint($5a827999), 13);
+ A:= LRot32(A + ((B and C) or (B and D) or (C and D)) + Data[ 3] + longint($5a827999), 3);
+ D:= LRot32(D + ((A and B) or (A and C) or (B and C)) + Data[ 7] + longint($5a827999), 5);
+ C:= LRot32(C + ((D and A) or (D and B) or (A and B)) + Data[11] + longint($5a827999), 9);
+ B:= LRot32(B + ((C and D) or (C and A) or (D and A)) + Data[15] + longint($5a827999), 13);
+
+ A:= LRot32(A + (B xor C xor D) + Data[ 0] + longint($6ed9eba1), 3);
+ D:= LRot32(D + (A xor B xor C) + Data[ 8] + longint($6ed9eba1), 9);
+ C:= LRot32(C + (D xor A xor B) + Data[ 4] + longint($6ed9eba1), 11);
+ B:= LRot32(B + (C xor D xor A) + Data[12] + longint($6ed9eba1), 15);
+ A:= LRot32(A + (B xor C xor D) + Data[ 2] + longint($6ed9eba1), 3);
+ D:= LRot32(D + (A xor B xor C) + Data[10] + longint($6ed9eba1), 9);
+ C:= LRot32(C + (D xor A xor B) + Data[ 6] + longint($6ed9eba1), 11);
+ B:= LRot32(B + (C xor D xor A) + Data[14] + longint($6ed9eba1), 15);
+ A:= LRot32(A + (B xor C xor D) + Data[ 1] + longint($6ed9eba1), 3);
+ D:= LRot32(D + (A xor B xor C) + Data[ 9] + longint($6ed9eba1), 9);
+ C:= LRot32(C + (D xor A xor B) + Data[ 5] + longint($6ed9eba1), 11);
+ B:= LRot32(B + (C xor D xor A) + Data[13] + longint($6ed9eba1), 15);
+ A:= LRot32(A + (B xor C xor D) + Data[ 3] + longint($6ed9eba1), 3);
+ D:= LRot32(D + (A xor B xor C) + Data[11] + longint($6ed9eba1), 9);
+ C:= LRot32(C + (D xor A xor B) + Data[ 7] + longint($6ed9eba1), 11);
+ B:= LRot32(B + (C xor D xor A) + Data[15] + longint($6ed9eba1), 15);
+
+ Inc(Buf[0], A);
+ Inc(Buf[1], B);
+ Inc(Buf[2], C);
+ Inc(Buf[3], D);
+end;
+
+{==============================================================================}
+
+function MD4(const Value: AnsiString): AnsiString;
+var
+ MDContext: TMDCtx;
+begin
+ MDInit(MDContext);
+ MDUpdate(MDContext, Value, @MD4Transform);
+ Result := MDFinal(MDContext, @MD4Transform);
+end;
+
+{==============================================================================}
+
+
+end.
diff --git a/branches/script-component/Units/Synapse/synacrypt.pas b/branches/script-component/Units/Synapse/synacrypt.pas
new file mode 100644
index 0000000..c80e891
--- /dev/null
+++ b/branches/script-component/Units/Synapse/synacrypt.pas
@@ -0,0 +1,1223 @@
+{==============================================================================|
+| Project : Ararat Synapse | 001.000.000 |
+|==============================================================================|
+| Content: Encryption support |
+|==============================================================================|
+| Copyright (c)2007, Lukas Gebauer |
+| All rights reserved. |
+| |
+| Redistribution and use in source and binary forms, with or without |
+| modification, are permitted provided that the following conditions are met: |
+| |
+| Redistributions of source code must retain the above copyright notice, this |
+| list of conditions and the following disclaimer. |
+| |
+| Redistributions in binary form must reproduce the above copyright notice, |
+| this list of conditions and the following disclaimer in the documentation |
+| and/or other materials provided with the distribution. |
+| |
+| Neither the name of Lukas Gebauer nor the names of its contributors may |
+| be used to endorse or promote products derived from this software without |
+| specific prior written permission. |
+| |
+| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
+| AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
+| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
+| ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR |
+| ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
+| DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
+| SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
+| CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
+| LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
+| OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
+| DAMAGE. |
+|==============================================================================|
+| The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).|
+| Portions created by Lukas Gebauer are Copyright (c)2007. |
+| All Rights Reserved. |
+| Based on work of David Barton and Eric Young |
+|==============================================================================|
+| Contributor(s): |
+|==============================================================================|
+| History: see HISTORY.HTM from distribution package |
+| (Found at URL: http://www.ararat.cz/synapse/) |
+|==============================================================================}
+
+{:@abstract(Encryption support)
+
+Implemented are DES and 3DES encryption/decryption by ECB, CBC, CFB-8bit,
+ CFB-block, OFB and CTR methods.
+}
+
+{$IFDEF FPC}
+ {$MODE DELPHI}
+{$ENDIF}
+{$Q-}
+{$R-}
+{$H+}
+
+unit synacrypt;
+
+interface
+
+uses
+ SysUtils, Classes, synautil;
+
+type
+ {:@abstract(Implementation of common routines for 64-bit block ciphers)
+
+ Do not use this class directly, use descendants only!}
+ TSynaBlockCipher= class(TObject)
+ protected
+ procedure InitKey(Key: AnsiString); virtual;
+ private
+ IV, CV: AnsiString;
+ procedure IncCounter;
+ public
+ {:Sets the IV to Value and performs a reset}
+ procedure SetIV(const Value: AnsiString); virtual;
+ {:Returns the current chaining information, not the actual IV}
+ function GetIV: AnsiString; virtual;
+ {:Reset any stored chaining information}
+ procedure Reset; virtual;
+ {:Encrypt a 64-bit block of data using the ECB method of encryption}
+ function EncryptECB(const InData: AnsiString): AnsiString; virtual;
+ {:Decrypt a 64-bit block of data using the ECB method of decryption}
+ function DecryptECB(const InData: AnsiString): AnsiString; virtual;
+ {:Encrypt data using the CBC method of encryption}
+ function EncryptCBC(const Indata: AnsiString): AnsiString; virtual;
+ {:Decrypt data using the CBC method of decryption}
+ function DecryptCBC(const Indata: AnsiString): AnsiString; virtual;
+ {:Encrypt data using the CFB (8 bit) method of encryption}
+ function EncryptCFB8bit(const Indata: AnsiString): AnsiString; virtual;
+ {:Decrypt data using the CFB (8 bit) method of decryption}
+ function DecryptCFB8bit(const Indata: AnsiString): AnsiString; virtual;
+ {:Encrypt data using the CFB (block) method of encryption}
+ function EncryptCFBblock(const Indata: AnsiString): AnsiString; virtual;
+ {:Decrypt data using the CFB (block) method of decryption}
+ function DecryptCFBblock(const Indata: AnsiString): AnsiString; virtual;
+ {:Encrypt data using the OFB method of encryption}
+ function EncryptOFB(const Indata: AnsiString): AnsiString; virtual;
+ {:Decrypt data using the OFB method of decryption}
+ function DecryptOFB(const Indata: AnsiString): AnsiString; virtual;
+ {:Encrypt data using the CTR method of encryption}
+ function EncryptCTR(const Indata: AnsiString): AnsiString; virtual;
+ {:Decrypt data using the CTR method of decryption}
+ function DecryptCTR(const Indata: AnsiString): AnsiString; virtual;
+ {:Create a encryptor/decryptor instance and initialize it by the Key.}
+ constructor Create(Key: AnsiString);
+ end;
+
+ {:@abstract(Datatype for holding one DES key data)
+
+ This data type is used internally.}
+ TDesKeyData = array[0..31] of integer;
+
+ {:@abstract(Implementation of common routines for DES encryption)
+
+ Do not use this class directly, use descendants only!}
+ TSynaCustomDes = class(TSynaBlockcipher)
+ protected
+ procedure DoInit(KeyB: AnsiString; var KeyData: TDesKeyData);
+ function EncryptBlock(const InData: AnsiString; var KeyData: TDesKeyData): AnsiString;
+ function DecryptBlock(const InData: AnsiString; var KeyData: TDesKeyData): AnsiString;
+ end;
+
+ {:@abstract(Implementation of DES encryption)}
+ TSynaDes= class(TSynaCustomDes)
+ protected
+ KeyData: TDesKeyData;
+ procedure InitKey(Key: AnsiString); override;
+ public
+ {:Encrypt a 64-bit block of data using the ECB method of encryption}
+ function EncryptECB(const InData: AnsiString): AnsiString; override;
+ {:Decrypt a 64-bit block of data using the ECB method of decryption}
+ function DecryptECB(const InData: AnsiString): AnsiString; override;
+ end;
+
+ {:@abstract(Implementation of 3DES encryption)}
+ TSyna3Des= class(TSynaCustomDes)
+ protected
+ KeyData: array[0..2] of TDesKeyData;
+ procedure InitKey(Key: AnsiString); override;
+ public
+ {:Encrypt a 64-bit block of data using the ECB method of encryption}
+ function EncryptECB(const InData: AnsiString): AnsiString; override;
+ {:Decrypt a 64-bit block of data using the ECB method of decryption}
+ function DecryptECB(const InData: AnsiString): AnsiString; override;
+ end;
+
+{:Call internal test of all DES encryptions. Returns @true if all is OK.}
+function TestDes: boolean;
+{:Call internal test of all 3DES encryptions. Returns @true if all is OK.}
+function Test3Des: boolean;
+
+{==============================================================================}
+implementation
+
+const
+ shifts2: array[0..15]of byte=
+ (0,0,1,1,1,1,1,1,0,1,1,1,1,1,1,0);
+
+ des_skb: array[0..7,0..63]of integer=(
+ (
+ (* for C bits (numbered as per FIPS 46) 1 2 3 4 5 6 *)
+ integer($00000000),integer($00000010),integer($20000000),integer($20000010),
+ integer($00010000),integer($00010010),integer($20010000),integer($20010010),
+ integer($00000800),integer($00000810),integer($20000800),integer($20000810),
+ integer($00010800),integer($00010810),integer($20010800),integer($20010810),
+ integer($00000020),integer($00000030),integer($20000020),integer($20000030),
+ integer($00010020),integer($00010030),integer($20010020),integer($20010030),
+ integer($00000820),integer($00000830),integer($20000820),integer($20000830),
+ integer($00010820),integer($00010830),integer($20010820),integer($20010830),
+ integer($00080000),integer($00080010),integer($20080000),integer($20080010),
+ integer($00090000),integer($00090010),integer($20090000),integer($20090010),
+ integer($00080800),integer($00080810),integer($20080800),integer($20080810),
+ integer($00090800),integer($00090810),integer($20090800),integer($20090810),
+ integer($00080020),integer($00080030),integer($20080020),integer($20080030),
+ integer($00090020),integer($00090030),integer($20090020),integer($20090030),
+ integer($00080820),integer($00080830),integer($20080820),integer($20080830),
+ integer($00090820),integer($00090830),integer($20090820),integer($20090830)
+ ),(
+ (* for C bits (numbered as per FIPS 46) 7 8 10 11 12 13 *)
+ integer($00000000),integer($02000000),integer($00002000),integer($02002000),
+ integer($00200000),integer($02200000),integer($00202000),integer($02202000),
+ integer($00000004),integer($02000004),integer($00002004),integer($02002004),
+ integer($00200004),integer($02200004),integer($00202004),integer($02202004),
+ integer($00000400),integer($02000400),integer($00002400),integer($02002400),
+ integer($00200400),integer($02200400),integer($00202400),integer($02202400),
+ integer($00000404),integer($02000404),integer($00002404),integer($02002404),
+ integer($00200404),integer($02200404),integer($00202404),integer($02202404),
+ integer($10000000),integer($12000000),integer($10002000),integer($12002000),
+ integer($10200000),integer($12200000),integer($10202000),integer($12202000),
+ integer($10000004),integer($12000004),integer($10002004),integer($12002004),
+ integer($10200004),integer($12200004),integer($10202004),integer($12202004),
+ integer($10000400),integer($12000400),integer($10002400),integer($12002400),
+ integer($10200400),integer($12200400),integer($10202400),integer($12202400),
+ integer($10000404),integer($12000404),integer($10002404),integer($12002404),
+ integer($10200404),integer($12200404),integer($10202404),integer($12202404)
+ ),(
+ (* for C bits (numbered as per FIPS 46) 14 15 16 17 19 20 *)
+ integer($00000000),integer($00000001),integer($00040000),integer($00040001),
+ integer($01000000),integer($01000001),integer($01040000),integer($01040001),
+ integer($00000002),integer($00000003),integer($00040002),integer($00040003),
+ integer($01000002),integer($01000003),integer($01040002),integer($01040003),
+ integer($00000200),integer($00000201),integer($00040200),integer($00040201),
+ integer($01000200),integer($01000201),integer($01040200),integer($01040201),
+ integer($00000202),integer($00000203),integer($00040202),integer($00040203),
+ integer($01000202),integer($01000203),integer($01040202),integer($01040203),
+ integer($08000000),integer($08000001),integer($08040000),integer($08040001),
+ integer($09000000),integer($09000001),integer($09040000),integer($09040001),
+ integer($08000002),integer($08000003),integer($08040002),integer($08040003),
+ integer($09000002),integer($09000003),integer($09040002),integer($09040003),
+ integer($08000200),integer($08000201),integer($08040200),integer($08040201),
+ integer($09000200),integer($09000201),integer($09040200),integer($09040201),
+ integer($08000202),integer($08000203),integer($08040202),integer($08040203),
+ integer($09000202),integer($09000203),integer($09040202),integer($09040203)
+ ),(
+ (* for C bits (numbered as per FIPS 46) 21 23 24 26 27 28 *)
+ integer($00000000),integer($00100000),integer($00000100),integer($00100100),
+ integer($00000008),integer($00100008),integer($00000108),integer($00100108),
+ integer($00001000),integer($00101000),integer($00001100),integer($00101100),
+ integer($00001008),integer($00101008),integer($00001108),integer($00101108),
+ integer($04000000),integer($04100000),integer($04000100),integer($04100100),
+ integer($04000008),integer($04100008),integer($04000108),integer($04100108),
+ integer($04001000),integer($04101000),integer($04001100),integer($04101100),
+ integer($04001008),integer($04101008),integer($04001108),integer($04101108),
+ integer($00020000),integer($00120000),integer($00020100),integer($00120100),
+ integer($00020008),integer($00120008),integer($00020108),integer($00120108),
+ integer($00021000),integer($00121000),integer($00021100),integer($00121100),
+ integer($00021008),integer($00121008),integer($00021108),integer($00121108),
+ integer($04020000),integer($04120000),integer($04020100),integer($04120100),
+ integer($04020008),integer($04120008),integer($04020108),integer($04120108),
+ integer($04021000),integer($04121000),integer($04021100),integer($04121100),
+ integer($04021008),integer($04121008),integer($04021108),integer($04121108)
+ ),(
+ (* for D bits (numbered as per FIPS 46) 1 2 3 4 5 6 *)
+ integer($00000000),integer($10000000),integer($00010000),integer($10010000),
+ integer($00000004),integer($10000004),integer($00010004),integer($10010004),
+ integer($20000000),integer($30000000),integer($20010000),integer($30010000),
+ integer($20000004),integer($30000004),integer($20010004),integer($30010004),
+ integer($00100000),integer($10100000),integer($00110000),integer($10110000),
+ integer($00100004),integer($10100004),integer($00110004),integer($10110004),
+ integer($20100000),integer($30100000),integer($20110000),integer($30110000),
+ integer($20100004),integer($30100004),integer($20110004),integer($30110004),
+ integer($00001000),integer($10001000),integer($00011000),integer($10011000),
+ integer($00001004),integer($10001004),integer($00011004),integer($10011004),
+ integer($20001000),integer($30001000),integer($20011000),integer($30011000),
+ integer($20001004),integer($30001004),integer($20011004),integer($30011004),
+ integer($00101000),integer($10101000),integer($00111000),integer($10111000),
+ integer($00101004),integer($10101004),integer($00111004),integer($10111004),
+ integer($20101000),integer($30101000),integer($20111000),integer($30111000),
+ integer($20101004),integer($30101004),integer($20111004),integer($30111004)
+ ),(
+ (* for D bits (numbered as per FIPS 46) 8 9 11 12 13 14 *)
+ integer($00000000),integer($08000000),integer($00000008),integer($08000008),
+ integer($00000400),integer($08000400),integer($00000408),integer($08000408),
+ integer($00020000),integer($08020000),integer($00020008),integer($08020008),
+ integer($00020400),integer($08020400),integer($00020408),integer($08020408),
+ integer($00000001),integer($08000001),integer($00000009),integer($08000009),
+ integer($00000401),integer($08000401),integer($00000409),integer($08000409),
+ integer($00020001),integer($08020001),integer($00020009),integer($08020009),
+ integer($00020401),integer($08020401),integer($00020409),integer($08020409),
+ integer($02000000),integer($0A000000),integer($02000008),integer($0A000008),
+ integer($02000400),integer($0A000400),integer($02000408),integer($0A000408),
+ integer($02020000),integer($0A020000),integer($02020008),integer($0A020008),
+ integer($02020400),integer($0A020400),integer($02020408),integer($0A020408),
+ integer($02000001),integer($0A000001),integer($02000009),integer($0A000009),
+ integer($02000401),integer($0A000401),integer($02000409),integer($0A000409),
+ integer($02020001),integer($0A020001),integer($02020009),integer($0A020009),
+ integer($02020401),integer($0A020401),integer($02020409),integer($0A020409)
+ ),(
+ (* for D bits (numbered as per FIPS 46) 16 17 18 19 20 21 *)
+ integer($00000000),integer($00000100),integer($00080000),integer($00080100),
+ integer($01000000),integer($01000100),integer($01080000),integer($01080100),
+ integer($00000010),integer($00000110),integer($00080010),integer($00080110),
+ integer($01000010),integer($01000110),integer($01080010),integer($01080110),
+ integer($00200000),integer($00200100),integer($00280000),integer($00280100),
+ integer($01200000),integer($01200100),integer($01280000),integer($01280100),
+ integer($00200010),integer($00200110),integer($00280010),integer($00280110),
+ integer($01200010),integer($01200110),integer($01280010),integer($01280110),
+ integer($00000200),integer($00000300),integer($00080200),integer($00080300),
+ integer($01000200),integer($01000300),integer($01080200),integer($01080300),
+ integer($00000210),integer($00000310),integer($00080210),integer($00080310),
+ integer($01000210),integer($01000310),integer($01080210),integer($01080310),
+ integer($00200200),integer($00200300),integer($00280200),integer($00280300),
+ integer($01200200),integer($01200300),integer($01280200),integer($01280300),
+ integer($00200210),integer($00200310),integer($00280210),integer($00280310),
+ integer($01200210),integer($01200310),integer($01280210),integer($01280310)
+ ),(
+ (* for D bits (numbered as per FIPS 46) 22 23 24 25 27 28 *)
+ integer($00000000),integer($04000000),integer($00040000),integer($04040000),
+ integer($00000002),integer($04000002),integer($00040002),integer($04040002),
+ integer($00002000),integer($04002000),integer($00042000),integer($04042000),
+ integer($00002002),integer($04002002),integer($00042002),integer($04042002),
+ integer($00000020),integer($04000020),integer($00040020),integer($04040020),
+ integer($00000022),integer($04000022),integer($00040022),integer($04040022),
+ integer($00002020),integer($04002020),integer($00042020),integer($04042020),
+ integer($00002022),integer($04002022),integer($00042022),integer($04042022),
+ integer($00000800),integer($04000800),integer($00040800),integer($04040800),
+ integer($00000802),integer($04000802),integer($00040802),integer($04040802),
+ integer($00002800),integer($04002800),integer($00042800),integer($04042800),
+ integer($00002802),integer($04002802),integer($00042802),integer($04042802),
+ integer($00000820),integer($04000820),integer($00040820),integer($04040820),
+ integer($00000822),integer($04000822),integer($00040822),integer($04040822),
+ integer($00002820),integer($04002820),integer($00042820),integer($04042820),
+ integer($00002822),integer($04002822),integer($00042822),integer($04042822)
+ ));
+
+ des_sptrans: array[0..7,0..63] of integer=(
+ (
+ (* nibble 0 *)
+ integer($02080800), integer($00080000), integer($02000002), integer($02080802),
+ integer($02000000), integer($00080802), integer($00080002), integer($02000002),
+ integer($00080802), integer($02080800), integer($02080000), integer($00000802),
+ integer($02000802), integer($02000000), integer($00000000), integer($00080002),
+ integer($00080000), integer($00000002), integer($02000800), integer($00080800),
+ integer($02080802), integer($02080000), integer($00000802), integer($02000800),
+ integer($00000002), integer($00000800), integer($00080800), integer($02080002),
+ integer($00000800), integer($02000802), integer($02080002), integer($00000000),
+ integer($00000000), integer($02080802), integer($02000800), integer($00080002),
+ integer($02080800), integer($00080000), integer($00000802), integer($02000800),
+ integer($02080002), integer($00000800), integer($00080800), integer($02000002),
+ integer($00080802), integer($00000002), integer($02000002), integer($02080000),
+ integer($02080802), integer($00080800), integer($02080000), integer($02000802),
+ integer($02000000), integer($00000802), integer($00080002), integer($00000000),
+ integer($00080000), integer($02000000), integer($02000802), integer($02080800),
+ integer($00000002), integer($02080002), integer($00000800), integer($00080802)
+ ),(
+ (* nibble 1 *)
+ integer($40108010), integer($00000000), integer($00108000), integer($40100000),
+ integer($40000010), integer($00008010), integer($40008000), integer($00108000),
+ integer($00008000), integer($40100010), integer($00000010), integer($40008000),
+ integer($00100010), integer($40108000), integer($40100000), integer($00000010),
+ integer($00100000), integer($40008010), integer($40100010), integer($00008000),
+ integer($00108010), integer($40000000), integer($00000000), integer($00100010),
+ integer($40008010), integer($00108010), integer($40108000), integer($40000010),
+ integer($40000000), integer($00100000), integer($00008010), integer($40108010),
+ integer($00100010), integer($40108000), integer($40008000), integer($00108010),
+ integer($40108010), integer($00100010), integer($40000010), integer($00000000),
+ integer($40000000), integer($00008010), integer($00100000), integer($40100010),
+ integer($00008000), integer($40000000), integer($00108010), integer($40008010),
+ integer($40108000), integer($00008000), integer($00000000), integer($40000010),
+ integer($00000010), integer($40108010), integer($00108000), integer($40100000),
+ integer($40100010), integer($00100000), integer($00008010), integer($40008000),
+ integer($40008010), integer($00000010), integer($40100000), integer($00108000)
+ ),(
+ (* nibble 2 *)
+ integer($04000001), integer($04040100), integer($00000100), integer($04000101),
+ integer($00040001), integer($04000000), integer($04000101), integer($00040100),
+ integer($04000100), integer($00040000), integer($04040000), integer($00000001),
+ integer($04040101), integer($00000101), integer($00000001), integer($04040001),
+ integer($00000000), integer($00040001), integer($04040100), integer($00000100),
+ integer($00000101), integer($04040101), integer($00040000), integer($04000001),
+ integer($04040001), integer($04000100), integer($00040101), integer($04040000),
+ integer($00040100), integer($00000000), integer($04000000), integer($00040101),
+ integer($04040100), integer($00000100), integer($00000001), integer($00040000),
+ integer($00000101), integer($00040001), integer($04040000), integer($04000101),
+ integer($00000000), integer($04040100), integer($00040100), integer($04040001),
+ integer($00040001), integer($04000000), integer($04040101), integer($00000001),
+ integer($00040101), integer($04000001), integer($04000000), integer($04040101),
+ integer($00040000), integer($04000100), integer($04000101), integer($00040100),
+ integer($04000100), integer($00000000), integer($04040001), integer($00000101),
+ integer($04000001), integer($00040101), integer($00000100), integer($04040000)
+ ),(
+ (* nibble 3 *)
+ integer($00401008), integer($10001000), integer($00000008), integer($10401008),
+ integer($00000000), integer($10400000), integer($10001008), integer($00400008),
+ integer($10401000), integer($10000008), integer($10000000), integer($00001008),
+ integer($10000008), integer($00401008), integer($00400000), integer($10000000),
+ integer($10400008), integer($00401000), integer($00001000), integer($00000008),
+ integer($00401000), integer($10001008), integer($10400000), integer($00001000),
+ integer($00001008), integer($00000000), integer($00400008), integer($10401000),
+ integer($10001000), integer($10400008), integer($10401008), integer($00400000),
+ integer($10400008), integer($00001008), integer($00400000), integer($10000008),
+ integer($00401000), integer($10001000), integer($00000008), integer($10400000),
+ integer($10001008), integer($00000000), integer($00001000), integer($00400008),
+ integer($00000000), integer($10400008), integer($10401000), integer($00001000),
+ integer($10000000), integer($10401008), integer($00401008), integer($00400000),
+ integer($10401008), integer($00000008), integer($10001000), integer($00401008),
+ integer($00400008), integer($00401000), integer($10400000), integer($10001008),
+ integer($00001008), integer($10000000), integer($10000008), integer($10401000)
+ ),(
+ (* nibble 4 *)
+ integer($08000000), integer($00010000), integer($00000400), integer($08010420),
+ integer($08010020), integer($08000400), integer($00010420), integer($08010000),
+ integer($00010000), integer($00000020), integer($08000020), integer($00010400),
+ integer($08000420), integer($08010020), integer($08010400), integer($00000000),
+ integer($00010400), integer($08000000), integer($00010020), integer($00000420),
+ integer($08000400), integer($00010420), integer($00000000), integer($08000020),
+ integer($00000020), integer($08000420), integer($08010420), integer($00010020),
+ integer($08010000), integer($00000400), integer($00000420), integer($08010400),
+ integer($08010400), integer($08000420), integer($00010020), integer($08010000),
+ integer($00010000), integer($00000020), integer($08000020), integer($08000400),
+ integer($08000000), integer($00010400), integer($08010420), integer($00000000),
+ integer($00010420), integer($08000000), integer($00000400), integer($00010020),
+ integer($08000420), integer($00000400), integer($00000000), integer($08010420),
+ integer($08010020), integer($08010400), integer($00000420), integer($00010000),
+ integer($00010400), integer($08010020), integer($08000400), integer($00000420),
+ integer($00000020), integer($00010420), integer($08010000), integer($08000020)
+ ),(
+ (* nibble 5 *)
+ integer($80000040), integer($00200040), integer($00000000), integer($80202000),
+ integer($00200040), integer($00002000), integer($80002040), integer($00200000),
+ integer($00002040), integer($80202040), integer($00202000), integer($80000000),
+ integer($80002000), integer($80000040), integer($80200000), integer($00202040),
+ integer($00200000), integer($80002040), integer($80200040), integer($00000000),
+ integer($00002000), integer($00000040), integer($80202000), integer($80200040),
+ integer($80202040), integer($80200000), integer($80000000), integer($00002040),
+ integer($00000040), integer($00202000), integer($00202040), integer($80002000),
+ integer($00002040), integer($80000000), integer($80002000), integer($00202040),
+ integer($80202000), integer($00200040), integer($00000000), integer($80002000),
+ integer($80000000), integer($00002000), integer($80200040), integer($00200000),
+ integer($00200040), integer($80202040), integer($00202000), integer($00000040),
+ integer($80202040), integer($00202000), integer($00200000), integer($80002040),
+ integer($80000040), integer($80200000), integer($00202040), integer($00000000),
+ integer($00002000), integer($80000040), integer($80002040), integer($80202000),
+ integer($80200000), integer($00002040), integer($00000040), integer($80200040)
+ ),(
+ (* nibble 6 *)
+ integer($00004000), integer($00000200), integer($01000200), integer($01000004),
+ integer($01004204), integer($00004004), integer($00004200), integer($00000000),
+ integer($01000000), integer($01000204), integer($00000204), integer($01004000),
+ integer($00000004), integer($01004200), integer($01004000), integer($00000204),
+ integer($01000204), integer($00004000), integer($00004004), integer($01004204),
+ integer($00000000), integer($01000200), integer($01000004), integer($00004200),
+ integer($01004004), integer($00004204), integer($01004200), integer($00000004),
+ integer($00004204), integer($01004004), integer($00000200), integer($01000000),
+ integer($00004204), integer($01004000), integer($01004004), integer($00000204),
+ integer($00004000), integer($00000200), integer($01000000), integer($01004004),
+ integer($01000204), integer($00004204), integer($00004200), integer($00000000),
+ integer($00000200), integer($01000004), integer($00000004), integer($01000200),
+ integer($00000000), integer($01000204), integer($01000200), integer($00004200),
+ integer($00000204), integer($00004000), integer($01004204), integer($01000000),
+ integer($01004200), integer($00000004), integer($00004004), integer($01004204),
+ integer($01000004), integer($01004200), integer($01004000), integer($00004004)
+ ),(
+ (* nibble 7 *)
+ integer($20800080), integer($20820000), integer($00020080), integer($00000000),
+ integer($20020000), integer($00800080), integer($20800000), integer($20820080),
+ integer($00000080), integer($20000000), integer($00820000), integer($00020080),
+ integer($00820080), integer($20020080), integer($20000080), integer($20800000),
+ integer($00020000), integer($00820080), integer($00800080), integer($20020000),
+ integer($20820080), integer($20000080), integer($00000000), integer($00820000),
+ integer($20000000), integer($00800000), integer($20020080), integer($20800080),
+ integer($00800000), integer($00020000), integer($20820000), integer($00000080),
+ integer($00800000), integer($00020000), integer($20000080), integer($20820080),
+ integer($00020080), integer($20000000), integer($00000000), integer($00820000),
+ integer($20800080), integer($20020080), integer($20020000), integer($00800080),
+ integer($20820000), integer($00000080), integer($00800080), integer($20020000),
+ integer($20820080), integer($00800000), integer($20800000), integer($20000080),
+ integer($00820000), integer($00020080), integer($20020080), integer($20800000),
+ integer($00000080), integer($20820000), integer($00820080), integer($00000000),
+ integer($20000000), integer($20800080), integer($00020000), integer($00820080)
+ ));
+
+{==============================================================================}
+
+function XorString(Indata1, Indata2: AnsiString): AnsiString;
+var
+ i: integer;
+begin
+ Indata2 := PadString(Indata2, length(Indata1), #0);
+ Result := '';
+ for i := 1 to length(Indata1) do
+ Result := Result + AnsiChar(ord(Indata1[i]) xor ord(Indata2[i]));
+end;
+
+procedure hperm_op(var a, t: integer; n, m: integer);
+begin
+ t:= ((a shl (16 - n)) xor a) and m;
+ a:= a xor t xor (t shr (16 - n));
+end;
+
+procedure perm_op(var a, b, t: integer; n, m: integer);
+begin
+ t:= ((a shr n) xor b) and m;
+ b:= b xor t;
+ a:= a xor (t shl n);
+end;
+
+{==============================================================================}
+procedure TSynaBlockCipher.IncCounter;
+var
+ i: integer;
+begin
+ Inc(CV[8]);
+ i:= 7;
+ while (i> 0) and (CV[i + 1] = #0) do
+ begin
+ Inc(CV[i]);
+ Dec(i);
+ end;
+end;
+
+procedure TSynaBlockCipher.Reset;
+begin
+ CV := IV;
+end;
+
+procedure TSynaBlockCipher.InitKey(Key: AnsiString);
+begin
+end;
+
+procedure TSynaBlockCipher.SetIV(const Value: AnsiString);
+begin
+ IV := PadString(Value, 8, #0);
+ Reset;
+end;
+
+function TSynaBlockCipher.GetIV: AnsiString;
+begin
+ Result := CV;
+end;
+
+function TSynaBlockCipher.EncryptECB(const InData: AnsiString): AnsiString;
+begin
+ Result := InData;
+end;
+
+function TSynaBlockCipher.DecryptECB(const InData: AnsiString): AnsiString;
+begin
+ Result := InData;
+end;
+
+function TSynaBlockCipher.EncryptCBC(const Indata: AnsiString): AnsiString;
+var
+ i: integer;
+ s: ansistring;
+ l: integer;
+begin
+ Result := '';
+ l := Length(InData);
+ for i:= 1 to (l div 8) do
+ begin
+ s := copy(Indata, (i - 1) * 8 + 1, 8);
+ s := XorString(s, CV);
+ s := EncryptECB(s);
+ CV := s;
+ Result := Result + s;
+ end;
+ if (l mod 8)<> 0 then
+ begin
+ CV := EncryptECB(CV);
+ s := copy(Indata, (l div 8) * 8 + 1, l mod 8);
+ s := XorString(s, CV);
+ Result := Result + s;
+ end;
+end;
+
+function TSynaBlockCipher.DecryptCBC(const Indata: AnsiString): AnsiString;
+var
+ i: integer;
+ s, temp: ansistring;
+ l: integer;
+begin
+ Result := '';
+ l := Length(InData);
+ for i:= 1 to (l div 8) do
+ begin
+ s := copy(Indata, (i - 1) * 8 + 1, 8);
+ temp := s;
+ s := DecryptECB(s);
+ s := XorString(s, CV);
+ Result := Result + s;
+ CV := Temp;
+ end;
+ if (l mod 8)<> 0 then
+ begin
+ CV := EncryptECB(CV);
+ s := copy(Indata, (l div 8) * 8 + 1, l mod 8);
+ s := XorString(s, CV);
+ Result := Result + s;
+ end;
+end;
+
+function TSynaBlockCipher.EncryptCFB8bit(const Indata: AnsiString): AnsiString;
+var
+ i: integer;
+ Temp: AnsiString;
+ c: AnsiChar;
+begin
+ Result := '';
+ for i:= 1 to Length(Indata) do
+ begin
+ Temp := EncryptECB(CV);
+ c := AnsiChar(ord(InData[i]) xor ord(temp[1]));
+ Result := Result + c;
+ Delete(CV, 1, 1);
+ CV := CV + c;
+ end;
+end;
+
+function TSynaBlockCipher.DecryptCFB8bit(const Indata: AnsiString): AnsiString;
+var
+ i: integer;
+ Temp: AnsiString;
+ c: AnsiChar;
+begin
+ Result := '';
+ for i:= 1 to length(Indata) do
+ begin
+ c:= Indata[i];
+ Temp := EncryptECB(CV);
+ Result := Result + AnsiChar(ord(InData[i]) xor ord(temp[1]));
+ Delete(CV, 1, 1);
+ CV := CV + c;
+ end;
+end;
+
+function TSynaBlockCipher.EncryptCFBblock(const Indata: AnsiString): AnsiString;
+var
+ i: integer;
+ s: AnsiString;
+ l: integer;
+begin
+ Result := '';
+ l := Length(InData);
+ for i:= 1 to (l div 8) do
+ begin
+ CV := EncryptECB(CV);
+ s := copy(Indata, (i - 1) * 8 + 1, 8);
+ s := XorString(s, CV);
+ Result := Result + s;
+ CV := s;
+ end;
+ if (l mod 8)<> 0 then
+ begin
+ CV := EncryptECB(CV);
+ s := copy(Indata, (l div 8) * 8 + 1, l mod 8);
+ s := XorString(s, CV);
+ Result := Result + s;
+ end;
+end;
+
+function TSynaBlockCipher.DecryptCFBblock(const Indata: AnsiString): AnsiString;
+var
+ i: integer;
+ S, Temp: AnsiString;
+ l: integer;
+begin
+ Result := '';
+ l := Length(InData);
+ for i:= 1 to (l div 8) do
+ begin
+ s := copy(Indata, (i - 1) * 8 + 1, 8);
+ Temp := s;
+ CV := EncryptECB(CV);
+ s := XorString(s, CV);
+ Result := result + s;
+ CV := temp;
+ end;
+ if (l mod 8)<> 0 then
+ begin
+ CV := EncryptECB(CV);
+ s := copy(Indata, (l div 8) * 8 + 1, l mod 8);
+ s := XorString(s, CV);
+ Result := Result + s;
+ end;
+end;
+
+function TSynaBlockCipher.EncryptOFB(const Indata: AnsiString): AnsiString;
+var
+ i: integer;
+ s: AnsiString;
+ l: integer;
+begin
+ Result := '';
+ l := Length(InData);
+ for i:= 1 to (l div 8) do
+ begin
+ CV := EncryptECB(CV);
+ s := copy(Indata, (i - 1) * 8 + 1, 8);
+ s := XorString(s, CV);
+ Result := Result + s;
+ end;
+ if (l mod 8)<> 0 then
+ begin
+ CV := EncryptECB(CV);
+ s := copy(Indata, (l div 8) * 8 + 1, l mod 8);
+ s := XorString(s, CV);
+ Result := Result + s;
+ end;
+end;
+
+function TSynaBlockCipher.DecryptOFB(const Indata: AnsiString): AnsiString;
+var
+ i: integer;
+ s: AnsiString;
+ l: integer;
+begin
+ Result := '';
+ l := Length(InData);
+ for i:= 1 to (l div 8) do
+ begin
+ Cv := EncryptECB(CV);
+ s := copy(Indata, (i - 1) * 8 + 1, 8);
+ s := XorString(s, CV);
+ Result := Result + s;
+ end;
+ if (l mod 8)<> 0 then
+ begin
+ CV := EncryptECB(CV);
+ s := copy(Indata, (l div 8) * 8 + 1, l mod 8);
+ s := XorString(s, CV);
+ Result := Result + s;
+ end;
+end;
+
+function TSynaBlockCipher.EncryptCTR(const Indata: AnsiString): AnsiString;
+var
+ temp: AnsiString;
+ i: integer;
+ s: AnsiString;
+ l: integer;
+begin
+ Result := '';
+ l := Length(InData);
+ for i:= 1 to (l div 8) do
+ begin
+ temp := EncryptECB(CV);
+ IncCounter;
+ s := copy(Indata, (i - 1) * 8 + 1, 8);
+ s := XorString(s, temp);
+ Result := Result + s;
+ end;
+ if (l mod 8)<> 0 then
+ begin
+ temp := EncryptECB(CV);
+ IncCounter;
+ s := copy(Indata, (l div 8) * 8 + 1, l mod 8);
+ s := XorString(s, temp);
+ Result := Result + s;
+ end;
+end;
+
+function TSynaBlockCipher.DecryptCTR(const Indata: AnsiString): AnsiString;
+var
+ temp: AnsiString;
+ s: AnsiString;
+ i: integer;
+ l: integer;
+begin
+ Result := '';
+ l := Length(InData);
+ for i:= 1 to (l div 8) do
+ begin
+ temp := EncryptECB(CV);
+ IncCounter;
+ s := copy(Indata, (i - 1) * 8 + 1, 8);
+ s := XorString(s, temp);
+ Result := Result + s;
+ end;
+ if (l mod 8)<> 0 then
+ begin
+ temp := EncryptECB(CV);
+ IncCounter;
+ s := copy(Indata, (l div 8) * 8 + 1, l mod 8);
+ s := XorString(s, temp);
+ Result := Result + s;
+ end;
+end;
+
+constructor TSynaBlockCipher.Create(Key: AnsiString);
+begin
+ inherited Create;
+ InitKey(Key);
+ IV := StringOfChar(#0, 8);
+ IV := EncryptECB(IV);
+ Reset;
+end;
+
+{==============================================================================}
+
+procedure TSynaCustomDes.DoInit(KeyB: AnsiString; var KeyData: TDesKeyData);
+var
+ c, d, t, s, t2, i: integer;
+begin
+ KeyB := PadString(KeyB, 8, #0);
+ c:= ord(KeyB[1]) or (ord(KeyB[2]) shl 8) or (ord(KeyB[3]) shl 16) or (ord(KeyB[4]) shl 24);
+ d:= ord(KeyB[5]) or (ord(KeyB[6]) shl 8) or (ord(KeyB[7]) shl 16) or (ord(KeyB[8]) shl 24);
+ perm_op(d,c,t,4,integer($0f0f0f0f));
+ hperm_op(c,t,integer(-2),integer($cccc0000));
+ hperm_op(d,t,integer(-2),integer($cccc0000));
+ perm_op(d,c,t,1,integer($55555555));
+ perm_op(c,d,t,8,integer($00ff00ff));
+ perm_op(d,c,t,1,integer($55555555));
+ d:= ((d and $ff) shl 16) or (d and $ff00) or ((d and $ff0000) shr 16) or
+ ((c and integer($f0000000)) shr 4);
+ c:= c and $fffffff;
+ for i:= 0 to 15 do
+ begin
+ if shifts2[i]<> 0 then
+ begin
+ c:= ((c shr 2) or (c shl 26));
+ d:= ((d shr 2) or (d shl 26));
+ end
+ else
+ begin
+ c:= ((c shr 1) or (c shl 27));
+ d:= ((d shr 1) or (d shl 27));
+ end;
+ c:= c and $fffffff;
+ d:= d and $fffffff;
+ s:= des_skb[0,c and $3f] or
+ des_skb[1,((c shr 6) and $03) or ((c shr 7) and $3c)] or
+ des_skb[2,((c shr 13) and $0f) or ((c shr 14) and $30)] or
+ des_skb[3,((c shr 20) and $01) or ((c shr 21) and $06) or ((c shr 22) and $38)];
+ t:= des_skb[4,d and $3f] or
+ des_skb[5,((d shr 7) and $03) or ((d shr 8) and $3c)] or
+ des_skb[6, (d shr 15) and $3f ] or
+ des_skb[7,((d shr 21) and $0f) or ((d shr 22) and $30)];
+ t2:= ((t shl 16) or (s and $ffff));
+ KeyData[(i shl 1)]:= ((t2 shl 2) or (t2 shr 30));
+ t2:= ((s shr 16) or (t and integer($ffff0000)));
+ KeyData[(i shl 1)+1]:= ((t2 shl 6) or (t2 shr 26));
+ end;
+end;
+
+function TSynaCustomDes.EncryptBlock(const InData: AnsiString; var KeyData: TDesKeyData): AnsiString;
+var
+ l, r, t, u: integer;
+ i: longint;
+begin
+ r := Swapbytes(DecodeLongint(Indata, 1));
+ l := swapbytes(DecodeLongint(Indata, 5));
+ t:= ((l shr 4) xor r) and $0f0f0f0f;
+ r:= r xor t;
+ l:= l xor (t shl 4);
+ t:= ((r shr 16) xor l) and $0000ffff;
+ l:= l xor t;
+ r:= r xor (t shl 16);
+ t:= ((l shr 2) xor r) and $33333333;
+ r:= r xor t;
+ l:= l xor (t shl 2);
+ t:= ((r shr 8) xor l) and $00ff00ff;
+ l:= l xor t;
+ r:= r xor (t shl 8);
+ t:= ((l shr 1) xor r) and $55555555;
+ r:= r xor t;
+ l:= l xor (t shl 1);
+ r:= (r shr 29) or (r shl 3);
+ l:= (l shr 29) or (l shl 3);
+ i:= 0;
+ while i< 32 do
+ begin
+ u:= r xor KeyData[i ];
+ t:= r xor KeyData[i+1];
+ t:= (t shr 4) or (t shl 28);
+ l:= l xor des_SPtrans[0,(u shr 2) and $3f] xor
+ des_SPtrans[2,(u shr 10) and $3f] xor
+ des_SPtrans[4,(u shr 18) and $3f] xor
+ des_SPtrans[6,(u shr 26) and $3f] xor
+ des_SPtrans[1,(t shr 2) and $3f] xor
+ des_SPtrans[3,(t shr 10) and $3f] xor
+ des_SPtrans[5,(t shr 18) and $3f] xor
+ des_SPtrans[7,(t shr 26) and $3f];
+ u:= l xor KeyData[i+2];
+ t:= l xor KeyData[i+3];
+ t:= (t shr 4) or (t shl 28);
+ r:= r xor des_SPtrans[0,(u shr 2) and $3f] xor
+ des_SPtrans[2,(u shr 10) and $3f] xor
+ des_SPtrans[4,(u shr 18) and $3f] xor
+ des_SPtrans[6,(u shr 26) and $3f] xor
+ des_SPtrans[1,(t shr 2) and $3f] xor
+ des_SPtrans[3,(t shr 10) and $3f] xor
+ des_SPtrans[5,(t shr 18) and $3f] xor
+ des_SPtrans[7,(t shr 26) and $3f];
+ u:= r xor KeyData[i+4];
+ t:= r xor KeyData[i+5];
+ t:= (t shr 4) or (t shl 28);
+ l:= l xor des_SPtrans[0,(u shr 2) and $3f] xor
+ des_SPtrans[2,(u shr 10) and $3f] xor
+ des_SPtrans[4,(u shr 18) and $3f] xor
+ des_SPtrans[6,(u shr 26) and $3f] xor
+ des_SPtrans[1,(t shr 2) and $3f] xor
+ des_SPtrans[3,(t shr 10) and $3f] xor
+ des_SPtrans[5,(t shr 18) and $3f] xor
+ des_SPtrans[7,(t shr 26) and $3f];
+ u:= l xor KeyData[i+6];
+ t:= l xor KeyData[i+7];
+ t:= (t shr 4) or (t shl 28);
+ r:= r xor des_SPtrans[0,(u shr 2) and $3f] xor
+ des_SPtrans[2,(u shr 10) and $3f] xor
+ des_SPtrans[4,(u shr 18) and $3f] xor
+ des_SPtrans[6,(u shr 26) and $3f] xor
+ des_SPtrans[1,(t shr 2) and $3f] xor
+ des_SPtrans[3,(t shr 10) and $3f] xor
+ des_SPtrans[5,(t shr 18) and $3f] xor
+ des_SPtrans[7,(t shr 26) and $3f];
+ Inc(i,8);
+ end;
+ r:= (r shr 3) or (r shl 29);
+ l:= (l shr 3) or (l shl 29);
+ t:= ((r shr 1) xor l) and $55555555;
+ l:= l xor t;
+ r:= r xor (t shl 1);
+ t:= ((l shr 8) xor r) and $00ff00ff;
+ r:= r xor t;
+ l:= l xor (t shl 8);
+ t:= ((r shr 2) xor l) and $33333333;
+ l:= l xor t;
+ r:= r xor (t shl 2);
+ t:= ((l shr 16) xor r) and $0000ffff;
+ r:= r xor t;
+ l:= l xor (t shl 16);
+ t:= ((r shr 4) xor l) and $0f0f0f0f;
+ l:= l xor t;
+ r:= r xor (t shl 4);
+ Result := CodeLongInt(Swapbytes(l)) + CodeLongInt(Swapbytes(r));
+end;
+
+function TSynaCustomDes.DecryptBlock(const InData: AnsiString; var KeyData: TDesKeyData): AnsiString;
+var
+ l, r, t, u: integer;
+ i: longint;
+begin
+ r := Swapbytes(DecodeLongint(Indata, 1));
+ l := Swapbytes(DecodeLongint(Indata, 5));
+ t:= ((l shr 4) xor r) and $0f0f0f0f;
+ r:= r xor t;
+ l:= l xor (t shl 4);
+ t:= ((r shr 16) xor l) and $0000ffff;
+ l:= l xor t;
+ r:= r xor (t shl 16);
+ t:= ((l shr 2) xor r) and $33333333;
+ r:= r xor t;
+ l:= l xor (t shl 2);
+ t:= ((r shr 8) xor l) and $00ff00ff;
+ l:= l xor t;
+ r:= r xor (t shl 8);
+ t:= ((l shr 1) xor r) and $55555555;
+ r:= r xor t;
+ l:= l xor (t shl 1);
+ r:= (r shr 29) or (r shl 3);
+ l:= (l shr 29) or (l shl 3);
+ i:= 30;
+ while i> 0 do
+ begin
+ u:= r xor KeyData[i ];
+ t:= r xor KeyData[i+1];
+ t:= (t shr 4) or (t shl 28);
+ l:= l xor des_SPtrans[0,(u shr 2) and $3f] xor
+ des_SPtrans[2,(u shr 10) and $3f] xor
+ des_SPtrans[4,(u shr 18) and $3f] xor
+ des_SPtrans[6,(u shr 26) and $3f] xor
+ des_SPtrans[1,(t shr 2) and $3f] xor
+ des_SPtrans[3,(t shr 10) and $3f] xor
+ des_SPtrans[5,(t shr 18) and $3f] xor
+ des_SPtrans[7,(t shr 26) and $3f];
+ u:= l xor KeyData[i-2];
+ t:= l xor KeyData[i-1];
+ t:= (t shr 4) or (t shl 28);
+ r:= r xor des_SPtrans[0,(u shr 2) and $3f] xor
+ des_SPtrans[2,(u shr 10) and $3f] xor
+ des_SPtrans[4,(u shr 18) and $3f] xor
+ des_SPtrans[6,(u shr 26) and $3f] xor
+ des_SPtrans[1,(t shr 2) and $3f] xor
+ des_SPtrans[3,(t shr 10) and $3f] xor
+ des_SPtrans[5,(t shr 18) and $3f] xor
+ des_SPtrans[7,(t shr 26) and $3f];
+ u:= r xor KeyData[i-4];
+ t:= r xor KeyData[i-3];
+ t:= (t shr 4) or (t shl 28);
+ l:= l xor des_SPtrans[0,(u shr 2) and $3f] xor
+ des_SPtrans[2,(u shr 10) and $3f] xor
+ des_SPtrans[4,(u shr 18) and $3f] xor
+ des_SPtrans[6,(u shr 26) and $3f] xor
+ des_SPtrans[1,(t shr 2) and $3f] xor
+ des_SPtrans[3,(t shr 10) and $3f] xor
+ des_SPtrans[5,(t shr 18) and $3f] xor
+ des_SPtrans[7,(t shr 26) and $3f];
+ u:= l xor KeyData[i-6];
+ t:= l xor KeyData[i-5];
+ t:= (t shr 4) or (t shl 28);
+ r:= r xor des_SPtrans[0,(u shr 2) and $3f] xor
+ des_SPtrans[2,(u shr 10) and $3f] xor
+ des_SPtrans[4,(u shr 18) and $3f] xor
+ des_SPtrans[6,(u shr 26) and $3f] xor
+ des_SPtrans[1,(t shr 2) and $3f] xor
+ des_SPtrans[3,(t shr 10) and $3f] xor
+ des_SPtrans[5,(t shr 18) and $3f] xor
+ des_SPtrans[7,(t shr 26) and $3f];
+ Dec(i,8);
+ end;
+ r:= (r shr 3) or (r shl 29);
+ l:= (l shr 3) or (l shl 29);
+ t:= ((r shr 1) xor l) and $55555555;
+ l:= l xor t;
+ r:= r xor (t shl 1);
+ t:= ((l shr 8) xor r) and $00ff00ff;
+ r:= r xor t;
+ l:= l xor (t shl 8);
+ t:= ((r shr 2) xor l) and $33333333;
+ l:= l xor t;
+ r:= r xor (t shl 2);
+ t:= ((l shr 16) xor r) and $0000ffff;
+ r:= r xor t;
+ l:= l xor (t shl 16);
+ t:= ((r shr 4) xor l) and $0f0f0f0f;
+ l:= l xor t;
+ r:= r xor (t shl 4);
+ Result := CodeLongInt(Swapbytes(l)) + CodeLongInt(Swapbytes(r));
+end;
+
+{==============================================================================}
+
+procedure TSynaDes.InitKey(Key: AnsiString);
+begin
+ Key := PadString(Key, 8, #0);
+ DoInit(Key,KeyData);
+end;
+
+function TSynaDes.EncryptECB(const InData: AnsiString): AnsiString;
+begin
+ Result := EncryptBlock(InData,KeyData);
+end;
+
+function TSynaDes.DecryptECB(const InData: AnsiString): AnsiString;
+begin
+ Result := DecryptBlock(Indata,KeyData);
+end;
+
+{==============================================================================}
+
+procedure TSyna3Des.InitKey(Key: AnsiString);
+var
+ Size: integer;
+ n: integer;
+begin
+ Size := length(Key);
+ key := PadString(key, 3 * 8, #0);
+ DoInit(Copy(key, 1, 8),KeyData[0]);
+ DoInit(Copy(key, 9, 8),KeyData[1]);
+ if Size > 16 then
+ DoInit(Copy(key, 17, 8),KeyData[2])
+ else
+ for n := 0 to high(KeyData[0]) do
+ KeyData[2][n] := Keydata[0][n];
+end;
+
+function TSyna3Des.EncryptECB(const InData: AnsiString): AnsiString;
+begin
+ Result := EncryptBlock(Indata,KeyData[0]);
+ Result := DecryptBlock(Result,KeyData[1]);
+ Result := EncryptBlock(Result,KeyData[2]);
+end;
+
+function TSyna3Des.DecryptECB(const InData: AnsiString): AnsiString;
+begin
+ Result := DecryptBlock(InData,KeyData[2]);
+ Result := EncryptBlock(Result,KeyData[1]);
+ Result := DecryptBlock(Result,KeyData[0]);
+end;
+
+{==============================================================================}
+
+function TestDes: boolean;
+var
+ des: TSynaDes;
+ s, t: string;
+const
+ key = '01234567';
+ data1= '01234567';
+ data2= '0123456789abcdefghij';
+begin
+ //ECB
+ des := TSynaDes.Create(key);
+ try
+ s := des.EncryptECB(data1);
+ t := strtohex(s);
+ result := t = 'c50ad028c6da9800';
+ s := des.DecryptECB(s);
+ result := result and (data1 = s);
+ finally
+ des.free;
+ end;
+ //CBC
+ des := TSynaDes.Create(key);
+ try
+ s := des.EncryptCBC(data2);
+ t := strtohex(s);
+ result := result and (t = 'eec50f6353115ad6dee90a22ed1b6a88a0926e35');
+ des.Reset;
+ s := des.DecryptCBC(s);
+ result := result and (data2 = s);
+ finally
+ des.free;
+ end;
+ //CFB-8bit
+ des := TSynaDes.Create(key);
+ try
+ s := des.EncryptCFB8bit(data2);
+ t := strtohex(s);
+ result := result and (t = 'eb6aa12c2f0ff634b4dfb6da6cb2af8f9c5c1452');
+ des.Reset;
+ s := des.DecryptCFB8bit(s);
+ result := result and (data2 = s);
+ finally
+ des.free;
+ end;
+ //CFB-block
+ des := TSynaDes.Create(key);
+ try
+ s := des.EncryptCFBblock(data2);
+ t := strtohex(s);
+ result := result and (t = 'ebdbbaa7f9286cdec28605e07f9b7f3be1053257');
+ des.Reset;
+ s := des.DecryptCFBblock(s);
+ result := result and (data2 = s);
+ finally
+ des.free;
+ end;
+ //OFB
+ des := TSynaDes.Create(key);
+ try
+ s := des.EncryptOFB(data2);
+ t := strtohex(s);
+ result := result and (t = 'ebdbbaa7f9286cdee0b8b3798c4c34baac87dbdc');
+ des.Reset;
+ s := des.DecryptOFB(s);
+ result := result and (data2 = s);
+ finally
+ des.free;
+ end;
+ //CTR
+ des := TSynaDes.Create(key);
+ try
+ s := des.EncryptCTR(data2);
+ t := strtohex(s);
+ result := result and (t = 'ebdbbaa7f9286cde0dd20b45f3afd9aa1b91b87e');
+ des.Reset;
+ s := des.DecryptCTR(s);
+ result := result and (data2 = s);
+ finally
+ des.free;
+ end;
+end;
+
+function Test3Des: boolean;
+var
+ des: TSyna3Des;
+ s, t: string;
+const
+ key = '0123456789abcdefghijklmn';
+ data1= '01234567';
+ data2= '0123456789abcdefghij';
+begin
+ //ECB
+ des := TSyna3Des.Create(key);
+ try
+ s := des.EncryptECB(data1);
+ t := strtohex(s);
+ result := t = 'e0dee91008dc460c';
+ s := des.DecryptECB(s);
+ result := result and (data1 = s);
+ finally
+ des.free;
+ end;
+ //CBC
+ des := TSyna3Des.Create(key);
+ try
+ s := des.EncryptCBC(data2);
+ t := strtohex(s);
+ result := result and (t = 'ee844a2a4f49c01b91a1599b8eba29128c1ad87a');
+ des.Reset;
+ s := des.DecryptCBC(s);
+ result := result and (data2 = s);
+ finally
+ des.free;
+ end;
+ //CFB-8bit
+ des := TSyna3Des.Create(key);
+ try
+ s := des.EncryptCFB8bit(data2);
+ t := strtohex(s);
+ result := result and (t = '935bbf5210c32cfa1faf61f91e8dc02dfa0ff1e8');
+ des.Reset;
+ s := des.DecryptCFB8bit(s);
+ result := result and (data2 = s);
+ finally
+ des.free;
+ end;
+ //CFB-block
+ des := TSyna3Des.Create(key);
+ try
+ s := des.EncryptCFBblock(data2);
+ t := strtohex(s);
+ result := result and (t = '93754e3d54828fbf4bd81f1739419e8d2cfe1671');
+ des.Reset;
+ s := des.DecryptCFBblock(s);
+ result := result and (data2 = s);
+ finally
+ des.free;
+ end;
+ //OFB
+ des := TSyna3Des.Create(key);
+ try
+ s := des.EncryptOFB(data2);
+ t := strtohex(s);
+ result := result and (t = '93754e3d54828fbf04ef0a5efc926ebdf2d95f20');
+ des.Reset;
+ s := des.DecryptOFB(s);
+ result := result and (data2 = s);
+ finally
+ des.free;
+ end;
+ //CTR
+ des := TSyna3Des.Create(key);
+ try
+ s := des.EncryptCTR(data2);
+ t := strtohex(s);
+ result := result and (t = '93754e3d54828fbf1c51a121d2c93f989e70b3ad');
+ des.Reset;
+ s := des.DecryptCTR(s);
+ result := result and (data2 = s);
+ finally
+ des.free;
+ end;
+end;
+
+{==============================================================================}
+
+end.
diff --git a/branches/script-component/Units/Synapse/synadbg.pas b/branches/script-component/Units/Synapse/synadbg.pas
new file mode 100644
index 0000000..ef84626
--- /dev/null
+++ b/branches/script-component/Units/Synapse/synadbg.pas
@@ -0,0 +1,152 @@
+{==============================================================================|
+| Project : Ararat Synapse | 001.001.000 |
+|==============================================================================|
+| Content: Socket debug tools |
+|==============================================================================|
+| Copyright (c)2008, Lukas Gebauer |
+| All rights reserved. |
+| |
+| Redistribution and use in source and binary forms, with or without |
+| modification, are permitted provided that the following conditions are met: |
+| |
+| Redistributions of source code must retain the above copyright notice, this |
+| list of conditions and the following disclaimer. |
+| |
+| Redistributions in binary form must reproduce the above copyright notice, |
+| this list of conditions and the following disclaimer in the documentation |
+| and/or other materials provided with the distribution. |
+| |
+| Neither the name of Lukas Gebauer nor the names of its contributors may |
+| be used to endorse or promote products derived from this software without |
+| specific prior written permission. |
+| |
+| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
+| AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
+| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
+| ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR |
+| ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
+| DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
+| SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
+| CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
+| LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
+| OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
+| DAMAGE. |
+|==============================================================================|
+| The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).|
+| Portions created by Lukas Gebauer are Copyright (c)2008. |
+| All Rights Reserved. |
+|==============================================================================|
+| Contributor(s): |
+|==============================================================================|
+| History: see HISTORY.HTM from distribution package |
+| (Found at URL: http://www.ararat.cz/synapse/) |
+|==============================================================================}
+
+{:@abstract(Socket debug tools)
+
+Routines for help with debugging of events on the Sockets.
+}
+
+
+unit synadbg;
+
+interface
+
+uses
+ blcksock, synsock, synautil, classes, sysutils;
+
+type
+ TSynaDebug = class(TObject)
+ class procedure HookStatus(Sender: TObject; Reason: THookSocketReason; const Value: string);
+ class procedure HookMonitor(Sender: TObject; Writing: Boolean; const Buffer: TMemory; Len: Integer);
+ end;
+
+procedure AppendToLog(const value: Ansistring);
+
+var
+ LogFile: string;
+
+implementation
+
+procedure AppendToLog(const value: Ansistring);
+var
+ st: TFileStream;
+ s: string;
+ h, m, ss, ms: word;
+ dt: Tdatetime;
+begin
+ if fileexists(LogFile) then
+ st := TFileStream.Create(LogFile, fmOpenReadWrite or fmShareDenyWrite)
+ else
+ st := TFileStream.Create(LogFile, fmCreate or fmShareDenyWrite);
+ try
+ st.Position := st.Size;
+ dt := now;
+ decodetime(dt, h, m, ss, ms);
+ s := formatdatetime('yyyymmdd-hhnnss', dt) + format('.%.3d', [ms]) + ' ' + value;
+ WriteStrToStream(st, s);
+ finally
+ st.free;
+ end;
+end;
+
+class procedure TSynaDebug.HookStatus(Sender: TObject; Reason: THookSocketReason; const Value: string);
+var
+ s: string;
+begin
+ case Reason of
+ HR_ResolvingBegin:
+ s := 'HR_ResolvingBegin';
+ HR_ResolvingEnd:
+ s := 'HR_ResolvingEnd';
+ HR_SocketCreate:
+ s := 'HR_SocketCreate';
+ HR_SocketClose:
+ s := 'HR_SocketClose';
+ HR_Bind:
+ s := 'HR_Bind';
+ HR_Connect:
+ s := 'HR_Connect';
+ HR_CanRead:
+ s := 'HR_CanRead';
+ HR_CanWrite:
+ s := 'HR_CanWrite';
+ HR_Listen:
+ s := 'HR_Listen';
+ HR_Accept:
+ s := 'HR_Accept';
+ HR_ReadCount:
+ s := 'HR_ReadCount';
+ HR_WriteCount:
+ s := 'HR_WriteCount';
+ HR_Wait:
+ s := 'HR_Wait';
+ HR_Error:
+ s := 'HR_Error';
+ else
+ s := '-unknown-';
+ end;
+ s := inttohex(integer(Sender), 8) + s + ': ' + value + CRLF;
+ AppendToLog(s);
+end;
+
+class procedure TSynaDebug.HookMonitor(Sender: TObject; Writing: Boolean; const Buffer: TMemory; Len: Integer);
+var
+ s, d: Ansistring;
+begin
+ setlength(s, len);
+ move(Buffer^, pointer(s)^, len);
+ if writing then
+ d := '-> '
+ else
+ d := '<- ';
+ s :=inttohex(integer(Sender), 8) + d + s + CRLF;
+ AppendToLog(s);
+end;
+
+initialization
+begin
+ Logfile := changefileext(paramstr(0), '.slog');
+end;
+
+end.
diff --git a/branches/script-component/Units/Synapse/synafpc.pas b/branches/script-component/Units/Synapse/synafpc.pas
new file mode 100644
index 0000000..a3d580b
--- /dev/null
+++ b/branches/script-component/Units/Synapse/synafpc.pas
@@ -0,0 +1,131 @@
+{==============================================================================|
+| Project : Ararat Synapse | 001.001.001 |
+|==============================================================================|
+| Content: Utils for FreePascal compatibility |
+|==============================================================================|
+| Copyright (c)1999-2007, Lukas Gebauer |
+| All rights reserved. |
+| |
+| Redistribution and use in source and binary forms, with or without |
+| modification, are permitted provided that the following conditions are met: |
+| |
+| Redistributions of source code must retain the above copyright notice, this |
+| list of conditions and the following disclaimer. |
+| |
+| Redistributions in binary form must reproduce the above copyright notice, |
+| this list of conditions and the following disclaimer in the documentation |
+| and/or other materials provided with the distribution. |
+| |
+| Neither the name of Lukas Gebauer nor the names of its contributors may |
+| be used to endorse or promote products derived from this software without |
+| specific prior written permission. |
+| |
+| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
+| AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
+| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
+| ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR |
+| ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
+| DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
+| SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
+| CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
+| LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
+| OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
+| DAMAGE. |
+|==============================================================================|
+| The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).|
+| Portions created by Lukas Gebauer are Copyright (c)2003-2007. |
+| All Rights Reserved. |
+|==============================================================================|
+| Contributor(s): |
+|==============================================================================|
+| History: see HISTORY.HTM from distribution package |
+| (Found at URL: http://www.ararat.cz/synapse/) |
+|==============================================================================}
+
+{:@exclude}
+
+{$IFDEF FPC}
+ {$MODE DELPHI}
+{$ENDIF}
+{$H+}
+
+unit synafpc;
+
+interface
+
+uses
+{$IFDEF FPC}
+ dynlibs, sysutils;
+{$ELSE}
+ {$IFDEF WIN32}
+ Windows;
+ {$ELSE}
+ SysUtils;
+ {$ENDIF}
+{$ENDIF}
+
+{$IFDEF FPC}
+type
+ TLibHandle = dynlibs.TLibHandle;
+
+function LoadLibrary(ModuleName: PChar): TLibHandle;
+function FreeLibrary(Module: TLibHandle): LongBool;
+function GetProcAddress(Module: TLibHandle; Proc: PChar): Pointer;
+function GetModuleFileName(Module: TLibHandle; Buffer: PChar; BufLen: Integer): Integer;
+{$ELSE}
+type
+ {$IFDEF CIL}
+ TLibHandle = Integer;
+ {$ELSE}
+ TLibHandle = HModule;
+ {$ENDIF}
+ {$IFDEF VER100}
+ LongWord = DWord;
+ {$ENDIF}
+{$ENDIF}
+
+procedure Sleep(milliseconds: Cardinal);
+
+
+implementation
+
+{==============================================================================}
+{$IFDEF FPC}
+function LoadLibrary(ModuleName: PChar): TLibHandle;
+begin
+ Result := dynlibs.LoadLibrary(Modulename);
+end;
+
+function FreeLibrary(Module: TLibHandle): LongBool;
+begin
+ Result := dynlibs.UnloadLibrary(Module);
+end;
+
+function GetProcAddress(Module: TLibHandle; Proc: PChar): Pointer;
+begin
+ Result := dynlibs.GetProcedureAddress(Module, Proc);
+end;
+
+function GetModuleFileName(Module: TLibHandle; Buffer: PChar; BufLen: Integer): Integer;
+begin
+ Result := 0;
+end;
+
+{$ELSE}
+{$ENDIF}
+
+procedure Sleep(milliseconds: Cardinal);
+begin
+{$IFDEF WIN32}
+ {$IFDEF FPC}
+ sysutils.sleep(milliseconds);
+ {$ELSE}
+ windows.sleep(milliseconds);
+ {$ENDIF}
+{$ELSE}
+ sysutils.sleep(milliseconds);
+{$ENDIF}
+
+end;
+
+end.
diff --git a/branches/script-component/Units/Synapse/synaicnv.pas b/branches/script-component/Units/Synapse/synaicnv.pas
new file mode 100644
index 0000000..8d01b74
--- /dev/null
+++ b/branches/script-component/Units/Synapse/synaicnv.pas
@@ -0,0 +1,357 @@
+{==============================================================================|
+| Project : Ararat Synapse | 001.001.000 |
+|==============================================================================|
+| Content: ICONV support for Win32, Linux and .NET |
+|==============================================================================|
+| Copyright (c)2004-2008, Lukas Gebauer |
+| All rights reserved. |
+| |
+| Redistribution and use in source and binary forms, with or without |
+| modification, are permitted provided that the following conditions are met: |
+| |
+| Redistributions of source code must retain the above copyright notice, this |
+| list of conditions and the following disclaimer. |
+| |
+| Redistributions in binary form must reproduce the above copyright notice, |
+| this list of conditions and the following disclaimer in the documentation |
+| and/or other materials provided with the distribution. |
+| |
+| Neither the name of Lukas Gebauer nor the names of its contributors may |
+| be used to endorse or promote products derived from this software without |
+| specific prior written permission. |
+| |
+| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
+| AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
+| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
+| ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR |
+| ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
+| DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
+| SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
+| CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
+| LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
+| OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
+| DAMAGE. |
+|==============================================================================|
+| The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).|
+| Portions created by Lukas Gebauer are Copyright (c)2004-2008. |
+| All Rights Reserved. |
+|==============================================================================|
+| Contributor(s): |
+|==============================================================================|
+| History: see HISTORY.HTM from distribution package |
+| (Found at URL: http://www.ararat.cz/synapse/) |
+|==============================================================================}
+
+{$IFDEF FPC}
+ {$MODE DELPHI}
+{$ENDIF}
+{$H+}
+
+{:@abstract(LibIconv support)
+
+This unit is Pascal interface to LibIconv library for charset translations.
+LibIconv is loaded dynamicly on-demand. If this library is not found in system,
+requested LibIconv function just return errorcode.
+}
+unit synaicnv;
+
+interface
+
+uses
+{$IFDEF CIL}
+ System.Runtime.InteropServices,
+ System.Text,
+{$ENDIF}
+ synafpc,
+{$IFNDEF WIN32}
+ {$IFNDEF FPC}
+ Libc,
+ {$ENDIF}
+ SysUtils;
+{$ELSE}
+ Windows;
+{$ENDIF}
+
+
+const
+ {$IFNDEF WIN32}
+ DLLIconvName = 'libiconv.so';
+ {$ELSE}
+ DLLIconvName = 'iconv.dll';
+ {$ENDIF}
+
+type
+ size_t = Cardinal;
+{$IFDEF CIL}
+ iconv_t = IntPtr;
+{$ELSE}
+ iconv_t = Pointer;
+{$ENDIF}
+ argptr = iconv_t;
+
+var
+ iconvLibHandle: TLibHandle = 0;
+
+function SynaIconvOpen(const tocode, fromcode: Ansistring): iconv_t;
+function SynaIconvOpenTranslit(const tocode, fromcode: Ansistring): iconv_t;
+function SynaIconvOpenIgnore(const tocode, fromcode: Ansistring): iconv_t;
+function SynaIconv(cd: iconv_t; inbuf: AnsiString; var outbuf: AnsiString): integer;
+function SynaIconvClose(var cd: iconv_t): integer;
+function SynaIconvCtl(cd: iconv_t; request: integer; argument: argptr): integer;
+
+function IsIconvloaded: Boolean;
+function InitIconvInterface: Boolean;
+function DestroyIconvInterface: Boolean;
+
+const
+ ICONV_TRIVIALP = 0; // int *argument
+ ICONV_GET_TRANSLITERATE = 1; // int *argument
+ ICONV_SET_TRANSLITERATE = 2; // const int *argument
+ ICONV_GET_DISCARD_ILSEQ = 3; // int *argument
+ ICONV_SET_DISCARD_ILSEQ = 4; // const int *argument
+
+
+implementation
+
+uses SyncObjs;
+
+{$IFDEF CIL}
+ [DllImport(DLLIconvName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'libiconv_open')]
+ function _iconv_open(tocode: string; fromcode: string): iconv_t; external;
+
+ [DllImport(DLLIconvName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'libiconv')]
+ function _iconv(cd: iconv_t; var inbuf: IntPtr; var inbytesleft: size_t;
+ var outbuf: IntPtr; var outbytesleft: size_t): size_t; external;
+
+ [DllImport(DLLIconvName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'libiconv_close')]
+ function _iconv_close(cd: iconv_t): integer; external;
+
+ [DllImport(DLLIconvName, CharSet = CharSet.Ansi,
+ SetLastError = False, CallingConvention= CallingConvention.cdecl,
+ EntryPoint = 'libiconvctl')]
+ function _iconvctl(cd: iconv_t; request: integer; argument: argptr): integer; external;
+
+{$ELSE}
+type
+ Ticonv_open = function(tocode: pAnsichar; fromcode: pAnsichar): iconv_t; cdecl;
+ Ticonv = function(cd: iconv_t; var inbuf: pointer; var inbytesleft: size_t;
+ var outbuf: pointer; var outbytesleft: size_t): size_t; cdecl;
+ Ticonv_close = function(cd: iconv_t): integer; cdecl;
+ Ticonvctl = function(cd: iconv_t; request: integer; argument: argptr): integer; cdecl;
+var
+ _iconv_open: Ticonv_open = nil;
+ _iconv: Ticonv = nil;
+ _iconv_close: Ticonv_close = nil;
+ _iconvctl: Ticonvctl = nil;
+{$ENDIF}
+
+
+var
+ IconvCS: TCriticalSection;
+ Iconvloaded: boolean = false;
+
+function SynaIconvOpen (const tocode, fromcode: Ansistring): iconv_t;
+begin
+{$IFDEF CIL}
+ try
+ Result := _iconv_open(tocode, fromcode);
+ except
+ on Exception do
+ Result := iconv_t(-1);
+ end;
+{$ELSE}
+ if InitIconvInterface and Assigned(_iconv_open) then
+ Result := _iconv_open(PAnsiChar(tocode), PAnsiChar(fromcode))
+ else
+ Result := iconv_t(-1);
+{$ENDIF}
+end;
+
+function SynaIconvOpenTranslit (const tocode, fromcode: Ansistring): iconv_t;
+begin
+ Result := SynaIconvOpen(tocode + '//IGNORE//TRANSLIT', fromcode);
+end;
+
+function SynaIconvOpenIgnore (const tocode, fromcode: Ansistring): iconv_t;
+begin
+ Result := SynaIconvOpen(tocode + '//IGNORE', fromcode);
+end;
+
+function SynaIconv (cd: iconv_t; inbuf: AnsiString; var outbuf: AnsiString): integer;
+var
+{$IFDEF CIL}
+ ib, ob: IntPtr;
+ ibsave, obsave: IntPtr;
+ l: integer;
+{$ELSE}
+ ib, ob: Pointer;
+{$ENDIF}
+ ix, ox: size_t;
+begin
+{$IFDEF CIL}
+ l := Length(inbuf) * 4;
+ ibsave := IntPtr.Zero;
+ obsave := IntPtr.Zero;
+ try
+ ibsave := Marshal.StringToHGlobalAnsi(inbuf);
+ obsave := Marshal.AllocHGlobal(l);
+ ib := ibsave;
+ ob := obsave;
+ ix := Length(inbuf);
+ ox := l;
+ _iconv(cd, ib, ix, ob, ox);
+ Outbuf := Marshal.PtrToStringAnsi(obsave, l);
+ setlength(Outbuf, l - ox);
+ Result := Length(inbuf) - ix;
+ finally
+ Marshal.FreeCoTaskMem(ibsave);
+ Marshal.FreeHGlobal(obsave);
+ end;
+{$ELSE}
+ if InitIconvInterface and Assigned(_iconv) then
+ begin
+ setlength(Outbuf, Length(inbuf) * 4);
+ ib := Pointer(inbuf);
+ ob := Pointer(Outbuf);
+ ix := Length(inbuf);
+ ox := Length(Outbuf);
+ _iconv(cd, ib, ix, ob, ox);
+ setlength(Outbuf, cardinal(Length(Outbuf)) - ox);
+ Result := Cardinal(Length(inbuf)) - ix;
+ end
+ else
+ begin
+ Outbuf := '';
+ Result := 0;
+ end;
+{$ENDIF}
+end;
+
+function SynaIconvClose(var cd: iconv_t): integer;
+begin
+ if cd = iconv_t(-1) then
+ begin
+ Result := 0;
+ Exit;
+ end;
+{$IFDEF CIL}
+ try;
+ Result := _iconv_close(cd)
+ except
+ on Exception do
+ Result := -1;
+ end;
+ cd := iconv_t(-1);
+{$ELSE}
+ if InitIconvInterface and Assigned(_iconv_close) then
+ Result := _iconv_close(cd)
+ else
+ Result := -1;
+ cd := iconv_t(-1);
+{$ENDIF}
+end;
+
+function SynaIconvCtl (cd: iconv_t; request: integer; argument: argptr): integer;
+begin
+{$IFDEF CIL}
+ Result := _iconvctl(cd, request, argument)
+{$ELSE}
+ if InitIconvInterface and Assigned(_iconvctl) then
+ Result := _iconvctl(cd, request, argument)
+ else
+ Result := 0;
+{$ENDIF}
+end;
+
+function InitIconvInterface: Boolean;
+begin
+ IconvCS.Enter;
+ try
+ if not IsIconvloaded then
+ begin
+{$IFDEF CIL}
+ IconvLibHandle := 1;
+{$ELSE}
+ IconvLibHandle := LoadLibrary(PChar(DLLIconvName));
+{$ENDIF}
+ if (IconvLibHandle <> 0) then
+ begin
+{$IFNDEF CIL}
+ _iconv_open := GetProcAddress(IconvLibHandle, PAnsiChar(AnsiString('libiconv_open')));
+ _iconv := GetProcAddress(IconvLibHandle, PAnsiChar(AnsiString('libiconv')));
+ _iconv_close := GetProcAddress(IconvLibHandle, PAnsiChar(AnsiString('libiconv_close')));
+ _iconvctl := GetProcAddress(IconvLibHandle, PAnsiChar(AnsiString('libiconvctl')));
+{$ENDIF}
+ Result := True;
+ Iconvloaded := True;
+ end
+ else
+ begin
+ //load failed!
+ if IconvLibHandle <> 0 then
+ begin
+{$IFNDEF CIL}
+ FreeLibrary(IconvLibHandle);
+{$ENDIF}
+ IconvLibHandle := 0;
+ end;
+ Result := False;
+ end;
+ end
+ else
+ //loaded before...
+ Result := true;
+ finally
+ IconvCS.Leave;
+ end;
+end;
+
+function DestroyIconvInterface: Boolean;
+begin
+ IconvCS.Enter;
+ try
+ Iconvloaded := false;
+ if IconvLibHandle <> 0 then
+ begin
+{$IFNDEF CIL}
+ FreeLibrary(IconvLibHandle);
+{$ENDIF}
+ IconvLibHandle := 0;
+ end;
+{$IFNDEF CIL}
+ _iconv_open := nil;
+ _iconv := nil;
+ _iconv_close := nil;
+ _iconvctl := nil;
+{$ENDIF}
+ finally
+ IconvCS.Leave;
+ end;
+ Result := True;
+end;
+
+function IsIconvloaded: Boolean;
+begin
+ Result := IconvLoaded;
+end;
+
+ initialization
+begin
+ IconvCS:= TCriticalSection.Create;
+end;
+
+finalization
+begin
+{$IFNDEF CIL}
+ DestroyIconvInterface;
+{$ENDIF}
+ IconvCS.Free;
+end;
+
+end.
diff --git a/branches/script-component/Units/Synapse/synaip.pas b/branches/script-component/Units/Synapse/synaip.pas
new file mode 100644
index 0000000..01c0691
--- /dev/null
+++ b/branches/script-component/Units/Synapse/synaip.pas
@@ -0,0 +1,416 @@
+{==============================================================================|
+| Project : Ararat Synapse | 001.002.000 |
+|==============================================================================|
+| Content: IP address support procedures and functions |
+|==============================================================================|
+| Copyright (c)2006-2009, Lukas Gebauer |
+| All rights reserved. |
+| |
+| Redistribution and use in source and binary forms, with or without |
+| modification, are permitted provided that the following conditions are met: |
+| |
+| Redistributions of source code must retain the above copyright notice, this |
+| list of conditions and the following disclaimer. |
+| |
+| Redistributions in binary form must reproduce the above copyright notice, |
+| this list of conditions and the following disclaimer in the documentation |
+| and/or other materials provided with the distribution. |
+| |
+| Neither the name of Lukas Gebauer nor the names of its contributors may |
+| be used to endorse or promote products derived from this software without |
+| specific prior written permission. |
+| |
+| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
+| AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
+| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
+| ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR |
+| ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
+| DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
+| SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
+| CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
+| LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
+| OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
+| DAMAGE. |
+|==============================================================================|
+| The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).|
+| Portions created by Lukas Gebauer are Copyright (c) 2006-2008. |
+| All Rights Reserved. |
+|==============================================================================|
+| Contributor(s): |
+|==============================================================================|
+| History: see HISTORY.HTM from distribution package |
+| (Found at URL: http://www.ararat.cz/synapse/) |
+|==============================================================================}
+
+{:@abstract(IP adress support procedures and functions)}
+
+{$IFDEF FPC}
+ {$MODE DELPHI}
+{$ENDIF}
+{$Q-}
+{$R-}
+{$H+}
+
+unit synaip;
+
+interface
+
+uses
+ SysUtils, SynaUtil;
+
+type
+{:binary form of IPv6 adress (for string conversion routines)}
+ TIp6Bytes = array [0..15] of Byte;
+{:binary form of IPv6 adress (for string conversion routines)}
+ TIp6Words = array [0..7] of Word;
+
+{:Returns @TRUE, if "Value" is a valid IPv4 address. Cannot be a symbolic Name!}
+function IsIP(const Value: string): Boolean;
+
+{:Returns @TRUE, if "Value" is a valid IPv6 address. Cannot be a symbolic Name!}
+function IsIP6(const Value: string): Boolean;
+
+{:Returns a string with the "Host" ip address converted to binary form.}
+function IPToID(Host: string): Ansistring;
+
+{:Convert IPv6 address from their string form to binary byte array.}
+function StrToIp6(value: string): TIp6Bytes;
+
+{:Convert IPv6 address from binary byte array to string form.}
+function Ip6ToStr(value: TIp6Bytes): string;
+
+{:Convert IPv4 address from their string form to binary.}
+function StrToIp(value: string): integer;
+
+{:Convert IPv4 address from binary to string form.}
+function IpToStr(value: integer): string;
+
+{:Convert IPv4 address to reverse form.}
+function ReverseIP(Value: AnsiString): AnsiString;
+
+{:Convert IPv6 address to reverse form.}
+function ReverseIP6(Value: AnsiString): AnsiString;
+
+{:Expand short form of IPv6 address to long form.}
+function ExpandIP6(Value: AnsiString): AnsiString;
+
+
+implementation
+
+{==============================================================================}
+
+function IsIP(const Value: string): Boolean;
+var
+ TempIP: string;
+ function ByteIsOk(const Value: string): Boolean;
+ var
+ x, n: integer;
+ begin
+ x := StrToIntDef(Value, -1);
+ Result := (x >= 0) and (x < 256);
+ // X may be in correct range, but value still may not be correct value!
+ // i.e. "$80"
+ if Result then
+ for n := 1 to length(Value) do
+ if not (Value[n] in ['0'..'9']) then
+ begin
+ Result := False;
+ Break;
+ end;
+ end;
+begin
+ TempIP := Value;
+ Result := False;
+ if not ByteIsOk(Fetch(TempIP, '.')) then
+ Exit;
+ if not ByteIsOk(Fetch(TempIP, '.')) then
+ Exit;
+ if not ByteIsOk(Fetch(TempIP, '.')) then
+ Exit;
+ if ByteIsOk(TempIP) then
+ Result := True;
+end;
+
+{==============================================================================}
+
+function IsIP6(const Value: string): Boolean;
+var
+ TempIP: string;
+ s,t: string;
+ x: integer;
+ partcount: integer;
+ zerocount: integer;
+ First: Boolean;
+begin
+ TempIP := Value;
+ Result := False;
+ if Value = '::' then
+ begin
+ Result := True;
+ Exit;
+ end;
+ partcount := 0;
+ zerocount := 0;
+ First := True;
+ while tempIP <> '' do
+ begin
+ s := fetch(TempIP, ':');
+ if not(First) and (s = '') then
+ Inc(zerocount);
+ First := False;
+ if zerocount > 1 then
+ break;
+ Inc(partCount);
+ if s = '' then
+ Continue;
+ if partCount > 8 then
+ break;
+ if tempIP = '' then
+ begin
+ t := SeparateRight(s, '%');
+ s := SeparateLeft(s, '%');
+ x := StrToIntDef('$' + t, -1);
+ if (x < 0) or (x > $ffff) then
+ break;
+ end;
+ x := StrToIntDef('$' + s, -1);
+ if (x < 0) or (x > $ffff) then
+ break;
+ if tempIP = '' then
+ if not((PartCount = 1) and (ZeroCount = 0)) then
+ Result := True;
+ end;
+end;
+
+{==============================================================================}
+function IPToID(Host: string): Ansistring;
+var
+ s: string;
+ i, x: Integer;
+begin
+ Result := '';
+ for x := 0 to 3 do
+ begin
+ s := Fetch(Host, '.');
+ i := StrToIntDef(s, 0);
+ Result := Result + Chr(i);
+ end;
+end;
+
+{==============================================================================}
+
+function StrToIp(value: string): integer;
+var
+ s: string;
+ i, x: Integer;
+begin
+ Result := 0;
+ for x := 0 to 3 do
+ begin
+ s := Fetch(value, '.');
+ i := StrToIntDef(s, 0);
+ Result := (256 * Result) + i;
+ end;
+end;
+
+{==============================================================================}
+
+function IpToStr(value: integer): string;
+var
+ x1, x2: word;
+ y1, y2: byte;
+begin
+ Result := '';
+ x1 := value shr 16;
+ x2 := value and $FFFF;
+ y1 := x1 div $100;
+ y2 := x1 mod $100;
+ Result := inttostr(y1) + '.' + inttostr(y2) + '.';
+ y1 := x2 div $100;
+ y2 := x2 mod $100;
+ Result := Result + inttostr(y1) + '.' + inttostr(y2);
+end;
+
+{==============================================================================}
+
+function ExpandIP6(Value: AnsiString): AnsiString;
+var
+ n: integer;
+ s: ansistring;
+ x: integer;
+begin
+ Result := '';
+ if value = '' then
+ exit;
+ x := countofchar(value, ':');
+ if x > 7 then
+ exit;
+ if value[1] = ':' then
+ value := '0' + value;
+ if value[length(value)] = ':' then
+ value := value + '0';
+ x := 8 - x;
+ s := '';
+ for n := 1 to x do
+ s := s + ':0';
+ s := s + ':';
+ Result := replacestring(value, '::', s);
+end;
+{==============================================================================}
+
+function StrToIp6(Value: string): TIp6Bytes;
+var
+ IPv6: TIp6Words;
+ Index: Integer;
+ n: integer;
+ b1, b2: byte;
+ s: string;
+ x: integer;
+begin
+ for n := 0 to 15 do
+ Result[n] := 0;
+ for n := 0 to 7 do
+ Ipv6[n] := 0;
+ Index := 0;
+ Value := ExpandIP6(value);
+ if value = '' then
+ exit;
+ while Value <> '' do
+ begin
+ if Index > 7 then
+ Exit;
+ s := fetch(value, ':');
+ if s = '@' then
+ break;
+ if s = '' then
+ begin
+ IPv6[Index] := 0;
+ end
+ else
+ begin
+ x := StrToIntDef('$' + s, -1);
+ if (x > 65535) or (x < 0) then
+ Exit;
+ IPv6[Index] := x;
+ end;
+ Inc(Index);
+ end;
+ for n := 0 to 7 do
+ begin
+ b1 := ipv6[n] div 256;
+ b2 := ipv6[n] mod 256;
+ Result[n * 2] := b1;
+ Result[(n * 2) + 1] := b2;
+ end;
+end;
+
+{==============================================================================}
+//based on routine by the Free Pascal development team
+function Ip6ToStr(value: TIp6Bytes): string;
+var
+ i, x: byte;
+ zr1,zr2: set of byte;
+ zc1,zc2: byte;
+ have_skipped: boolean;
+ ip6w: TIp6words;
+begin
+ zr1 := [];
+ zr2 := [];
+ zc1 := 0;
+ zc2 := 0;
+ for i := 0 to 7 do
+ begin
+ x := i * 2;
+ ip6w[i] := value[x] * 256 + value[x + 1];
+ if ip6w[i] = 0 then
+ begin
+ include(zr2, i);
+ inc(zc2);
+ end
+ else
+ begin
+ if zc1 < zc2 then
+ begin
+ zc1 := zc2;
+ zr1 := zr2;
+ zc2 := 0;
+ zr2 := [];
+ end;
+ end;
+ end;
+ if zc1 < zc2 then
+ begin
+ zr1 := zr2;
+ end;
+ SetLength(Result, 8*5-1);
+ SetLength(Result, 0);
+ have_skipped := false;
+ for i := 0 to 7 do
+ begin
+ if not(i in zr1) then
+ begin
+ if have_skipped then
+ begin
+ if Result = '' then
+ Result := '::'
+ else
+ Result := Result + ':';
+ have_skipped := false;
+ end;
+ Result := Result + IntToHex(Ip6w[i], 1) + ':';
+ end
+ else
+ begin
+ have_skipped := true;
+ end;
+ end;
+ if have_skipped then
+ if Result = '' then
+ Result := '::0'
+ else
+ Result := Result + ':';
+
+ if Result = '' then
+ Result := '::0';
+ if not (7 in zr1) then
+ SetLength(Result, Length(Result)-1);
+ Result := LowerCase(result);
+end;
+
+{==============================================================================}
+function ReverseIP(Value: AnsiString): AnsiString;
+var
+ x: Integer;
+begin
+ Result := '';
+ repeat
+ x := LastDelimiter('.', Value);
+ Result := Result + '.' + Copy(Value, x + 1, Length(Value) - x);
+ Delete(Value, x, Length(Value) - x + 1);
+ until x < 1;
+ if Length(Result) > 0 then
+ if Result[1] = '.' then
+ Delete(Result, 1, 1);
+end;
+
+{==============================================================================}
+function ReverseIP6(Value: AnsiString): AnsiString;
+var
+ ip6: TIp6bytes;
+ n: integer;
+ x, y: integer;
+begin
+ ip6 := StrToIP6(Value);
+ x := ip6[15] div 16;
+ y := ip6[15] mod 16;
+ Result := IntToHex(y, 1) + '.' + IntToHex(x, 1);
+ for n := 14 downto 0 do
+ begin
+ x := ip6[n] div 16;
+ y := ip6[n] mod 16;
+ Result := Result + '.' + IntToHex(y, 1) + '.' + IntToHex(x, 1);
+ end;
+end;
+
+{==============================================================================}
+end.
diff --git a/branches/script-component/Units/Synapse/synamisc.pas b/branches/script-component/Units/Synapse/synamisc.pas
new file mode 100644
index 0000000..354fa45
--- /dev/null
+++ b/branches/script-component/Units/Synapse/synamisc.pas
@@ -0,0 +1,389 @@
+{==============================================================================|
+| Project : Ararat Synapse | 001.003.000 |
+|==============================================================================|
+| Content: misc. procedures and functions |
+|==============================================================================|
+| Copyright (c)1999-2008, Lukas Gebauer |
+| All rights reserved. |
+| |
+| Redistribution and use in source and binary forms, with or without |
+| modification, are permitted provided that the following conditions are met: |
+| |
+| Redistributions of source code must retain the above copyright notice, this |
+| list of conditions and the following disclaimer. |
+| |
+| Redistributions in binary form must reproduce the above copyright notice, |
+| this list of conditions and the following disclaimer in the documentation |
+| and/or other materials provided with the distribution. |
+| |
+| Neither the name of Lukas Gebauer nor the names of its contributors may |
+| be used to endorse or promote products derived from this software without |
+| specific prior written permission. |
+| |
+| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
+| AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
+| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
+| ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR |
+| ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
+| DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
+| SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
+| CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
+| LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
+| OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
+| DAMAGE. |
+|==============================================================================|
+| The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).|
+| Portions created by Lukas Gebauer are Copyright (c) 2002-2008. |
+| All Rights Reserved. |
+|==============================================================================|
+| Contributor(s): |
+|==============================================================================|
+| History: see HISTORY.HTM from distribution package |
+| (Found at URL: http://www.ararat.cz/synapse/) |
+|==============================================================================}
+
+{:@abstract(Misc. network based utilities)}
+
+{$IFDEF FPC}
+ {$MODE DELPHI}
+{$ENDIF}
+{$Q-}
+{$H+}
+
+unit synamisc;
+
+interface
+
+{$IFDEF VER125}
+ {$DEFINE BCB}
+{$ENDIF}
+{$IFDEF BCB}
+ {$ObjExportAll On}
+ {$HPPEMIT '#pragma comment( lib , "wininet.lib" )'}
+{$ENDIF}
+
+uses
+ synautil, blcksock, SysUtils, Classes,
+{$IFDEF LINUX}
+ Libc;
+{$ELSE}
+ Windows;
+{$ENDIF}
+
+Type
+ {:@abstract(This record contains information about proxy setting.)}
+ TProxySetting = record
+ Host: string;
+ Port: string;
+ Bypass: string;
+ end;
+
+{:By this function you can turn-on computer on network, if this computer
+ supporting Wake-on-lan feature. You need MAC number (network card indentifier)
+ of computer for turn-on. You can also assign target IP addres. If you not
+ specify it, then is used broadcast for delivery magic wake-on packet. However
+ broadcasts workinh only on your local network. When you need to wake-up
+ computer on another network, you must specify any existing IP addres on same
+ network segment as targeting computer.}
+procedure WakeOnLan(MAC, IP: string);
+
+{:Autodetect current DNS servers used by system. If is defined more then one DNS
+ server, then result is comma-delimited.}
+function GetDNS: string;
+
+{:Autodetect InternetExplorer proxy setting for given protocol. This function
+working only on windows!}
+function GetIEProxy(protocol: string): TProxySetting;
+
+{:Return all known IP addresses on local system. Addresses are divided by comma.}
+function GetLocalIPs: string;
+
+implementation
+
+{==============================================================================}
+procedure WakeOnLan(MAC, IP: string);
+var
+ sock: TUDPBlockSocket;
+ HexMac: Ansistring;
+ data: Ansistring;
+ n: integer;
+ b: Byte;
+begin
+ if MAC <> '' then
+ begin
+ MAC := ReplaceString(MAC, '-', '');
+ MAC := ReplaceString(MAC, ':', '');
+ if Length(MAC) < 12 then
+ Exit;
+ HexMac := '';
+ for n := 0 to 5 do
+ begin
+ b := StrToIntDef('$' + MAC[n * 2 + 1] + MAC[n * 2 + 2], 0);
+ HexMac := HexMac + char(b);
+ end;
+ if IP = '' then
+ IP := cBroadcast;
+ sock := TUDPBlockSocket.Create;
+ try
+ sock.CreateSocket;
+ sock.EnableBroadcast(true);
+ sock.Connect(IP, '9');
+ data := #$FF + #$FF + #$FF + #$FF + #$FF + #$FF;
+ for n := 1 to 16 do
+ data := data + HexMac;
+ sock.SendString(data);
+ finally
+ sock.Free;
+ end;
+ end;
+end;
+
+{==============================================================================}
+
+{$IFNDEF LINUX}
+function GetDNSbyIpHlp: string;
+type
+ PTIP_ADDRESS_STRING = ^TIP_ADDRESS_STRING;
+ TIP_ADDRESS_STRING = array[0..15] of Ansichar;
+ PTIP_ADDR_STRING = ^TIP_ADDR_STRING;
+ TIP_ADDR_STRING = packed record
+ Next: PTIP_ADDR_STRING;
+ IpAddress: TIP_ADDRESS_STRING;
+ IpMask: TIP_ADDRESS_STRING;
+ Context: DWORD;
+ end;
+ PTFixedInfo = ^TFixedInfo;
+ TFixedInfo = packed record
+ HostName: array[1..128 + 4] of Ansichar;
+ DomainName: array[1..128 + 4] of Ansichar;
+ CurrentDNSServer: PTIP_ADDR_STRING;
+ DNSServerList: TIP_ADDR_STRING;
+ NodeType: UINT;
+ ScopeID: array[1..256 + 4] of Ansichar;
+ EnableRouting: UINT;
+ EnableProxy: UINT;
+ EnableDNS: UINT;
+ end;
+const
+ IpHlpDLL = 'IPHLPAPI.DLL';
+var
+ IpHlpModule: THandle;
+ FixedInfo: PTFixedInfo;
+ InfoSize: Longint;
+ PDnsServer: PTIP_ADDR_STRING;
+ err: integer;
+ GetNetworkParams: function(FixedInfo: PTFixedInfo; pOutPutLen: PULONG): DWORD; stdcall;
+begin
+ InfoSize := 0;
+ Result := '...';
+ IpHlpModule := LoadLibrary(IpHlpDLL);
+ if IpHlpModule = 0 then
+ exit;
+ try
+ GetNetworkParams := GetProcAddress(IpHlpModule,PAnsiChar(AnsiString('GetNetworkParams')));
+ if @GetNetworkParams = nil then
+ Exit;
+ err := GetNetworkParams(Nil, @InfoSize);
+ if err <> ERROR_BUFFER_OVERFLOW then
+ Exit;
+ Result := '';
+ GetMem (FixedInfo, InfoSize);
+ try
+ err := GetNetworkParams(FixedInfo, @InfoSize);
+ if err <> ERROR_SUCCESS then
+ exit;
+ with FixedInfo^ do
+ begin
+ Result := DnsServerList.IpAddress;
+ PDnsServer := DnsServerList.Next;
+ while PDnsServer <> Nil do
+ begin
+ if Result <> '' then
+ Result := Result + ',';
+ Result := Result + PDnsServer^.IPAddress;
+ PDnsServer := PDnsServer.Next;
+ end;
+ end;
+ finally
+ FreeMem(FixedInfo);
+ end;
+ finally
+ FreeLibrary(IpHlpModule);
+ end;
+end;
+
+function ReadReg(SubKey, Vn: PChar): string;
+var
+ OpenKey: HKEY;
+ DataType, DataSize: integer;
+ Temp: array [0..2048] of char;
+begin
+ Result := '';
+ if RegOpenKeyEx(HKEY_LOCAL_MACHINE, SubKey, REG_OPTION_NON_VOLATILE,
+ KEY_READ, OpenKey) = ERROR_SUCCESS then
+ begin
+ DataType := REG_SZ;
+ DataSize := SizeOf(Temp);
+ if RegQueryValueEx(OpenKey, Vn, nil, @DataType, @Temp, @DataSize) = ERROR_SUCCESS then
+ SetString(Result, Temp, DataSize div SizeOf(Char) - 1);
+ RegCloseKey(OpenKey);
+ end;
+end ;
+{$ENDIF}
+
+function GetDNS: string;
+{$IFDEF LINUX}
+var
+ l: TStringList;
+ n: integer;
+begin
+ Result := '';
+ l := TStringList.Create;
+ try
+ l.LoadFromFile('/etc/resolv.conf');
+ for n := 0 to l.Count - 1 do
+ if Pos('NAMESERVER', uppercase(l[n])) = 1 then
+ begin
+ if Result <> '' then
+ Result := Result + ',';
+ Result := Result + SeparateRight(l[n], ' ');
+ end;
+ finally
+ l.Free;
+ end;
+end;
+{$ELSE}
+const
+ NTdyn = 'System\CurrentControlSet\Services\Tcpip\Parameters\Temporary';
+ NTfix = 'System\CurrentControlSet\Services\Tcpip\Parameters';
+ W9xfix = 'System\CurrentControlSet\Services\MSTCP';
+begin
+ Result := GetDNSbyIpHlp;
+ if Result = '...' then
+ begin
+ if Win32Platform = VER_PLATFORM_WIN32_NT then
+ begin
+ Result := ReadReg(NTdyn, 'NameServer');
+ if result = '' then
+ Result := ReadReg(NTfix, 'NameServer');
+ if result = '' then
+ Result := ReadReg(NTfix, 'DhcpNameServer');
+ end
+ else
+ Result := ReadReg(W9xfix, 'NameServer');
+ Result := ReplaceString(trim(Result), ' ', ',');
+ end;
+end;
+{$ENDIF}
+
+{==============================================================================}
+
+function GetIEProxy(protocol: string): TProxySetting;
+{$IFDEF LINUX}
+begin
+ Result.Host := '';
+ Result.Port := '';
+ Result.Bypass := '';
+end;
+{$ELSE}
+type
+ PInternetProxyInfo = ^TInternetProxyInfo;
+ TInternetProxyInfo = packed record
+ dwAccessType: DWORD;
+ lpszProxy: LPCSTR;
+ lpszProxyBypass: LPCSTR;
+ end;
+const
+ INTERNET_OPTION_PROXY = 38;
+ INTERNET_OPEN_TYPE_PROXY = 3;
+ WininetDLL = 'WININET.DLL';
+var
+ WininetModule: THandle;
+ ProxyInfo: PInternetProxyInfo;
+ Err: Boolean;
+ Len: DWORD;
+ Proxy: string;
+ DefProxy: string;
+ ProxyList: TStringList;
+ n: integer;
+ InternetQueryOption: function (hInet: Pointer; dwOption: DWORD;
+ lpBuffer: Pointer; var lpdwBufferLength: DWORD): BOOL; stdcall;
+begin
+ Result.Host := '';
+ Result.Port := '';
+ Result.Bypass := '';
+ WininetModule := LoadLibrary(WininetDLL);
+ if WininetModule = 0 then
+ exit;
+ try
+ InternetQueryOption := GetProcAddress(WininetModule,PAnsiChar(AnsiString('InternetQueryOptionA')));
+ if @InternetQueryOption = nil then
+ Exit;
+
+ if protocol = '' then
+ protocol := 'http';
+ Len := 4096;
+ GetMem(ProxyInfo, Len);
+ ProxyList := TStringList.Create;
+ try
+ Err := InternetQueryOption(nil, INTERNET_OPTION_PROXY, ProxyInfo, Len);
+ if Err then
+ if ProxyInfo^.dwAccessType = INTERNET_OPEN_TYPE_PROXY then
+ begin
+ ProxyList.CommaText := ReplaceString(ProxyInfo^.lpszProxy, ' ', ',');
+ Proxy := '';
+ DefProxy := '';
+ for n := 0 to ProxyList.Count -1 do
+ begin
+ if Pos(lowercase(protocol) + '=', lowercase(ProxyList[n])) = 1 then
+ begin
+ Proxy := SeparateRight(ProxyList[n], '=');
+ break;
+ end;
+ if Pos('=', ProxyList[n]) < 1 then
+ DefProxy := ProxyList[n];
+ end;
+ if Proxy = '' then
+ Proxy := DefProxy;
+ if Proxy <> '' then
+ begin
+ Result.Host := Trim(SeparateLeft(Proxy, ':'));
+ Result.Port := Trim(SeparateRight(Proxy, ':'));
+ end;
+ Result.Bypass := ReplaceString(ProxyInfo^.lpszProxyBypass, ' ', ',');
+ end;
+ finally
+ ProxyList.Free;
+ FreeMem(ProxyInfo);
+ end;
+ finally
+ FreeLibrary(WininetModule);
+ end;
+end;
+{$ENDIF}
+
+{==============================================================================}
+
+function GetLocalIPs: string;
+var
+ TcpSock: TTCPBlockSocket;
+ ipList: TStringList;
+begin
+ Result := '';
+ ipList := TStringList.Create;
+ try
+ TcpSock := TTCPBlockSocket.create;
+ try
+ TcpSock.ResolveNameToIP(TcpSock.LocalName, ipList);
+ Result := ipList.CommaText;
+ finally
+ TcpSock.Free;
+ end;
+ finally
+ ipList.Free;
+ end;
+end;
+
+{==============================================================================}
+
+end.
diff --git a/branches/script-component/Units/Synapse/synaser.pas b/branches/script-component/Units/Synapse/synaser.pas
new file mode 100644
index 0000000..a9eec96
--- /dev/null
+++ b/branches/script-component/Units/Synapse/synaser.pas
@@ -0,0 +1,2298 @@
+{==============================================================================|
+| Project : Ararat Synapse | 007.003.000 |
+|==============================================================================|
+| Content: Serial port support |
+|==============================================================================|
+| Copyright (c)2001-2008, Lukas Gebauer |
+| All rights reserved. |
+| |
+| Redistribution and use in source and binary forms, with or without |
+| modification, are permitted provided that the following conditions are met: |
+| |
+| Redistributions of source code must retain the above copyright notice, this |
+| list of conditions and the following disclaimer. |
+| |
+| Redistributions in binary form must reproduce the above copyright notice, |
+| this list of conditions and the following disclaimer in the documentation |
+| and/or other materials provided with the distribution. |
+| |
+| Neither the name of Lukas Gebauer nor the names of its contributors may |
+| be used to endorse or promote products derived from this software without |
+| specific prior written permission. |
+| |
+| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
+| AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
+| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
+| ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR |
+| ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
+| DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
+| SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
+| CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
+| LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
+| OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
+| DAMAGE. |
+|==============================================================================|
+| The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).|
+| Portions created by Lukas Gebauer are Copyright (c)2001-2008. |
+| All Rights Reserved. |
+|==============================================================================|
+| Contributor(s): |
+| (c)2002, Hans-Georg Joepgen (cpom Comport Ownership Manager and bugfixes) |
+|==============================================================================|
+| History: see HISTORY.HTM from distribution package |
+| (Found at URL: http://www.ararat.cz/synapse/) |
+|==============================================================================}
+
+{: @abstract(Serial port communication library)
+This unit contains a class that implements serial port communication for Windows
+ or Linux. This class provides numerous methods with same name and functionality
+ as methods of the Ararat Synapse TCP/IP library.
+
+The following is a small example how establish a connection by modem (in this
+case with my USB modem):
+@longcode(#
+ ser:=TBlockSerial.Create;
+ try
+ ser.Connect('COM3');
+ ser.config(460800,8,'N',0,false,true);
+ ser.ATCommand('AT');
+ if (ser.LastError <> 0) or (not ser.ATResult) then
+ Exit;
+ ser.ATConnect('ATDT+420971200111');
+ if (ser.LastError <> 0) or (not ser.ATResult) then
+ Exit;
+ // you are now connected to a modem at +420971200111
+ // you can transmit or receive data now
+ finally
+ ser.free;
+ end;
+#)
+}
+
+{$IFDEF FPC}
+ {$MODE DELPHI}
+ {$IFDEF WIN32}
+ {$ASMMODE intel}
+ {$ENDIF}
+ {define working mode w/o LIBC for fpc}
+ {$DEFINE NO_LIBC}
+{$ENDIF}
+{$Q-}
+{$H+}
+{$M+}
+
+unit synaser;
+
+interface
+
+uses
+{$IFNDEF WIN32}
+ {$IFNDEF NO_LIBC}
+ Libc,
+ KernelIoctl,
+ {$ELSE}
+ termio, baseunix, unix,
+ {$ENDIF}
+ {$IFNDEF FPC}
+ Types,
+ {$ENDIF}
+{$ELSE}
+ Windows, registry,
+ {$IFDEF FPC}
+ winver,
+ {$ENDIF}
+{$ENDIF}
+ synafpc,
+ Classes, SysUtils, synautil;
+
+const
+ CR = #$0d;
+ LF = #$0a;
+ CRLF = CR + LF;
+ cSerialChunk = 8192;
+
+ LockfileDirectory = '/var/lock'; {HGJ}
+ PortIsClosed = -1; {HGJ}
+ ErrAlreadyOwned = 9991; {HGJ}
+ ErrAlreadyInUse = 9992; {HGJ}
+ ErrWrongParameter = 9993; {HGJ}
+ ErrPortNotOpen = 9994; {HGJ}
+ ErrNoDeviceAnswer = 9995; {HGJ}
+ ErrMaxBuffer = 9996;
+ ErrTimeout = 9997;
+ ErrNotRead = 9998;
+ ErrFrame = 9999;
+ ErrOverrun = 10000;
+ ErrRxOver = 10001;
+ ErrRxParity = 10002;
+ ErrTxFull = 10003;
+
+ dcb_Binary = $00000001;
+ dcb_ParityCheck = $00000002;
+ dcb_OutxCtsFlow = $00000004;
+ dcb_OutxDsrFlow = $00000008;
+ dcb_DtrControlMask = $00000030;
+ dcb_DtrControlDisable = $00000000;
+ dcb_DtrControlEnable = $00000010;
+ dcb_DtrControlHandshake = $00000020;
+ dcb_DsrSensivity = $00000040;
+ dcb_TXContinueOnXoff = $00000080;
+ dcb_OutX = $00000100;
+ dcb_InX = $00000200;
+ dcb_ErrorChar = $00000400;
+ dcb_NullStrip = $00000800;
+ dcb_RtsControlMask = $00003000;
+ dcb_RtsControlDisable = $00000000;
+ dcb_RtsControlEnable = $00001000;
+ dcb_RtsControlHandshake = $00002000;
+ dcb_RtsControlToggle = $00003000;
+ dcb_AbortOnError = $00004000;
+ dcb_Reserveds = $FFFF8000;
+
+ {:stopbit value for 1 stopbit}
+ SB1 = 0;
+ {:stopbit value for 1.5 stopbit}
+ SB1andHalf = 1;
+ {:stopbit value for 2 stopbits}
+ SB2 = 2;
+
+{$IFNDEF WIN32}
+const
+ INVALID_HANDLE_VALUE = THandle(-1);
+ CS7fix = $0000020;
+
+type
+ TDCB = packed record
+ DCBlength: DWORD;
+ BaudRate: DWORD;
+ Flags: Longint;
+ wReserved: Word;
+ XonLim: Word;
+ XoffLim: Word;
+ ByteSize: Byte;
+ Parity: Byte;
+ StopBits: Byte;
+ XonChar: CHAR;
+ XoffChar: CHAR;
+ ErrorChar: CHAR;
+ EofChar: CHAR;
+ EvtChar: CHAR;
+ wReserved1: Word;
+ end;
+ PDCB = ^TDCB;
+
+const
+// MaxRates = 30;
+ MaxRates = 19; //FPC on some platforms not know high speeds?
+ Rates: array[0..MaxRates, 0..1] of cardinal =
+ (
+ (0, B0),
+ (50, B50),
+ (75, B75),
+ (110, B110),
+ (134, B134),
+ (150, B150),
+ (200, B200),
+ (300, B300),
+ (600, B600),
+ (1200, B1200),
+ (1800, B1800),
+ (2400, B2400),
+ (4800, B4800),
+ (9600, B9600),
+ (19200, B19200),
+ (38400, B38400),
+ (57600, B57600),
+ (115200, B115200),
+ (230400, B230400),
+ (460800, B460800){,
+ (500000, B500000),
+ (576000, B576000),
+ (921600, B921600),
+ (1000000, B1000000),
+ (1152000, B1152000),
+ (1500000, B1500000),
+ (2000000, B2000000),
+ (2500000, B2500000),
+ (3000000, B3000000),
+ (3500000, B3500000),
+ (4000000, B4000000)}
+ );
+{$ENDIF}
+
+const
+ sOK = 0;
+ sErr = integer(-1);
+
+type
+
+ {:Possible status event types for @link(THookSerialStatus)}
+ THookSerialReason = (
+ HR_SerialClose,
+ HR_Connect,
+ HR_CanRead,
+ HR_CanWrite,
+ HR_ReadCount,
+ HR_WriteCount,
+ HR_Wait
+ );
+
+ {:procedural prototype for status event hooking}
+ THookSerialStatus = procedure(Sender: TObject; Reason: THookSerialReason;
+ const Value: string) of object;
+
+ {:@abstract(Exception type for SynaSer errors)}
+ ESynaSerError = class(Exception)
+ public
+ ErrorCode: integer;
+ ErrorMessage: string;
+ end;
+
+ {:@abstract(Main class implementing all communication routines)}
+ TBlockSerial = class(TObject)
+ protected
+ FOnStatus: THookSerialStatus;
+ Fhandle: THandle;
+ FTag: integer;
+ FDevice: string;
+ FLastError: integer;
+ FLastErrorDesc: string;
+ FBuffer: string;
+ FRaiseExcept: boolean;
+ FRecvBuffer: integer;
+ FSendBuffer: integer;
+ FModemWord: integer;
+ FRTSToggle: Boolean;
+ FDeadlockTimeout: integer;
+ FInstanceActive: boolean; {HGJ}
+ FTestDSR: Boolean;
+ FTestCTS: Boolean;
+ FLastCR: Boolean;
+ FLastLF: Boolean;
+ FMaxLineLength: Integer;
+ FLinuxLock: Boolean;
+ FMaxSendBandwidth: Integer;
+ FNextSend: LongWord;
+ FMaxRecvBandwidth: Integer;
+ FNextRecv: LongWord;
+ FConvertLineEnd: Boolean;
+ FATResult: Boolean;
+ FAtTimeout: integer;
+ FInterPacketTimeout: Boolean;
+ FComNr: integer;
+{$IFDEF WIN32}
+ FPortAddr: Word;
+ function CanEvent(Event: dword; Timeout: integer): boolean;
+ procedure DecodeCommError(Error: DWord); virtual;
+ function GetPortAddr: Word; virtual;
+ function ReadTxEmpty(PortAddr: Word): Boolean; virtual;
+{$ENDIF}
+ procedure SetSizeRecvBuffer(size: integer); virtual;
+ function GetDSR: Boolean; virtual;
+ procedure SetDTRF(Value: Boolean); virtual;
+ function GetCTS: Boolean; virtual;
+ procedure SetRTSF(Value: Boolean); virtual;
+ function GetCarrier: Boolean; virtual;
+ function GetRing: Boolean; virtual;
+ procedure DoStatus(Reason: THookSerialReason; const Value: string); virtual;
+ procedure GetComNr(Value: string); virtual;
+ function PreTestFailing: boolean; virtual;{HGJ}
+ function TestCtrlLine: Boolean; virtual;
+{$IFNDEF WIN32}
+ procedure DcbToTermios(const dcb: TDCB; var term: termios); virtual;
+ procedure TermiosToDcb(const term: termios; var dcb: TDCB); virtual;
+{$ENDIF}
+{$IFDEF LINUX}
+ function ReadLockfile: integer; virtual;
+ function LockfileName: String; virtual;
+ procedure CreateLockfile(PidNr: integer); virtual;
+{$ENDIF}
+ procedure LimitBandwidth(Length: Integer; MaxB: integer; var Next: LongWord); virtual;
+ procedure SetBandwidth(Value: Integer); virtual;
+ public
+ {: data Control Block with communication parameters. Usable only when you
+ need to call API directly.}
+ DCB: Tdcb;
+{$IFNDEF WIN32}
+ TermiosStruc: termios;
+{$ENDIF}
+ {:Object constructor.}
+ constructor Create;
+ {:Object destructor.}
+ destructor Destroy; override;
+
+ {:Returns a string containing the version number of the library.}
+ class function GetVersion: string; virtual;
+
+ {:Destroy handle in use. It close connection to serial port.}
+ procedure CloseSocket; virtual;
+
+ {:Reconfigure communication parameters on the fly. You must be connected to
+ port before!
+ @param(baud Define connection speed. Baud rate can be from 50 to 4000000
+ bits per second. (it depends on your hardware!))
+ @param(bits Number of bits in communication.)
+ @param(parity Define communication parity (N - None, O - Odd, E - Even, M - Mark or S - Space).)
+ @param(stop Define number of stopbits. Use constants @link(SB1),
+ @link(SB1andHalf) and @link(SB2).)
+ @param(softflow Enable XON/XOFF handshake.)
+ @param(hardflow Enable CTS/RTS handshake.)}
+ procedure Config(baud, bits: integer; parity: char; stop: integer;
+ softflow, hardflow: boolean); virtual;
+
+ {:Connects to the port indicated by comport. Comport can be used in Windows
+ style (COM2), or in Linux style (/dev/ttyS1). When you use windows style
+ in Linux, then it will be converted to Linux name. And vice versa! However
+ you can specify any device name! (other device names then standart is not
+ converted!)
+
+ After successfull connection the DTR signal is set (if you not set hardware
+ handshake, then the RTS signal is set, too!)
+
+ Connection parameters is predefined by your system configuration. If you
+ need use another parameters, then you can use Config method after.
+ Notes:
+
+ - Remember, the commonly used serial Laplink cable does not support
+ hardware handshake.
+
+ - Before setting any handshake you must be sure that it is supported by
+ your hardware.
+
+ - Some serial devices are slow. In some cases you must wait up to a few
+ seconds after connection for the device to respond.
+
+ - when you connect to a modem device, then is best to test it by an empty
+ AT command. (call ATCommand('AT'))}
+ procedure Connect(comport: string); virtual;
+
+ {:Set communication parameters from the DCB structure (the DCB structure is
+ simulated under Linux).}
+ procedure SetCommState; virtual;
+
+ {:Read communication parameters into the DCB structure (DCB structure is
+ simulated under Linux).}
+ procedure GetCommState; virtual;
+
+ {:Sends Length bytes of data from Buffer through the connected port.}
+ function SendBuffer(buffer: pointer; length: integer): integer; virtual;
+
+ {:One data BYTE is sent.}
+ procedure SendByte(data: byte); virtual;
+
+ {:Send the string in the data parameter. No terminator is appended by this
+ method. If you need to send a string with CR/LF terminator, you must append
+ the CR/LF characters to the data string!
+
+ Since no terminator is appended, you can use this function for sending
+ binary data too.}
+ procedure SendString(data: string); virtual;
+
+ {:send four bytes as integer.}
+ procedure SendInteger(Data: integer); virtual;
+
+ {:send data as one block. Each block begins with integer value with Length
+ of block.}
+ procedure SendBlock(const Data: string); virtual;
+
+ {:send content of stream from current position}
+ procedure SendStreamRaw(const Stream: TStream); virtual;
+
+ {:send content of stream as block. see @link(SendBlock)}
+ procedure SendStream(const Stream: TStream); virtual;
+
+ {:send content of stream as block, but this is compatioble with Indy library.
+ (it have swapped lenght of block). See @link(SendStream)}
+ procedure SendStreamIndy(const Stream: TStream); virtual;
+
+ {:Waits until the allocated buffer is filled by received data. Returns number
+ of data bytes received, which equals to the Length value under normal
+ operation. If it is not equal, the communication channel is possibly broken.
+
+ This method not using any internal buffering, like all others receiving
+ methods. You cannot freely combine this method with all others receiving
+ methods!}
+ function RecvBuffer(buffer: pointer; length: integer): integer; virtual;
+
+ {:Method waits until data is received. If no data is received within
+ the Timeout (in milliseconds) period, @link(LastError) is set to
+ @link(ErrTimeout). This method is used to read any amount of data
+ (e. g. 1MB), and may be freely combined with all receviving methods what
+ have Timeout parameter, like the @link(RecvString), @link(RecvByte) or
+ @link(RecvTerminated) methods.}
+ function RecvBufferEx(buffer: pointer; length: integer; timeout: integer): integer; virtual;
+
+ {:It is like recvBufferEx, but data is readed to dynamicly allocated binary
+ string.}
+ function RecvBufferStr(Length: Integer; Timeout: Integer): string; virtual;
+
+ {:Read all available data and return it in the function result string. This
+ function may be combined with @link(RecvString), @link(RecvByte) or related
+ methods.}
+ function RecvPacket(Timeout: Integer): string; virtual;
+
+ {:Waits until one data byte is received which is returned as the function
+ result. If no data is received within the Timeout (in milliseconds) period,
+ @link(LastError) is set to @link(ErrTimeout).}
+ function RecvByte(timeout: integer): byte; virtual;
+
+ {:This method waits until a terminated data string is received. This string
+ is terminated by the Terminator string. The resulting string is returned
+ without this termination string! If no data is received within the Timeout
+ (in milliseconds) period, @link(LastError) is set to @link(ErrTimeout).}
+ function RecvTerminated(Timeout: Integer; const Terminator: string): string; virtual;
+
+ {:This method waits until a terminated data string is received. The string
+ is terminated by a CR/LF sequence. The resulting string is returned without
+ the terminator (CR/LF)! If no data is received within the Timeout (in
+ milliseconds) period, @link(LastError) is set to @link(ErrTimeout).
+
+ If @link(ConvertLineEnd) is used, then the CR/LF sequence may not be exactly
+ CR/LF. See the description of @link(ConvertLineEnd).
+
+ This method serves for line protocol implementation and uses its own
+ buffers to maximize performance. Therefore do NOT use this method with the
+ @link(RecvBuffer) method to receive data as it may cause data loss.}
+ function Recvstring(timeout: integer): string; virtual;
+
+ {:Waits until four data bytes are received which is returned as the function
+ integer result. If no data is received within the Timeout (in milliseconds) period,
+ @link(LastError) is set to @link(ErrTimeout).}
+ function RecvInteger(Timeout: Integer): Integer; virtual;
+
+ {:Waits until one data block is received. See @link(sendblock). If no data
+ is received within the Timeout (in milliseconds) period, @link(LastError)
+ is set to @link(ErrTimeout).}
+ function RecvBlock(Timeout: Integer): string; virtual;
+
+ {:Receive all data to stream, until some error occured. (for example timeout)}
+ procedure RecvStreamRaw(const Stream: TStream; Timeout: Integer); virtual;
+
+ {:receive requested count of bytes to stream}
+ procedure RecvStreamSize(const Stream: TStream; Timeout: Integer; Size: Integer); virtual;
+
+ {:receive block of data to stream. (Data can be sended by @link(sendstream)}
+ procedure RecvStream(const Stream: TStream; Timeout: Integer); virtual;
+
+ {:receive block of data to stream. (Data can be sended by @link(sendstreamIndy)}
+ procedure RecvStreamIndy(const Stream: TStream; Timeout: Integer); virtual;
+
+ {:Returns the number of received bytes waiting for reading. 0 is returned
+ when there is no data waiting.}
+ function WaitingData: integer; virtual;
+
+ {:Same as @link(WaitingData), but in respect to data in the internal
+ @link(LineBuffer).}
+ function WaitingDataEx: integer; virtual;
+
+ {:Returns the number of bytes waiting to be sent in the output buffer.
+ 0 is returned when the output buffer is empty.}
+ function SendingData: integer; virtual;
+
+ {:Enable or disable RTS driven communication (half-duplex). It can be used
+ to communicate with RS485 converters, or other special equipment. If you
+ enable this feature, the system automatically controls the RTS signal.
+
+ Notes:
+
+ - On Windows NT (or higher) ir RTS signal driven by system driver.
+
+ - On Win9x family is used special code for waiting until last byte is
+ sended from your UART.
+
+ - On Linux you must have kernel 2.1 or higher!}
+ procedure EnableRTSToggle(value: boolean); virtual;
+
+ {:Waits until all data to is sent and buffers are emptied.
+ Warning: On Windows systems is this method returns when all buffers are
+ flushed to the serial port controller, before the last byte is sent!}
+ procedure Flush; virtual;
+
+ {:Unconditionally empty all buffers. It is good when you need to interrupt
+ communication and for cleanups.}
+ procedure Purge; virtual;
+
+ {:Returns @True, if you can from read any data from the port. Status is
+ tested for a period of time given by the Timeout parameter (in milliseconds).
+ If the value of the Timeout parameter is 0, the status is tested only once
+ and the function returns immediately. If the value of the Timeout parameter
+ is set to -1, the function returns only after it detects data on the port
+ (this may cause the process to hang).}
+ function CanRead(Timeout: integer): boolean; virtual;
+
+ {:Returns @True, if you can write any data to the port (this function is not
+ sending the contents of the buffer). Status is tested for a period of time
+ given by the Timeout parameter (in milliseconds). If the value of
+ the Timeout parameter is 0, the status is tested only once and the function
+ returns immediately. If the value of the Timeout parameter is set to -1,
+ the function returns only after it detects that it can write data to
+ the port (this may cause the process to hang).}
+ function CanWrite(Timeout: integer): boolean; virtual;
+
+ {:Same as @link(CanRead), but the test is against data in the internal
+ @link(LineBuffer) too.}
+ function CanReadEx(Timeout: integer): boolean; virtual;
+
+ {:Returns the status word of the modem. Decoding the status word could yield
+ the status of carrier detect signaland other signals. This method is used
+ internally by the modem status reading properties. You usually do not need
+ to call this method directly.}
+ function ModemStatus: integer; virtual;
+
+ {:Send a break signal to the communication device for Duration milliseconds.}
+ procedure SetBreak(Duration: integer); virtual;
+
+ {:This function is designed to send AT commands to the modem. The AT command
+ is sent in the Value parameter and the response is returned in the function
+ return value (may contain multiple lines!).
+ If the AT command is processed successfully (modem returns OK), then the
+ @link(ATResult) property is set to True.
+
+ This function is designed only for AT commands that return OK or ERROR
+ response! To call connection commands the @link(ATConnect) method.
+ Remember, when you connect to a modem device, it is in AT command mode.
+ Now you can send AT commands to the modem. If you need to transfer data to
+ the modem on the other side of the line, you must first switch to data mode
+ using the @link(ATConnect) method.}
+ function ATCommand(value: string): string; virtual;
+
+ {:This function is used to send connect type AT commands to the modem. It is
+ for commands to switch to connected state. (ATD, ATA, ATO,...)
+ It sends the AT command in the Value parameter and returns the modem's
+ response (may be multiple lines - usually with connection parameters info).
+ If the AT command is processed successfully (the modem returns CONNECT),
+ then the ATResult property is set to @True.
+
+ This function is designed only for AT commands which respond by CONNECT,
+ BUSY, NO DIALTONE NO CARRIER or ERROR. For other AT commands use the
+ @link(ATCommand) method.
+
+ The connect timeout is 90*@link(ATTimeout). If this command is successful
+ (@link(ATresult) is @true), then the modem is in data state. When you now
+ send or receive some data, it is not to or from your modem, but from the
+ modem on other side of the line. Now you can transfer your data.
+ If the connection attempt failed (@link(ATResult) is @False), then the
+ modem is still in AT command mode.}
+ function ATConnect(value: string): string; virtual;
+
+ {:If you "manually" call API functions, forward their return code in
+ the SerialResult parameter to this function, which evaluates it and sets
+ @link(LastError) and @link(LastErrorDesc).}
+ function SerialCheck(SerialResult: integer): integer; virtual;
+
+ {:If @link(Lasterror) is not 0 and exceptions are enabled, then this procedure
+ raises an exception. This method is used internally. You may need it only
+ in special cases.}
+ procedure ExceptCheck; virtual;
+
+ {:Set Synaser to error state with ErrNumber code. Usually used by internal
+ routines.}
+ procedure SetSynaError(ErrNumber: integer); virtual;
+
+ {:Raise Synaser error with ErrNumber code. Usually used by internal routines.}
+ procedure RaiseSynaError(ErrNumber: integer); virtual;
+{$IFDEF LINUX}
+ function cpomComportAccessible: boolean; virtual;{HGJ}
+ procedure cpomReleaseComport; virtual; {HGJ}
+{$ENDIF}
+ {:True device name of currently used port}
+ property Device: string read FDevice;
+
+ {:Error code of last operation. Value is defined by the host operating
+ system, but value 0 is always OK.}
+ property LastError: integer read FLastError;
+
+ {:Human readable description of LastError code.}
+ property LastErrorDesc: string read FLastErrorDesc;
+
+ {:Indicates if the last @link(ATCommand) or @link(ATConnect) method was successful}
+ property ATResult: Boolean read FATResult;
+
+ {:Read the value of the RTS signal.}
+ property RTS: Boolean write SetRTSF;
+
+ {:Indicates the presence of the CTS signal}
+ property CTS: boolean read GetCTS;
+
+ {:Use this property to set the value of the DTR signal.}
+ property DTR: Boolean write SetDTRF;
+
+ {:Exposes the status of the DSR signal.}
+ property DSR: boolean read GetDSR;
+
+ {:Indicates the presence of the Carrier signal}
+ property Carrier: boolean read GetCarrier;
+
+ {:Reflects the status of the Ring signal.}
+ property Ring: boolean read GetRing;
+
+ {:indicates if this instance of SynaSer is active. (Connected to some port)}
+ property InstanceActive: boolean read FInstanceActive; {HGJ}
+
+ {:Defines maximum bandwidth for all sending operations in bytes per second.
+ If this value is set to 0 (default), bandwidth limitation is not used.}
+ property MaxSendBandwidth: Integer read FMaxSendBandwidth Write FMaxSendBandwidth;
+
+ {:Defines maximum bandwidth for all receiving operations in bytes per second.
+ If this value is set to 0 (default), bandwidth limitation is not used.}
+ property MaxRecvBandwidth: Integer read FMaxRecvBandwidth Write FMaxRecvBandwidth;
+
+ {:Defines maximum bandwidth for all sending and receiving operations
+ in bytes per second. If this value is set to 0 (default), bandwidth
+ limitation is not used.}
+ property MaxBandwidth: Integer Write SetBandwidth;
+
+ {:Size of the Windows internal receive buffer. Default value is usually
+ 4096 bytes. Note: Valid only in Windows versions!}
+ property SizeRecvBuffer: integer read FRecvBuffer write SetSizeRecvBuffer;
+ published
+ {:Returns the descriptive text associated with ErrorCode. You need this
+ method only in special cases. Description of LastError is now accessible
+ through the LastErrorDesc property.}
+ class function GetErrorDesc(ErrorCode: integer): string;
+
+ {:Freely usable property}
+ property Tag: integer read FTag write FTag;
+
+ {:Contains the handle of the open communication port.
+ You may need this value to directly call communication functions outside
+ SynaSer.}
+ property Handle: THandle read Fhandle write FHandle;
+
+ {:Internally used read buffer.}
+ property LineBuffer: string read FBuffer write FBuffer;
+
+ {:If @true, communication errors raise exceptions. If @false (default), only
+ the @link(LastError) value is set.}
+ property RaiseExcept: boolean read FRaiseExcept write FRaiseExcept;
+
+ {:This event is triggered when the communication status changes. It can be
+ used to monitor communication status.}
+ property OnStatus: THookSerialStatus read FOnStatus write FOnStatus;
+
+ {:If you set this property to @true, then the value of the DSR signal
+ is tested before every data transfer. It can be used to detect the presence
+ of a communications device.}
+ property TestDSR: boolean read FTestDSR write FTestDSR;
+
+ {:If you set this property to @true, then the value of the CTS signal
+ is tested before every data transfer. It can be used to detect the presence
+ of a communications device. Warning: This property cannot be used if you
+ need hardware handshake!}
+ property TestCTS: boolean read FTestCTS write FTestCTS;
+
+ {:Use this property you to limit the maximum size of LineBuffer
+ (as a protection against unlimited memory allocation for LineBuffer).
+ Default value is 0 - no limit.}
+ property MaxLineLength: Integer read FMaxLineLength Write FMaxLineLength;
+
+ {:This timeout value is used as deadlock protection when trying to send data
+ to (or receive data from) a device that stopped communicating during data
+ transmission (e.g. by physically disconnecting the device).
+ The timeout value is in milliseconds. The default value is 30,000 (30 seconds).}
+ property DeadlockTimeout: Integer read FDeadlockTimeout Write FDeadlockTimeout;
+
+ {:If set to @true (default value), port locking is enabled (under Linux only).
+ WARNING: To use this feature, the application must run by a user with full
+ permission to the /var/lock directory!}
+ property LinuxLock: Boolean read FLinuxLock write FLinuxLock;
+
+ {:Indicates if non-standard line terminators should be converted to a CR/LF pair
+ (standard DOS line terminator). If @TRUE, line terminators CR, single LF
+ or LF/CR are converted to CR/LF. Defaults to @FALSE.
+ This property has effect only on the behavior of the RecvString method.}
+ property ConvertLineEnd: Boolean read FConvertLineEnd Write FConvertLineEnd;
+
+ {:Timeout for AT modem based operations}
+ property AtTimeout: integer read FAtTimeout Write FAtTimeout;
+
+ {:If @true (default), then all timeouts is timeout between two characters.
+ If @False, then timeout is overall for whoole reading operation.}
+ property InterPacketTimeout: Boolean read FInterPacketTimeout Write FInterPacketTimeout;
+ end;
+
+{:Returns list of existing computer serial ports. Working properly only in Windows!}
+function GetSerialPortNames: string;
+
+implementation
+
+constructor TBlockSerial.Create;
+begin
+ inherited create;
+ FRaiseExcept := false;
+ FHandle := INVALID_HANDLE_VALUE;
+ FDevice := '';
+ FComNr:= PortIsClosed; {HGJ}
+ FInstanceActive:= false; {HGJ}
+ Fbuffer := '';
+ FRTSToggle := False;
+ FMaxLineLength := 0;
+ FTestDSR := False;
+ FTestCTS := False;
+ FDeadlockTimeout := 30000;
+ FLinuxLock := True;
+ FMaxSendBandwidth := 0;
+ FNextSend := 0;
+ FMaxRecvBandwidth := 0;
+ FNextRecv := 0;
+ FConvertLineEnd := False;
+ SetSynaError(sOK);
+ FRecvBuffer := 4096;
+ FLastCR := False;
+ FLastLF := False;
+ FAtTimeout := 1000;
+ FInterPacketTimeout := True;
+end;
+
+destructor TBlockSerial.Destroy;
+begin
+ CloseSocket;
+ inherited destroy;
+end;
+
+class function TBlockSerial.GetVersion: string;
+begin
+ Result := 'SynaSer 6.3.5';
+end;
+
+procedure TBlockSerial.CloseSocket;
+begin
+ if Fhandle <> INVALID_HANDLE_VALUE then
+ begin
+ Purge;
+ RTS := False;
+ DTR := False;
+ FileClose(integer(FHandle));
+ end;
+ if InstanceActive then
+ begin
+ {$IFDEF LINUX}
+ if FLinuxLock then
+ cpomReleaseComport;
+ {$ENDIF}
+ FInstanceActive:= false
+ end;
+ Fhandle := INVALID_HANDLE_VALUE;
+ FComNr:= PortIsClosed;
+ SetSynaError(sOK);
+ DoStatus(HR_SerialClose, FDevice);
+end;
+
+{$IFDEF WIN32}
+function TBlockSerial.GetPortAddr: Word;
+begin
+ Result := 0;
+ if Win32Platform <> VER_PLATFORM_WIN32_NT then
+ begin
+ EscapeCommFunction(FHandle, 10);
+ asm
+ MOV @Result, DX;
+ end;
+ end;
+end;
+
+function TBlockSerial.ReadTxEmpty(PortAddr: Word): Boolean;
+begin
+ Result := True;
+ if Win32Platform <> VER_PLATFORM_WIN32_NT then
+ begin
+ asm
+ MOV DX, PortAddr;
+ ADD DX, 5;
+ IN AL, DX;
+ AND AL, $40;
+ JZ @K;
+ MOV AL,1;
+ @K: MOV @Result, AL;
+ end;
+ end;
+end;
+{$ENDIF}
+
+procedure TBlockSerial.GetComNr(Value: string);
+begin
+ FComNr := PortIsClosed;
+ if pos('COM', uppercase(Value)) = 1 then
+ FComNr := StrToIntdef(copy(Value, 4, Length(Value) - 3), PortIsClosed + 1) - 1;
+ if pos('/DEV/TTYS', uppercase(Value)) = 1 then
+ FComNr := StrToIntdef(copy(Value, 10, Length(Value) - 9), PortIsClosed - 1);
+end;
+
+procedure TBlockSerial.SetBandwidth(Value: Integer);
+begin
+ MaxSendBandwidth := Value;
+ MaxRecvBandwidth := Value;
+end;
+
+procedure TBlockSerial.LimitBandwidth(Length: Integer; MaxB: integer; var Next: LongWord);
+var
+ x: LongWord;
+ y: LongWord;
+begin
+ if MaxB > 0 then
+ begin
+ y := GetTick;
+ if Next > y then
+ begin
+ x := Next - y;
+ if x > 0 then
+ begin
+ DoStatus(HR_Wait, IntToStr(x));
+ sleep(x);
+ end;
+ end;
+ Next := GetTick + Trunc((Length / MaxB) * 1000);
+ end;
+end;
+
+procedure TBlockSerial.Config(baud, bits: integer; parity: char; stop: integer;
+ softflow, hardflow: boolean);
+begin
+ FillChar(dcb, SizeOf(dcb), 0);
+ dcb.DCBlength := SizeOf(dcb);
+ dcb.BaudRate := baud;
+ dcb.ByteSize := bits;
+ case parity of
+ 'N', 'n': dcb.parity := 0;
+ 'O', 'o': dcb.parity := 1;
+ 'E', 'e': dcb.parity := 2;
+ 'M', 'm': dcb.parity := 3;
+ 'S', 's': dcb.parity := 4;
+ end;
+ dcb.StopBits := stop;
+ dcb.XonChar := #17;
+ dcb.XoffChar := #19;
+ dcb.XonLim := FRecvBuffer div 4;
+ dcb.XoffLim := FRecvBuffer div 4;
+ dcb.Flags := dcb_Binary;
+ if softflow then
+ dcb.Flags := dcb.Flags or dcb_OutX or dcb_InX;
+ if hardflow then
+ dcb.Flags := dcb.Flags or dcb_OutxCtsFlow or dcb_RtsControlHandshake
+ else
+ dcb.Flags := dcb.Flags or dcb_RtsControlEnable;
+ dcb.Flags := dcb.Flags or dcb_DtrControlEnable;
+ if dcb.Parity > 0 then
+ dcb.Flags := dcb.Flags or dcb_ParityCheck;
+ SetCommState;
+end;
+
+procedure TBlockSerial.Connect(comport: string);
+{$IFDEF WIN32}
+var
+ CommTimeouts: TCommTimeouts;
+{$ENDIF}
+begin
+ // Is this TBlockSerial Instance already busy?
+ if InstanceActive then {HGJ}
+ begin {HGJ}
+ RaiseSynaError(ErrAlreadyInUse);
+ Exit; {HGJ}
+ end; {HGJ}
+ FBuffer := '';
+ FDevice := comport;
+ GetComNr(comport);
+{$IFDEF WIN32}
+ SetLastError (sOK);
+{$ELSE}
+ {$IFNDEF FPC}
+ SetLastError (sOK);
+ {$ELSE}
+ fpSetErrno(sOK);
+ {$ENDIF}
+{$ENDIF}
+{$IFNDEF WIN32}
+ if FComNr <> PortIsClosed then
+ FDevice := '/dev/ttyS' + IntToStr(FComNr);
+ // Comport already owned by another process? {HGJ}
+ if FLinuxLock then
+ if not cpomComportAccessible then
+ begin
+ RaiseSynaError(ErrAlreadyOwned);
+ Exit;
+ end;
+{$IFNDEF FPC}
+ FHandle := THandle(Libc.open(pchar(FDevice), O_RDWR or O_SYNC));
+{$ELSE}
+ FHandle := THandle(fpOpen(FDevice, O_RDWR or O_SYNC));
+{$ENDIF}
+ SerialCheck(integer(FHandle));
+ {$IFDEF LINUX}
+ if FLastError <> sOK then
+ if FLinuxLock then
+ cpomReleaseComport;
+ {$ENDIF}
+ ExceptCheck;
+ if FLastError <> sOK then
+ Exit;
+{$ELSE}
+ if FComNr <> PortIsClosed then
+ FDevice := '\\.\COM' + IntToStr(FComNr + 1);
+ FHandle := THandle(CreateFile(PChar(FDevice), GENERIC_READ or GENERIC_WRITE,
+ 0, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL or FILE_FLAG_OVERLAPPED, 0));
+ SerialCheck(integer(FHandle));
+ ExceptCheck;
+ if FLastError <> sOK then
+ Exit;
+ SetCommMask(FHandle, 0);
+ SetupComm(Fhandle, FRecvBuffer, 0);
+ CommTimeOuts.ReadIntervalTimeout := MAXWORD;
+ CommTimeOuts.ReadTotalTimeoutMultiplier := 0;
+ CommTimeOuts.ReadTotalTimeoutConstant := 0;
+ CommTimeOuts.WriteTotalTimeoutMultiplier := 0;
+ CommTimeOuts.WriteTotalTimeoutConstant := 0;
+ SetCommTimeOuts(FHandle, CommTimeOuts);
+ FPortAddr := GetPortAddr;
+{$ENDIF}
+ SetSynaError(sOK);
+ if not TestCtrlLine then {HGJ}
+ begin
+ SetSynaError(ErrNoDeviceAnswer);
+ FileClose(integer(FHandle)); {HGJ}
+ {$IFDEF LINUX}
+ if FLinuxLock then
+ cpomReleaseComport; {HGJ}
+ {$ENDIF} {HGJ}
+ Fhandle := INVALID_HANDLE_VALUE; {HGJ}
+ FComNr:= PortIsClosed; {HGJ}
+ end
+ else
+ begin
+ FInstanceActive:= True;
+ RTS := True;
+ DTR := True;
+ Purge;
+ end;
+ ExceptCheck;
+ DoStatus(HR_Connect, FDevice);
+end;
+
+function TBlockSerial.SendBuffer(buffer: pointer; length: integer): integer;
+{$IFDEF WIN32}
+var
+ Overlapped: TOverlapped;
+ x, y, Err: DWord;
+{$ENDIF}
+begin
+ Result := 0;
+ if PreTestFailing then {HGJ}
+ Exit; {HGJ}
+ LimitBandwidth(Length, FMaxSendBandwidth, FNextsend);
+ if FRTSToggle then
+ begin
+ Flush;
+ RTS := True;
+ end;
+{$IFNDEF WIN32}
+ result := FileWrite(integer(Fhandle), Buffer^, Length);
+ serialcheck(result);
+{$ELSE}
+ FillChar(Overlapped, Sizeof(Overlapped), 0);
+ SetSynaError(sOK);
+ y := 0;
+ if not WriteFile(FHandle, Buffer^, Length, DWord(Result), @Overlapped) then
+ y := GetLastError;
+ if y = ERROR_IO_PENDING then
+ begin
+ x := WaitForSingleObject(FHandle, FDeadlockTimeout);
+ if x = WAIT_TIMEOUT then
+ begin
+ PurgeComm(FHandle, PURGE_TXABORT);
+ SetSynaError(ErrTimeout);
+ end;
+ GetOverlappedResult(FHandle, Overlapped, Dword(Result), False);
+ end
+ else
+ SetSynaError(y);
+ ClearCommError(FHandle, err, nil);
+ if err <> 0 then
+ DecodeCommError(err);
+{$ENDIF}
+ if FRTSToggle then
+ begin
+ Flush;
+ CanWrite(255);
+ RTS := False;
+ end;
+ ExceptCheck;
+ DoStatus(HR_WriteCount, IntToStr(Result));
+end;
+
+procedure TBlockSerial.SendByte(data: byte);
+begin
+ SendBuffer(@Data, 1);
+end;
+
+procedure TBlockSerial.SendString(data: string);
+begin
+ SendBuffer(Pointer(Data), Length(Data));
+end;
+
+procedure TBlockSerial.SendInteger(Data: integer);
+begin
+ SendBuffer(@data, SizeOf(Data));
+end;
+
+procedure TBlockSerial.SendBlock(const Data: string);
+begin
+ SendInteger(Length(data));
+ SendString(Data);
+end;
+
+procedure TBlockSerial.SendStreamRaw(const Stream: TStream);
+var
+ si: integer;
+ x, y, yr: integer;
+ s: string;
+begin
+ si := Stream.Size - Stream.Position;
+ x := 0;
+ while x < si do
+ begin
+ y := si - x;
+ if y > cSerialChunk then
+ y := cSerialChunk;
+ Setlength(s, y);
+ yr := Stream.read(Pchar(s)^, y);
+ if yr > 0 then
+ begin
+ SetLength(s, yr);
+ SendString(s);
+ Inc(x, yr);
+ end
+ else
+ break;
+ end;
+end;
+
+procedure TBlockSerial.SendStreamIndy(const Stream: TStream);
+var
+ si: integer;
+begin
+ si := Stream.Size - Stream.Position;
+ si := Swapbytes(si);
+ SendInteger(si);
+ SendStreamRaw(Stream);
+end;
+
+procedure TBlockSerial.SendStream(const Stream: TStream);
+var
+ si: integer;
+begin
+ si := Stream.Size - Stream.Position;
+ SendInteger(si);
+ SendStreamRaw(Stream);
+end;
+
+function TBlockSerial.RecvBuffer(buffer: pointer; length: integer): integer;
+{$IFNDEF WIN32}
+begin
+ Result := 0;
+ if PreTestFailing then {HGJ}
+ Exit; {HGJ}
+ LimitBandwidth(Length, FMaxRecvBandwidth, FNextRecv);
+ result := FileRead(integer(FHandle), Buffer^, length);
+ serialcheck(result);
+{$ELSE}
+var
+ Overlapped: TOverlapped;
+ x, y, Err: DWord;
+begin
+ Result := 0;
+ if PreTestFailing then {HGJ}
+ Exit; {HGJ}
+ LimitBandwidth(Length, FMaxRecvBandwidth, FNextRecv);
+ FillChar(Overlapped, Sizeof(Overlapped), 0);
+ SetSynaError(sOK);
+ y := 0;
+ if not ReadFile(FHandle, Buffer^, length, Dword(Result), @Overlapped) then
+ y := GetLastError;
+ if y = ERROR_IO_PENDING then
+ begin
+ x := WaitForSingleObject(FHandle, FDeadlockTimeout);
+ if x = WAIT_TIMEOUT then
+ begin
+ PurgeComm(FHandle, PURGE_RXABORT);
+ SetSynaError(ErrTimeout);
+ end;
+ GetOverlappedResult(FHandle, Overlapped, Dword(Result), False);
+ end
+ else
+ SetSynaError(y);
+ ClearCommError(FHandle, err, nil);
+ if err <> 0 then
+ DecodeCommError(err);
+{$ENDIF}
+ ExceptCheck;
+ DoStatus(HR_ReadCount, IntToStr(Result));
+end;
+
+function TBlockSerial.RecvBufferEx(buffer: pointer; length: integer; timeout: integer): integer;
+var
+ s: string;
+ rl, l: integer;
+ ti: LongWord;
+begin
+ Result := 0;
+ if PreTestFailing then {HGJ}
+ Exit; {HGJ}
+ SetSynaError(sOK);
+ rl := 0;
+ repeat
+ ti := GetTick;
+ s := RecvPacket(Timeout);
+ l := System.Length(s);
+ if (rl + l) > Length then
+ l := Length - rl;
+ Move(Pointer(s)^, IncPoint(Buffer, rl)^, l);
+ rl := rl + l;
+ if FLastError <> sOK then
+ Break;
+ if rl >= Length then
+ Break;
+ if not FInterPacketTimeout then
+ begin
+ Timeout := Timeout - integer(TickDelta(ti, GetTick));
+ if Timeout <= 0 then
+ begin
+ SetSynaError(ErrTimeout);
+ Break;
+ end;
+ end;
+ until False;
+ delete(s, 1, l);
+ FBuffer := s;
+ Result := rl;
+end;
+
+function TBlockSerial.RecvBufferStr(Length: Integer; Timeout: Integer): string;
+var
+ x: integer;
+begin
+ Result := '';
+ if PreTestFailing then {HGJ}
+ Exit; {HGJ}
+ SetSynaError(sOK);
+ if Length > 0 then
+ begin
+ Setlength(Result, Length);
+ x := RecvBufferEx(PChar(Result), Length , Timeout);
+ if FLastError = sOK then
+ SetLength(Result, x)
+ else
+ Result := '';
+ end;
+end;
+
+function TBlockSerial.RecvPacket(Timeout: Integer): string;
+var
+ x: integer;
+begin
+ Result := '';
+ if PreTestFailing then {HGJ}
+ Exit; {HGJ}
+ SetSynaError(sOK);
+ if FBuffer <> '' then
+ begin
+ Result := FBuffer;
+ FBuffer := '';
+ end
+ else
+ begin
+ //not drain CPU on large downloads...
+ Sleep(0);
+ x := WaitingData;
+ if x > 0 then
+ begin
+ SetLength(Result, x);
+ x := RecvBuffer(Pointer(Result), x);
+ if x >= 0 then
+ SetLength(Result, x);
+ end
+ else
+ begin
+ if CanRead(Timeout) then
+ begin
+ x := WaitingData;
+ if x = 0 then
+ SetSynaError(ErrTimeout);
+ if x > 0 then
+ begin
+ SetLength(Result, x);
+ x := RecvBuffer(Pointer(Result), x);
+ if x >= 0 then
+ SetLength(Result, x);
+ end;
+ end
+ else
+ SetSynaError(ErrTimeout);
+ end;
+ end;
+ ExceptCheck;
+end;
+
+
+function TBlockSerial.RecvByte(timeout: integer): byte;
+begin
+ Result := 0;
+ if PreTestFailing then {HGJ}
+ Exit; {HGJ}
+ SetSynaError(sOK);
+ if FBuffer = '' then
+ FBuffer := RecvPacket(Timeout);
+ if (FLastError = sOK) and (FBuffer <> '') then
+ begin
+ Result := Ord(FBuffer[1]);
+ System.Delete(FBuffer, 1, 1);
+ end;
+ ExceptCheck;
+end;
+
+function TBlockSerial.RecvTerminated(Timeout: Integer; const Terminator: string): string;
+var
+ x: Integer;
+ s: string;
+ l: Integer;
+ CorCRLF: Boolean;
+ t: ansistring;
+ tl: integer;
+ ti: LongWord;
+begin
+ Result := '';
+ if PreTestFailing then {HGJ}
+ Exit; {HGJ}
+ SetSynaError(sOK);
+ l := system.Length(Terminator);
+ if l = 0 then
+ Exit;
+ tl := l;
+ CorCRLF := FConvertLineEnd and (Terminator = CRLF);
+ s := '';
+ x := 0;
+ repeat
+ ti := GetTick;
+ //get rest of FBuffer or incomming new data...
+ s := s + RecvPacket(Timeout);
+ if FLastError <> sOK then
+ Break;
+ x := 0;
+ if Length(s) > 0 then
+ if CorCRLF then
+ begin
+ if FLastCR and (s[1] = LF) then
+ Delete(s, 1, 1);
+ if FLastLF and (s[1] = CR) then
+ Delete(s, 1, 1);
+ FLastCR := False;
+ FLastLF := False;
+ t := '';
+ x := PosCRLF(s, t);
+ tl := system.Length(t);
+ if t = CR then
+ FLastCR := True;
+ if t = LF then
+ FLastLF := True;
+ end
+ else
+ begin
+ x := pos(Terminator, s);
+ tl := l;
+ end;
+ if (FMaxLineLength <> 0) and (system.Length(s) > FMaxLineLength) then
+ begin
+ SetSynaError(ErrMaxBuffer);
+ Break;
+ end;
+ if x > 0 then
+ Break;
+ if not FInterPacketTimeout then
+ begin
+ Timeout := Timeout - integer(TickDelta(ti, GetTick));
+ if Timeout <= 0 then
+ begin
+ SetSynaError(ErrTimeout);
+ Break;
+ end;
+ end;
+ until False;
+ if x > 0 then
+ begin
+ Result := Copy(s, 1, x - 1);
+ System.Delete(s, 1, x + tl - 1);
+ end;
+ FBuffer := s;
+ ExceptCheck;
+end;
+
+
+function TBlockSerial.RecvString(Timeout: Integer): string;
+var
+ s: string;
+begin
+ Result := '';
+ s := RecvTerminated(Timeout, #13 + #10);
+ if FLastError = sOK then
+ Result := s;
+end;
+
+function TBlockSerial.RecvInteger(Timeout: Integer): Integer;
+var
+ s: string;
+begin
+ Result := 0;
+ s := RecvBufferStr(4, Timeout);
+ if FLastError = 0 then
+ Result := (ord(s[1]) + ord(s[2]) * 256) + (ord(s[3]) + ord(s[4]) * 256) * 65536;
+end;
+
+function TBlockSerial.RecvBlock(Timeout: Integer): string;
+var
+ x: integer;
+begin
+ Result := '';
+ x := RecvInteger(Timeout);
+ if FLastError = 0 then
+ Result := RecvBufferStr(x, Timeout);
+end;
+
+procedure TBlockSerial.RecvStreamRaw(const Stream: TStream; Timeout: Integer);
+var
+ s: string;
+begin
+ repeat
+ s := RecvPacket(Timeout);
+ if FLastError = 0 then
+ WriteStrToStream(Stream, s);
+ until FLastError <> 0;
+end;
+
+procedure TBlockSerial.RecvStreamSize(const Stream: TStream; Timeout: Integer; Size: Integer);
+var
+ s: string;
+ n: integer;
+begin
+ for n := 1 to (Size div cSerialChunk) do
+ begin
+ s := RecvBufferStr(cSerialChunk, Timeout);
+ if FLastError <> 0 then
+ Exit;
+ Stream.Write(Pchar(s)^, cSerialChunk);
+ end;
+ n := Size mod cSerialChunk;
+ if n > 0 then
+ begin
+ s := RecvBufferStr(n, Timeout);
+ if FLastError <> 0 then
+ Exit;
+ Stream.Write(Pchar(s)^, n);
+ end;
+end;
+
+procedure TBlockSerial.RecvStreamIndy(const Stream: TStream; Timeout: Integer);
+var
+ x: integer;
+begin
+ x := RecvInteger(Timeout);
+ x := SwapBytes(x);
+ if FLastError = 0 then
+ RecvStreamSize(Stream, Timeout, x);
+end;
+
+procedure TBlockSerial.RecvStream(const Stream: TStream; Timeout: Integer);
+var
+ x: integer;
+begin
+ x := RecvInteger(Timeout);
+ if FLastError = 0 then
+ RecvStreamSize(Stream, Timeout, x);
+end;
+
+{$IFNDEF WIN32}
+function TBlockSerial.WaitingData: integer;
+begin
+{$IFNDEF FPC}
+ serialcheck(ioctl(integer(FHandle), FIONREAD, @result));
+{$ELSE}
+ serialcheck(fpIoctl(FHandle, FIONREAD, @result));
+{$ENDIF}
+ if FLastError <> 0 then
+ Result := 0;
+ ExceptCheck;
+end;
+{$ELSE}
+function TBlockSerial.WaitingData: integer;
+var
+ stat: TComStat;
+ err: DWORD;
+begin
+ if ClearCommError(FHandle, err, @stat) then
+ begin
+ SetSynaError(sOK);
+ Result := stat.cbInQue;
+ end
+ else
+ begin
+ SerialCheck(sErr);
+ Result := 0;
+ end;
+ ExceptCheck;
+end;
+{$ENDIF}
+
+function TBlockSerial.WaitingDataEx: integer;
+begin
+ if FBuffer <> '' then
+ Result := Length(FBuffer)
+ else
+ Result := Waitingdata;
+end;
+
+{$IFNDEF WIN32}
+function TBlockSerial.SendingData: integer;
+begin
+ SetSynaError(sOK);
+ Result := 0;
+end;
+{$ELSE}
+function TBlockSerial.SendingData: integer;
+var
+ stat: TComStat;
+ err: DWORD;
+begin
+ SetSynaError(sOK);
+ if not ClearCommError(FHandle, err, @stat) then
+ serialcheck(sErr);
+ ExceptCheck;
+ result := stat.cbOutQue;
+end;
+{$ENDIF}
+
+{$IFNDEF WIN32}
+procedure TBlockSerial.DcbToTermios(const dcb: TDCB; var term: termios);
+var
+ n: integer;
+ x: cardinal;
+begin
+ //others
+ cfmakeraw(term);
+ term.c_cflag := term.c_cflag or CREAD;
+ term.c_cflag := term.c_cflag or CLOCAL;
+ term.c_cflag := term.c_cflag or HUPCL;
+ //hardware handshake
+ if (dcb.flags and dcb_RtsControlHandshake) > 0 then
+ term.c_cflag := term.c_cflag or CRTSCTS
+ else
+ term.c_cflag := term.c_cflag and (not CRTSCTS);
+ //software handshake
+ if (dcb.flags and dcb_OutX) > 0 then
+ term.c_iflag := term.c_iflag or IXON or IXOFF or IXANY
+ else
+ term.c_iflag := term.c_iflag and (not (IXON or IXOFF or IXANY));
+ //size of byte
+ term.c_cflag := term.c_cflag and (not CSIZE);
+ case dcb.bytesize of
+ 5:
+ term.c_cflag := term.c_cflag or CS5;
+ 6:
+ term.c_cflag := term.c_cflag or CS6;
+ 7:
+{$IFDEF FPC}
+ term.c_cflag := term.c_cflag or CS7;
+{$ELSE}
+ term.c_cflag := term.c_cflag or CS7fix;
+{$ENDIF}
+ 8:
+ term.c_cflag := term.c_cflag or CS8;
+ end;
+ //parity
+ if (dcb.flags and dcb_ParityCheck) > 0 then
+ term.c_cflag := term.c_cflag or PARENB
+ else
+ term.c_cflag := term.c_cflag and (not PARENB);
+ case dcb.parity of
+ 1: //'O'
+ term.c_cflag := term.c_cflag or PARODD;
+ 2: //'E'
+ term.c_cflag := term.c_cflag and (not PARODD);
+ end;
+ //stop bits
+ if dcb.stopbits > 0 then
+ term.c_cflag := term.c_cflag or CSTOPB
+ else
+ term.c_cflag := term.c_cflag and (not CSTOPB);
+ //set baudrate;
+ x := 0;
+ for n := 0 to Maxrates do
+ if rates[n, 0] = dcb.BaudRate then
+ begin
+ x := rates[n, 1];
+ break;
+ end;
+ cfsetospeed(term, x);
+ cfsetispeed(term, x);
+end;
+
+procedure TBlockSerial.TermiosToDcb(const term: termios; var dcb: TDCB);
+var
+ n: integer;
+ x: cardinal;
+begin
+ //set baudrate;
+ dcb.baudrate := 0;
+ {$IFDEF FPC}
+ //why FPC not have cfgetospeed???
+ x := term.c_oflag and $0F;
+ {$ELSE}
+ x := cfgetospeed(term);
+ {$ENDIF}
+ for n := 0 to Maxrates do
+ if rates[n, 1] = x then
+ begin
+ dcb.baudrate := rates[n, 0];
+ break;
+ end;
+ //hardware handshake
+ if (term.c_cflag and CRTSCTS) > 0 then
+ dcb.flags := dcb.flags or dcb_RtsControlHandshake or dcb_OutxCtsFlow
+ else
+ dcb.flags := dcb.flags and (not (dcb_RtsControlHandshake or dcb_OutxCtsFlow));
+ //software handshake
+ if (term.c_cflag and IXOFF) > 0 then
+ dcb.flags := dcb.flags or dcb_OutX or dcb_InX
+ else
+ dcb.flags := dcb.flags and (not (dcb_OutX or dcb_InX));
+ //size of byte
+ case term.c_cflag and CSIZE of
+ CS5:
+ dcb.bytesize := 5;
+ CS6:
+ dcb.bytesize := 6;
+ CS7fix:
+ dcb.bytesize := 7;
+ CS8:
+ dcb.bytesize := 8;
+ end;
+ //parity
+ if (term.c_cflag and PARENB) > 0 then
+ dcb.flags := dcb.flags or dcb_ParityCheck
+ else
+ dcb.flags := dcb.flags and (not dcb_ParityCheck);
+ dcb.parity := 0;
+ if (term.c_cflag and PARODD) > 0 then
+ dcb.parity := 1
+ else
+ dcb.parity := 2;
+ //stop bits
+ if (term.c_cflag and CSTOPB) > 0 then
+ dcb.stopbits := 2
+ else
+ dcb.stopbits := 0;
+end;
+{$ENDIF}
+
+{$IFNDEF WIN32}
+procedure TBlockSerial.SetCommState;
+begin
+ DcbToTermios(dcb, termiosstruc);
+ SerialCheck(tcsetattr(integer(FHandle), TCSANOW, termiosstruc));
+ ExceptCheck;
+end;
+{$ELSE}
+procedure TBlockSerial.SetCommState;
+begin
+ SetSynaError(sOK);
+ if not windows.SetCommState(Fhandle, dcb) then
+ SerialCheck(sErr);
+ ExceptCheck;
+end;
+{$ENDIF}
+
+{$IFNDEF WIN32}
+procedure TBlockSerial.GetCommState;
+begin
+ SerialCheck(tcgetattr(integer(FHandle), termiosstruc));
+ ExceptCheck;
+ TermiostoDCB(termiosstruc, dcb);
+end;
+{$ELSE}
+procedure TBlockSerial.GetCommState;
+begin
+ SetSynaError(sOK);
+ if not windows.GetCommState(Fhandle, dcb) then
+ SerialCheck(sErr);
+ ExceptCheck;
+end;
+{$ENDIF}
+
+procedure TBlockSerial.SetSizeRecvBuffer(size: integer);
+begin
+{$IFDEF WIN32}
+ SetupComm(Fhandle, size, 0);
+ GetCommState;
+ dcb.XonLim := size div 4;
+ dcb.XoffLim := size div 4;
+ SetCommState;
+{$ENDIF}
+ FRecvBuffer := size;
+end;
+
+function TBlockSerial.GetDSR: Boolean;
+begin
+ ModemStatus;
+{$IFNDEF WIN32}
+ Result := (FModemWord and TIOCM_DSR) > 0;
+{$ELSE}
+ Result := (FModemWord and MS_DSR_ON) > 0;
+{$ENDIF}
+end;
+
+procedure TBlockSerial.SetDTRF(Value: Boolean);
+begin
+{$IFNDEF WIN32}
+ ModemStatus;
+ if Value then
+ FModemWord := FModemWord or TIOCM_DTR
+ else
+ FModemWord := FModemWord and not TIOCM_DTR;
+ {$IFNDEF FPC}
+ ioctl(integer(FHandle), TIOCMSET, @FModemWord);
+ {$ELSE}
+ fpioctl(integer(FHandle), TIOCMSET, @FModemWord);
+ {$ENDIF}
+{$ELSE}
+ if Value then
+ EscapeCommFunction(FHandle, SETDTR)
+ else
+ EscapeCommFunction(FHandle, CLRDTR);
+{$ENDIF}
+end;
+
+function TBlockSerial.GetCTS: Boolean;
+begin
+ ModemStatus;
+{$IFNDEF WIN32}
+ Result := (FModemWord and TIOCM_CTS) > 0;
+{$ELSE}
+ Result := (FModemWord and MS_CTS_ON) > 0;
+{$ENDIF}
+end;
+
+procedure TBlockSerial.SetRTSF(Value: Boolean);
+begin
+{$IFNDEF WIN32}
+ ModemStatus;
+ if Value then
+ FModemWord := FModemWord or TIOCM_RTS
+ else
+ FModemWord := FModemWord and not TIOCM_RTS;
+ {$IFNDEF FPC}
+ ioctl(integer(FHandle), TIOCMSET, @FModemWord);
+ {$ELSE}
+ fpioctl(integer(FHandle), TIOCMSET, @FModemWord);
+ {$ENDIF}
+{$ELSE}
+ if Value then
+ EscapeCommFunction(FHandle, SETRTS)
+ else
+ EscapeCommFunction(FHandle, CLRRTS);
+{$ENDIF}
+end;
+
+function TBlockSerial.GetCarrier: Boolean;
+begin
+ ModemStatus;
+{$IFNDEF WIN32}
+ Result := (FModemWord and TIOCM_CAR) > 0;
+{$ELSE}
+ Result := (FModemWord and MS_RLSD_ON) > 0;
+{$ENDIF}
+end;
+
+function TBlockSerial.GetRing: Boolean;
+begin
+ ModemStatus;
+{$IFNDEF WIN32}
+ Result := (FModemWord and TIOCM_RNG) > 0;
+{$ELSE}
+ Result := (FModemWord and MS_RING_ON) > 0;
+{$ENDIF}
+end;
+
+{$IFDEF WIN32}
+function TBlockSerial.CanEvent(Event: dword; Timeout: integer): boolean;
+var
+ ex: DWord;
+ y: Integer;
+ Overlapped: TOverlapped;
+begin
+ FillChar(Overlapped, Sizeof(Overlapped), 0);
+ Overlapped.hEvent := CreateEvent(nil, True, False, nil);
+ try
+ SetCommMask(FHandle, Event);
+ SetSynaError(sOK);
+ if (Event = EV_RXCHAR) and (Waitingdata > 0) then
+ Result := True
+ else
+ begin
+ y := 0;
+ if not WaitCommEvent(FHandle, ex, @Overlapped) then
+ y := GetLastError;
+ if y = ERROR_IO_PENDING then
+ begin
+ //timedout
+ WaitForSingleObject(Overlapped.hEvent, Timeout);
+ SetCommMask(FHandle, 0);
+ GetOverlappedResult(FHandle, Overlapped, DWord(y), True);
+ end;
+ Result := (ex and Event) = Event;
+ end;
+ finally
+ SetCommMask(FHandle, 0);
+ CloseHandle(Overlapped.hEvent);
+ end;
+end;
+{$ENDIF}
+
+{$IFNDEF WIN32}
+function TBlockSerial.CanRead(Timeout: integer): boolean;
+var
+ FDSet: TFDSet;
+ TimeVal: PTimeVal;
+ TimeV: TTimeVal;
+ x: Integer;
+begin
+ TimeV.tv_usec := (Timeout mod 1000) * 1000;
+ TimeV.tv_sec := Timeout div 1000;
+ TimeVal := @TimeV;
+ if Timeout = -1 then
+ TimeVal := nil;
+ {$IFNDEF FPC}
+ FD_ZERO(FDSet);
+ FD_SET(integer(FHandle), FDSet);
+ x := Select(integer(FHandle) + 1, @FDSet, nil, nil, TimeVal);
+ {$ELSE}
+ fpFD_ZERO(FDSet);
+ fpFD_SET(integer(FHandle), FDSet);
+ x := fpSelect(integer(FHandle) + 1, @FDSet, nil, nil, TimeVal);
+ {$ENDIF}
+ SerialCheck(x);
+ if FLastError <> sOK then
+ x := 0;
+ Result := x > 0;
+ ExceptCheck;
+ if Result then
+ DoStatus(HR_CanRead, '');
+end;
+{$ELSE}
+function TBlockSerial.CanRead(Timeout: integer): boolean;
+begin
+ Result := WaitingData > 0;
+ if not Result then
+ Result := CanEvent(EV_RXCHAR, Timeout);
+ if Result then
+ DoStatus(HR_CanRead, '');
+end;
+{$ENDIF}
+
+{$IFNDEF WIN32}
+function TBlockSerial.CanWrite(Timeout: integer): boolean;
+var
+ FDSet: TFDSet;
+ TimeVal: PTimeVal;
+ TimeV: TTimeVal;
+ x: Integer;
+begin
+ TimeV.tv_usec := (Timeout mod 1000) * 1000;
+ TimeV.tv_sec := Timeout div 1000;
+ TimeVal := @TimeV;
+ if Timeout = -1 then
+ TimeVal := nil;
+ {$IFNDEF FPC}
+ FD_ZERO(FDSet);
+ FD_SET(integer(FHandle), FDSet);
+ x := Select(integer(FHandle) + 1, nil, @FDSet, nil, TimeVal);
+ {$ELSE}
+ fpFD_ZERO(FDSet);
+ fpFD_SET(integer(FHandle), FDSet);
+ x := fpSelect(integer(FHandle) + 1, nil, @FDSet, nil, TimeVal);
+ {$ENDIF}
+ SerialCheck(x);
+ if FLastError <> sOK then
+ x := 0;
+ Result := x > 0;
+ ExceptCheck;
+ if Result then
+ DoStatus(HR_CanWrite, '');
+end;
+{$ELSE}
+function TBlockSerial.CanWrite(Timeout: integer): boolean;
+var
+ t: LongWord;
+begin
+ Result := SendingData = 0;
+ if not Result then
+ Result := CanEvent(EV_TXEMPTY, Timeout);
+ if Result and (Win32Platform <> VER_PLATFORM_WIN32_NT) then
+ begin
+ t := GetTick;
+ while not ReadTxEmpty(FPortAddr) do
+ begin
+ if TickDelta(t, GetTick) > 255 then
+ Break;
+ Sleep(0);
+ end;
+ end;
+ if Result then
+ DoStatus(HR_CanWrite, '');
+end;
+{$ENDIF}
+
+function TBlockSerial.CanReadEx(Timeout: integer): boolean;
+begin
+ if Fbuffer <> '' then
+ Result := True
+ else
+ Result := CanRead(Timeout);
+end;
+
+procedure TBlockSerial.EnableRTSToggle(Value: boolean);
+begin
+ SetSynaError(sOK);
+{$IFNDEF WIN32}
+ FRTSToggle := Value;
+ if Value then
+ RTS:=False;
+{$ELSE}
+ if Win32Platform = VER_PLATFORM_WIN32_NT then
+ begin
+ GetCommState;
+ if value then
+ dcb.Flags := dcb.Flags or dcb_RtsControlToggle
+ else
+ dcb.flags := dcb.flags and (not dcb_RtsControlToggle);
+ SetCommState;
+ end
+ else
+ begin
+ FRTSToggle := Value;
+ if Value then
+ RTS:=False;
+ end;
+{$ENDIF}
+end;
+
+procedure TBlockSerial.Flush;
+begin
+{$IFNDEF WIN32}
+ SerialCheck(tcdrain(integer(FHandle)));
+{$ELSE}
+ SetSynaError(sOK);
+ if not Flushfilebuffers(FHandle) then
+ SerialCheck(sErr);
+{$ENDIF}
+ ExceptCheck;
+end;
+
+{$IFNDEF WIN32}
+procedure TBlockSerial.Purge;
+begin
+ {$IFNDEF FPC}
+ SerialCheck(ioctl(integer(FHandle), TCFLSH, TCIOFLUSH));
+ {$ELSE}
+ SerialCheck(fpioctl(integer(FHandle), TCFLSH, TCIOFLUSH));
+ {$ENDIF}
+ FBuffer := '';
+ ExceptCheck;
+end;
+{$ELSE}
+procedure TBlockSerial.Purge;
+var
+ x: integer;
+begin
+ SetSynaError(sOK);
+ x := PURGE_TXABORT or PURGE_TXCLEAR or PURGE_RXABORT or PURGE_RXCLEAR;
+ if not PurgeComm(FHandle, x) then
+ SerialCheck(sErr);
+ FBuffer := '';
+ ExceptCheck;
+end;
+{$ENDIF}
+
+function TBlockSerial.ModemStatus: integer;
+begin
+ Result := 0;
+{$IFNDEF WIN32}
+ {$IFNDEF FPC}
+ SerialCheck(ioctl(integer(FHandle), TIOCMGET, @Result));
+ {$ELSE}
+ SerialCheck(fpioctl(integer(FHandle), TIOCMGET, @Result));
+ {$ENDIF}
+{$ELSE}
+ SetSynaError(sOK);
+ if not GetCommModemStatus(FHandle, dword(Result)) then
+ SerialCheck(sErr);
+{$ENDIF}
+ ExceptCheck;
+ FModemWord := Result;
+end;
+
+procedure TBlockSerial.SetBreak(Duration: integer);
+begin
+{$IFNDEF WIN32}
+ SerialCheck(tcsendbreak(integer(FHandle), Duration));
+{$ELSE}
+ SetCommBreak(FHandle);
+ Sleep(Duration);
+ SetSynaError(sOK);
+ if not ClearCommBreak(FHandle) then
+ SerialCheck(sErr);
+{$ENDIF}
+end;
+
+{$IFDEF WIN32}
+procedure TBlockSerial.DecodeCommError(Error: DWord);
+begin
+ if (Error and DWord(CE_FRAME)) > 1 then
+ FLastError := ErrFrame;
+ if (Error and DWord(CE_OVERRUN)) > 1 then
+ FLastError := ErrOverrun;
+ if (Error and DWord(CE_RXOVER)) > 1 then
+ FLastError := ErrRxOver;
+ if (Error and DWord(CE_RXPARITY)) > 1 then
+ FLastError := ErrRxParity;
+ if (Error and DWord(CE_TXFULL)) > 1 then
+ FLastError := ErrTxFull;
+end;
+{$ENDIF}
+
+//HGJ
+function TBlockSerial.PreTestFailing: Boolean;
+begin
+ if not FInstanceActive then
+ begin
+ RaiseSynaError(ErrPortNotOpen);
+ result:= true;
+ Exit;
+ end;
+ Result := not TestCtrlLine;
+ if result then
+ RaiseSynaError(ErrNoDeviceAnswer)
+end;
+
+function TBlockSerial.TestCtrlLine: Boolean;
+begin
+ result := ((not FTestDSR) or DSR) and ((not FTestCTS) or CTS);
+end;
+
+function TBlockSerial.ATCommand(value: string): string;
+var
+ s: string;
+ ConvSave: Boolean;
+begin
+ result := '';
+ FAtResult := False;
+ ConvSave := FConvertLineEnd;
+ try
+ FConvertLineEnd := True;
+ SendString(value + #$0D);
+ repeat
+ s := RecvString(FAtTimeout);
+ if s <> Value then
+ result := result + s + CRLF;
+ if s = 'OK' then
+ begin
+ FAtResult := True;
+ break;
+ end;
+ if s = 'ERROR' then
+ break;
+ until FLastError <> sOK;
+ finally
+ FConvertLineEnd := Convsave;
+ end;
+end;
+
+
+function TBlockSerial.ATConnect(value: string): string;
+var
+ s: string;
+ ConvSave: Boolean;
+begin
+ result := '';
+ FAtResult := False;
+ ConvSave := FConvertLineEnd;
+ try
+ FConvertLineEnd := True;
+ SendString(value + #$0D);
+ repeat
+ s := RecvString(90 * FAtTimeout);
+ if s <> Value then
+ result := result + s + CRLF;
+ if s = 'NO CARRIER' then
+ break;
+ if s = 'ERROR' then
+ break;
+ if s = 'BUSY' then
+ break;
+ if s = 'NO DIALTONE' then
+ break;
+ if Pos('CONNECT', s) = 1 then
+ begin
+ FAtResult := True;
+ break;
+ end;
+ until FLastError <> sOK;
+ finally
+ FConvertLineEnd := Convsave;
+ end;
+end;
+
+function TBlockSerial.SerialCheck(SerialResult: integer): integer;
+begin
+ if SerialResult = integer(INVALID_HANDLE_VALUE) then
+{$IFDEF WIN32}
+ result := GetLastError
+{$ELSE}
+ {$IFNDEF FPC}
+ result := GetLastError
+ {$ELSE}
+ result := fpGetErrno
+ {$ENDIF}
+{$ENDIF}
+ else
+ result := sOK;
+ FLastError := result;
+ FLastErrorDesc := GetErrorDesc(FLastError);
+end;
+
+procedure TBlockSerial.ExceptCheck;
+var
+ e: ESynaSerError;
+ s: string;
+begin
+ if FRaiseExcept and (FLastError <> sOK) then
+ begin
+ s := GetErrorDesc(FLastError);
+ e := ESynaSerError.CreateFmt('Communication error %d: %s', [FLastError, s]);
+ e.ErrorCode := FLastError;
+ e.ErrorMessage := s;
+ raise e;
+ end;
+end;
+
+procedure TBlockSerial.SetSynaError(ErrNumber: integer);
+begin
+ FLastError := ErrNumber;
+ FLastErrorDesc := GetErrorDesc(FLastError);
+end;
+
+procedure TBlockSerial.RaiseSynaError(ErrNumber: integer);
+begin
+ SetSynaError(ErrNumber);
+ ExceptCheck;
+end;
+
+procedure TBlockSerial.DoStatus(Reason: THookSerialReason; const Value: string);
+begin
+ if assigned(OnStatus) then
+ OnStatus(Self, Reason, Value);
+end;
+
+{======================================================================}
+
+class function TBlockSerial.GetErrorDesc(ErrorCode: integer): string;
+begin
+ Result:= '';
+ case ErrorCode of
+ sOK: Result := 'OK';
+ ErrAlreadyOwned: Result := 'Port owned by other process';{HGJ}
+ ErrAlreadyInUse: Result := 'Instance already in use'; {HGJ}
+ ErrWrongParameter: Result := 'Wrong paramter at call'; {HGJ}
+ ErrPortNotOpen: Result := 'Instance not yet connected'; {HGJ}
+ ErrNoDeviceAnswer: Result := 'No device answer detected'; {HGJ}
+ ErrMaxBuffer: Result := 'Maximal buffer length exceeded';
+ ErrTimeout: Result := 'Timeout during operation';
+ ErrNotRead: Result := 'Reading of data failed';
+ ErrFrame: Result := 'Receive framing error';
+ ErrOverrun: Result := 'Receive Overrun Error';
+ ErrRxOver: Result := 'Receive Queue overflow';
+ ErrRxParity: Result := 'Receive Parity Error';
+ ErrTxFull: Result := 'Tranceive Queue is full';
+ end;
+ if Result = '' then
+ begin
+ Result := SysErrorMessage(ErrorCode);
+ end;
+end;
+
+
+{---------- cpom Comport Ownership Manager Routines -------------
+ by Hans-Georg Joepgen of Stuttgart, Germany.
+ Copyright (c) 2002, by Hans-Georg Joepgen
+
+ Stefan Krauss of Stuttgart, Germany, contributed literature and Internet
+ research results, invaluable advice and excellent answers to the Comport
+ Ownership Manager.
+}
+
+{$IFDEF LINUX}
+
+function TBlockSerial.LockfileName: String;
+var
+ s: string;
+begin
+ s := SeparateRight(FDevice, '/dev/');
+ result := LockfileDirectory + '/LCK..' + s;
+end;
+
+procedure TBlockSerial.CreateLockfile(PidNr: integer);
+var
+ f: TextFile;
+ s: string;
+begin
+ // Create content for file
+ s := IntToStr(PidNr);
+ while length(s) < 10 do
+ s := ' ' + s;
+ // Create file
+ try
+ AssignFile(f, LockfileName);
+ try
+ Rewrite(f);
+ writeln(f, s);
+ finally
+ CloseFile(f);
+ end;
+ // Allow all users to enjoy the benefits of cpom
+ s := 'chmod a+rw ' + LockfileName;
+{$IFNDEF FPC}
+ Libc.system(pchar(s));
+{$ELSE}
+ fpSystem(s);
+{$ENDIF}
+ except
+ // not raise exception, if you not have write permission for lock.
+ on Exception do
+ ;
+ end;
+end;
+
+function TBlockSerial.ReadLockfile: integer;
+{Returns PID from Lockfile. Lockfile must exist.}
+var
+ f: TextFile;
+ s: string;
+begin
+ AssignFile(f, LockfileName);
+ Reset(f);
+ try
+ readln(f, s);
+ finally
+ CloseFile(f);
+ end;
+ Result := StrToIntDef(s, -1)
+end;
+
+function TBlockSerial.cpomComportAccessible: boolean;
+var
+ MyPid: integer;
+ Filename: string;
+begin
+ Filename := LockfileName;
+ {$IFNDEF FPC}
+ MyPid := Libc.getpid;
+ {$ELSE}
+ MyPid := fpGetPid;
+ {$ENDIF}
+ // Make sure, the Lock Files Directory exists. We need it.
+ if not DirectoryExists(LockfileDirectory) then
+ CreateDir(LockfileDirectory);
+ // Check the Lockfile
+ if not FileExists (Filename) then
+ begin // comport is not locked. Lock it for us.
+ CreateLockfile(MyPid);
+ result := true;
+ exit; // done.
+ end;
+ // Is port owned by orphan? Then it's time for error recovery.
+ //FPC forgot to add getsid.. :-(
+ {$IFNDEF FPC}
+ if Libc.getsid(ReadLockfile) = -1 then
+ begin // Lockfile was left from former desaster
+ DeleteFile(Filename); // error recovery
+ CreateLockfile(MyPid);
+ result := true;
+ exit;
+ end;
+ {$ENDIF}
+ result := false // Sorry, port is owned by living PID and locked
+end;
+
+procedure TBlockSerial.cpomReleaseComport;
+begin
+ DeleteFile(LockfileName);
+end;
+
+{$ENDIF}
+{----------------------------------------------------------------}
+
+{$IFDEF WIN32}
+function GetSerialPortNames: string;
+var
+ reg: TRegistry;
+ l, v: TStringList;
+ n: integer;
+begin
+ l := TStringList.Create;
+ v := TStringList.Create;
+ reg := TRegistry.Create;
+ try
+{$IFNDEF VER100}
+{$IFNDEF VER120}
+ reg.Access := KEY_READ;
+{$ENDIF}
+{$ENDIF}
+ reg.RootKey := HKEY_LOCAL_MACHINE;
+ reg.OpenKey('\HARDWARE\DEVICEMAP\SERIALCOMM', false);
+ reg.GetValueNames(l);
+ for n := 0 to l.Count - 1 do
+ v.Add(reg.ReadString(l[n]));
+ Result := v.CommaText;
+ finally
+ reg.Free;
+ l.Free;
+ v.Free;
+ end;
+end;
+{$ENDIF}
+{$IFNDEF WIN32}
+function GetSerialPortNames: string;
+var
+ Index: Integer;
+ Data: string;
+ TmpPorts: String;
+ sr : TSearchRec;
+begin
+ try
+ TmpPorts := '';
+ if FindFirst('/dev/ttyS*', $FFFFFFFF, sr) = 0 then
+ begin
+ repeat
+ if (sr.Attr and $FFFFFFFF) = Sr.Attr then
+ begin
+ data := sr.Name;
+ index := length(data);
+ while (index > 1) and (data[index] <> '/') do
+ index := index - 1;
+ TmpPorts := TmpPorts + ' ' + copy(data, 1, index + 1);
+ end;
+ until FindNext(sr) <> 0;
+ end;
+ FindClose(sr);
+ finally
+ Result:=TmpPorts;
+ end;
+end;
+{$ENDIF}
+
+end.
diff --git a/branches/script-component/Units/Synapse/synautil.pas b/branches/script-component/Units/Synapse/synautil.pas
new file mode 100644
index 0000000..0bd1cd4
--- /dev/null
+++ b/branches/script-component/Units/Synapse/synautil.pas
@@ -0,0 +1,1807 @@
+{==============================================================================|
+| Project : Ararat Synapse | 004.013.000 |
+|==============================================================================|
+| Content: support procedures and functions |
+|==============================================================================|
+| Copyright (c)1999-2008, Lukas Gebauer |
+| All rights reserved. |
+| |
+| Redistribution and use in source and binary forms, with or without |
+| modification, are permitted provided that the following conditions are met: |
+| |
+| Redistributions of source code must retain the above copyright notice, this |
+| list of conditions and the following disclaimer. |
+| |
+| Redistributions in binary form must reproduce the above copyright notice, |
+| this list of conditions and the following disclaimer in the documentation |
+| and/or other materials provided with the distribution. |
+| |
+| Neither the name of Lukas Gebauer nor the names of its contributors may |
+| be used to endorse or promote products derived from this software without |
+| specific prior written permission. |
+| |
+| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
+| AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
+| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
+| ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR |
+| ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
+| DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
+| SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
+| CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
+| LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
+| OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
+| DAMAGE. |
+|==============================================================================|
+| The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).|
+| Portions created by Lukas Gebauer are Copyright (c) 1999-2008. |
+| Portions created by Hernan Sanchez are Copyright (c) 2000. |
+| All Rights Reserved. |
+|==============================================================================|
+| Contributor(s): |
+| Hernan Sanchez (hernan.sanchez@iname.com) |
+|==============================================================================|
+| History: see HISTORY.HTM from distribution package |
+| (Found at URL: http://www.ararat.cz/synapse/) |
+|==============================================================================}
+
+{:@abstract(Support procedures and functions)}
+
+{$IFDEF FPC}
+ {$MODE DELPHI}
+{$ENDIF}
+{$Q-}
+{$R-}
+{$H+}
+
+unit synautil;
+
+interface
+
+uses
+{$IFDEF WIN32}
+ Windows,
+{$ELSE}
+ {$IFDEF FPC}
+ UnixUtil, Unix, BaseUnix,
+ {$ELSE}
+ Libc,
+ {$ENDIF}
+{$ENDIF}
+{$IFDEF CIL}
+ System.IO,
+{$ENDIF}
+ SysUtils, Classes, SynaFpc;
+
+{$IFDEF VER100}
+type
+ int64 = integer;
+{$ENDIF}
+
+{:Return your timezone bias from UTC time in minutes.}
+function TimeZoneBias: integer;
+
+{:Return your timezone bias from UTC time in string representation like "+0200".}
+function TimeZone: string;
+
+{:Returns current time in format defined in RFC-822. Useful for SMTP messages,
+ but other protocols use this time format as well. Results contains the timezone
+ specification. Four digit year is used to break any Y2K concerns. (Example
+ 'Fri, 15 Oct 1999 21:14:56 +0200')}
+function Rfc822DateTime(t: TDateTime): string;
+
+{:Returns date and time in format defined in C compilers in format "mmm dd hh:nn:ss"}
+function CDateTime(t: TDateTime): string;
+
+{:Returns date and time in format defined in format 'yymmdd hhnnss'}
+function SimpleDateTime(t: TDateTime): string;
+
+{:Returns date and time in format defined in ANSI C compilers in format
+ "ddd mmm d hh:nn:ss yyyy" }
+function AnsiCDateTime(t: TDateTime): string;
+
+{:Decode three-letter string with name of month to their month number. If string
+ not match any month name, then is returned 0. For parsing are used predefined
+ names for English, French and German and names from system locale too.}
+function GetMonthNumber(Value: AnsiString): integer;
+
+{:Return decoded time from given string. Time must be witch separator ':'. You
+ can use "hh:mm" or "hh:mm:ss".}
+function GetTimeFromStr(Value: string): TDateTime;
+
+{:Decode string in format "m-d-y" to TDateTime type.}
+function GetDateMDYFromStr(Value: string): TDateTime;
+
+{:Decode various string representations of date and time to Tdatetime type.
+ This function do all timezone corrections too! This function can decode lot of
+ formats like:
+ @longcode(#
+ ddd, d mmm yyyy hh:mm:ss
+ ddd, d mmm yy hh:mm:ss
+ ddd, mmm d yyyy hh:mm:ss
+ ddd mmm dd hh:mm:ss yyyy #)
+
+and more with lot of modifications, include:
+@longcode(#
+Sun, 06 Nov 1994 08:49:37 GMT ; RFC 822, updated by RFC 1123
+Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036
+Sun Nov 6 08:49:37 1994 ; ANSI C's asctime() Format
+#)
+Timezone corrections known lot of symbolic timezone names (like CEST, EDT, etc.)
+or numeric representation (like +0200). By convention defined in RFC timezone
+ +0000 is GMT and -0000 is current your system timezone.}
+function DecodeRfcDateTime(Value: string): TDateTime;
+
+{:Return current system date and time in UTC timezone.}
+function GetUTTime: TDateTime;
+
+{:Set Newdt as current system date and time in UTC timezone. This function work
+ only if you have administrator rights!}
+function SetUTTime(Newdt: TDateTime): Boolean;
+
+{:Return current value of system timer with precizion 1 millisecond. Good for
+ measure time difference.}
+function GetTick: LongWord;
+
+{:Return difference between two timestamps. It working fine only for differences
+ smaller then maxint. (difference must be smaller then 24 days.)}
+function TickDelta(TickOld, TickNew: LongWord): LongWord;
+
+{:Return two characters, which ordinal values represents the value in byte
+ format. (High-endian)}
+function CodeInt(Value: Word): Ansistring;
+
+{:Decodes two characters located at "Index" offset position of the "Value"
+ string to Word values.}
+function DecodeInt(const Value: Ansistring; Index: Integer): Word;
+
+{:Return four characters, which ordinal values represents the value in byte
+ format. (High-endian)}
+function CodeLongInt(Value: LongInt): Ansistring;
+
+{:Decodes four characters located at "Index" offset position of the "Value"
+ string to LongInt values.}
+function DecodeLongInt(const Value: Ansistring; Index: Integer): LongInt;
+
+{:Dump binary buffer stored in a string to a result string.}
+function DumpStr(const Buffer: Ansistring): string;
+
+{:Dump binary buffer stored in a string to a result string. All bytes with code
+ of character is written as character, not as hexadecimal value.}
+function DumpExStr(const Buffer: Ansistring): string;
+
+{:Dump binary buffer stored in a string to a file with DumpFile filename.}
+procedure Dump(const Buffer: AnsiString; DumpFile: string);
+
+{:Dump binary buffer stored in a string to a file with DumpFile filename. All
+ bytes with code of character is written as character, not as hexadecimal value.}
+procedure DumpEx(const Buffer: AnsiString; DumpFile: string);
+
+{:Like TrimLeft, but remove only spaces, not control characters!}
+function TrimSPLeft(const S: string): string;
+
+{:Like TrimRight, but remove only spaces, not control characters!}
+function TrimSPRight(const S: string): string;
+
+{:Like Trim, but remove only spaces, not control characters!}
+function TrimSP(const S: string): string;
+
+{:Returns a portion of the "Value" string located to the left of the "Delimiter"
+ string. If a delimiter is not found, results is original string.}
+function SeparateLeft(const Value, Delimiter: string): string;
+
+{:Returns the portion of the "Value" string located to the right of the
+ "Delimiter" string. If a delimiter is not found, results is original string.}
+function SeparateRight(const Value, Delimiter: string): string;
+
+{:Returns parameter value from string in format:
+ parameter1="value1"; parameter2=value2}
+function GetParameter(const Value, Parameter: string): string;
+
+{:parse value string with elements differed by Delimiter into stringlist.}
+procedure ParseParametersEx(Value, Delimiter: string; const Parameters: TStrings);
+
+{:parse value string with elements differed by ';' into stringlist.}
+procedure ParseParameters(Value: string; const Parameters: TStrings);
+
+{:Index of string in stringlist with same beginning as Value is returned.}
+function IndexByBegin(Value: string; const List: TStrings): integer;
+
+{:Returns only the e-mail portion of an address from the full address format.
+ i.e. returns 'nobody@@somewhere.com' from '"someone" '}
+function GetEmailAddr(const Value: string): string;
+
+{:Returns only the description part from a full address format. i.e. returns
+ 'someone' from '"someone" '}
+function GetEmailDesc(Value: string): string;
+
+{:Returns a string with hexadecimal digits representing the corresponding values
+ of the bytes found in "Value" string.}
+function StrToHex(const Value: Ansistring): string;
+
+{:Returns a string of binary "Digits" representing "Value".}
+function IntToBin(Value: Integer; Digits: Byte): string;
+
+{:Returns an integer equivalent of the binary string in "Value".
+ (i.e. ('10001010') returns 138)}
+function BinToInt(const Value: string): Integer;
+
+{:Parses a URL to its various components.}
+function ParseURL(URL: string; var Prot, User, Pass, Host, Port, Path,
+ Para: string): string;
+
+{:Replaces all "Search" string values found within "Value" string, with the
+ "Replace" string value.}
+function ReplaceString(Value, Search, Replace: AnsiString): AnsiString;
+
+{:It is like RPos, but search is from specified possition.}
+function RPosEx(const Sub, Value: string; From: integer): Integer;
+
+{:It is like POS function, but from right side of Value string.}
+function RPos(const Sub, Value: String): Integer;
+
+{:Like @link(fetch), but working with binary strings, not with text.}
+function FetchBin(var Value: string; const Delimiter: string): string;
+
+{:Fetch string from left of Value string.}
+function Fetch(var Value: string; const Delimiter: string): string;
+
+{:Fetch string from left of Value string. This function ignore delimitesr inside
+ quotations.}
+function FetchEx(var Value: string; const Delimiter, Quotation: string): string;
+
+{:If string is binary string (contains non-printable characters), then is
+ returned true.}
+function IsBinaryString(const Value: string): Boolean;
+
+{:return position of string terminator in string. If terminator found, then is
+ returned in terminator parameter.
+ Possible line terminators are: CRLF, LFCR, CR, LF}
+function PosCRLF(const Value: AnsiString; var Terminator: AnsiString): integer;
+
+{:Delete empty strings from end of stringlist.}
+Procedure StringsTrim(const value: TStrings);
+
+{:Like Pos function, buf from given string possition.}
+function PosFrom(const SubStr, Value: String; From: integer): integer;
+
+{$IFNDEF CIL}
+{:Increase pointer by value.}
+function IncPoint(const p: pointer; Value: integer): pointer;
+{$ENDIF}
+
+{:Get string between PairBegin and PairEnd. This function respect nesting.
+ For example:
+ @longcode(#
+ Value is: 'Hi! (hello(yes!))'
+ pairbegin is: '('
+ pairend is: ')'
+ In this case result is: 'hello(yes!)'#)}
+function GetBetween(const PairBegin, PairEnd, Value: string): string;
+
+{:Return count of Chr in Value string.}
+function CountOfChar(const Value: string; Chr: char): integer;
+
+{:Remove quotation from Value string. If Value is not quoted, then return same
+ string without any modification. }
+function UnquoteStr(const Value: string; Quote: Char): string;
+
+{:Quote Value string. If Value contains some Quote chars, then it is doubled.}
+function QuoteStr(const Value: string; Quote: Char): string;
+
+{:Convert lines in stringlist from 'name: value' form to 'name=value' form.}
+procedure HeadersToList(const Value: TStrings);
+
+{:Convert lines in stringlist from 'name=value' form to 'name: value' form.}
+procedure ListToHeaders(const Value: TStrings);
+
+{:swap bytes in integer.}
+function SwapBytes(Value: integer): integer;
+
+{:read string with requested length form stream.}
+function ReadStrFromStream(const Stream: TStream; len: integer): AnsiString;
+
+{:write string to stream.}
+procedure WriteStrToStream(const Stream: TStream; Value: AnsiString);
+
+{:Return filename of new temporary file in Dir (if empty, then default temporary
+ directory is used) and with optional filename prefix.}
+function GetTempFile(const Dir, prefix: AnsiString): AnsiString;
+
+{:Return padded string. If length is greater, string is truncated. If length is
+ smaller, string is padded by Pad character.}
+function PadString(const Value: AnsiString; len: integer; Pad: AnsiChar): AnsiString;
+
+{:Read header from "Value" stringlist beginning at "Index" position. If header
+ is Splitted into multiple lines, then this procedure de-split it into one line.}
+function NormalizeHeader(Value: TStrings; var Index: Integer): string;
+
+var
+ {:can be used for your own months strings for @link(getmonthnumber)}
+ CustomMonthNames: array[1..12] of string;
+
+implementation
+
+{==============================================================================}
+
+const
+ MyDayNames: array[1..7] of AnsiString =
+ ('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat');
+var
+ MyMonthNames: array[0..6, 1..12] of AnsiString =
+ (
+ ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', //rewrited by system locales
+ 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'),
+ ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', //English
+ 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'),
+ ('jan', 'fév', 'mar', 'avr', 'mai', 'jun', //French
+ 'jul', 'aoû', 'sep', 'oct', 'nov', 'déc'),
+ ('jan', 'fev', 'mar', 'avr', 'mai', 'jun', //French#2
+ 'jul', 'aou', 'sep', 'oct', 'nov', 'dec'),
+ ('Jan', 'Feb', 'Mar', 'Apr', 'Mai', 'Jun', //German
+ 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez'),
+ ('Jan', 'Feb', 'Mär', 'Apr', 'Mai', 'Jun', //German#2
+ 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez'),
+ ('Led', 'Úno', 'Bøe', 'Dub', 'Kvì', 'Èen', //Czech
+ 'Èec', 'Srp', 'Záø', 'Øíj', 'Lis', 'Pro')
+ );
+
+
+{==============================================================================}
+
+function TimeZoneBias: integer;
+{$IFNDEF WIN32}
+{$IFNDEF FPC}
+var
+ t: TTime_T;
+ UT: TUnixTime;
+begin
+ __time(@T);
+ localtime_r(@T, UT);
+ Result := ut.__tm_gmtoff div 60;
+{$ELSE}
+begin
+ Result := TZSeconds div 60;
+{$ENDIF}
+{$ELSE}
+var
+ zoneinfo: TTimeZoneInformation;
+ bias: Integer;
+begin
+ case GetTimeZoneInformation(Zoneinfo) of
+ 2:
+ bias := zoneinfo.Bias + zoneinfo.DaylightBias;
+ 1:
+ bias := zoneinfo.Bias + zoneinfo.StandardBias;
+ else
+ bias := zoneinfo.Bias;
+ end;
+ Result := bias * (-1);
+{$ENDIF}
+end;
+
+{==============================================================================}
+
+function TimeZone: string;
+var
+ bias: Integer;
+ h, m: Integer;
+begin
+ bias := TimeZoneBias;
+ if bias >= 0 then
+ Result := '+'
+ else
+ Result := '-';
+ bias := Abs(bias);
+ h := bias div 60;
+ m := bias mod 60;
+ Result := Result + Format('%.2d%.2d', [h, m]);
+end;
+
+{==============================================================================}
+
+function Rfc822DateTime(t: TDateTime): string;
+var
+ wYear, wMonth, wDay: word;
+begin
+ DecodeDate(t, wYear, wMonth, wDay);
+ Result := Format('%s, %d %s %s %s', [MyDayNames[DayOfWeek(t)], wDay,
+ MyMonthNames[1, wMonth], FormatDateTime('yyyy hh":"nn":"ss', t), TimeZone]);
+end;
+
+{==============================================================================}
+
+function CDateTime(t: TDateTime): string;
+var
+ wYear, wMonth, wDay: word;
+begin
+ DecodeDate(t, wYear, wMonth, wDay);
+ Result:= Format('%s %2d %s', [MyMonthNames[1, wMonth], wDay,
+ FormatDateTime('hh":"nn":"ss', t)]);
+end;
+
+{==============================================================================}
+
+function SimpleDateTime(t: TDateTime): string;
+begin
+ Result := FormatDateTime('yymmdd hhnnss', t);
+end;
+
+{==============================================================================}
+
+function AnsiCDateTime(t: TDateTime): string;
+var
+ wYear, wMonth, wDay: word;
+begin
+ DecodeDate(t, wYear, wMonth, wDay);
+ Result := Format('%s %s %d %s', [MyDayNames[DayOfWeek(t)], MyMonthNames[1, wMonth],
+ wDay, FormatDateTime('hh":"nn":"ss yyyy ', t)]);
+end;
+
+{==============================================================================}
+
+function DecodeTimeZone(Value: string; var Zone: integer): Boolean;
+var
+ x: integer;
+ zh, zm: integer;
+ s: string;
+begin
+ Result := false;
+ s := Value;
+ if (Pos('+', s) = 1) or (Pos('-',s) = 1) then
+ begin
+ if s = '-0000' then
+ Zone := TimeZoneBias
+ else
+ if Length(s) > 4 then
+ begin
+ zh := StrToIntdef(s[2] + s[3], 0);
+ zm := StrToIntdef(s[4] + s[5], 0);
+ zone := zh * 60 + zm;
+ if s[1] = '-' then
+ zone := zone * (-1);
+ end;
+ Result := True;
+ end
+ else
+ begin
+ x := 32767;
+ if s = 'NZDT' then x := 13;
+ if s = 'IDLE' then x := 12;
+ if s = 'NZST' then x := 12;
+ if s = 'NZT' then x := 12;
+ if s = 'EADT' then x := 11;
+ if s = 'GST' then x := 10;
+ if s = 'JST' then x := 9;
+ if s = 'CCT' then x := 8;
+ if s = 'WADT' then x := 8;
+ if s = 'WAST' then x := 7;
+ if s = 'ZP6' then x := 6;
+ if s = 'ZP5' then x := 5;
+ if s = 'ZP4' then x := 4;
+ if s = 'BT' then x := 3;
+ if s = 'EET' then x := 2;
+ if s = 'MEST' then x := 2;
+ if s = 'MESZ' then x := 2;
+ if s = 'SST' then x := 2;
+ if s = 'FST' then x := 2;
+ if s = 'CEST' then x := 2;
+ if s = 'CET' then x := 1;
+ if s = 'FWT' then x := 1;
+ if s = 'MET' then x := 1;
+ if s = 'MEWT' then x := 1;
+ if s = 'SWT' then x := 1;
+ if s = 'UT' then x := 0;
+ if s = 'UTC' then x := 0;
+ if s = 'GMT' then x := 0;
+ if s = 'WET' then x := 0;
+ if s = 'WAT' then x := -1;
+ if s = 'BST' then x := -1;
+ if s = 'AT' then x := -2;
+ if s = 'ADT' then x := -3;
+ if s = 'AST' then x := -4;
+ if s = 'EDT' then x := -4;
+ if s = 'EST' then x := -5;
+ if s = 'CDT' then x := -5;
+ if s = 'CST' then x := -6;
+ if s = 'MDT' then x := -6;
+ if s = 'MST' then x := -7;
+ if s = 'PDT' then x := -7;
+ if s = 'PST' then x := -8;
+ if s = 'YDT' then x := -8;
+ if s = 'YST' then x := -9;
+ if s = 'HDT' then x := -9;
+ if s = 'AHST' then x := -10;
+ if s = 'CAT' then x := -10;
+ if s = 'HST' then x := -10;
+ if s = 'EAST' then x := -10;
+ if s = 'NT' then x := -11;
+ if s = 'IDLW' then x := -12;
+ if x <> 32767 then
+ begin
+ zone := x * 60;
+ Result := True;
+ end;
+ end;
+end;
+
+{==============================================================================}
+
+function GetMonthNumber(Value: AnsiString): integer;
+var
+ n: integer;
+ function TestMonth(Value: AnsiString; Index: Integer): Boolean;
+ var
+ n: integer;
+ begin
+ Result := False;
+ for n := 0 to 6 do
+ if Value = AnsiUppercase(MyMonthNames[n, Index]) then
+ begin
+ Result := True;
+ Break;
+ end;
+ end;
+begin
+ Result := 0;
+ Value := AnsiUppercase(Value);
+ for n := 1 to 12 do
+ if TestMonth(Value, n) or (Value = AnsiUppercase(CustomMonthNames[n])) then
+ begin
+ Result := n;
+ Break;
+ end;
+end;
+
+{==============================================================================}
+
+function GetTimeFromStr(Value: string): TDateTime;
+var
+ x: integer;
+begin
+ x := rpos(':', Value);
+ if (x > 0) and ((Length(Value) - x) > 2) then
+ Value := Copy(Value, 1, x + 2);
+ Value := ReplaceString(Value, ':', TimeSeparator);
+ Result := -1;
+ try
+ Result := StrToTime(Value);
+ except
+ on Exception do ;
+ end;
+end;
+
+{==============================================================================}
+
+function GetDateMDYFromStr(Value: string): TDateTime;
+var
+ wYear, wMonth, wDay: word;
+ s: string;
+begin
+ Result := 0;
+ s := Fetch(Value, '-');
+ wMonth := StrToIntDef(s, 12);
+ s := Fetch(Value, '-');
+ wDay := StrToIntDef(s, 30);
+ wYear := StrToIntDef(Value, 1899);
+ if wYear < 1000 then
+ if (wYear > 99) then
+ wYear := wYear + 1900
+ else
+ if wYear > 50 then
+ wYear := wYear + 1900
+ else
+ wYear := wYear + 2000;
+ try
+ Result := EncodeDate(wYear, wMonth, wDay);
+ except
+ on Exception do ;
+ end;
+end;
+
+{==============================================================================}
+
+function DecodeRfcDateTime(Value: string): TDateTime;
+var
+ day, month, year: Word;
+ zone: integer;
+ x, y: integer;
+ s: string;
+ t: TDateTime;
+begin
+// ddd, d mmm yyyy hh:mm:ss
+// ddd, d mmm yy hh:mm:ss
+// ddd, mmm d yyyy hh:mm:ss
+// ddd mmm dd hh:mm:ss yyyy
+// Sun, 06 Nov 1994 08:49:37 GMT ; RFC 822, updated by RFC 1123
+// Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036
+// Sun Nov 6 08:49:37 1994 ; ANSI C's asctime() Format
+
+ Result := 0;
+ if Value = '' then
+ Exit;
+ day := 0;
+ month := 0;
+ year := 0;
+ zone := 0;
+ Value := ReplaceString(Value, ' -', ' #');
+ Value := ReplaceString(Value, '-', ' ');
+ Value := ReplaceString(Value, ' #', ' -');
+ while Value <> '' do
+ begin
+ s := Fetch(Value, ' ');
+ s := uppercase(s);
+ // timezone
+ if DecodetimeZone(s, x) then
+ begin
+ zone := x;
+ continue;
+ end;
+ x := StrToIntDef(s, 0);
+ // day or year
+ if x > 0 then
+ if (x < 32) and (day = 0) then
+ begin
+ day := x;
+ continue;
+ end
+ else
+ begin
+ if (year = 0) and ((month > 0) or (x > 12)) then
+ begin
+ year := x;
+ if year < 32 then
+ year := year + 2000;
+ if year < 1000 then
+ year := year + 1900;
+ continue;
+ end;
+ end;
+ // time
+ if rpos(':', s) > Pos(':', s) then
+ begin
+ t := GetTimeFromStr(s);
+ if t <> -1 then
+ Result := t;
+ continue;
+ end;
+ //timezone daylight saving time
+ if s = 'DST' then
+ begin
+ zone := zone + 60;
+ continue;
+ end;
+ // month
+ y := GetMonthNumber(s);
+ if (y > 0) and (month = 0) then
+ month := y;
+ end;
+ if year = 0 then
+ year := 1980;
+ if month < 1 then
+ month := 1;
+ if month > 12 then
+ month := 12;
+ if day < 1 then
+ day := 1;
+ x := MonthDays[IsLeapYear(year), month];
+ if day > x then
+ day := x;
+ Result := Result + Encodedate(year, month, day);
+ zone := zone - TimeZoneBias;
+ x := zone div 1440;
+ Result := Result - x;
+ zone := zone mod 1440;
+ t := EncodeTime(Abs(zone) div 60, Abs(zone) mod 60, 0, 0);
+ if zone < 0 then
+ t := 0 - t;
+ Result := Result - t;
+end;
+
+{==============================================================================}
+
+function GetUTTime: TDateTime;
+{$IFDEF WIN32}
+{$IFNDEF FPC}
+var
+ st: TSystemTime;
+begin
+ GetSystemTime(st);
+ result := SystemTimeToDateTime(st);
+{$ELSE}
+var
+ st: SysUtils.TSystemTime;
+ stw: Windows.TSystemTime;
+begin
+ GetSystemTime(stw);
+ st.Year := stw.wYear;
+ st.Month := stw.wMonth;
+ st.Day := stw.wDay;
+ st.Hour := stw.wHour;
+ st.Minute := stw.wMinute;
+ st.Second := stw.wSecond;
+ st.Millisecond := stw.wMilliseconds;
+ result := SystemTimeToDateTime(st);
+{$ENDIF}
+{$ELSE}
+{$IFNDEF FPC}
+var
+ TV: TTimeVal;
+begin
+ gettimeofday(TV, nil);
+ Result := UnixDateDelta + (TV.tv_sec + TV.tv_usec / 1000000) / 86400;
+{$ELSE}
+var
+ TV: TimeVal;
+begin
+ fpgettimeofday(@TV, nil);
+ Result := UnixDateDelta + (TV.tv_sec + TV.tv_usec / 1000000) / 86400;
+{$ENDIF}
+{$ENDIF}
+end;
+
+{==============================================================================}
+
+function SetUTTime(Newdt: TDateTime): Boolean;
+{$IFDEF WIN32}
+{$IFNDEF FPC}
+var
+ st: TSystemTime;
+begin
+ DateTimeToSystemTime(newdt,st);
+ Result := SetSystemTime(st);
+{$ELSE}
+var
+ st: SysUtils.TSystemTime;
+ stw: Windows.TSystemTime;
+begin
+ DateTimeToSystemTime(newdt,st);
+ stw.wYear := st.Year;
+ stw.wMonth := st.Month;
+ stw.wDay := st.Day;
+ stw.wHour := st.Hour;
+ stw.wMinute := st.Minute;
+ stw.wSecond := st.Second;
+ stw.wMilliseconds := st.Millisecond;
+ Result := SetSystemTime(stw);
+{$ENDIF}
+{$ELSE}
+{$IFNDEF FPC}
+var
+ TV: TTimeVal;
+ d: double;
+ TZ: Ttimezone;
+ PZ: PTimeZone;
+begin
+ TZ.tz_minuteswest := 0;
+ TZ.tz_dsttime := 0;
+ PZ := @TZ;
+ gettimeofday(TV, PZ);
+ d := (newdt - UnixDateDelta) * 86400;
+ TV.tv_sec := trunc(d);
+ TV.tv_usec := trunc(frac(d) * 1000000);
+ Result := settimeofday(TV, TZ) <> -1;
+{$ELSE}
+var
+ TV: TimeVal;
+ d: double;
+begin
+ d := (newdt - UnixDateDelta) * 86400;
+ TV.tv_sec := trunc(d);
+ TV.tv_usec := trunc(frac(d) * 1000000);
+ Result := fpsettimeofday(@TV, nil) <> -1;
+{$ENDIF}
+{$ENDIF}
+end;
+
+{==============================================================================}
+
+{$IFNDEF WIN32}
+function GetTick: LongWord;
+var
+ Stamp: TTimeStamp;
+begin
+ Stamp := DateTimeToTimeStamp(Now);
+ Result := Stamp.Time;
+end;
+{$ELSE}
+function GetTick: LongWord;
+var
+ tick, freq: TLargeInteger;
+{$IFDEF VER100}
+ x: TLargeInteger;
+{$ENDIF}
+begin
+ if Windows.QueryPerformanceFrequency(freq) then
+ begin
+ Windows.QueryPerformanceCounter(tick);
+{$IFDEF VER100}
+ x.QuadPart := (tick.QuadPart / freq.QuadPart) * 1000;
+ Result := x.LowPart;
+{$ELSE}
+ Result := Trunc((tick / freq) * 1000) and High(LongWord)
+{$ENDIF}
+ end
+ else
+ Result := Windows.GetTickCount;
+end;
+{$ENDIF}
+
+{==============================================================================}
+
+function TickDelta(TickOld, TickNew: LongWord): LongWord;
+begin
+//if DWord is signed type (older Deplhi),
+// then it not work properly on differencies larger then maxint!
+ Result := 0;
+ if TickOld <> TickNew then
+ begin
+ if TickNew < TickOld then
+ begin
+ TickNew := TickNew + LongWord(MaxInt) + 1;
+ TickOld := TickOld + LongWord(MaxInt) + 1;
+ end;
+ Result := TickNew - TickOld;
+ if TickNew < TickOld then
+ if Result > 0 then
+ Result := 0 - Result;
+ end;
+end;
+
+{==============================================================================}
+
+function CodeInt(Value: Word): Ansistring;
+begin
+ setlength(result, 2);
+ result[1] := AnsiChar(Value div 256);
+ result[2] := AnsiChar(Value mod 256);
+// Result := AnsiChar(Value div 256) + AnsiChar(Value mod 256)
+end;
+
+{==============================================================================}
+
+function DecodeInt(const Value: Ansistring; Index: Integer): Word;
+var
+ x, y: Byte;
+begin
+ if Length(Value) > Index then
+ x := Ord(Value[Index])
+ else
+ x := 0;
+ if Length(Value) >= (Index + 1) then
+ y := Ord(Value[Index + 1])
+ else
+ y := 0;
+ Result := x * 256 + y;
+end;
+
+{==============================================================================}
+
+function CodeLongInt(Value: Longint): Ansistring;
+var
+ x, y: word;
+begin
+ // this is fix for negative numbers on systems where longint = integer
+ x := (Value shr 16) and integer($ffff);
+ y := Value and integer($ffff);
+ setlength(result, 4);
+ result[1] := AnsiChar(x div 256);
+ result[2] := AnsiChar(x mod 256);
+ result[3] := AnsiChar(y div 256);
+ result[4] := AnsiChar(y mod 256);
+end;
+
+{==============================================================================}
+
+function DecodeLongInt(const Value: Ansistring; Index: Integer): LongInt;
+var
+ x, y: Byte;
+ xl, yl: Byte;
+begin
+ if Length(Value) > Index then
+ x := Ord(Value[Index])
+ else
+ x := 0;
+ if Length(Value) >= (Index + 1) then
+ y := Ord(Value[Index + 1])
+ else
+ y := 0;
+ if Length(Value) >= (Index + 2) then
+ xl := Ord(Value[Index + 2])
+ else
+ xl := 0;
+ if Length(Value) >= (Index + 3) then
+ yl := Ord(Value[Index + 3])
+ else
+ yl := 0;
+ Result := ((x * 256 + y) * 65536) + (xl * 256 + yl);
+end;
+
+{==============================================================================}
+
+function DumpStr(const Buffer: Ansistring): string;
+var
+ n: Integer;
+begin
+ Result := '';
+ for n := 1 to Length(Buffer) do
+ Result := Result + ' +#$' + IntToHex(Ord(Buffer[n]), 2);
+end;
+
+{==============================================================================}
+
+function DumpExStr(const Buffer: Ansistring): string;
+var
+ n: Integer;
+ x: Byte;
+begin
+ Result := '';
+ for n := 1 to Length(Buffer) do
+ begin
+ x := Ord(Buffer[n]);
+ if x in [65..90, 97..122] then
+ Result := Result + ' +''' + char(x) + ''''
+ else
+ Result := Result + ' +#$' + IntToHex(Ord(Buffer[n]), 2);
+ end;
+end;
+
+{==============================================================================}
+
+procedure Dump(const Buffer: AnsiString; DumpFile: string);
+var
+ f: Text;
+begin
+ AssignFile(f, DumpFile);
+ if FileExists(DumpFile) then
+ DeleteFile(DumpFile);
+ Rewrite(f);
+ try
+ Writeln(f, DumpStr(Buffer));
+ finally
+ CloseFile(f);
+ end;
+end;
+
+{==============================================================================}
+
+procedure DumpEx(const Buffer: AnsiString; DumpFile: string);
+var
+ f: Text;
+begin
+ AssignFile(f, DumpFile);
+ if FileExists(DumpFile) then
+ DeleteFile(DumpFile);
+ Rewrite(f);
+ try
+ Writeln(f, DumpExStr(Buffer));
+ finally
+ CloseFile(f);
+ end;
+end;
+
+{==============================================================================}
+
+function TrimSPLeft(const S: string): string;
+var
+ I, L: Integer;
+begin
+ Result := '';
+ if S = '' then
+ Exit;
+ L := Length(S);
+ I := 1;
+ while (I <= L) and (S[I] = ' ') do
+ Inc(I);
+ Result := Copy(S, I, Maxint);
+end;
+
+{==============================================================================}
+
+function TrimSPRight(const S: string): string;
+var
+ I: Integer;
+begin
+ Result := '';
+ if S = '' then
+ Exit;
+ I := Length(S);
+ while (I > 0) and (S[I] = ' ') do
+ Dec(I);
+ Result := Copy(S, 1, I);
+end;
+
+{==============================================================================}
+
+function TrimSP(const S: string): string;
+begin
+ Result := TrimSPLeft(s);
+ Result := TrimSPRight(Result);
+end;
+
+{==============================================================================}
+
+function SeparateLeft(const Value, Delimiter: string): string;
+var
+ x: Integer;
+begin
+ x := Pos(Delimiter, Value);
+ if x < 1 then
+ Result := Value
+ else
+ Result := Copy(Value, 1, x - 1);
+end;
+
+{==============================================================================}
+
+function SeparateRight(const Value, Delimiter: string): string;
+var
+ x: Integer;
+begin
+ x := Pos(Delimiter, Value);
+ if x > 0 then
+ x := x + Length(Delimiter) - 1;
+ Result := Copy(Value, x + 1, Length(Value) - x);
+end;
+
+{==============================================================================}
+
+function GetParameter(const Value, Parameter: string): string;
+var
+ s: string;
+ v: string;
+begin
+ Result := '';
+ v := Value;
+ while v <> '' do
+ begin
+ s := Trim(FetchEx(v, ';', '"'));
+ if Pos(Uppercase(parameter), Uppercase(s)) = 1 then
+ begin
+ Delete(s, 1, Length(Parameter));
+ s := Trim(s);
+ if s = '' then
+ Break;
+ if s[1] = '=' then
+ begin
+ Result := Trim(SeparateRight(s, '='));
+ Result := UnquoteStr(Result, '"');
+ break;
+ end;
+ end;
+ end;
+end;
+
+{==============================================================================}
+
+procedure ParseParametersEx(Value, Delimiter: string; const Parameters: TStrings);
+var
+ s: string;
+begin
+ Parameters.Clear;
+ while Value <> '' do
+ begin
+ s := Trim(FetchEx(Value, Delimiter, '"'));
+ Parameters.Add(s);
+ end;
+end;
+
+{==============================================================================}
+
+procedure ParseParameters(Value: string; const Parameters: TStrings);
+begin
+ ParseParametersEx(Value, ';', Parameters);
+end;
+
+{==============================================================================}
+
+function IndexByBegin(Value: string; const List: TStrings): integer;
+var
+ n: integer;
+ s: string;
+begin
+ Result := -1;
+ Value := uppercase(Value);
+ for n := 0 to List.Count -1 do
+ begin
+ s := UpperCase(List[n]);
+ if Pos(Value, s) = 1 then
+ begin
+ Result := n;
+ Break;
+ end;
+ end;
+end;
+
+{==============================================================================}
+
+function GetEmailAddr(const Value: string): string;
+var
+ s: string;
+begin
+ s := SeparateRight(Value, '<');
+ s := SeparateLeft(s, '>');
+ Result := Trim(s);
+end;
+
+{==============================================================================}
+
+function GetEmailDesc(Value: string): string;
+var
+ s: string;
+begin
+ Value := Trim(Value);
+ s := SeparateRight(Value, '"');
+ if s <> Value then
+ s := SeparateLeft(s, '"')
+ else
+ begin
+ s := SeparateLeft(Value, '<');
+ if s = Value then
+ begin
+ s := SeparateRight(Value, '(');
+ if s <> Value then
+ s := SeparateLeft(s, ')')
+ else
+ s := '';
+ end;
+ end;
+ Result := Trim(s);
+end;
+
+{==============================================================================}
+
+function StrToHex(const Value: Ansistring): string;
+var
+ n: Integer;
+begin
+ Result := '';
+ for n := 1 to Length(Value) do
+ Result := Result + IntToHex(Byte(Value[n]), 2);
+ Result := LowerCase(Result);
+end;
+
+{==============================================================================}
+
+function IntToBin(Value: Integer; Digits: Byte): string;
+var
+ x, y, n: Integer;
+begin
+ Result := '';
+ x := Value;
+ repeat
+ y := x mod 2;
+ x := x div 2;
+ if y > 0 then
+ Result := '1' + Result
+ else
+ Result := '0' + Result;
+ until x = 0;
+ x := Length(Result);
+ for n := x to Digits - 1 do
+ Result := '0' + Result;
+end;
+
+{==============================================================================}
+
+function BinToInt(const Value: string): Integer;
+var
+ n: Integer;
+begin
+ Result := 0;
+ for n := 1 to Length(Value) do
+ begin
+ if Value[n] = '0' then
+ Result := Result * 2
+ else
+ if Value[n] = '1' then
+ Result := Result * 2 + 1
+ else
+ Break;
+ end;
+end;
+
+{==============================================================================}
+
+function ParseURL(URL: string; var Prot, User, Pass, Host, Port, Path,
+ Para: string): string;
+var
+ x, y: Integer;
+ sURL: string;
+ s: string;
+ s1, s2: string;
+begin
+ Prot := 'http';
+ User := '';
+ Pass := '';
+ Port := '80';
+ Para := '';
+
+ x := Pos('://', URL);
+ if x > 0 then
+ begin
+ Prot := SeparateLeft(URL, '://');
+ sURL := SeparateRight(URL, '://');
+ end
+ else
+ sURL := URL;
+ if UpperCase(Prot) = 'HTTPS' then
+ Port := '443';
+ if UpperCase(Prot) = 'FTP' then
+ Port := '21';
+ x := Pos('@', sURL);
+ y := Pos('/', sURL);
+ if (x > 0) and ((x < y) or (y < 1))then
+ begin
+ s := SeparateLeft(sURL, '@');
+ sURL := SeparateRight(sURL, '@');
+ x := Pos(':', s);
+ if x > 0 then
+ begin
+ User := SeparateLeft(s, ':');
+ Pass := SeparateRight(s, ':');
+ end
+ else
+ User := s;
+ end;
+ x := Pos('/', sURL);
+ if x > 0 then
+ begin
+ s1 := SeparateLeft(sURL, '/');
+ s2 := SeparateRight(sURL, '/');
+ end
+ else
+ begin
+ s1 := sURL;
+ s2 := '';
+ end;
+ if Pos('[', s1) = 1 then
+ begin
+ Host := Separateleft(s1, ']');
+ Delete(Host, 1, 1);
+ s1 := SeparateRight(s1, ']');
+ if Pos(':', s1) = 1 then
+ Port := SeparateRight(s1, ':');
+ end
+ else
+ begin
+ x := Pos(':', s1);
+ if x > 0 then
+ begin
+ Host := SeparateLeft(s1, ':');
+ Port := SeparateRight(s1, ':');
+ end
+ else
+ Host := s1;
+ end;
+ Result := '/' + s2;
+ x := Pos('?', s2);
+ if x > 0 then
+ begin
+ Path := '/' + SeparateLeft(s2, '?');
+ Para := SeparateRight(s2, '?');
+ end
+ else
+ Path := '/' + s2;
+ if Host = '' then
+ Host := 'localhost';
+end;
+
+{==============================================================================}
+
+function ReplaceString(Value, Search, Replace: AnsiString): AnsiString;
+var
+ x, l, ls, lr: Integer;
+begin
+ if (Value = '') or (Search = '') then
+ begin
+ Result := Value;
+ Exit;
+ end;
+ ls := Length(Search);
+ lr := Length(Replace);
+ Result := '';
+ x := Pos(Search, Value);
+ while x > 0 do
+ begin
+ {$IFNDEF CIL}
+ l := Length(Result);
+ SetLength(Result, l + x - 1);
+ Move(Pointer(Value)^, Pointer(@Result[l + 1])^, x - 1);
+ {$ELSE}
+ Result:=Result+Copy(Value,1,x-1);
+ {$ENDIF}
+ {$IFNDEF CIL}
+ l := Length(Result);
+ SetLength(Result, l + lr);
+ Move(Pointer(Replace)^, Pointer(@Result[l + 1])^, lr);
+ {$ELSE}
+ Result:=Result+Replace;
+ {$ENDIF}
+ Delete(Value, 1, x - 1 + ls);
+ x := Pos(Search, Value);
+ end;
+ Result := Result + Value;
+end;
+
+{==============================================================================}
+
+function RPosEx(const Sub, Value: string; From: integer): Integer;
+var
+ n: Integer;
+ l: Integer;
+begin
+ result := 0;
+ l := Length(Sub);
+ for n := From - l + 1 downto 1 do
+ begin
+ if Copy(Value, n, l) = Sub then
+ begin
+ result := n;
+ break;
+ end;
+ end;
+end;
+
+{==============================================================================}
+
+function RPos(const Sub, Value: String): Integer;
+begin
+ Result := RPosEx(Sub, Value, Length(Value));
+end;
+
+{==============================================================================}
+
+function FetchBin(var Value: string; const Delimiter: string): string;
+var
+ s: string;
+begin
+ Result := SeparateLeft(Value, Delimiter);
+ s := SeparateRight(Value, Delimiter);
+ if s = Value then
+ Value := ''
+ else
+ Value := s;
+end;
+
+{==============================================================================}
+
+function Fetch(var Value: string; const Delimiter: string): string;
+begin
+ Result := FetchBin(Value, Delimiter);
+ Result := TrimSP(Result);
+ Value := TrimSP(Value);
+end;
+
+{==============================================================================}
+
+function FetchEx(var Value: string; const Delimiter, Quotation: string): string;
+var
+ b: Boolean;
+begin
+ Result := '';
+ b := False;
+ while Length(Value) > 0 do
+ begin
+ if b then
+ begin
+ if Pos(Quotation, Value) = 1 then
+ b := False;
+ Result := Result + Value[1];
+ Delete(Value, 1, 1);
+ end
+ else
+ begin
+ if Pos(Delimiter, Value) = 1 then
+ begin
+ Delete(Value, 1, Length(delimiter));
+ break;
+ end;
+ b := Pos(Quotation, Value) = 1;
+ Result := Result + Value[1];
+ Delete(Value, 1, 1);
+ end;
+ end;
+end;
+
+{==============================================================================}
+
+function IsBinaryString(const Value: string): Boolean;
+var
+ n: integer;
+begin
+ Result := False;
+ for n := 1 to Length(Value) do
+ if Value[n] in [#0..#8, #10..#31] then
+ //ignore null-terminated strings
+ if not ((n = Length(value)) and (Value[n] = #0)) then
+ begin
+ Result := True;
+ Break;
+ end;
+end;
+
+{==============================================================================}
+
+function PosCRLF(const Value: AnsiString; var Terminator: AnsiString): integer;
+var
+ n, l: integer;
+begin
+ Result := -1;
+ Terminator := '';
+ l := length(value);
+ for n := 1 to l do
+ if value[n] in [#$0d, #$0a] then
+ begin
+ Result := n;
+ Terminator := Value[n];
+ if n <> l then
+ case value[n] of
+ #$0d:
+ if value[n + 1] = #$0a then
+ Terminator := #$0d + #$0a;
+ #$0a:
+ if value[n + 1] = #$0d then
+ Terminator := #$0a + #$0d;
+ end;
+ Break;
+ end;
+end;
+
+{==============================================================================}
+
+Procedure StringsTrim(const Value: TStrings);
+var
+ n: integer;
+begin
+ for n := Value.Count - 1 downto 0 do
+ if Value[n] = '' then
+ Value.Delete(n)
+ else
+ Break;
+end;
+
+{==============================================================================}
+
+function PosFrom(const SubStr, Value: String; From: integer): integer;
+var
+ ls,lv: integer;
+begin
+ Result := 0;
+ ls := Length(SubStr);
+ lv := Length(Value);
+ if (ls = 0) or (lv = 0) then
+ Exit;
+ if From < 1 then
+ From := 1;
+ while (ls + from - 1) <= (lv) do
+ begin
+ {$IFNDEF CIL}
+ if CompareMem(@SubStr[1],@Value[from],ls) then
+ {$ELSE}
+ if SubStr = copy(Value, from, ls) then
+ {$ENDIF}
+ begin
+ result := from;
+ break;
+ end
+ else
+ inc(from);
+ end;
+end;
+
+{==============================================================================}
+
+{$IFNDEF CIL}
+function IncPoint(const p: pointer; Value: integer): pointer;
+begin
+ Result := PAnsiChar(p) + Value;
+end;
+{$ENDIF}
+
+{==============================================================================}
+//improved by 'DoggyDawg'
+function GetBetween(const PairBegin, PairEnd, Value: string): string;
+var
+ n: integer;
+ x: integer;
+ s: string;
+ lenBegin: integer;
+ lenEnd: integer;
+ str: string;
+ max: integer;
+begin
+ lenBegin := Length(PairBegin);
+ lenEnd := Length(PairEnd);
+ n := Length(Value);
+ if (Value = PairBegin + PairEnd) then
+ begin
+ Result := '';//nothing between
+ exit;
+ end;
+ if (n < lenBegin + lenEnd) then
+ begin
+ Result := Value;
+ exit;
+ end;
+ s := SeparateRight(Value, PairBegin);
+ if (s = Value) then
+ begin
+ Result := Value;
+ exit;
+ end;
+ n := Pos(PairEnd, s);
+ if (n = 0) then
+ begin
+ Result := Value;
+ exit;
+ end;
+ Result := '';
+ x := 1;
+ max := Length(s) - lenEnd + 1;
+ for n := 1 to max do
+ begin
+ str := copy(s, n, lenEnd);
+ if (str = PairEnd) then
+ begin
+ Dec(x);
+ if (x <= 0) then
+ Break;
+ end;
+ str := copy(s, n, lenBegin);
+ if (str = PairBegin) then
+ Inc(x);
+ Result := Result + s[n];
+ end;
+end;
+
+{==============================================================================}
+
+function CountOfChar(const Value: string; Chr: char): integer;
+var
+ n: integer;
+begin
+ Result := 0;
+ for n := 1 to Length(Value) do
+ if Value[n] = chr then
+ Inc(Result);
+end;
+
+{==============================================================================}
+// ! do not use AnsiExtractQuotedStr, it's very buggy and can crash application!
+function UnquoteStr(const Value: string; Quote: Char): string;
+var
+ n: integer;
+ inq, dq: Boolean;
+ c, cn: char;
+begin
+ Result := '';
+ if Value = '' then
+ Exit;
+ if Value = Quote + Quote then
+ Exit;
+ inq := False;
+ dq := False;
+ for n := 1 to Length(Value) do
+ begin
+ c := Value[n];
+ if n <> Length(Value) then
+ cn := Value[n + 1]
+ else
+ cn := #0;
+ if c = quote then
+ if dq then
+ dq := False
+ else
+ if not inq then
+ inq := True
+ else
+ if cn = quote then
+ begin
+ Result := Result + Quote;
+ dq := True;
+ end
+ else
+ inq := False
+ else
+ Result := Result + c;
+ end;
+end;
+
+{==============================================================================}
+
+function QuoteStr(const Value: string; Quote: Char): string;
+var
+ n: integer;
+begin
+ Result := '';
+ for n := 1 to length(value) do
+ begin
+ Result := result + Value[n];
+ if value[n] = Quote then
+ Result := Result + Quote;
+ end;
+ Result := Quote + Result + Quote;
+end;
+
+{==============================================================================}
+
+procedure HeadersToList(const Value: TStrings);
+var
+ n, x, y: integer;
+ s: string;
+begin
+ for n := 0 to Value.Count -1 do
+ begin
+ s := Value[n];
+ x := Pos(':', s);
+ if x > 0 then
+ begin
+ y:= Pos('=',s);
+ if not ((y > 0) and (y < x)) then
+ begin
+ s[x] := '=';
+ Value[n] := s;
+ end;
+ end;
+ end;
+end;
+
+{==============================================================================}
+
+procedure ListToHeaders(const Value: TStrings);
+var
+ n, x: integer;
+ s: string;
+begin
+ for n := 0 to Value.Count -1 do
+ begin
+ s := Value[n];
+ x := Pos('=', s);
+ if x > 0 then
+ begin
+ s[x] := ':';
+ Value[n] := s;
+ end;
+ end;
+end;
+
+{==============================================================================}
+
+function SwapBytes(Value: integer): integer;
+var
+ s: AnsiString;
+ x, y, xl, yl: Byte;
+begin
+ s := CodeLongInt(Value);
+ x := Ord(s[4]);
+ y := Ord(s[3]);
+ xl := Ord(s[2]);
+ yl := Ord(s[1]);
+ Result := ((x * 256 + y) * 65536) + (xl * 256 + yl);
+end;
+
+{==============================================================================}
+
+function ReadStrFromStream(const Stream: TStream; len: integer): AnsiString;
+var
+ x: integer;
+{$IFDEF CIL}
+ buf: Array of Byte;
+{$ENDIF}
+begin
+{$IFDEF CIL}
+ Setlength(buf, Len);
+ x := Stream.read(buf, Len);
+ SetLength(buf, x);
+ Result := StringOf(Buf);
+{$ELSE}
+ Setlength(Result, Len);
+ x := Stream.read(PAnsiChar(Result)^, Len);
+ SetLength(Result, x);
+{$ENDIF}
+end;
+
+{==============================================================================}
+
+procedure WriteStrToStream(const Stream: TStream; Value: AnsiString);
+{$IFDEF CIL}
+var
+ buf: Array of Byte;
+{$ENDIF}
+begin
+{$IFDEF CIL}
+ buf := BytesOf(Value);
+ Stream.Write(buf,length(Value));
+{$ELSE}
+ Stream.Write(PAnsiChar(Value)^, Length(Value));
+{$ENDIF}
+end;
+
+{==============================================================================}
+function GetTempFile(const Dir, prefix: AnsiString): AnsiString;
+{$IFNDEF FPC}
+{$IFDEF WIN32}
+var
+ Path: AnsiString;
+ x: integer;
+{$ENDIF}
+{$ENDIF}
+begin
+{$IFDEF FPC}
+ Result := GetTempFileName(Dir, Prefix);
+{$ELSE}
+ {$IFNDEF WIN32}
+ Result := tempnam(Pointer(Dir), Pointer(prefix));
+ {$ELSE}
+ {$IFDEF CIL}
+ Result := System.IO.Path.GetTempFileName;
+ {$ELSE}
+ if Dir = '' then
+ begin
+ SetLength(Path, MAX_PATH);
+ x := GetTempPath(Length(Path), PChar(Path));
+ SetLength(Path, x);
+ end
+ else
+ Path := Dir;
+ x := Length(Path);
+ if Path[x] <> '\' then
+ Path := Path + '\';
+ SetLength(Result, MAX_PATH + 1);
+ GetTempFileName(PChar(Path), PChar(Prefix), 0, PChar(Result));
+ Result := PChar(Result);
+ SetFileattributes(PChar(Result), GetFileAttributes(PChar(Result)) or FILE_ATTRIBUTE_TEMPORARY);
+ {$ENDIF}
+ {$ENDIF}
+{$ENDIF}
+end;
+
+{==============================================================================}
+
+function PadString(const Value: AnsiString; len: integer; Pad: AnsiChar): AnsiString;
+begin
+ if length(value) >= len then
+ Result := Copy(value, 1, len)
+ else
+ Result := Value + StringOfChar(Pad, len - length(value));
+end;
+
+{==============================================================================}
+
+function NormalizeHeader(Value: TStrings; var Index: Integer): string;
+var
+ s, t: string;
+ n: Integer;
+begin
+ s := Value[Index];
+ Inc(Index);
+ if s <> '' then
+ while (Value.Count - 1) > Index do
+ begin
+ t := Value[Index];
+ if t = '' then
+ Break;
+ for n := 1 to Length(t) do
+ if t[n] = #9 then
+ t[n] := ' ';
+ if not(t[1] in [' ', '"', ':', '=']) then
+ Break
+ else
+ begin
+ s := s + ' ' + Trim(t);
+ Inc(Index);
+ end;
+ end;
+ Result := TrimRight(s);
+end;
+
+{==============================================================================}
+var
+ n: integer;
+begin
+ for n := 1 to 12 do
+ begin
+ CustomMonthNames[n] := ShortMonthNames[n];
+ MyMonthNames[0, n] := ShortMonthNames[n];
+ end;
+end.
diff --git a/branches/script-component/Units/Synapse/synsock.pas b/branches/script-component/Units/Synapse/synsock.pas
new file mode 100644
index 0000000..c4bc977
--- /dev/null
+++ b/branches/script-component/Units/Synapse/synsock.pas
@@ -0,0 +1,67 @@
+{==============================================================================|
+| Project : Ararat Synapse | 005.001.000 |
+|==============================================================================|
+| Content: Socket Independent Platform Layer |
+|==============================================================================|
+| Copyright (c)1999-2003, Lukas Gebauer |
+| All rights reserved. |
+| |
+| Redistribution and use in source and binary forms, with or without |
+| modification, are permitted provided that the following conditions are met: |
+| |
+| Redistributions of source code must retain the above copyright notice, this |
+| list of conditions and the following disclaimer. |
+| |
+| Redistributions in binary form must reproduce the above copyright notice, |
+| this list of conditions and the following disclaimer in the documentation |
+| and/or other materials provided with the distribution. |
+| |
+| Neither the name of Lukas Gebauer nor the names of its contributors may |
+| be used to endorse or promote products derived from this software without |
+| specific prior written permission. |
+| |
+| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
+| AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
+| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
+| ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR |
+| ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
+| DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
+| SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
+| CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
+| LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
+| OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
+| DAMAGE. |
+|==============================================================================|
+| The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).|
+| Portions created by Lukas Gebauer are Copyright (c)2001-2003. |
+| All Rights Reserved. |
+|==============================================================================|
+| Contributor(s): |
+|==============================================================================|
+| History: see HISTORY.HTM from distribution package |
+| (Found at URL: http://www.ararat.cz/synapse/) |
+|==============================================================================}
+
+{:@exclude}
+
+unit synsock;
+
+{$MINENUMSIZE 4}
+
+{$IFDEF CIL}
+ {$I ssdotnet.pas}
+{$ENDIF}
+
+{$IFDEF WIN32}
+ {$I sswin32.pas}
+{$ELSE}
+ {$IFDEF FPC}
+ {$I ssfpc.pas}
+ {$ELSE}
+ {$I sslinux.pas}
+ {$ENDIF}
+{$ENDIF}
+
+
+end.
+
diff --git a/branches/script-component/Units/Synapse/tlntsend.pas b/branches/script-component/Units/Synapse/tlntsend.pas
new file mode 100644
index 0000000..0fdb9e0
--- /dev/null
+++ b/branches/script-component/Units/Synapse/tlntsend.pas
@@ -0,0 +1,358 @@
+{==============================================================================|
+| Project : Ararat Synapse | 001.003.000 |
+|==============================================================================|
+| Content: TELNET and SSH2 client |
+|==============================================================================|
+| Copyright (c)1999-2008, Lukas Gebauer |
+| All rights reserved. |
+| |
+| Redistribution and use in source and binary forms, with or without |
+| modification, are permitted provided that the following conditions are met: |
+| |
+| Redistributions of source code must retain the above copyright notice, this |
+| list of conditions and the following disclaimer. |
+| |
+| Redistributions in binary form must reproduce the above copyright notice, |
+| this list of conditions and the following disclaimer in the documentation |
+| and/or other materials provided with the distribution. |
+| |
+| Neither the name of Lukas Gebauer nor the names of its contributors may |
+| be used to endorse or promote products derived from this software without |
+| specific prior written permission. |
+| |
+| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
+| AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
+| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
+| ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR |
+| ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
+| DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
+| SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
+| CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
+| LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
+| OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
+| DAMAGE. |
+|==============================================================================|
+| The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).|
+| Portions created by Lukas Gebauer are Copyright (c)2002-2008. |
+| All Rights Reserved. |
+|==============================================================================|
+| Contributor(s): |
+|==============================================================================|
+| History: see HISTORY.HTM from distribution package |
+| (Found at URL: http://www.ararat.cz/synapse/) |
+|==============================================================================}
+
+{:@abstract(Telnet script client)
+
+Used RFC: RFC-854
+}
+
+{$IFDEF FPC}
+ {$MODE DELPHI}
+{$ENDIF}
+{$H+}
+
+unit tlntsend;
+
+interface
+
+uses
+ SysUtils, Classes,
+ blcksock, synautil;
+
+const
+ cTelnetProtocol = '23';
+ cSSHProtocol = '22';
+
+ TLNT_EOR = #239;
+ TLNT_SE = #240;
+ TLNT_NOP = #241;
+ TLNT_DATA_MARK = #242;
+ TLNT_BREAK = #243;
+ TLNT_IP = #244;
+ TLNT_AO = #245;
+ TLNT_AYT = #246;
+ TLNT_EC = #247;
+ TLNT_EL = #248;
+ TLNT_GA = #249;
+ TLNT_SB = #250;
+ TLNT_WILL = #251;
+ TLNT_WONT = #252;
+ TLNT_DO = #253;
+ TLNT_DONT = #254;
+ TLNT_IAC = #255;
+
+type
+ {:@abstract(State of telnet protocol). Used internaly by TTelnetSend.}
+ TTelnetState =(tsDATA, tsIAC, tsIAC_SB, tsIAC_WILL, tsIAC_DO, tsIAC_WONT,
+ tsIAC_DONT, tsIAC_SBIAC, tsIAC_SBDATA, tsSBDATA_IAC);
+
+ {:@abstract(Class with implementation of Telnet/SSH script client.)
+
+ Note: Are you missing properties for specify server address and port? Look to
+ parent @link(TSynaClient) too!}
+ TTelnetSend = class(TSynaClient)
+ private
+ FSock: TTCPBlockSocket;
+ FBuffer: Ansistring;
+ FState: TTelnetState;
+ FSessionLog: Ansistring;
+ FSubNeg: Ansistring;
+ FSubType: Ansichar;
+ FTermType: Ansistring;
+ function Connect: Boolean;
+ function Negotiate(const Buf: Ansistring): Ansistring;
+ procedure FilterHook(Sender: TObject; var Value: AnsiString);
+ public
+ constructor Create;
+ destructor Destroy; override;
+
+ {:Connects to Telnet server.}
+ function Login: Boolean;
+
+ {:Connects to SSH2 server and login by Username and Password properties.
+
+ You must use some of SSL plugins with SSH support. For exammple CryptLib.}
+ function SSHLogin: Boolean;
+
+ {:Logout from telnet server.}
+ procedure Logout;
+
+ {:Send this data to telnet server.}
+ procedure Send(const Value: string);
+
+ {:Reading data from telnet server until Value is readed. If it is not readed
+ until timeout, result is @false. Otherwise result is @true.}
+ function WaitFor(const Value: string): Boolean;
+
+ {:Read data terminated by terminator from telnet server.}
+ function RecvTerminated(const Terminator: string): string;
+
+ {:Read string from telnet server.}
+ function RecvString: string;
+ published
+ {:Socket object used for TCP/IP operation. Good for seting OnStatus hook, etc.}
+ property Sock: TTCPBlockSocket read FSock;
+
+ {:all readed datas in this session (from connect) is stored in this large
+ string.}
+ property SessionLog: Ansistring read FSessionLog write FSessionLog;
+
+ {:Terminal type indentification. By default is 'SYNAPSE'.}
+ property TermType: Ansistring read FTermType write FTermType;
+ end;
+
+implementation
+
+constructor TTelnetSend.Create;
+begin
+ inherited Create;
+ FSock := TTCPBlockSocket.Create;
+ FSock.OnReadFilter := FilterHook;
+ FTimeout := 60000;
+ FTargetPort := cTelnetProtocol;
+ FSubNeg := '';
+ FSubType := #0;
+ FTermType := 'SYNAPSE';
+end;
+
+destructor TTelnetSend.Destroy;
+begin
+ FSock.Free;
+ inherited Destroy;
+end;
+
+function TTelnetSend.Connect: Boolean;
+begin
+ // Do not call this function! It is calling by LOGIN method!
+ FBuffer := '';
+ FSessionLog := '';
+ FState := tsDATA;
+ FSock.CloseSocket;
+ FSock.LineBuffer := '';
+ FSock.Bind(FIPInterface, cAnyPort);
+ FSock.Connect(FTargetHost, FTargetPort);
+ Result := FSock.LastError = 0;
+end;
+
+function TTelnetSend.RecvTerminated(const Terminator: string): string;
+begin
+ Result := FSock.RecvTerminated(FTimeout, Terminator);
+end;
+
+function TTelnetSend.RecvString: string;
+begin
+ Result := FSock.RecvTerminated(FTimeout, CRLF);
+end;
+
+function TTelnetSend.WaitFor(const Value: string): Boolean;
+begin
+ Result := FSock.RecvTerminated(FTimeout, Value) <> '';
+end;
+
+procedure TTelnetSend.FilterHook(Sender: TObject; var Value: AnsiString);
+begin
+ Value := Negotiate(Value);
+ FSessionLog := FSessionLog + Value;
+end;
+
+function TTelnetSend.Negotiate(const Buf: Ansistring): Ansistring;
+var
+ n: integer;
+ c: Ansichar;
+ Reply: Ansistring;
+ SubReply: Ansistring;
+begin
+ Result := '';
+ for n := 1 to Length(Buf) do
+ begin
+ c := Buf[n];
+ Reply := '';
+ case FState of
+ tsData:
+ if c = TLNT_IAC then
+ FState := tsIAC
+ else
+ Result := Result + c;
+
+ tsIAC:
+ case c of
+ TLNT_IAC:
+ begin
+ FState := tsData;
+ Result := Result + TLNT_IAC;
+ end;
+ TLNT_WILL:
+ FState := tsIAC_WILL;
+ TLNT_WONT:
+ FState := tsIAC_WONT;
+ TLNT_DONT:
+ FState := tsIAC_DONT;
+ TLNT_DO:
+ FState := tsIAC_DO;
+ TLNT_EOR:
+ FState := tsDATA;
+ TLNT_SB:
+ begin
+ FState := tsIAC_SB;
+ FSubType := #0;
+ FSubNeg := '';
+ end;
+ else
+ FState := tsData;
+ end;
+
+ tsIAC_WILL:
+ begin
+ case c of
+ #3: //suppress GA
+ Reply := TLNT_DO;
+ else
+ Reply := TLNT_DONT;
+ end;
+ FState := tsData;
+ end;
+
+ tsIAC_WONT:
+ begin
+ Reply := TLNT_DONT;
+ FState := tsData;
+ end;
+
+ tsIAC_DO:
+ begin
+ case c of
+ #24: //termtype
+ Reply := TLNT_WILL;
+ else
+ Reply := TLNT_WONT;
+ end;
+ FState := tsData;
+ end;
+
+ tsIAC_DONT:
+ begin
+ Reply := TLNT_WONT;
+ FState := tsData;
+ end;
+
+ tsIAC_SB:
+ begin
+ FSubType := c;
+ FState := tsIAC_SBDATA;
+ end;
+
+ tsIAC_SBDATA:
+ begin
+ if c = TLNT_IAC then
+ FState := tsSBDATA_IAC
+ else
+ FSubNeg := FSubNeg + c;
+ end;
+
+ tsSBDATA_IAC:
+ case c of
+ TLNT_IAC:
+ begin
+ FState := tsIAC_SBDATA;
+ FSubNeg := FSubNeg + c;
+ end;
+ TLNT_SE:
+ begin
+ SubReply := '';
+ case FSubType of
+ #24: //termtype
+ begin
+ if (FSubNeg <> '') and (FSubNeg[1] = #1) then
+ SubReply := #0 + FTermType;
+ end;
+ end;
+ Sock.SendString(TLNT_IAC + TLNT_SB + FSubType + SubReply + TLNT_IAC + TLNT_SE);
+ FState := tsDATA;
+ end;
+ else
+ FState := tsDATA;
+ end;
+
+ else
+ FState := tsData;
+ end;
+ if Reply <> '' then
+ Sock.SendString(TLNT_IAC + Reply + c);
+ end;
+
+end;
+
+procedure TTelnetSend.Send(const Value: string);
+begin
+ Sock.SendString(ReplaceString(Value, TLNT_IAC, TLNT_IAC + TLNT_IAC));
+end;
+
+function TTelnetSend.Login: Boolean;
+begin
+ Result := False;
+ if not Connect then
+ Exit;
+ Result := True;
+end;
+
+function TTelnetSend.SSHLogin: Boolean;
+begin
+ Result := False;
+ if Connect then
+ begin
+ FSock.SSL.SSLType := LT_SSHv2;
+ FSock.SSL.Username := FUsername;
+ FSock.SSL.Password := FPassword;
+ FSock.SSLDoConnect;
+ Result := FSock.LastError = 0;
+ end;
+end;
+
+procedure TTelnetSend.Logout;
+begin
+ FSock.CloseSocket;
+end;
+
+
+end.