diff --git a/programs/network/ircc/encodings.inc b/programs/network/ircc/encodings.inc index 220ef9ec2a..fe910aec0e 100644 --- a/programs/network/ircc/encodings.inc +++ b/programs/network/ircc/encodings.inc @@ -220,8 +220,7 @@ print_character: mov [pos], eax newdata: - mov eax, [window_print] - or [eax + window.flags], FLAG_UPDATED + call window_is_updated popa ret diff --git a/programs/network/ircc/gui.inc b/programs/network/ircc/gui.inc index ffad315fe3..b64d377a06 100644 --- a/programs/network/ircc/gui.inc +++ b/programs/network/ircc/gui.inc @@ -1,3 +1,15 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;; ;; +;; GNU GENERAL PUBLIC LICENSE ;; +;; Version 2, June 1991 ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + draw_window: pusha @@ -47,7 +59,7 @@ draw_window: mov ecx, TOP_Y SHL 16 + TOP_Y mcall - mov edi, [window_open] + mov edi, [window_active] cmp [edi + window.type], WINDOWTYPE_CHANNEL jne .not_channel @@ -81,8 +93,7 @@ draw_window: call [edit_box_draw] ; tabs - - call draw_windownames + call draw_windowtabs popa ret @@ -93,7 +104,7 @@ redraw_channel_list: ; First, calculate scrollbar - mov ebx, [window_open] + mov ebx, [window_active] mov eax, [ebx + window.users] ; number of users in the open window mov [scroll1.max_area], eax @@ -138,7 +149,6 @@ redraw_channel_list: print_channel_list: pusha -; Now, draw the usernames themselves ; first, draw an invisible button mov ebx, [xsize] @@ -149,21 +159,21 @@ print_channel_list: mov ecx, [ysize] add ecx, TEXT_Y shl 16 - (TEXT_Y + 15) ;;;;; + 10??? push ecx ebx - mov edx, 50 + 1 shl 29 + 1 shl 30 + mov edx, WINDOW_BTN_LIST + 1 shl 29 + 1 shl 30 mcall 8 -; now draw rectangle to clear the names +; draw rectangle to clear previously printed names pop ebx ecx mov edx, [colors.work] mcall 13 -; now draw the names according with 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 mul ecx mov edx, eax - mov eax, [window_open] + mov eax, [window_active] mov ebp, [eax + window.selected] add edx, [eax + window.data_ptr] sub ebp, [scroll1.position] @@ -269,12 +279,17 @@ draw_channel_text: pop ecx loop .dct + mov eax, [window_active] + and [eax + window.flags], not FLAG_UPDATED ; clear the 'window is updated' flag + popa ret -draw_windownames: +draw_windowtabs: + +; Create the buttons mov eax, 8 mov ebx, 5 shl 16 + 120 @@ -283,7 +298,7 @@ draw_windownames: mov edi, windows .more_btn: mov esi, [colors.work_button] - cmp [window_open], edi + cmp [window_active], edi jne @f not esi and esi, 0x00ffffff @@ -295,22 +310,48 @@ draw_windownames: cmp [edi + window.data_ptr], 0 jne .more_btn +; Draw the windownames onto the buttons + mov eax, 4 mov ebx, 10 shl 16 + 15 - mov ecx, [colors.work_button_text] - or ecx, 0x80000000 ; ASCIIZ string - lea edx, [windows + window.name] mov esi, MAX_WINDOWS + mov edi, windows .more: + mov ecx, [colors.work_button_text] + test [edi + window.flags], FLAG_UPDATED + jz @f + mov ecx, 0x00aa0000 ; RED! + @@: + or ecx, 0x80000000 ; ASCIIZ string + lea edx, [edi + window.name] mcall - add edx, sizeof.window - cmp byte[edx], 0 + add edi, sizeof.window ; get ptr to next window + cmp [edi + window.data_ptr], 0 je .enough add ebx, 125 shl 16 dec esi jnz .more .enough: +; Draw the close window button + + mov edi, [window_active] + cmp [edi + window.type], WINDOWTYPE_SERVER ; dont let the user close server window + je @f + + mov eax, 8 + mov ebx, [xsize] + sub ebx, 12 + shl ebx, 16 + mov bx, 12 + mov ecx, 6 shl 16 + 12 + mov edx, WINDOW_BTN_CLOSE +; mov esi, [colors.work_button] + mov esi, 0x00aa0000 ; red ! + mcall + + @@: + ret diff --git a/programs/network/ircc/ircc.asm b/programs/network/ircc/ircc.asm index a0880b352f..daf70e944c 100644 --- a/programs/network/ircc/ircc.asm +++ b/programs/network/ircc/ircc.asm @@ -66,6 +66,8 @@ TIMESTAMP = 3 ; 3 = hh:mm:ss, 2 = hh:mm, 0 = no timestamp MAX_WINDOWNAME_LEN = 256 WINDOW_BTN_START = 100 +WINDOW_BTN_CLOSE = 2 +WINDOW_BTN_LIST = 3 SCROLLBAR_WIDTH = 12 @@ -126,7 +128,7 @@ START: mcall 68, 11 ; init heap so we can allocate memory dynamically ; wanted events - mcall 40,EVM_REDRAW+EVM_KEY+EVM_BUTTON+EVM_STACK+EVM_MOUSE+EVM_MOUSE_FILTER + mcall 40, EVM_REDRAW+EVM_KEY+EVM_BUTTON+EVM_STACK+EVM_MOUSE+EVM_MOUSE_FILTER ; load libraries stdcall dll.Load, @IMPORT @@ -182,12 +184,13 @@ START: ; get settings from ini invoke ini.get_str, path, str_user, str_nick, user_nick, MAX_NICK_LEN, default_nick invoke ini.get_str, path, str_user, str_real, user_real_name, MAX_REAL_LEN, default_real + invoke ini.get_str, path, str_user, str_quitmsg, quit_msg, 250, default_quit ; Welcome user mov esi, str_welcome call print_text2 - call draw_window ;;; FIXME (gui is not correctly drawn first time) + call draw_window ;;; FIXME (gui is not correctly drawn first time because of window sizes) redraw: call draw_window @@ -211,7 +214,7 @@ still: call process_network_event - mov edx, [window_open] + mov edx, [window_active] test [edx + window.flags], FLAG_UPDATED jz .no_update and [edx + window.flags], not FLAG_UPDATED @@ -226,14 +229,23 @@ still: button: mcall 17 ; get id - shr eax, 8 + ror eax, 8 cmp ax, 1 ; close program je exit - cmp ax, 50 + cmp ax, WINDOW_BTN_CLOSE jne @f + call window_close + jmp still + + @@: + cmp ax, WINDOW_BTN_LIST + jne @f + + push eax + mcall 37, 1 ; Get mouse position sub ax, TEXT_Y mov bl, 10 @@ -241,11 +253,27 @@ button: and eax, 0x000000ff inc eax add eax, [scroll1.position] - mov ebx, [window_open] + mov ebx, [window_active] mov [ebx + window.selected], eax call print_channel_list + pop eax + test eax, 1 shl 25 ; Right mouse button pressed? + jz still + +; Right mouse BTN was pressed, open chat window + mov ebx, [window_active] + mov eax, [ebx + window.selected] + dec eax + imul eax, MAX_NICK_LEN + mov ebx, [ebx + window.data_ptr] + lea esi, [ebx + window_data.names + eax] + call window_open + push [window_print] + pop [window_active] + call redraw + jmp still @@: @@ -262,12 +290,20 @@ button: add edx, windows cmp [edx + window.data_ptr], 0 je exit - mov [window_open], edx + mov [window_active], edx call window_refresh call draw_window jmp still + exit: + + cmp [socketnum], 0 + je @f + mov esi, quit_msg + call cmd_usr_quit_server + @@: + mcall -1 @@ -290,7 +326,7 @@ main_window_key: push dword edit1 call [edit_box_draw] - mov edx, [window_open] + mov edx, [window_active] mov edx, [edx + window.data_ptr] add edx, window_data.text call draw_channel_text @@ -348,9 +384,11 @@ str_user db 'user', 0 str_nick db 'nick', 0 str_real db 'realname', 0 str_email db 'email', 0 +str_quitmsg db 'quitmsg', 0 default_nick db 'kolibri_user', 0 default_real db 'Kolibri User', 0 +default_quit db 'KolibriOS forever', 0 str_welcome db 10 db ' ______________________ __ __ __',10 @@ -397,7 +435,7 @@ irc_data dd 0x0 ; encoder textbox_width dd 80 ; in characters, not pixels ;) pos dd 66 * 11 ; encoder -window_open dd windows +window_active dd windows window_print dd windows scroll dd 1 @@ -460,6 +498,7 @@ irc_server_name rb MAX_SERVER_NAME user_nick rb MAX_NICK_LEN user_real_name rb MAX_REAL_LEN +quit_msg rb 250 windows rb MAX_WINDOWS*sizeof.window diff --git a/programs/network/ircc/ircc.ini b/programs/network/ircc/ircc.ini index 6232627005..3f082f148b 100644 --- a/programs/network/ircc/ircc.ini +++ b/programs/network/ircc/ircc.ini @@ -1,6 +1,7 @@ [user] nick = kolibri_user realname = tetten +partmsg = KolibriOS forever [colors] action1 = 0x000000aa diff --git a/programs/network/ircc/serverparser.inc b/programs/network/ircc/serverparser.inc index cdde091532..8355e292a7 100644 --- a/programs/network/ircc/serverparser.inc +++ b/programs/network/ircc/serverparser.inc @@ -134,100 +134,6 @@ skip_nick: ret -align 4 -find_window: ; esi is ptr to windowname - - push esi - - mov edi, esi - call compare_to_nick - jne .nochat - - 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 - -; create channel window - search for empty slot - .create_it: - mov ebx, windows - mov ecx, MAX_WINDOWS - .scanloop2: - cmp [ebx + window.data_ptr], 0 - je .free_found - add ebx, sizeof.window - dec ecx - jnz .scanloop2 -; Error: no more available windows! - jmp .just_skip - - .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 - - call window_set_name - - mov [window_open], ebx - mov [window_print], ebx - call window_refresh - - call draw_windownames - jmp .just_skip - -; found it! - .got_it: - mov [window_print], ebx - call window_refresh - - .just_skip: - pop esi - .skip1: -; skip text - lodsb - test al, al - jz .quit - cmp al, ' ' - jne .skip1 - dec esi -; now skip trailing spaces and semicolons - .skip2: - lodsb - test al, al - jz .quit - cmp al, ' ' - je .skip2 - cmp al, ':' - je .skip2 - dec esi - - .quit: - ret - - - - - cmd_328: cmd_421: @@ -307,7 +213,7 @@ cmd_ping: cmd_privmsg: add esi, 8 ; skip 'PRIVMSG ' - call find_window ; esi now points to end of destination name + call window_open ; esi now points to end of destination name cmp byte[esi], 1 je cmd_ctcp @@ -368,6 +274,8 @@ end if ret + + cmd_ctcp: inc esi @@ -520,7 +428,7 @@ cmd_part: add esi, 5 ; skip 'PART ' push esi call skip_nick - call find_window + call window_open pop esi ; Is it me who parted? @@ -595,7 +503,7 @@ cmd_join: call window_set_name - mov [window_open], ebx + mov [window_active], ebx mov [window_print], ebx call window_refresh @@ -619,7 +527,7 @@ cmd_join: .no_new_window: push esi - call find_window + call window_open mov esi, action_header call print_text2 @@ -726,7 +634,7 @@ cmd_kick: ; find the channel user has been kicked from push esi call skip_nick - call find_window + call window_open mov esi, action_header_short call print_text2 @@ -806,7 +714,7 @@ cmd_353: ; channel usernames reply call skip_nick inc esi ; channel type '*', '=' or '@' inc esi ; ' ' - call find_window + call window_open ; now find window ptr and check if this is the first 353 message mov ebx, [window_print] @@ -843,7 +751,7 @@ cmd_366: ; channel usernames end add esi, 4 ; skip '366 ' call skip_nick - call find_window + call window_open mov ebx, [window_print] and [ebx + window.flags], not FLAG_RECEIVING_NAMES @@ -857,7 +765,7 @@ cmd_topic: add esi, 4 ; skip '332 ' call skip_nick - call find_window + call window_open push esi mov esi, action_header @@ -879,7 +787,7 @@ cmd_333: add esi, 4 ; skip '333 ' call skip_nick ;;;; - call find_window + call window_open ; mov ecx, 2 ; number of spaces to find ;;; CHECKME ; .loop: diff --git a/programs/network/ircc/socket.inc b/programs/network/ircc/socket.inc index 7b771d9f4a..2a23b2ea17 100644 --- a/programs/network/ircc/socket.inc +++ b/programs/network/ircc/socket.inc @@ -111,7 +111,7 @@ socket_write_userinfo: dec ecx jnz .loop .done: - mov ax, 0x0d0a + mov ax, 0x0a0d stosw mov eax, 'USER' @@ -144,7 +144,7 @@ socket_write_userinfo: dec ecx jnz .loop3 .done3: - mov ax, 0x0d0a + mov ax, 0x0a0d stosw lea esi, [edi - packetbuf] diff --git a/programs/network/ircc/userparser.inc b/programs/network/ircc/userparser.inc index e106c87ff5..f93fc719c7 100644 --- a/programs/network/ircc/userparser.inc +++ b/programs/network/ircc/userparser.inc @@ -28,7 +28,7 @@ user_parser: ; TODO: dont send if it's a server window? - push [window_open] ; print to the current window + push [window_active] ; print to the current window pop [window_print] call window_refresh @@ -42,9 +42,9 @@ user_parser: mov esi, user_nick call print_text2 - mov bl,'>' + mov bl, '>' call print_character - mov bl,' ' + mov bl, ' ' call print_character mov eax, [edit1.size] @@ -61,7 +61,7 @@ user_parser: mov dword[packetbuf], 'priv' mov dword[packetbuf+4], 'msg ' - mov esi, [window_open] + mov esi, [window_active] add esi, window.name mov edi, packetbuf+8 mov ecx, MAX_WINDOWNAME_LEN @@ -103,6 +103,7 @@ user_commands: ; TODO: All other commands require a connection to the server. dd 'quer', cmd_usr_quer dd 'quit', cmd_usr_quit + dd 'part', cmd_usr_part .number = ($ - user_commands) / 8 @@ -132,14 +133,13 @@ server_command: cmd_usr_quit: - cmp [edit1.size], 5 - je .ok - jb cmd_usr_send - cmp byte[usercommand+5], ' ' - jne cmd_usr_send + mov esi, quit_msg - .ok: - call cmd_usr_send + cmp byte[usercommand+5], ' ' + jne .default_msg + lea esi,[usercommand+6] + .default_msg: + call cmd_usr_quit_server mcall close, [socketnum] @@ -155,6 +155,31 @@ cmd_usr_quit: +; esi = quit message +cmd_usr_quit_server: + +; User wants to close a channel, send PART command to server + mov dword[packetbuf], 'QUIT' + mov word[packetbuf+4], ' :' + lea edi, [packetbuf+6] +; Append our quit msg + @@: + lodsb + stosb + test al, al + jnz @r +; end the command with a CRLF + dec edi + mov ax, 0x0a0d + stosw + + lea esi, [edi - packetbuf] ; calculate length + mcall send, [socketnum], packetbuf, , 0 ; and finally send to server + + ret + + + cmd_usr_nick: @@ -305,6 +330,46 @@ cmd_usr_code: +; User typed a part command +cmd_usr_part: + + cmp byte[usercommand+5], 13 ; parameters given? + jne cmd_usr_send + + mov esi, [window_active] ; window is not a server window? + cmp [esi + window.type], WINDOWTYPE_SERVER + je @f + + call window_close ; OK, close currently open (channel/chat/..) window + @@: + + ret + +; Send part command to server +; esi must point to channel name (ASCIIZ) +cmd_usr_part_channel: + +; User wants to close a channel, send PART command to server + mov dword[packetbuf], 'PART' + mov byte[packetbuf+4], ' ' + lea edi, [packetbuf+5] + @@: + lodsb + stosb + test al, al + jnz @r +; end the command with a CRLF + dec edi + mov ax, 0x0a0d + stosw + + lea esi, [edi - packetbuf] ; calculate length + mcall send, [socketnum], packetbuf, , 0 ; and finally send to server + + ret + + +; The user typed some undefined command, just recode it and send to the server cmd_usr_send: mov esi, usercommand+1 diff --git a/programs/network/ircc/users.inc b/programs/network/ircc/users.inc index f84a67111d..4e96ea7afe 100644 --- a/programs/network/ircc/users.inc +++ b/programs/network/ircc/users.inc @@ -1,3 +1,13 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;; ;; +;; GNU GENERAL PUBLIC LICENSE ;; +;; Version 2, June 1991 ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; esi is ptr to nick diff --git a/programs/network/ircc/window.inc b/programs/network/ircc/window.inc index 5065b60cef..8724a696b0 100644 --- a/programs/network/ircc/window.inc +++ b/programs/network/ircc/window.inc @@ -55,7 +55,7 @@ window_set_name: ; esi = ptr to name, ebx = window ptr xor al, al stosb - call draw_windownames ; redraw it + call draw_windowtabs ; redraw it popa @@ -78,7 +78,8 @@ window_refresh: ret -window_updated: + +window_is_updated: mov edi, [window_print] test [edi + window.flags], FLAG_UPDATED @@ -88,11 +89,150 @@ window_updated: ; now play a sound :) + call draw_windowtabs ; highlight updated tabs .skip: ret + +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: + +; Remove the window (overwrite current structure with trailing ones) + mov edi, [window_active] + 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 + sub ecx, esi + rep movsb + +; Completely zero the trailing window block (there will always be one!) + mov ecx, sizeof.window + xor al, al + rep stosb + +; free the window data block + pop ecx + mcall 68, 13 + +; We closed this window so we need to show another + mov edi, [window_active] + cmp [edi + window.data_ptr], 0 + jne @f + sub edi, sizeof.window + mov [window_active], edi + mov [window_print], edi + @@: + +; At last, redraw everything + call draw_window + + 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! +; +; esi = ptr to ASCIIZ windowname +window_open: + + push esi + + mov edi, esi + call compare_to_nick + jne .nochat + + 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 + +; create channel window - search for empty slot + .create_it: + mov ebx, windows + mov ecx, MAX_WINDOWS + .scanloop2: + cmp [ebx + window.data_ptr], 0 + je .free_found + add ebx, sizeof.window + dec ecx + jnz .scanloop2 +; Error: no more available windows! + jmp .just_skip + + .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 + + 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 + lodsb + test al, al + jz .quit + cmp al, ' ' + jne .skip1 + dec esi +; now skip trailing spaces and semicolons + .skip2: + lodsb + test al, al + jz .quit + cmp al, ' ' + je .skip2 + cmp al, ':' + je .skip2 + dec esi + + .quit: + ret + + print_text: ; eax = start ptr ; dl = end char pusha