/kernel/branches/net/applications/ircc/encodings.inc |
---|
0,0 → 1,317 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; ;; |
;; GNU GENERAL PUBLIC LICENSE ;; |
;; Version 2, June 1991 ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
get_next_byte: |
; Load next byte from the packet, translating to cp866 if necessary |
; At input esi = pointer to data, edx = limit of data |
; Output is either (translated) byte in al with CF set or CF cleared. |
mov eax, [encoding] |
jmp [get_byte_table+eax*4] |
get_byte_cp866: |
cmp esi, edx |
jae .nothing |
lodsb |
.nothing: |
ret |
get_byte_cp1251: |
cmp esi, edx |
jae .nothing |
lodsb |
cmp al, 0x80 |
jb @f |
and eax, 0x7F |
mov al, [cp1251_table+eax] |
@@: |
stc |
.nothing: |
ret |
get_byte_utf8: |
; UTF8 decoding is slightly complicated. |
; One character can occupy one or more bytes. |
; The boundary in packets theoretically can be anywhere in data, |
; so this procedure keeps internal state between calls and handles |
; one byte at a time, looping until character is read or packet is over. |
; Globally, there are two distinct tasks: decode byte sequence to unicode char |
; and convert this unicode char to our base encoding (that is cp866). |
; 1. Check that there are data. |
cmp esi, edx |
jae .nothing |
; 2. Load byte. |
lodsb |
movzx ecx, al |
; 3. Bytes in an UTF8 sequence can be of any of three types. |
; If most significant bit is cleared, sequence is one byte and usual ASCII char. |
; First byte of a sequence must be 11xxxxxx, other bytes are 10yyyyyy. |
and al, 0xC0 |
jns .single_byte |
jp .first_byte |
; 4. This byte is not first in UTF8 sequence. |
; 4a. Check that the sequence was started. If no, it is invalid byte |
; and we simply ignore it. |
cmp [utf8_bytes_rest], 0 |
jz get_byte_utf8 |
; 4b. Otherwise, it is really next byte and it gives some more bits of char. |
mov eax, [utf8_char] |
shl eax, 6 |
lea eax, [eax+ecx-0x80] |
; 4c. Decrement number of bytes rest in the sequence. |
; If it goes to zero, character is read, so return it. |
dec [utf8_bytes_rest] |
jz .got_char |
mov [utf8_char], eax |
jmp get_byte_utf8 |
; 5. If the byte is first in UTF8 sequence, calculate the number of leading 1s |
; - it equals total number of bytes in the sequence; some other bits rest for |
; leading bits in the character. |
.first_byte: |
mov eax, -1 |
@@: |
inc eax |
add cl, cl |
js @b |
mov [utf8_bytes_rest], eax |
xchg eax, ecx |
inc ecx |
shr al, cl |
mov [utf8_char], eax |
jmp get_byte_utf8 |
; 6. If the byte is ASCII char, it is the character. |
.single_byte: |
xchg eax, ecx |
.got_char: |
; We got the character, now abandon a possible sequence in progress. |
and [utf8_bytes_rest], 0 |
; Now second task. The unicode character is in eax, and now we shall convert it |
; to cp866. |
cmp eax, 0x80 |
jb .done |
; 0x410-0x43F -> 0x80-0xAF, 0x440-0x44F -> 0xE0-0xEF, 0x401 -> 0xF0, 0x451 -> 0xF1 |
cmp eax, 0x401 |
jz .YO |
cmp eax, 0x451 |
jz .yo |
cmp eax, 0x410 |
jb .unrecognized |
cmp eax, 0x440 |
jb .part1 |
cmp eax, 0x450 |
jae .unrecognized |
sub al, (0x40-0xE0) and 0xFF |
ret |
.part1: |
sub al, 0x10-0x80 |
.nothing: |
.done: |
ret |
.unrecognized: |
mov al, '?' |
stc |
ret |
.YO: |
mov al, 0xF0 |
stc |
ret |
.yo: |
mov al, 0xF1 |
stc |
ret |
print_character: |
pusha |
cmp bl, 13 ; line beginning |
jne nobol |
mov ecx, [pos] |
inc ecx |
boll1: |
dec ecx |
mov eax, ecx |
xor edx, edx |
mov ebx, [textbox_width] |
div ebx |
test edx, edx |
jnz boll1 |
mov [pos], ecx |
jmp newdata |
nobol: |
cmp bl, 10 ; line down |
jne nolf |
addx1: |
inc [pos] |
mov eax, [pos] |
xor edx, edx |
mov ecx, [textbox_width] |
div ecx |
test edx, edx |
jnz addx1 |
mov eax, [pos] |
jmp cm1 |
nolf: |
no_lf_ret: |
cmp bl, 15 ; character |
jbe newdata |
mov eax, [irc_data] |
shl eax, 8 |
mov al, bl |
mov [irc_data], eax |
mov eax, [pos] |
;---- draw data |
pusha |
and ebx, 0xff |
add eax, [text_start] |
mov [eax], bl |
popa |
;---- draw data |
mov eax, [pos] |
inc eax |
cm1: |
mov ebx, [scroll+4] |
imul ebx, [textbox_width] |
cmp eax, ebx |
jb noeaxz |
mov esi, [text_start] |
add esi, [textbox_width] |
mov edi, [text_start] |
mov ecx, ebx |
rep movsb |
mov esi, [text_start] |
mov ecx, [textbox_width] |
imul ecx, 61 |
add esi, ecx |
mov edi, [text_start] |
mov ecx, [textbox_width] |
imul ecx, 60 |
add edi, ecx |
mov ecx, ebx |
rep movsb |
mov eax, ebx |
sub eax, [textbox_width] |
noeaxz: |
mov [pos], eax |
newdata: |
mov eax, [window_print] |
or [eax + window.flags], FLAG_UPDATED |
popa |
ret |
recode_to_cp866: |
rep movsb |
ret |
recode_to_cp1251: |
xor eax, eax |
jecxz .nothing |
.loop: |
lodsb |
cmp al,0x80 |
jb @f |
mov al, [cp866_table-0x80+eax] |
@@: stosb |
loop .loop |
.nothing: |
ret |
recode_to_utf8: |
jecxz .nothing |
.loop: |
lodsb |
cmp al, 0x80 |
jb .single_byte |
and eax, 0x7F |
mov ax, [utf8_table+eax*2] |
stosw |
loop .loop |
ret |
.single_byte: |
stosb |
loop .loop |
.nothing: |
ret |
recode: |
mov eax, [encoding] |
jmp [recode_proc+eax*4] |
encoding dd UTF8 |
recode_proc dd recode_to_cp866, recode_to_cp1251, recode_to_utf8 |
get_byte_table dd get_byte_cp866, get_byte_cp1251, get_byte_utf8 |
cp1251_table: |
db '?','?','?','?','?','?','?','?' , '?','?','?','?','?','?','?','?' ; 8 |
db '?','?','?','?','?',$F9,'?','?' , '?','?','?','?','?','?','?','?' ; 9 |
db '?',$F6,$F7,'?',$FD,'?','?','?' , $F0,'?',$F2,'?','?','?','?',$F4 ; A |
db $F8,'?','?','?','?','?','?',$FA , $F1,$FC,$F3,'?','?','?','?',$F5 ; B |
db $80,$81,$82,$83,$84,$85,$86,$87 , $88,$89,$8A,$8B,$8C,$8D,$8E,$8F ; C |
db $90,$91,$92,$93,$94,$95,$96,$97 , $98,$99,$9A,$9B,$9C,$9D,$9E,$9F ; D |
db $A0,$A1,$A2,$A3,$A4,$A5,$A6,$A7 , $A8,$A9,$AA,$AB,$AC,$AD,$AE,$AF ; E |
db $E0,$E1,$E2,$E3,$E4,$E5,$E6,$E7 , $E8,$E9,$EA,$EB,$EC,$ED,$EE,$EF ; F |
; 0 1 2 3 4 5 6 7 8 9 A B C D E F |
utf8_table: |
times 80h dw 0x98C3 ; default placeholder |
; 0x80-0xAF -> 0x90D0-0xBFD0 |
repeat 0x30 |
store byte 0xD0 at utf8_table+2*(%-1) |
store byte 0x90+%-1 at utf8_table+2*%-1 |
end repeat |
; 0xE0-0xEF -> 0x80D1-0x8FD1 |
repeat 0x10 |
store byte 0xD1 at utf8_table+2*(0xE0-0x80+%-1) |
store byte 0x80+%-1 at utf8_table+2*(0xE0-0x80+%)-1 |
end repeat |
; 0xF0 -> 0x81D0, 0xF1 -> 0x91D1 |
store dword 0x91D181D0 at utf8_table+2*(0xF0-0x80) |
cp866_table: |
db $C0,$C1,$C2,$C3,$C4,$C5,$C6,$C7 , $C8,$C9,$CA,$CB,$CC,$CD,$CE,$CF ; 8 |
db $D0,$D1,$D2,$D3,$D4,$D5,$D6,$D7 , $D8,$D9,$DA,$DB,$DC,$DD,$DE,$DF ; 9 |
db $E0,$E1,$E2,$E3,$E4,$E5,$E6,$E7 , $E8,$E9,$EA,$EB,$EC,$ED,$EE,$EF ; A |
db '?','?','?','?','?','?','?','?' , '?','?','?','?','?','?','?','?' ; B |
db '?','?','?','?','?','?','?','?' , '?','?','?','?','?','?','?','?' ; C |
db '?','?','?','?','?','?','?','?' , '?','?','?','?','?','?','?','?' ; D |
db $F0,$F1,$F2,$F3,$F4,$F5,$F6,$F7 , $F8,$F9,$FA,$FB,$FC,$FD,$FE,$FF ; E |
db $A8,$B8,$AA,$BA,$AF,$BF,$A1,$A2 , $B0,$95,$B7,'?',$B9,$A4,'?','?' ; F |
; 0 1 2 3 4 5 6 7 8 9 A B C D E F |
/kernel/branches/net/applications/ircc/gui.inc |
---|
0,0 → 1,241 |
draw_window: |
pusha |
mcall 9, thread_info, -1 ; get current window size |
mov eax, dword[thread_info+42] ; window xsize |
mov ebx, dword[thread_info+46] ; ysize |
mov edx, dword[thread_info+62] ; work area xsize |
mov esi, dword[thread_info+66] ; ysize |
sub eax, edx |
sub ebx, esi |
cmp edx, WIN_MIN_X |
jae .x_ok |
mov edx, WIN_MIN_X |
.x_ok: |
mov [xsize], edx |
add edx, eax |
cmp esi, WIN_MIN_Y |
jae .y_ok |
mov esi, WIN_MIN_Y |
.y_ok: |
mov [ysize], esi |
add esi, ebx |
mcall 67, -1, -1 ; set the new sizes |
mcall 12, 1 |
xor eax, eax ; draw window |
mov ebx, WIN_MIN_X |
mov ecx, WIN_MIN_Y |
mov edx, [colors.work] |
add edx, 0x33000000 |
mov edi, str_programname |
mcall |
mov ebx, [xsize] |
mov ecx, [ysize] |
sub cx, 35 |
push cx |
shl ecx, 16 |
pop cx |
mov edx, [colors.work_graph] |
mcall 38 ; draw line |
mov ecx, TOP_Y SHL 16 + TOP_Y |
mcall |
mov edi, [window_open] |
cmp [edi + window.type], WINDOWTYPE_CHANNEL |
jne .not_channel |
mov ebx, [xsize] |
sub ebx, 100 |
push bx |
shl ebx, 16 |
pop bx |
mov ecx, [ysize] |
add ecx, TOP_Y SHL 16 -(15+20) |
mcall |
call print_channel_list |
.not_channel: |
mov edx, [edi + window.data_ptr] |
add edx, window_data.text |
call draw_channel_text |
; editbox |
mov eax, [ysize] |
sub eax, 30 ;;;;;; |
mov [edit1.top], eax |
mov eax, [xsize] |
sub eax, 10 ;;;;;; |
mov [edit1.width], eax |
push dword edit1 |
call [edit_box_draw] |
; scrollbar |
mov eax, [ysize] |
sub eax, TOP_Y + 35 ;;;; |
mov [scroll1.y_size], ax |
mov eax, [xsize] |
sub eax, SCROLLBAR_WIDTH |
mov [scroll1.x_pos], ax |
mov [scroll1.all_redraw], 1 |
push dword scroll1 |
call [scrollbar_v_draw] |
call draw_windownames |
mcall 12, 2 |
popa |
ret |
print_channel_list: |
pusha |
mov eax, 13 ; draw rectangle (clear list) |
mov ebx, [xsize] |
sub ebx, 95 |
shl ebx, 16 |
push ebx |
mov bx, 90 ; x size ;;; FIXME |
mov ecx, TEXT_Y shl 16 + 12*10 ; y size ;;; FIXME |
mov edx, [colors.work] |
mcall |
mov eax, 4 ; draw text |
pop ebx |
mov bx, TEXT_Y |
mov ecx, [colors.work_text] |
or ecx, 0x80000000 ; ASCIIZ string |
mov edx, [window_open] |
mov edx, [edx + window.data_ptr] |
add edx, window_data.names |
mov edi, MAX_CHANNELS |
.loop: |
mcall |
add edx, MAX_NICK_LEN ; next name |
add ebx, 10 ; height distance between lines |
dec edi |
jnz .loop |
popa |
ret |
draw_channel_text: |
pusha |
mov eax, 4 ; draw text |
mov ebx, TEXT_X shl 16 + TEXT_Y |
mov ecx, 12 ; 12 lines max ? |
mov esi, [textbox_width] |
.dct: |
pusha |
mov cx, bx |
shl ecx, 16 |
mov cx, 9 ; character height |
mov eax, 13 ; draw rectangle |
mov ebx, TEXT_X shl 16 |
mov bx, word[textbox_width] |
imul bx, 6 ; character width |
mov edx, [colors.work] |
mcall |
popa |
push ecx |
mov ecx, [colors.work_text] |
cmp word[edx], '* ' |
jne .no_red |
mov ecx, 0x00aa0000 |
jmp .draw |
.no_red: |
cmp word[edx], '**' |
jne .no_light_blue |
cmp byte[edx+2], '*' |
jne .no_light_blue |
mov ecx, 0x000000aa |
jmp .draw |
.no_light_blue: |
cmp byte[edx], '#' |
jne .no_blue |
mov ecx, 0x0000aa00 |
; jmp .draw |
.no_blue: |
.draw: |
mcall |
add edx, [textbox_width] |
add ebx, 10 ; height distance between lines |
pop ecx |
loop .dct |
popa |
ret |
draw_windownames: |
mov eax, 8 |
mov ebx, 5 shl 16 + 120 |
mov ecx, 12 shl 16 + 12 |
mov edx, WINDOW_BTN_START |
mov edi, windows |
.more_btn: |
mov esi, [colors.work_button] |
cmp [window_open], edi |
jne @f |
not esi |
and esi, 0x00ffffff |
@@: |
mcall |
inc edx |
add ebx, 125 shl 16 |
add edi, sizeof.window |
cmp [edi + + window.data_ptr], 0 |
jne .more_btn |
mov eax, 4 |
mov ebx, 10 shl 16 + 15 |
mov ecx, [colors.work_button_text] |
or ecx, 0x80000000 ; ASCIIZ string |
lea edx, [windows + window.name] |
mov esi, MAX_WINDOWS |
.more: |
mcall |
add edx, sizeof.window |
cmp byte[edx], 0 |
je .enough |
add ebx, 125 shl 16 |
dec esi |
jnz .more |
.enough: |
ret |
/kernel/branches/net/applications/ircc/ircc.asm |
---|
0,0 → 1,449 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; IRC client for KolibriOS ;; |
;; ;; |
;; Written by hidnplayr@kolibrios.org, ;; |
;; text encoder/decoder by Clevermouse. ;; |
;; ;; |
;; GNU GENERAL PUBLIC LICENSE ;; |
;; Version 2, June 1991 ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
version equ '0.1' |
; connection status |
STATUS_DISCONNECTED = 0 |
STATUS_RESOLVING = 1 |
STATUS_CONNECTING = 2 |
STATUS_CONNECTED = 3 |
; window flags |
FLAG_UPDATED = 1 shl 0 |
FLAG_CLOSE = 1 shl 1 |
; window types |
WINDOWTYPE_SERVER = 0 |
WINDOWTYPE_CHANNEL = 1 |
WINDOWTYPE_CHAT = 2 |
WINDOWTYPE_LIST = 3 |
WINDOWTYPE_DCC = 4 |
; supported encodings |
CP866 = 0 |
CP1251 = 1 |
UTF8 = 2 |
; settings |
USERCMD_MAX_SIZE = 400 |
WIN_MIN_X = 600 |
WIN_MIN_Y = 200 |
TEXT_X = 5 |
TEXT_Y = 45 |
TOP_Y = 40 |
MAX_WINDOWS = 20 |
MAX_NICK_LEN = 32 |
MAX_REAL_LEN = 32 ; realname |
MAX_SERVER_NAME = 256 |
MAX_CHANNEL_LEN = 40 |
MAX_CHANNELS = 37 |
MAX_COMMAND_LEN = 512 |
TIMESTAMP = 3 ; 3 = hh:mm:ss, 2 = hh:mm, 0 = no timestamp |
MAX_WINDOWNAME_LEN = 256 |
WINDOW_BTN_START = 100 |
SCROLLBAR_WIDTH = 12 |
format binary as "" |
use32 |
org 0x0 |
db 'MENUET01' ; 8 byte id |
dd 1 ; header version |
dd START ; program start |
dd I_END ; program image size |
dd IM_END+2048 ; required amount of memory |
dd IM_END+2048 |
dd 0 |
dd path |
include "../macros.inc" |
include "../proc32.inc" |
include "../dll.inc" |
include "../network.inc" |
include "../struct.inc" |
include '../../../../../programs/develop/libraries/box_lib/trunk/box_lib.mac' |
struct window |
data_ptr dd ? ; zero if not used |
flags db ? |
type db ? |
name rb MAX_WINDOWNAME_LEN |
ends |
struct window_data |
text rb 120*60 |
title rb 256 |
names rb 1200 |
namespos dd ? |
usertext rb 256 |
usertextlen dd ? |
ends |
include "encodings.inc" |
include "window.inc" ; also contains text print routines |
include "serverparser.inc" |
include "userparser.inc" |
include "socket.inc" |
include "gui.inc" |
START: |
mcall 68, 11 ; init heap so we can allocate memory dynamically |
; wanted events |
mcall 40, EVM_REDRAW + EVM_KEY + EVM_BUTTON + EVM_STACK + EVM_MOUSE |
; load libraries |
stdcall dll.Load, @IMPORT |
test eax, eax |
jnz exit |
; find path to main settings file (ircc.ini) |
mov edi, path ; Calculate the length of zero-terminated string |
xor al, al |
mov ecx, 1024 |
repne scasb |
dec edi |
mov eax, '.ini' |
stosd |
xor al, al |
stosb |
; Fill the window buffer with zeros |
mov edi, windows |
mov ecx, (sizeof.window*MAX_WINDOWS+3)/4 |
xor eax, eax |
rep stosd |
; clear command area too |
mov edi, servercommand |
mov ecx, 600/4 |
rep stosd |
; allocate window data block |
call window_create |
mov ebx, windows |
mov [ebx + window.data_ptr], eax |
mov [ebx + window.flags], 0 |
mov [ebx + window.type], WINDOWTYPE_SERVER |
add eax, window_data.text |
mov [text_start], eax |
call window_refresh |
; get system colors |
mcall 48, 3, colors, 40 |
; set edit box and scrollbar colors |
mov eax, [colors.work] |
mov [scroll1.bg_color], eax |
mov eax, [colors.work_button] |
mov [scroll1.front_color], eax |
mov eax, [colors.work_text] |
mov [scroll1.line_color], eax |
; get settings from ini |
invoke ini.get_str, path, str_user, str_nick, user_nick, MAX_NICK_LEN, default_nick |
invoke ini.get_str, path, str_user, str_real, user_real_name, MAX_REAL_LEN, default_real |
; Welcome user |
mov esi, str_welcome |
call print_text2 |
call draw_window ;;; FIXME (gui is not correctly drawn first time) |
redraw: |
call draw_window |
still: |
; wait here for event |
mcall 10 |
dec eax |
jz redraw |
dec eax |
jz main_window_key |
dec eax |
jz button |
cmp al, 3 |
je mouse |
call process_network_event |
mov edx, [window_open] |
test [edx + window.flags], FLAG_UPDATED |
jz .no_update |
and [edx + window.flags], not FLAG_UPDATED |
mov edx, [edx + window.data_ptr] |
add edx, window_data.text |
call draw_channel_text |
.no_update: |
call print_channel_list |
jmp still |
button: |
mcall 17 ; get id |
shr eax, 8 |
cmp ax, 1 ; close program |
je exit |
sub ax, WINDOW_BTN_START |
jb exit |
cmp ax, MAX_WINDOWS |
ja exit |
mov dx, sizeof.window |
mul dx |
shl edx, 16 |
mov dx, ax |
add edx, windows |
cmp [edx + window.data_ptr], 0 |
je exit |
mov [window_open], edx |
call window_refresh |
call draw_window |
jmp still |
exit: |
mcall -1 |
main_window_key: |
mcall 2 |
push dword edit1 |
call [edit_box_key] |
cmp ah, 13 ; enter |
jne no_send2 |
call user_parser |
mov [edit1.size], 0 |
mov [edit1.pos], 0 |
push dword edit1 |
call [edit_box_draw] |
mov edx, [window_open] |
mov edx, [edx + window.data_ptr] |
add edx, window_data.text |
call draw_channel_text |
jmp still |
no_send2: |
jmp still |
mouse: |
push dword edit1 |
call [edit_box_mouse] |
push dword scroll1 |
call [scrollbar_v_mouse] |
jmp still |
; DATA AREA |
encoding_text: |
db 'CP866 ' |
db 'CP1251' |
db 'UTF-8 ' |
encoding_text_len = 6 |
action_header db '*** ', 0 |
action_header_short db '* ', 0 |
ctcp_header db '-> [',0 |
ctcp_version db '] VERSION',10,0 |
ctcp_ping db '] PING',10,0 |
ctcp_time db '] TIME',10,0 |
has_left_channel db ' has left ', 0 |
joins_channel db ' has joined ', 0 |
is_now_known_as db ' is now known as ', 0 |
has_quit_irc db ' has quit IRC', 0 |
sets_mode db ' sets mode ', 0 |
kicked db ' is kicked from ', 0 |
str_talking db 'Now talking in ',0 |
str_topic db 'Topic is ',0 |
str_setby db 'Set by ',0 |
str_version db 'VERSION ' |
str_programname db 'KolibriOS IRC client ', version, 0 |
str_user db 'user', 0 |
str_nick db 'nick', 0 |
str_real db 'realname', 0 |
str_email db 'email', 0 |
default_nick db 'kolibri_user', 0 |
default_real db 'Kolibri User', 0 |
str_welcome db 10 |
db '.______________________ .__ .__ __',10 |
db '| \______ \_ ___ \ ____ | | |__| ____ _____/ |_',10 |
db '| || _/ \ \/ _/ ___\| | | |/ __ \ / \ __\',10 |
db '| || | \ \____ \ \___| |_| \ ___/| | \ |',10 |
db '|___||____|_ /\______ / \___ >____/__|\___ >___| /__|',10 |
db ' \/ \/ \/ \/ \/',10 |
db 10 |
db 'Welcome to IRC client ',version,' for KolibriOS',10 |
db 10 |
db 'Type /help for help',10,0 |
str_nickchange db 10,'Nickname is now ',0 |
str_realchange db 10,'Real name is now ',0 |
str_dotnewline db '.',10, 0 |
str_newline db 10, 0 |
str_connecting db 10,'* Connecting to ',0 |
str_help db 10,'following commands are available:',10 |
db 10 |
db '/nick <nick> : change nickname to <nick>',10 |
db '/real <real name> : change real name to <real name>',10 |
db '/server <address> : connect to server <address>',10 |
db '/code <code> : change codepage to cp866, cp1251, or utf8',10,0 |
str_1 db ' -',0 |
str_2 db '- ',0 |
str_sockerr db 'Socket Error',10,0 |
str_dnserr db 'Unable to resolve hostname.',10,0 |
str_refused db 'Connection refused',10,0 |
sockaddr1: |
dw AF_INET4 |
.port dw 0x0b1a ; 6667 |
.ip dd 0 |
rb 10 |
status dd STATUS_DISCONNECTED |
channel_line_sun dd 0x9999ff |
channel_line_shadow dd 0x666699 |
index_list_2 dd 0x0000ff |
text_start dd ? ; pointer to current textbox data |
irc_data dd 0x0 ; encoder |
textbox_width dd 80 ; in characters, not pixels ;) |
pos dd 66 * 11 ; encoder |
window_open dd windows |
window_print dd windows |
scroll dd 1 |
dd 12 |
align 4 |
@IMPORT: |
library network, 'network.obj',\ |
libini, 'libini.obj',\ |
boxlib, 'box_lib.obj' |
import network,\ |
getaddrinfo, 'getaddrinfo',\ |
freeaddrinfo, 'freeaddrinfo',\ |
inet_ntoa, 'inet_ntoa' |
import libini,\ |
ini.get_str, 'ini_get_str',\ |
ini.get_int, 'ini_get_int' |
import boxlib,\ |
edit_box_draw ,'edit_box' ,\ |
edit_box_key ,'edit_box_key' ,\ |
edit_box_mouse ,'edit_box_mouse' ,\ |
scrollbar_v_draw ,'scrollbar_v_draw' ,\ |
scrollbar_v_mouse,'scrollbar_v_mouse' |
usercommand db '/server chat.freenode.net', 0 |
rb MAX_COMMAND_LEN |
I_END: |
; width, left, top |
edit1 edit_box 0, 5, 0, 0xffffff, 0x6f9480, 0, 0, 0, USERCMD_MAX_SIZE, usercommand, mouse_dd, ed_focus, 25, 25 |
; xsize, xpos, ysize, ypos, max, cur, pos, bgcol, frcol, linecol |
scroll1 scrollbar SCROLLBAR_WIDTH, 300, 150, TOP_Y, 10, 100, 0, 0, 0, 0, 0, 5 |
main_PID dd ? ; identifier of main thread |
utf8_bytes_rest dd ? ; bytes rest in current UTF8 sequence |
utf8_char dd ? ; first bits of current UTF8 character |
gai_reqdata rb 32 ; buffer for getaddrinfo_start/process |
ip_list dd ? ; will be filled as pointer to addrinfo list |
packetbuf rb 1024 ; buffer for packets to server |
path rb 1024 |
socketnum dd ? |
servercommand rb 600 |
thread_info rb 1024 |
xsize dd ? |
ysize dd ? |
colors system_colors |
irc_server_name rb MAX_SERVER_NAME |
user_nick rb MAX_NICK_LEN |
user_real_name rb MAX_REAL_LEN |
windows rb MAX_WINDOWS*sizeof.window |
mouse_dd dd ? |
IM_END: |
/kernel/branches/net/applications/ircc/ircc.ini |
---|
0,0 → 1,8 |
[user] |
nick = kolibri_user |
realname = tetten |
[colors] |
action1 = 0x000000aa |
action2 = 0x0000aa00 |
action3 = 0x00aa0000 |
/kernel/branches/net/applications/ircc/serverparser.inc |
---|
0,0 → 1,882 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; ;; |
;; GNU GENERAL PUBLIC LICENSE ;; |
;; Version 2, June 1991 ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
server_parser: |
mov esi, servercommand |
cmp byte [esi], ':' |
jne .parse |
.spaceloop: |
lodsb |
test al, al |
jz .fail |
cmp al, ' ' |
jne .spaceloop |
.parse: |
mov eax, [esi] |
or eax, 0x20202020 |
mov edi, server_commands |
mov ecx, server_commands.number |
.loop: |
scasd |
je .got_cmd |
add edi, 4 |
dec ecx |
jnz .loop |
.fail: |
ret |
.got_cmd: |
jmp dword[edi+4] |
server_commands: |
dd '328 ', cmd_328 |
dd '332 ', cmd_topic |
dd '333 ', cmd_333 ; nickname and time of topic |
dd '353 ', cmd_353 ; name reply |
dd '366 ', cmd_366 ; end of names list |
dd '372 ', cmd_372 ; motd |
dd '375 ', cmd_375 ; start of motd |
dd '376 ', cmd_376 ; end of motd |
dd '421 ', cmd_421 ; unknown command |
dd 'join', cmd_join |
dd 'kick', cmd_kick |
dd 'mode', cmd_mode |
dd 'nick', cmd_nick |
dd 'part', cmd_part |
dd 'ping', cmd_ping |
dd 'priv', cmd_privmsg |
dd 'quit', cmd_quit |
dd 'noti', cmd_notice |
.number = ($ - server_commands) / 8 |
compare_to_nick: |
push esi |
mov ecx, MAX_NICK_LEN |
mov esi, user_nick |
.loop: |
lodsb |
cmp al, ' ' |
jbe .done |
cmp al, 'a' |
jb .ok |
cmp al, 'z' |
ja .ok |
sub al, 0x20 |
.ok: |
mov bl, byte[edi] |
cmp bl, 'a' |
jb .ok2 |
cmp bl, 'z' |
ja .ok2 |
sub bl, 0x20 |
.ok2: |
cmp bl, al |
jne .not_equal |
inc edi |
dec ecx |
jnz .loop |
.done: |
xor eax, eax |
pop esi |
ret |
.not_equal: |
or eax, -1 |
pop esi |
ret |
find_window: |
; mov [window_print], |
ret |
cmd_328: |
cmd_421: |
cmd_372: |
cmd_375: |
cmd_376: |
add esi, 4 |
jmp cmd_notice.loop |
cmd_notice: |
cmp byte[servercommand], ':' |
jne .gogogo |
mov byte [esi-1], 0 |
push esi |
mov esi, str_1 |
call print_text2 |
mov esi, servercommand+1 |
call print_text2 |
mov esi, str_2 |
call print_text2 |
pop esi |
.gogogo: |
add esi, 6 |
.loop: |
inc esi |
cmp byte [esi], 0 |
je .fail |
cmp byte [esi], 10 ; newline |
je server_parser.parse |
cmp byte [esi], ' ' |
jne .loop |
.loop2: |
inc esi |
cmp byte [esi], 0 |
je .fail |
cmp byte [esi], ' ' |
je .loop2 |
cmp byte [esi], ':' |
je .loop2 |
call print_text2 |
mov esi, str_newline |
call print_text2 |
.fail: |
ret |
cmd_ping: |
; Just change PING to PONG |
mov dword[esi], 'PONG' |
; Find the end of the command |
lea edi, [esi + 5] |
xor al, al |
repne scasb |
; Now send it back |
mov edx, esi |
mov esi, edi |
mov word [esi], 0x0d0a |
inc esi |
inc esi |
sub esi, edx |
mcall send, [socketnum], , , 0 |
ret |
cmd_privmsg: |
; Check if it was destined for me privately |
mov edi, servercommand+1 |
call compare_to_nick |
;;; je .private |
; If not, find the correct window ??? |
; now find the end of nick |
mov edi, esi |
.loop: |
inc edi |
cmp byte [edi], 0 |
je .fail |
cmp byte [edi], ' ' |
jne .loop |
.loop2: |
inc edi |
cmp byte [edi], 0 |
je .fail |
cmp byte [edi], ' ' |
je .loop2 |
cmp byte [edi], ':' |
je .loop2 |
cmp byte [edi], 1 |
je cmd_ctcp |
; Action? |
cmp dword[edi+1], 'ACTI' |
je .action |
; nope, just plain old privmsg |
if TIMESTAMP |
call print_timestamp |
end if |
push edi |
mov bl, '<' |
call print_character |
mov eax, servercommand+1 |
mov dl, '!' |
call print_text |
mov bl, '>' |
call print_character |
mov bl, ' ' |
call print_character |
pop esi |
call print_text2 |
mov bl, 10 |
call print_character |
.fail: |
ret |
.action: |
push edi |
if TIMESTAMP |
call print_timestamp |
end if |
mov esi, action_header_short |
call print_text2 |
mov eax, servercommand+1 |
mov dl, ' ' |
call print_text |
mov bl, ' ' |
call print_character |
pop esi |
add esi, 8 |
call print_text2 |
mov bl, 10 |
call print_character |
ret |
cmd_ctcp: |
cmp dword[edi+1], 'VERS' |
je .version |
cmp dword[edi+1], 'TIME' |
je .time |
cmp dword[edi+1], 'PING' |
je .ping |
ret |
.time: |
lea esi, [edi+1] |
mov byte [edi+5], ' ' |
add edi, 6 |
; TODO: add system date (fn 29) in human readable format |
mcall 3 ; get system time |
mov ecx, 3 |
.timeloop: |
mov bl, al |
shr al, 4 |
add al, '0' |
stosb |
mov al, bl |
and al, 0x0f |
add al, '0' |
stosb |
dec ecx |
jz .timedone |
mov al, ':' |
stosb |
shr eax, 8 |
jmp .timeloop |
.timedone: |
xor al, al |
stosb |
call ctcp_reply |
if TIMESTAMP |
call print_timestamp |
end if |
mov esi, ctcp_header |
call print_text2 |
mov esi, servercommand+1 |
call print_text2 |
mov esi, ctcp_time |
call print_text2 |
ret |
.version: |
mov esi, str_version |
call ctcp_reply |
if TIMESTAMP |
call print_timestamp |
end if |
mov esi, ctcp_header |
call print_text2 |
mov esi, servercommand+1 |
call print_text2 |
mov esi, ctcp_version |
call print_text2 |
ret |
.ping: |
lea esi, [edi+1] |
call ctcp_reply |
if TIMESTAMP |
call print_timestamp |
end if |
mov esi, ctcp_header |
call print_text2 |
mov esi, servercommand+1 |
call print_text2 |
mov esi, ctcp_ping |
call print_text2 |
ret |
ctcp_reply: |
push esi |
mov dword [usercommand], 'NOTI' |
mov dword [usercommand+4], 'CE ' |
mov esi, servercommand+1 |
mov edi, usercommand+7 |
.nickloop: |
lodsb |
cmp al, '!' |
je .done |
cmp al, ' ' |
je .done |
test al, al |
je .fail |
stosb |
jmp .nickloop |
.done: |
mov byte [esi-1], 0 |
mov ax, ' :' |
stosw |
mov al, 1 |
stosb |
pop esi |
.replyloop: |
lodsb |
cmp al, 1 |
jbe .done2 |
stosb |
jmp .replyloop |
.done2: |
mov al, 1 |
stosb |
mov ax, 0x0a0d |
stosw |
lea esi, [edi - usercommand] |
mcall send, [socketnum], usercommand, , 0 |
.fail: |
ret |
cmd_part: |
; Is it me who parted? |
mov edi, servercommand+1 |
call compare_to_nick |
jne .dont_close |
; yes, close the window |
mov edi, [window_print] |
mov [edi + window.flags], FLAG_UPDATED + FLAG_CLOSE |
ret |
; somebody else parted, just print message |
.dont_close: |
push esi |
mov esi, action_header |
call print_text2 |
mov eax, servercommand+1 |
mov dl, '!' |
mov cl, ' ' |
call print_text |
mov esi, has_left_channel |
call print_text2 |
pop esi |
call print_text2 |
ret |
cmd_join: |
; compare nick: did we join a channel? |
mov edi, servercommand+1 |
call compare_to_nick |
jne .no_new_window |
; create channel window - search for empty slot |
mov ebx, windows |
mov ecx, MAX_WINDOWS |
.loop: |
cmp [ebx + window.data_ptr], 0 |
je .free_found |
add ebx, sizeof.window |
dec ecx |
jnz .loop |
; Error: no more available windows!! ;;;;; TODO |
.fail: |
ret |
.free_found: |
push ebx |
call window_create |
pop ebx |
test eax, eax |
jz .fail |
mov [ebx + window.data_ptr], eax |
mov [ebx + window.type], WINDOWTYPE_CHANNEL |
mov [ebx + window.flags], 0 |
call window_set_name |
mov [window_open], ebx |
mov [window_print], ebx |
call window_refresh |
push esi |
mov esi, action_header |
call print_text2 |
mov esi, str_talking |
call print_text2 |
pop eax |
mov dl, ' ' |
call print_text |
mov esi, str_dotnewline |
call print_text2 |
call draw_window |
ret |
.no_new_window: |
push esi |
call window_set_name |
mov esi, action_header |
call print_text2 |
mov eax, servercommand+1 |
mov dl, ' ' |
call print_text |
mov esi, joins_channel |
call print_text2 |
pop esi |
call print_text2 |
mov esi, str_newline |
call print_text2 |
ret |
cmd_nick: ; FIXME |
push esi |
; test for change of my nick |
mov esi, servercommand+1 |
mov edi, user_nick |
mov ecx, MAX_NICK_LEN |
rep cmpsb |
cmp byte[edi-1], 0 |
jne .notmy |
cmp byte[esi-1], '!' |
jne .notmy |
; yes, this is my nick, set to new |
pop esi |
or ecx, -1 |
mov edi, esi |
xor eax, eax |
repne scasb |
neg ecx |
cmp ecx, MAX_NICK_LEN |
jb @f |
mov ecx, MAX_NICK_LEN |
@@: |
mov edi, user_nick |
rep movsb |
.notmy: |
; replace nick in all lists of users |
mov ebx, windows |
.channels: |
mov esi, [ebx + window.data_ptr] |
lea esi, [esi + window_data.names] |
;;;;; mov edx, [esi + window_data.nameslen] |
add edx, esi |
.nicks: |
mov edi, servercommand+1 |
cmp byte[esi], '@' |
jne @f |
inc esi |
@@: |
cmp esi, edx |
jae .srcdone |
lodsb |
cmp al, ' ' |
je .srcdone |
scasb |
je @b |
@@: |
cmp esi, edx |
jae .nextchannel |
lodsb |
cmp al, ' ' |
jne @b |
.nextnick: |
cmp esi, edx |
jae .nextchannel |
lodsb |
cmp al, ' ' |
jz .nextnick |
dec esi |
jmp .nicks |
.srcdone: |
cmp byte [edi], '!' |
jne .nextnick |
; here we have esi -> end of nick which must be replaced to [servercommand_position]+6 |
lea edx, [edi-servercommand-1] |
sub esi, edx |
or ecx, -1 |
xor eax, eax |
; mov edi, [servercommand_position] ;;;;; FIXME |
repnz scasb |
not ecx |
dec ecx |
push ecx |
cmp ecx, edx |
jb .decrease |
jz .copy |
.increase: |
; new nick is longer than the old |
push esi |
lea edi, [ebx+120*10] ;;;;;; |
lea esi, [edi+edx] |
sub esi, ecx |
mov ecx, esi |
sub ecx, [esp] |
dec esi |
dec edi |
std |
rep movsb |
cld |
pop esi |
jmp .copy |
.decrease: |
; new nick is shorter than the old |
push esi |
lea edi, [esi+ecx] |
add esi, edx |
lea ecx, [ebx+120*10] |
sub ecx, edi |
rep movsb |
pop esi |
.copy: |
; copy nick |
mov edi, esi |
dec edi |
; mov esi, [servercommand_position] ;;;;; FIXME |
pop ecx |
sub edx, ecx |
sub [ebx-4], edx |
rep movsb |
mov al, ' ' |
stosb |
.nextchannel: |
add ebx, sizeof.window |
cmp ebx, windows + sizeof.window*MAX_WINDOWS |
jb .channels |
; mov [text_start], window_text + 120*80 |
new_all_channels3: |
mov esi, action_header_short |
call print_text2 |
mov eax, servercommand+1 |
mov dl,'!' |
call print_text |
mov esi,is_now_known_as |
call print_text2 |
; mov esi,[servercommand_position] ;;;;; FIXME |
call print_text2 |
;;; call notify_channel_thread |
; go to next window (and check if its a channel!) |
; add [text_start], 120*80 |
; cmp [text_start], I_END+120*80*20 |
; jb new_all_channels3 |
ret |
cmd_kick: |
; Is it me who got kicked? |
mov edi, servercommand+1 |
call compare_to_nick |
jne .not_me |
; TODO: mark channel as disconnected |
.not_me: |
; find the channel user has been kicked from |
push esi |
mov esi, action_header_short |
call print_text2 |
mov eax, servercommand+1 |
mov dl,'!' |
call print_text |
mov esi, kicked |
call print_text2 |
pop esi |
call print_text2 |
ret |
cmd_quit: |
mov esi, action_header |
call print_text2 |
mov eax, servercommand+1 |
mov dl, '!' |
call print_text |
mov esi, has_quit_irc |
call print_text2 |
ret |
cmd_mode: |
push esi |
mov esi, action_header_short |
call print_text2 |
mov eax, servercommand+1 |
mov dl, ' ' |
call print_text |
mov esi, sets_mode |
call print_text2 |
pop esi |
call print_text2 |
mov esi, str_newline |
call print_text2 |
ret |
cmd_353: ; channel usernames reply |
; TODO: mark a bit that we are receiving names |
; first, find the channel name |
.loop1: |
lodsb |
cmp al, '#' |
je .got_channel |
test al, al |
jnz .loop1 |
ret |
.got_channel: |
; call find_channel ;;;; ASSUME current channel for now |
mov ebx, [window_print] |
mov ebx, [ebx + window.data_ptr] |
lea edi, [ebx + window_data.names] |
lea edx, [edi + MAX_NICK_LEN] |
; now find the semicolon separating channelname and usernames |
.loop2: |
lodsb |
cmp al, ':' |
je .namesloop |
test al, al |
jnz .loop2 |
ret |
.namesloop: |
; now the names list begins, separated with spaces |
lodsb |
test al, al |
jz .done |
cmp al, ' ' |
jz .next |
stosb |
jmp .namesloop |
.next: |
mov edi, edx |
add edx, MAX_NICK_LEN |
;;; cmp edi, .. ; Check for buffer overflow |
jmp .namesloop |
.done: |
call print_channel_list |
ret |
cmd_366: ; channel usernames end |
; TODO: clear the bit that we are receiving names |
ret |
cmd_topic: |
.loop: |
lodsb |
test al, al |
je .fail |
cmp al, ':' |
jne .loop |
push esi |
mov esi, action_header |
call print_text2 |
mov esi, str_topic |
call print_text2 |
pop esi |
call print_text2 |
mov esi, str_newline |
call print_text2 |
.fail: |
ret |
cmd_333: |
; TODO: check channelname and change pointer accordingly |
mov ecx, 3 ; number of spaces to find |
.loop: |
lodsb |
test al, al |
je .fail |
cmp al, ' ' |
jne .loop |
dec ecx |
jnz .loop ; find some more spaces |
push esi |
mov esi, action_header |
call print_text2 |
mov esi, str_setby |
call print_text2 |
pop esi |
call print_text2 |
mov esi, str_newline |
call print_text2 |
.fail: |
ret |
/kernel/branches/net/applications/ircc/socket.inc |
---|
0,0 → 1,240 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; ;; |
;; GNU GENERAL PUBLIC LICENSE ;; |
;; Version 2, June 1991 ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
socket_connect: |
; cmp [status], STATUS_CONNECTED ; TODO |
; je disconnect |
; ignore if status is not "disconnected" |
cmp [status], STATUS_DISCONNECTED |
jne .nothing |
mov esi, str_connecting |
call print_text2 |
mov esi, irc_server_name |
call print_text2 |
mov esi, str_dotnewline |
call print_text2 |
; update status |
inc [status] ; was STATUS_DISCONNECTED, now STATUS_RESOLVING |
; resolve name |
push esp ; reserve stack place |
push esp ; fourth parameter |
push 0 ; third parameter |
push 0 ; second parameter |
push irc_server_name |
call [getaddrinfo] |
pop esi |
; test for error |
test eax, eax |
jnz .fail_dns |
; fill in ip in sockstruct |
mov eax, [esi + addrinfo.ai_addr] |
mov eax, [eax + sockaddr_in.sin_addr] |
mov [sockaddr1.ip], eax |
; free allocated memory |
push esi |
call [freeaddrinfo] |
; update status |
inc [status] |
; connect |
mcall socket, AF_INET4, SOCK_STREAM, 0 |
cmp eax, -1 |
jz .fail |
mov [socketnum], eax |
mcall connect, [socketnum], sockaddr1, 18 |
cmp eax, -1 |
jz .fail_refused |
.nothing: |
ret |
.fail: |
mov [status], STATUS_DISCONNECTED |
mov esi, str_sockerr |
call print_text2 |
ret |
.fail_dns: |
mov [status], STATUS_DISCONNECTED |
mov esi, str_dnserr |
call print_text2 |
ret |
.fail_refused: |
mov [status], STATUS_DISCONNECTED |
mov esi, str_refused |
call print_text2 |
ret |
socket_write_userinfo: |
; create packet in packetbuf |
mov edi, packetbuf |
mov eax, 'NICK' |
stosd |
mov al, ' ' |
stosb |
mov esi, user_nick |
mov ecx, MAX_NICK_LEN |
.loop: |
lodsb |
test al, al |
jz .done |
stosb |
dec ecx |
jnz .loop |
.done: |
mov ax, 0x0d0a |
stosw |
mov eax, 'USER' |
stosd |
mov al, ' ' |
stosb |
mov esi, user_nick |
mov ecx, MAX_NICK_LEN |
.loop2: |
lodsb |
test al, al |
jz .done2 |
stosb |
dec ecx |
jnz .loop2 |
.done2: |
mov eax, ' 8 *' |
stosd |
mov ax, ' :' |
stosw |
mov al, ' ' |
stosb |
mov esi, user_real_name |
mov ecx, MAX_REAL_LEN |
.loop3: |
lodsb |
test al, al |
jz .done3 |
stosb |
dec ecx |
jnz .loop3 |
.done3: |
mov ax, 0x0d0a |
stosw |
lea esi, [edi - packetbuf] |
mcall send, [socketnum], packetbuf, , 0 |
ret |
process_network_event: |
; values for status: 0, 1, 2, 3 |
mov eax, [status] |
dec eax |
; 0 = STATUS_DISCONNECTED - do nothing |
; (ignore network events if we are disconnected from network) |
js .nothing |
; 1 = STATUS_RESOLVING |
jz .nothing |
; 2 = STATUS_CONNECTING |
dec eax |
jz .connecting |
; 3 = STATUS_CONNECTED |
jmp .connected |
.nothing: |
ret |
.connecting: |
call socket_write_userinfo |
; The connection has been established, change status from "connecting" to "connected". |
inc [status] |
.connected: |
call read_incoming_data |
ret |
disconnect: |
cmp [status], STATUS_DISCONNECTED |
je .nothing |
mcall close, [socketnum] |
mov [status], STATUS_DISCONNECTED |
.nothing: |
ret |
read_incoming_data: |
pusha |
; TODO: read more data if we receive one full packet |
.nextpacket: |
mcall recv, [socketnum], packetbuf, 1024 ; read a packet |
inc eax ; check if we got one |
jz .done |
dec eax |
jz .done |
; ok we have data, now feed it to the recoder |
lea edx, [packetbuf + eax] ; edx = end pointer |
mov esi, packetbuf ; esi = start pointer |
.nextcommand: |
mov edi, servercommand |
.byteloop: |
call get_next_byte ; reads byte from [esi] to al |
jnc .nextpacket ; if CF is set, we need more data |
cmp al, 10 |
je .got_command |
stosb |
jmp .byteloop |
; we have a command, call the serverparser |
.got_command: |
mov byte[edi-1], 0 ; mark the end of the command |
push esi edx |
call server_parser |
pop edx esi |
jmp .nextcommand |
.done: |
popa |
ret |
/kernel/branches/net/applications/ircc/userparser.inc |
---|
0,0 → 1,313 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; ;; |
;; GNU GENERAL PUBLIC LICENSE ;; |
;; Version 2, June 1991 ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
user_parser: |
mov eax, [edit1.size] |
mov word [usercommand + eax], 0x0a0d ; terminate the line |
cmp byte[usercommand], '/' ; is it a server command ? |
je server_command |
; Ignore data commands when not connected. |
cmp [status], STATUS_CONNECTED |
jne sdts_ret |
; Ok, we said something, print it to our textbox |
if TIMESTAMP |
call print_timestamp |
end if |
mov bl, '<' |
call print_character |
mov esi, user_nick |
call print_text2 |
mov bl,'>' |
call print_character |
mov bl,' ' |
call print_character |
mov eax, [edit1.size] |
mov byte[usercommand + eax],0 |
mov esi, usercommand |
call print_text2 |
mov bl, 10 |
call print_character |
; and now send it to the server |
mov dword[packetbuf], 'priv' |
mov dword[packetbuf+4], 'msg ' |
mov esi, [window_print] |
add esi, window.name |
mov edi, packetbuf+8 |
mov ecx, MAX_WINDOWNAME_LEN |
.loop: |
lodsb |
test al, al |
jz .done |
stosb |
dec ecx |
jnz .loop |
.done: |
mov ax, ' :' |
stosw |
mov esi, usercommand |
mov ecx, [edit1.size] |
inc ecx |
call recode |
mov al, 10 |
stosb |
lea esi, [edi - packetbuf] |
mcall send, [socketnum], packetbuf, , 0 |
sdts_ret: |
ret |
user_commands: |
dd 'nick', cmd_usr_nick |
dd 'real', cmd_usr_real |
dd 'serv', cmd_usr_server |
dd 'help', cmd_usr_help |
dd 'code', cmd_usr_code |
; TODO: All other commands require a connection to the server. |
dd 'quer', cmd_usr_quer |
dd 'quit', cmd_usr_quit |
.number = ($ - user_commands) / 8 |
server_command: |
mov eax, dword[usercommand+1] |
or eax, 0x20202020 |
mov edi, user_commands |
mov ecx, user_commands.number |
.loop: |
scasd |
je .got_cmd |
add edi, 4 |
dec ecx |
jnz .loop |
jmp cmd_usr_send ; If none of the previous commands, just send to server |
.got_cmd: |
jmp dword[edi] |
cmd_usr_quit: |
cmp [edit1.size], 5 |
je .ok |
jb cmd_usr_send |
cmp byte[usercommand+5], ' ' |
jne cmd_usr_send |
.ok: |
call cmd_usr_send |
mcall close, [socketnum] |
mov ecx, MAX_WINDOWS |
mov edi, windows |
.loop: |
mov [edi+window.flags], FLAG_CLOSE |
; call notify_channel_thread |
add edi, sizeof.window |
dec ecx |
jnz .loop |
ret |
cmd_usr_nick: |
cmp [edit1.size], 5 |
je .justprint |
cmp byte[usercommand+5], ' ' |
jne cmd_usr_send |
mov ecx, MAX_NICK_LEN |
mov esi, usercommand+6 |
mov edi, user_nick |
.loop: |
lodsb |
cmp al, 13 |
je .done |
stosb |
dec ecx |
jnz .loop |
.done: |
xor al, al |
stosb |
cmp [socketnum], 0 |
je .justprint |
lea esi, [edi - usercommand] |
mcall send, [socketnum], usercommand+1, , 0 |
.justprint: |
mov esi, str_nickchange |
call print_text2 |
mov esi, user_nick |
call print_text2 |
mov esi, str_dotnewline |
call print_text2 |
ret |
cmd_usr_real: |
cmp byte[usercommand+5], ' ' |
jne cmd_usr_send |
mov ecx, MAX_REAL_LEN |
mov esi, usercommand+6 |
mov edi, user_real_name |
.loop: |
lodsb |
cmp al, 13 |
je .done |
stosb |
dec ecx |
jnz .loop |
.done: |
xor al, al |
stosb |
mov esi, str_realchange |
call print_text2 |
mov esi, user_real_name |
call print_text2 |
mov esi, str_dotnewline |
call print_text2 |
ret |
cmd_usr_server: |
mov eax, dword[usercommand+5] ; check for 'er ', we only checked 'serv' |
or eax, 0x00002020 |
and eax, 0x00ffffff |
cmp eax, 'er ' |
jne cmd_usr_send |
mov ecx, [edit1.size] ; ok now set the address |
sub ecx, 8 |
mov esi, usercommand+8 |
push esi |
mov edi, irc_server_name |
rep movsb |
xor al, al |
stosb |
pop esi |
; set it also in window name |
mov ebx, [window_print] |
call window_set_name |
; now connect |
call socket_connect |
ret |
cmd_usr_quer: |
mov ecx, MAX_WINDOWS |
mov ebx, windows |
.loop: |
cmp [ebx + window.data_ptr], 0 |
je .found |
add ebx, sizeof.window |
dec ecx |
jnz .loop |
; error: no available channels ! FIXME |
ret |
.found: |
call window_create |
test eax, eax |
jz .error |
mov [ebx + window.data_ptr], eax |
mov esi, usercommand+7 |
call window_set_name |
mov [ebx + window.type], WINDOWTYPE_CHAT |
mov [ebx + window.flags], 0 |
.error: |
ret |
cmd_usr_help: |
mov esi, str_help |
call print_text2 |
ret |
cmd_usr_code: |
; TODO |
ret |
cmd_usr_send: |
mov esi, usercommand+1 |
mov ecx, [edit1.size] |
inc ecx |
mov edi, packetbuf |
call recode |
lea esi, [edi - packetbuf] |
mcall send, [socketnum], packetbuf, , 0 |
ret |
/kernel/branches/net/applications/ircc/window.inc |
---|
0,0 → 1,163 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; ;; |
;; GNU GENERAL PUBLIC LICENSE ;; |
;; Version 2, June 1991 ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
window_create: |
; allocate the window data block |
mcall 68, 12, sizeof.window_data |
test eax, eax |
jz .fail |
; fill it with all zeros |
push eax |
mov edi, eax |
mov ecx, (sizeof.window_data+3)/4 |
xor eax, eax |
rep stosd |
pop eax |
.fail: |
ret |
window_set_name: ; esi = ptr to name, ebx = window ptr |
pusha |
; Skip heading spaces |
.spaceloop: |
cmp byte[esi], ' ' |
jne .done |
inc esi |
jmp .spaceloop |
.done: |
; Now copy it |
lea edi, [ebx + window.name] |
mov ecx, MAX_WINDOWNAME_LEN |
.loop: |
lodsb |
cmp al, 10 |
jbe .addzero |
stosb |
dec ecx |
jnz .loop |
.addzero: |
xor al, al |
stosb |
call draw_windownames ; redraw it |
popa |
ret |
window_find: ; esi is ptr to windowname |
; mov [current_window], |
; call reset_gui |
.fail: |
ret |
window_refresh: |
; set the correct buffer pointers ; FIXME: what is it good for? |
mov eax, [textbox_width] ; |
imul eax, 11 ; |
mov [pos], eax ; |
mov eax, [window_open] |
mov eax, [eax + window.data_ptr] |
add eax, window_data.text |
mov [text_start], eax |
ret |
print_text: ; eax = start ptr |
; dl = end char |
pusha |
ptr2: |
mov bl, [eax] |
cmp bl, dl |
je ptr_ret |
cmp bl, 0 |
je ptr_ret |
call print_character |
inc eax |
jmp ptr2 |
ptr_ret: |
popa |
ret |
print_text2: ; esi = ptr to ASCIIZ string |
pusha |
.loop: |
lodsb |
test al, al |
jz .done |
mov bl, al |
call print_character |
jmp .loop |
.done: |
popa |
ret |
if TIMESTAMP |
print_timestamp: |
pusha |
mcall 3 ; get system time |
mov bl, '[' |
call print_character |
mov ecx, TIMESTAMP |
.loop: |
mov bl, al |
shr bl, 4 |
add bl, '0' |
call print_character |
mov bl, al |
and bl, 0x0f |
add bl, '0' |
call print_character |
dec ecx |
jz .done |
mov bl, ':' |
call print_character |
shr eax, 8 |
jmp .loop |
.done: |
mov bl, ']' |
call print_character |
mov bl, ' ' |
call print_character |
popa |
ret |
end if |