Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 1187 → Rev 1188

/programs/network/airc/trunk/airc.asm
1,15 → 1,16
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; IRC CLIENT for MenuetOS ;;
;; IRC CLIENT for KolibriOS ;;
;; ;;
;; License: GPL / See file COPYING for details ;;
;; Copyright 2004 (c) Ville Turjanmaa ;;
;; Copyright 2009 (c) CleverMouse ;;
;; ;;
;; Compile with FASM for Menuet ;;
;; Compile with FASM for Kolibri ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
version equ '0.51'
version equ '0.6'
 
 
;__DEBUG__ equ 1
22,34 → 23,72
db 'MENUET01' ; 8 byte id
dd 0x01 ; required os
dd START ; program start
dd I_END ; program image size
dd initialized_size ; program image size
dd 0x100000 ; required amount of memory
dd 0x100000
dd 0,0
 
include "..\..\..\macros.inc"
include "../../../macros.inc"
include "../../../proc32.inc"
include "../../../develop/libraries/network/network.inc"
include "dll.inc"
;include "fdo.inc"
include "eth.inc"
;include "lang.inc"
 
irc_server_name db 'kolibrios.org',0 ; default server name
; 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 'kolibrios.org',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,10000111b
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 eax,32
mov al,32
cld
rep stosb
 
65,24 → 104,20
 
still:
 
inc [cursor_on_off]
 
mov eax,5
mov ebx,1
mov eax,10 ; wait here for event
mcall
 
mov eax,11 ; wait here for event
mcall
 
call print_status
 
cmp eax,1 ; redraw
dec eax ; redraw
je redraw
cmp eax,2 ; key
dec eax ; key
je main_window_key
cmp eax,3 ; button
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
90,16 → 125,7
call draw_channel_text
no_main_update:
 
call read_incoming_data
 
call send_data_to_server
 
test [cursor_on_off],0x3f
jnz nopri
inc [blink]
call blink_cursor
call print_channel_list
nopri:
 
jmp still
 
110,78 → 136,112
 
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
 
print_status:
main_window_key:
 
pusha
 
mov eax,53
mov ebx,6
mov ecx,[socket]
mov eax,2
mcall
 
mov [status],eax
shr eax,8
 
cmp [old_status],eax
je nopr
cmp eax,8
jne no_bks2
cmp [xpos],0
je still
dec [xpos]
call print_entry
jmp still
no_bks2:
 
mov [old_status],eax
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:
 
push eax
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:
 
mov eax,13
mov ebx,450*65536+30
mov ecx,231*65536+10
mov edx,0xffffff
mcall
jmp still
 
pop ecx
mov eax,47
mov ebx,2*65536
mov edx,450*65536+231
mov esi,0x000000
mcall
 
nopr:
 
popa
 
ret
 
status dd 0
old_status dd 0
 
 
socket_commands:
 
cmp ah,22 ; open socket
cmp ah,22 ; connect
jnz tst3
mov eax,3
mcall
mov ecx,eax
 
pusha
mov eax,irc_server_name
resolve irc_server_name,dword[irc_server_ip]
;DEBUGF 1,'%u.%u.%u.%u\n',1[irc_server_ip],1[irc_server_ip+1],1[irc_server_ip+2],1[irc_server_ip+3]
popa
; ignore if status is not "disconnected"
cmp [status], STATUS_DISCONNECTED
jnz .nothing
 
mov eax,53
mov ebx,5
mov edx,6667
mov esi,dword [irc_server_ip]
mov edi,1
mcall
mov [socket], eax
; 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:
 
 
188,116 → 248,161
cmp ah,23 ; write userinfo
jnz tst4
 
mov eax,53 ; user
mov ebx,7
mov ecx,[socket]
mov edx,string0l-string0
; 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
mcall
 
mov eax,53 ;
mov ebx,7
mov ecx,[socket]
mov edx,[user_real_name]
mov ecx, string0l-string0
rep movsb
mov esi,user_real_name+4
mcall
 
mov eax,53 ;
mov ebx,7
mov ecx,[socket]
mov edx,2
mov esi,line_feed
mcall
 
 
mov eax,5
mov ebx,10
mcall
 
mov eax,53 ; nick
mov ebx,7
mov ecx,[socket]
mov edx,string1l-string1
mov ecx, [esi-4]
rep movsb
mov al, 13
stosb
mov al, 10
stosb
mov esi,string1
mcall
 
mov eax,53 ;
mov ebx,7
mov ecx,[socket]
mov edx,[user_nick]
mov ecx, string1l-string1
rep movsb
mov esi,user_nick+4
mcall
 
mov eax,53 ;
mov ebx,7
mov ecx,[socket]
mov edx,2
mov esi,line_feed
mcall
 
 
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
 
line_feed: db 13,10
 
tst4:
 
 
cmp ah,24 ; close socket
jnz no_24
mov eax,53
mov ebx,8
mov ecx,[socket]
mcall
ret
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
 
main_window_key:
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
 
mov eax,2
mcall
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
 
shr eax,8
msgbox_notify:
inc byte [msgbox_running]
mcall 60,2,[main_PID],0,1
ret
 
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_send
cmp [xpos],0
je no_send2
cmp [send_string],byte '/' ; server command
jne no_send2
mov [send_to_server],1
jmp still
no_send2:
 
jmp still
 
 
print_channel_list:
 
pusha
431,29 → 536,48
 
start_user_list_at dd 0x0
 
recode_to_cp866:
rep movsb
ret
 
recode_to_cp1251:
push esi edx
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 al,[cp866_table+eax]
@@: mov [esi-1],al
dec edx
jnz .loop
pop edx esi
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]
 
send_data_to_server:
process_command:
 
pusha
 
cmp [send_to_server],1
jne sdts_ret
 
mov eax,[xpos]
mov [send_string+eax+0],byte 13
mov [send_string+eax+1],byte 10
469,6 → 593,10
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
510,27 → 638,26
mov [edi],word ' :'
 
mov esi, send_string_header
mov edx,10
mov ecx,10
movzx ebx,byte [eax+31]
add edx,ebx
add ecx,ebx
 
mov eax, 53 ; write channel
mov ebx, 7
mov ecx, [socket]
mcall
mov edi, packetbuf
rep movsb
 
mov esi,send_string
mov edx,[xpos]
inc edx
mov ecx,[xpos]
inc ecx
 
call recode_to_cp1251
call recode
 
mov eax, 53 ; write message
mov ebx, 7
mov ecx, [socket]
mcall
mov esi, packetbuf
mov edx, edi
sub edx, esi
mcall 53, 7, [socket]
 
jmp send_done
mov [xpos], 0
jmp sdts_ret
 
server_command:
 
539,6 → 666,10
 
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
548,7 → 679,7
 
pusha
mov edi,text+70*1+15
mov eax,32
mov al,32
mov ecx,15
cld
rep stosb
556,15 → 687,13
 
mov esi,user_nick+4
mov edi,text+70*1+15
mov ecx,[user_nick]
mov ecx,[esi-4]
cld
rep movsb
 
mov [xpos],0
call draw_window
 
mov [xpos],0
mov [send_to_server],0
 
popa
ret
 
575,6 → 704,10
 
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
584,7 → 717,7
 
pusha
mov edi,text+70*0+15
mov eax,32
mov al,32
mov ecx,15
cld
rep stosb
592,16 → 725,12
 
mov esi,user_real_name+4
mov edi,text+70*0+15
mov ecx,[xpos]
sub ecx,7
cld
mov ecx,[esi-4]
rep movsb
 
mov [xpos],0
call draw_window
 
mov [xpos],0
mov [send_to_server],0
 
popa
ret
 
610,43 → 739,42
cmp [send_string+1],dword 'aser'
jne no_set_server
 
pusha
mov eax,send_string
add eax,[xpos]
mov dword[eax],0
resolve send_string+7,dword[irc_server_ip]
;DEBUGF 1,'%u.%u.%u.%u\n',1[irc_server_ip],1[irc_server_ip+1],1[irc_server_ip+2],1[irc_server_ip+3]
popa
 
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 eax,32
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
cld
rep movsb
 
mov [xpos],0
call draw_window
 
mov [xpos],0
mov [send_to_server],0
 
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
 
675,7 → 803,7
push edi
push eax
mov [edi+120*60+8],byte 1 ; query window
mov eax,32
mov al,32
mov ecx,120*60
cld
rep stosb
683,11 → 811,10
pop edi
 
; eax has the free position
mov [thread_screen],edi
; mov [thread_screen],edi
call create_channel_window
 
mov [xpos],0
mov [send_to_server],0
 
popa
ret
696,8 → 823,13
 
 
mov esi, send_string+1
mov edx, [xpos]
add edx,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
707,7 → 839,6
send_done:
 
mov [xpos],0
mov [send_to_server],0
 
cmp [send_string+1],dword 'quit'
jne no_quit_server
724,6 → 855,7
mov edi,I_END
newclose:
mov [edi+120*60+4],byte 1
call notify_channel_thread
add edi,120*80
loop newclose
 
737,49 → 869,161
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
 
read_new_byte:
 
call read_incoming_byte
cmp ecx,-1
je no_data_in_buffer
 
cmp bl,10
jne no_start_command
.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 bl,13
jne no_end_command
mov eax,[cmd]
mov [eax+command-2],byte 0
.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
mov eax,0
cld
xor eax, eax
rep stosb
mov [cmd],0
no_end_command:
 
mov eax,[cmd]
cmp eax,512
jge still
 
mov [eax+command-2],bl
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 read_new_byte
 
no_data_in_buffer:
 
@@:
jmp .byteloop
.nothing:
popa
 
ret
 
 
823,20 → 1067,20
 
mov [cursor_on_off],0
 
mov [thread_nro],eax
; 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
mov edx,[thread_stack]
mcall
mov [edi+120*60+12], eax
 
mov eax,5
mov ebx,10
mcall
 
add [thread_stack],0x4000
add [thread_screen],120*80
; add [thread_screen],120*80
 
popa
 
862,12 → 1106,11
 
popa
 
ret
; Fall through to draw_cursor.
; ret
 
blink dd 0x0
draw_cursor:
 
blink_cursor:
 
pusha
 
mov eax,9
875,17 → 1118,15
mov ecx,-1
mcall
 
mov edx,[blink]
and edx,1
sub edx,1
cmp ax,word [0xe0000+4]
setnz dl
movzx edx,dl
neg edx
and edx,0xffffff
; mov edx,0
; jne no_blink
 
cmp ax,word [0xe0000+4]
jne no_blink
; call print_entry
 
call print_entry
 
mov ebx,[xpos]
imul ebx,6
add ebx,8
900,14 → 1141,14
 
ret
 
no_blink:
; no_blink:
;
; mov eax,13
; mov ebx,8*65536+6*60
; mov ecx,151*65536+13
; mov edx,0xffffff
; mcall
 
mov eax,13
mov ebx,8*65536+6*60
mov ecx,151*65536+13
mov edx,0xffffff
mcall
 
popa
 
ret
1016,32 → 1257,32
imul ecx,11
mov [pos],ecx
 
mov bl,13
; mov bl,13
; call print_character
mov bl,10
; mov bl,10
; call print_character
 
mov ecx,[cmd]
sub ecx,2
mov esi,command+0
newcmdc:
mov bl,[esi]
; mov ecx,[cmd]
; sub ecx,2
; mov esi,command+0
; newcmdc:
; mov bl,[esi]
; call print_character
inc esi
loop newcmdc
; inc esi
; loop newcmdc
 
mov edx,I_END
; call draw_channel_text
 
cmp [cmd],20
jge cmd_len_ok
; cmp [cmd],20
; jge cmd_len_ok
;
; mov [cmd],0
;
; popa
; ret
 
mov [cmd],0
 
popa
ret
 
 
cmd_len_ok:
 
cmp [command],dword 'PING' ; ping response
1065,23 → 1306,13
mov ebx,7
mov ecx,[socket]
mov edx,[cmd]
sub edx,2
and edx,255
mov esi,command
mov word [esi+edx-2], 0x0a0d
mcall
 
mov eax,53
mov ebx,7
mov ecx,[socket]
mov edx,2
mov esi,linef
mcall
 
popa
ret
 
linef db 13,10
 
no_ping_responce:
 
mov eax,[rxs]
1150,6 → 1381,7
add eax,8
mov dl,0
call print_text
call notify_channel_thread
popa
ret
 
1169,6 → 1401,7
 
mov dl,0
call print_text
call notify_channel_thread
 
popa
ret
1190,8 → 1423,9
add eax,5
call set_channel
 
mov eax,[text_start]
mov [eax+120*60+4],byte 1
mov edi,[text_start]
mov [edi+120*60+4],byte 1
call notify_channel_thread
 
popa
ret
1216,6 → 1450,7
add eax,5
mov dl,' '
call print_text
call notify_channel_thread
 
popa
ret
1268,7 → 1503,7
push edi
push eax
mov [edi+120*60+8],byte 0 ; channel window
mov eax,32
mov al,32
mov ecx,120*60
cld
rep stosb
1276,7 → 1511,7
pop edi
 
; eax has the free position
mov [thread_screen],edi
; mov [thread_screen],edi
call create_channel_window
 
no_new_window:
1301,6 → 1536,7
add eax,6
mov dl,0
call print_text
call notify_channel_thread
 
popa
ret
1329,6 → 1565,7
add eax,6
mov dl,0
call print_text
call notify_channel_thread
 
add [text_start],120*80
cmp [text_start],I_END+120*80*20
1365,6 → 1602,7
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
1395,6 → 1633,7
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
1432,6 → 1671,7
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
1465,7 → 1705,7
add edi,120*70
mov [edi-8],dword 0
mov [edi-4],dword 0
mov eax,32
mov al,32
mov ecx,1200
cld
rep stosb
1501,6 → 1741,7
mov ebx,[text_start]
add ebx,120*70
mov [ebx-4],eax
call notify_channel_thread
 
popa
ret
1645,6 → 1886,21
 
; 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
1746,6 → 2002,13
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:
1760,37 → 2023,7
ret
 
 
read_incoming_byte:
 
mov eax, 53
mov ebx, 2
mov ecx, [socket]
mcall
 
mov ecx,-1
 
cmp eax,0
je no_more_data
 
mov eax, 53
mov ebx, 3
mov ecx, [socket]
mcall
 
cmp bl,0x80
jb @f
and ebx,0x7F
mov bl,[cp1251_table+ebx]
@@:
 
mov ecx,0
 
no_more_data:
 
ret
 
 
 
draw_window:
 
pusha
1799,33 → 2032,40
mov ebx,1
mcall
 
mov [old_status],300
 
xor eax,eax ; draw window
mov ebx,5*65536+499
mov ecx,5*65536+345
mov ecx,5*65536+381
mov edx,[wcolor]
add edx,0x14ffffff
mov edi,title
mcall
 
mov eax,8 ; button: open socket
mov ebx,43*65536+22
mov ecx,229*65536+10
mov edx,22
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,229*65536+10
mov edx,23
mov ecx,241*65536+10
; mov edx,23
inc edx
mcall
 
;mov eax,8 ; button: close socket
mov ebx,317*65536+22
mov ecx,229*65536+10
mov edx,24
mov ecx,241*65536+10
; mov edx,24
inc edx
mcall
 
mov eax,38 ; line
1862,6 → 2102,8
mov edx,I_END ; text from server
call draw_channel_text
 
call print_entry
 
mov eax,12
mov ebx,2
mcall
1870,6 → 2112,40
 
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
 
1879,9 → 2155,12
db ' Real name : KolibriOS User - change with eg /areal Jill User '
db ' Nick : kolibri_user - change with eg /anick Jill '
db ' Server : kolibrios.org - change with eg /aserv irc.by '
db ' Encoding : UTF-8 '
db ' '
db ' 1) Open socket 2) Send userinfo Close socket '
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 #general '
1890,9 → 2169,19
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
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; CHANNEL THREADS
1903,23 → 2192,42
 
channel_thread:
 
mov ebp,[thread_nro]
; 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 eax,32
cld
; mov edi,ebp ; clear thread memory
; imul edi,120*80
; add edi,I_END
; mov ecx,120*80
; mov al,32
; cld
; rep stosb
 
mov edx,[thread_screen]
; 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:
 
1937,24 → 2245,18
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
 
mov eax,23
mov ebx,1
mcall
 
cmp eax,1
jne no_draw_window
call thread_draw_window
call draw_channel_text
call print_user_list
no_draw_window:
 
cmp eax,2
je thread_key
 
cmp eax,3
jne no_end
jmp w_t
thread_end:
mov eax,17
mcall
mov eax,ebp
1981,6 → 2283,8
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
1989,10 → 2293,6
call draw_channel_text
no_update:
 
test [cursor_on_off],0x3f
jnz nopri2
 
call blink_cursor
call print_user_list
 
nopri2:
2095,13 → 2395,15
cmp [xpos],0
je no_send
mov dword [send_to_channel],ebp
mov [send_to_server],1
pusha
mcall 60,2,[main_PID],0,1
wait_for_sending:
mov eax,5
mov ebx,1
mcall
cmp [send_to_server],1
je wait_for_sending
cmp dword [ipcbuf+4],8
jne wait_for_sending
popa
call draw_channel_text
call print_entry
jmp w_t
2265,8 → 2567,8
max_windows dd 20
 
thread_stack dd 0x9fff0
thread_nro dd 1
thread_screen dd I_END+120*80*1
;thread_nro dd 1
;thread_screen dd I_END+120*80*1
 
action_header_blue db 10,'*** ',0
action_header_red db 10,'*** ',0
2330,13 → 2632,55
labelc db 'AIRC - WINDOW X: #xxx '
title db 'IRC client ',version,0
 
;include_debug_strings ; ALWAYS present in data section
ipcbuf:
dd 0
dd 8
dd ?
dd ?
db ?
.size = $
 
irc_server_ip db ? ; bufer for server_IP
align 4
@IMPORT:
 
dnsMsg: rb 512 ; buffer used by DNS client
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
;;
2348,6 → 2692,7
;; 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
/programs/network/airc/trunk/dll.inc
0,0 → 1,124
 
proc dll.Load, import_table:dword
mov esi,[import_table]
.next_lib: mov edx,[esi]
or edx,edx
jz .exit
push esi
mov esi,[esi+4]
mov edi,s_libdir.fname
@@: lodsb
stosb
or al,al
jnz @b
mcall 68,19,s_libdir
or eax,eax
jz .fail
stdcall dll.Link,eax,edx
push eax
mov eax, [eax]
cmp dword [eax], 'lib_'
pop eax
jnz @f
stdcall dll.Init,[eax+4]
@@:
pop esi
add esi,8
jmp .next_lib
.exit: xor eax,eax
ret
.fail: add esp,4
xor eax,eax
inc eax
ret
endp
 
proc dll.Link, exp:dword,imp:dword
push eax
mov esi,[imp]
test esi,esi
jz .done
.next: lodsd
test eax,eax
jz .done
stdcall dll.GetProcAddress,[exp],eax
or eax,eax
jz @f
mov [esi-4],eax
jmp .next
@@: mov dword[esp],0
.done: pop eax
ret
endp
 
proc dll.Init, dllentry:dword
pushad
mov eax,mem.Alloc
mov ebx,mem.Free
mov ecx,mem.ReAlloc
mov edx,dll.Load
stdcall [dllentry]
popad
ret
endp
 
proc dll.GetProcAddress, exp:dword,sz_name:dword
mov edx,[exp]
xor eax,eax
.next: or edx,edx
jz .end
cmp dword[edx],0
jz .end
stdcall strcmp,[edx],[sz_name]
test eax,eax
jz .ok
add edx,8
jmp .next
.ok: mov eax,[edx+4]
.end: ret
endp
 
proc strcmp, str1:dword,str2:dword
push esi edi
mov esi,[str1]
mov edi,[str2]
xor eax,eax
@@: lodsb
scasb
jne .fail
or al,al
jnz @b
jmp .ok
.fail: or eax,-1
.ok: pop edi esi
ret
endp
 
; void* __stdcall mem.Alloc(unsigned size);
mem.Alloc:
push ebx ecx
mov ecx, [esp+12]
mcall 68, 12
pop ecx ebx
ret 4
 
; void* __stdcall mem.ReAlloc(void* mptr, unsigned size);
mem.ReAlloc:
push ebx ecx edx
mov edx, [esp+16]
mov ecx, [esp+20]
mcall 68, 20
pop edx ecx ebx
ret 8
 
; void __stdcall mem.Free(void* mptr);
mem.Free:
push ebx ecx
mov ecx, [esp+12]
mcall 68, 13
pop ecx ebx
ret 4
 
s_libdir:
db '/sys/lib/'
.fname rb 32