Subversion Repositories Kolibri OS

Rev

Rev 1295 | Rev 3112 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
717 mikedld 1
;;================================================================================================;;
2
;;//// libini.asm //// (c) mike.dld, 2006-2008 ///////////////////////////////////////////////////;;
3
;;================================================================================================;;
4
;;                                                                                                ;;
5
;; This file is part of Common development libraries (Libs-Dev).                                  ;;
6
;;                                                                                                ;;
7
;; Libs-Dev is free software: you can redistribute it and/or modify it under the terms of the GNU ;;
1001 diamond 8
;; Lesser General Public License as published by the Free Software Foundation, either version 2.1 ;;
9
;; of the License, or (at your option) any later version.                                         ;;
717 mikedld 10
;;                                                                                                ;;
11
;; Libs-Dev is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without  ;;
12
;; even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU  ;;
1001 diamond 13
;; Lesser General Public License for more details.                                                ;;
717 mikedld 14
;;                                                                                                ;;
1001 diamond 15
;; You should have received a copy of the GNU Lesser General Public License along with Libs-Dev.  ;;
16
;; If not, see .                                                    ;;
717 mikedld 17
;;                                                                                                ;;
18
;;================================================================================================;;
19
;;                                                                                                ;;
1048 mikedld 20
;; 2009-03-08 (mike.dld)                                                                          ;;
21
;;   bug-fixes:                                                                                   ;;
22
;;     - moved buffer bound check in libini._.low.read_value up (reported by Insolor)             ;;
23
;;   new features:                                                                                ;;
24
;;     - comments support (char is ini.COMMENT_CHAR, defaults to ';')                             ;;
25
;;       inline comments are not supported                                                        ;;
988 mikedld 26
;; 2008-12-29 (mike.dld)                                                                          ;;
27
;;   bug-fixes:                                                                                   ;;
28
;;     - unnecessary 'stosb' in ini.get_str was causing problems                                  ;;
995 mikedld 29
;;   new features:                                                                                ;;
30
;;     - new functions: ini.get_color and ini.set_color                                           ;;
845 mikedld 31
;; 2008-08-06 (mike.dld)                                                                          ;;
32
;;   changes:                                                                                     ;;
33
;;     - split private procs into libini_p.asm, added comments                                    ;;
717 mikedld 34
;; 2008-02-07 (mike.dld)                                                                          ;;
35
;;   changes:                                                                                     ;;
36
;;     - renamed all *.aux.* to *._.* to match overall libraries design                           ;;
37
;; 2007-09-26 (mike.dld)                                                                          ;;
38
;;   bug-fixes:                                                                                   ;;
39
;;     - value was not correctly trimmed (reported by diamond)                                    ;;
40
;; 2007-08-01 (mike.dld)                                                                          ;;
41
;;   bug-fixes:                                                                                   ;;
42
;;     - serious defect in ini.set_str causing displaced write operations                         ;;
43
;;       (reported by diamond)                                                                    ;;
44
;;     - another serious defect in ini.enum_keys introduced with refactoring                      ;;
45
;;   changes:                                                                                     ;;
46
;;     - callback for enum_keys now takes additional parameter - key value                        ;;
47
;;     - handling trailing spaces in section/key/value                                            ;;
48
;; 2007-05-19 (mike.dld)                                                                          ;;
49
;;   bug-fixes:                                                                                   ;;
50
;;     - last char still wasn't read correctly                                                    ;;
51
;;     - digits of number were reversed when using ini.set_int                                    ;;
52
;;     - now using 'ini.aux.unget_char' instead of dangerous 'dec esi'                            ;;
53
;;   changes:                                                                                     ;;
54
;;     - all non-public functions now start with ini.aux.*                                        ;;
55
;;     - added ini.enum_sections and ini.enum_keys                                                ;;
56
;;     - removed ini.query_sec (use ini.enum_* instead)                                           ;;
57
;;                                                                                                ;;
58
;;================================================================================================;;
59
 
60
format MS COFF
61
 
62
public @EXPORT as 'EXPORTS'
63
 
64
include '../../../../proc32.inc'
65
include '../../../../macros.inc'
66
include '../libio/libio.inc'
1327 diamond 67
purge section,mov,add,sub
717 mikedld 68
 
69
include 'libini_p.inc'
70
 
845 mikedld 71
section '.flat' code readable align 16
717 mikedld 72
 
845 mikedld 73
include 'libini_p.asm'
717 mikedld 74
 
75
;;================================================================================================;;
76
proc ini.enum_sections _f_name, _callback ;///////////////////////////////////////////////////////;;
77
;;------------------------------------------------------------------------------------------------;;
845 mikedld 78
;? Enumerate sections, calling callback function for each of them                                 ;;
717 mikedld 79
;;------------------------------------------------------------------------------------------------;;
845 mikedld 80
;> _f_name = ini filename                                                                 ;;
81
;> _callback = callback function address: func(f_name, sec_name), where                           ;;
82
;>   f_name = ini filename (as passed to the function)                                    ;;
83
;>   sec_name = section name found                                                        ;;
717 mikedld 84
;;------------------------------------------------------------------------------------------------;;
845 mikedld 85
;< eax = -1 (error) / 0                                                                           ;;
717 mikedld 86
;;================================================================================================;;
87
locals
88
  f	  IniFile
89
  f_addr  dd ?
90
  sec_buf dd ?
91
endl
92
 
93
	push	ebx esi edi
94
 
95
	cld
96
 
97
	invoke	mem.alloc, ini.MAX_NAME_LEN
98
	or	eax, eax
99
	jz	.exit_error.2
100
	mov	[sec_buf], eax
101
 
102
	xor	eax, eax
103
	mov	[f.fh], eax
104
	mov	[f.buf], eax
105
	invoke	file.open, [_f_name], O_READ
106
	cmp	eax, 32
107
	jb	.exit_error
108
	mov	[f.fh], eax
109
	invoke	mem.alloc, ini.MEM_SIZE
110
	or	eax, eax
111
	jz	.exit_error
112
	mov	[f.buf], eax
113
	lea	ebx, [f]
114
	mov	[f_addr], ebx
115
 
919 mikedld 116
	invoke	file.seek, [f.fh], 0, SEEK_SET
845 mikedld 117
	stdcall libini._.preload_block, [f_addr]
717 mikedld 118
 
119
  .next_section:
845 mikedld 120
	stdcall libini._.find_next_section, [f_addr]
717 mikedld 121
	or	eax, eax
122
	jnz	.exit_error
123
 
845 mikedld 124
	stdcall libini._.get_char, [f_addr]
125
	stdcall libini._.skip_spaces, [f_addr]
717 mikedld 126
	mov	edi, [sec_buf]
845 mikedld 127
    @@: stdcall libini._.get_char, [f_addr]
717 mikedld 128
	cmp	al, ']'
129
	je	@f
130
	or	al, al
131
	jz	.exit_ok
132
	cmp	al, 13
133
	je	.next_section
134
	cmp	al, 10
135
	je	.next_section
136
	stosb
137
	jmp	@b
138
    @@: xor	al, al
139
	stosb
140
	add	edi, -2
141
    @@: cmp	byte[edi], 32
142
	ja	@f
143
	mov	byte[edi], 0
144
	dec	edi
145
	jmp	@b
146
    @@:
147
	pushad
148
	mov	eax, [f_addr]
149
	stdcall [_callback], [_f_name], [sec_buf]
150
	or	eax, eax
151
	popad
152
	jnz	.next_section
153
 
154
  .exit_ok:
155
	invoke	file.close, [f.fh]
156
	invoke	mem.free, [f.buf]
157
	invoke	mem.free, [sec_buf]
158
	xor	eax, eax
159
	pop	edi esi ebx
160
	ret
161
 
162
  .exit_error:
163
	invoke	file.close, [f.fh]
164
	invoke	mem.free, [f.buf]
165
	invoke	mem.free, [sec_buf]
166
  .exit_error.2:
167
	or	eax, -1
168
	pop	edi esi ebx
169
	ret
170
endp
171
 
172
;;================================================================================================;;
173
proc ini.enum_keys _f_name, _sec_name, _callback ;////////////////////////////////////////////////;;
174
;;------------------------------------------------------------------------------------------------;;
845 mikedld 175
;? Enumerate keys within a section, calling callback function for each of them                    ;;
717 mikedld 176
;;------------------------------------------------------------------------------------------------;;
845 mikedld 177
;> _f_name = ini filename                                                                 ;;
178
;> _sec_name = section name                                                               ;;
179
;> _callback = callback function address: func(f_name, sec_name, key_name, key_value), where      ;;
180
;>   f_name = ini filename (as passed to the function)                                    ;;
181
;>   sec_name = section name (as passed to the function)                                  ;;
182
;>   key_name = key name found                                                            ;;
183
;>   key_value = value of key found                                                       ;;
717 mikedld 184
;;------------------------------------------------------------------------------------------------;;
845 mikedld 185
;< eax = -1 (error) / 0                                                                           ;;
717 mikedld 186
;;================================================================================================;;
187
locals
188
  f	  IniFile
189
  f_addr  dd ?
190
  key_buf dd ?
191
  val_buf dd ?
192
endl
193
 
194
	push	ebx esi edi
195
 
196
	cld
197
 
198
	invoke	mem.alloc, ini.MAX_NAME_LEN
199
	or	eax, eax
200
	jz	.exit_error.3
201
	mov	[key_buf], eax
202
	invoke	mem.alloc, ini.MAX_VALUE_LEN
203
	or	eax, eax
204
	jz	.exit_error.2
205
	mov	[val_buf], eax
206
 
207
	xor	eax, eax
208
	mov	[f.fh], eax
209
	mov	[f.buf], eax
210
	invoke	file.open, [_f_name], O_READ
211
	cmp	eax, 32
212
	jb	.exit_error
213
	mov	[f.fh], eax
214
	invoke	mem.alloc, ini.MEM_SIZE
215
	or	eax, eax
216
	jz	.exit_error
217
	mov	[f.buf], eax
218
	lea	ebx, [f]
219
	mov	[f_addr], ebx
845 mikedld 220
	stdcall libini._.find_section, ebx, [_sec_name]
717 mikedld 221
	or	eax, eax
222
	jnz	.exit_error
223
 
224
  .next_key:
845 mikedld 225
	stdcall libini._.skip_line, [f_addr]
226
	stdcall libini._.skip_nonblanks, [f_addr]
717 mikedld 227
	or	al, al
228
	jz	.exit_error
229
	cmp	al, '['
230
	je	.exit_error
231
	mov	edi, [key_buf]
845 mikedld 232
    @@: stdcall libini._.get_char, [f_addr]
717 mikedld 233
	or	al, al
234
	jz	.exit_error
235
	cmp	al, '='
236
	je	@f
237
	stosb
238
	jmp	@b
239
    @@:
240
	xor	al, al
241
	stosb
242
	add	edi, -2
243
    @@: cmp	byte[edi], 32
244
	ja	@f
245
	mov	byte[edi], 0
246
	dec	edi
247
	jmp	@b
845 mikedld 248
    @@: stdcall libini._.low.read_value, [f_addr], [val_buf], ini.MAX_VALUE_LEN
717 mikedld 249
	pushad
250
	stdcall [_callback], [_f_name], [_sec_name], [key_buf], [val_buf]
251
	or	eax, eax
252
	popad
253
	jnz	.next_key
254
 
255
    @@: invoke	file.close, [f.fh]
256
	invoke	mem.free, [f.buf]
257
	xor	eax, eax
258
	stosb
259
	pop	edi esi ebx
260
	ret
261
 
262
  .exit_error:
263
	invoke	file.close, [f.fh]
264
	invoke	mem.free, [f.buf]
265
	invoke	mem.free, [val_buf]
266
  .exit_error.2:
267
	invoke	mem.free, [key_buf]
268
  .exit_error.3:
269
	or	eax, -1
270
	pop	edi esi ebx
271
	ret
272
endp
273
 
274
;;================================================================================================;;
275
proc ini.get_str _f_name, _sec_name, _key_name, _buffer, _buf_len, _def_val ;/////////////////////;;
276
;;------------------------------------------------------------------------------------------------;;
845 mikedld 277
;? Read string                                                                                    ;;
717 mikedld 278
;;------------------------------------------------------------------------------------------------;;
845 mikedld 279
;> _f_name = ini filename                                                                 ;;
280
;> _sec_name = section name                                                               ;;
281
;> _key_name = key name                                                                   ;;
282
;> _buffer = destination buffer address                                                    ;;
283
;> _buf_len = buffer size (maximum bytes to read)                                          ;;
284
;> _def_val = default value to return if no key, section or file found                    ;;
717 mikedld 285
;;------------------------------------------------------------------------------------------------;;
845 mikedld 286
;< eax = -1 (error) / 0                                                                           ;;
287
;< [_buffer] = [_def_val] (error) / found key value                                       ;;
717 mikedld 288
;;================================================================================================;;
289
locals
290
  f	 IniFile
291
  f_addr dd ?
292
endl
293
 
294
	push	ebx esi edi
295
 
296
	xor	eax, eax
297
	mov	[f.fh], eax
298
	mov	[f.buf], eax
299
	invoke	file.open, [_f_name], O_READ
300
	cmp	eax, 32
301
	jb	.exit_error
302
	mov	[f.fh], eax
303
	invoke	mem.alloc, ini.MEM_SIZE
304
	or	eax, eax
305
	jz	.exit_error
306
	mov	[f.buf], eax
307
	lea	ebx, [f]
308
	mov	[f_addr], ebx
845 mikedld 309
	stdcall libini._.find_section, ebx, [_sec_name]
717 mikedld 310
	or	eax, eax
311
	jnz	.exit_error
312
 
845 mikedld 313
	stdcall libini._.find_key, ebx, [_key_name]
717 mikedld 314
	or	eax, eax
315
	jnz	.exit_error
316
 
845 mikedld 317
	stdcall libini._.low.read_value, [f_addr], [_buffer], [_buf_len]
717 mikedld 318
    @@: invoke	file.close, [f.fh]
319
	invoke	mem.free, [f.buf]
320
	xor	eax, eax
321
	pop	edi esi ebx
322
	ret
323
 
324
  .exit_error:
325
	invoke	file.close, [f.fh]
326
	invoke	mem.free, [f.buf]
988 mikedld 327
	mov	edi, [_buffer]
717 mikedld 328
	mov	esi, [_def_val]
988 mikedld 329
	xor	al, al
330
	or	esi, esi
331
	jz	.exit_error.2
717 mikedld 332
    @@: lodsb
988 mikedld 333
  .exit_error.2:
717 mikedld 334
	stosb
335
	or	al, al
336
	jnz	@b
337
	or	eax, -1
338
	pop	edi esi ebx
339
	ret
340
endp
341
 
342
;;================================================================================================;;
343
proc ini.set_str _f_name, _sec_name, _key_name, _buffer, _buf_len ;///////////////////////////////;;
344
;;------------------------------------------------------------------------------------------------;;
845 mikedld 345
;? Write string                                                                                   ;;
717 mikedld 346
;;------------------------------------------------------------------------------------------------;;
845 mikedld 347
;> _f_name = ini filename                                                                 ;;
348
;> _sec_name = section name                                                               ;;
349
;> _key_name = key name                                                                   ;;
350
;> _buffer = source buffer address                                                         ;;
351
;> _buf_len = buffer size (bytes to write)                                                 ;;
717 mikedld 352
;;------------------------------------------------------------------------------------------------;;
845 mikedld 353
;< eax = -1 (error) / 0                                                                           ;;
717 mikedld 354
;;================================================================================================;;
355
locals
356
  f	 IniFile
357
  f_addr dd ?
358
endl
359
 
360
	push	ebx esi edi
361
 
362
	xor	eax, eax
363
	mov	[f.fh], eax
364
	mov	[f.buf], eax
365
	invoke	file.open, [_f_name], O_READ + O_WRITE + O_CREATE
366
	cmp	eax, 32
367
	jb	.exit_error
368
	mov	[f.fh], eax
369
	invoke	mem.alloc, ini.MEM_SIZE
370
	or	eax, eax
371
	jz	.exit_error
372
	mov	[f.buf], eax
373
	lea	ebx, [f]
374
	mov	[f_addr], ebx
375
 
845 mikedld 376
	stdcall libini._.find_section, ebx, [_sec_name]
717 mikedld 377
	or	eax, eax
378
	jnz	.create_section
379
 
845 mikedld 380
	stdcall libini._.find_key, ebx, [_key_name]
717 mikedld 381
	or	eax, eax
382
	jnz	.create_key
383
 
384
  .modify_key:
845 mikedld 385
	stdcall libini._.get_value_length, [f_addr]
717 mikedld 386
	sub	eax, [_buf_len]
845 mikedld 387
	stdcall libini._.shift_content, [f_addr], eax
717 mikedld 388
 
389
  .modify_key.ex:
390
	invoke	file.tell, [f.fh]
391
	sub	eax, [f.cnt]
919 mikedld 392
	invoke	file.seek, [f.fh], eax, SEEK_SET
717 mikedld 393
	invoke	file.write, [f.fh], [_buffer], [_buf_len]
394
 
395
	pop	edi esi ebx
396
	xor	eax, eax
397
	ret
398
 
399
  .create_key:
400
	mov	edi, [f.buf]
401
	add	edi, ini.BLOCK_SIZE
402
	push	edi
403
 
404
  .create_key.ex:
405
	mov	esi, [_key_name]
845 mikedld 406
	call	libini._.string_copy
717 mikedld 407
	mov	byte[edi], '='
408
	inc	edi
409
	mov	esi, [_buffer]
410
	mov	ecx, [_buf_len]
411
	rep	movsb
412
	mov	word[edi], 0x0A0D
413
	add	edi, 2
414
	mov	eax, edi
415
 
416
	pop	edi
417
	sub	eax, edi
418
	mov	[_buffer], edi
419
	mov	[_buf_len], eax
420
	neg	eax
845 mikedld 421
	stdcall libini._.shift_content, [f_addr], eax
717 mikedld 422
 
423
	jmp	.modify_key.ex
424
 
425
  .create_section:
426
	mov	edi, [f.buf]
427
	add	edi, ini.BLOCK_SIZE
428
	push	edi
429
 
430
	mov	esi, [_sec_name]
431
	mov	byte[edi], '['
432
	inc	edi
845 mikedld 433
	call	libini._.string_copy
717 mikedld 434
	mov	dword[edi], ']' + (0x0A0D shl 8)
435
	add	edi, 3
436
 
437
	jmp	.create_key.ex
438
 
439
  .exit_error:
440
	pop	edi esi ebx
441
	or	eax, -1
442
	ret
443
endp
444
 
445
;;================================================================================================;;
446
proc ini.get_int _f_name, _sec_name, _key_name, _def_val ;////////////////////////////////////////;;
447
;;------------------------------------------------------------------------------------------------;;
845 mikedld 448
;? Read integer                                                                                   ;;
717 mikedld 449
;;------------------------------------------------------------------------------------------------;;
845 mikedld 450
;> _f_name = ini filename                                                                 ;;
451
;> _sec_name = section name                                                               ;;
452
;> _key_name = key name                                                                   ;;
453
;> _def_val = default value to return if no key, section or file found                     ;;
717 mikedld 454
;;------------------------------------------------------------------------------------------------;;
845 mikedld 455
;< eax = [_def_val] (error) / found key value                                              ;;
717 mikedld 456
;;================================================================================================;;
457
locals
458
  f	 IniFile
459
  f_addr dd ?
460
endl
461
 
462
	push	ebx esi edi
463
 
464
	xor	eax, eax
465
	mov	[f.fh], eax
466
	mov	[f.buf], eax
467
	invoke	file.open, [_f_name], O_READ
468
	cmp	eax, 32
469
	jb	.exit_error
470
	mov	[f.fh], eax
471
	invoke	mem.alloc, ini.MEM_SIZE
472
	or	eax, eax
473
	jz	.exit_error
474
	mov	[f.buf], eax
475
	lea	ebx, [f]
476
	mov	[f_addr], ebx
845 mikedld 477
	stdcall libini._.find_section, ebx, [_sec_name]
717 mikedld 478
	or	eax, eax
479
	jnz	.exit_error
480
 
845 mikedld 481
	stdcall libini._.find_key, ebx, [_key_name]
717 mikedld 482
	or	eax, eax
483
	jnz	.exit_error
484
 
1048 mikedld 485
	stdcall libini._.skip_spaces, [f_addr]
717 mikedld 486
	xor	eax, eax
487
	xor	ebx, ebx
488
	xor	edx, edx
845 mikedld 489
	stdcall libini._.get_char, [f_addr]
717 mikedld 490
	cmp	al, '-'
491
	jne	.lp1
492
	inc	bh
845 mikedld 493
    @@: stdcall libini._.get_char, [f_addr]
717 mikedld 494
  .lp1: cmp	al, '0'
495
	jb	@f
496
	cmp	al, '9'
497
	ja	@f
498
	inc	bl
499
	add	eax, -'0'
500
	imul	edx, 10
501
	add	edx, eax
502
	jmp	@b
503
    @@:
504
	or	bl, bl
505
	jz	.exit_error
506
	or	bh, bh
507
	jz	@f
508
	neg	edx
509
    @@: invoke	file.close, [f.fh]
510
	invoke	mem.free, [f.buf]
511
	mov	eax, edx
512
	pop	edi esi ebx
513
	ret
514
 
515
  .exit_error:
516
	invoke	file.close, [f.fh]
517
	invoke	mem.free, [f.buf]
518
	mov	eax, [_def_val]
519
	pop	edi esi ebx
520
	ret
521
endp
522
 
523
;;================================================================================================;;
524
proc ini.set_int _f_name, _sec_name, _key_name, _val ;////////////////////////////////////////////;;
525
;;------------------------------------------------------------------------------------------------;;
845 mikedld 526
;? Write integer                                                                                  ;;
717 mikedld 527
;;------------------------------------------------------------------------------------------------;;
845 mikedld 528
;> _f_name = ini filename                                                                 ;;
529
;> _sec_name = section name                                                               ;;
530
;> _key_name = key name                                                                   ;;
531
;> _val = value                                                                            ;;
717 mikedld 532
;;------------------------------------------------------------------------------------------------;;
845 mikedld 533
;< eax = -1 (error) / 0                                                                           ;;
717 mikedld 534
;;================================================================================================;;
535
locals
536
  buf rb 16
537
endl
538
 
539
	push	ecx edx edi
540
 
541
	lea	edi, [buf]
542
	add	edi, 15
543
	mov	eax, [_val]
544
	or	eax, eax
545
	jns	@f
546
	mov	byte[edi], '-'
547
	neg	eax
548
	inc	edi
549
    @@: mov	ecx, 10
550
    @@: xor	edx, edx
551
	idiv	ecx
552
	add	dl, '0'
553
	mov	[edi], dl
554
	dec	edi
555
	or	eax, eax
556
	jnz	@b
557
	lea	eax, [buf]
558
	add	eax, 15
559
	sub	eax, edi
560
	inc	edi
561
 
562
	stdcall ini.set_str, [_f_name], [_sec_name], [_key_name], edi, eax
563
 
564
	pop	edi edx ecx
565
	ret
566
endp
567
 
988 mikedld 568
;;================================================================================================;;
569
proc ini.get_color _f_name, _sec_name, _key_name, _def_val ;//////////////////////////////////////;;
570
;;------------------------------------------------------------------------------------------------;;
571
;? Read color                                                                                     ;;
572
;;------------------------------------------------------------------------------------------------;;
573
;> _f_name = ini filename                                                                 ;;
574
;> _sec_name = section name                                                               ;;
575
;> _key_name = key name                                                                   ;;
576
;> _def_val = default value to return if no key, section or file found                     ;;
577
;;------------------------------------------------------------------------------------------------;;
578
;< eax = [_def_val] (error) / found key value                                              ;;
579
;;================================================================================================;;
580
locals
581
  buf rb 14
582
endl
717 mikedld 583
 
988 mikedld 584
	push	ebx esi edi
585
 
586
	lea	esi, [buf]
587
	stdcall ini.get_str, [_f_name], [_sec_name], [_key_name], esi, 14, 0
588
	cmp	byte[esi],0
589
	je	.exit_error
590
 
591
	xor	ebx, ebx
592
	stdcall libini._.str_to_int
593
	movzx	ebx, al
594
	shl	ebx, 16
595
	lodsb
596
	cmp	al, ','
597
	jne	@f
598
	stdcall libini._.str_to_int
599
	mov	bh, al
600
	lodsb
601
	cmp	al, ','
602
	jne	@f
603
	stdcall libini._.str_to_int
604
	mov	bl, al
605
 
606
    @@: mov	eax, ebx
607
 
608
	pop	edi esi ebx
609
	ret
610
 
611
  .exit_error:
612
	mov	eax, [_def_val]
613
	pop	edi esi ebx
614
	ret
615
endp
616
 
717 mikedld 617
;;================================================================================================;;
988 mikedld 618
proc ini.set_color _f_name, _sec_name, _key_name, _val ;//////////////////////////////////////////;;
619
;;------------------------------------------------------------------------------------------------;;
620
;? Write color                                                                                    ;;
621
;;------------------------------------------------------------------------------------------------;;
622
;> _f_name = ini filename                                                                 ;;
623
;> _sec_name = section name                                                               ;;
624
;> _key_name = key name                                                                   ;;
625
;> _val = value                                                                            ;;
626
;;------------------------------------------------------------------------------------------------;;
627
;< eax = -1 (error) / 0                                                                           ;;
628
;;================================================================================================;;
629
locals
630
  buf rb 16
631
endl
632
 
633
	push	ecx edx edi
634
 
635
	lea	edi, [buf]
636
	mov	ecx, 10
637
	mov	ebx, [_val]
638
	mov	eax, ebx
639
	shr	eax, 16
640
	and	eax, 0x0ff
641
	stdcall libini._.int_to_str
642
	mov	byte[edi], ','
643
	inc	edi
644
	movzx	eax, bh
645
	stdcall libini._.int_to_str
646
	mov	byte[edi], ','
647
	inc	edi
648
	movzx	eax, bl
649
	stdcall libini._.int_to_str
650
 
651
	lea	eax, [buf]
652
	sub	edi, eax
653
 
654
	stdcall ini.set_str, [_f_name], [_sec_name], [_key_name], eax, edi
655
 
656
	pop	edi edx ecx
657
	ret
658
endp
659
 
1327 diamond 660
;;================================================================================================;;
661
proc ini.get_shortcut _f_name, _sec_name, _key_name, _def_val, _modifiers ;///////////////////////;;
662
;;------------------------------------------------------------------------------------------------;;
663
;? Read shortcut key                                                                              ;;
664
;;------------------------------------------------------------------------------------------------;;
665
;> _f_name = ini filename                                                                 ;;
666
;> _sec_name = section name                                                               ;;
667
;> _key_name = key name                                                                   ;;
668
;> _def_val = default value to return if no key, section or file found                     ;;
669
;> _modifiers = pointer to dword variable which receives modifiers state as in 66.4       ;;
670
;;------------------------------------------------------------------------------------------------;;
671
;< eax = [_def_val] (error) / shortcut key value as scancode                                 ;;
672
;< [[_modifiers]] = unchanged (error) / modifiers state for this shortcut                    ;;
673
;;================================================================================================;;
674
locals
675
  buf rb 64
676
endl
988 mikedld 677
 
1327 diamond 678
	push	ebx esi edi
679
 
680
	lea	esi, [buf]
681
	stdcall ini.get_str, [_f_name], [_sec_name], [_key_name], esi, 64, 0
682
	cmp	byte[esi],0
683
	je	.exit_error
684
 
685
	xor	ebx, ebx	; ebx holds the value of modifiers
686
.loop:
687
; test for end
688
	xor	eax, eax
689
	cmp	byte [esi], al
690
	jz	.exit_ok	; exit with scancode zero
691
; skip all '+'s
692
	cmp	byte [esi], '+'
693
	jnz	@f
694
	inc	esi
695
	jmp	.loop
696
@@:
697
; test for names
698
	mov	edi, .names_table
699
	xor	edx, edx
700
.names_loop:
701
	movzx	ecx, byte [edi]
702
	inc	edi
703
	push	esi
704
@@:
705
	lodsb
706
	or	al, 20h
707
	scasb
708
	loopz	@b
709
	jz	.name_found
710
	pop	esi
711
	lea	edi, [edi+ecx+4]
712
	inc	edx
713
	cmp	byte [edi], 0
714
	jnz	.names_loop
715
; special test: functional keys F
716
	cmp	byte [esi], 'f'
717
	jz	@f
718
	cmp	byte [esi], 'F'
719
	jnz	.no_fx
720
@@:
721
	mov	edi, esi
722
	inc	esi
723
	call	libini._.str_to_int
724
	test	eax, eax
725
	jz	.fx
726
	mov	esi, edi
727
.no_fx:
728
; name not found, that must be usual key
729
	movzx	eax, byte [esi]
730
	stdcall	libini._.ascii_to_scan, eax
731
	test	eax, eax
732
	jz	.exit_error
733
; all is ok
734
.exit_ok:
735
	mov	ecx, [_modifiers]
736
	test	ecx, ecx
737
	jz	@f
738
	mov	[ecx], ebx
739
 
740
@@:
741
 
742
	pop	edi esi ebx
743
	ret
744
 
745
.exit_error:
746
	mov	eax, [_def_val]
747
	pop	edi esi ebx
748
	ret
749
; handler for Fx
750
; eax = number
751
.fx:
752
	cmp	eax, 10
753
	ja	@f
754
	add	eax, 3Bh-1
755
	jmp	.exit_ok
756
@@:
757
	add	eax, 57h-11
758
	jmp	.exit_ok
759
; handlers for names
760
.name_found:
761
	pop	eax	; ignore saved esi
762
	call	dword [edi]
763
	cmp	edx, .num_modifiers
764
	jae	.exit_ok
765
	jmp	.loop
766
; modifiers
767
; syntax of value for each modifier:
768
; 0 = none, 1 = exactly one of L+R, 2 = both L+R, 3 = L, 4 = R
769
; Logic for switching: LShift+RShift=LShift+Shift=Shift+Shift, LShift+LShift=LShift
770
; generic modifier: 0->1->2->2, 3->2, 4->2
771
; left modifier: 0->3->3, 1->2->2, 4->2
772
; right modifier: 0->4->4, 1->2->2, 3->2
773
; Shift corresponds to first hex digit, Ctrl - second, Alt - third
774
macro shortcut_handle_modifiers name,reg,shift
775
{
776
local .set2,.set3,.set4
777
.#name#_handler:	; generic modifier
778
	test	reg, 0xF
779
	jnz	.set2
780
if shift
781
	or	reg, 1 shl shift
782
else
783
	inc	reg
784
end if
785
	retn
786
.set2:
787
	and	reg, not (0xF shl shift)
788
	or	reg, 2 shl shift
789
	retn
790
.l#name#_handler:
791
	mov	al, reg
792
	and	al, 0xF shl shift
793
	jz	.set3
794
	cmp	al, 3 shl shift
795
	jnz	.set2
796
	retn
797
.set3:
798
	add	reg, 3 shl shift
799
	retn
800
.r#name#_handler:
801
	mov	al, reg
802
	and	al, 0xF shl shift
803
	jz	.set4
804
	cmp	al, 4 shl shift
805
	jnz	.set2
806
	retn
807
.set4:
808
	add	reg, 4 shl shift
809
	retn
810
}
811
shortcut_handle_modifiers shift,bl,0
812
shortcut_handle_modifiers ctrl,bl,4
813
shortcut_handle_modifiers alt,bh,0
814
; names of keys
815
.name_handler:
816
	movzx	eax, byte [.names_scancodes+edx-.num_modifiers]
817
	retn
818
endp
819
 
820
; note: comparison ignores case, so this table keeps lowercase names
821
; macro does this
822
macro shortcut_name_with_handler name,handler
823
{
824
local .start, .end
825
	db	.end - .start
826
.start:
827
	db	name
828
.end:
829
repeat .end - .start
830
	load .a byte from .start + % - 1
831
	store byte .a or 0x20 at .start + % - 1
832
end repeat
833
	dd	handler
834
}
835
macro shortcut_name [name]
836
{
837
	shortcut_name_with_handler name, .name_handler
838
}
839
; all names here must be in english
840
; ... or modify lowercasing in macro and in comparison
841
.names_table:
842
; generic modifiers
843
	shortcut_name_with_handler 'Ctrl', .ctrl_handler
844
	shortcut_name_with_handler 'Alt', .alt_handler
845
	shortcut_name_with_handler 'Shift', .shift_handler
846
; concrete modifiers
847
	shortcut_name_with_handler 'LCtrl', .lctrl_handler
848
	shortcut_name_with_handler 'RCtrl', .rctrl_handler
849
	shortcut_name_with_handler 'LAlt', .lalt_handler
850
	shortcut_name_with_handler 'RAlt', .ralt_handler
851
	shortcut_name_with_handler 'LShift', .lshift_handler
852
	shortcut_name_with_handler 'RShift', .rshift_handler
853
.num_modifiers = 9
854
; symbolic names of keys
855
	shortcut_name 'Home', 'End', 'PgUp', 'PgDn', 'Ins', 'Insert', 'Del', 'Delete'
856
	shortcut_name 'Tab', 'Plus', 'Esc', 'Enter', 'Backspace', 'Space', 'Left', 'Right'
857
	shortcut_name 'Up', 'Down'
858
; end of table
859
	db	0
860
ini.get_shortcut.names_scancodes:
861
; scancodes for 'Home' ... 'Down'
862
	db	47h, 4Fh, 49h, 51h, 52h, 52h, 53h, 53h
863
	db	0Fh, 4Eh, 01h, 1Ch, 0Eh, 39h, 4Bh, 4Dh
864
	db	48h, 50h
865
 
988 mikedld 866
;;================================================================================================;;
717 mikedld 867
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
868
;;================================================================================================;;
869
;! Imported functions section                                                                     ;;
870
;;================================================================================================;;
871
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
872
;;================================================================================================;;
873
 
874
 
875
align 16
876
@IMPORT:
877
 
878
library \
845 mikedld 879
	libio , 'libio.obj'
717 mikedld 880
 
845 mikedld 881
import	libio			    , \
1102 diamond 882
	file.size   , 'file_size'   , \
883
	file.open   , 'file_open'   , \
884
	file.read   , 'file_read'   , \
885
	file.write  , 'file_write'  , \
886
	file.seek   , 'file_seek'   , \
887
	file.eof?   , 'file_iseof'  , \
888
	file.seteof , 'file_seteof' , \
889
	file.tell   , 'file_tell'   , \
890
	file.close  , 'file_close'
717 mikedld 891
 
892
 
893
;;================================================================================================;;
894
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
895
;;================================================================================================;;
896
;! Exported functions section                                                                     ;;
897
;;================================================================================================;;
898
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
899
;;================================================================================================;;
900
 
901
 
902
align 16
903
@EXPORT:
904
 
905
export						  \
845 mikedld 906
	libini._.init	  , 'lib_init'		, \
1327 diamond 907
	0x00080009	  , 'version'		, \
1102 diamond 908
	ini.enum_sections , 'ini_enum_sections' , \
909
	ini.enum_keys	  , 'ini_enum_keys'	, \
910
	ini.get_str	  , 'ini_get_str'	, \
911
	ini.get_int	  , 'ini_get_int'	, \
912
	ini.get_color	  , 'ini_get_color'	, \
913
	ini.set_str	  , 'ini_set_str'	, \
914
	ini.set_int	  , 'ini_set_int'	, \
1327 diamond 915
	ini.set_color	  , 'ini_set_color'	, \
916
	ini.get_shortcut  , 'ini_get_shortcut'