Subversion Repositories Kolibri OS

Rev

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

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