Subversion Repositories Kolibri OS

Rev

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