Subversion Repositories Kolibri OS

Rev

Rev 2603 | Rev 3131 | 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_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.         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. ;;------------------------------------------------------------------------------------------------;;
  175. ;? Enumerate keys within a section, calling callback function for each of them                    ;;
  176. ;;------------------------------------------------------------------------------------------------;;
  177. ;> _f_name = ini filename <asciiz>                                                                ;;
  178. ;> _sec_name = section name <asciiz>                                                              ;;
  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) <asciiz>                                   ;;
  181. ;>   sec_name = section name (as passed to the function) <asciiz>                                 ;;
  182. ;>   key_name = key name found <asciiz>                                                           ;;
  183. ;>   key_value = value of key found <asciiz>                                                      ;;
  184. ;;------------------------------------------------------------------------------------------------;;
  185. ;< eax = -1 (error) / 0                                                                           ;;
  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
  220.         stdcall libini._.find_section, ebx, [_sec_name]
  221.         or      eax, eax
  222.         jnz     .exit_error
  223.  
  224.   .next_key:
  225.         stdcall libini._.skip_line, [f_addr]
  226.         stdcall libini._.skip_nonblanks, [f_addr]
  227.         or      al, al
  228.         jz      .exit_error
  229.         cmp     al, '['
  230.         je      .exit_error
  231.         mov     edi, [key_buf]
  232.     @@: stdcall libini._.get_char, [f_addr]
  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
  248.     @@: stdcall libini._.low.read_value, [f_addr], [val_buf], ini.MAX_VALUE_LEN
  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. ;;------------------------------------------------------------------------------------------------;;
  277. ;? Read string                                                                                    ;;
  278. ;;------------------------------------------------------------------------------------------------;;
  279. ;> _f_name = ini filename <asciiz>                                                                ;;
  280. ;> _sec_name = section name <asciiz>                                                              ;;
  281. ;> _key_name = key name <asciiz>                                                                  ;;
  282. ;> _buffer = destination buffer address <byte*>                                                   ;;
  283. ;> _buf_len = buffer size (maximum bytes to read) <dword>                                         ;;
  284. ;> _def_val = default value to return if no key, section or file found <asciiz>                   ;;
  285. ;;------------------------------------------------------------------------------------------------;;
  286. ;< eax = -1 (error) / 0                                                                           ;;
  287. ;< [_buffer] = [_def_val] (error) / found key value <asciiz>                                      ;;
  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
  309.         stdcall libini._.find_section, ebx, [_sec_name]
  310.         or      eax, eax
  311.         jnz     .exit_error
  312.  
  313.         stdcall libini._.find_key, ebx, [_key_name]
  314.         or      eax, eax
  315.         jnz     .exit_error
  316.  
  317.         stdcall libini._.low.read_value, [f_addr], [_buffer], [_buf_len]
  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]
  327.         mov     edi, [_buffer]
  328.         mov     esi, [_def_val]
  329.         xor     al, al
  330.         or      esi, esi
  331.         jz      .exit_error.2
  332.     @@: lodsb
  333.   .exit_error.2:
  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. ;;------------------------------------------------------------------------------------------------;;
  345. ;? Write string                                                                                   ;;
  346. ;;------------------------------------------------------------------------------------------------;;
  347. ;> _f_name = ini filename <asciiz>                                                                ;;
  348. ;> _sec_name = section name <asciiz>                                                              ;;
  349. ;> _key_name = key name <asciiz>                                                                  ;;
  350. ;> _buffer = source buffer address <byte*>                                                        ;;
  351. ;> _buf_len = buffer size (bytes to write) <dword>                                                ;;
  352. ;;------------------------------------------------------------------------------------------------;;
  353. ;< eax = -1 (error) / 0                                                                           ;;
  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.  
  376.         stdcall libini._.find_section, ebx, [_sec_name]
  377.         or      eax, eax
  378.         jnz     .create_section
  379.  
  380.         stdcall libini._.find_key, ebx, [_key_name]
  381.         or      eax, eax
  382.         jnz     .create_key
  383.  
  384.   .modify_key:
  385.         stdcall libini._.get_value_length, [f_addr]
  386.         sub     eax, [_buf_len]
  387.         stdcall libini._.shift_content, [f_addr], eax
  388.  
  389.   .modify_key.ex:
  390.         invoke  file.tell, [f.fh]
  391.         sub     eax, [f.cnt]
  392.         invoke  file.seek, [f.fh], eax, SEEK_SET
  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]
  406.         call    libini._.string_copy
  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
  421.         stdcall libini._.shift_content, [f_addr], eax
  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
  433.         call    libini._.string_copy
  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. ;;------------------------------------------------------------------------------------------------;;
  448. ;? Read integer                                                                                   ;;
  449. ;;------------------------------------------------------------------------------------------------;;
  450. ;> _f_name = ini filename <asciiz>                                                                ;;
  451. ;> _sec_name = section name <asciiz>                                                              ;;
  452. ;> _key_name = key name <asciiz>                                                                  ;;
  453. ;> _def_val = default value to return if no key, section or file found <dword>                    ;;
  454. ;;------------------------------------------------------------------------------------------------;;
  455. ;< eax = [_def_val] (error) / found key value <dword>                                             ;;
  456. ;;================================================================================================;;
  457. locals
  458.   f      IniFile
  459.   f_addr dd ?
  460. endl
  461.  
  462.         push    edx 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
  477.         stdcall libini._.find_section, ebx, [_sec_name]
  478.         or      eax, eax
  479.         jnz     .exit_error
  480.  
  481.         stdcall libini._.find_key, ebx, [_key_name]
  482.         or      eax, eax
  483.         jnz     .exit_error
  484.  
  485.         stdcall libini._.skip_spaces, [f_addr]
  486.         xor     eax, eax
  487.         xor     ebx, ebx
  488.         xor     edx, edx
  489.         stdcall libini._.get_char, [f_addr]
  490.         cmp     al, '-'
  491.         jne     .lp1
  492.         inc     bh
  493.     @@: stdcall libini._.get_char, [f_addr]
  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 edx
  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 edx
  520.         ret
  521. endp
  522.  
  523. ;;================================================================================================;;
  524. proc ini.set_int _f_name, _sec_name, _key_name, _val ;////////////////////////////////////////////;;
  525. ;;------------------------------------------------------------------------------------------------;;
  526. ;? Write integer                                                                                  ;;
  527. ;;------------------------------------------------------------------------------------------------;;
  528. ;> _f_name = ini filename <asciiz>                                                                ;;
  529. ;> _sec_name = section name <asciiz>                                                              ;;
  530. ;> _key_name = key name <asciiz>                                                                  ;;
  531. ;> _val = value <dword>                                                                           ;;
  532. ;;------------------------------------------------------------------------------------------------;;
  533. ;< eax = -1 (error) / 0                                                                           ;;
  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.  
  568. ;;================================================================================================;;
  569. proc ini.get_color _f_name, _sec_name, _key_name, _def_val ;//////////////////////////////////////;;
  570. ;;------------------------------------------------------------------------------------------------;;
  571. ;? Read color                                                                                     ;;
  572. ;;------------------------------------------------------------------------------------------------;;
  573. ;> _f_name = ini filename <asciiz>                                                                ;;
  574. ;> _sec_name = section name <asciiz>                                                              ;;
  575. ;> _key_name = key name <asciiz>                                                                  ;;
  576. ;> _def_val = default value to return if no key, section or file found <dword>                    ;;
  577. ;;------------------------------------------------------------------------------------------------;;
  578. ;< eax = [_def_val] (error) / found key value <dword>                                             ;;
  579. ;;================================================================================================;;
  580. locals
  581.   buf rb 14
  582. endl
  583.  
  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.  
  617. ;;================================================================================================;;
  618. proc ini.set_color _f_name, _sec_name, _key_name, _val ;//////////////////////////////////////////;;
  619. ;;------------------------------------------------------------------------------------------------;;
  620. ;? Write color                                                                                    ;;
  621. ;;------------------------------------------------------------------------------------------------;;
  622. ;> _f_name = ini filename <asciiz>                                                                ;;
  623. ;> _sec_name = section name <asciiz>                                                              ;;
  624. ;> _key_name = key name <asciiz>                                                                  ;;
  625. ;> _val = value <dword>                                                                           ;;
  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.  
  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 <asciiz>                                                                ;;
  666. ;> _sec_name = section name <asciiz>                                                              ;;
  667. ;> _key_name = key name <asciiz>                                                                  ;;
  668. ;> _def_val = default value to return if no key, section or file found <dword>                    ;;
  669. ;> _modifiers = pointer to dword variable which receives modifiers state as in 66.4 <dword*>      ;;
  670. ;;------------------------------------------------------------------------------------------------;;
  671. ;< eax = [_def_val] (error) / shortcut key value as scancode <int>                                ;;
  672. ;< [[_modifiers]] = unchanged (error) / modifiers state for this shortcut <int>                   ;;
  673. ;;================================================================================================;;
  674. locals
  675.   buf rb 64
  676. endl
  677.  
  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<number>
  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.         jnz     .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.  
  866. ;;================================================================================================;;
  867. ;;////////////////////////////////////////////////////////////////////////////////////////////////;;
  868. ;;================================================================================================;;
  869. ;! Imported functions section                                                                     ;;
  870. ;;================================================================================================;;
  871. ;;////////////////////////////////////////////////////////////////////////////////////////////////;;
  872. ;;================================================================================================;;
  873.  
  874.  
  875. align 16
  876. @IMPORT:
  877.  
  878. library \
  879.         libio , 'libio.obj'
  880.  
  881. import  libio                       , \
  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'
  891.  
  892.  
  893. ;;================================================================================================;;
  894. ;;////////////////////////////////////////////////////////////////////////////////////////////////;;
  895. ;;================================================================================================;;
  896. ;! Exported functions section                                                                     ;;
  897. ;;================================================================================================;;
  898. ;;////////////////////////////////////////////////////////////////////////////////////////////////;;
  899. ;;================================================================================================;;
  900.  
  901.  
  902. align 16
  903. @EXPORT:
  904.  
  905. export                                            \
  906.         libini._.init     , 'lib_init'          , \
  907.         0x00080009        , 'version'           , \
  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'       , \
  915.         ini.set_color     , 'ini_set_color'     , \
  916.         ini.get_shortcut  , 'ini_get_shortcut'
  917.