Subversion Repositories Kolibri OS

Rev

Rev 3832 | Rev 3920 | 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.         jmp     .searchSect
  733.     .NoFindSect:
  734.         mov     edi,[begDel]
  735.     .searchSect:
  736.         mov     al,'['
  737.         repne   scasb
  738.         test    ecx,ecx
  739.         jnz     @f
  740.  
  741.         pop     esi edi ecx ebx
  742.         mov     eax,1
  743.         ret
  744.       @@:
  745.         mov     [begDel],edi
  746.         mov     esi,[_sec_name]
  747.       @@:
  748.         lodsb
  749.         test    al,al
  750.         jz      @f
  751.         scasb
  752.         jne     .NoFindSect
  753.         jmp     @b
  754.       @@:
  755.         cmp     byte[edi],']'
  756.         jne     .NoFindSect
  757.  
  758.         mov     edi,[begDel]
  759.         dec     [begDel]
  760.                                        ;search end section
  761.     .searchEndSect:
  762.         mov     al,'['
  763.         repne   scasb
  764.  
  765.         dec     edi
  766.         mov     [endDel],edi
  767.  
  768.         test    ecx,ecx
  769.         jnz     @f
  770.         jmp     .SaveToFile
  771.       @@:
  772.  
  773.  
  774.         mov     esi,[endDel]
  775.         mov     edi,[begDel]
  776.    @@:  lodsb
  777.         stosb
  778.         cmp     esi,[endMem]
  779.         jb      @b
  780.  
  781.    .SaveToFile:
  782.         mov     eax,dword[funcFile+12]
  783.         sub     eax,[endDel]
  784.         add     eax,[begDel]
  785.         dec     eax
  786.  
  787.         mov     dword[funcFile],2               ;write buffer to file
  788.         mov     dword[funcFile+12],eax
  789.         m2m     dword[funcFile+16],[begMem]
  790.         lea     ebx,[funcFile]
  791.         mcall   70
  792.  
  793.         xor     eax,eax
  794.         pop     esi edi ecx ebx
  795.         ret
  796. endp
  797.  
  798.  
  799.  
  800.  
  801. ;;================================================================================================;;
  802. proc ini.get_shortcut _f_name, _sec_name, _key_name, _def_val, _modifiers ;///////////////////////;;
  803. ;;------------------------------------------------------------------------------------------------;;
  804. ;? Read shortcut key                                                                              ;;
  805. ;;------------------------------------------------------------------------------------------------;;
  806. ;> _f_name = ini filename <asciiz>                                                                ;;
  807. ;> _sec_name = section name <asciiz>                                                              ;;
  808. ;> _key_name = key name <asciiz>                                                                  ;;
  809. ;> _def_val = default value to return if no key, section or file found <dword>                    ;;
  810. ;> _modifiers = pointer to dword variable which receives modifiers state as in 66.4 <dword*>      ;;
  811. ;;------------------------------------------------------------------------------------------------;;
  812. ;< eax = [_def_val] (error) / shortcut key value as scancode <int>                                ;;
  813. ;< [[_modifiers]] = unchanged (error) / modifiers state for this shortcut <int>                   ;;
  814. ;;================================================================================================;;
  815. locals
  816.   buf rb 64
  817. endl
  818.  
  819.         push    ebx esi edi
  820.  
  821.         lea     esi, [buf]
  822.         stdcall ini.get_str, [_f_name], [_sec_name], [_key_name], esi, 64, 0
  823.         cmp     byte[esi],0
  824.         je      .exit_error
  825.  
  826.         xor     ebx, ebx        ; ebx holds the value of modifiers
  827. .loop:
  828. ; test for end
  829.         xor     eax, eax
  830.         cmp     byte [esi], al
  831.         jz      .exit_ok        ; exit with scancode zero
  832. ; skip all '+'s
  833.         cmp     byte [esi], '+'
  834.         jnz     @f
  835.         inc     esi
  836.         jmp     .loop
  837. @@:
  838. ; test for names
  839.         mov     edi, .names_table
  840.         xor     edx, edx
  841. .names_loop:
  842.         movzx   ecx, byte [edi]
  843.         inc     edi
  844.         push    esi
  845. @@:
  846.         lodsb
  847.         or      al, 20h
  848.         scasb
  849.         loopz   @b
  850.         jz      .name_found
  851.         pop     esi
  852.         lea     edi, [edi+ecx+4]
  853.         inc     edx
  854.         cmp     byte [edi], 0
  855.         jnz     .names_loop
  856. ; special test: functional keys F<number>
  857.         cmp     byte [esi], 'f'
  858.         jz      @f
  859.         cmp     byte [esi], 'F'
  860.         jnz     .no_fx
  861. @@:
  862.         mov     edi, esi
  863.         inc     esi
  864.         call    libini._.str_to_int
  865.         test    eax, eax
  866.         jnz     .fx
  867.         mov     esi, edi
  868. .no_fx:
  869. ; name not found, that must be usual key
  870.         movzx   eax, byte [esi]
  871.         stdcall libini._.ascii_to_scan, eax
  872.         test    eax, eax
  873.         jz      .exit_error
  874. ; all is ok
  875. .exit_ok:
  876.         mov     ecx, [_modifiers]
  877.         test    ecx, ecx
  878.         jz      @f
  879.         mov     [ecx], ebx
  880.  
  881. @@:
  882.  
  883.         pop     edi esi ebx
  884.         ret
  885.  
  886. .exit_error:
  887.         mov     eax, [_def_val]
  888.         pop     edi esi ebx
  889.         ret
  890. ; handler for Fx
  891. ; eax = number
  892. .fx:
  893.         cmp     eax, 10
  894.         ja      @f
  895.         add     eax, 3Bh-1
  896.         jmp     .exit_ok
  897. @@:
  898.         add     eax, 57h-11
  899.         jmp     .exit_ok
  900. ; handlers for names
  901. .name_found:
  902.         pop     eax     ; ignore saved esi
  903.         call    dword [edi]
  904.         cmp     edx, .num_modifiers
  905.         jae     .exit_ok
  906.         jmp     .loop
  907. ; modifiers
  908. ; syntax of value for each modifier:
  909. ; 0 = none, 1 = exactly one of L+R, 2 = both L+R, 3 = L, 4 = R
  910. ; Logic for switching: LShift+RShift=LShift+Shift=Shift+Shift, LShift+LShift=LShift
  911. ; generic modifier: 0->1->2->2, 3->2, 4->2
  912. ; left modifier: 0->3->3, 1->2->2, 4->2
  913. ; right modifier: 0->4->4, 1->2->2, 3->2
  914. ; Shift corresponds to first hex digit, Ctrl - second, Alt - third
  915. macro shortcut_handle_modifiers name,reg,shift
  916. {
  917. local .set2,.set3,.set4
  918. .#name#_handler:        ; generic modifier
  919.         test    reg, 0xF
  920.         jnz     .set2
  921. if shift
  922.         or      reg, 1 shl shift
  923. else
  924.         inc     reg
  925. end if
  926.         retn
  927. .set2:
  928.         and     reg, not (0xF shl shift)
  929.         or      reg, 2 shl shift
  930.         retn
  931. .l#name#_handler:
  932.         mov     al, reg
  933.         and     al, 0xF shl shift
  934.         jz      .set3
  935.         cmp     al, 3 shl shift
  936.         jnz     .set2
  937.         retn
  938. .set3:
  939.         add     reg, 3 shl shift
  940.         retn
  941. .r#name#_handler:
  942.         mov     al, reg
  943.         and     al, 0xF shl shift
  944.         jz      .set4
  945.         cmp     al, 4 shl shift
  946.         jnz     .set2
  947.         retn
  948. .set4:
  949.         add     reg, 4 shl shift
  950.         retn
  951. }
  952. shortcut_handle_modifiers shift,bl,0
  953. shortcut_handle_modifiers ctrl,bl,4
  954. shortcut_handle_modifiers alt,bh,0
  955. ; names of keys
  956. .name_handler:
  957.         movzx   eax, byte [.names_scancodes+edx-.num_modifiers]
  958.         retn
  959. endp
  960.  
  961. ; note: comparison ignores case, so this table keeps lowercase names
  962. ; macro does this
  963. macro shortcut_name_with_handler name,handler
  964. {
  965. local .start, .end
  966.         db      .end - .start
  967. .start:
  968.         db      name
  969. .end:
  970. repeat .end - .start
  971.         load .a byte from .start + % - 1
  972.         store byte .a or 0x20 at .start + % - 1
  973. end repeat
  974.         dd      handler
  975. }
  976. macro shortcut_name [name]
  977. {
  978.         shortcut_name_with_handler name, .name_handler
  979. }
  980.  
  981. ; all names here must be in english
  982. ; ... or modify lowercasing in macro and in comparison
  983. .names_table:
  984. ; generic modifiers
  985.         shortcut_name_with_handler 'Ctrl', .ctrl_handler
  986.         shortcut_name_with_handler 'Alt', .alt_handler
  987.         shortcut_name_with_handler 'Shift', .shift_handler
  988. ; concrete modifiers
  989.         shortcut_name_with_handler 'LCtrl', .lctrl_handler
  990.         shortcut_name_with_handler 'RCtrl', .rctrl_handler
  991.         shortcut_name_with_handler 'LAlt', .lalt_handler
  992.         shortcut_name_with_handler 'RAlt', .ralt_handler
  993.         shortcut_name_with_handler 'LShift', .lshift_handler
  994.         shortcut_name_with_handler 'RShift', .rshift_handler
  995. .num_modifiers = 9
  996. ; symbolic names of keys
  997.         shortcut_name 'Home', 'End', 'PgUp', 'PgDn', 'Ins', 'Insert', 'Del', 'Delete'
  998.         shortcut_name 'Tab', 'Plus', 'Esc', 'Enter', 'Backspace', 'Space', 'Left', 'Right'
  999.         shortcut_name 'Up', 'Down'
  1000. ; end of table
  1001.         db      0
  1002. ini.get_shortcut.names_scancodes:
  1003. ; scancodes for 'Home' ... 'Down'
  1004.         db      47h, 4Fh, 49h, 51h, 52h, 52h, 53h, 53h
  1005.         db      0Fh, 4Eh, 01h, 1Ch, 0Eh, 39h, 4Bh, 4Dh
  1006.         db      48h, 50h
  1007.  
  1008. ;;================================================================================================;;
  1009. ;;////////////////////////////////////////////////////////////////////////////////////////////////;;
  1010. ;;================================================================================================;;
  1011. ;! Imported functions section                                                                     ;;
  1012. ;;================================================================================================;;
  1013. ;;////////////////////////////////////////////////////////////////////////////////////////////////;;
  1014. ;;================================================================================================;;
  1015.  
  1016.  
  1017. align 16
  1018. @IMPORT:
  1019.  
  1020. library \
  1021.         libio , 'libio.obj'
  1022.  
  1023. import  libio                       , \
  1024.         file.size   , 'file_size'   , \
  1025.         file.open   , 'file_open'   , \
  1026.         file.read   , 'file_read'   , \
  1027.         file.write  , 'file_write'  , \
  1028.         file.seek   , 'file_seek'   , \
  1029.         file.eof?   , 'file_iseof'  , \
  1030.         file.seteof , 'file_seteof' , \
  1031.         file.tell   , 'file_tell'   , \
  1032.         file.close  , 'file_close'
  1033.  
  1034.  
  1035. ;;================================================================================================;;
  1036. ;;////////////////////////////////////////////////////////////////////////////////////////////////;;
  1037. ;;================================================================================================;;
  1038. ;! Exported functions section                                                                     ;;
  1039. ;;================================================================================================;;
  1040. ;;////////////////////////////////////////////////////////////////////////////////////////////////;;
  1041. ;;================================================================================================;;
  1042.  
  1043.  
  1044. align 16
  1045. @EXPORT:
  1046.  
  1047. export                                            \
  1048.         libini._.init     , 'lib_init'          , \
  1049.         0x00080009        , 'version'           , \
  1050.         ini.enum_sections , 'ini_enum_sections' , \
  1051.         ini.enum_keys     , 'ini_enum_keys'     , \
  1052.         ini.get_str       , 'ini_get_str'       , \
  1053.         ini.get_int       , 'ini_get_int'       , \
  1054.         ini.get_color     , 'ini_get_color'     , \
  1055.         ini.set_str       , 'ini_set_str'       , \
  1056.         ini.set_int       , 'ini_set_int'       , \
  1057.         ini.set_color     , 'ini_set_color'     , \
  1058.         ini.get_shortcut  , 'ini_get_shortcut'  , \
  1059.         ini.del_section   , 'ini_del_section'
  1060.