Subversion Repositories Kolibri OS

Rev

Rev 3131 | Rev 3859 | 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.         xor     eax, eax
  401.         ret
  402.  
  403.   .create_key:
  404.         mov     edi, [f.buf]
  405.         add     edi, ini.BLOCK_SIZE
  406.         push    edi
  407.  
  408.   .create_key.ex:
  409.         mov     esi, [_key_name]
  410.         call    libini._.string_copy
  411.         mov     byte[edi], '='
  412.         inc     edi
  413.         mov     esi, [_buffer]
  414.         mov     ecx, [_buf_len]
  415.         rep     movsb
  416.         mov     word[edi], 0x0A0D
  417.         add     edi, 2
  418.         mov     eax, edi
  419.  
  420.         pop     edi
  421.         sub     eax, edi
  422.         mov     [_buffer], edi
  423.         mov     [_buf_len], eax
  424.         neg     eax
  425.         stdcall libini._.shift_content, [f_addr], eax
  426.  
  427.         jmp     .modify_key.ex
  428.  
  429.   .create_section:
  430.         mov     edi, [f.buf]
  431.         add     edi, ini.BLOCK_SIZE
  432.         push    edi
  433.  
  434.         mov     esi, [_sec_name]
  435.         mov     byte[edi], '['
  436.         inc     edi
  437.         call    libini._.string_copy
  438.         mov     dword[edi], ']' + (0x0A0D shl 8)
  439.         add     edi, 3
  440.  
  441.         jmp     .create_key.ex
  442.  
  443.   .exit_error:
  444.         invoke  file.close, [f.fh]
  445.   .exit_file_error:
  446.         pop     edi esi ebx
  447.         or      eax, -1
  448.         ret
  449. endp
  450.  
  451. ;;================================================================================================;;
  452. proc ini.get_int _f_name, _sec_name, _key_name, _def_val ;////////////////////////////////////////;;
  453. ;;------------------------------------------------------------------------------------------------;;
  454. ;? Read integer                                                                                   ;;
  455. ;;------------------------------------------------------------------------------------------------;;
  456. ;> _f_name = ini filename <asciiz>                                                                ;;
  457. ;> _sec_name = section name <asciiz>                                                              ;;
  458. ;> _key_name = key name <asciiz>                                                                  ;;
  459. ;> _def_val = default value to return if no key, section or file found <dword>                    ;;
  460. ;;------------------------------------------------------------------------------------------------;;
  461. ;< eax = [_def_val] (error) / found key value <dword>                                             ;;
  462. ;;================================================================================================;;
  463. locals
  464.   f      IniFile
  465.   f_addr dd ?
  466. endl
  467.  
  468.         push    edx ebx esi edi
  469.  
  470.         xor     eax, eax
  471.         mov     [f.fh], eax
  472.         mov     [f.buf], eax
  473.         invoke  file.open, [_f_name], O_READ
  474.         cmp     eax, 32
  475.         jb      .exit_file_error
  476.         mov     [f.fh], eax
  477.         invoke  mem.alloc, ini.MEM_SIZE
  478.         or      eax, eax
  479.         jz      .exit_error
  480.         mov     [f.buf], eax
  481.         lea     ebx, [f]
  482.         mov     [f_addr], ebx
  483.         stdcall libini._.find_section, ebx, [_sec_name]
  484.         or      eax, eax
  485.         jnz     .exit_error
  486.  
  487.         stdcall libini._.find_key, ebx, [_key_name]
  488.         or      eax, eax
  489.         jnz     .exit_error
  490.  
  491.         stdcall libini._.skip_spaces, [f_addr]
  492.         xor     eax, eax
  493.         xor     ebx, ebx
  494.         xor     edx, edx
  495.         stdcall libini._.get_char, [f_addr]
  496.         cmp     al, '-'
  497.         jne     .lp1
  498.         inc     bh
  499.     @@: stdcall libini._.get_char, [f_addr]
  500.   .lp1: cmp     al, '0'
  501.         jb      @f
  502.         cmp     al, '9'
  503.         ja      @f
  504.         inc     bl
  505.         add     eax, -'0'
  506.         imul    edx, 10
  507.         add     edx, eax
  508.         jmp     @b
  509.     @@:
  510.         or      bl, bl
  511.         jz      .exit_error
  512.         or      bh, bh
  513.         jz      @f
  514.         neg     edx
  515.     @@: invoke  file.close, [f.fh]
  516.         invoke  mem.free, [f.buf]
  517.         mov     eax, edx
  518.         pop     edi esi ebx edx
  519.         ret
  520.  
  521.   .exit_error:
  522.         invoke  file.close, [f.fh]
  523.   .exit_file_error:
  524.         invoke  mem.free, [f.buf]
  525.         mov     eax, [_def_val]
  526.         pop     edi esi ebx edx
  527.         ret
  528. endp
  529.  
  530. ;;================================================================================================;;
  531. proc ini.set_int _f_name, _sec_name, _key_name, _val ;////////////////////////////////////////////;;
  532. ;;------------------------------------------------------------------------------------------------;;
  533. ;? Write integer                                                                                  ;;
  534. ;;------------------------------------------------------------------------------------------------;;
  535. ;> _f_name = ini filename <asciiz>                                                                ;;
  536. ;> _sec_name = section name <asciiz>                                                              ;;
  537. ;> _key_name = key name <asciiz>                                                                  ;;
  538. ;> _val = value <dword>                                                                           ;;
  539. ;;------------------------------------------------------------------------------------------------;;
  540. ;< eax = -1 (error) / 0                                                                           ;;
  541. ;;================================================================================================;;
  542. locals
  543.   buf rb 16
  544.   bNeg rd 1
  545. endl
  546.  
  547.         push    ecx edx edi
  548.  
  549.         lea     edi, [buf]
  550.         add     edi, 15
  551.  
  552.         mov     eax, [_val]
  553.         mov     [bNeg],0
  554.         or      eax, eax
  555.         jns     @f
  556.         mov     [bNeg],1
  557.         neg     eax
  558.  
  559.     @@: mov     ecx, 10
  560.     @@: xor     edx, edx
  561.         idiv    ecx
  562.         add     dl, '0'
  563.         mov     [edi], dl
  564.         dec     edi
  565.         or      eax, eax
  566.         jnz     @b
  567.  
  568.         cmp     [bNeg],0
  569.         je      @f
  570.         mov     byte[edi], '-'
  571.         dec     edi
  572.      @@:
  573.         lea     eax, [buf]
  574.         add     eax, 15
  575.         sub     eax, edi
  576.         inc     edi
  577.  
  578.  
  579.  
  580.         stdcall ini.set_str, [_f_name], [_sec_name], [_key_name], edi, eax
  581.  
  582.         pop     edi edx ecx
  583.         ret
  584. endp
  585.  
  586. ;;================================================================================================;;
  587. proc ini.get_color _f_name, _sec_name, _key_name, _def_val ;//////////////////////////////////////;;
  588. ;;------------------------------------------------------------------------------------------------;;
  589. ;? Read color                                                                                     ;;
  590. ;;------------------------------------------------------------------------------------------------;;
  591. ;> _f_name = ini filename <asciiz>                                                                ;;
  592. ;> _sec_name = section name <asciiz>                                                              ;;
  593. ;> _key_name = key name <asciiz>                                                                  ;;
  594. ;> _def_val = default value to return if no key, section or file found <dword>                    ;;
  595. ;;------------------------------------------------------------------------------------------------;;
  596. ;< eax = [_def_val] (error) / found key value <dword>                                             ;;
  597. ;;================================================================================================;;
  598. locals
  599.   buf rb 14
  600. endl
  601.  
  602.         push    ebx esi edi
  603.  
  604.         lea     esi, [buf]
  605.         stdcall ini.get_str, [_f_name], [_sec_name], [_key_name], esi, 14, 0
  606.         cmp     byte[esi],0
  607.         je      .exit_error
  608.  
  609.         xor     ebx, ebx
  610.         stdcall libini._.str_to_int
  611.         movzx   ebx, al
  612.         shl     ebx, 16
  613.         lodsb
  614.         cmp     al, ','
  615.         jne     @f
  616.         stdcall libini._.str_to_int
  617.         mov     bh, al
  618.         lodsb
  619.         cmp     al, ','
  620.         jne     @f
  621.         stdcall libini._.str_to_int
  622.         mov     bl, al
  623.  
  624.     @@: mov     eax, ebx
  625.  
  626.         pop     edi esi ebx
  627.         ret
  628.  
  629.   .exit_error:
  630.         mov     eax, [_def_val]
  631.         pop     edi esi ebx
  632.         ret
  633. endp
  634.  
  635. ;;================================================================================================;;
  636. proc ini.set_color _f_name, _sec_name, _key_name, _val ;//////////////////////////////////////////;;
  637. ;;------------------------------------------------------------------------------------------------;;
  638. ;? Write color                                                                                    ;;
  639. ;;------------------------------------------------------------------------------------------------;;
  640. ;> _f_name = ini filename <asciiz>                                                                ;;
  641. ;> _sec_name = section name <asciiz>                                                              ;;
  642. ;> _key_name = key name <asciiz>                                                                  ;;
  643. ;> _val = value <dword>                                                                           ;;
  644. ;;------------------------------------------------------------------------------------------------;;
  645. ;< eax = -1 (error) / 0                                                                           ;;
  646. ;;================================================================================================;;
  647. locals
  648.   buf rb 16
  649. endl
  650.  
  651.         push    ecx edx edi
  652.  
  653.         lea     edi, [buf]
  654.         mov     ecx, 10
  655.         mov     ebx, [_val]
  656.         mov     eax, ebx
  657.         shr     eax, 16
  658.         and     eax, 0x0ff
  659.         stdcall libini._.int_to_str
  660.         mov     byte[edi], ','
  661.         inc     edi
  662.         movzx   eax, bh
  663.         stdcall libini._.int_to_str
  664.         mov     byte[edi], ','
  665.         inc     edi
  666.         movzx   eax, bl
  667.         stdcall libini._.int_to_str
  668.  
  669.         lea     eax, [buf]
  670.         sub     edi, eax
  671.  
  672.         stdcall ini.set_str, [_f_name], [_sec_name], [_key_name], eax, edi
  673.  
  674.         pop     edi edx ecx
  675.         ret
  676. endp
  677.  
  678.  
  679. ;;================================================================================================;;
  680. proc ini.del_section _f_name, _sec_name ;/////////////////////////////////////////////////////////;;
  681. ;;------------------------------------------------------------------------------------------------;;
  682. ;? Delete section and all key in this section                                                     ;;
  683. ;;------------------------------------------------------------------------------------------------;;
  684. ;> _f_name = ini filename <asciiz>                                                                ;;
  685. ;> _sec_name = section name <asciiz>                                                              ;;
  686. ;;------------------------------------------------------------------------------------------------;;
  687. ;< eax = 0 - success                                                                              ;;
  688. ;<      -1 - file not found                                                                       ;;
  689. ;<       1 - section not found                                                                    ;;
  690. ;;================================================================================================;;
  691. locals
  692.    funcFile     rb 25
  693.    fileInfo     rb 40
  694.    begMem       rd 1
  695.    endMem       rd 1
  696.    begDel       rd 1
  697.    endDel       rd 1
  698. endl
  699.         push    ebx ecx edi esi
  700.         mov     dword[funcFile],5               ;get file info
  701.         mov     dword[funcFile+4],0
  702.         mov     dword[funcFile+8],0
  703.         mov     dword[funcFile+12],0
  704.         lea     eax,[fileInfo]
  705.         mov     dword[funcFile+16],eax
  706.         mov     byte[funcFile+20],0
  707.         m2m     dword[funcFile+21],[_f_name]
  708.         lea     ebx,[funcFile]
  709.         mcall   70
  710.         test    eax,eax
  711.         jz      @f
  712.  
  713.         or      eax,-1
  714.         pop     esi edi ecx ebx
  715.         ret
  716.       @@:
  717.  
  718.         mov     ecx,dword[fileInfo+32]          ;allocation mem for all file
  719.         mcall   68,12
  720.  
  721.         mov     [begMem],eax
  722.         mov     [endMem],eax
  723.         add     [endMem],ecx
  724.  
  725.         mov     dword[funcFile],0               ;read file to buffer
  726.         mov     dword[funcFile+12],ecx
  727.         mov     dword[funcFile+16],eax
  728.         lea     ebx,[funcFile]
  729.         mcall   70
  730.  
  731.         mov     edi,[begMem]                    ;search begin section
  732.     .searchSect:
  733.         mov     al,'['
  734.         repne   scasb
  735.         test    ecx,ecx
  736.         jnz     @f
  737.        
  738.         pop     esi edi ecx ebx
  739.         mov     eax,1
  740.         ret
  741.       @@:
  742.         mov     [begDel],edi
  743.         mov     esi,[_sec_name]
  744.       @@:
  745.         lodsb
  746.         test    al,al
  747.         jz      @f
  748.         scasb
  749.         jne     .searchSect
  750.         jmp     @b
  751.       @@:
  752.         cmp     byte[edi],']'
  753.         jne     .searchSect
  754.  
  755.         dec     [begDel]
  756.  
  757.         mov     edi,[begDel]                    ;search end section
  758.         inc     edi
  759.     .searchEndSect:
  760.         mov     al,'['
  761.         repne   scasb
  762.  
  763.         dec     edi
  764.         mov     [endDel],edi
  765.  
  766.         test    ecx,ecx
  767.         jnz     @f
  768.         jmp     .SaveToFile
  769.       @@:
  770.  
  771.  
  772.         mov     esi,[endDel]
  773.         mov     edi,[begDel]
  774.    @@:  lodsb
  775.         stosb
  776.         cmp     esi,[endMem]
  777.         jb      @b
  778.  
  779.    .SaveToFile:
  780.         mov     eax,dword[funcFile+12]
  781.         sub     eax,[endDel]
  782.         add     eax,[begDel]
  783.  
  784.         mov     dword[funcFile],2               ;write buffer to file
  785.         mov     dword[funcFile+12],eax
  786.         m2m     dword[funcFile+16],[begMem]
  787.         lea     ebx,[funcFile]
  788.         mcall   70
  789.  
  790.         xor     eax,eax
  791.         pop     esi edi ecx ebx
  792.         ret
  793. endp
  794.  
  795.  
  796.  
  797.  
  798. ;;================================================================================================;;
  799. proc ini.get_shortcut _f_name, _sec_name, _key_name, _def_val, _modifiers ;///////////////////////;;
  800. ;;------------------------------------------------------------------------------------------------;;
  801. ;? Read shortcut key                                                                              ;;
  802. ;;------------------------------------------------------------------------------------------------;;
  803. ;> _f_name = ini filename <asciiz>                                                                ;;
  804. ;> _sec_name = section name <asciiz>                                                              ;;
  805. ;> _key_name = key name <asciiz>                                                                  ;;
  806. ;> _def_val = default value to return if no key, section or file found <dword>                    ;;
  807. ;> _modifiers = pointer to dword variable which receives modifiers state as in 66.4 <dword*>      ;;
  808. ;;------------------------------------------------------------------------------------------------;;
  809. ;< eax = [_def_val] (error) / shortcut key value as scancode <int>                                ;;
  810. ;< [[_modifiers]] = unchanged (error) / modifiers state for this shortcut <int>                   ;;
  811. ;;================================================================================================;;
  812. locals
  813.   buf rb 64
  814. endl
  815.  
  816.         push    ebx esi edi
  817.  
  818.         lea     esi, [buf]
  819.         stdcall ini.get_str, [_f_name], [_sec_name], [_key_name], esi, 64, 0
  820.         cmp     byte[esi],0
  821.         je      .exit_error
  822.  
  823.         xor     ebx, ebx        ; ebx holds the value of modifiers
  824. .loop:
  825. ; test for end
  826.         xor     eax, eax
  827.         cmp     byte [esi], al
  828.         jz      .exit_ok        ; exit with scancode zero
  829. ; skip all '+'s
  830.         cmp     byte [esi], '+'
  831.         jnz     @f
  832.         inc     esi
  833.         jmp     .loop
  834. @@:
  835. ; test for names
  836.         mov     edi, .names_table
  837.         xor     edx, edx
  838. .names_loop:
  839.         movzx   ecx, byte [edi]
  840.         inc     edi
  841.         push    esi
  842. @@:
  843.         lodsb
  844.         or      al, 20h
  845.         scasb
  846.         loopz   @b
  847.         jz      .name_found
  848.         pop     esi
  849.         lea     edi, [edi+ecx+4]
  850.         inc     edx
  851.         cmp     byte [edi], 0
  852.         jnz     .names_loop
  853. ; special test: functional keys F<number>
  854.         cmp     byte [esi], 'f'
  855.         jz      @f
  856.         cmp     byte [esi], 'F'
  857.         jnz     .no_fx
  858. @@:
  859.         mov     edi, esi
  860.         inc     esi
  861.         call    libini._.str_to_int
  862.         test    eax, eax
  863.         jnz     .fx
  864.         mov     esi, edi
  865. .no_fx:
  866. ; name not found, that must be usual key
  867.         movzx   eax, byte [esi]
  868.         stdcall libini._.ascii_to_scan, eax
  869.         test    eax, eax
  870.         jz      .exit_error
  871. ; all is ok
  872. .exit_ok:
  873.         mov     ecx, [_modifiers]
  874.         test    ecx, ecx
  875.         jz      @f
  876.         mov     [ecx], ebx
  877.  
  878. @@:
  879.  
  880.         pop     edi esi ebx
  881.         ret
  882.  
  883. .exit_error:
  884.         mov     eax, [_def_val]
  885.         pop     edi esi ebx
  886.         ret
  887. ; handler for Fx
  888. ; eax = number
  889. .fx:
  890.         cmp     eax, 10
  891.         ja      @f
  892.         add     eax, 3Bh-1
  893.         jmp     .exit_ok
  894. @@:
  895.         add     eax, 57h-11
  896.         jmp     .exit_ok
  897. ; handlers for names
  898. .name_found:
  899.         pop     eax     ; ignore saved esi
  900.         call    dword [edi]
  901.         cmp     edx, .num_modifiers
  902.         jae     .exit_ok
  903.         jmp     .loop
  904. ; modifiers
  905. ; syntax of value for each modifier:
  906. ; 0 = none, 1 = exactly one of L+R, 2 = both L+R, 3 = L, 4 = R
  907. ; Logic for switching: LShift+RShift=LShift+Shift=Shift+Shift, LShift+LShift=LShift
  908. ; generic modifier: 0->1->2->2, 3->2, 4->2
  909. ; left modifier: 0->3->3, 1->2->2, 4->2
  910. ; right modifier: 0->4->4, 1->2->2, 3->2
  911. ; Shift corresponds to first hex digit, Ctrl - second, Alt - third
  912. macro shortcut_handle_modifiers name,reg,shift
  913. {
  914. local .set2,.set3,.set4
  915. .#name#_handler:        ; generic modifier
  916.         test    reg, 0xF
  917.         jnz     .set2
  918. if shift
  919.         or      reg, 1 shl shift
  920. else
  921.         inc     reg
  922. end if
  923.         retn
  924. .set2:
  925.         and     reg, not (0xF shl shift)
  926.         or      reg, 2 shl shift
  927.         retn
  928. .l#name#_handler:
  929.         mov     al, reg
  930.         and     al, 0xF shl shift
  931.         jz      .set3
  932.         cmp     al, 3 shl shift
  933.         jnz     .set2
  934.         retn
  935. .set3:
  936.         add     reg, 3 shl shift
  937.         retn
  938. .r#name#_handler:
  939.         mov     al, reg
  940.         and     al, 0xF shl shift
  941.         jz      .set4
  942.         cmp     al, 4 shl shift
  943.         jnz     .set2
  944.         retn
  945. .set4:
  946.         add     reg, 4 shl shift
  947.         retn
  948. }
  949. shortcut_handle_modifiers shift,bl,0
  950. shortcut_handle_modifiers ctrl,bl,4
  951. shortcut_handle_modifiers alt,bh,0
  952. ; names of keys
  953. .name_handler:
  954.         movzx   eax, byte [.names_scancodes+edx-.num_modifiers]
  955.         retn
  956. endp
  957.  
  958. ; note: comparison ignores case, so this table keeps lowercase names
  959. ; macro does this
  960. macro shortcut_name_with_handler name,handler
  961. {
  962. local .start, .end
  963.         db      .end - .start
  964. .start:
  965.         db      name
  966. .end:
  967. repeat .end - .start
  968.         load .a byte from .start + % - 1
  969.         store byte .a or 0x20 at .start + % - 1
  970. end repeat
  971.         dd      handler
  972. }
  973. macro shortcut_name [name]
  974. {
  975.         shortcut_name_with_handler name, .name_handler
  976. }
  977.  
  978. ; all names here must be in english
  979. ; ... or modify lowercasing in macro and in comparison
  980. .names_table:
  981. ; generic modifiers
  982.         shortcut_name_with_handler 'Ctrl', .ctrl_handler
  983.         shortcut_name_with_handler 'Alt', .alt_handler
  984.         shortcut_name_with_handler 'Shift', .shift_handler
  985. ; concrete modifiers
  986.         shortcut_name_with_handler 'LCtrl', .lctrl_handler
  987.         shortcut_name_with_handler 'RCtrl', .rctrl_handler
  988.         shortcut_name_with_handler 'LAlt', .lalt_handler
  989.         shortcut_name_with_handler 'RAlt', .ralt_handler
  990.         shortcut_name_with_handler 'LShift', .lshift_handler
  991.         shortcut_name_with_handler 'RShift', .rshift_handler
  992. .num_modifiers = 9
  993. ; symbolic names of keys
  994.         shortcut_name 'Home', 'End', 'PgUp', 'PgDn', 'Ins', 'Insert', 'Del', 'Delete'
  995.         shortcut_name 'Tab', 'Plus', 'Esc', 'Enter', 'Backspace', 'Space', 'Left', 'Right'
  996.         shortcut_name 'Up', 'Down'
  997. ; end of table
  998.         db      0
  999. ini.get_shortcut.names_scancodes:
  1000. ; scancodes for 'Home' ... 'Down'
  1001.         db      47h, 4Fh, 49h, 51h, 52h, 52h, 53h, 53h
  1002.         db      0Fh, 4Eh, 01h, 1Ch, 0Eh, 39h, 4Bh, 4Dh
  1003.         db      48h, 50h
  1004.  
  1005. ;;================================================================================================;;
  1006. ;;////////////////////////////////////////////////////////////////////////////////////////////////;;
  1007. ;;================================================================================================;;
  1008. ;! Imported functions section                                                                     ;;
  1009. ;;================================================================================================;;
  1010. ;;////////////////////////////////////////////////////////////////////////////////////////////////;;
  1011. ;;================================================================================================;;
  1012.  
  1013.  
  1014. align 16
  1015. @IMPORT:
  1016.  
  1017. library \
  1018.         libio , 'libio.obj'
  1019.  
  1020. import  libio                       , \
  1021.         file.size   , 'file_size'   , \
  1022.         file.open   , 'file_open'   , \
  1023.         file.read   , 'file_read'   , \
  1024.         file.write  , 'file_write'  , \
  1025.         file.seek   , 'file_seek'   , \
  1026.         file.eof?   , 'file_iseof'  , \
  1027.         file.seteof , 'file_seteof' , \
  1028.         file.tell   , 'file_tell'   , \
  1029.         file.close  , 'file_close'
  1030.  
  1031.  
  1032. ;;================================================================================================;;
  1033. ;;////////////////////////////////////////////////////////////////////////////////////////////////;;
  1034. ;;================================================================================================;;
  1035. ;! Exported functions section                                                                     ;;
  1036. ;;================================================================================================;;
  1037. ;;////////////////////////////////////////////////////////////////////////////////////////////////;;
  1038. ;;================================================================================================;;
  1039.  
  1040.  
  1041. align 16
  1042. @EXPORT:
  1043.  
  1044. export                                            \
  1045.         libini._.init     , 'lib_init'          , \
  1046.         0x00080009        , 'version'           , \
  1047.         ini.enum_sections , 'ini_enum_sections' , \
  1048.         ini.enum_keys     , 'ini_enum_keys'     , \
  1049.         ini.get_str       , 'ini_get_str'       , \
  1050.         ini.get_int       , 'ini_get_int'       , \
  1051.         ini.get_color     , 'ini_get_color'     , \
  1052.         ini.set_str       , 'ini_set_str'       , \
  1053.         ini.set_int       , 'ini_set_int'       , \
  1054.         ini.set_color     , 'ini_set_color'     , \
  1055.         ini.get_shortcut  , 'ini_get_shortcut'  , \
  1056.         ini.del_section   , 'ini_del_section'
  1057.