Subversion Repositories Kolibri OS

Rev

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

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                                 ;;
  3. ;; Copyright (C) KolibriOS team 2004-2013. All rights reserved.    ;;
  4. ;; Distributed under terms of the GNU General Public License       ;;
  5. ;;                                                                 ;;
  6. ;;   Written by hidnplayr@kolibrios.org                            ;;
  7. ;;                                                                 ;;
  8. ;;         GNU GENERAL PUBLIC LICENSE                              ;;
  9. ;;          Version 2, June 1991                                   ;;
  10. ;;                                                                 ;;
  11. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  12.  
  13.  
  14. server_parser:
  15.  
  16.         mov     esi, servercommand
  17.  
  18.         cmp     byte [esi], ':'
  19.         jne     .parse
  20.  
  21.   .spaceloop:
  22.         lodsb
  23.         test    al, al
  24.         jz      .fail
  25.         cmp     al, ' '
  26.         jne     .spaceloop
  27.  
  28.   .parse:
  29.         mov     eax, [esi]
  30.         or      eax, 0x20202020
  31.         mov     edi, server_commands
  32.         mov     ecx, server_commands.number
  33.  
  34.   .loop:
  35.         scasd
  36.         je      .got_cmd
  37.         add     edi, 4
  38.         dec     ecx
  39.         jnz     .loop
  40.  
  41.   .fail:
  42.         ret
  43.  
  44.   .got_cmd:
  45.         jmp     dword[edi]
  46.  
  47.  
  48. server_commands:
  49.  
  50.         dd      '322 ', cmd_322         ; RPL_LIST
  51.         dd      '323 ', cmd_323         ; RPL_LISTEND
  52.         dd      '324 ', cmd_324 ;;;;
  53.         dd      '328 ', cmd_328         ; RPL_CHANNEL_URL
  54.         dd      '329 ', cmd_329
  55.         dd      '332 ', cmd_topic
  56.         dd      '333 ', cmd_333         ; nickname and time of topic
  57.         dd      '353 ', cmd_353         ; name reply
  58.         dd      '366 ', cmd_366         ; end of names list
  59.         dd      '372 ', cmd_372         ; motd
  60.         dd      '375 ', cmd_375         ; start of motd
  61.         dd      '376 ', cmd_376         ; end of motd
  62.         dd      '421 ', cmd_421         ; unknown command
  63.         dd      'join', cmd_join
  64.         dd      'kick', cmd_kick
  65.         dd      'mode', cmd_mode
  66.         dd      'nick', cmd_nick
  67.         dd      'part', cmd_part
  68.         dd      'ping', cmd_ping
  69.         dd      'priv', cmd_privmsg
  70.         dd      'quit', cmd_quit
  71.         dd      'noti', cmd_notice
  72.  
  73.         .number = ($ - server_commands) / 8
  74.  
  75.  
  76. align 4
  77. compare_to_nick:
  78.  
  79.         push    esi
  80.         mov     ecx, MAX_NICK_LEN
  81.         mov     esi, user_nick
  82.   .loop:
  83.         lodsb
  84.         cmp     al, ' '
  85.         jbe     .done
  86.         cmp     al, 'a'
  87.         jb      .ok
  88.         cmp     al, 'z'
  89.         ja      .ok
  90.         sub     al, 0x20
  91.   .ok:
  92.  
  93.         mov     bl, byte[edi]
  94.         cmp     bl, 'a'
  95.         jb      .ok2
  96.         cmp     bl, 'z'
  97.         ja      .ok2
  98.         sub     bl, 0x20
  99.   .ok2:
  100.         cmp     bl, al
  101.         jne     .not_equal
  102.         inc     edi
  103.         dec     ecx
  104.         jnz     .loop
  105.  
  106.   .done:
  107.         xor     eax, eax
  108.         pop     esi
  109.         ret
  110.  
  111.   .not_equal:
  112.         or      eax, -1
  113.         pop     esi
  114.         ret
  115.  
  116.  
  117.  
  118. align 4
  119. skip_nick:
  120.  
  121. ; First: skip the NICK (maybe we should verify it?)
  122.   .nick:
  123.         lodsb
  124.         cmp     al, ' '
  125.         je      .skip
  126.         cmp     al, ':'
  127.         je      .skip
  128.         jmp     .nick
  129.  
  130. ; skip all leading spaces and semicolons
  131.   .skip:
  132.         lodsb
  133.         cmp     al, ' '
  134.         je      .skip
  135.         cmp     al, ':'
  136.         je      .skip
  137.         dec     esi
  138.  
  139.         ret
  140.  
  141.  
  142.  
  143. cmd_324:
  144. cmd_329:
  145. cmd_328:
  146. cmd_421:
  147. cmd_372:
  148. cmd_375:
  149. cmd_376:
  150.         add     esi, 4
  151.         jmp     cmd_notice.loop
  152.  
  153. cmd_notice:
  154.  
  155.         cmp     byte[servercommand], ':'
  156.         jne     .gogogo
  157.  
  158.         mov     byte [esi-1], 0
  159.         if TIMESTAMP
  160.         call    print_timestamp
  161.         end if
  162.  
  163.         push    esi
  164.         mov     esi, str_1
  165.         call    print_text2
  166.         mov     eax, servercommand+1
  167.         mov     dl, '!'
  168.         call    print_text
  169.         mov     esi, str_2
  170.         call    print_text2
  171.         pop     esi
  172.  
  173.   .gogogo:
  174.         add     esi, 6
  175.  
  176.   .loop:
  177.         inc     esi
  178.         cmp     byte [esi], 0
  179.         je      .fail
  180.         cmp     byte [esi], ' '
  181.         jne     .loop
  182.  
  183.   .loop2:
  184.         inc     esi
  185.         cmp     byte [esi], 0
  186.         je      .fail
  187.         cmp     byte [esi], ' '
  188.         je      .loop2
  189.         cmp     byte [esi], ':'
  190.         je      .loop2
  191.  
  192.   .fail:
  193.         call    print_text2
  194.         mov     esi, str_newline
  195.         call    print_text2
  196.  
  197.         ret
  198.  
  199.  
  200.  
  201. cmd_ping:
  202.  
  203. ; Just change PING to PONG
  204.         mov     dword[esi], 'PONG'
  205.  
  206. ; Find the end of the command
  207.         lea     edi, [esi + 5]
  208.         xor     al, al
  209.         repne   scasb
  210.  
  211. ; Now send it back
  212.         mov     edx, esi
  213.         mov     esi, edi
  214.         mov     word [esi], 0x0d0a
  215.         inc     esi
  216.         inc     esi
  217.         sub     esi, edx
  218.         mcall   send, [socketnum], , , 0
  219.  
  220.         ret
  221.  
  222.  
  223.  
  224. cmd_privmsg:
  225.  
  226.         mov     eax, dword[esi+4]
  227.         or      eax, 0x20202020
  228.         cmp     eax, 'msg '
  229.         jne     .fail
  230.         add     esi, 8          ; skip 'PRIVMSG '
  231.         call    window_open     ; esi now points to end of destination name
  232.  
  233.         cmp     byte[esi], 1    ; Client to Client protocol?
  234.         je      cmd_ctcp
  235.  
  236. ; nope, just plain old privmsg, print it using '<nick> message' format
  237.         if TIMESTAMP
  238.         call    print_timestamp
  239.         end if
  240.  
  241.         push    esi
  242.         mov     bl, '<'
  243.         call    print_character
  244.  
  245.         mov     eax, servercommand+1
  246.         mov     dl, '!'
  247.         call    print_text
  248.  
  249.         mov     bl, '>'
  250.         call    print_character
  251.  
  252.         mov     bl, ' '
  253.         call    print_character
  254.  
  255.         pop     esi
  256.         call    print_text2
  257.  
  258.         mov     bl, 10
  259.         call    print_character
  260.  
  261.   .fail:
  262.         ret
  263.  
  264.  
  265.  
  266.  
  267. cmd_ctcp:
  268.  
  269.         cmp     byte [esi+4], ' '
  270.         jne     .fail
  271.         inc     esi
  272.         mov     eax, dword[esi]
  273.         or      eax, 0x20202020
  274.  
  275.         cmp     eax, 'vers'
  276.         je      .version
  277.         cmp     eax, 'time'
  278.         je      .time
  279.         cmp     eax, 'ping'
  280.         je      .ping
  281.         cmp     eax, 'acti'
  282.         je      .action
  283. ;        cmp     eax, 'dcc '    ; TODO
  284. ;        je      cmd_dcc
  285.  
  286. ; Unknown CTCP command: TODO: just print to window??
  287.  
  288.   .fail:
  289.  
  290.         ret
  291.  
  292.   .time:
  293.         mov     byte[esi+4], ' '
  294.         lea     edi, [esi+5]
  295.  
  296.         ; TODO: add system date (fn 29) in human readable format
  297.  
  298.         mcall   3                       ; get system time
  299.  
  300.         mov     ecx, 3
  301.   .timeloop:
  302.         mov     bl, al
  303.         shr     al, 4
  304.         add     al, '0'
  305.         stosb
  306.  
  307.         mov     al, bl
  308.         and     al, 0x0f
  309.         add     al, '0'
  310.         stosb
  311.  
  312.         dec     ecx
  313.         jz      .timedone
  314.  
  315.         mov     al, ':'
  316.         stosb
  317.         shr     eax, 8
  318.         jmp     .timeloop
  319.  
  320.   .timedone:
  321.         xor     al, al
  322.         stosb
  323.         call    ctcp_reply
  324.  
  325.         if TIMESTAMP
  326.         call    print_timestamp
  327.         end if
  328.  
  329.         mov     esi, ctcp_header
  330.         call    print_text2
  331.  
  332.         mov     esi, servercommand+1
  333.         call    print_text2
  334.  
  335.         mov     esi, ctcp_time
  336.         call    print_text2
  337.  
  338.         ret
  339.  
  340.   .version:
  341.         mov     esi, str_version
  342.         call    ctcp_reply
  343.  
  344.         if TIMESTAMP
  345.         call    print_timestamp
  346.         end if
  347.  
  348.         mov     esi, ctcp_header
  349.         call    print_text2
  350.  
  351.         mov     esi, servercommand+1
  352.         call    print_text2
  353.  
  354.         mov     esi, ctcp_version
  355.         call    print_text2
  356.  
  357.         ret
  358.  
  359.   .ping:
  360.         call    ctcp_reply
  361.  
  362.         if TIMESTAMP
  363.         call    print_timestamp
  364.         end if
  365.  
  366.         mov     esi, ctcp_header
  367.         call    print_text2
  368.  
  369.         mov     esi, servercommand+1
  370.         call    print_text2
  371.  
  372.         mov     esi, ctcp_ping
  373.         call    print_text2
  374.  
  375.         ret
  376.  
  377.   .action:
  378.         add     esi, 7
  379.         push    esi
  380.  
  381.         if TIMESTAMP
  382.         call    print_timestamp
  383.         end if
  384.  
  385.         mov     esi, action_header
  386.         call    print_text2
  387.  
  388.         mov     eax, servercommand+1    ; print nickname
  389.         mov     dl, '!'
  390.         call    print_text
  391.  
  392.         mov     bl, ' '
  393.         call    print_character
  394.  
  395.         pop     esi
  396.         call    print_text2             ; print message
  397.  
  398.         mov     bl, 10
  399.         call    print_character
  400.  
  401.         ret
  402.  
  403.  
  404. cmd_dcc:
  405.         add     esi, 4
  406.         mov     eax, dword[esi]
  407.         or      eax, 0x202020
  408.  
  409.         cmp     eax, 'send'
  410.         je      .send
  411.  
  412.         ret
  413.  
  414.   .send:
  415.  
  416.         ret
  417.  
  418.  
  419.  
  420. ctcp_reply:
  421.  
  422.         push    esi
  423.         mov     dword [usercommand], 'NOTI'
  424.         mov     dword [usercommand+4], 'CE  '
  425.  
  426.         mov     esi, servercommand+1
  427.         mov     edi, usercommand+7
  428.   .nickloop:
  429.         lodsb
  430.         cmp     al, '!'
  431.         je      .done
  432.         cmp     al, ' '
  433.         je      .done
  434.         test    al, al
  435.         je      .fail
  436.         stosb
  437.         jmp     .nickloop
  438.   .done:
  439.         mov     byte [esi-1], 0
  440.         mov     ax, ' :'
  441.         stosw
  442.         mov     al, 1
  443.         stosb
  444.  
  445.         pop     esi
  446.   .replyloop:
  447.         lodsb
  448.         cmp     al, 1
  449.         jbe     .done2
  450.         stosb
  451.         jmp     .replyloop
  452.   .done2:
  453.  
  454.         mov     al, 1
  455.         stosb
  456.         mov     ax, 0x0a0d
  457.         stosw
  458.  
  459.         lea     esi, [edi - usercommand]
  460.         mcall   send, [socketnum], usercommand, , 0
  461.   .fail:
  462.         ret
  463.  
  464.  
  465.  
  466. cmd_part:
  467.  
  468.         cmp     byte [esi+4], ' '
  469.         jne     .fail
  470.         add     esi, 5  ; skip 'PART '
  471.  
  472. ; Is it me who parted?
  473.         mov     edi, servercommand+1
  474.         call    compare_to_nick
  475.         jne     .dont_close
  476.  
  477. ; yes, close the window (if its open)
  478.         call    window_find
  479.         test    ebx, ebx
  480.         jz      @f
  481.         call    window_close
  482.   @@:
  483.   .fail:
  484.  
  485.         ret
  486.  
  487.  
  488. ; somebody else parted, just print message
  489.   .dont_close:
  490.         push    esi
  491.         call    skip_nick
  492.         call    window_open
  493.  
  494.         mov     esi, part_header
  495.         call    print_text2
  496.  
  497.         mov     eax, servercommand+1
  498.         mov     dl, '!'
  499.         mov     cl, ' '
  500.         call    print_text
  501.  
  502.         mov     esi, has_left_channel
  503.         call    print_text2
  504.  
  505.         pop     esi
  506.         call    print_text2
  507.  
  508.         mov     esi, str_newline
  509.         call    print_text2
  510.  
  511.         mov     ebx, [window_print]
  512.         mov     esi, servercommand+1
  513.         call    user_remove
  514.  
  515.         ret
  516.  
  517.  
  518.  
  519. cmd_join:
  520.  
  521.         cmp     byte [esi+4], ' '
  522.         jne     .fail
  523.         add     esi, 5  ; skip 'JOIN '
  524.  
  525. ; compare nick: did we join a channel?
  526.         mov     edi, servercommand+1
  527.         call    compare_to_nick
  528.         jne     .no_new_window
  529.  
  530. ; create channel window - search for empty slot
  531.         mov     ebx, windows
  532.         mov     ecx, MAX_WINDOWS
  533.   .loop:
  534.         cmp     [ebx + window.data_ptr], 0
  535.         je      .free_found
  536.         add     ebx, sizeof.window
  537.         dec     ecx
  538.         jnz     .loop
  539. ; Error: no more available windows!! ;;;;; TODO
  540.  
  541.         ret
  542.  
  543.   .free_found:
  544.         call    window_create
  545.         test    eax, eax
  546.         jz      .fail
  547.         mov     [ebx + window.type], WINDOWTYPE_CHANNEL
  548.  
  549.         call    window_set_name
  550.  
  551.         mov     [window_active], ebx
  552.         mov     [window_print], ebx
  553.  
  554.         if TIMESTAMP
  555.         call    print_timestamp
  556.         end if
  557.  
  558.         push    esi
  559.         mov     esi, join_header
  560.         call    print_text2
  561.  
  562.         mov     esi, str_talking
  563.         call    print_text2
  564.  
  565.         pop     eax
  566.         mov     dl, ' '
  567.         call    print_text
  568.  
  569.         mov     esi, str_dotnewline
  570.         call    print_text2
  571.  
  572.         call    draw_window
  573.  
  574.         ret
  575.  
  576.   .no_new_window:
  577.         push    esi
  578.         call    window_open
  579.  
  580.         if TIMESTAMP
  581.         call    print_timestamp
  582.         end if
  583.  
  584.         mov     esi, join_header
  585.         call    print_text2
  586.  
  587.         mov     eax, servercommand+1
  588.         mov     dl, '!'
  589.         call    print_text
  590.  
  591.         mov     esi, joins_channel
  592.         call    print_text2
  593.  
  594.         pop     esi
  595.         call    print_text2
  596.  
  597.         mov     esi, str_newline
  598.         call    print_text2
  599.  
  600.         mov     ebx, [window_print]
  601.         mov     esi, servercommand+1
  602.         call    user_add
  603.  
  604.   .fail:
  605.  
  606.         ret
  607.  
  608.  
  609.  
  610.  
  611. cmd_nick:
  612.  
  613.         cmp     byte[esi+4], ' '
  614.         jne     .fail
  615.         add     esi, 5          ; skip 'NICK '
  616.         cmp     byte[esi], ':'
  617.         jne     @f
  618.         inc     esi
  619.   @@:
  620.  
  621. ; Is it me who changed nick?
  622.         push    esi
  623.         mov     edi, servercommand+1
  624.         call    compare_to_nick
  625.         jne     .not_me
  626.  
  627.         mov     ecx, MAX_NICK_LEN-1
  628.         mov     esi, [esp]
  629.   @@:
  630.         lodsb
  631.         test    al, al
  632.         jz      @f
  633.         cmp     al, ' '
  634.         je      @f
  635.         cmp     al, 10
  636.         je      @f
  637.         cmp     al, 13
  638.         je      @f
  639.         stosb
  640.         dec     ecx
  641.         jnz     @r
  642.   @@:
  643.         xor     al, al
  644.         stosb
  645.   .not_me:
  646.  
  647.         mov     ebx, windows
  648.         mov     ecx, MAX_WINDOWS
  649.   .window_loop:
  650.         push    ecx ebx
  651.         cmp     [ebx + window.type], WINDOWTYPE_CHANNEL
  652.         jne     .next_window
  653.  
  654.         mov     esi, servercommand+1
  655.         call    user_remove
  656.         test    edi, edi
  657.         jz      .next_window
  658.  
  659.         mov     esi, [esp + 8]
  660.         call    user_add
  661.  
  662.         mov     [window_print], ebx
  663.  
  664.         if TIMESTAMP
  665.         call    print_timestamp
  666.         end if
  667.  
  668.         mov     esi, nick_header
  669.         call    print_text2
  670.  
  671.         mov     eax, servercommand+1
  672.         mov     dl, '!'
  673.         call    print_text
  674.  
  675.         mov     esi, is_now_known_as
  676.         call    print_text2
  677.  
  678.         mov     esi, [esp + 8]  ; FIXME: dont print the 0x0a0d!!!
  679.         call    print_text2
  680.  
  681.         mov     esi, str_newline
  682.         call    print_text2
  683.  
  684.   .next_window:
  685.         pop     ebx ecx
  686.         add     ebx, sizeof.window
  687.         dec     ecx
  688.         jnz     .window_loop
  689.  
  690.         pop     esi
  691.  
  692.   .fail:
  693.  
  694.         ret
  695.  
  696.  
  697.  
  698.  
  699. cmd_kick:
  700.  
  701.         cmp     byte [esi+4], ' '
  702.         jne     .fail
  703.         add     esi, 5  ; skip 'KICK '
  704. ; Is it me who got kicked?
  705.         mov     edi, servercommand+1
  706.         call    compare_to_nick
  707.         jne     .not_me
  708.  
  709. ; TODO: mark channel as disconnected
  710.  
  711.   .not_me:
  712. ; find the channel user has been kicked from
  713.         push    esi
  714.         call    skip_nick
  715.         call    window_open
  716.  
  717.         if TIMESTAMP
  718.         call    print_timestamp
  719.         end if
  720.  
  721.         mov     esi, kick_header
  722.         call    print_text2
  723.  
  724.         mov     eax, servercommand+1
  725.         mov     dl, '!'
  726.         call    print_text
  727.  
  728.         mov     esi, kicked
  729.         call    print_text2
  730.  
  731.         pop     esi
  732.         call    print_text2
  733.  
  734.         mov     esi, str_newline
  735.         call    print_text2
  736.  
  737.         mov     ebx, [window_print]
  738.         mov     esi, servercommand+1
  739.         call    user_remove
  740.  
  741.   .fail:
  742.  
  743.         ret
  744.  
  745.  
  746.  
  747. cmd_quit:
  748.  
  749.         cmp     byte [esi+4], ' '
  750.         jne     .fail
  751.  
  752.         mov     ebx, windows
  753.         mov     ecx, MAX_WINDOWS
  754.  
  755.   .window_loop:
  756.         push    ecx
  757.         cmp     [ebx + window.type], WINDOWTYPE_CHANNEL
  758.         jne     .next_window
  759.  
  760.         mov     esi, servercommand+1
  761.         call    user_remove
  762.         test    edi, edi
  763.         jz      .next_window
  764.  
  765.         push    ebx
  766.         mov     [window_print], ebx
  767.  
  768.         if TIMESTAMP
  769.         call    print_timestamp
  770.         end if
  771.  
  772.         mov     esi, quit_header
  773.         call    print_text2
  774.  
  775.         mov     eax, servercommand+1
  776.         mov     dl, '!'
  777.         call    print_text
  778.  
  779.         mov     esi, has_quit_irc
  780.         call    print_text2
  781.  
  782. ; TODO: check if quit message was given, and print it to the window
  783.         pop     ebx
  784.   .next_window:
  785.         pop     ecx
  786.         add     ebx, sizeof.window
  787.         dec     ecx
  788.         jnz     .window_loop
  789.  
  790.   .fail:
  791.  
  792.  
  793.         ret
  794.  
  795.  
  796.  
  797. cmd_mode:
  798.  
  799.         cmp     byte [esi+4], ' '
  800.         jne     .fail
  801.         add     esi, 5  ; skip 'MODE '
  802.         call    window_find
  803.         test    ebx, ebx
  804.         jz      .fail
  805.  
  806. ; skip channel name
  807.   @@:
  808.         lodsb
  809.         test    al, al
  810.         jz      .fail
  811.         cmp     al, 10
  812.         je      .fail
  813.         cmp     al, 13
  814.         je      .fail
  815.         cmp     al, ' '
  816.         jne     @r
  817.         push    esi
  818.  
  819.         if TIMESTAMP
  820.         call    print_timestamp
  821.         end if
  822.  
  823.         mov     esi, mode_header
  824.         call    print_text2
  825.  
  826.         mov     eax, servercommand+1
  827.         mov     dl, '!'
  828.         call    print_text
  829.  
  830.         mov     esi, sets_mode
  831.         call    print_text2
  832.  
  833.         pop     esi
  834.         call    print_text2
  835.  
  836.         mov     esi, str_newline
  837.         call    print_text2
  838.  
  839. ;;; TODO: change username if needed
  840.  
  841.   .fail:
  842.  
  843.         ret
  844.  
  845.  
  846. cmd_353:                ; channel usernames reply
  847.  
  848.         add     esi, 4  ; skip '353 '
  849.         call    skip_nick
  850.         inc     esi     ; channel type '*', '=' or '@'
  851.         inc     esi     ; ' '
  852.         call    window_open
  853.  
  854. ; now find window ptr and check if this is the first 353 message
  855.         mov     ebx, [window_print]
  856.         test    [ebx + window.flags], FLAG_RECEIVING_NAMES
  857.         jnz     .add
  858.  
  859.         or      [ebx + window.flags], FLAG_RECEIVING_NAMES
  860. ;        mov     [ebx + window.users], 0
  861.         ; TODO: remove all users?
  862.  
  863.   .add:
  864.         push    esi
  865.         call    user_add
  866.         pop     esi
  867.  
  868.   .namesloop:
  869.         lodsb
  870.         test    al, al
  871.         jz      .done
  872.         cmp     al, ' '                 ; names list is separated with spaces
  873.         jne     .namesloop
  874.         jmp     .add
  875.  
  876.   .done:
  877.         call    draw_channel_list
  878.  
  879.         ret
  880.  
  881.  
  882.  
  883.  
  884.  
  885. cmd_366:        ; channel usernames end
  886.  
  887.         add     esi, 4          ; skip '366 '
  888.         call    skip_nick
  889.         call    window_open
  890.  
  891.         mov     ebx, [window_print]
  892.         and     [ebx + window.flags], not FLAG_RECEIVING_NAMES
  893.  
  894.         ret
  895.  
  896.  
  897.  
  898.  
  899. cmd_topic:
  900.  
  901.         add     esi, 4          ; skip '332 '
  902.         call    skip_nick
  903.         call    window_open
  904.  
  905.         if TIMESTAMP
  906.         call    print_timestamp
  907.         end if
  908.  
  909.         push    esi
  910.         mov     esi, topic_header
  911.         call    print_text2
  912.  
  913.         mov     esi, str_topic
  914.         call    print_text2
  915.  
  916.         pop     esi
  917.         call    print_text2
  918.  
  919.         mov     esi, str_newline
  920.         call    print_text2
  921.  
  922.         ret
  923.  
  924.  
  925. cmd_333:
  926.  
  927.         add     esi, 4          ; skip '333 '
  928.         call    skip_nick               ;;;;
  929.         call    window_open
  930.  
  931. ;        mov     ecx, 2  ; number of spaces to find    ;;; CHECKME
  932. ;  .loop:
  933. ;        lodsb
  934. ;        test    al, al
  935. ;        je      .fail
  936. ;        cmp     al, ' '
  937. ;        jne     .loop
  938. ;        dec     ecx
  939. ;        jnz     .loop   ; find some more spaces
  940.  
  941.         if TIMESTAMP
  942.         call    print_timestamp
  943.         end if
  944.  
  945.         push    esi
  946.         mov     esi, topic_header
  947.         call    print_text2
  948.  
  949.         mov     esi, str_setby
  950.         call    print_text2
  951.  
  952. ;        pop     esi
  953. ;        call    print_text2
  954.  
  955.         pop     eax
  956.         mov     dl, '!'
  957.         call    print_text
  958.  
  959.         mov     esi, str_newline
  960.         call    print_text2
  961.  
  962.   .fail:
  963.         ret
  964.  
  965. cmd_322:        ; LIST
  966.  
  967.         add     esi, 4
  968.  
  969.         mov     [window_print], windows         ; FIXME
  970.         call    skip_nick
  971.         mov     eax, esi
  972.         mov     dl, 13
  973.         call    print_text
  974.         mov     esi, str_newline
  975.         call    print_text2
  976.  
  977.         ret
  978.  
  979. cmd_323:        ; LIST END
  980.  
  981.         ret