kolibrios/programs/network/airc/trunk/airc.asm

2865 lines
49 KiB
NASM
Raw Normal View History

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; IRC CLIENT for KolibriOS ;;
;; ;;
;; License: GPL / See file COPYING for details ;;
;; Copyright 2004 (c) Ville Turjanmaa ;;
;; Copyright 2009 (c) CleverMouse ;;
;; ;;
;; Compile with FASM for Kolibri ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
version equ '0.6'
;__DEBUG__ equ 1
;__DEBUG_LEVEL__ equ 1
use32
org 0x0
db 'MENUET01' ; 8 byte id
dd 0x01 ; required os
dd START ; program start
dd initialized_size ; program image size
dd 0x100000 ; required amount of memory
dd 0x100000
dd 0,0
include "../../../macros.inc"
include "../../../proc32.inc"
include "../../../develop/libraries/network/network.inc"
include "dll.inc"
;include "fdo.inc"
include "eth.inc"
include "lang.inc"
; connection statuses
STATUS_DISCONNECTED = 0 ; disconnected
STATUS_RESOLVING = 1 ; resolving server name
STATUS_CONNECTING = 2 ; connecting to server
STATUS_CONNECTED = 3 ; connected
; where to display status
STATUS_X = 25 + 22*6
STATUS_Y = 183 + 7*12
; supported encodings
CP866 = 0
CP1251 = 1
UTF8 = 2
; where to display encoding
ENCODING_X = 25 + 15*6
ENCODING_Y = 183 + 3*12
def_server_name db 'chat.freenode.net',0 ; default server name
user_nick dd 12 ; length
db 'kolibri_user ' ; string
user_nick_max = $ - user_nick - 4
user_real_name dd 14 ; length
db 'KolibriOS User ' ; string
user_real_name_max = $ - user_real_name - 4
START: ; start of execution
stdcall dll.Load, @IMPORT
test eax,eax
jnz exit
mov eax,40
mov ebx,11000111b
mcall
mcall 60, 1, ipcbuf, ipcbuf.size
mcall 9, 0xe0000, -1
mov eax,[ebx+process_information.PID]
mov [main_PID],eax
mov esi, def_server_name
mov edi, irc_server_name
@@:
lodsb
stosb
test al, al
jnz @b
mov edi,I_END
mov ecx,60*120
mov al,32
cld
rep stosb
mov eax,[rxs]
imul eax,11
mov [pos],eax
mov ebp,0
mov edx,I_END
redraw: ; redraw
call draw_window ; at first, draw the window
still:
mov eax,10 ; wait here for event
mcall
dec eax ; redraw
je redraw
dec eax ; key
je main_window_key
dec eax ; button
je button
cmp al,4
jz ipc
call process_network_event
cmp [I_END+120*60],byte 1
jne no_main_update
mov [I_END+120*60],byte 0
mov edx,I_END
call draw_channel_text
no_main_update:
call print_channel_list
jmp still
button: ; button
mov eax,17 ; get id
mcall
cmp ah,1 ; close program
jne noclose
exit:
or eax,-1
mcall
noclose:
cmp ah,21
jne no_change_encoding
cmp byte[edx-1],0
jnz still
mov eax,[encoding]
inc eax
mov edx,msgbox_struct
mov byte[edx],al
mov byte[edx-1],1 ; msgbox is running
push mb_stack
push edx
call [mb_create]
push msgbox_func_array
call [mb_setfunctions]
jmp still
no_change_encoding:
call socket_commands
jmp still
ipc:
mov edx,msgbox_struct
cmp byte[edx-1],0
jz @f
mov byte[edx-1],0
mov al,[edx]
dec eax
mov byte[encoding],al
call update_encoding
jmp ipc_done
@@:
call process_command
ipc_done:
mov dword [ipcbuf+4], 8
jmp still
main_window_key:
mov eax,2
mcall
shr eax,8
cmp eax,8
jne no_bks2
cmp [xpos],0
je still
dec [xpos]
call print_entry
jmp still
no_bks2:
cmp eax,20
jbe no_character2
mov ebx,[xpos]
mov [send_string+ebx],al
inc [xpos]
cmp [xpos],80
jb noxposdec
mov [xpos],79
noxposdec:
call print_entry
jmp still
no_character2:
cmp eax,13
jne no_send2
cmp [xpos],0
je no_send2
cmp [send_string],byte '/' ; server command
jne no_send2
call process_command
jmp still
no_send2:
jmp still
socket_commands:
cmp ah,22 ; connect
jnz tst3
; ignore if status is not "disconnected"
cmp [status], STATUS_DISCONNECTED
jnz .nothing
; start name resolving
inc [status] ; was STATUS_DISCONNECTED, now STATUS_RESOLVING
push gai_reqdata
push ip_list
push 0
push 0
push irc_server_name
call [getaddrinfo_start]
test eax, eax
jns getaddrinfo_done
call update_status
.nothing:
ret
tst3:
cmp ah,23 ; write userinfo
jnz tst4
; ignore if status is not "connected"
cmp [status], STATUS_CONNECTED
jnz .nothing
; create packet in packetbuf
mov edi, packetbuf
mov edx, edi
mov esi, string0
mov ecx, string0l-string0
rep movsb
mov esi, user_real_name+4
mov ecx, [esi-4]
rep movsb
mov al, 13
stosb
mov al, 10
stosb
mov esi, string1
mov ecx, string1l-string1
rep movsb
mov esi, user_nick+4
mov ecx, [esi-4]
rep movsb
mov al, 13
stosb
mov al, 10
stosb
; send packet
xchg edx, edi
sub edx, edi
mov esi, edi
mcall 53, 7, [socket]
.nothing:
ret
tst4:
cmp ah,24 ; close socket
jz disconnect
no_24:
ret
getaddrinfo_done:
; The address resolving is done.
; If eax is zero, address is resolved, otherwise there was some problems.
test eax, eax
jz .good
.disconnect:
; Change status to "disconnected" and return.
and [status], 0
call update_status
ret
.good:
; We got a list of IP addresses. Try to connect to first of them.
mov eax, [ip_list]
mov esi, [eax + addrinfo.ai_addr]
mov esi, [esi + sockaddr_in.sin_addr]
push eax
call [freeaddrinfo]
mcall 53, 5, 0, 6667, , 1
cmp eax, -1
jz .disconnect
; Socket has been opened. Save handle and change status to "connecting".
mov [socket], eax
inc [status] ; was STATUS_RESOLVING, now STATUS_CONNECTING
call update_status
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 .resolving
; 2 = STATUS_CONNECTING
dec eax
jz .connecting
; 3 = STATUS_CONNECTED
jmp .connected
.resolving:
; We are inside address resolving. Let the network library work.
push ip_list
push gai_reqdata
call [getaddrinfo_process]
; Negative returned value means that the resolving is not yet finished,
; and we continue the loop without status change.
; Zero and positive values are handled by getaddrinfo_done.
test eax, eax
jns getaddrinfo_done
.nothing:
ret
.connecting:
; We are connecting to the server, and socket status has changed.
mcall 53, 6, [socket]
; Possible values for status: SYN_SENT=2, SYN_RECEIVED=3, ESTABLISHED=4, CLOSE_WAIT=7
; First two mean that we are still connecting, and we must continue wait loop
; without status change.
; Last means that server has immediately closed the connection,
; and status becomes "disconnected".
cmp eax, 4
jb .nothing
jz .established
and [status], 0
call update_status
; close socket
mcall 53, 8
ret
.established:
; The connection has been established, change status from "connecting" to "connected".
inc [status]
call update_status
; Fall through to .connected, because some data can be already in buffer.
.connected:
call read_incoming_data
; Handle closing socket by the server.
mcall 53, 6, [socket]
cmp eax, 4
jnz disconnect
ret
disconnect:
; Release all allocated resources.
; Exact actions depend on current status.
mov eax, [status]
dec eax
; 0 = STATUS_DISCONNECTED - do nothing
js .nothing
; 1 = STATUS_RESOLVING
jz .resolving
; 2 = STATUS_CONNECTING, 3 = STATUS_CONNECTED
; In both cases we should close the socket.
mcall 53, 8, [socket]
jmp .disconnected
.resolving:
; Let the network library handle abort of resolving process.
push gai_reqdata
call [getaddrinfo_abort]
.disconnected:
; In all cases, set status to "disconnected".
and [status], 0
call update_status
.nothing:
ret
msgbox_notify:
inc byte [msgbox_running]
mcall 60,2,[main_PID],0,1
ret
print_channel_list:
pusha
mov eax,13
mov ebx,415*65536+6*13
mov ecx,27*65536+12*10
mov edx,0xffffff
mcall
mov eax,4
mov ebx,415*65536+27
mov ecx,[index_list_1]
mov edx,channel_list+32
newch:
movzx esi,byte [edx+31]
and esi,0x1f
mcall
add edx,32
add ebx,12
cmp edx,channel_list+32*10
jbe newch
no_channel_list:
popa
ret
print_user_list:
pusha
newtry:
mov edx,ebp
imul edx,120*80
add edx,120*60+8+I_END
cmp [edx],byte 1
je nonp
mov edx,ebp
imul edx,120*80
add edx,120*70+I_END
mov edi,edx
mov eax,[edx-8]
mov ebx,[edx-4]
add ebx,edx
sub ebx,3
inc eax
dec edx
newnss:
inc edx
dec eax
jz startuu
asdf:
cmp [edx],word ' '
jne nodouble
inc edx
nodouble:
cmp [edx],byte ' '
je newnss
inc edx
cmp edx,ebx
jbe asdf
dec dword [edi-8]
popa
ret
startuu:
cmp [edx],byte ' '
jne startpr
inc edx
startpr:
pusha
mov eax,13
mov ebx,415*65536+6*13
mov ecx,27*65536+12*10
mov edx,0xffffff
mcall
popa
mov eax,4
mov ebx,415*65536+27
mov ebp,0
newuser:
mov esi,0
newusers:
cmp [edx+esi],byte ' '
je do_print
inc esi
cmp esi,20
jbe newusers
do_print:
mov ecx,[index_list_1]
cmp [edx],byte '@'
jne no_op
mov ecx,[index_list_2]
no_op:
mcall
inc ebp
cmp ebp,10
je nonp
add ebx,12
add edx,esi
inc edx
cmp [edx],byte ' '
jne newuser
inc edx
jmp newuser
nonp:
popa
ret
start_user_list_at dd 0x0
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]
process_command:
pusha
mov eax,[xpos]
mov [send_string+eax+0],byte 13
mov [send_string+eax+1],byte 10
mov eax,[rxs]
imul eax,11
mov [pos],eax
mov eax,[send_to_channel]
imul eax,120*80
add eax,I_END
mov [text_start],eax
cmp [send_string],byte '/' ; server command
je server_command
; Ignore data commands when not connected.
cmp [status], STATUS_CONNECTED
jnz sdts_ret
mov bl,13
call print_character
mov bl,10
call print_character
mov bl,'<'
call print_character
mov esi,user_nick+4
mov ecx,[user_nick]
newnp:
mov bl,[esi]
call print_character
inc esi
loop newnp
mov bl,'>'
call print_character
mov bl,' '
call print_character
mov ecx,[xpos]
mov esi,send_string
newcw:
mov bl,[esi]
call print_character
inc esi
loop newcw
mov eax,dword [send_to_channel]
shl eax,5
add eax,channel_list
mov esi,eax
mov edi,send_string_header+8
movzx ecx,byte [eax+31]
cld
rep movsb
mov [edi],word ' :'
mov esi, send_string_header
mov ecx,10
movzx ebx,byte [eax+31]
add ecx,ebx
mov edi, packetbuf
rep movsb
mov esi,send_string
mov ecx,[xpos]
inc ecx
call recode
mov esi, packetbuf
mov edx, edi
sub edx, esi
mcall 53, 7, [socket]
mov [xpos], 0
jmp sdts_ret
server_command:
cmp [send_string+1],dword 'anic'
jne no_set_nick
mov ecx,[xpos]
sub ecx,7
cmp ecx,user_nick_max
jb @f
mov ecx,user_nick_max
@@:
mov [user_nick],ecx
mov esi,send_string+7
mov edi,user_nick+4
cld
rep movsb
pusha
mov edi,text+70*1+15
mov al,32
mov ecx,15
cld
rep stosb
popa
mov esi,user_nick+4
mov edi,text+70*1+15
mov ecx,[esi-4]
cld
rep movsb
mov [xpos],0
call draw_window
popa
ret
no_set_nick:
cmp [send_string+1],dword 'area'
jne no_set_real_name
mov ecx,[xpos]
sub ecx,7
cmp ecx,user_real_name_max
jb @f
mov ecx,user_real_name_max
@@:
mov [user_real_name],ecx
mov esi,send_string+7
mov edi,user_real_name+4
cld
rep movsb
pusha
mov edi,text+70*0+15
mov al,32
mov ecx,15
cld
rep stosb
popa
mov esi,user_real_name+4
mov edi,text+70*0+15
mov ecx,[esi-4]
rep movsb
mov [xpos],0
call draw_window
popa
ret
no_set_real_name:
cmp [send_string+1],dword 'aser'
jne no_set_server
mov ecx,[xpos]
sub ecx,7
mov esi,send_string+7
mov edi,irc_server_name
rep movsb
mov al,0
stosb
pusha
mov edi,text+70*2+15
mov al,32
mov ecx,15
cld
rep stosb
popa
mov ecx,[xpos]
sub ecx,7
mov esi,send_string+7
mov edi,text+70*2+15
rep movsb
mov [xpos],0
call draw_window
popa
ret
no_set_server:
; All other commands require a connection to the server.
cmp [status], STATUS_CONNECTED
jnz sdts_ret
cmp [send_string+1],dword 'quer'
jne no_query_create
mov edi,I_END+120*80
mov eax,1 ; create channel window - search for empty slot
newse2:
mov ebx,eax
shl ebx,5
cmp dword [channel_list+ebx],dword ' '
je free_found2
add edi,120*80
inc eax
cmp eax,[max_windows]
jb newse2
free_found2:
mov edx,send_string+7
mov ecx,[xpos]
sub ecx,7
mov [channel_list+ebx+31],cl
call create_channel_name
push edi
push eax
mov [edi+120*60+8],byte 1 ; query window
mov al,32
mov ecx,120*60
cld
rep stosb
pop eax
pop edi
; eax has the free position
; mov [thread_screen],edi
call create_channel_window
mov [xpos],0
popa
ret
no_query_create:
mov esi, send_string+1
mov ecx, [xpos]
inc ecx
mov edi, packetbuf
call recode
mov esi, packetbuf
mov edx, edi
sub edx, esi
mov eax, 53 ; write server command
mov ebx, 7
mov ecx, [socket]
mcall
send_done:
mov [xpos],0
cmp [send_string+1],dword 'quit'
jne no_quit_server
mov eax,5
mov ebx,200
mcall
mov eax, 53 ; close socket
mov ebx, 8
mov ecx, [socket]
mcall
mov ecx,[max_windows]
mov edi,I_END
newclose:
mov [edi+120*60+4],byte 1
call notify_channel_thread
add edi,120*80
loop newclose
popa
ret
no_quit_server:
sdts_ret:
popa
ret
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
read_incoming_data:
pusha
.packetloop:
.nextpacket:
mcall 53, 11, [socket], packetbuf, 1024
test eax, eax
jz .nothing
mov esi, edx ; esi = pointer to data
add edx, eax ; edx = limit of data
.byteloop:
call get_next_byte
jnc .nextpacket
cmp al, 10
jne .no_start_command
mov [cmd], 1
.no_start_command:
cmp al, 13
jne .no_end_command
mov ebx, [cmd]
mov byte [ebx+command-2], 0
call analyze_command
mov edi, command
mov ecx, 250
xor eax, eax
rep stosb
mov [cmd], eax
mov al, 13
.no_end_command:
mov ebx, [cmd]
cmp ebx, 512
jge @f
mov [ebx+command-2], al
inc [cmd]
@@:
jmp .byteloop
.nothing:
popa
ret
create_channel_name:
pusha
search_first_letter:
cmp [edx],byte ' '
jne first_letter_found
inc edx
jmp search_first_letter
first_letter_found:
mov esi,edx
mov edi,channel_list
add edi,ebx
mov ecx,30
xor eax,eax
newcase:
mov al,[esi]
cmp eax,'a'
jb nocdec
cmp eax,'z'
jg nocdec
sub al,97-65
nocdec:
mov [edi],al
inc esi
inc edi
loop newcase
popa
ret
create_channel_window:
pusha
mov [cursor_on_off],0
; mov [thread_nro],eax
mov edx,[thread_stack]
sub edx,8
mov [edx],eax
mov [edx+4],edi
mov eax,51
mov ebx,1
mov ecx,channel_thread
mcall
mov [edi+120*60+12], eax
add [thread_stack],0x4000
; add [thread_screen],120*80
popa
ret
print_entry:
pusha
mov eax,13
mov ebx,8*65536+6*80
mov ecx,151*65536+13
mov edx,0xffffff
mcall
mov eax,4
mov ebx,8*65536+154
mov ecx,0x000000
mov edx,send_string
mov esi,[xpos]
mcall
popa
; Fall through to draw_cursor.
; ret
draw_cursor:
pusha
mov eax,9
mov ebx,0xe0000
mov ecx,-1
mcall
cmp ax,word [0xe0000+4]
setnz dl
movzx edx,dl
neg edx
and edx,0xffffff
; jne no_blink
; call print_entry
mov ebx,[xpos]
imul ebx,6
add ebx,8
mov cx,bx
shl ebx,16
mov bx,cx
mov ecx,151*65536+163
mov eax,38
mcall
popa
ret
; no_blink:
;
; mov eax,13
; mov ebx,8*65536+6*60
; mov ecx,151*65536+13
; mov edx,0xffffff
; mcall
popa
ret
set_channel:
pusha
; UPPER / LOWER CASE CHECK
mov esi,eax
mov edi,channel_temp
mov ecx,40
xor eax,eax
newcase2:
mov al,[esi]
cmp eax,'#'
jb newcase_over2
cmp eax,'a'
jb nocdec2
cmp eax,'z'
jg nocdec2
sub al,97-65
nocdec2:
mov [edi],al
inc esi
inc edi
loop newcase2
newcase_over2:
sub edi,channel_temp
mov [channel_temp_length],edi
mov eax,channel_temp
mov [text_start],I_END+120*80
mov ebx,channel_list+32
mov eax,[eax]
mov edx,[channel_temp_length]
stcl1:
cmp dl,[ebx+31]
jne notfound
pusha
xor eax,eax
xor edx,edx
mov ecx,0
stc4:
mov dl,[ebx+ecx]
mov al,[channel_temp+ecx]
cmp eax,edx
jne notfound2
inc ecx
cmp ecx,[channel_temp_length]
jb stc4
popa
jmp found
notfound2:
popa
notfound:
add [text_start],120*80
add ebx,32
cmp ebx,channel_list+19*32
jb stcl1
mov [text_start],I_END
found:
popa
ret
channel_temp: times 100 db 0
channel_temp_length dd 0x0
print_nick:
pusha
mov eax,command+1
mov dl,'!'
call print_text
popa
ret
analyze_command:
pusha
mov [text_start],I_END
mov ecx,[rxs]
imul ecx,11
mov [pos],ecx
; mov bl,13
; call print_character
; mov bl,10
; call print_character
; mov ecx,[cmd]
; sub ecx,2
; mov esi,command+0
; newcmdc:
; mov bl,[esi]
; call print_character
; inc esi
; loop newcmdc
mov edx,I_END
; call draw_channel_text
; cmp [cmd],20
; jge cmd_len_ok
;
; mov [cmd],0
;
; popa
; ret
cmd_len_ok:
cmp [command],dword 'PING' ; ping response
jne no_ping_responce
call print_command_to_main
mov [command],dword 'PONG'
call print_command_to_main
mov eax,4
mov ebx,100*65536+3
mov ecx,0xffffff
mov edx,command
mov esi,[cmd]
mov [command+esi-1],word '**'
; mcall
mov eax,53
mov ebx,7
mov ecx,[socket]
mov edx,[cmd]
mov esi,command
mov word [esi+edx-2], 0x0a0d
mcall
popa
ret
no_ping_responce:
mov eax,[rxs]
imul eax,11
mov [pos],eax
mov [command],byte '<'
mov eax,command
mov ecx,100
new_blank:
cmp [eax],byte ' '
je bl_found
inc eax
loop new_blank
mov eax,50
bl_found:
inc eax
mov [command_position],eax
mov esi,eax
mov edi,irc_command
mov ecx,8
cld
rep movsb
cmp [irc_command],'PRIV' ; message to channel
jne no_privmsg
; compare nick
mov eax,[command_position]
add eax,8
call compare_to_nick
cmp [cresult],0
jne no_query_msg
mov eax,command+1
no_query_msg:
call set_channel
mov ecx,100 ; [cmd]
mov eax,command+10
acl3:
cmp [eax],byte ':'
je acl4
inc eax
loop acl3
mov eax,10
acl4:
inc eax
cmp [eax+1],dword 'ACTI'
jne no_action
push eax
mov eax,action_header_short
mov dl,0
call print_text
mov eax,command+1
mov dl,'!'
call print_text
mov bl,' '
call print_character
pop eax
add eax,8
mov dl,0
call print_text
call notify_channel_thread
popa
ret
no_action:
push eax
mov bl,10
call print_character
mov eax,command
mov dl,'!'
call print_text
mov bl,'>'
call print_character
mov bl,' '
call print_character
pop eax
mov dl,0
call print_text
call notify_channel_thread
popa
ret
no_privmsg:
cmp [irc_command],'PART' ; channel leave
jne no_part
; compare nick
mov eax,command+1
call compare_to_nick
cmp [cresult],0
jne no_close_window
mov eax,[command_position]
add eax,5
call set_channel
mov edi,[text_start]
mov [edi+120*60+4],byte 1
call notify_channel_thread
popa
ret
no_close_window:
mov eax,[command_position]
add eax,5
call set_channel
mov eax,action_header_red
mov dl,0
call print_text
mov eax,command+1
mov dl,'!'
mov cl,' '
call print_text
mov eax,has_left_channel
mov dl,0
call print_text
mov eax,[command_position]
add eax,5
mov dl,' '
call print_text
call notify_channel_thread
popa
ret
no_part:
cmp [irc_command],'JOIN' ; channel join
jne no_join
; compare nick
mov eax,command+1
call compare_to_nick
cmp [cresult],0
jne no_new_window
mov edi,I_END+120*80
mov eax,1 ; create channel window - search for empty slot
newse:
mov ebx,eax
shl ebx,5
cmp dword [channel_list+ebx],dword ' '
je free_found
add edi,120*80
inc eax
cmp eax,[max_windows]
jb newse
free_found:
mov edx,[command_position]
add edx,6
push eax
push edx
mov ecx,0
finde:
inc ecx
inc edx
movzx eax,byte [edx]
cmp eax,'#'
jge finde
mov [channel_list+ebx+31],cl
pop edx
pop eax
call create_channel_name
push edi
push eax
mov [edi+120*60+8],byte 0 ; channel window
mov al,32
mov ecx,120*60
cld
rep stosb
pop eax
pop edi
; eax has the free position
; mov [thread_screen],edi
call create_channel_window
no_new_window:
mov eax,[command_position]
add eax,6
call set_channel
mov eax,action_header_blue
mov dl,0
call print_text
mov eax,command+1
mov dl,'!'
mov cl,' '
call print_text
mov eax,joins_channel
mov dl,0
call print_text
mov eax,[command_position]
add eax,6
mov dl,0
call print_text
call notify_channel_thread
popa
ret
no_join:
cmp [irc_command],'NICK' ; nick change
jne no_nick_change
add [command_position], 6
; test for change of my nick
mov esi, command+1
mov edi, user_nick+4
mov ecx, [edi-4]
repz cmpsb
jnz .notmy
cmp byte [esi], '!'
jnz .notmy
; yes, this is my nick, set to new
mov esi, [command_position]
or ecx, -1
mov edi, esi
xor eax, eax
repnz scasb
not ecx
dec ecx
cmp ecx, user_nick_max
jb @f
mov ecx, user_nick_max
@@:
mov edi, user_nick+4
mov [edi-4], ecx
rep movsb
mov edi, text+70*1+15
mov al, ' '
mov cl, 15
push edi
rep stosb
pop edi
mov esi, user_nick+4
mov ecx, [esi-4]
cmp ecx, 15
jb @f
mov ecx, 15
@@:
rep movsb
mov [xpos], 0
call draw_window
.notmy:
; replace nick in all lists of users
mov ebx, I_END + 120*70
.channels:
mov esi, ebx
mov edx, [esi-4]
add edx, esi
.nicks:
mov edi, command+1
cmp byte [esi], '@'
jnz @f
inc esi
@@:
cmp esi, edx
jae .srcdone
lodsb
cmp al, ' '
jz .srcdone
scasb
jz @b
@@:
cmp esi, edx
jae .nextchannel
lodsb
cmp al, ' '
jnz @b
.nextnick:
cmp esi, edx
jae .nextchannel
lodsb
cmp al, ' '
jz .nextnick
dec esi
jmp .nicks
.srcdone:
cmp byte [edi], '!'
jnz .nextnick
; here we have esi -> end of nick which must be replaced to [command_position]+6
lea edx, [edi-command-1]
sub esi, edx
or ecx, -1
xor eax, eax
mov edi, [command_position]
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, [command_position]
pop ecx
sub edx, ecx
sub [ebx-4], edx
rep movsb
mov al, ' '
stosb
.nextchannel:
add ebx, 120*80
cmp ebx, I_END + 120*70 + 120*80*19
jb .channels
mov [text_start],I_END
add [text_start],120*80
new_all_channels3:
mov eax,action_header_short
mov dl,0
call print_text
mov eax,command+1
mov dl,'!'
call print_text
mov eax,is_now_known_as
mov dl,0
call print_text
mov eax,[command_position]
mov dl,0
call print_text
call notify_channel_thread
add [text_start],120*80
cmp [text_start],I_END+120*80*20
jb new_all_channels3
popa
ret
no_nick_change:
cmp [irc_command],'KICK' ; kick
jne no_kick
mov [text_start],I_END
add [text_start],120*80
mov eax,[command_position]
add eax,5
call set_channel
; new_all_channels4:
mov eax,action_header_short
mov dl,0
call print_text
mov eax,command+1
mov dl,'!'
call print_text
mov eax,kicked
mov dl,0
call print_text
mov eax,[command_position]
add eax,5
mov dl,0
call print_text
call notify_channel_thread
; add [text_start],120*80
; cmp [text_start],I_END+120*80*20
; jb new_all_channels4
popa
ret
no_kick:
cmp [irc_command],'QUIT' ; irc quit
jne no_quit
mov [text_start],I_END
add [text_start],120*80
new_all_channels2:
mov eax,action_header_red
mov dl,0
call print_text
mov eax,command+1
mov dl,'!'
call print_text
mov eax,has_quit_irc
mov dl,0
call print_text
call notify_channel_thread
add [text_start],120*80
cmp [text_start],I_END+120*80*20
jb new_all_channels2
popa
ret
no_quit:
cmp [irc_command],dword 'MODE' ; channel mode change
jne no_mode
mov [text_start],I_END
add [text_start],120*80
mov eax,[command_position]
add eax,5
call set_channel
new_all_channels:
mov eax,action_header_short
mov dl,0
call print_text
call print_nick
mov eax,sets_mode
mov dl,0
call print_text
mov eax,[command_position]
add eax,5
mov dl,0
call print_text
call notify_channel_thread
; add [text_start],120*80
; cmp [text_start],I_END+120*80*20
; jb new_all_channels
popa
ret
no_mode:
cmp [irc_command],dword '353 ' ; channel user names
jne no_user_list
mov eax,[command_position]
finde2:
inc eax
cmp [eax],byte '#'
jne finde2
call set_channel
finde3:
inc eax
cmp [eax],byte ':'
jne finde3
pusha
cmp [user_list_pos],0
jne no_clear_user_list
mov edi,[text_start]
add edi,120*70
mov [edi-8],dword 0
mov [edi-4],dword 0
mov al,32
mov ecx,1200
cld
rep stosb
no_clear_user_list:
popa
push eax
mov esi,eax
inc esi
mov edi,[text_start]
add edi,120*70
add edi,[user_list_pos]
mov edx,edi
mov ecx,command
add ecx,[cmd]
sub ecx,[esp]
sub ecx,3
and ecx,0xfff
cld
rep movsb
pop eax
mov ebx,command
add ebx,[cmd]
sub ebx,eax
sub ebx,2
mov [edx+ebx-1],dword ' '
add [user_list_pos],ebx
mov eax,[user_list_pos]
mov ebx,[text_start]
add ebx,120*70
mov [ebx-4],eax
call notify_channel_thread
popa
ret
user_list_pos dd 0x0
no_user_list:
cmp [irc_command],dword '366 ' ; channel user names end
jne no_user_list_end
mov [user_list_pos],0
popa
ret
no_user_list_end:
mov [command],byte '-'
call print_command_to_main
popa
ret
cresult db 0
compare_to_nick:
; input : eax = start of compare
; output : [cresult] = 0 if match, [cresult]=1 if no match
pusha
mov esi,eax
mov edi,0
new_nick_compare:
mov bl,byte [esi]
mov cl,byte [user_nick+4+edi]
cmp bl,cl
jne nonickm
add esi,1
add edi,1
cmp edi,[user_nick]
jb new_nick_compare
movzx eax,byte [esi]
cmp eax,40
jge nonickm
popa
mov [cresult],0
ret
nonickm:
popa
mov [cresult],1
ret
print_command_to_main:
pusha
mov [text_start],I_END
mov ecx,[rxs]
imul ecx,11
mov [pos],ecx
mov bl,13
call print_character
mov bl,10
call print_character
mov ecx,[cmd]
sub ecx,2
mov esi,command
newcmdc2:
mov bl,[esi]
call print_character
inc esi
loop newcmdc2
mov edx,I_END
call draw_channel_text
popa
ret
print_text:
pusha
mov ecx,command-2
add ecx,[cmd]
ptr2:
mov bl,[eax]
cmp bl,dl
je ptr_ret
cmp bl,0
je ptr_ret
call print_character
inc eax
cmp eax,ecx
jbe ptr2
ptr_ret:
mov eax,[text_start]
mov [eax+120*60],byte 1
popa
ret
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
print_character:
pusha
cmp bl,13 ; line beginning
jne nobol
mov ecx,[pos]
add ecx,1
boll1:
sub ecx,1
mov eax,ecx
xor edx,edx
mov ebx,[rxs]
div ebx
cmp edx,0
jne boll1
mov [pos],ecx
jmp newdata
nobol:
cmp bl,10 ; line down
jne nolf
addx1:
add [pos],dword 1
mov eax,[pos]
xor edx,edx
mov ecx,[rxs]
div ecx
cmp edx,0
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]
call draw_data
mov eax,[pos]
add eax,1
cm1:
mov ebx,[scroll+4]
imul ebx,[rxs]
cmp eax,ebx
jb noeaxz
mov esi,[text_start]
add esi,[rxs]
mov edi,[text_start]
mov ecx,ebx
cld
rep movsb
mov esi,[text_start]
mov ecx,[rxs]
imul ecx,61
add esi,ecx
mov edi,[text_start]
mov ecx,[rxs]
imul ecx,60
add edi,ecx
mov ecx,ebx
cld
rep movsb
mov eax,ebx
sub eax,[rxs]
noeaxz:
mov [pos],eax
newdata:
mov eax,[text_start]
mov [eax+120*60],byte 1
popa
ret
notify_channel_thread:
pusha
mov eax, [text_start]
mov ecx, [eax+120*60+12]
mcall 60, 2, , 0, 1
popa
ret
draw_data:
pusha
and ebx,0xff
add eax,[text_start]
mov [eax],bl
popa
ret
draw_window:
pusha
mov eax,12
mov ebx,1
mcall
xor eax,eax ; draw window
mov ebx,5*65536+499
mov ecx,5*65536+381
mov edx,[wcolor]
add edx,0x14ffffff
mov edi,title
mcall
mov eax,8 ; button: change encoding
mov ebx,(ENCODING_X-2)*65536+38
mov ecx,(ENCODING_Y-2)*65536+12
mov edx,21
mov esi,[main_button]
mcall
; mov eax,8 ; button: open socket
mov ebx,43*65536+22
mov ecx,241*65536+10
; mov edx,22
inc edx
mcall
;mov eax,8 ; button: send userinfo
mov ebx,180*65536+22
mov ecx,241*65536+10
; mov edx,23
inc edx
mcall
;mov eax,8 ; button: close socket
mov ebx,317*65536+22
mov ecx,241*65536+10
; mov edx,24
inc edx
mcall
mov eax,38 ; line
mov ebx,5*65536+494
mov ecx,148*65536+148
mov edx,[main_line]
mcall
add ecx,1*65536+1
mov eax,38 ; line
mov ebx,5*65536+494
mov ecx,166*65536+166
mcall
add ecx,1*65536+1
mov eax,38 ; line
mov ebx,410*65536+410
mov ecx,22*65536+148
mcall
add ebx,1*65536+1
mov ebx,25*65536+183 ; info text
mov ecx,0x000000
mov edx,text
mov esi,70
newline:
mov eax,4
mcall
add ebx,12
add edx,70
cmp [edx],byte 'x'
jne newline
mov edx,I_END ; text from server
call draw_channel_text
call print_entry
mov eax,12
mov ebx,2
mcall
popa
ret
update_status:
pusha
mov esi, [status]
mov edi, text + 7*70 + 22
mov ecx, status_text_len
push ecx
imul esi, ecx
add esi, status_text
mov edx, edi
rep movsb
pop esi
mcall 4, STATUS_X*65536+STATUS_Y, 0x40000000, , , 0xFFFFFF
popa
ret
update_encoding:
pusha
mov edx, 21
mcall 8 ; delete button
mov esi, [main_button]
mcall , <(ENCODING_X-2),38>, <(ENCODING_Y-2),12> ; recreate it
mov esi, [encoding]
mov edi, text + 3*70 + 15
mov ecx, encoding_text_len
push ecx
imul esi, ecx
add esi, encoding_text
mov edx, edi
rep movsb
pop esi
mcall 4, ENCODING_X*65536+ENCODING_Y, 0
popa
ret
main_line dd 0x000000
main_button dd 0x6565cc
if lang eq ru
text:
db ' <20><><EFBFBD><EFBFBD> <20><><EFBFBD> : KolibriOS User - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ⠪: /areal Jill User '
db ' <20><><EFBFBD> : kolibri_user - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ⠪: /anick Jill '
db ' <20><><EFBFBD> : freenode.net - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ⠪: /aserv irc.by '
db ' <20><><EFBFBD><EFBFBD><EFBFBD><E0AEA2> : UTF-8 '
db ' '
db ' 1) Connect 2) Send userinfo 3) Disconnect '
db ' '
db ' <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><><E1AEA5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: <20><><><E1AEA5><EFBFBD><EFBFBD><EFBFBD><EFBFBD> '
db ' '
db ' <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><E3AFAD> <20><><20><><EFBFBD><E2A0AD><EFBFBD><EFBFBD><><E1AEA5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: '
db ' '
db ' /join #ChannelName - <20><><EFBFBD><EFBFBD><E0A8AC>: /join #kolibrios '
db ' /part #ChannelName - <20><><EFBFBD><EFBFBD><E0A8AC>: /part #windows '
db ' /query Nickname - <20><><EFBFBD><EFBFBD><E0A8AC>: /query Mary '
db ' /quit - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><><E1AEAA> '
db 'x' ; <- END MARKER, DONT DELETE
status_text:
db '<27><><><E1AEA5><EFBFBD><EFBFBD><EFBFBD><EFBFBD> '
db '<27><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><E0A2A5>... '
db 'ᮥ<><E1AEA5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>... '
db 'ᮥ<><E1AEA5><EFBFBD><EFBFBD><EFBFBD><EFBFBD> '
status_text_len = 24
encoding_text:
db 'CP866 '
db 'CP1251'
db 'UTF-8 '
encoding_text_len = 6
else
text:
db ' Real name : KolibriOS User - change with eg /areal Jill User '
db ' Nick : kolibri_user - change with eg /anick Jill '
db ' Server : freenode.net - change with eg /aserv irc.by '
db ' Encoding : UTF-8 '
db ' '
db ' 1) Connect 2) Send userinfo 3) Disconnect '
db ' '
db ' Connection status: disconnected '
db ' '
db ' Commands after established connection: '
db ' '
db ' /join #ChannelName - eg /join #kolibrios '
db ' /part #ChannelName - eg /part #windows '
db ' /query Nickname - eg /query Mary '
db ' /quit - Quit server and Close socket '
db 'x' ; <- END MARKER, DONT DELETE
status_text:
db 'disconnected '
db 'resolving server name...'
db 'connecting... '
db 'connected '
status_text_len = 24
encoding_text:
db 'CP866 '
db 'CP1251'
db 'UTF-8 '
encoding_text_len = 6
end if
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; CHANNEL THREADS
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
channel_thread:
; mov ebp,[thread_nro]
pop ebp
pop edx
mov eax,ebp
shl eax,14
add eax,0x80000
mov esp,eax
; mov edi,ebp ; clear thread memory
; imul edi,120*80
; add edi,I_END
; mov ecx,120*80
; mov al,32
; cld
; rep stosb
; Create IPC buffer in the stack.
push eax
push eax
push eax
push 8
push 0
mov ecx, esp
push edx
mcall 60, 1, , 20
pop edx
mcall 40, 1100111b
; mov edx,[thread_screen]
thread_redraw:
call thread_draw_window
call draw_channel_text
call print_user_list
call print_entry
w_t:
mov esi,ebp
imul esi,120*80
add esi,I_END
cmp [esi+120*60+4],byte 1
jne no_channel_leave
mov [esi+120*60+4],byte 0
mov edi,ebp
shl edi,5
mov dword [channel_list+edi],dword ' '
mov byte [channel_list+edi+31],byte 1
mov eax,-1
mcall
no_channel_leave:
mcall 10
dec eax
jz thread_redraw
dec eax
jz thread_key
dec eax
jz thread_end
cmp al,4
jz thread_ipc
call check_mouse
jmp w_t
thread_end:
mov eax,17
mcall
mov eax,ebp
imul eax,120*80
add eax,I_END
cmp [eax+120*60+8],byte 0 ; channel window
je not_close
mov eax,ebp
shl eax,5
add eax,channel_list
mov [eax],dword ' '
mov [eax+31],byte 1
mov eax,-1
mcall
not_close:
mov [text_start],eax
mov eax,nocl
newcc:
mov bl,[eax]
call print_character
inc eax
cmp [eax],byte 0
jne newcc
call draw_channel_text
jmp w_t
nocl: db 13,10,'To exit channel, use PART or QUIT command.',0
thread_ipc:
mov byte [esp+4], 8 ; erase message from IPC buffer
no_end:
cmp [edx+120*60],byte 1
jne no_update
mov [edx+120*60],byte 0
call draw_channel_text
no_update:
call print_user_list
nopri2:
jmp w_t
check_mouse:
pusha
mov eax,37
mov ebx,1
mcall
mov ebx,eax
shr eax,16
and ebx,0xffff
cmp eax,420
jb no_mouse
cmp eax,494
jg no_mouse
cmp ebx,145
jg no_mouse
cmp ebx,23
jb no_mouse
cmp ebx,100
jb no_plus
mov eax,ebp
imul eax,120*80
add eax,120*70+I_END
inc dword [eax-8]
call print_user_list
mov eax,5
mov ebx,8
mcall
jmp no_mouse
no_plus:
cmp ebx,80
jg no_mouse
mov eax,ebp
imul eax,120*80
add eax,120*70+I_END
cmp dword [eax-8],dword 0
je no_mouse
dec dword [eax-8]
call print_user_list
mov eax,5
mov ebx,8
mcall
no_minus:
no_mouse:
popa
ret
thread_key:
mov eax,2
mcall
shr eax,8
cmp eax,8
jne no_bks
cmp [xpos],0
je w_t
dec [xpos]
call print_entry
jmp w_t
no_bks:
cmp eax,20
jbe no_character
mov ebx,[xpos]
mov [send_string+ebx],al
inc [xpos]
cmp [xpos],80
jb xpok
mov [xpos],79
xpok:
call print_entry
jmp w_t
no_character:
cmp eax,13
jne no_send
cmp [xpos],0
je no_send
mov dword [send_to_channel],ebp
pusha
mcall 60,2,[main_PID],0,1
wait_for_sending:
mov eax,5
mov ebx,1
mcall
cmp dword [ipcbuf+4],8
jne wait_for_sending
popa
call draw_channel_text
call print_entry
jmp w_t
no_send:
jmp w_t
draw_channel_text:
pusha
mov eax,4
mov ebx,10*65536+26
mov ecx,12
mov esi,[rxs]
dct:
pusha
mov cx,bx
shl ecx,16
mov cx,9
mov eax,13
mov ebx,10*65536
mov bx,word [rxs]
imul bx,6
mov edx,0xffffff
mcall
popa
push ecx
mov eax,4
mov ecx,0
cmp [edx],word '* '
jne no_red
mov ecx,0x0000ff
no_red:
cmp [edx],word '**'
jne no_light_blue
cmp [edx+2],byte '*'
jne no_light_blue
mov ecx,0x0000ff
no_light_blue:
cmp [edx],byte '#'
jne no_blue
mov ecx,0x0000ff
no_blue:
mcall
add edx,[rxs]
add ebx,10
pop ecx
loop dct
popa
ret
thread_draw_window:
pusha
mov eax,12
mov ebx,1
mcall
mov ebx,ebp ; draw window
shl ebx,16+4
xor eax,eax
mov ecx,ebx
mov bx,499
mov cx,170
mov edx,[wcolor]
add edx,0x03ffffff
mov esi,0x80555599
mov edi,0x00ffffff
mcall
mov eax,ebp ; label
add eax,48
mov [labelc+14],al
mov eax,ebp
shl eax,5
add eax,channel_list
mov esi,eax
mov edi,labelc+17
movzx ecx,byte [eax+31]
cld
rep movsb
mov esi,17 ; print label
movzx ebx,byte [eax+31]
add esi,ebx
mov eax,4
mov ebx,9*65536+8
mov ecx,0x00ffffff
mov edx,labelc
mcall
mov eax,38 ; line
mov ebx,5*65536+494
mov ecx,148*65536+148
mov edx,[channel_line_sun]
mcall
add ecx,1*65536+1
mov edx,[channel_line_shadow]
mcall
;mov eax,38 ; line
mov ebx,410*65536+410
mov ecx,22*65536+148
mov edx,[channel_line_sun]
mcall
add ebx,1*65536+1
mov edx,[channel_line_shadow]
mcall
mov eax,12
mov ebx,2
mcall
popa
ret
; DATA AREA
socket dd 0x0
bgc dd 0x000000
dd 0x000000
dd 0x00ff00
dd 0x0000ff
dd 0x005500
dd 0xff00ff
dd 0x00ffff
dd 0x770077
tc dd 0xffffff
dd 0xff00ff
dd 0xffffff
dd 0xffffff
dd 0xffffff
dd 0xffffff
dd 0xffffff
dd 0xffffff
channel_line_sun dd 0x9999ff
channel_line_shadow dd 0x666699
cursor_on_off dd 0x0
max_windows dd 20
thread_stack dd 0x9fff0
;thread_nro dd 1
;thread_screen dd I_END+120*80*1
action_header_blue db 10,'*** ',0
action_header_red db 10,'*** ',0
action_header_short db 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 ' kicked from ',0
index_list_1 dd 0x0000bb
index_list_2 dd 0x0000ff
posx dd 0x0
incoming_pos dd 0x0
incoming_string: times 128 db 0
pos dd 0x0
text_start dd I_END
irc_data dd 0x0
print db 0x0
cmd dd 0x0
rxs dd 66
res: db 0,0
command: times 600 db 0x0
nick dd 0,0,0
irc_command dd 0,0
command_position dd 0x0
counter dd 0
send_to_server db 0
channel_list: times 32*20 db 32
send_to_channel dd 0x0
send_string_header: db 'privmsg #eax :'
times 100 db 0x0
send_string: times 100 db 0x0
xpos dd 0
string0: db 'USER guest ser1 ser2 :'
string0l:
string1: db 'nick '
string1l:
attribute dd 0
scroll dd 1
dd 12
numtext db ' '
wcolor dd 0x000000
labelc db 'AIRC - WINDOW X: #xxx '
title db 'IRC client ',version,0
ipcbuf:
dd 0
dd 8
dd ?
dd ?
db ?
.size = $
align 4
@IMPORT:
library network, 'network.obj', msgbox, 'msgbox.obj'
import network, \
getaddrinfo_start, 'getaddrinfo_start', \
getaddrinfo_process, 'getaddrinfo_process', \
getaddrinfo_abort, 'getaddrinfo_abort', \
freeaddrinfo, 'freeaddrinfo'
import msgbox, mb_create, 'mb_create', mb_setfunctions, 'mb_setfunctions'
msgbox_running db ? ; must be the byte before msgbox_struct
; look to the handler of button 21
msgbox_struct:
.default:
dw ? ; default button, will be filled with current encoding
db 'Encoding',0
db 'Select encoding for all messages:',0
db 'CP866',0
db 'CP1251',0
db 'UTF-8',0
db 0
align 4
status dd STATUS_DISCONNECTED
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
msgbox_func_array:
times 3 dd msgbox_notify
initialized_size:
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
irc_server_name rb 256 ; buffer for irc_server_name
packetbuf rb 1024 ; buffer for packets to server
mb_stack rb 1024 ; stack for messagebox thread
;;
;; Channel data at I_END
;;
;; 120*80 * channel window (1+)
;;
;; At Size
;;
;; 00 , 120*60 window text 120 characters per row
;; 120*60 , 1 text is updated
;; 120*60+4 , 1 close yourself
;; 120*60+8 , 1 0 = channel window : 1 = private chat
;; 120*60+12 , 4 identifier of the thread
;; 120*61 , 256 channel name
;; 120*61+254 , 254 channel entry text from user
;; 120*61+255 , 1 length of entry text
;; 120*69+248 , 4 display names from n:th name
;; 120*69+252 , 4 length of names string
;; 120*70 , 1200 names separated with space
;;
I_END: