/////////////////////////////////////////////////////////////////////////////// //Telnet Win32 : an ANSI telnet client. //Copyright (C) 1998 Paul Brannan //Copyright (C) 1998 I.Ioannou //Copyright (C) 1997 Brad Johnson // //This program is free software; you can redistribute it and/or //modify it under the terms of the GNU General Public License //as published by the Free Software Foundation; either version 2 //of the License, or (at your option) any later version. // //This program is distributed in the hope that it will be useful, //but WITHOUT ANY WARRANTY; without even the implied warranty of //MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //GNU General Public License for more details. // //You should have received a copy of the GNU General Public License //along with this program; if not, write to the Free Software //Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // //I.Ioannou //roryt@hol.gr // /////////////////////////////////////////////////////////////////////////// // TMouse.cpp // A simple class for handling mouse events // Written by Paul Brannan // Last modified August 30, 1998 #include "precomp.h" TMouse::TMouse(Tnclip &RefClipboard): Clipboard(RefClipboard) { hConsole = GetStdHandle(STD_INPUT_HANDLE); hStdout = GetStdHandle(STD_OUTPUT_HANDLE); } TMouse::~TMouse() { } void TMouse::get_coords(COORD *start_coords, COORD *end_coords, COORD *first_coords, COORD *last_coords) { if(end_coords->Y < start_coords->Y || (end_coords->Y == start_coords->Y && end_coords->X < start_coords->X)) { *first_coords = *end_coords; *last_coords = *start_coords; } else { *first_coords = *start_coords; *last_coords = *end_coords; } last_coords->X++; } void TMouse::doMouse_init() { GetConsoleScreenBufferInfo(hStdout, &ConsoleInfo); chiBuffer = newBuffer(); saveScreen(chiBuffer); } void TMouse::doMouse_cleanup() { restoreScreen(chiBuffer); delete[] chiBuffer; } void TMouse::move_mouse(COORD start_coords, COORD end_coords) { COORD screen_start = {0, 0}; COORD first_coords, last_coords; DWORD Result; FillConsoleOutputAttribute(hStdout, normal, ConsoleInfo.dwSize.X * ConsoleInfo.dwSize.Y, screen_start, &Result); get_coords(&start_coords, &end_coords, &first_coords, &last_coords); FillConsoleOutputAttribute(hStdout, inverse, ConsoleInfo.dwSize.X * (last_coords.Y - first_coords.Y) + (last_coords.X - first_coords.X), first_coords, &Result); } void TMouse::doClip(COORD start_coords, COORD end_coords) { // COORD screen_start = {0, 0}; COORD first_coords, last_coords; DWORD Result; get_coords(&start_coords, &end_coords, &first_coords, &last_coords); // Allocate the minimal size buffer int data_size = 3 + ConsoleInfo.dwSize.X * (last_coords.Y - first_coords.Y) + (last_coords.X - first_coords.X); HGLOBAL clipboard_data = GlobalAlloc(GMEM_MOVEABLE + GMEM_DDESHARE, data_size); LPVOID mem_ptr = GlobalLock(clipboard_data); // Reset data_size so we can count the actual data size data_size = 0; // Read the console, put carriage returns at the end of each line if // reading more than one line (Paul Brannan 9/17/98) for(int j = first_coords.Y; j <= last_coords.Y; j++) { // Read line at (0,j) COORD coords; coords.X = 0; coords.Y = j; int length = ConsoleInfo.dwSize.X; if(j == first_coords.Y) { coords.X = first_coords.X; length = ConsoleInfo.dwSize.X - first_coords.X; } else { // Add a carriage return to the end of the previous line *((char *)mem_ptr + data_size++) = '\r'; *((char *)mem_ptr + data_size++) = '\n'; } if(j == last_coords.Y) { length -= (ConsoleInfo.dwSize.X - last_coords.X); } // Read the next line ReadConsoleOutputCharacter(hStdout, (LPTSTR)((char *)mem_ptr + data_size), length, coords, &Result); data_size += Result; // Strip the spaces at the end of the line if((j != last_coords.Y) && (first_coords.Y != last_coords.Y)) while(*((char *)mem_ptr + data_size - 1) == ' ') data_size--; } if(first_coords.Y != last_coords.Y) { // Add a carriage return to the end of the last line *((char *)mem_ptr + data_size++) = '\r'; *((char *)mem_ptr + data_size++) = '\n'; } *((char *)mem_ptr + data_size) = 0; GlobalUnlock(clipboard_data); Clipboard.Copy(clipboard_data); } void TMouse::doMouse() { INPUT_RECORD InputRecord; DWORD Result; InputRecord.EventType = KEY_EVENT; // just in case while(InputRecord.EventType != MOUSE_EVENT) { if (!ReadConsoleInput(hConsole, &InputRecord, 1, &Result)) return; // uh oh! we don't know the starting coordinates! } if(InputRecord.Event.MouseEvent.dwButtonState == 0) return; if(!(InputRecord.Event.MouseEvent.dwButtonState & FROM_LEFT_1ST_BUTTON_PRESSED)) { Clipboard.Paste(); return; } COORD screen_start = {0, 0}; COORD start_coords = InputRecord.Event.MouseEvent.dwMousePosition; COORD end_coords = start_coords; BOOL done = FALSE; // init vars doMouse_init(); int normal_bg = ini.get_normal_bg(); int normal_fg = ini.get_normal_fg(); if(normal_bg == -1) normal_bg = 0; // FIX ME!! This is just a hack if(normal_fg == -1) normal_fg = 7; normal = (normal_bg << 4) | normal_fg; inverse = (normal_fg << 4) | normal_bg; // make screen all one attribute FillConsoleOutputAttribute(hStdout, normal, ConsoleInfo.dwSize.X * ConsoleInfo.dwSize.Y, screen_start, &Result); while(!done) { switch (InputRecord.EventType) { case MOUSE_EVENT: switch(InputRecord.Event.MouseEvent.dwEventFlags) { case 0: // only copy if the mouse button has been released if(!InputRecord.Event.MouseEvent.dwButtonState) { doClip(start_coords, end_coords); done = TRUE; } break; case MOUSE_MOVED: end_coords = InputRecord.Event.MouseEvent.dwMousePosition; move_mouse(start_coords, end_coords); break; } break; // If we are changing focus, we don't want to highlight anything // (Paul Brannan 9/2/98) case FOCUS_EVENT: return; } WaitForSingleObject(hConsole, INFINITE); if (!ReadConsoleInput(hConsole, &InputRecord, 1, &Result)) done = TRUE; } doMouse_cleanup(); } void TMouse::scrollMouse() { doMouse(); }