1 /******************************************************************************
2 *
3 * Copyright (C) 2004-2007, The Gentee Group. All rights reserved.
4 * This file is part of the Gentee open source project - http://www.gentee.com.
5 *
6 * THIS FILE IS PROVIDED UNDER THE TERMS OF THE GENTEE LICENSE ("AGREEMENT").
7 * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS FILE CONSTITUTES RECIPIENTS
8 * ACCEPTANCE OF THE AGREEMENT.
9 *
10 * ID: res 15.08.07 0.0.A.
11 *
12 * Author: Alexey Krivonogov ( gentee )
13 *
14 ******************************************************************************/
15
16 type reshead32 {
17 uint ressize
18 uint hdrsize
19 ushort restypeid
20 ushort restype
21 ushort resnameid
22 ushort resname
23 uint dversion
24 ushort memflag
25 ushort lang
26 uint version
27 uint characts
28 }
29
30 type res
31 {
32 buf data
33 uint iconid // Последний занятый номер для иконок
34 uint ismanifest // Есть или нет манифест
35 }
36
37 include : "ico.g"
38
39 define
40 {
41 // Memory/ flags
42 RCF_MOVEABLE = 0x0010
43 RCF_PURE = 0x0020
44 RCF_PRELOAD = 0x0040
45 RCF_DISCARDABLE = 0x1000
46
47 // Resource type IDs
48 RC_CURSOR = 1
49 RC_BITMAP = 2
50 RC_ICON = 3
51 RC_MENU = 4
52 RC_DIALOG = 5
53 RC_STRING = 6
54 RC_FONTDIR = 7
55 RC_FONT = 8
56 RC_ACCELERATOR = 9
57 RC_RCDATA = 10
58 RC_MESSAGETABLE = 11
59 RC_GROUP_CURSOR = 12
60 RC_GROUP_ICON = 14
61 RC_VERSION = 16
62 RC_DLGINCLUDE = 17
63 RC_PLUGPLAY = 19
64 RC_VXD = 20
65 RC_ANICURSOR = 21
66 RC_ANIICON = 22
67 RC_MANIFEST = 24
68 RC_DLGINIT = 240
69 RC_TOOLBAR = 241
70 RC_BITMAPNEW = 0x2002
71 RC_MENUNEW = 0x2004
72 RC_DIALOGNEW = 0x2005
73
74 CP_ACP = 0 // default to ANSI code page
75 CP_OEMCP = 1 // default to OEM code page
76 MB_PRECOMPOSED = 0x00000001 // use precomposed chars
77 }
78
79 method res res.init
80 {
81 // Добавляем пустой reshead32
82 this.data = '\h4 0 20 ffff ffff 0 0 0 0'
83 return this
84 }
85
86 method res.error( str msgtext )
87 {
88 print( "Resource error: \(msgtext)\nPress any key..." )
89 getch()
90 exit( 0 )
91 }
92
93 method res.addresource( uint typeres, str name, buf data )
94 {
95 buf uname
96 uint headsize
97
98 if name[0] > '9' // Указано имя ресурса
99 {
100 uname.expand( 128 )
101 // Переводим в Unicode
102 uname.use = MultiByteToWideChar( $CP_ACP, $MB_PRECOMPOSED,
103 name.ptr(), 0xFFFFFFFF, uname.ptr(), 64 ) * 2
104 uname.align()
105 }
106 this.data += *data
107 if *uname
108 {
109 this.data += sizeof( reshead32 ) + *uname - 4
110 }
111 else : this.data += sizeof( reshead32 )
112
113 this.data += ushort( 0xFFFF )
114 this.data += ushort( typeres )
115
116 if *uname
117 {
118 this.data += uname
119 }
120 else
121 {
122 this.data += ushort( 0xFFFF )
123 this.data += ushort( uint( name ))
124 }
125 this.data += '\h4 0 4090000 0 0'
126 this.data += data
127 this.data.align()
128 }
129
130 method uint res.addicon( str idname iconfile )
131 {
132 uint i
133 buf groupicon
134 arr icons of iconinfo
135
136 if !geticoninfo( iconfile, icons ) : return 0
137 groupicon += ushort( 0 )
138 groupicon += ushort( 1 )
139 groupicon += ushort( *icons )
140 fornum i, *icons
141 {
142 uint idir
143 idir as icons[i].icondir
144
145 this.addresource( $RC_ICON, str( ++this.iconid ), icons[i].data )
146 groupicon += byte( idir.bWidth )
147 groupicon += byte( idir.bHeight )
148 groupicon += byte( idir.bColorCount )
149 groupicon += byte( 0)
150 groupicon += ushort( idir.wPlanes )
151 groupicon += ushort( idir.wBitCount )
152 groupicon += idir.dwBytesInRes
153 groupicon += ushort( this.iconid )
154 }
155 this.addresource( $RC_GROUP_ICON, idname, groupicon )
156 return 1
157 }
158
159 method uint res.addmanifest( str name )
160 {
161 str manifest
162
163 manifest = "\[..]<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> <assemblyIdentity version="1.0.0.0" name="[..]\(name)\[..]" processorArchitecture="*" type="win32"/> <dependency> <dependentAssembly> <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" language="*" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" /> </dependentAssembly> </dependency>
164 <description>Description</description>
165 <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
166 <security>
167 <requestedPrivileges>
168 <requestedExecutionLevel
169 level="requireAdministrator"
170 uiAccess="false"/>
171 </requestedPrivileges>
172 </security>
173 </trustInfo>
174 </assembly>[..]"
175
176 manifest->buf.use--
177 this.addresource( $RC_MANIFEST, "1", manifest->buf )
178 this.ismanifest = 1
179 return 1
180 }
181
182 method uint res.addres( str filename )
183 {
184 buf newres
185 uint cur end reshead maxicon data
186
187 newres.read( filename )
188 if !*newres : return 0
189
190 end = newres.ptr() + *newres
191 cur = newres.ptr() + 0x20
192
193 while cur < end
194 {
195 reshead as cur->reshead32
196 if reshead.restypeid == 0xFFFF
197 {
198 switch reshead.restype
199 {
200 case $RC_ICON
201 {
202 if reshead.resnameid == 0xFFFF
203 {
204 reshead.resname += this.iconid
205 if maxicon < reshead.resname : maxicon = reshead.resname
206 }
207 }
208 case $RC_GROUP_ICON
209 {
210 uint count
211
212 data = cur + reshead.hdrsize + 4
213 count = data->ushort
214 data += 2
215 while count--
216 {
217 ( data + 12 )->ushort += this.iconid
218 data += 14
219 }
220 }
221 case $RC_MANIFEST
222 {
223 this.ismanifest = 1
224 }
225 }
226 }
227 // Переход на следующий элемент
228 cur += reshead.ressize + reshead.hdrsize
229 // Выравнивание
230 if cur & 0x3 : cur += 4 - ( cur & 0x3 )
231 }
232 this.data.append( newres.ptr() + 0x20, *newres - 0x20 )
233 this.data.align()
234 if maxicon : this.iconid = maxicon
235
236 return 1
237 }
238
239 method uint res.write( str filename )
240 {
241 return this.data.write( filename )
242 }
243
244 // Добавление иконок из проекта
245 method uint res.icons( arrstr icolist )
246 {
247 foreach curico, icolist
248 {
249 arrstr icons
250
251 curico.split( icons, ',', $SPLIT_FIRST | $SPLIT_NOSYS )
252 if *icons == 1
253 {
254 icons += icons[0]
255 icons[0] = "ICON_APP"
256 }
257 if !fileexist( icons[1] ) || !this.addicon( icons[0], icons[1] )
258 {
259 this.error( "Cannot load icon \(icons[1])" )
260 }
261 }
262 return 1
263 }
264
265 // Упаковка и добавление временных файлов
266 method res.temps( arrstr temps )
267 {
268 if !*temps : return
269 /* uint i
270 geae egea
271 geaeinit geai
272 geacomp gc
273 str tempdir geaname
274 buf btemp
275
276 if !>e : return
277 gettempdir( tempdir )
278
279 gte.getattrib( "filename", geaname )
280 if *geaname : goto readtemp
281
282 if !gte.listcount() : return
283
284 gc.compmethod = $GEA_LZGE
285 gc.order = 10
286 gc.solid = 0
287 geai.flags = $GEAI_IGNORECOPY
288 geai.userfunc = &gealogfunc
289
290 geaname = "\(tempdir)\\setup_temp.gea"
291 if !egea.create( geaname, geai )
292 {
293 optierr("Cannot create \(geaname)")
294 }
295 optilog->func( $OPTIE_COMPILE,
296 %{"Adding temporary files to EXE"})
297
298 fornum i, gte.listcount()
299 {
300 str val
301 arr temps of str
302
303 gte.list( i, val )
304 val.split( temps, ',', $SPLIT_FIRST | $SPLIT_NOSYS )
305 if *temps != 2 : continue
306 gc.idgroup = uint( temps[0] )
307 if !fileexist( temps[1] ) || !egea.add( temps[1], gc )
308 {
309 optierr("Cannot pack \(temps[1])")
310 }
311 }
312 egea.close()
313 label readtemp
314 btemp.read( geaname )
315 exeres.addresource( $RC_RCDATA, "SETUP_TEMP", btemp )*/
316 }
317
318 // Добавление файлов ресурсов
319 method res.resfiles( arrstr reslist )
320 {
321 foreach curres, reslist
322 {
323 if !fileexist( curres ) || !this.addres( curres )
324 {
325 this.error( "Cannot add the file \( curres )" )
326 }
327 }
328 }
Edit