Check-in [383eee6465]
Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Added some example files and some code has been fixed.
Timelines: family | ancestors | descendants | both | HelpServer
Files: files | file ages | folders
SHA1:383eee646550c65cdf7d94228333309c080720b4
User & Date: johnfound 2014-03-18 13:01:07
Context
2015-12-02
12:27
Some documentation changes. The precompiled files has been removed from the repository. Leaf check-in: be09eb6de2 user: johnfound tags: HelpServer
2014-03-18
13:01
Added some example files and some code has been fixed. check-in: 383eee6465 user: johnfound tags: HelpServer
08:09
Missed files added. check-in: 09f7282ce8 user: johnfound tags: HelpServer
Changes

Changes to phWeb/html_header.inc.

3
4
5
6
7
8
9






  <head>
    <link rel="stylesheet" href="help.css" type="text/css" />
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <meta http-equiv="Content-Style-Type" content="text/css" />
    <title>Fresh IDE html help</title>
  </head>
  <body>













>
>
>
>
>
>
3
4
5
6
7
8
9
10
11
12
13
14
15
  <head>
    <link rel="stylesheet" href="help.css" type="text/css" />
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <meta http-equiv="Content-Style-Type" content="text/css" />
    <title>Fresh IDE html help</title>
  </head>
  <body>
    <div class="main_menu">
      <a href="index.md">Table of contents</a>
      <a href="http://board.flatassembler.net">Ask a question</a>
    </div>

    <div class="content">

Changes to phWeb/phWeb.

cannot compute difference between binary files

Changes to phWeb/phWeb.exe.

cannot compute difference between binary files

Changes to phWeb/phWeb.fpr.

cannot compute difference between binary files

Changes to phWeb/requests.asm.

74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
...
118
119
120
121
122
123
124
125
126
127
128


129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
...
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196

; Process user requests
; arguments:
;   hSocket - the socket handler of the accepted connection.
;   pHeaders - array with strings containing all received headers, including the request line.
proc ProcessRequest, .hSocket, .pHeaders, .pPostData
  .method    dd ?
  .hCommand  dd ?
  .query     dd ?
  .protocol  dd ?
begin
        pushad

        mov     [.method],   0
        mov     [.hCommand], 0
        mov     [.query],    0
        mov     [.protocol], 0


; Debug code
if defined options.DebugMode & ~options.DebugMode = 0
        mov     esi, [.pHeaders]
        mov     ecx, [esi+TArray.count]
.loop:
................................................................................
        cmp     ecx, 4
        jb      .bad_request    ; 400, bad request

        mov     eax, [edi]
        lea     edi, [edi+4]
        sub     ecx, 4

        mov     [.method], eax

        mov     al, ' '
        repe scasb



        cmp     byte [edi], '/'
        jne     @f
        inc     edi
        dec     ecx
@@:
        mov     esi, edi
        repnz scasb

        mov     edx, edi
        sub     edx, esi
        dec     edx

        test    edx, edx
        jnz     .copy_cmd

        stdcall StrNew
        stdcall StrCharCat, eax, 'index.html'
        jmp     .cmd_ok

.copy_cmd:
        stdcall StrExtract, esi, 0, edx

.cmd_ok:
        mov     [.hCommand], eax

        jecxz   .protocol_ok

        stdcall StrExtract, edi, 0, ecx
        mov     [.protocol], eax

.protocol_ok:
................................................................................
; 200, OK + HEAD
.head_method:
        stdcall SendResponse, headerHTTP200
        jmp     .finish


.request_ok:
        stdcall ExecuteCommand, [.hSocket], [.hCommand], [.pPostData]

.finish:
        stdcall StrDel, [.hCommand]
        stdcall StrDel, [.query]
        stdcall StrDel, [.protocol]
        popad
        return
endp









|





|
|
|
|







 







|



>
>






|







|


|
|

|


|
|







 







|


|







74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
...
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
...
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198

; Process user requests
; arguments:
;   hSocket - the socket handler of the accepted connection.
;   pHeaders - array with strings containing all received headers, including the request line.
proc ProcessRequest, .hSocket, .pHeaders, .pPostData
  .method    dd ?
  .hFileName dd ?
  .query     dd ?
  .protocol  dd ?
begin
        pushad

        mov     [.method],    0
        mov     [.hFileName], 0
        mov     [.query],     0
        mov     [.protocol],  0


; Debug code
if defined options.DebugMode & ~options.DebugMode = 0
        mov     esi, [.pHeaders]
        mov     ecx, [esi+TArray.count]
.loop:
................................................................................
        cmp     ecx, 4
        jb      .bad_request    ; 400, bad request

        mov     eax, [edi]
        lea     edi, [edi+4]
        sub     ecx, 4

        mov     [.method], eax   ; the requests are limit to 4 bytes.

        mov     al, ' '
        repe scasb

        dec     edi

        cmp     byte [edi], '/'
        jne     @f
        inc     edi
        dec     ecx
@@:
        mov     esi, edi  ; scan to the first space (notice, that the path should not contain any spaces.
        repnz scasb

        mov     edx, edi
        sub     edx, esi
        dec     edx

        test    edx, edx
        jnz     .copy_fn

        stdcall StrNew
        stdcall StrCat, eax, 'index.md'
        jmp     .filename_ok

.copy_fn:
        stdcall StrExtract, esi, 0, edx

.filename_ok:
        mov     [.hFileName], eax

        jecxz   .protocol_ok

        stdcall StrExtract, edi, 0, ecx
        mov     [.protocol], eax

.protocol_ok:
................................................................................
; 200, OK + HEAD
.head_method:
        stdcall SendResponse, headerHTTP200
        jmp     .finish


.request_ok:
        stdcall ExecuteCommand, [.hSocket], [.hFileName], [.pPostData]

.finish:
        stdcall StrDel, [.hFileName]
        stdcall StrDel, [.query]
        stdcall StrDel, [.protocol]
        popad
        return
endp


Changes to phWeb/static.asm.

1
2
3



4
5
6
7
8
9
10
..
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
...
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
...
211
212
213
214
215
216
217

218
219
220
221
222
223
224
225
iglobal
  cMarkdownHeader file 'html_header.inc'
                  dd   0



endg



proc ExecuteCommand, .hSocket, .hFileName, .ptrPostData

  .md_result TMarkdownResults
................................................................................
        stdcall StrURLDecode, eax
        stdcall StrCat, ebx, eax
        stdcall StrDel, eax


; here, determine the type...

;        int3
;
;        stdcall NormalizeFilename, ebx
;        jc      .error404



        stdcall StrExtractExt, ebx
        jc      .error403
        push    eax

        xor     edx, edx

................................................................................
        je      .free

        lea     eax, [.md_result]
        stdcall TranslateMarkdown, edx, 0, FALSE, eax

        stdcall SocketSendStr, [.hSocket], cMarkdownHeader
        stdcall SocketSendStr, [.hSocket], [.md_result.hContent]
        stdcall SocketSendStr, [.hSocket], '</body></html>'

        stdcall StrDel, [.md_result.hContent]
        stdcall StrDel, [.md_result.hIndex]
        stdcall StrDel, [.md_result.hKeywords]
        stdcall StrDel, [.md_result.hDescription]
        jmp     .free

................................................................................

        stdcall StrFixLen, [.hString]
        shr     edx, 1
        pop     edi esi edx eax
        return

.dir:

        lea     edi, [esi+1]
        jmp     .loop1

.back:
        cmp     edi, esi
        lea     esi, [esi+3]
        je      .error          ; the path can not be normalized.




>
>
>







 







<
<
|
|
<
<







 







|







 







>
|







1
2
3
4
5
6
7
8
9
10
11
12
13
..
23
24
25
26
27
28
29


30
31


32
33
34
35
36
37
38
...
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
...
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
iglobal
  cMarkdownHeader file 'html_header.inc'
                  dd   0

  cMarkdownFooter file 'html_footer.inc'
                  dd   0
endg



proc ExecuteCommand, .hSocket, .hFileName, .ptrPostData

  .md_result TMarkdownResults
................................................................................
        stdcall StrURLDecode, eax
        stdcall StrCat, ebx, eax
        stdcall StrDel, eax


; here, determine the type...



        stdcall NormalizeFilename, ebx
        jc      .error404



        stdcall StrExtractExt, ebx
        jc      .error403
        push    eax

        xor     edx, edx

................................................................................
        je      .free

        lea     eax, [.md_result]
        stdcall TranslateMarkdown, edx, 0, FALSE, eax

        stdcall SocketSendStr, [.hSocket], cMarkdownHeader
        stdcall SocketSendStr, [.hSocket], [.md_result.hContent]
        stdcall SocketSendStr, [.hSocket], cMarkdownFooter

        stdcall StrDel, [.md_result.hContent]
        stdcall StrDel, [.md_result.hIndex]
        stdcall StrDel, [.md_result.hKeywords]
        stdcall StrDel, [.md_result.hDescription]
        jmp     .free

................................................................................

        stdcall StrFixLen, [.hString]
        shr     edx, 1
        pop     edi esi edx eax
        return

.dir:
        inc     esi
        mov     edi, esi
        jmp     .loop1

.back:
        cmp     edi, esi
        lea     esi, [esi+3]
        je      .error          ; the path can not be normalized.

Added phWeb/www/FreshLibUserGuide.md.











































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
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
91
92
93
94
95
96
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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
FreshLib user guide
# Chapter 7 FreshLib user guide

-----------------------------------

## Work with dynamic memory.

### Use with heap manager

FreshLib provides uniform and OS independent way to work with dynamic memory blocks.
The API is simple - there are only 3 procedures:

`proc GetMem, .size` - allocates new block with size at least `[.size]` and returns a pointer to this
block in EAX. In case of error the procedure returns EAX=0 and CF=1.

`proc FreeMem, .ptr` - frees already allocated by GetMem block of memory.

`proc ResizeMem, .ptr, .newsize` - changes the size of some memory block, allocated by GetMem.

The implementation of these procedures differs on the different OSes. In Win32, these procedures are
implemented using Win32 heap functions. In Linux, using libc functions.

There is an another approach to the memory management - FreshLib has its own implementation of a heap manager, 
that is OS independent and can be used in multiply operating systems. 
What heap management code will be used is defined through the `HeapManager` preprocessor symbol to "ASM".

If `HeapManager` is set to `OS`, the OS specific memory management will be used.

If `HeapManager` is set to `ASM` the FreshLib heap manager will be compiled.

The FreshLib heap manager must always be used for OSes that has no their own method of heap management.
For example KolibriOS port of the library uses this heap manager by default.

The heap manager procedures in FreshLib are thread safe.


### Use without heap manager

The heap management is not mandatory and can be disabled at all. In this case the application will be
able to allocate the whole needed memory as one big chunk.

There is only one procedure about this approach:

`proc SpaceAllocate, .size` - allocates memory with the specified size. In this case, the start 
address of the allocated memory is placed in the global variable `_MemoryFreeSpace` and will not be
changed during the program execution. Only the size of the available block of RAM can be changed by
the above procedure.

Unfortunately, big amount of FreshLib functionality depends on the heap managemer. This way, if you are using
this memory management approach, this functionality can not be used in the user program.

That is why, generally, this approach is not recommended for wide use. Although, there are some
situations (for example simple program, that needs big, contiguous block of memory) where such simple
approach can give you big performance gain without the mentioned disadvantages.



-----------------------------------

## Work with dynamic strings

The strings in FreshLib are dynamic - their length is changed in order to hold the whole information user
put into the string.

Because of this, the strings are represented not by their address, but by handle. However, most of the
procedures in the library can operate with memory pointers as well. 

The strings in FreshLib are always UTF-8 encoded.

### Internal string format

The library distinguish the handles from the pointers, because of the two most significant bits 
(30th and 31st) of the handle are always set to 1. (this approach can rarely create some problem 
with systems where such high addresses are used, but usually it is OK).

In order to create new string, the user should use the procedures `StrNew` or `StrDup`. The first
creates new empty string. The second, creates new string with content copied from some existing 
string.

Some of the strings processing procedures also can create new string and return it as a result value.



### Short list of the string manipulating procedures

 *Here is a table with most used string functions with short description:*

;table

 *Procedure*

 *Arguments*

 *Operation*

 *Notes*

;-------------------------------------------------------------------------------------------------
`StrNew`

.....

Creates new string

.....

;-------------------------------------------------------------------------------------------------

`StrDup`

.hString

Creates new string from existing one.

.....

;--------------------------------------------------------------------------------------------------

`StrPtr`

.hString

Returns a pointer to the current string memory.

.....

;--------------------------------------------------------------------------------------------------

`StrDel`

.hString

Deletes some string.

Preserves all registers and flags.
;--------------------------------------------------------------------------------------------------

`StrLen` 

.hString

Returns the length of the string in bytes. This procedure is very fast for direct pointers 
and instant for FreshLib strings.

.....

;--------------------------------------------------------------------------------------------------

`StrCopy`

.dest, .source

Copies the content of the `[.source]` string to the `[.dest]` string.

.....

;--------------------------------------------------------------------------------------------------

`StrCat`

.dest, .source

Concatenate the content of `[.source]` at the end of `[.dest]` string.

.....

;--------------------------------------------------------------------------------------------------

`StrCopyPart`

.dest, .source, .pos, .len

Copies a part of `[.source]` string - from byte `[.pos]` with length `[.len]` to the `[.dest]` string.

.....

;--------------------------------------------------------------------------------------------------

`StrExtract` 

.string, .pos, .len

Extracts a part of the string `[.string]` (from byte `[.pos]` and with length `[.len]`) and returns it as
a new created string.

.....

;--------------------------------------------------------------------------------------------------

`StrSplit`

.hString, .pos

Splits the string by two parts. The left part remains in `[.hString]` and the right part remains in new
created string, returned by the procedure.

.....

;--------------------------------------------------------------------------------------------------

`StrTrim`

.hString, .pos

Trims the string at position `[.pos]` The remaining of the string is lost.

.....

;--------------------------------------------------------------------------------------------------

`StrInsert`

.dest, .source, .pos

Inserts the string `[.source]` in the string `[.dest]` at byte `[.pos]`.

.....

;--------------------------------------------------------------------------------------------------

`NumToStr` 

.num, .flags

Converts the 32bit number `[.num]` into a new string, depending on the flags `[.flags]`.

Flags: ((ntsSigned | ntsUnsigned)+(ntsFixedWidth)) + (ntsBin | ntsQuad | ntsOct | ntsDec | ntsHex)

;--------------------------------------------------------------------------------------------------

`StrToNumEx`

.hString

Converts a string containing FASM formated number into a number.

.....

;--------------------------------------------------------------------------------------------------

`StrCharCat`

.hString, .char

Concatenates to the string `[.hString]` up to 4 bytes of ascii (UTF-8) characters from `[.char]`.

.....

;--------------------------------------------------------------------------------------------------

`StrCharInsert`

.hString, .char, .pos

Inserts up to 4 characters from `[.char]` into the string `[.hString]` at the position `[.pos]`.

.....

;--------------------------------------------------------------------------------------------------

`StrClipSpacesR`

.hString

Removes all trailing spaces from the string `[.hString]`.

.....

;--------------------------------------------------------------------------------------------------

`StrClipSpacesL`

.hString

Removes all leading spaces from the string `[.hString]`.

.....

;--------------------------------------------------------------------------------------------------

`StrCleanDupSpaces`

.hString

Removes all duplicated spaces from `[.hString]` and leaves only one space on this place.

.....

;--------------------------------------------------------------------------------------------------

`StrHash`

.hString

Computes and returns FNV-1b hash of the string `[.hString]`.

.....

;--------------------------------------------------------------------------------------------------

`DataHash`

.ptrData, .len

Computes the FNV-1b hash of the memory area from `[.ptrData]` with length `[.len]`.

.....

;--------------------------------------------------------------------------------------------------

`StrURLEncode`

.hString

Encodes the string in `[.hString]` in URL encoding.

.....

;--------------------------------------------------------------------------------------------------

`StrURLDecode`

.hString

Decodes URL encoded string in place.

.....

;--------------------------------------------------------------------------------------------------

`StrLenUtf8`

.hString

Computes the length in chars of the UTF-8 encoded string in `[.hString]` This operation is relatively slow
because the string must be scanned byte by byte.

.....

;--------------------------------------------------------------------------------------------------

`StrOffsUtf8`

.hString, .pos

Returns the byte offset of the character position `[.pos]` in the UTF-8 encoded string `[.hString]`.

.....

;--------------------------------------------------------------------------------------------------

`StrExpandTabs`

.hString, .tabstop

Converts all tabs in the string `[.hString]` into a spaces using `[.tabstop]` as a tab distance.

.....

;--------------------------------------------------------------------------------------------------

`StrIP2Num` 

.hString

Converts the string representation of IP address into a 32bit number.

.....

;--------------------------------------------------------------------------------------------------

`IP2Str`

.ip

Converts numeric representation of an IP number `[.ip]` into a string.

.....

;--------------------------------------------------------------------------------------------------

`StrEncodeHTML`

.hString

Encodes the string `[.hString]` in HTML encoding.

.....

;--------------------------------------------------------------------------------------------------

`StrDecodeHTML`

.hString

Decodes the HTML encoded string `[.hString]`.

.....

;--------------------------------------------------------------------------------------------------

`DateTimeToStr`

.pDateTime, .format

Converts TDateTime structure into a string, depending on `[.format]` flags.

.....

;--------------------------------------------------------------------------------------------------

`StrMD5`

.hString

Computes MD5 sum of the string `[.hString]`.

.....

;--------------------------------------------------------------------------------------------------

`StrSplitList`

.hString, .Separator, .fAutoEmpty

Creates dynamic array of dword, filled with the parts of the string `[.hString]`, splitted on the character 
`[.Separator]`. The returned array must be freed after use with: `stdcall  ListFree, [RetPtr], StrDel`.

.....

;--------------------------------------------------------------------------------------------------

`AnsiToUtf8`

.SrcEncoding, .hString

Converts an ANSI, `[.SrcEncoding]` encoded string into UTF-8 encoding.

WIN1251, CP866, KOI8R and KOI8U are currently supported, but FreshLib has tool that creates encoding
tables from UNICODE mapping tables from [http://www.unicode.org/Public/MAPPINGS/]

;--------------------------------------------------------------------------------------------------

`Utf8ToAnsi`

.hString, .DstEncoding

Converts UTF-8 encoded string into an ANSI encoded with encoding `[.DstEncoding]`

.....

;end table


### String procedures example

Here is some simple example demonstrating the use of several string functions:

;begin
iglobal
  MyConst1 db 'Mickey ', 0
  MyConst2 db 'Mouse ', 0
endg

    stdcall StrNew
    mov     ebx, eax
    stdcall StrDup, MyConst1
    stdcall StrCat, eax, MyConst2        ; note, that StrCat does not change any registers.
    stdcall StrCat, ebx, eax
    stdcall StrDel, eax                  ; StrDel also preserves the flags.

;end



-----------------------------------

## Using dynamic libraries other than the standard.

FreshLib creates all the import tables needed for the program automatically. 

Usually, the functions imported from external DLLs are not supposed to be called from the user code, because such 
calls are not portable. 

But sometimes, the programmer needs some functionality that is accessible only through an external library. There are 
two cases:

1. The internal library is available only for one particular OS. In this case, the result program will be not portable 
and nothing can be done.

2. There are versions of the same library for all target platforms. This is the best variant that will allow to keep 
the created program portable. But in this variant, there is a catch. It requires the calling conventions of the 
different OS versions of the library to be the same. 

In order to use external DLLs, the one will need a file with definitions of the imported functions placed somewhere in 
the project directory. This file should contain a list with the functions exported from the DLL using the FreshLib macro 
'import_proto'.

[#import_proto] macro is defined for Linux and Windows, following way:

;begin
       macro import_proto library, [iname, arg, ename]
;end

Where:

  `library` is the name of the DLL;
    
  `iname`   is the name of the function as it will appears in the FreshLib program.

  `arg`     is an optional list with the function's arguments. They will be used for function call argument hinting 

  `ename`   is a string with the name of the function as exported from the DLL.

The only difference between the Windows and Linux version is the value of *library* field. In Windows it is the name of
the DLL without the extension. In Linux it is a string with the full name of the shared library.

Here are two examples of this macro use for sqlite3 library for Windows and Linux (here are only the first 4 function 
definitions):

  In *Windows:*
;begin
        import_proto sqlite3,  \
            sqliteAggregateContext, <.context, .nbytes>,  'sqlite3_aggregate_context',  \
            sqliteAggregateCount_OLD, <VOID>,  'sqlite3_aggregate_count',  \
            sqliteAutoExtension, <.ptrCallback>,  'sqlite3_auto_extension',  \
            sqliteBackupFinish, <.ptrBackup>,  'sqlite3_backup_finish',  \
;end
  In *Linux:*
;begin
        import_proto 'libsqlite3.so.0',  \
            sqliteAggregateContext, <.context, .nbytes>,  'sqlite3_aggregate_context',  \
            sqliteAggregateCount_OLD, <VOID>,  'sqlite3_aggregate_count',  \
            sqliteAutoExtension, <.ptrCallback>,  'sqlite3_auto_extension',  \
            sqliteBackupFinish, <.ptrBackup>,  'sqlite3_backup_finish',  \
;end

In the argument definitions, there are two special values: `<NONE>` means that the arguments are unknown and `<VOID>` 
means the function does not has any arguments. All arguments must start with '.', i.e. to be defined as local labels.

In the above example, the function `sqlite3_aggregate_context` has two arguments `.context` and `.nbytes` and is 
imported with the name `sqliteAggregateContext`.

If several definition files for different OSes are created, they have to be placed in separate directories, named after 
the OS they are targeted for. For the above example the first file will be placed in "myproject/Win32/sqlite.inc" and 
the second in "myproject/Linux/sqlite.inc".

If only one OS definition file is created, it may be placed anywhere.

The use of these definition files is with the macro `uses`, placed somewhere in your code that uses this library. The 
macro is defined following way:

[#uses]

;begin
        macro uses [libname] 
;end

Where `libname` is the name of the library in format: `LIBRARY_NAME[:definition_filename]`. The filename of the 
definition file is optional and if omitted is created automatically as '%lib%/imports/%TargetOS%/LIBRARY_NAME.inc

If several definition filenames are created for different OSes, the uses macro must contain %TargetOS% environment 
variable. For example:

;begin
        uses sqlite3:'myproject/%TargetOS%/sqlite3.inc'
;end

Defined this way functions can be used in the program from everywhere and later, when @AllImportSection or 
@AllImportEmbeded is used, FreshLib will automatically create the import table of the executable.

Notice, that only the functions that are used will be imported. This way, it is always safe to use `uses` macro. 
It will never create over-bloated import table. 








Added phWeb/www/advanced_setup.md.















































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
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
91
92
93
94
95
96
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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
Setup manual
# Chapter 4 Fresh IDE setup

    The upcoming version 3.0 of Fresh IDE will be fully portable, but until then,
we have to use the Windows version of Fresh.

    Nevertheless, development of Windows and Linux applications in the same time is possible 
    and easy with the current version of Fresh.

    The good news are that Fresh IDE runs like a charm in [Wine].

    So, now (since v2.0.5) we have a choice - whatever OS we choose we can develop applications
for Linux and Windows, including editing, compiling, running and debugging. Of course we are
talking about GUI applications.

    The installation of Fresh is easy, but if we want to use the full potential of the IDE
some setup and adjustments are necessary. Let see how to setup Fresh IDE for work in Windows 
and Linux:

[wine] http://www.winehq.org/


## Windows setup

    In order to run Linux native applications inside Windows, Fresh uses special Linux
distribution - [andlinux].

    *andLinux* is complete Ubuntu distribution, that uses coLinux kernel in order to allow
running of Linux inside Windows OS.

[andLinux] http://andlinux.org
[andLinux download page] http://andlinux.org/downloads.php

    How to setup andLinux to work with Fresh?

### Download andLinux

    Download andLinux package from [andLinux download page]

    There are two packages: "KDE version" and "minimal/XFCE version" available. For use with
Fresh IDE, it is not important what version you will choose.

    KDE package is very big and very slow distribution that contains many bundled programs
and tools, but in general you will not need them. The size of KDE package is 500MB download
and 5GB installed.

    The XFCE package is relatively smaller and faster. Relatively means 200MB downloaded file
and 2GB installed on the disk.

    It is obvious that the right choice is to use XFCE package.

### Install andLinux

    Run the downloaded setup file and answer to the different questions of the
setup wizard:

    * coLinux version - choose the stable version (0.7.4 in my case) instead of latest (0.8.0) - 
we shall work with andLinux, not to play.

    * Memory size - 256MB RAM (or maybe more - if you can afford it).

    * Install XMing server on your primary screen.

    * Sound - you can enable or disable sound in Linux option - it is harmless although
it is one more running server.

    * Startup type + Panel - select *"run andLinux automatically as a NT service" + "use Windows shortcuts"*;
It is not very important, but can save you a little manual work and troubles later.

    * andLinux login - just select your user name and password for Linux root.

    * Windows File Access - it is important! - select *"using CoFS"*, no matter it is not recommended.

    * File Access Using CoFS - important! - create one new directory somewhere and select it to
be mount via CoFS. This will be the shared directory, visible from Windows and from Linux in the
same time.

    All other features you can choose freely or simply leave them to default state.

    When you start installation, the installer will try to install network driver.
It is possible Windows will protest and will atempt to mislead you by asking to not install
not certified driver. You must ignore these attempts and firmly click "install".

    After the installation of andLinux, you have to restart Windows and probably andLinux will
not run. :)

    It is because of the Windows firewall. All new network adapters are firewalled
by default. As long as installed adapter (named TAP-Colinux) is virtual and local, you will
not need any firewall, so, go to "Control panel/Windows firewall/Advanced" and uncheck
"TAP-Colinux" adapter from the list of adapters.

    Then you can run some Linux program - in the Windows tray, there is a andLinux menu icon
that have shortcuts to several Linux programs.


### Additional tools

    Install several additional Linux tools. You will need additionally debugger and
some decent terminal emulator. I choose xterm for terminal, because it is small and white by
default. ;)

    You can choose to use the built-in terminal named in the simple Linux manner:
"xfce4-terminal" and console debugger "gdb". In this case you can skip this step because these tools
are already installed.

    Start "Synaptic" - package manager for Ubuntu from the tray menu. You have to enter root
password you choose on install.

    When Synaptic is started, click "Reload" to refresh the package list from the network and
then use search to locate needed programs. I personally recommend "xterm" as terminal and "ddd"
as a GUI front end to "gdb".

    Well, I recommend "ddd" only because it is only Linux debugger that I was able to run under
andLinux and able to show disassembled code of the program.

    Mark selected programs for install, click on Apply button and wait until downloading and
installation.

    Here you can encounter only one problem - your computer is behind a proxy server.

    If the proxy is a normal proxy, you simply have to set its address and port in the
Synaptic preferences and it should work.

    Completely another story is when the proxy is MS ISA server configured with NTLM user
authorization.

    Most Linux programs can't work with such authorization and Synaptic is not an exception.

    Fortunately, there is a workaround of this situation. You need [ntlmaps] authorization 
proxy server.

    Setting up of this server is out of the scope of this article. On the ntlmaps home page you
can read complete documentation and explanations.

    OK, we are ready with andLinux. Now you have working copy of Ubuntu inside your Windows box.

    It's time to configure Fresh to run Linux applications inside andLinux. Continue with:

[ntlmaps] http://ntlmaps.sourceforge.net/

### Fresh IDE configuration.

    Run Fresh and open "Options|IDE options" dialog. Select "Debuggers and Emulators" page.
    Then select following directories and commands:

    * "andLinux directory" - the directory where you installed andLinux.

    * "andLinux shared directory" - shared directory you selected during andLinux installation.

    * "Linux debugger" - Enter "ddd" (or whatever debugger you choose).

    * "Linux terminal" - Enter: `xterm -hold +mesg -e` - the options are important.

    *And voila! You finished the configuration!*

    Now you can load the source of some Linux program (for example "Fresh/examples/XLib/XLib.fpr") and run it with
shift+F9 or load it in the debugger with shift+F8.

    Now Fresh IDE will detect when you compiled ELF executable and will run it in andLinux instead of
Windows. Of course, the Windows applications will be treated as usually.


## Linux setup

    Working in Linux needs Wine installation. Fresh is tested with v1.2 and 1.3 and works great.
You can skip some steps if they are already set.

### Install Wine

    Install Wine - use whatever package manager is good for you. Synaptic is the usual choice.
In the "Wine configuration|Graphics" panel, uncheck the option "Allow the window manager to decorate the windows".

### Install Fresh IDE

    Install Fresh IDE v2.0.5 or newer - you can use the installation package or ZIP
archive. It is better (at least for v2.0.5) to install Fresh IDE in "c:\" but you can put it at
whatever place you like.

### Debuggers

    Install whatever debugger you will use for Linux applications and OllyDbg for
Windows applications. (OllyDbg works in Wine).

    For Linux, personally I prefer [EDB] but any other is OK
including mentioned in the previous chapter "ddd" and "gdb".

[edb] http://www.codef00.com/projects#Debugger

### Configure Fresh IDE

Run Fresh IDE and if some paths are not set properly, set them manually in
"Options|IDE options" menu.

    You will need at least following directory aliases: "Fresh", "finc" and "lib" - set
them respectively to the Fresh main directory, Fresh "include" directory and "freshlib"
directory, both located in Fresh main directory. (As a rule, there is an auto setup of these
paths, so you don't to have to make it manually. But sometimes the algorithm fails)

    In order to work with FASM examples and programs, you can set manually "include" or any
other alias (environment variable) you prefer.

### External tools

    Set the paths to the external tools needed: (of course you have to install these
tools in advance).

    In "Options|IDE options|Debuggers and emulators" leave "andLinux directory" and
"andLinux shared directory" fields empty. (they are not needed when Fresh runs in Linux)

    Set "Linux debugger" field to binary file of the debugger you prefer. Add the needed
options to the line as well.

    For example, in my settings "Linux debugger" is set to `z:/usr/bin/edb --run`

    Set "Linux terminal" to preferred terminal. For example `z:/usr/bin/xterm -hold +mesg`.

    Set "Win32 external debugger" to OllyDbg.
In my case: `c:\Program files\OllyDebugger\Ollydbg.exe`.

    *All paths must be "dos style" (Note: Wine maps Linux file system to device Z: ).*

### Test it

    Try to compile and run some test applications both for Windows and Linux.
Ctrl+F9 should compile, Shift+F9 should run the application and Shift+F8 should load it
in the respective debugger. The type of the application should be automatically determined.

    *IMPORTANT NOTE:* The only known problem (for Fresh v2.0.5) is that the first time compiled
ELF is not set to be executable. So, you will get "access denied" message on run. The workaround
is to set the permissions manually from the file manager, or console "chmod" command. It is one
time procedure - the following compilations, runs and debugs should work properly.

Changes to phWeb/www/help.css.

cannot compute difference between binary files

Added phWeb/www/index.md.























>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
Fresh IDE help index.

# Fresh IDE help system.

This is the main index of the Fresh IDE help system. The following documents are available:

  [advanced_setup.md][Fresh IDE advanced setup guide.]

  [FreshLibRef.md][FreshLib programmers reference.]

  [FreshLibUserGuide.md][FreshLib user guide.]

Added phWeb/www/tips.md.





























































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
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
91
92
93
94
95
96
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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
Tips and tricks
# Chapter 5 Fresh tips and tricks.

    There is still no full user guide for Fresh.

    I will write in this page some tips and tricks. Later, they will be used in the full user guide.


## Linux support

* How to develop Linux application from Windows?

* How to develop Windows application from Linux?

* What about Fresh IDE version for Linux?

    For now, Fresh is Windows application. The versions 2.x.x will be Windows applications.
The upcoming v3.0.0 is planed to be portable - for Windows and Linux. Of course every port
will be able to create applications for every OS.

    Despite of this situation, even the current versions can work in Linux through Wine.

    There is a separate [setup][setup manual] describing the setup of Fresh IDE for Linux development.

[setup] 0_advanced_setup.htm

## Goto address

    How to find the place in the source where application crashes?

    Press Ctrl+G in order to open "Goto address" dialog:

        [!goto][Goto address]

    Then enter the address where application crashes and press OK. Fresh will show you the
line of the source that is compiled on the given address. The format of the number is standard
FASM number format.


## Code exploration and cross reference.

There are several functions, aimed to provide easy exploration the source of the big project.

### Labels explorer

After compilation, you can browse all labels tree from the labels explorer. Open it from the 
main menu: `Project|Label explorer`.
In the label explorer you can view the lables values, type and where in the source these labels 
was defined and used.

### Editor cross reference

If you position the text caret on some label and press Ctrl+R, or choose from context menu 
"Cross reference", a window with the cross reference information for this label will be open.

          [!cross][Cross reference]

The first row of the table display the line of the source, label was defined. 
Following rows - the lines where the label is used. Besides the pointed label, all its 
children labels will be displayed.s

If you double click on some of the rows, the editor will bring you to this line of source.

The cross reference window can be closed by pressing *Esc* key.

## Goto definition

If you position the text caret on some symbol and press *Ctrl+D* or choose from the context menu 
"Goto definition", the editor will bring you to the line of the source where this symbol were 
defined.
The project must be compiled for this function to work.

## Embeded help

Similar to "Goto definition" is the next function "Embeded help". 

If the definition of some symbol is preceded by comments block, describing this symbol, Fresh can
show this description everywhere in the source, when you position the text caret on the symbol and
press *Ctrl+W* shortcut. 

The hint window looks like on the screenshot:

                    [!_images/EmbededHelp.png][Embeded help system]

The hint window can be closed by pressing *Esc* key.

## Arguments hint

    How to use "Procedure arguments hint"?

        [!procarg][Procedure argument hints]

    This function works with call macros: *stdcall, ccall, invoke and cinvoke*;

    When you type such line and the function is known (the source have to be compiled prior to
that moment) Fresh shows a hint window that helps you to enter the arguments. This happens
automatically when you type "," somewhere in the line.

    When you want to open the hint window without typing (just for check up) you can press
Ctrl+Q when the caret is at the line. You can close the hint window, pressing *Esc* key.

    "Procedure argumens hint" works for the procedures defined in the compiled source and if
the program uses import definitions from FreshLib, for imported functions as well.

## Code completion

    How to type less and to code more?

        [!code][Code completion]

    Code completion is very powerful function, that can save you thousands of keystrokes.
In order to use it, the source have to be compiled (at least partially - some errors are
acceptable) because Fresh have to build the tree of labels, defined in you program.

    Fresh does not use fixed pre-defined lists. It uses the labels you defined in the source.

    This is the only possible solution, because Fresh is not committed to any particular OS or
platform. If you write Win32 program, you need Windows API and constants in the auto completion box.
If you write Linux program, you need all Linux constants and API functions.

    To open code completion, press *Ctrl+Space* shortcut. Then when you type, the content of the box
will be refreshed in order to correspond with the word you type.

    You can select suitable element from the list with *Up, Down, PgUp and PgDn* keys
and press *Enter* to insert it in the line.

    Auto competion list will open automatically when you type some existing in the list label
and then press *"."* in order to select local label.

    You can close the auto completion window with *ESC* key.

## Project categories

    How to move a file from one category to another in the project?

    Open the file in the editor. Select the category where you want it to be moved.
Click the right mouse button on the tab of the file in order to display the context menu.
Select "Add to project" function. It will remove the file from the old category and will
move it to the current selected category.

## Fast open files

    How to open the file specified in "include" or "file" directive?

    Place the caret on the line that contains file name and press Ctrl+Enter.
    Opening files this way, Fresh replace the directory aliases and/or environment 
variables in the filename.

    Files like `%lib%/%TargetOS%/MyFile.asm` will be opened correctly.

## Directory aliases

    How to set promptly the values of the environment variables?

    Fresh have very flexible system of environment variables handling. Actually I prefer to call them
"Aliase", because they are aliases of the directories or other text.

    You can define such aliases in three ways:

* As OS environment variable.

* As IDE-wide aliases in the Fresh IDE options dialog ("Options|IDE options|Aliases" menu).

* As Project-wide aliases in the project options (Project|Project options" menu or Ctrl+F12 shortcut)

    When exists alias defined several times, then the project aliases have higher priority, then
the IDE aliases and with lowest priority are the OS environment variables.

    Now on the topic: The project aliases allows rapid value change. In order to use this
feature, you have to define the alias with several values, delimited with "|" symbol.
The count of different values is not limited.

    One typical example is the alias %TargetOS% used in the FreshLib test project.
This alias may have as values the names of the OS, the project will be compiled for.
So, in order to switch quick from Win32 to Linux we can define TargetOS as "Win32|Linux".

    In this case, at the top of the project window appears popup menu, where you can select what of these
values to be used. Additionally, the panel "Settings:" will display currently selected values.

       [!alias][Alias fast change]

## Portable applications

    How to write portable assembly applications with Fresh IDE?

    Most people think that assembly language can't be portable. It is not the case. There are many
examples that assembly can be portable. It is only matter of the project design, not the language.

    In order to allow creating of portable applications, FreshLib was created. It is work-in-progress,
but even now it allows creating of small applications that can be compiled for Win32 and Linux platforms
without change of the source.

    Read the unfinished [FreshLibRef][FreshLib reference manual]
and check the sources of FreshLib in "Fresh/freshlib" directory of your Fresh IDE installation.
There is a working test project called TestFreshLib.fpr that I use to test different FreshLib features.

Also, you can create FreshLib projects from template engine. Choose "File|New Application" from the 
main menu or press *Shift+Ctrl+N* shortcut. 

In the dialog window, select the target directory and application template - 
"FreshLib portble console application" or "FreshLib portable GUI application", 
then click *"OK"* and new project will be created.

Press *Shift+Ctrl+S* to save all new created files (you can change the filenames to whatever you like).

Then you can compile your application to Linux or Windows executable file.

The latest development version of FreshLib can be downloaded from the [rep][repository] - *FreshLibDev* branch.

[FreshLibRef] 2_FreshLibDoc.htm

[rep] http://chiselapp.com/user/johnfound/repository/FreshIDE/
        
[!goto] _images/goto.png

[!procarg] _images/ProcArgumentsHint.png

[!code] _images/CodeCompletion.png

[!alias] _images/AliasFastChange.png

[!cross] _images/CrossReference.png