1 " |
1 " |
2 COPYRIGHT (c) 1993 by Claus Gittinger |
2 COPYRIGHT (c) 1993 by Claus Gittinger |
3 All Rights Reserved |
3 All Rights Reserved |
4 |
4 |
5 This software is furnished under a license and may be used |
5 This software is furnished under a license and may be used |
6 only in accordance with the terms of that license and with the |
6 only in accordance with the terms of that license and with the |
7 inclusion of the above copyright notice. This software may not |
7 inclusion of the above copyright notice. This software may not |
8 be provided or otherwise made available to, or used by, any |
8 be provided or otherwise made available to, or used by, any |
9 other person. No title to or ownership of the software is |
9 other person. No title to or ownership of the software is |
10 hereby transferred. |
10 hereby transferred. |
11 " |
11 " |
12 |
12 |
13 Dictionary subclass:#ResourcePack |
13 Dictionary subclass:#ResourcePack |
14 instanceVariableNames:'elements dependents packsClassName' |
14 instanceVariableNames:'elements dependents packsClassName' |
15 classVariableNames:'Packs' |
15 classVariableNames:'Packs' |
16 poolDictionaries:'' |
16 poolDictionaries:'' |
17 category:'System-Support' |
17 category:'System-Support' |
18 ! |
18 ! |
19 |
19 |
20 ResourcePack comment:' |
20 ResourcePack comment:' |
21 COPYRIGHT (c) 1993 by Claus Gittinger |
21 COPYRIGHT (c) 1993 by Claus Gittinger |
22 All Rights Reserved |
22 All Rights Reserved |
23 |
23 |
24 $Header: /cvs/stx/stx/libview/ResourcePack.st,v 1.8 1994-08-05 01:14:58 claus Exp $ |
24 $Header: /cvs/stx/stx/libview/ResourcePack.st,v 1.9 1994-10-10 02:33:00 claus Exp $ |
25 '! |
25 '! |
26 |
26 |
27 !ResourcePack class methodsFor:'documentation'! |
27 !ResourcePack class methodsFor:'documentation'! |
28 |
28 |
29 copyright |
29 copyright |
30 " |
30 " |
31 COPYRIGHT (c) 1993 by Claus Gittinger |
31 COPYRIGHT (c) 1993 by Claus Gittinger |
32 All Rights Reserved |
32 All Rights Reserved |
33 |
33 |
34 This software is furnished under a license and may be used |
34 This software is furnished under a license and may be used |
35 only in accordance with the terms of that license and with the |
35 only in accordance with the terms of that license and with the |
36 inclusion of the above copyright notice. This software may not |
36 inclusion of the above copyright notice. This software may not |
37 be provided or otherwise made available to, or used by, any |
37 be provided or otherwise made available to, or used by, any |
57 The resourcePack consists of a mapping from strings to values, which are |
57 The resourcePack consists of a mapping from strings to values, which are |
58 then used in labels, buttons, menus etc. |
58 then used in labels, buttons, menus etc. |
59 The resourcePack initializes itself from a file found in 'resources/<className>.rs', |
59 The resourcePack initializes itself from a file found in 'resources/<className>.rs', |
60 where 'className' is built by the usual abbreviation mechanism (see abbrev-files). |
60 where 'className' is built by the usual abbreviation mechanism (see abbrev-files). |
61 Conditional mappings are possible, by including lines as: |
61 Conditional mappings are possible, by including lines as: |
62 #if <expression> |
62 #if <expression> |
63 #endif |
63 #endif |
64 in the resourcefile. Example: |
64 in the resourcefile. Example: |
65 file 'foo.rs': |
65 file 'foo.rs': |
66 #if Language == #german |
66 #if Language == #german |
67 'abort' 'Abbruch' |
67 'abort' 'Abbruch' |
68 #endif |
68 #endif |
69 #if Language == #french |
69 #if Language == #french |
70 'abort' 'canceller' |
70 'abort' 'canceller' |
71 #endif |
71 #endif |
72 the corresponding resource-strings are accessed using: |
72 the corresponding resource-strings are accessed using: |
73 resource string:'abort' |
73 resource string:'abort' |
74 returning the mapped string (i.e. 'Abbruch' if the global Language is set |
74 returning the mapped string (i.e. 'Abbruch' if the global Language is set |
75 to #german).. |
75 to #german).. |
76 If no corresponding entry is found in the resources, the key is returned. |
76 If no corresponding entry is found in the resources, the key is returned. |
77 Translations can also include arguments, such as: |
77 Translations can also include arguments, such as: |
78 resources string:'really delete %1' with:fileName |
78 resources string:'really delete %1' with:fileName |
79 " |
79 " |
80 ! ! |
80 ! ! |
81 |
81 |
82 !ResourcePack class methodsFor:'initialization'! |
82 !ResourcePack class methodsFor:'initialization'! |
83 |
83 |
84 initialize |
84 initialize |
85 Packs isNil ifTrue:[ |
85 Packs isNil ifTrue:[ |
86 Packs := WeakArray new:30 |
86 Packs := WeakArray new:30 |
87 ]. |
87 ]. |
88 |
88 |
89 "ResourcePack initialize" |
89 "ResourcePack initialize" |
90 ! |
90 ! |
91 |
91 |
92 flushResources |
92 flushCachedResourcePacks |
93 "forget all cached resources - needed after a style change" |
93 "forget all cached resources - needed after a style change" |
94 |
94 |
95 Packs := nil. |
95 Packs := nil. |
96 self initialize |
96 self initialize |
97 |
97 |
98 "ResourcePack flushResources" |
98 "ResourcePack flushCachedResourcePacks" |
99 ! ! |
99 ! ! |
100 |
100 |
101 !ResourcePack class methodsFor:'private'! |
101 !ResourcePack class methodsFor:'private'! |
102 |
102 |
103 addToCache:aPack |
103 addToCache:aPack |
104 |idx| |
104 |idx| |
105 |
105 |
106 idx := Packs identityIndexOf:nil. |
106 idx := Packs identityIndexOf:nil. |
107 idx == 0 ifTrue:[ |
107 idx == 0 ifTrue:[ |
108 " |
108 " |
109 throw away oldest |
109 throw away oldest |
110 " |
110 " |
111 idx := Packs size. |
111 idx := Packs size. |
112 Packs replaceFrom:1 to:idx-1 with:Packs startingAt:2. |
112 Packs replaceFrom:1 to:idx-1 with:Packs startingAt:2. |
113 ]. |
113 ]. |
114 Packs at:idx put:aPack |
114 Packs at:idx put:aPack |
115 ! |
115 ! |
116 |
116 |
117 searchCacheFor:aClassname |
117 searchCacheFor:aClassname |
118 |sz| |
118 |sz| |
119 |
119 |
120 Packs isNil ifTrue:[ |
120 Packs isNil ifTrue:[ |
121 self initialize. |
121 self initialize. |
122 ^ nil |
122 ^ nil |
123 ]. |
123 ]. |
124 |
124 |
125 sz := Packs size. |
125 sz := Packs size. |
126 1 to:sz do:[:idx | |
126 1 to:sz do:[:idx | |
127 |aPack| |
127 |aPack| |
128 |
128 |
129 aPack := Packs at:idx. |
129 aPack := Packs at:idx. |
130 aPack notNil ifTrue:[ |
130 aPack notNil ifTrue:[ |
131 aPack packsClassName = aClassname ifTrue:[ |
131 aClassname = aPack packsClassName ifTrue:[ |
132 " |
132 " |
133 bring to end for LRU |
133 bring to end for LRU |
134 " |
134 " |
135 Packs replaceFrom:idx to:sz-1 with:Packs startingAt:idx+1. |
135 Packs replaceFrom:idx to:sz-1 with:Packs startingAt:idx+1. |
136 Packs at:sz put:aPack. |
136 Packs at:sz put:aPack. |
137 ^ aPack |
137 ^ aPack |
138 ] |
138 ] |
139 ] |
139 ] |
140 ]. |
140 ]. |
141 ^ nil |
141 ^ nil |
142 ! ! |
142 ! ! |
143 |
143 |
144 !ResourcePack class methodsFor:'instance creation'! |
144 !ResourcePack class methodsFor:'instance creation'! |
145 |
145 |
146 fromFile:aFileName directory:dirName |
146 fromFile:aFileName directory:dirName |
147 "get the resource definitions from a file in a directory. |
147 "get the resource definitions from a file in a directory. |
148 Uncached low-level entry." |
148 Uncached low-level entry." |
149 |
149 |
150 |inStream newPack| |
150 |newPack| |
151 |
151 |
152 newPack := self new. |
152 newPack := self new. |
153 inStream := Smalltalk systemFileStreamFor:('resources/' , aFileName). |
153 newPack readFromFile:aFileName directory:dirName. |
154 inStream isNil ifTrue:[ |
|
155 " |
|
156 an empty pack |
|
157 " |
|
158 ^ newPack |
|
159 ]. |
|
160 newPack readFromResourceStream:inStream. |
|
161 inStream close. |
|
162 |
|
163 self addToCache:newPack. |
|
164 ^ newPack |
154 ^ newPack |
165 ! |
155 ! |
166 |
156 |
167 fromFile:aFileName |
157 fromFile:aFileName |
168 "get the resource definitions from a file in the default directory. |
158 "get the resource definitions from a file in the default directory. |
187 pack := self searchCacheFor:nm. |
177 pack := self searchCacheFor:nm. |
188 pack notNil ifTrue:[^ pack]. |
178 pack notNil ifTrue:[^ pack]. |
189 |
179 |
190 pack := self fromFile:(Smalltalk fileNameForClass:nm) , '.rs'. |
180 pack := self fromFile:(Smalltalk fileNameForClass:nm) , '.rs'. |
191 aClass == Object ifFalse:[ |
181 aClass == Object ifFalse:[ |
192 superPack := self for:(aClass superclass). |
182 superPack := self for:(aClass superclass). |
193 pack := pack merge:superPack |
183 pack := pack merge:superPack |
194 ]. |
184 ]. |
195 pack packsClassName:nm. |
185 pack packsClassName:nm. |
196 self addToCache:pack. |
186 self addToCache:pack. |
197 ^ pack |
187 ^ pack |
198 ! ! |
188 ! ! |
199 |
189 |
200 !ResourcePack methodsFor:'merging'! |
190 !ResourcePack methodsFor:'merging'! |
201 |
191 |
202 merge:anotherPack |
192 merge:anotherPack |
203 anotherPack keysAndValuesDo:[:key :value | |
193 anotherPack keysAndValuesDo:[:key :value | |
204 (self includesKey:key) ifFalse:[ |
194 (self includesKey:key) ifFalse:[ |
205 self at:key put:value |
195 self at:key put:value |
206 ] |
196 ] |
207 ] |
197 ] |
208 ! ! |
198 ! ! |
209 |
199 |
210 !ResourcePack methodsFor:'accessing'! |
200 !ResourcePack methodsFor:'accessing'! |
211 |
201 |
263 template := self at:s ifAbsent:[s]. |
253 template := self at:s ifAbsent:[s]. |
264 expandedString := ''. |
254 expandedString := ''. |
265 stop := template size. |
255 stop := template size. |
266 start := 1. |
256 start := 1. |
267 [start < stop] whileTrue:[ |
257 [start < stop] whileTrue:[ |
268 idx := template indexOf:$% startingAt:start. |
258 idx := template indexOf:$% startingAt:start. |
269 idx == 0 ifTrue:[ |
259 idx == 0 ifTrue:[ |
270 ^ expandedString , (template copyFrom:start to:stop) |
260 ^ expandedString , (template copyFrom:start to:stop) |
271 ]. |
261 ]. |
272 "found a %" |
262 "found a %" |
273 expandedString := expandedString , (template copyFrom:start to:(idx - 1)). |
263 expandedString := expandedString , (template copyFrom:start to:(idx - 1)). |
274 next := template at:(idx + 1). |
264 next := template at:(idx + 1). |
275 (next == $%) ifTrue:[ |
265 (next == $%) ifTrue:[ |
276 expandedString := expandedString , '%' |
266 expandedString := expandedString , '%' |
277 ] ifFalse:[ |
267 ] ifFalse:[ |
278 expandedString := expandedString , (argArray at:(next digitValue)) printString |
268 expandedString := expandedString , (argArray at:(next digitValue)) printString |
279 ]. |
269 ]. |
280 start := idx + 2 |
270 start := idx + 2 |
281 ]. |
271 ]. |
282 ^ expandedString |
272 ^ expandedString |
283 ! ! |
273 ! ! |
284 |
274 |
285 !ResourcePack methodsFor:'file reading'! |
275 !ResourcePack methodsFor:'file reading'! |
286 |
276 |
287 readFromResourceStream:inStream |
277 readFromFile:fileName directory:dirName |
288 |lineString rest value ifLevel skipping l name first| |
278 |inStream| |
|
279 |
|
280 inStream := Smalltalk systemFileStreamFor:(dirName , '/' , fileName). |
|
281 inStream isNil ifTrue:[ |
|
282 " |
|
283 an empty pack |
|
284 " |
|
285 ^ nil |
|
286 ]. |
|
287 self readFromResourceStream:inStream in:dirName. |
|
288 inStream close. |
|
289 ! |
|
290 |
|
291 readFromResourceStream:inStream in:dirName |
|
292 |lineString rest value ifLevel skipping l name first str macroName| |
289 |
293 |
290 ifLevel := 0. |
294 ifLevel := 0. |
291 skipping := false. |
295 skipping := false. |
292 [inStream atEnd] whileFalse:[ |
296 [inStream atEnd] whileFalse:[ |
293 lineString := inStream nextLine. |
297 lineString := inStream nextLine. |
294 (lineString notNil and:[lineString isEmpty not]) ifTrue:[ |
298 (lineString notNil and:[lineString isEmpty not]) ifTrue:[ |
295 first := lineString at:1. |
299 first := lineString at:1. |
296 first == $; ifFalse:[ |
300 first == $; ifFalse:[ |
297 first == $# ifTrue:[ |
301 first == $# ifTrue:[ |
298 (lineString startsWith:'#if') ifTrue:[ |
302 lineString := (lineString copyFrom:2) withoutSpaces. |
299 skipping ifFalse:[ |
303 |
300 rest := lineString copyFrom:4. |
304 (lineString startsWith:'if') ifTrue:[ |
301 value := Compiler evaluate:rest. |
305 skipping ifFalse:[ |
302 (value == #Error) ifTrue:[ |
306 rest := lineString copyFrom:3. |
303 Transcript show:('error in resource:' , lineString). |
307 value := Compiler evaluate:rest. |
304 ]. |
308 (value == #Error) ifTrue:[ |
305 (value == false) ifTrue:[ |
309 Transcript show:('error in resource:' , lineString). |
306 skipping := true |
310 ]. |
307 ] |
311 (value == false) ifTrue:[ |
308 ]. |
312 skipping := true |
309 ifLevel := ifLevel + 1 |
313 ] |
310 ] ifFalse:[ |
314 ]. |
311 (lineString startsWith:'#endif') ifTrue:[ |
315 ifLevel := ifLevel + 1 |
312 ifLevel := ifLevel - 1. |
316 ] ifFalse:[ |
313 ifLevel == 0 ifTrue:[ |
317 (lineString startsWith:'endif') ifTrue:[ |
314 skipping := false |
318 ifLevel := ifLevel - 1. |
315 ] |
319 ifLevel == 0 ifTrue:[ |
316 ]. |
320 skipping := false |
317 ]. |
321 ] |
318 ] ifFalse:[ |
322 ] ifFalse:[ |
319 skipping ifFalse:[ |
323 (lineString startsWith:'else') ifTrue:[ |
320 lineString := lineString withoutSeparators. |
324 skipping := skipping not |
321 name := nil. |
325 ] ifFalse:[ |
322 (lineString at:1) == $' ifTrue:[ |
326 (lineString startsWith:'include') ifTrue:[ |
323 l := lineString indexOf:$' startingAt:2. |
327 rest := lineString copyFrom:8. |
324 l ~~ 0 ifTrue:[ |
328 value := Compiler evaluate:rest. |
325 name := (lineString copyFrom:2 to:l-1). |
329 self readFromFile:value directory:dirName |
326 l := l + 1 |
330 ] |
327 ] |
331 ] |
328 ] ifFalse:[ |
332 ] |
329 l := lineString indexOfSeparatorStartingAt:1. |
333 ]. |
330 l ~~ 0 ifTrue:[ |
334 ] ifFalse:[ |
331 name := lineString copyFrom:1 to:l-1. |
335 skipping ifFalse:[ |
332 ] |
336 lineString := lineString withoutSeparators. |
333 ]. |
337 name := nil. |
334 name notNil ifTrue:[ |
338 (lineString at:1) == $' ifTrue:[ |
335 rest := lineString copyFrom:l. |
339 str := ReadStream on:lineString. |
336 value := Compiler evaluate:rest. |
340 name := String readFrom:str. |
337 (value == #Error) ifTrue:[ |
341 l := str position. |
338 Transcript show:('error in resource:' , name). |
342 |
339 ]. |
343 "/ l := lineString indexOf:$' startingAt:2. |
340 self at:name put:value. |
344 "/ l ~~ 0 ifTrue:[ |
341 ] |
345 "/ name := (lineString copyFrom:2 to:l-1). |
342 ] |
346 "/ l := l + 1 |
343 ] |
347 "/ ] |
344 ] |
348 ] ifFalse:[ |
345 ] |
349 l := lineString indexOfSeparatorStartingAt:1. |
|
350 l ~~ 0 ifTrue:[ |
|
351 name := lineString copyFrom:1 to:l-1. |
|
352 ] |
|
353 ]. |
|
354 name notNil ifTrue:[ |
|
355 rest := (lineString copyFrom:l) withoutSeparators. |
|
356 (rest startsWith:'=') ifTrue:[ |
|
357 rest := rest copyFrom:2. |
|
358 str := ReadStream on:rest. |
|
359 macroName := str nextWord. |
|
360 rest := str upToEnd. |
|
361 value := self at:macroName. |
|
362 value := Compiler evaluate:('self ' , rest) |
|
363 receiver:value |
|
364 notifying:nil. |
|
365 ] ifFalse:[ |
|
366 value := Compiler evaluate:rest. |
|
367 (value == #Error) ifTrue:[ |
|
368 Transcript show:('error in resource:' , name). |
|
369 ] |
|
370 ]. |
|
371 self at:name put:value. |
|
372 ] |
|
373 ] |
|
374 ] |
|
375 ] |
|
376 ] |
346 ]. |
377 ]. |
347 ! ! |
378 ! ! |
348 |
379 |
349 ResourcePack initialize! |
380 ResourcePack initialize! |