Subversion Repositories Kolibri OS

Rev

Rev 3859 | Rev 4422 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  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 ;;
  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.                                         ;;
  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  ;;
  13. ;; Lesser General Public License for more details.                                                ;;
  14. ;;                                                                                                ;;
  15. ;; You should have received a copy of the GNU Lesser General Public License along with Libs-Dev.  ;;
  16. ;; If not, see <http://www.gnu.org/licenses/>.                                                    ;;
  17. ;;                                                                                                ;;
  18. ;;================================================================================================;;
  19. ;;                                                                                                ;;
  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                                                        ;;
  26. ;; 2008-12-29 (mike.dld)                                                                          ;;
  27. ;;   bug-fixes:                                                                                   ;;
  28. ;;     - unnecessary 'stosb' in ini.get_str was causing problems                                  ;;
  29. ;;   new features:                                                                                ;;
  30. ;;     - new functions: ini.get_color and ini.set_color                                           ;;
  31. ;; 2008-08-06 (mike.dld)                                                                          ;;
  32. ;;   changes:                                                                                     ;;
  33. ;;     - split private procs into libini_p.asm, added comments                                    ;;
  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'
  67. purge section,mov,add,sub
  68.  
  69. include 'libini_p.inc'
  70.  
  71. section '.flat' code readable align 16
  72.  
  73. include 'libini_p.asm'
  74.  
  75. ;;================================================================================================;;
  76. proc ini.enum_sections _f_name, _callback ;///////////////////////////////////////////////////////;;
  77. ;;------------------------------------------------------------------------------------------------;;
  78. ;? Enumerate sections, calling callback function for each of them                                 ;;
  79. ;;------------------------------------------------------------------------------------------------;;
  80. ;> _f_name = ini filename <asciiz>                                                                ;;
  81. ;> _callback = callback function address: func(f_name, sec_name), where                           ;;
  82. ;>   f_name = ini filename (as passed to the function) <asciiz>                                   ;;
  83. ;>   sec_name = section name found <asciiz>                                                       ;;
  84. ;;------------------------------------------------------------------------------------------------;;
  85. ;< eax = -1 (error) / 0                                                                           ;;
  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_file_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.  
  116.         invoke  file.seek, [f.fh], 0, SEEK_SET
  117.         stdcall libini._.preload_block, [f_addr]
  118.  
  119.   .next_section:
  120.         stdcall libini._.find_next_section, [f_addr]
  121.         or      eax, eax
  122.         jnz     .exit_error
  123.  
  124.         stdcall libini._.get_char, [f_addr]
  125.         stdcall libini._.skip_spaces, [f_addr]
  126.         mov     edi, [sec_buf]
  127.     @@: stdcall libini._.get_char, [f_addr]
  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.   .exit_file_error:
  166.         invoke  mem.free, [sec_buf]
  167.   .exit_error.2:
  168.         or      eax, -1
  169.         pop     edi esi ebx
  170.         ret
  171. endp
  172.  
  173. ;;================================================================================================;;
  174. proc ini.enum_keys _f_name, _sec_name, _callback ;////////////////////////////////////////////////;;
  175. ;;------------------------------------------------------------------------------------------------;;
  176. ;? Enumerate keys within a section, calling callback function for each of them                    ;;
  177. ;;------------------------------------------------------------------------------------------------;;
  178. ;> _f_name = ini filename <asciiz>                                                                ;;
  179. ;> _sec_name = section name <asciiz>                                                              ;;
  180. ;> _callback = callback function address: func(f_name, sec_name, key_name, key_value), where      ;;
  181. ;>   f_name = ini filename (as passed to the function) <asciiz>                                   ;;
  182. ;>   sec_name = section name (as passed to the function) <asciiz>                                 ;;
  183. ;>   key_name = key name found <asciiz>                                                           ;;
  184. ;>   key_value = value of key found <asciiz>                                                      ;;
  185. ;;------------------------------------------------------------------------------------------------;;
  186. ;< eax = -1 (error) / 0                                                                           ;;
  187. ;;================================================================================================;;
  188. locals
  189.   f       IniFile
  190.   f_addr  dd ?
  191.   key_buf dd ?
  192.   val_buf dd ?
  193. endl
  194.  
  195.         push    ebx esi edi
  196.  
  197.         cld
  198.  
  199.         invoke  mem.alloc, ini.MAX_NAME_LEN
  200.         or      eax, eax
  201.         jz      .exit_error.3
  202.         mov     [key_buf], eax
  203.         invoke  mem.alloc, ini.MAX_VALUE_LEN
  204.         or      eax, eax
  205.         jz      .exit_error.2
  206.         mov     [val_buf], eax
  207.  
  208.         xor     eax, eax
  209.         mov     [f.fh], eax
  210.         mov     [f.buf], eax
  211.         invoke  file.open, [_f_name], O_READ
  212.         cmp     eax, 32
  213.         jb      .exit_file_error
  214.         mov     [f.fh], eax
  215.         invoke  mem.alloc, ini.MEM_SIZE
  216.         or      eax, eax
  217.         jz      .exit_error
  218.         mov     [f.buf], eax
  219.         lea     ebx, [f]
  220.         mov     [f_addr], ebx
  221.         stdcall libini._.find_section, ebx, [_sec_name]
  222.         or      eax, eax
  223.         jnz     .exit_error
  224.  
  225.   .next_key:
  226.         stdcall libini._.skip_line, [f_addr]
  227.         stdcall libini._.skip_nonblanks, [f_addr]
  228.         or      al, al
  229.         jz      .exit_error
  230.         cmp     al, '['
  231.         je      .exit_error
  232.         mov     edi, [key_buf]
  233.     @@: stdcall libini._.get_char, [f_addr]
  234.         or      al, al
  235.         jz      .exit_error
  236.         cmp     al, '='
  237.         je      @f
  238.         stosb
  239.         jmp     @b
  240.     @@:
  241.         xor     al, al
  242.         stosb
  243.         add     edi, -2
  244.     @@: cmp     byte[edi], 32
  245.         ja      @f
  246.         mov     byte[edi], 0
  247.         dec     edi
  248.         jmp     @b
  249.     @@: stdcall libini._.low.read_value, [f_addr], [val_buf], ini.MAX_VALUE_LEN
  250.         pushad
  251.         stdcall [_callback], [_f_name], [_sec_name], [key_buf], [val_buf]
  252.         or      eax, eax
  253.         popad
  254.         jnz     .next_key
  255.  
  256.     @@: invoke  file.close, [f.fh]
  257.         invoke  mem.free, [f.buf]
  258.         xor     eax, eax
  259.         stosb
  260.         pop     edi esi ebx
  261.         ret
  262.  
  263.   .exit_error:
  264.         invoke  file.close, [f.fh]
  265.         invoke  mem.free, [f.buf]
  266.   .exit_file_error:
  267.         invoke  mem.free, [val_buf]
  268.   .exit_error.2:
  269.         invoke  mem.free, [key_buf]
  270.   .exit_error.3:
  271.         or      eax, -1
  272.         pop     edi esi ebx
  273.         ret
  274. endp
  275.  
  276. ;;================================================================================================;;
  277. proc ini.get_str _f_name, _sec_name, _key_name, _buffer, _buf_len, _def_val ;/////////////////////;;
  278. ;;------------------------------------------------------------------------------------------------;;
  279. ;? Read string                                                                                    ;;
  280. ;;------------------------------------------------------------------------------------------------;;
  281. ;> _f_name = ini filename <asciiz>                                                                ;;
  282. ;> _sec_name = section name <asciiz>                                                              ;;
  283. ;> _key_name = key name <asciiz>                                                                  ;;
  284. ;> _buffer = destination buffer address <byte*>                                                   ;;
  285. ;> _buf_len = buffer size (maximum bytes to read) <dword>                                         ;;
  286. ;> _def_val = default value to return if no key, section or file found <asciiz>                   ;;
  287. ;;------------------------------------------------------------------------------------------------;;
  288. ;< eax = -1 (error) / 0                                                                           ;;
  289. ;< [_buffer] = [_def_val] (error) / found key value <asciiz>                                      ;;
  290. ;;================================================================================================;;
  291. locals
  292.   f      IniFile
  293.   f_addr dd ?
  294. endl
  295.  
  296.         push    ebx esi edi
  297.  
  298.         xor     eax, eax
  299.         mov     [f.fh], eax
  300.         mov     [f.buf], eax
  301.         invoke  file.open, [_f_name], O_READ
  302.         cmp     eax, 32
  303.         jb      .exit_file_error
  304.         mov     [f.fh], eax
  305.         invoke  mem.alloc, ini.MEM_SIZE
  306.         or      eax, eax
  307.         jz      .exit_error
  308.         mov     [f.buf], eax
  309.         lea     ebx, [f]
  310.         mov     [f_addr], ebx
  311.         stdcall libini._.find_section, ebx, [_sec_name]
  312.         or      eax, eax
  313.         jnz     .exit_error
  314.  
  315.         stdcall libini._.find_key, ebx, [_key_name]
  316.         or      eax, eax
  317.         jnz     .exit_error
  318.  
  319.         stdcall libini._.low.read_value, [f_addr], [_buffer], [_buf_len]
  320.     @@: invoke  file.close, [f.fh]
  321.         invoke  mem.free, [f.buf]
  322.         xor     eax, eax
  323.         pop     edi esi ebx
  324.         ret
  325.  
  326.   .exit_error:
  327.         invoke  file.close, [f.fh]
  328.         invoke  mem.free, [f.buf]
  329.   .exit_file_error:
  330.         mov     edi, [_buffer]
  331.         mov     esi, [_def_val]
  332.         xor     al, al
  333.         or      esi, esi
  334.         jz      .exit_error.2
  335.     @@: lodsb
  336.   .exit_error.2:
  337.         stosb
  338.         or      al, al
  339.         jnz     @b
  340.         or      eax, -1
  341.         pop     edi esi ebx
  342.         ret
  343. endp
  344.  
  345. ;;================================================================================================;;
  346. proc ini.set_str _f_name, _sec_name, _key_name, _buffer, _buf_len ;///////////////////////////////;;
  347. ;;------------------------------------------------------------------------------------------------;;
  348. ;? Write string                                                                                   ;;
  349. ;;------------------------------------------------------------------------------------------------;;
  350. ;> _f_name = ini filename <asciiz>                                                                ;;
  351. ;> _sec_name = section name <asciiz>                                                              ;;
  352. ;> _key_name = key name <asciiz>                                                                  ;;
  353. ;> _buffer = source buffer address <byte*>                                                        ;;
  354. ;> _buf_len = buffer size (bytes to write) <dword>                                                ;;
  355. ;;------------------------------------------------------------------------------------------------;;
  356. ;< eax = -1 (error) / 0                                                                           ;;
  357. ;;================================================================================================;;
  358. locals
  359.   f      IniFile
  360.   f_addr dd ?
  361. endl
  362.  
  363.         push    ebx esi edi
  364.  
  365.         xor     eax, eax
  366.         mov     [f.fh], eax
  367.         mov     [f.buf], eax
  368.         invoke  file.open, [_f_name], O_READ + O_WRITE + O_CREATE
  369.         cmp     eax, 32
  370.         jb      .exit_file_error
  371.         mov     [f.fh], eax
  372.         invoke  mem.alloc, ini.MEM_SIZE
  373.         or      eax, eax
  374.         jz      .exit_error
  375.         mov     [f.buf], eax
  376.         lea     ebx, [f]
  377.         mov     [f_addr], ebx
  378.  
  379.         stdcall libini._.find_section, ebx, [_sec_name]
  380.         or      eax, eax
  381.         jnz     .create_section
  382.  
  383.         stdcall libini._.find_key, ebx, [_key_name]
  384.         or      eax, eax
  385.         jnz     .create_key
  386.  
  387.   .modify_key:
  388.         stdcall libini._.get_value_length, [f_addr]
  389.         sub     eax, [_buf_len]
  390.         stdcall libini._.shift_content, [f_addr], eax
  391.  
  392.   .modify_key.ex:
  393.         invoke  file.tell, [f.fh]
  394.         sub     eax, [f.cnt]
  395.         invoke  file.seek, [f.fh], eax, SEEK_SET
  396.         invoke  file.write, [f.fh], [_buffer], [_buf_len]
  397.  
  398.         invoke  file.close, [f.fh]
  399.         pop     edi esi ebx
  400.         mcall   68,13,[f.buf]
  401.         xor     eax, eax
  402.         ret
  403.  
  404.   .create_key:
  405.         mov     edi, [f.buf]
  406.         add     edi, ini.BLOCK_SIZE
  407.         push    edi
  408.  
  409.   .create_key.ex:
  410.         mov     esi, [_key_name]
  411.         call    libini._.string_copy
  412.         mov     byte[edi], '='
  413.         inc     edi
  414.         mov     esi, [_buffer]
  415.         mov     ecx, [_buf_len]
  416.         rep     movsb
  417.         mov     word[edi], 0x0A0D
  418.         add     edi, 2
  419.         mov     eax, edi
  420.  
  421.         pop     edi
  422.         sub     eax, edi
  423.         mov     [_buffer], edi
  424.         mov     [_buf_len], eax
  425.         neg     eax
  426.         stdcall libini._.shift_content, [f_addr], eax
  427.  
  428.         jmp     .modify_key.ex
  429.  
  430.   .create_section:
  431.         mov     edi, [f.buf]
  432.         add     edi, ini.BLOCK_SIZE
  433.         push    edi
  434.  
  435.         mov     esi, [_sec_name]
  436.         mov     byte[edi], '['
  437.         inc     edi
  438.         call    libini._.string_copy
  439.         mov     dword[edi], ']' + (0x0A0D shl 8)
  440.         add     edi, 3
  441.  
  442.         jmp     .create_key.ex
  443.  
  444.   .exit_error:
  445.         invoke  file.close, [f.fh]
  446.   .exit_file_error:
  447.         pop     edi esi ebx
  448.         or      eax, -1
  449.         ret
  450. endp
  451.  
  452. ;;================================================================================================;;
  453. proc ini.get_int _f_name, _sec_name, _key_name, _def_val ;////////////////////////////////////////;;
  454. ;;------------------------------------------------------------------------------------------------;;
  455. ;? Read integer                                                                                   ;;
  456. ;;------------------------------------------------------------------------------------------------;;
  457. ;> _f_name = ini filename <asciiz>                                                                ;;
  458. ;> _sec_name = section name <asciiz>                                                              ;;
  459. ;> _key_name = key name <asciiz>                                                                  ;;
  460. ;> _def_val = default value to return if no key, section or file found <dword>                    ;;
  461. ;;------------------------------------------------------------------------------------------------;;
  462. ;< eax = [_def_val] (error) / found key value <dword>                                             ;;
  463. ;;================================================================================================;;
  464. locals
  465.   f      IniFile
  466.   f_addr dd ?
  467. endl
  468.  
  469.         push    edx ebx esi edi
  470.  
  471.         xor     eax, eax
  472.         mov     [f.fh], eax
  473.         mov     [f.buf], eax
  474.         invoke  file.open, [_f_name], O_READ
  475.         cmp     eax, 32
  476.         jb      .exit_file_error
  477.         mov     [f.fh], eax
  478.         invoke  mem.alloc, ini.MEM_SIZE
  479.         or      eax, eax
  480.         jz      .exit_error
  481.         mov     [f.buf], eax
  482.         lea     ebx, [f]
  483.         mov     [f_addr], ebx
  484.         stdcall libini._.find_section, ebx, [_sec_name]
  485.         or      eax, eax
  486.         jnz     .exit_error
  487.  
  488.         stdcall libini._.find_key, ebx, [_key_name]
  489.         or      eax, eax
  490.         jnz     .exit_error
  491.  
  492.         stdcall libini._.skip_spaces, [f_addr]
  493.         xor     eax, eax
  494.         xor     ebx, ebx
  495.         xor     edx, edx
  496.         stdcall libini._.get_char, [f_addr]
  497.         cmp     al, '-'
  498.         jne     .lp1
  499.         inc     bh
  500.     @@: stdcall libini._.get_char, [f_addr]
  501.   .lp1: cmp     al, '0'
  502.         jb      @f
  503.         cmp     al, '9'
  504.         ja      @f
  505.         inc     bl
  506.         add     eax, -'0'
  507.         imul    edx, 10
  508.         add     edx, eax
  509.         jmp     @b
  510.     @@:
  511.         or      bl, bl
  512.         jz      .exit_error
  513.         or      bh, bh
  514.         jz      @f
  515.         neg     edx
  516.     @@: invoke  file.close, [f.fh]
  517.         invoke  mem.free, [f.buf]
  518.         mov     eax, edx
  519.         pop     edi esi ebx edx
  520.         ret
  521.  
  522.   .exit_error:
  523.         invoke  file.close, [f.fh]
  524.   .exit_file_error:
  525.         invoke  mem.free, [f.buf]
  526.         mov     eax, [_def_val]
  527.         pop     edi esi ebx edx
  528.         ret
  529. endp
  530.  
  531. ;;================================================================================================;;
  532. proc ini.set_int _f_name, _sec_name, _key_name, _val ;////////////////////////////////////////////;;
  533. ;;------------------------------------------------------------------------------------------------;;
  534. ;? Write integer                                                                                  ;;
  535. ;;------------------------------------------------------------------------------------------------;;
  536. ;> _f_name = ini filename <asciiz>                                                                ;;
  537. ;> _sec_name = section name <asciiz>                                                              ;;
  538. ;> _key_name = key name <asciiz>                                                                  ;;
  539. ;> _val = value <dword>                                                                           ;;
  540. ;;------------------------------------------------------------------------------------------------;;
  541. ;< eax = -1 (error) / 0                                                                           ;;
  542. ;;================================================================================================;;
  543. locals
  544.   buf rb 16
  545.   bNeg rd 1
  546. endl
  547.  
  548.         push    ecx edx edi
  549.  
  550.         lea     edi, [buf]
  551.         add     edi, 15
  552.  
  553.         mov     eax, [_val]
  554.         mov     [bNeg],0
  555.         or      eax, eax
  556.         jns     @f
  557.         mov     [bNeg],1
  558.         neg     eax
  559.  
  560.     @@: mov     ecx, 10
  561.     @@: xor     edx, edx
  562.         idiv    ecx
  563.         add     dl, '0'
  564.         mov     [edi], dl
  565.         dec     edi
  566.         or      eax, eax
  567.         jnz     @b
  568.  
  569.         cmp     [bNeg],0
  570.         je      @f
  571.         mov     byte[edi], '-'
  572.         dec     edi
  573.      @@:
  574.         lea     eax, [buf]
  575.         add     eax, 15
  576.         sub     eax, edi
  577.         inc     edi
  578.  
  579.  
  580.  
  581.         stdcall ini.set_str, [_f_name], [_sec_name], [_key_name], edi, eax
  582.  
  583.         pop     edi edx ecx
  584.         ret
  585. endp
  586.  
  587. ;;================================================================================================;;
  588. proc ini.get_color _f_name, _sec_name, _key_name, _def_val ;//////////////////////////////////////;;
  589. ;;------------------------------------------------------------------------------------------------;;
  590. ;? Read color                                                                                     ;;
  591. ;;------------------------------------------------------------------------------------------------;;
  592. ;> _f_name = ini filename <asciiz>                                                                ;;
  593. ;> _sec_name = section name <asciiz>                                                              ;;
  594. ;> _key_name = key name <asciiz>                                                                  ;;
  595. ;> _def_val = default value to return if no key, section or file found <dword>                    ;;
  596. ;;------------------------------------------------------------------------------------------------;;
  597. ;< eax = [_def_val] (error) / found key value <dword>                                             ;;
  598. ;;================================================================================================;;
  599. locals
  600.   buf rb 14
  601. endl
  602.  
  603.         push    ebx esi edi
  604.  
  605.         lea     esi, [buf]
  606.         stdcall ini.get_str, [_f_name], [_sec_name], [_key_name], esi, 14, 0
  607.         cmp     byte[esi],0
  608.         je      .exit_error
  609.  
  610.         xor     ebx, ebx
  611.         stdcall libini._.str_to_int
  612.         movzx   ebx, al
  613.         shl     ebx, 16
  614.         lodsb
  615.         cmp     al, ','
  616.         jne     @f
  617.         stdcall libini._.str_to_int
  618.         mov     bh, al
  619.         lodsb
  620.         cmp     al, ','
  621.         jne     @f
  622.         stdcall libini._.str_to_int
  623.         mov     bl, al
  624.  
  625.     @@: mov     eax, ebx
  626.  
  627.         pop     edi esi ebx
  628.         ret
  629.  
  630.   .exit_error:
  631.         mov     eax, [_def_val]
  632.         pop     edi esi ebx
  633.         ret
  634. endp
  635.  
  636. ;;================================================================================================;;
  637. proc ini.set_color _f_name, _sec_name, _key_name, _val ;//////////////////////////////////////////;;
  638. ;;------------------------------------------------------------------------------------------------;;
  639. ;? Write color                                                                                    ;;
  640. ;;------------------------------------------------------------------------------------------------;;
  641. ;> _f_name = ini filename <asciiz>                                                                ;;
  642. ;> _sec_name = section name <asciiz>                                                              ;;
  643. ;> _key_name = key name <asciiz>                                                                  ;;
  644. ;> _val = value <dword>                                                                           ;;
  645. ;;------------------------------------------------------------------------------------------------;;
  646. ;< eax = -1 (error) / 0                                                                           ;;
  647. ;;================================================================================================;;
  648. locals
  649.   buf rb 16
  650. endl
  651.  
  652.         push    ecx edx edi
  653.  
  654.         lea     edi, [buf]
  655.         mov     ecx, 10
  656.         mov     ebx, [_val]
  657.         mov     eax, ebx
  658.         shr     eax, 16
  659.         and     eax, 0x0ff
  660.         stdcall libini._.int_to_str
  661.         mov     byte[edi], ','
  662.         inc     edi
  663.         movzx   eax, bh
  664.         stdcall libini._.int_to_str
  665.         mov     byte[edi], ','
  666.         inc     edi
  667.         movzx   eax, bl
  668.         stdcall libini._.int_to_str
  669.  
  670.         lea     eax, [buf]
  671.         sub     edi, eax
  672.  
  673.         stdcall ini.set_str, [_f_name], [_sec_name], [_key_name], eax, edi
  674.  
  675.         pop     edi edx ecx
  676.         ret
  677. endp
  678.  
  679.  
  680. ;;================================================================================================;;
  681. proc ini.del_section _f_name, _sec_name ;/////////////////////////////////////////////////////////;;
  682. ;;------------------------------------------------------------------------------------------------;;
  683. ;? Delete section and all key in this section                                                     ;;
  684. ;;------------------------------------------------------------------------------------------------;;
  685. ;> _f_name = ini filename <asciiz>                                                                ;;
  686. ;> _sec_name = section name <asciiz>                                                              ;;
  687. ;;------------------------------------------------------------------------------------------------;;
  688. ;< eax = 0 - success                                                                              ;;
  689. ;<      -1 - file not found                                                                       ;;
  690. ;<       1 - section not found                                                                    ;;
  691. ;;================================================================================================;;
  692. locals
  693.    funcFile     rb 25
  694.    fileInfo     rb 40
  695.    begMem       rd 1
  696.    endMem       rd 1
  697.    begDel       rd 1
  698.    endDel       rd 1
  699. endl
  700.         push    ebx ecx edi esi
  701.         mov     dword[funcFile],5               ;get file info
  702.         mov     dword[funcFile+4],0
  703.         mov     dword[funcFile+8],0
  704.         mov     dword[funcFile+12],0
  705.         lea     eax,[fileInfo]
  706.         mov     dword[funcFile+16],eax
  707.         mov     byte[funcFile+20],0
  708.         m2m     dword[funcFile+21],[_f_name]
  709.         lea     ebx,[funcFile]
  710.         mcall   70
  711.         test    eax,eax
  712.         jz      @f
  713.  
  714.         or      eax,-1
  715.         pop     esi edi ecx ebx
  716.         ret
  717.       @@:
  718.  
  719.         mov     ecx,dword[fileInfo+32]          ;allocation mem for all file
  720.         mcall   68,12
  721.  
  722.         mov     [begMem],eax
  723.         mov     [endMem],eax
  724.         add     [endMem],ecx
  725.  
  726.         mov     dword[funcFile],0               ;read file to buffer
  727.         mov     dword[funcFile+12],ecx
  728.         mov     dword[funcFile+16],eax
  729.         lea     ebx,[funcFile]
  730.         mcall   70
  731.  
  732.         mov     edi,[begMem]                    ;search begin section
  733.         jmp     .searchSect
  734.     .NoFindSect:
  735.         mov     edi,[begDel]
  736.     .searchSect:
  737.         mov     al,'['
  738.         repne   scasb
  739.         test    ecx,ecx
  740.         jnz     @f
  741.  
  742.         pop     esi edi ecx ebx
  743.         mov     eax,1
  744.         ret
  745.       @@:
  746.         mov     [begDel],edi
  747.         mov     esi,[_sec_name]
  748.       @@:
  749.         lodsb
  750.         test    al,al
  751.         jz      @f
  752.         scasb
  753.         jne     .NoFindSect
  754.         jmp     @b
  755.       @@:
  756.         cmp     byte[edi],']'
  757.         jne     .NoFindSect
  758.  
  759.         mov     edi,[begDel]
  760.         dec     [begDel]
  761.                                        ;search end section
  762.     .searchEndSect:
  763.         mov     al,'['
  764.         repne   scasb
  765.  
  766.         dec     edi
  767.         mov     [endDel],edi
  768.  
  769.         test    ecx,ecx
  770.         jnz     @f
  771.         jmp     .SaveToFile
  772.       @@:
  773.  
  774.  
  775.         mov     esi,[endDel]
  776.         mov     edi,[begDel]
  777.    @@:  lodsb
  778.         stosb
  779.         cmp     esi,[endMem]
  780.         jb      @b
  781.  
  782.    .SaveToFile:
  783.         mov     eax,dword[funcFile+12]
  784.         sub     eax,[endDel]
  785.         add     eax,[begDel]
  786.         dec     eax
  787.  
  788.         mov     dword[funcFile],2               ;write buffer to file
  789.         mov     dword[funcFile+12],eax
  790.         m2m     dword[funcFile+16],[begMem]
  791.         lea     ebx,[funcFile]
  792.         mcall   70
  793.  
  794.         mcall   68,13,[begMem]
  795.  
  796.         xor     eax,eax
  797.         pop     esi edi ecx ebx
  798.         ret
  799. endp
  800.  
  801.  
  802.  
  803.  
  804. ;;================================================================================================;;
  805. proc ini.get_shortcut _f_name, _sec_name, _key_name, _def_val, _modifiers ;///////////////////////;;
  806. ;;------------------------------------------------------------------------------------------------;;
  807. ;? Read shortcut key                                                                              ;;
  808. ;;------------------------------------------------------------------------------------------------;;
  809. ;> _f_name = ini filename <asciiz>                                                                ;;
  810. ;> _sec_name = section name <asciiz>                                                              ;;
  811. ;> _key_name = key name <asciiz>                                                                  ;;
  812. ;> _def_val = default value to return if no key, section or file found <dword>                    ;;
  813. ;> _modifiers = pointer to dword variable which receives modifiers state as in 66.4 <dword*>      ;;
  814. ;;------------------------------------------------------------------------------------------------;;
  815. ;< eax = [_def_val] (error) / shortcut key value as scancode <int>                                ;;
  816. ;< [[_modifiers]] = unchanged (error) / modifiers state for this shortcut <int>                   ;;
  817. ;;================================================================================================;;
  818. locals
  819.   buf rb 64
  820. endl
  821.  
  822.         push    ebx esi edi
  823.  
  824.         lea     esi, [buf]
  825.         stdcall ini.get_str, [_f_name], [_sec_name], [_key_name], esi, 64, 0
  826.         cmp     byte[esi],0
  827.         je      .exit_error
  828.  
  829.         xor     ebx, ebx        ; ebx holds the value of modifiers
  830. .loop:
  831. ; test for end
  832.         xor     eax, eax
  833.         cmp     byte [esi], al
  834.         jz      .exit_ok        ; exit with scancode zero
  835. ; skip all '+'s
  836.         cmp     byte [esi], '+'
  837.         jnz     @f
  838.         inc     esi
  839.         jmp     .loop
  840. @@:
  841. ; test for names
  842.         mov     edi, .names_table
  843.         xor     edx, edx
  844. .names_loop:
  845.         movzx   ecx, byte [edi]
  846.         inc     edi
  847.         push    esi
  848. @@:
  849.         lodsb
  850.         or      al, 20h
  851.         scasb
  852.         loopz   @b
  853.         jz      .name_found
  854.         pop     esi
  855.         lea     edi, [edi+ecx+4]
  856.         inc     edx
  857.         cmp     byte [edi], 0
  858.         jnz     .names_loop
  859. ; special test: functional keys F<number>
  860.         cmp     byte [esi], 'f'
  861.         jz      @f
  862.         cmp     byte [esi], 'F'
  863.         jnz     .no_fx
  864. @@:
  865.         mov     edi, esi
  866.         inc     esi
  867.         call    libini._.str_to_int
  868.         test    eax, eax
  869.         jnz     .fx
  870.         mov     esi, edi
  871. .no_fx:
  872. ; name not found, that must be usual key
  873.         movzx   eax, byte [esi]
  874.         stdcall libini._.ascii_to_scan, eax
  875.         test    eax, eax
  876.         jz      .exit_error
  877. ; all is ok
  878. .exit_ok:
  879.         mov     ecx, [_modifiers]
  880.         test    ecx, ecx
  881.         jz      @f
  882.         mov     [ecx], ebx
  883.  
  884. @@:
  885.  
  886.         pop     edi esi ebx
  887.         ret
  888.  
  889. .exit_error:
  890.         mov     eax, [_def_val]
  891.         pop     edi esi ebx
  892.         ret
  893. ; handler for Fx
  894. ; eax = number
  895. .fx:
  896.         cmp     eax, 10
  897.         ja      @f
  898.         add     eax, 3Bh-1
  899.         jmp     .exit_ok
  900. @@:
  901.         add     eax, 57h-11
  902.         jmp     .exit_ok
  903. ; handlers for names
  904. .name_found:
  905.         pop     eax     ; ignore saved esi
  906.         call    dword [edi]
  907.         cmp     edx, .num_modifiers
  908.         jae     .exit_ok
  909.         jmp     .loop
  910. ; modifiers
  911. ; syntax of value for each modifier:
  912. ; 0 = none, 1 = exactly one of L+R, 2 = both L+R, 3 = L, 4 = R
  913. ; Logic for switching: LShift+RShift=LShift+Shift=Shift+Shift, LShift+LShift=LShift
  914. ; generic modifier: 0->1->2->2, 3->2, 4->2
  915. ; left modifier: 0->3->3, 1->2->2, 4->2
  916. ; right modifier: 0->4->4, 1->2->2, 3->2
  917. ; Shift corresponds to first hex digit, Ctrl - second, Alt - third
  918. macro shortcut_handle_modifiers name,reg,shift
  919. {
  920. local .set2,.set3,.set4
  921. .#name#_handler:        ; generic modifier
  922.         test    reg, 0xF
  923.         jnz     .set2
  924. if shift
  925.         or      reg, 1 shl shift
  926. else
  927.         inc     reg
  928. end if
  929.         retn
  930. .set2:
  931.         and     reg, not (0xF shl shift)
  932.         or      reg, 2 shl shift
  933.         retn
  934. .l#name#_handler:
  935.         mov     al, reg
  936.         and     al, 0xF shl shift
  937.         jz      .set3
  938.         cmp     al, 3 shl shift
  939.         jnz     .set2
  940.         retn
  941. .set3:
  942.         add     reg, 3 shl shift
  943.         retn
  944. .r#name#_handler:
  945.         mov     al, reg
  946.         and     al, 0xF shl shift
  947.         jz      .set4
  948.         cmp     al, 4 shl shift
  949.         jnz     .set2
  950.         retn
  951. .set4:
  952.         add     reg, 4 shl shift
  953.         retn
  954. }
  955. shortcut_handle_modifiers shift,bl,0
  956. shortcut_handle_modifiers ctrl,bl,4
  957. shortcut_handle_modifiers alt,bh,0
  958. ; names of keys
  959. .name_handler:
  960.         movzx   eax, byte [.names_scancodes+edx-.num_modifiers]
  961.         retn
  962. endp
  963.  
  964. ; note: comparison ignores case, so this table keeps lowercase names
  965. ; macro does this
  966. macro shortcut_name_with_handler name,handler
  967. {
  968. local .start, .end
  969.         db      .end - .start
  970. .start:
  971.         db      name
  972. .end:
  973. repeat .end - .start
  974.         load .a byte from .start + % - 1
  975.         store byte .a or 0x20 at .start + % - 1
  976. end repeat
  977.         dd      handler
  978. }
  979. macro shortcut_name [name]
  980. {
  981.         shortcut_name_with_handler name, .name_handler
  982. }
  983.  
  984. ; all names here must be in english
  985. ; ... or modify lowercasing in macro and in comparison
  986. .names_table:
  987. ; generic modifiers
  988.         shortcut_name_with_handler 'Ctrl', .ctrl_handler
  989.         shortcut_name_with_handler 'Alt', .alt_handler
  990.         shortcut_name_with_handler 'Shift', .shift_handler
  991. ; concrete modifiers
  992.         shortcut_name_with_handler 'LCtrl', .lctrl_handler
  993.         shortcut_name_with_handler 'RCtrl', .rctrl_handler
  994.         shortcut_name_with_handler 'LAlt', .lalt_handler
  995.         shortcut_name_with_handler 'RAlt', .ralt_handler
  996.         shortcut_name_with_handler 'LShift', .lshift_handler
  997.         shortcut_name_with_handler 'RShift', .rshift_handler
  998. .num_modifiers = 9
  999. ; symbolic names of keys
  1000.         shortcut_name 'Home', 'End', 'PgUp', 'PgDn', 'Ins', 'Insert', 'Del', 'Delete'
  1001.         shortcut_name 'Tab', 'Plus', 'Esc', 'Enter', 'Backspace', 'Space', 'Left', 'Right'
  1002.         shortcut_name 'Up', 'Down'
  1003. ; end of table
  1004.         db      0
  1005. ini.get_shortcut.names_scancodes:
  1006. ; scancodes for 'Home' ... 'Down'
  1007.         db      47h, 4Fh, 49h, 51h, 52h, 52h, 53h, 53h
  1008.         db      0Fh, 4Eh, 01h, 1Ch, 0Eh, 39h, 4Bh, 4Dh
  1009.         db      48h, 50h
  1010.  
  1011. ;;================================================================================================;;
  1012. ;;////////////////////////////////////////////////////////////////////////////////////////////////;;
  1013. ;;================================================================================================;;
  1014. ;! Imported functions section                                                                     ;;
  1015. ;;================================================================================================;;
  1016. ;;////////////////////////////////////////////////////////////////////////////////////////////////;;
  1017. ;;================================================================================================;;
  1018.  
  1019.  
  1020. align 16
  1021. @IMPORT:
  1022.  
  1023. library \
  1024.         libio , 'libio.obj'
  1025.  
  1026. import  libio                       , \
  1027.         file.size   , 'file_size'   , \
  1028.         file.open   , 'file_open'   , \
  1029.         file.read   , 'file_read'   , \
  1030.         file.write  , 'file_write'  , \
  1031.         file.seek   , 'file_seek'   , \
  1032.         file.eof?   , 'file_iseof'  , \
  1033.         file.seteof , 'file_seteof' , \
  1034.         file.tell   , 'file_tell'   , \
  1035.         file.close  , 'file_close'
  1036.  
  1037.  
  1038. ;;================================================================================================;;
  1039. ;;////////////////////////////////////////////////////////////////////////////////////////////////;;
  1040. ;;================================================================================================;;
  1041. ;! Exported functions section                                                                     ;;
  1042. ;;================================================================================================;;
  1043. ;;////////////////////////////////////////////////////////////////////////////////////////////////;;
  1044. ;;================================================================================================;;
  1045.  
  1046.  
  1047. align 16
  1048. @EXPORT:
  1049.  
  1050. export                                            \
  1051.         libini._.init     , 'lib_init'          , \
  1052.         0x00080009        , 'version'           , \
  1053.         ini.enum_sections , 'ini_enum_sections' , \
  1054.         ini.enum_keys     , 'ini_enum_keys'     , \
  1055.         ini.get_str       , 'ini_get_str'       , \
  1056.         ini.get_int       , 'ini_get_int'       , \
  1057.         ini.get_color     , 'ini_get_color'     , \
  1058.         ini.set_str       , 'ini_set_str'       , \
  1059.         ini.set_int       , 'ini_set_int'       , \
  1060.         ini.set_color     , 'ini_set_color'     , \
  1061.         ini.get_shortcut  , 'ini_get_shortcut'  , \
  1062.         ini.del_section   , 'ini_del_section'
  1063.