From 8ad9d9edd3ee668ff738e32237654d8ec910757a Mon Sep 17 00:00:00 2001 From: hidnplayr Date: Fri, 1 Nov 2013 14:02:08 +0000 Subject: [PATCH] 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 --- programs/network/ircc/encodings.inc | 1 + programs/network/ircc/gui.inc | 147 ++++++----- programs/network/ircc/ircc.asm | 210 ++++++++++----- programs/network/ircc/serverparser.inc | 351 +++++++++++++++++-------- programs/network/ircc/socket.inc | 49 ++-- programs/network/ircc/textbox.inc | 334 +++++++++++++++++++---- programs/network/ircc/userparser.inc | 254 ++++++++++++++---- programs/network/ircc/users.inc | 17 +- programs/network/ircc/window.inc | 172 +++++------- 9 files changed, 1079 insertions(+), 456 deletions(-) diff --git a/programs/network/ircc/encodings.inc b/programs/network/ircc/encodings.inc index f902ae05f1..3f44f3d3d9 100644 --- a/programs/network/ircc/encodings.inc +++ b/programs/network/ircc/encodings.inc @@ -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 ;; diff --git a/programs/network/ircc/gui.inc b/programs/network/ircc/gui.inc index 9c3166699f..2a9405b008 100644 --- a/programs/network/ircc/gui.inc +++ b/programs/network/ircc/gui.inc @@ -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 diff --git a/programs/network/ircc/ircc.asm b/programs/network/ircc/ircc.asm index e2060e8f78..ff6c25aa80 100644 --- a/programs/network/ircc/ircc.asm +++ b/programs/network/ircc/ircc.asm @@ -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 : change nickname to ',10 @@ -414,13 +464,30 @@ str_help db 10,'following commands are available:',10 db '/server
: connect to server
',10 db '/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 diff --git a/programs/network/ircc/serverparser.inc b/programs/network/ircc/serverparser.inc index d30e481efc..c902eb324a 100644 --- a/programs/network/ircc/serverparser.inc +++ b/programs/network/ircc/serverparser.inc @@ -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 ' 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 \ No newline at end of file diff --git a/programs/network/ircc/socket.inc b/programs/network/ircc/socket.inc index 2a23b2ea17..4429751a8a 100644 --- a/programs/network/ircc/socket.inc +++ b/programs/network/ircc/socket.inc @@ -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 diff --git a/programs/network/ircc/textbox.inc b/programs/network/ircc/textbox.inc index eb4d8544df..8f7f773851 100644 --- a/programs/network/ircc/textbox.inc +++ b/programs/network/ircc/textbox.inc @@ -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 \ No newline at end of file diff --git a/programs/network/ircc/userparser.inc b/programs/network/ircc/userparser.inc index f93fc719c7..2ce08ebe10 100644 --- a/programs/network/ircc/userparser.inc +++ b/programs/network/ircc/userparser.inc @@ -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,16 +29,11 @@ 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 + if TIMESTAMP call print_timestamp - end if + end if mov bl, '<' call print_character @@ -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: @@ -333,18 +414,33 @@ cmd_usr_code: ; User typed a part command cmd_usr_part: - cmp byte[usercommand+5], 13 ; parameters given? - jne cmd_usr_send + cmp byte[usercommand+5], 13 ; parameters given? + 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 + + + + diff --git a/programs/network/ircc/users.inc b/programs/network/ircc/users.inc index 4e96ea7afe..67724b9c45 100644 --- a/programs/network/ircc/users.inc +++ b/programs/network/ircc/users.inc @@ -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 @@ -21,7 +26,7 @@ user_add: mov edi, [ebx + window.data_ptr] add edi, window_data.names mov ebp, [ebx + window.users] - inc ebp ; CHECKME + inc ebp ; CHECKME push esi edi .restart: @@ -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 diff --git a/programs/network/ircc/window.inc b/programs/network/ircc/window.inc index 49c4cfb8ea..b7f10fb102 100644 --- a/programs/network/ircc/window.inc +++ b/programs/network/ircc/window.inc @@ -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 @@ -231,43 +240,4 @@ window_open: dec esi .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 \ No newline at end of file + ret \ No newline at end of file