Intermediate version of IRCC: new multiline resizeable textbox with proper line-breaking, colors and scrolling. New usercommands: msg and ctcp. Small bugfixes and enhancements

git-svn-id: svn://kolibrios.org@4143 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
hidnplayr 2013-11-01 14:02:08 +00:00
parent 7830e9f673
commit 8ad9d9edd3
9 changed files with 1079 additions and 456 deletions

View File

@ -3,6 +3,7 @@
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; Written by CleverMouse ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;

View File

@ -3,6 +3,7 @@
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
@ -10,7 +11,8 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
draw_window:
draw_window: ; Completely redraw the window, recalculate all coordinates and sizes
pusha
@ -37,6 +39,12 @@ draw_window:
add esi, ebx
mcall 67, -1, -1 ; set the new sizes
popa
.dont_resize:
pusha
mcall 12, 1
xor eax, eax ; draw window
mov ebx, WIN_MIN_X
@ -49,39 +57,76 @@ draw_window:
mov ebx, [xsize]
mov ecx, [ysize]
sub cx, 15 ;;;;
sub cx, BOTTOM_Y ;;;;
push cx
shl ecx, 16
pop cx
mov edx, [colors.work_graph]
mcall 38 ; draw line
mcall 38 ; draw bottom line
mov ecx, TOP_Y SHL 16 + TOP_Y
mcall
mcall ; draw top line
; calculate available space for textbox and coordinates for scrollbars
mov eax, [ysize]
sub eax, TOP_Y + BOTTOM_Y - 1 ;;;;
mov [scroll2.y_size], ax
mov [scroll1.y_size], ax
sub eax, 4 ;;;;
xor edx, edx
mov ecx, FONT_HEIGHT
div ecx
mov [textbox_height], eax
mov [scroll2.cur_area], eax
mov [scroll1.cur_area], eax
mov eax, [xsize]
sub eax, SCROLLBAR_WIDTH
mov [scroll1.x_pos], ax
mov edi, [window_active]
cmp [edi + window.type], WINDOWTYPE_CHANNEL
jne @f
sub eax, USERLIST_WIDTH + SCROLLBAR_WIDTH + 2
@@:
mov [scroll2.x_pos], ax
sub eax, 10
xor edx, edx
mov ecx, FONT_WIDTH
div ecx
mov [textbox_width], eax
; recalculate text line breaks (because height/width might have changed..)
mov edi, [window_active]
mov esi, [edi + window.text_start]
call text_insert_newlines
mov [edi + window.text_lines], edx
mov [edi + window.text_scanned], esi
; and redraw the textbox (and scrollbar if needed)
mov [scroll2.all_redraw], 1
call draw_channel_text
; Draw userlist if active window is a channel
mov edi, [window_active]
cmp [edi + window.type], WINDOWTYPE_CHANNEL
jne .not_channel
; draw a vertical separator line
; TODO: dont draw this if we draw textbox scrollbar ??
mov ebx, [xsize]
sub ebx, USERLIST_X + SCROLLBAR_WIDTH + 3
sub ebx, USERLIST_WIDTH + SCROLLBAR_WIDTH + 3
push bx
shl ebx, 16
pop bx
mov ecx, [ysize]
add ecx, TOP_Y SHL 16 -(15) ;;;;
mcall
call redraw_channel_list
add ecx, TOP_Y SHL 16 -(BOTTOM_Y) ;;;;
mov edx, [colors.work_graph]
mcall 38
mov [scroll1.all_redraw], 1
call draw_channel_list
.not_channel:
mov edx, [edi + window.data_ptr]
add edx, window_data.text
call draw_channel_text
; editbox
; draw editbox
mov eax, [ysize]
sub eax, 12 ;;;;;;
mov [edit1.top], eax
@ -92,7 +137,7 @@ draw_window:
push dword edit1
call [edit_box_draw]
; tabs
; draw tabs
call draw_windowtabs
popa
@ -100,31 +145,15 @@ draw_window:
redraw_channel_list:
draw_channel_list:
; First, calculate scrollbar
mov ebx, [window_active]
mov eax, [ebx + window.users] ; number of users in the open window
mov [scroll1.max_area], eax
mov eax, [ysize]
sub eax, TOP_Y + 15 ;;;;
push eax
mov [scroll1.y_size], ax
mov eax, [xsize]
sub eax, SCROLLBAR_WIDTH
mov [scroll1.x_pos], ax
pop eax ; scrollbar height
xor edx, edx
mov ecx, 10
div ecx
mov [scroll1.cur_area], eax
pusha
; Do we need a scrollbar?
cmp eax, [scroll1.max_area]
mov ebx, [window_active]
mov eax, [ebx + window.users]
mov [scroll1.max_area], eax
cmp [scroll1.cur_area], eax
jae .noscroll
; Is the current position greater then the max position?
@ -132,42 +161,37 @@ redraw_channel_list:
ja @f
mov [scroll1.position], eax
@@:
; OK, draw the scrollbar
mov [scroll1.all_redraw], 1
push dword scroll1
call [scrollbar_v_draw]
call [scrollbar_draw]
jmp print_channel_list
; dont redraw scrollbar completely next time,
; unless draw_window asks us to by setting [scroll1.all_redraw] back to 1
mov [scroll1.all_redraw], 0
jmp .scroll_done
.noscroll:
mov [scroll1.position], 0
.scroll_done:
print_channel_list:
pusha
; first, draw an invisible button
; draw an invisible button, where the usernames will go
mov ebx, [xsize]
sub ebx, USERLIST_X + SCROLLBAR_WIDTH
sub ebx, USERLIST_WIDTH + SCROLLBAR_WIDTH
shl ebx, 16
push ebx
mov bx, USERLIST_X
mov bx, USERLIST_WIDTH
mov ecx, [ysize]
add ecx, TEXT_Y shl 16 - (TEXT_Y + 15) ;;;;; + 10???
add ecx, TEXT_Y shl 16 - (TEXT_Y + 16)
push ecx ebx
mov edx, WINDOW_BTN_LIST + 1 shl 29 + 1 shl 30
mcall 8
; draw rectangle to clear previously printed names
; draw a filled rectangle to clear previously printed names
pop ebx ecx
mov edx, [colors.work]
mcall 13
; now draw the names according to the scrollbar position and window size
; now, draw the names according to the scrollbar position and window size
mov eax, [scroll1.position]
xor edx, edx
mov ecx, MAX_NICK_LEN
@ -185,8 +209,7 @@ print_channel_list:
or ecx, 0x80000000 ; ASCIIZ string
mov eax, 4 ; draw text
mov edi, [ysize] ; Calculate how many names will fit on screen
sub edi, TEXT_Y + 15 ;+ 10 ;;;;;
mov edi, [textbox_height] ; how many names will fit on screen
.loop:
cmp byte[edx], 0 ; end of list?
je .done
@ -196,7 +219,7 @@ print_channel_list:
; yes, highlight it
pusha
mov cx, bx
mov bx, USERLIST_X
mov bx, USERLIST_WIDTH
shl ecx, 16
mov cx, 10 - 1
mov edx, 0x00000055 ; blue!
@ -214,10 +237,10 @@ print_channel_list:
mcall
.next:
add edx, MAX_NICK_LEN ; next name
add ebx, 10 ; height distance between lines
sub edi, 10
ja .loop
add edx, MAX_NICK_LEN
add ebx, FONT_HEIGHT
dec edi
jnz .loop
.done:
popa

View File

@ -13,7 +13,7 @@
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
version equ '0.1'
version equ '0.15'
; connection status
STATUS_DISCONNECTED = 0
@ -23,15 +23,15 @@ STATUS_CONNECTED = 3
; window flags
FLAG_UPDATED = 1 shl 0
FLAG_CLOSE = 1 shl 1
FLAG_RECEIVING_NAMES = 1 shl 2
FLAG_RECEIVING_NAMES = 1 shl 1
; window types
WINDOWTYPE_SERVER = 0
WINDOWTYPE_CHANNEL = 1
WINDOWTYPE_CHAT = 2
WINDOWTYPE_LIST = 3
WINDOWTYPE_DCC = 4
WINDOWTYPE_NONE = 0
WINDOWTYPE_SERVER = 1
WINDOWTYPE_CHANNEL = 2
WINDOWTYPE_CHAT = 3
WINDOWTYPE_LIST = 4
WINDOWTYPE_DCC = 5
; supported encodings
CP866 = 0
@ -42,15 +42,17 @@ UTF8 = 2
USERCMD_MAX_SIZE = 400
WIN_MIN_X = 600
WIN_MIN_Y = 165
WIN_MIN_Y = 170
TEXT_X = 5
TEXT_Y = 30
TEXT_Y = TOP_Y + 2
TOP_Y = 25
TOP_Y = 24
BOTTOM_Y = 15
MAX_WINDOWS = 20
MAX_USERS = 4096
TEXT_BUFFERSIZE = 4096;*1024
MAX_NICK_LEN = 32
MAX_REAL_LEN = 32 ; realname
@ -69,11 +71,11 @@ WINDOW_BTN_START = 100
WINDOW_BTN_CLOSE = 2
WINDOW_BTN_LIST = 3
SCROLLBAR_WIDTH = 12
SCROLLBAR_WIDTH = 14
USERLIST_WIDTH = 100
USERLIST_X = 98
TEXTBOX_LINES = 12
FONT_HEIGHT = 9
FONT_WIDTH = 6
format binary as ""
@ -98,25 +100,31 @@ include "../../struct.inc"
include '../../develop/libraries/box_lib/trunk/box_lib.mac'
struct window
data_ptr dd ? ; zero if not used
data_ptr dd ?
flags db ?
type db ?
name rb MAX_WINDOWNAME_LEN
users dd ?
users_scroll dd ?
selected dd ? ; selected user, 0 if none selected
text_start dd ? ; pointer to current textbox data
text_end dd ?
text_print dd ? ; pointer to first character to print on screen
text_line_print dd ? ; line number of that character
text_write dd ? ; write pointer
text_lines dd ? ; total number of lines
text_scanned dd ? ; pointer to beginning of unscanned data (we still need to count number of lines, insert newline characters,..)
ends
struct window_data
text rb 120*60
title rb 256
text rb TEXT_BUFFERSIZE
names rb MAX_NICK_LEN * MAX_USERS
usertext rb 256
usertextlen dd ?
ends
include "encodings.inc"
include "window.inc" ; also contains text print routines
include "window.inc"
include "serverparser.inc"
include "userparser.inc"
include "socket.inc"
@ -160,26 +168,30 @@ START:
rep stosd
; allocate window data block
call window_create
mov ebx, windows
mov [ebx + window.data_ptr], eax
mov [ebx + window.flags], 0
call window_create
test eax, eax
jz error
mov [ebx + window.type], WINDOWTYPE_SERVER
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 [scroll2.bg_color], eax
mov eax, [colors.work_button]
mov [scroll1.front_color], eax
mov [scroll2.front_color], eax
mov eax, [colors.work_text]
mov [scroll1.line_color], eax
mov [scroll2.line_color], eax
mov [scroll1.type], 1 ; 0 = simple, 1 = skinned
mov [scroll2.type], 1
; get settings from ini
invoke ini.get_str, path, str_user, str_nick, user_nick, MAX_NICK_LEN, default_nick
@ -190,13 +202,12 @@ START:
mov esi, str_welcome
call print_text2
call draw_window ;;; FIXME (gui is not correctly drawn first time because of window sizes)
call draw_window ; Draw window a first time, so we can figure out skin size
redraw:
call draw_window
still:
; wait here for event
mcall 10
@ -214,15 +225,15 @@ still:
call process_network_event
mov edx, [window_active]
test [edx + window.flags], FLAG_UPDATED
mov edi, [window_active]
test [edi + 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
mov edi, [window_active]
cmp [edi + window.type], WINDOWTYPE_CHANNEL
jne .no_update
call draw_channel_list
.no_update:
call print_channel_list
jmp still
@ -236,8 +247,7 @@ button:
cmp ax, WINDOW_BTN_CLOSE
jne @f
call window_close
call cmd_usr_close_window
jmp still
@@:
@ -248,7 +258,7 @@ button:
mcall 37, 1 ; Get mouse position
sub ax, TEXT_Y
mov bl, 10
mov bl, FONT_HEIGHT
div bl
and eax, 0x000000ff
inc eax
@ -256,7 +266,7 @@ button:
mov ebx, [window_active]
mov [ebx + window.selected], eax
call print_channel_list
call draw_channel_list
pop eax
test eax, 1 shl 25 ; Right mouse button pressed?
@ -283,15 +293,17 @@ button:
cmp ax, MAX_WINDOWS
ja exit
; OK, time to switch to another window.
mov dx, sizeof.window
mul dx
shl edx, 16
mov dx, ax
add edx, windows
cmp [edx + window.data_ptr], 0
cmp [edx + window.type], WINDOWTYPE_NONE
je exit
mov [window_active], edx
call window_refresh
mov [scroll2.position], 1 ;;; FIXME
call draw_window
jmp still
@ -304,6 +316,8 @@ exit:
call cmd_usr_quit_server
@@:
error:
mcall -1
@ -315,20 +329,32 @@ main_window_key:
push dword edit1
call [edit_box_key]
; cmp ah, 178
; jne .no_up
;
; jmp still
;
;
; .no_up:
; cmp ah, 177
; jne .no_down
;
; jmp still
;
; .no_down:
cmp ah, 13 ; enter
jne no_send2
call user_parser
mov eax, [edit1.size]
mov [edit1.size], 0
mov [edit1.pos], 0
push dword edit1
call [edit_box_draw]
mov edx, [window_active]
mov edx, [edx + window.data_ptr]
add edx, window_data.text
call draw_channel_text
jmp still
@ -340,14 +366,31 @@ mouse:
push dword edit1
call [edit_box_mouse]
; TODO: check if scrollbar is active
; TODO: check if scrollbar is active?
mov edi, [window_active]
cmp [edi + window.type], WINDOWTYPE_CHANNEL
jne @f
push [scroll1.position]
push dword scroll1
call [scrollbar_v_mouse]
call [scrollbar_mouse]
pop eax
cmp eax, [scroll1.position] ; did the scrollbar move?
je @f
call print_channel_list
call draw_channel_list
@@:
; TODO: check if scrollbar is active?
mov edi, [window_active]
mov eax, [edi + window.text_lines]
cmp eax, [textbox_height]
jbe @f
push dword scroll2
call [scrollbar_mouse]
; mov edi, [window_active]
mov edx, [scroll2.position]
sub edx, [edi + window.text_line_print]
je @f
call draw_channel_text.scroll_to_pos
@@:
jmp still
@ -361,9 +404,16 @@ db 'CP1251'
db 'UTF-8 '
encoding_text_len = 6
action_header db '*** ', 0
action_header_short db '* ', 0
ctcp_header db '-> [',0
join_header db 3,'3* ', 0
quit_header db 3,'5* ', 0
nick_header db 3,'2* ', 0
kick_header db 3,'5* ', 0
mode_header db 3,'2* ', 0
part_header db 3,'5* ', 0
topic_header db 3,'3* ', 0
action_header db 3,'6* ', 0
ctcp_header db 3,'13-> [',0
msg_header db 3,'7-> *',0
ctcp_version db '] VERSION',10,0
ctcp_ping db '] PING',10,0
ctcp_time db '] TIME',10,0
@ -376,6 +426,7 @@ 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_reconnect db 'Connection reset by user.',10,0
str_version db 'VERSION '
str_programname db 'KolibriOS IRC client ', version, 0
@ -390,23 +441,22 @@ default_nick db 'kolibri_user', 0
default_real db 'Kolibri User', 0
default_quit db 'KolibriOS forever', 0
str_welcome db 10
db ' ______________________ __ __ __',10
db '| \______ \_ ___ \ ____ | | |__| ____ _____/ |_',10
db '| || _/ \ \/ _/ ___\| | | |/ __ \ / \ __\',10
db '| || | \ \____ \ \___| |_| \ ___/| | \ |',10
db '|___||____|_ /\______ / \___ >____/__|\___ >___| /__|',10
db ' \/ \/ \/ \/ \/',10
str_welcome db 3,'3 ___',3,'7__________',3,'6_________ ',3,'4 __ __ __',10
db 3,'3| \',3,'7______ \',3,'6_ ___ \ ',3,'4 ____ | | |__| ____ _____/ |_',10
db 3,'3| |',3,'7| _/',3,'6 \ \/ ',3,'4 _/ ___\| | | |/ __ \ / \ __\',10
db 3,'3| |',3,'7| | \',3,'6 \____',3,'4 \ \___| |_| \ ___/| | \ |',10
db 3,'3|___|',3,'7|____|_ /\',3,'6______ /',3,'4 \___ >____/__|\___ >___| /__|',10
db 3,'3 ',3,'7 \/ ',3,'6 \/ ',3,'4 \/ \/ \/',10
db 10
db 'Welcome to IRC client ',version,' for KolibriOS',10
db 'Welcome to the KolibriOS IRC client v',version,10
db 10
db 'Type /help for help',10,0
db 'Type /help for help',10,10,0
str_nickchange db 'Nickname is now ',0
str_realchange db 'Real name is now ',0
str_dotnewline db '.',10, 0
str_newline db 10, 0
str_connecting db 10,'* Connecting to ',0
str_connecting db 3,'3* Connecting to ',0
str_help db 10,'following commands are available:',10
db 10
db '/nick <nick> : change nickname to <nick>',10
@ -414,13 +464,30 @@ str_help db 10,'following commands are available:',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_1 db 3,'13 -',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
irc_colors dd 0xffffff ; 0 white
dd 0x000000 ; 1 black
dd 0x00007f ; 2 blue (navy)
dd 0x009300 ; 3 green
dd 0xff0000 ; 4 red
dd 0x7f0000 ; 5 brown (maroon)
dd 0x9c009c ; 6 purple
dd 0xfc7f00 ; 7 olive
dd 0xffff00 ; 8 yellow
dd 0x00fc00 ; 9 light green
dd 0x009393 ; 10 teal
dd 0x00ffff ; 11 cyan
dd 0x0000fc ; 12 royal blue
dd 0xff00ff ; 13 pink
dd 0x7f7f7f ; 14 grey
dd 0xd4d0c4 ; 15 light grey (silver)
sockaddr1:
dw AF_INET4
.port dw 0x0b1a ; 6667
@ -430,9 +497,9 @@ sockaddr1:
status dd STATUS_DISCONNECTED
text_start dd ? ; pointer to current textbox data
textbox_width dd 80 ; in characters, not pixels ;)
text_pos dd ? ; text writing cursor
textbox_height dd 12 ; in characters
textbox_width dd 78 ; in characters, not pixels ;)
window_active dd windows
window_print dd windows
@ -454,24 +521,23 @@ import libini,\
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'
edit_box_draw, 'edit_box',\
edit_box_key, 'edit_box_key',\
edit_box_mouse, 'edit_box_mouse',\
scrollbar_draw, 'scrollbar_v_draw',\
scrollbar_mouse,'scrollbar_v_mouse'
I_END:
; width, left, top
edit1 edit_box 0, 0, 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, 1
scroll2 scrollbar SCROLLBAR_WIDTH, 300, 150, TOP_Y, 10, 100, 0, 0, 0, 0, 0, 1
; xsize, xpos, ysize, ypos, btn_height, max, cur, pos, bgcol, frcol, linecol
scroll1 scrollbar SCROLLBAR_WIDTH, 0, 0, TOP_Y, SCROLLBAR_WIDTH, 0, 0, 0, 0, 0, 0, 1
scroll2 scrollbar SCROLLBAR_WIDTH, 0, 0, TOP_Y, SCROLLBAR_WIDTH, 0, 0, 0, 0, 0, 0, 1
usercommand db '/server chat.freenode.net', 0
rb MAX_COMMAND_LEN
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

View File

@ -3,6 +3,7 @@
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
@ -48,7 +49,9 @@ server_commands:
dd '322 ', cmd_322 ; RPL_LIST
dd '323 ', cmd_323 ; RPL_LISTEND
dd '324 ', cmd_324 ;;;;
dd '328 ', cmd_328 ; RPL_CHANNEL_URL
dd '329 ', cmd_329
dd '332 ', cmd_topic
dd '333 ', cmd_333 ; nickname and time of topic
dd '353 ', cmd_353 ; name reply
@ -110,6 +113,8 @@ compare_to_nick:
pop esi
ret
align 4
skip_nick:
@ -135,6 +140,8 @@ skip_nick:
cmd_324:
cmd_329:
cmd_328:
cmd_421:
cmd_372:
@ -149,11 +156,16 @@ cmd_notice:
jne .gogogo
mov byte [esi-1], 0
if TIMESTAMP
call print_timestamp
end if
push esi
mov esi, str_1
call print_text2
mov esi, servercommand+1
call print_text2
mov eax, servercommand+1
mov dl, '!'
call print_text
mov esi, str_2
call print_text2
pop esi
@ -177,12 +189,11 @@ cmd_notice:
cmp byte [esi], ':'
je .loop2
.fail:
call print_text2
mov esi, str_newline
call print_text2
.fail:
ret
@ -212,19 +223,20 @@ cmd_ping:
cmd_privmsg:
mov eax, dword[esi+4]
or eax, 0x20202020
cmp eax, 'msg '
jne .fail
add esi, 8 ; skip 'PRIVMSG '
call window_open ; esi now points to end of destination name
cmp byte[esi], 1
cmp byte[esi], 1 ; Client to Client protocol?
je cmd_ctcp
cmp dword[esi], 'ACTI' ; Action?
je .action
; nope, just plain old privmsg
if TIMESTAMP
; nope, just plain old privmsg, print it using '<nick> message' format
if TIMESTAMP
call print_timestamp
end if
end if
push esi
mov bl, '<'
@ -249,49 +261,36 @@ end if
.fail:
ret
.action:
add esi, 8
push esi
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
call print_text2
mov bl, 10
call print_character
ret
cmd_ctcp:
cmp byte [esi+4], ' '
jne .fail
inc esi
mov eax, dword[esi]
or eax, 0x20202020
cmp dword[esi], 'VERS'
cmp eax, 'vers'
je .version
cmp dword[esi], 'TIME'
cmp eax, 'time'
je .time
cmp dword[esi], 'PING'
cmp eax, 'ping'
je .ping
cmp eax, 'acti'
je .action
; cmp eax, 'dcc ' ; TODO
; je cmd_dcc
; Unknown CTCP command: TODO: just print to window??
.fail:
ret
.time:
mov byte [esi+4], ' '
mov byte[esi+4], ' '
lea edi, [esi+5]
; TODO: add system date (fn 29) in human readable format
@ -375,12 +374,52 @@ cmd_ctcp:
ret
.action:
add esi, 7
push esi
if TIMESTAMP
call print_timestamp
end if
mov esi, action_header
call print_text2
mov eax, servercommand+1 ; print nickname
mov dl, '!'
call print_text
mov bl, ' '
call print_character
pop esi
call print_text2 ; print message
mov bl, 10
call print_character
ret
cmd_dcc:
add esi, 4
mov eax, dword[esi]
or eax, 0x202020
cmp eax, 'send'
je .send
ret
.send:
ret
ctcp_reply:
push esi
mov dword [usercommand], 'NOTI'
mov dword [usercommand+4], 'CE '
@ -425,27 +464,34 @@ ctcp_reply:
cmd_part:
cmp byte [esi+4], ' '
jne .fail
add esi, 5 ; skip 'PART '
push esi
call skip_nick
call window_open
pop esi
; 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
; yes, close the window (if its open)
call window_find
test ebx, ebx
jz @f
call window_close
@@:
.fail:
ret
; somebody else parted, just print message
.dont_close:
push esi
mov esi, action_header
call skip_nick
call window_open
mov esi, part_header
call print_text2
mov eax, servercommand+1
@ -471,6 +517,9 @@ cmd_part:
cmd_join:
cmp byte [esi+4], ' '
jne .fail
add esi, 5 ; skip 'JOIN '
; compare nick: did we join a channel?
@ -488,27 +537,26 @@ cmd_join:
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_active], ebx
mov [window_print], ebx
call window_refresh
if TIMESTAMP
call print_timestamp
end if
push esi
mov esi, action_header
mov esi, join_header
call print_text2
mov esi, str_talking
@ -529,7 +577,11 @@ cmd_join:
push esi
call window_open
mov esi, action_header
if TIMESTAMP
call print_timestamp
end if
mov esi, join_header
call print_text2
mov eax, servercommand+1
@ -549,58 +601,71 @@ cmd_join:
mov esi, servercommand+1
call user_add
.fail:
ret
cmd_nick:
; NOTE: This command applies to a user, and thus has no specific channel
add esi, 5 ; skip 'NICK '
cmp byte[esi], ':' ; TODO: skip all spaces and semicolons?
cmp byte[esi+4], ' '
jne .fail
add esi, 5 ; skip 'NICK '
cmp byte[esi], ':'
jne @f
inc esi
@@:
; Change the nick in the current userlist. TODO: check other channels too!
push esi
mov ebx, [window_print]
mov esi, servercommand+1
call user_remove
mov esi, [esp]
call user_add
call redraw_channel_list
; Is it me who changed nick?
push esi
mov edi, servercommand+1
call compare_to_nick
pop esi
jne .not_me
mov ecx, MAX_NICK_LEN-1
push esi
.copyloop:
mov esi, [esp]
@@:
lodsb
test al, al
jz .copydone
jz @f
cmp al, ' '
je .copydone
je @f
cmp al, 10
je @f
cmp al, 13
je @f
stosb
dec ecx
jnz .copyloop
.copydone:
jnz @r
@@:
xor al, al
stosb
pop esi
.not_me:
; Now print a message on the current channel
push esi
mov esi, action_header_short
mov ebx, windows
mov ecx, MAX_WINDOWS
.window_loop:
push ecx ebx
cmp [ebx + window.type], WINDOWTYPE_CHANNEL
jne .next_window
mov esi, servercommand+1
call user_remove
test edi, edi
jz .next_window
mov esi, [esp + 8]
call user_add
mov [window_print], ebx
if TIMESTAMP
call print_timestamp
end if
mov esi, nick_header
call print_text2
mov eax, servercommand+1
@ -610,18 +675,31 @@ cmd_nick:
mov esi, is_now_known_as
call print_text2
pop esi
mov esi, [esp + 8] ; FIXME: dont print the 0x0a0d!!!
call print_text2
mov esi, str_newline
call print_text2
.next_window:
pop ebx ecx
add ebx, sizeof.window
dec ecx
jnz .window_loop
pop esi
.fail:
ret
cmd_kick:
cmp byte [esi+4], ' '
jne .fail
add esi, 5 ; skip 'KICK '
; Is it me who got kicked?
mov edi, servercommand+1
@ -636,7 +714,11 @@ cmd_kick:
call skip_nick
call window_open
mov esi, action_header_short
if TIMESTAMP
call print_timestamp
end if
mov esi, kick_header
call print_text2
mov eax, servercommand+1
@ -656,14 +738,38 @@ cmd_kick:
mov esi, servercommand+1
call user_remove
.fail:
ret
cmd_quit:
; NOTE: This command applies to a user, and thus has no specific channel
mov esi, action_header
cmp byte [esi+4], ' '
jne .fail
mov ebx, windows
mov ecx, MAX_WINDOWS
.window_loop:
push ecx
cmp [ebx + window.type], WINDOWTYPE_CHANNEL
jne .next_window
mov esi, servercommand+1
call user_remove
test edi, edi
jz .next_window
push ebx
mov [window_print], ebx
if TIMESTAMP
call print_timestamp
end if
mov esi, quit_header
call print_text2
mov eax, servercommand+1
@ -673,10 +779,16 @@ cmd_quit:
mov esi, has_quit_irc
call print_text2
; TODO: check other channels on same server too!
mov ebx, [window_print]
mov esi, servercommand+1
call user_remove
; TODO: check if quit message was given, and print it to the window
pop ebx
.next_window:
pop ecx
add ebx, sizeof.window
dec ecx
jnz .window_loop
.fail:
ret
@ -684,14 +796,35 @@ cmd_quit:
cmd_mode:
cmp byte [esi+4], ' '
jne .fail
add esi, 5 ; skip 'MODE '
call window_find
test ebx, ebx
jz .fail
; skip channel name
@@:
lodsb
test al, al
jz .fail
cmp al, 10
je .fail
cmp al, 13
je .fail
cmp al, ' '
jne @r
push esi
mov esi, action_header_short
if TIMESTAMP
call print_timestamp
end if
mov esi, mode_header
call print_text2
mov eax, servercommand+1
mov dl, ' '
mov dl, '!'
call print_text
mov esi, sets_mode
@ -705,6 +838,8 @@ cmd_mode:
;;; TODO: change username if needed
.fail:
ret
@ -739,7 +874,7 @@ cmd_353: ; channel usernames reply
jmp .add
.done:
call redraw_channel_list
call draw_channel_list
ret
@ -767,8 +902,12 @@ cmd_topic:
call skip_nick
call window_open
if TIMESTAMP
call print_timestamp
end if
push esi
mov esi, action_header
mov esi, topic_header
call print_text2
mov esi, str_topic
@ -799,8 +938,12 @@ cmd_333:
; dec ecx
; jnz .loop ; find some more spaces
if TIMESTAMP
call print_timestamp
end if
push esi
mov esi, action_header
mov esi, topic_header
call print_text2
mov esi, str_setby
@ -819,18 +962,20 @@ cmd_333:
.fail:
ret
cmd_322:
cmd_322: ; LIST
add esi, 4
mov [window_print], windows ; FIXME
call skip_nick
call print_text2
mov eax, esi
mov dl, 13
call print_text
mov esi, str_newline
call print_text2
ret
cmd_323:
cmd_323: ; LIST END
ret

View File

@ -3,6 +3,7 @@
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
@ -12,13 +13,13 @@
socket_connect:
; cmp [status], STATUS_CONNECTED ; TODO
; je disconnect
; ignore if status is not "disconnected"
cmp [status], STATUS_DISCONNECTED
jne .nothing
jne .reconnect
if TIMESTAMP
call print_timestamp
end if
mov esi, str_connecting
call print_text2
mov esi, irc_server_name
@ -63,12 +64,14 @@ socket_connect:
cmp eax, -1
jz .fail_refused
.nothing:
ret
.fail:
mov [status], STATUS_DISCONNECTED
if TIMESTAMP
call print_timestamp
end if
mov esi, str_sockerr
call print_text2
@ -77,6 +80,9 @@ socket_connect:
.fail_dns:
mov [status], STATUS_DISCONNECTED
if TIMESTAMP
call print_timestamp
end if
mov esi, str_dnserr
call print_text2
@ -85,11 +91,26 @@ socket_connect:
.fail_refused:
mov [status], STATUS_DISCONNECTED
if TIMESTAMP
call print_timestamp
end if
mov esi, str_refused
call print_text2
ret
.reconnect:
if TIMESTAMP
call print_timestamp
end if
mov esi, str_reconnect
call print_text2
mov esi, quit_msg
call cmd_usr_quit.with_message
jmp socket_connect
socket_write_userinfo:
@ -180,25 +201,11 @@ process_network_event:
inc [status]
.connected:
call read_incoming_data
call socket_receive
ret
disconnect:
cmp [status], STATUS_DISCONNECTED
je .nothing
mcall close, [socketnum]
mov [status], STATUS_DISCONNECTED
.nothing:
ret
read_incoming_data:
socket_receive:
pusha

View File

@ -3,6 +3,7 @@
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
@ -10,6 +11,71 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
text_insert_newlines: ; esi = ASCIIZ string
xor edx, edx ; number of lines of text
cmp byte[esi], 0
je .done
.next_line:
xor ebx, ebx
mov ecx, [textbox_width]
inc ecx
.more:
dec ecx
jz .end_of_line
lodsb ; get one character of the string
test al, al ; end of string?
jz .almost_done
cmp al, ' ' ; it's a space! remember its position
je .space
cmp al, 13 ; we already inserted a newline once, make it a space again
je .soft_nl
cmp al, 10 ; it's a newline, continue onto the next line
jne .more
inc edx
jmp .next_line
.soft_nl:
inc edx
mov byte[esi-1], ' '
mov ebx, esi
jmp .more
.space:
mov ebx, esi ; last detected space
jmp .more
.end_of_line:
inc edx
test ebx, ebx ; did we detect any spaces on this line?
jz .next_line ; no: just continue onto the next line
mov byte[ebx-1], 13 ; yes: replace last space on line with a soft newline
mov esi, ebx ; and continue parsing just after last space
jmp .next_line ;
.almost_done:
dec esi
.done:
ret
; When you set the direction flag before calling, you can also scan for previous line!
; in: esi
; out:esi
text_nextline:
mov ecx, [textbox_width]
.loop:
cmp byte[esi], 0
je .done
lodsb
cmp al, 10
je .done
cmp al, 13
je .done
dec ecx
jnz .loop
.done:
ret
print_text: ; eax = start ptr
; dl = end char
pusha
@ -27,6 +93,7 @@ print_text: ; eax = start ptr
.done:
popa
ret
@ -44,80 +111,253 @@ print_text2: ; esi = ptr to ASCIIZ string
.done:
popa
ret
; Character in bl
print_character:
pusha
mov ecx, TEXTBOX_LINES
imul ecx, [textbox_width]
mov esi, [text_start]
push esi edi
mov esi, [window_print]
mov edi, [esi + window.text_write]
mov byte[edi], bl
inc edi
cmp edi, [esi + window.text_end]
jae .uh_ow
mov [esi + window.text_write], edi
.continue:
or [esi + window.flags], FLAG_UPDATED
pop edi esi
cmp bl, 10 ; line down
je .linefeed
mov eax, [text_pos]
mov byte[esi + eax], bl ; write the byte
inc [text_pos]
cmp [text_pos], ecx
jb .done
.linefeed:
; scroll all text one line to the top
mov edi, esi
add esi, [textbox_width]
rep movsb
mov ecx, TEXTBOX_LINES - 1
imul ecx, [textbox_width]
mov [text_pos], ecx
.done:
call window_is_updated
popa
ret
draw_channel_text: ; edx = pointer to text
.uh_ow:
pusha
mov edi, [esi + window.text_start]
mov [esi + window.text_print], edi
lea esi, [edi + TEXT_BUFFERSIZE/2]
call text_nextline
mov ecx, TEXT_BUFFERSIZE/8
rep movsd
mov esi, edi
call text_insert_newlines
mov ebx, TEXT_X shl 16 + TEXT_Y
mov ecx, TEXTBOX_LINES
mov ebx, [window_print]
mov [ebx + window.text_lines], edx
mov [ebx + window.text_scanned], esi
mov [ebx + window.text_write], esi
mov [ebx + window.text_line_print], 0
popa
jmp .continue
draw_channel_text:
mov edi, [window_active]
and [edi + window.flags], not FLAG_UPDATED ; clear the 'window is updated' flag
; Scan new text for newlines
mov esi, [edi + window.text_scanned]
call text_insert_newlines
add [edi + window.text_lines], edx
mov [edi + window.text_scanned], esi
; should we scroll up/down some lines ? ; TODO: only scroll down automatically when scrollbar is at lowest position ?
mov edx, [edi + window.text_lines]
sub edx, [textbox_height]
jle .noscroll ; There are less lines of text than fit into the window, dont scroll..
sub edx, [edi + window.text_line_print]
je .noscroll ; We are already at the bottom pos, dont scroll..
.scroll_to_pos: ; edx = number of lines to go up/down (flags must indicate direction)
pushf
add [edi + window.text_line_print], edx
mov esi, [edi + window.text_print]
popf
ja .loop_forward
std ; set direction flag so we can scan backwards
dec esi ; move our cursor just in front of newline, for scanning backwards
dec edx ;;;;; FIXME: this seems to be needed, but why ???
.loop_backward:
call text_nextline
inc edx
jnz .loop_backward
inc esi ; move the cursor just after last newline
cld
jmp .ok
.loop_forward:
call text_nextline
dec edx
jnz .loop_forward
.ok:
mov [edi + window.text_print], esi
.noscroll:
mov edx, [edi + window.text_print]
; Calculate start coordinates (align text to bottom)
mov ebx, [textbox_height]
sub ebx, [edi + window.text_lines]
jae @f
xor ebx, ebx
@@:
imul ebx, FONT_HEIGHT
add ebx, TEXT_X shl 16 + TEXT_Y
; Prepare to actually draw some text
mov eax, [textbox_height] ; max number of lines to draw
mov ecx, [colors.work_text] ; default text color
.drawloop:
cmp byte[edx], 0
je .end
; Clear one row of characters
pusha
mov cx, bx
shl ecx, 16
mov cx, 9 ; character height
mov cx, FONT_HEIGHT
mov ebx, TEXT_X shl 16
mov bx, word[textbox_width]
imul bx, 6 ; character width
imul bx, FONT_WIDTH
mov edx, [colors.work]
mcall 13 ; draw rectangle
popa
push ecx
mov ecx, [colors.work_text]
mov esi, edx
add esi, [textbox_width]
.line:
cmp byte[edx], 0
je .end
cmp byte[edx], 13
je .newline_soft
cmp byte[edx], 10
je .newline_hard
push esi eax
cmp byte[edx], 3 ; escape code for mIRC colors
jne .no_colors
inc edx
call dec_to_esi
jz .no_colors
mov ecx, [irc_colors + 4*esi]
cmp byte[edx], ',' ; background color?
jne .no_colors
inc edx
call dec_to_esi
jz .no_colors
mov edi, [irc_colors + 4*esi]
or ecx, 0x40000000
.no_colors:
.draw:
mov esi, [textbox_width]
mov esi, 1
mcall 4 ; draw text
add edx, [textbox_width]
add ebx, 10 ; height distance between lines
add ebx, FONT_WIDTH shl 16
inc edx
pop eax esi
cmp edx, esi
jb .line
jmp .line_full
pop ecx
loop .drawloop
.newline_hard:
mov ecx, [colors.work_text]
.newline_soft:
inc edx
.line_full:
and ebx, 0x0000ffff
add ebx, TEXT_X shl 16 + FONT_HEIGHT
dec eax
jnz .drawloop
mov eax, [window_active]
and [eax + window.flags], not FLAG_UPDATED ; clear the 'window is updated' flag
; take care of the scrollbar
.scrollbar:
mov edi, [window_active]
mov edx, [edi + window.text_lines]
cmp edx, [textbox_height]
ja .draw_scroll
mov [scroll2.position], 0 ; disable scrollbar
jmp .scroll_done
.draw_scroll:
mov [scroll2.max_area], edx
mov eax, [edi + window.text_line_print]
mov [scroll2.position], eax
push dword scroll2 ; redraw scrollbar
call [scrollbar_draw]
mov [scroll2.all_redraw], 0 ; next time, dont redraw it completely
.scroll_done:
.end:
ret
dec_to_esi:
xor esi, esi
.loop:
movzx eax, byte[edx]
sub al, '0'
jb .done
cmp al, 9
ja .done
inc edx
shl esi, 1 ; esi * 2
lea esi, [esi + 4*esi] ; esi * 5
add esi, eax
jmp .loop
.done:
cmp esi, 16
jae .fail
ret
.fail:
xor esi, esi
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

View File

@ -3,6 +3,7 @@
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
@ -12,6 +13,9 @@
user_parser:
push [window_active] ; print to the current window
pop [window_print]
mov eax, [edit1.size]
test eax, eax
jz sdts_ret ; ignore empty commands
@ -25,13 +29,8 @@ user_parser:
jne sdts_ret
; Ok, we said something, print it to our textbox
; TODO: dont send if it's a server window?
push [window_active] ; print to the current window
pop [window_print]
call window_refresh
if TIMESTAMP
call print_timestamp
end if
@ -57,9 +56,8 @@ user_parser:
call print_character
; and now send it to the server
mov dword[packetbuf], 'priv'
mov dword[packetbuf+4], 'msg '
mov dword[packetbuf], 'PRIV'
mov dword[packetbuf+4], 'MSG '
mov esi, [window_active]
add esi, window.name
@ -82,8 +80,9 @@ user_parser:
inc ecx
call recode
mov al, 10
stosb
; end the command with a CRLF
mov ax, 0x0a0d
stosw
lea esi, [edi - packetbuf]
mcall send, [socketnum], packetbuf, , 0
@ -100,10 +99,13 @@ user_commands:
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.
; All following commands require a connection to the server. TODO: verify connection
dd 'quer', cmd_usr_quer
dd 'quit', cmd_usr_quit
dd 'part', cmd_usr_part
dd 'ctcp', cmd_usr_ctcp
dd 'msg ', cmd_usr_msg
.number = ($ - user_commands) / 8
@ -131,22 +133,94 @@ server_command:
cmd_usr_quit:
cmd_usr_msg:
lea esi, [usercommand+5]
mov dword[packetbuf], 'PRIV'
mov dword[packetbuf+4], 'MSG '
lea edi, [packetbuf+8]
@@:
lodsb
test al, al
jz .fail
cmp al, 10
je .fail
cmp al, 13
je .fail
stosb
cmp al, ' '
jne @r
mov al, ':'
stosb
push edi
@@:
lodsb
test al, al
jz @f
cmp al, 10
je @f
cmp al, 13
je @f
stosb
jmp @r
@@:
; end the command with a CRLF
mov ax, 0x0a0d
stosw
mov byte[edi], 0
lea esi, [edi - packetbuf]
mcall send, [socketnum], packetbuf, , 0
; now print to the window
if TIMESTAMP
call print_timestamp
end if
mov esi, msg_header
call print_text2
mov eax, packetbuf+8
mov dl, ' '
call print_text
mov bl, '*'
call print_character
mov bl, ' '
call print_character
pop esi
call print_text2
.fail:
ret
cmd_usr_quit:
mov esi, quit_msg
cmp byte[usercommand+5], ' '
jne .default_msg
lea esi,[usercommand+6]
.default_msg:
jne .with_message
lea esi, [usercommand+6]
.with_message:
call cmd_usr_quit_server
mcall close, [socketnum]
mov [status], STATUS_DISCONNECTED
mov ecx, MAX_WINDOWS
mov edi, windows
.loop:
mov [edi + window.flags], FLAG_CLOSE
mov [window_print], edi
push edi ecx
call window_close
pop ecx edi
add edi, sizeof.window
dec ecx
jnz .loop
@ -165,11 +239,14 @@ cmd_usr_quit_server:
; Append our quit msg
@@:
lodsb
stosb
cmp al, 13
je @f
test al, al
jnz @r
jz @f
stosb
jmp @r
@@:
; end the command with a CRLF
dec edi
mov ax, 0x0a0d
stosw
@ -184,31 +261,37 @@ cmd_usr_quit_server:
cmd_usr_nick:
cmp [edit1.size], 5
je .justprint
je .dontsend
cmp byte[usercommand+5], ' '
jne cmd_usr_send
jne .fail
cmp [socketnum], 0
je .dontsend
mov dword[usercommand+1], 'NICK'
mov esi, [edit1.size]
mov word[usercommand + esi], 0x0a0d
inc esi
mcall send, [socketnum], usercommand+1, , 0
.fail:
ret
.dontsend:
mov ecx, MAX_NICK_LEN
mov esi, usercommand+6
mov edi, user_nick
.loop:
@@:
lodsb
cmp al, 13
je .done
je @f
stosb
dec ecx
jnz .loop
.done:
jnz @r
@@:
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
@ -299,13 +382,11 @@ cmd_usr_quer:
call window_create
test eax, eax
jz .error
mov [ebx + window.data_ptr], eax
mov [ebx + window.type], WINDOWTYPE_CHAT
mov esi, usercommand+7
call window_set_name
mov [ebx + window.type], WINDOWTYPE_CHAT
mov [ebx + window.flags], 0
.error:
@ -334,17 +415,32 @@ cmd_usr_code:
cmd_usr_part:
cmp byte[usercommand+5], 13 ; parameters given?
jne cmd_usr_send
jne cmd_usr_send ; yes, send command straight to server
mov esi, [window_active] ; window is not a server window?
; close active window
cmd_usr_close_window:
mov esi, [window_active]
mov [window_print], esi
cmp [esi + window.type], WINDOWTYPE_SERVER
je @f
je .not_channel
call window_close ; OK, close currently open (channel/chat/..) window
@@:
lea esi, [esi + window.name]
call cmd_usr_part_channel
call window_close
ret
.not_channel:
cmp [esi + window.type], WINDOWTYPE_CHAT
jne .not_chat
call window_close
.not_chat:
ret
; Send part command to server
; esi must point to channel name (ASCIIZ)
cmd_usr_part_channel:
@ -355,11 +451,16 @@ cmd_usr_part_channel:
lea edi, [packetbuf+5]
@@:
lodsb
stosb
test al, al
jnz @r
jz @f
cmp al, 13
je @f
cmp al, 10
je @f
stosb
jmp @r
@@:
; end the command with a CRLF
dec edi
mov ax, 0x0a0d
stosw
@ -369,6 +470,63 @@ cmd_usr_part_channel:
ret
cmd_usr_ctcp:
cmp byte[usercommand+5], ' '
jne cmd_usr_send
mov esi, usercommand+6
; prepare a 'PRIVMSG '
mov dword[packetbuf], 'PRIV'
mov dword[packetbuf+4], 'MSG '
lea edi, [packetbuf+8]
; append the destination (nickname/channel)
@@:
lodsb
test al, al
jz .fail
cmp al, ' '
je @f
stosb
jmp @r
@@:
mov ax, ' :'
stosw
mov al, 0x01
stosb
; copy the message itself
@@:
lodsb
test al, al
jz @f
cmp al, 13
je @f
cmp al, 10
je @f
stosb
jmp @r
@@:
; end of message
mov al, 0x01
stosb
mov ax, 0x0a0d
stosw
; now send it away
lea esi, [edi - packetbuf] ; calculate length
mcall send, [socketnum], packetbuf, , 0 ; and finally send to server
;; TODO: print to window
.fail:
ret
; The user typed some undefined command, just recode it and send to the server
cmd_usr_send:
@ -383,3 +541,7 @@ cmd_usr_send:
ret

View File

@ -3,12 +3,17 @@
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; TODO: work correctly with user prefixes.
; use first byte of nick for prefix ONLY (use a space for those that do not have special powers..)
user_prefixes db '~&@%+ ', 0 ; in descending order
; esi is ptr to nick
; ebx is ptr to window
@ -78,8 +83,7 @@ user_add:
; mov all trailing usernames by MAX_NICK_LEN bytes
push esi edi
mov esi, [ebx + window.data_ptr]
add esi, window_data.names + MAX_NICK_LEN * (MAX_USERS - 1)
add esi, window_data.names + MAX_NICK_LEN * (MAX_USERS - 1) - 4 ; -4 because we're copying backward, dword wise
mov ecx, esi
sub ecx, edi
add ecx, MAX_NICK_LEN
@ -98,6 +102,10 @@ user_add:
je .done
cmp al, '!'
je .done
cmp al, 13
je .done
cmp al, 10
je .done
stosb
loop .fill
.done:
@ -105,6 +113,7 @@ user_add:
stosb
inc [ebx + window.users]
or [ebx + window.flags], FLAG_UPDATED
ret
@ -128,7 +137,7 @@ user_remove:
rep movsd
dec [ebx + window.users]
xor eax, eax
or [ebx + window.flags], FLAG_UPDATED
ret

View File

@ -3,6 +3,7 @@
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
@ -10,11 +11,15 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; in: window ptr in ebx
; out: eax = 0 on error
window_create:
push ebx
; allocate the window data block
mcall 68, 12, sizeof.window_data
test eax, eax
pop ebx
jz .fail
; fill it with all zeros
@ -25,6 +30,19 @@ window_create:
rep stosd
pop eax
mov [ebx + window.data_ptr], eax
mov [ebx + window.flags], 0
add eax, window_data.text+1 ; let text begin at offset 1, this way the text will be prepended with a 0
mov [ebx + window.text_start], eax
mov [ebx + window.text_print], eax
mov [ebx + window.text_write], eax
mov [ebx + window.text_scanned], eax
mov [ebx + window.text_lines], 0
mov [ebx + window.text_line_print], 0
add eax, TEXT_BUFFERSIZE-1
mov [ebx + window.text_end], eax
.fail:
ret
@ -63,32 +81,16 @@ window_set_name: ; esi = ptr to name, ebx = window ptr
window_refresh:
; set text write cursor to beginning of last line
mov eax, [textbox_width]
imul eax, TEXTBOX_LINES - 1
mov [text_pos], eax
; set the textbuffer pointer
mov eax, [window_print]
mov eax, [eax + window.data_ptr]
add eax, window_data.text
mov [text_start], eax
ret
window_is_updated:
mov edi, [window_print]
cmp edi, [window_active]
je .skip
test [edi + window.flags], FLAG_UPDATED
jnz .skip
or [edi + window.flags], FLAG_UPDATED
; now play a sound :)
; TODO: make some noise
call draw_windowtabs ; highlight updated tabs
.skip:
@ -97,19 +99,10 @@ window_is_updated:
window_close:
; If current window is a channel, send part command to server
mov esi, [window_active]
cmp [esi + window.type], WINDOWTYPE_CHANNEL
jne .not_channel
lea esi, [esi + window.name]
call cmd_usr_part_channel
.not_channel:
window_close: ; closes the 'print' window
; Remove the window (overwrite current structure with trailing ones)
mov edi, [window_active]
mov edi, [window_print]
push [edi + window.data_ptr] ; remember data ptr so we can free it later
lea esi, [edi + sizeof.window]
mov ecx, windows + MAX_WINDOWS*sizeof.window
@ -131,7 +124,7 @@ window_close:
jne @f
sub edi, sizeof.window
mov [window_active], edi
mov [window_print], edi
mov [window_print], edi ;;;;;;;;
@@:
; At last, redraw everything
@ -141,6 +134,46 @@ window_close:
window_find: ; esi = window name
; search for window in list
mov ebx, windows
mov [window_print], ebx ; set first window (server window) as default output window
mov eax, MAX_WINDOWS
.scanloop:
push esi
cmp [ebx + window.type], WINDOWTYPE_NONE
je .try_next
lea edi, [ebx + window.name]
mov ecx, MAX_WINDOWNAME_LEN
repe cmpsb
cmp byte[edi-1], 0
jne .try_next
cmp byte[esi-1], 0
je .got_it
cmp byte[esi-1], 10
je .got_it
cmp byte[esi-1], 13
je .got_it
cmp byte[esi-1], ' '
je .got_it
.try_next:
pop esi
add ebx, sizeof.window
dec eax
jnz .scanloop
xor ebx, ebx
ret
.got_it:
pop esi ;;; TODO: dont reset ESI ?
mov [window_print], ebx
ret
; open a window with a given name, if it does not exist, create it
; This procedure only affects window_print ptr, not window_active!
@ -157,22 +190,9 @@ window_open:
mov esi, servercommand+1
.nochat:
; now search for window in list
mov ebx, windows
mov [window_print], ebx ; set first window (server window) as default output window
.scanloop:
cmp [ebx + window.data_ptr], 0
je .create_it
push esi
lea edi, [ebx + window.name]
mov ecx, MAX_WINDOWNAME_LEN
repe cmpsb
pop esi
cmp byte[edi-1], 0
je .got_it
add ebx, sizeof.window
; TODO: check buffer limits ?
jmp .scanloop
call window_find
test ebx, ebx
jne .got_it
; create channel window - search for empty slot
.create_it:
@ -185,31 +205,20 @@ window_open:
dec ecx
jnz .scanloop2
; Error: no more available windows!
jmp .just_skip
jmp .got_it ; TODO: return error
.free_found:
push ebx
call window_create
pop ebx
test eax, eax
jz .just_skip
mov [ebx + window.data_ptr], eax
mov [ebx + window.type], WINDOWTYPE_CHAT
mov [ebx + window.flags], 0
jz .got_it ; TODO: return error
mov [ebx + window.type], WINDOWTYPE_CHAT ; FIXME: let caller handle this ?
call window_set_name
mov [window_print], ebx
call window_refresh
call draw_windowtabs
jmp .just_skip
; found it!
.got_it:
mov [window_print], ebx
call window_refresh
.just_skip:
pop esi
.skip1:
; skip text
@ -232,42 +241,3 @@ window_open:
.quit:
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