Subversion Repositories Kolibri OS

Rev

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