Subversion Repositories Kolibri OS

Rev

Rev 4477 | Rev 4617 | 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.         mov     ecx, MAX_NICK_LEN-1
  644.         mov     esi, [esp]
  645.   @@:
  646.         lodsb
  647.         test    al, al
  648.         jz      @f
  649.         cmp     al, ' '
  650.         je      @f
  651.         cmp     al, 10
  652.         je      @f
  653.         cmp     al, 13
  654.         je      @f
  655.         stosb
  656.         dec     ecx
  657.         jnz     @r
  658.   @@:
  659.         xor     al, al
  660.         stosb
  661.   .not_me:
  662.  
  663.         mov     ebx, windows
  664.         mov     ecx, MAX_WINDOWS
  665.   .window_loop:
  666.         push    ecx ebx
  667.         cmp     [ebx + window.type], WINDOWTYPE_CHANNEL
  668.         jne     .next_window
  669.  
  670.         mov     esi, servercommand+1
  671.         call    user_remove
  672.         test    edi, edi
  673.         jz      .next_window
  674.  
  675.         mov     esi, [esp + 8]
  676.         call    user_add
  677.  
  678.         mov     [window_print], ebx
  679.  
  680.         if TIMESTAMP
  681.         call    print_timestamp
  682.         end if
  683.  
  684.         mov     esi, nick_header
  685.         call    print_text2
  686.  
  687.         mov     eax, servercommand+1
  688.         mov     dl, '!'
  689.         call    print_text
  690.  
  691.         mov     esi, is_now_known_as
  692.         call    print_text2
  693.  
  694.         mov     esi, [esp + 8]  ; FIXME: dont print the 0x0a0d!!!
  695.         call    print_text2
  696.  
  697.         mov     esi, str_newline
  698.         call    print_text2
  699.  
  700.   .next_window:
  701.         pop     ebx ecx
  702.         add     ebx, sizeof.window
  703.         dec     ecx
  704.         jnz     .window_loop
  705.  
  706.         pop     esi
  707.  
  708.   .fail:
  709.  
  710.         ret
  711.  
  712.  
  713.  
  714.  
  715. cmd_kick:
  716.  
  717.         cmp     byte [esi+4], ' '
  718.         jne     .fail
  719.         add     esi, 5  ; skip 'KICK '
  720.  
  721. ; TODO: Is it me who got kicked?
  722. ; if so, mark channel as disconnected
  723.  
  724.   .not_me:
  725. ; find the channel user has been kicked from
  726.         push    esi
  727.         call    window_open
  728.         push    esi
  729.  
  730.         if TIMESTAMP
  731.         call    print_timestamp
  732.         end if
  733.  
  734.         mov     esi, kick_header
  735.         call    print_text2
  736.  
  737.         pop     eax
  738.         mov     dl, ' '
  739.         call    print_text
  740.  
  741.         mov     esi, str_kicked
  742.         call    print_text2
  743.  
  744.         pop     eax
  745.         mov     dl, ' '
  746.         call    print_text2
  747.  
  748.         mov     esi, str_by
  749.         call    print_text2
  750.  
  751.         mov     eax, servercommand+1
  752.         mov     dl, '!'
  753.         call    print_text
  754.  
  755.         mov     esi, str_dotnewline
  756.         call    print_text2
  757.  
  758.         mov     ebx, [window_print]
  759.         mov     esi, servercommand+1
  760.         call    user_remove
  761.  
  762.   .fail:
  763.  
  764.         ret
  765.  
  766.  
  767.  
  768. cmd_quit:
  769.  
  770.         cmp     byte [esi+4], ' '
  771.         jne     .fail
  772.  
  773.         mov     ebx, windows
  774.         mov     ecx, MAX_WINDOWS
  775.  
  776.   .window_loop:
  777.         push    ecx
  778.         cmp     [ebx + window.type], WINDOWTYPE_CHANNEL
  779.         jne     .next_window
  780.  
  781.         mov     esi, servercommand+1
  782.         call    user_remove
  783.         test    edi, edi
  784.         jz      .next_window
  785.  
  786.         push    ebx
  787.         mov     [window_print], ebx
  788.  
  789.         if TIMESTAMP
  790.         call    print_timestamp
  791.         end if
  792.  
  793.         mov     esi, quit_header
  794.         call    print_text2
  795.  
  796.         mov     eax, servercommand+1
  797.         mov     dl, '!'
  798.         call    print_text
  799.  
  800.         mov     esi, has_quit_irc
  801.         call    print_text2
  802.  
  803. ; TODO: check if quit message was given, and print it to the window
  804.         pop     ebx
  805.   .next_window:
  806.         pop     ecx
  807.         add     ebx, sizeof.window
  808.         dec     ecx
  809.         jnz     .window_loop
  810.  
  811.   .fail:
  812.  
  813.  
  814.         ret
  815.  
  816.  
  817.  
  818. cmd_mode:
  819.  
  820.         cmp     byte [esi+4], ' '
  821.         jne     .fail
  822.         add     esi, 5  ; skip 'MODE '
  823.         call    window_find
  824.         test    ebx, ebx
  825.         jz      .fail
  826.         mov     [window_print], ebx
  827.         push    esi
  828.  
  829.         if TIMESTAMP
  830.         call    print_timestamp
  831.         end if
  832.  
  833.         mov     esi, mode_header
  834.         call    print_text2
  835.  
  836.         mov     eax, servercommand+1
  837.         mov     dl, '!'
  838.         call    print_text
  839.  
  840.         mov     esi, sets_mode
  841.         call    print_text2
  842.  
  843.         pop     esi
  844.         call    print_text2
  845.  
  846.         mov     esi, str_newline
  847.         call    print_text2
  848.  
  849. ;;; TODO: change username if needed
  850.  
  851.   .fail:
  852.  
  853.         ret
  854.  
  855.  
  856. cmd_353:                ; channel usernames reply
  857.  
  858.         add     esi, 4  ; skip '353 '
  859.         call    skip_parameter
  860.         inc     esi     ; channel type '*', '=' or '@'
  861.         inc     esi     ; ' '
  862.         call    window_open
  863.  
  864. ; now find window ptr and check if this is the first 353 message
  865.         mov     ebx, [window_print]
  866.         test    [ebx + window.flags], FLAG_RECEIVING_NAMES
  867.         jnz     .add
  868.  
  869.         or      [ebx + window.flags], FLAG_RECEIVING_NAMES
  870. ;        mov     [ebx + window.users], 0
  871.         ; TODO: remove all users?
  872.  
  873.   .add:
  874.         push    esi
  875.         call    user_add
  876.         pop     esi
  877.  
  878.   .namesloop:
  879.         lodsb
  880.         test    al, al
  881.         jz      .done
  882.         cmp     al, ' '                 ; names list is separated with spaces
  883.         jne     .namesloop
  884.         jmp     .add
  885.  
  886.   .done:
  887.         call    draw_channel_list
  888.  
  889.         ret
  890.  
  891.  
  892.  
  893.  
  894.  
  895. cmd_366:        ; channel usernames end
  896.  
  897.         add     esi, 4          ; skip '366 '
  898.         call    skip_parameter
  899.         call    window_open
  900.  
  901.         mov     ebx, [window_print]
  902.         and     [ebx + window.flags], not FLAG_RECEIVING_NAMES
  903.  
  904.         ret
  905.  
  906.  
  907.  
  908.  
  909. cmd_topic:
  910.  
  911.         add     esi, 4          ; skip '332 '
  912.         call    skip_parameter
  913.         call    window_open
  914.  
  915.         if TIMESTAMP
  916.         call    print_timestamp
  917.         end if
  918.  
  919.         push    esi
  920.         mov     esi, topic_header
  921.         call    print_text2
  922.  
  923.         mov     esi, str_topic
  924.         call    print_text2
  925.  
  926.         pop     esi
  927.         call    print_text2
  928.  
  929.         mov     esi, str_topic_end
  930.         call    print_text2
  931.  
  932.         ret
  933.  
  934.  
  935. cmd_333:
  936.  
  937.         add     esi, 4          ; skip '333 '
  938.         call    skip_parameter               ;;;;
  939.         call    window_open
  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_parameter
  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