1 /////////////////////////////////////////////////////////////////////////////// 2 //Telnet Win32 : an ANSI telnet client. 3 //Copyright (C) 1998 Paul Brannan 4 //Copyright (C) 1998 I.Ioannou 5 //Copyright (C) 1997 Brad Johnson 6 // 7 //This program is free software; you can redistribute it and/or 8 //modify it under the terms of the GNU General Public License 9 //as published by the Free Software Foundation; either version 2 10 //of the License, or (at your option) any later version. 11 // 12 //This program is distributed in the hope that it will be useful, 13 //but WITHOUT ANY WARRANTY; without even the implied warranty of 14 //MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 //GNU General Public License for more details. 16 // 17 //You should have received a copy of the GNU General Public License 18 //along with this program; if not, write to the Free Software 19 //Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 // 21 //I.Ioannou 22 //roryt@hol.gr 23 // 24 /////////////////////////////////////////////////////////////////////////// 25 26 // TMouse.cpp 27 // A simple class for handling mouse events 28 // Written by Paul Brannan <pbranna@clemson.edu> 29 // Last modified August 30, 1998 30 31 #include "precomp.h" 32 33 TMouse::TMouse(Tnclip &RefClipboard): Clipboard(RefClipboard) { 34 hConsole = GetStdHandle(STD_INPUT_HANDLE); 35 hStdout = GetStdHandle(STD_OUTPUT_HANDLE); 36 } 37 38 TMouse::~TMouse() { 39 } 40 41 void TMouse::get_coords(COORD *start_coords, COORD *end_coords, 42 COORD *first_coords, COORD *last_coords) { 43 if(end_coords->Y < start_coords->Y || 44 (end_coords->Y == start_coords->Y && end_coords->X < start_coords->X)) 45 { 46 *first_coords = *end_coords; 47 *last_coords = *start_coords; 48 } else { 49 *first_coords = *start_coords; 50 *last_coords = *end_coords; 51 } 52 last_coords->X++; 53 } 54 55 void TMouse::doMouse_init() { 56 GetConsoleScreenBufferInfo(hStdout, &ConsoleInfo); 57 chiBuffer = newBuffer(); 58 saveScreen(chiBuffer); 59 } 60 61 void TMouse::doMouse_cleanup() { 62 restoreScreen(chiBuffer); 63 delete[] chiBuffer; 64 } 65 66 void TMouse::move_mouse(COORD start_coords, COORD end_coords) { 67 COORD screen_start = {0, 0}; 68 COORD first_coords, last_coords; 69 DWORD Result; 70 71 FillConsoleOutputAttribute(hStdout, normal, 72 ConsoleInfo.dwSize.X * ConsoleInfo.dwSize.Y, screen_start, &Result); 73 74 get_coords(&start_coords, &end_coords, &first_coords, &last_coords); 75 FillConsoleOutputAttribute(hStdout, inverse, ConsoleInfo.dwSize.X * 76 (last_coords.Y - first_coords.Y) + (last_coords.X - first_coords.X), 77 first_coords, &Result); 78 } 79 80 void TMouse::doClip(COORD start_coords, COORD end_coords) { 81 // COORD screen_start = {0, 0}; 82 COORD first_coords, last_coords; 83 DWORD Result; 84 85 get_coords(&start_coords, &end_coords, &first_coords, &last_coords); 86 87 // Allocate the minimal size buffer 88 int data_size = 3 + ConsoleInfo.dwSize.X * 89 (last_coords.Y - first_coords.Y) + (last_coords.X - first_coords.X); 90 HGLOBAL clipboard_data = GlobalAlloc(GMEM_MOVEABLE + GMEM_DDESHARE, 91 data_size); 92 LPVOID mem_ptr = GlobalLock(clipboard_data); 93 94 // Reset data_size so we can count the actual data size 95 data_size = 0; 96 97 // Read the console, put carriage returns at the end of each line if 98 // reading more than one line (Paul Brannan 9/17/98) 99 for(int j = first_coords.Y; j <= last_coords.Y; j++) { 100 101 // Read line at (0,j) 102 COORD coords; 103 coords.X = 0; 104 coords.Y = j; 105 int length = ConsoleInfo.dwSize.X; 106 107 if(j == first_coords.Y) { 108 coords.X = first_coords.X; 109 length = ConsoleInfo.dwSize.X - first_coords.X; 110 } else { 111 // Add a carriage return to the end of the previous line 112 *((char *)mem_ptr + data_size++) = '\r'; 113 *((char *)mem_ptr + data_size++) = '\n'; 114 } 115 116 if(j == last_coords.Y) { 117 length -= (ConsoleInfo.dwSize.X - last_coords.X); 118 } 119 120 // Read the next line 121 ReadConsoleOutputCharacter(hStdout, (LPTSTR)((char *)mem_ptr + 122 data_size), length, coords, &Result); 123 data_size += Result; 124 125 // Strip the spaces at the end of the line 126 if((j != last_coords.Y) && (first_coords.Y != last_coords.Y)) 127 while(*((char *)mem_ptr + data_size - 1) == ' ') data_size--; 128 } 129 if(first_coords.Y != last_coords.Y) { 130 // Add a carriage return to the end of the last line 131 *((char *)mem_ptr + data_size++) = '\r'; 132 *((char *)mem_ptr + data_size++) = '\n'; 133 } 134 135 *((char *)mem_ptr + data_size) = 0; 136 GlobalUnlock(clipboard_data); 137 138 Clipboard.Copy(clipboard_data); 139 } 140 141 void TMouse::doMouse() { 142 INPUT_RECORD InputRecord; 143 DWORD Result; 144 InputRecord.EventType = KEY_EVENT; // just in case 145 while(InputRecord.EventType != MOUSE_EVENT) { 146 if (!ReadConsoleInput(hConsole, &InputRecord, 1, &Result)) 147 return; // uh oh! we don't know the starting coordinates! 148 } 149 if(InputRecord.Event.MouseEvent.dwButtonState == 0) return; 150 if(!(InputRecord.Event.MouseEvent.dwButtonState & 151 FROM_LEFT_1ST_BUTTON_PRESSED)) { 152 Clipboard.Paste(); 153 return; 154 } 155 156 COORD screen_start = {0, 0}; 157 COORD start_coords = InputRecord.Event.MouseEvent.dwMousePosition; 158 COORD end_coords = start_coords; 159 BOOL done = FALSE; 160 161 // init vars 162 doMouse_init(); 163 int normal_bg = ini.get_normal_bg(); 164 int normal_fg = ini.get_normal_fg(); 165 if(normal_bg == -1) normal_bg = 0; // FIX ME!! This is just a hack 166 if(normal_fg == -1) normal_fg = 7; 167 normal = (normal_bg << 4) | normal_fg; 168 inverse = (normal_fg << 4) | normal_bg; 169 170 // make screen all one attribute 171 FillConsoleOutputAttribute(hStdout, normal, ConsoleInfo.dwSize.X * 172 ConsoleInfo.dwSize.Y, screen_start, &Result); 173 174 while(!done) { 175 176 switch (InputRecord.EventType) { 177 case MOUSE_EVENT: 178 switch(InputRecord.Event.MouseEvent.dwEventFlags) { 179 case 0: // only copy if the mouse button has been released 180 if(!InputRecord.Event.MouseEvent.dwButtonState) { 181 doClip(start_coords, end_coords); 182 done = TRUE; 183 } 184 break; 185 186 case MOUSE_MOVED: 187 end_coords = InputRecord.Event.MouseEvent.dwMousePosition; 188 move_mouse(start_coords, end_coords); 189 break; 190 } 191 break; 192 // If we are changing focus, we don't want to highlight anything 193 // (Paul Brannan 9/2/98) 194 case FOCUS_EVENT: 195 return; 196 } 197 198 WaitForSingleObject(hConsole, INFINITE); 199 if (!ReadConsoleInput(hConsole, &InputRecord, 1, &Result)) 200 done = TRUE; 201 202 } 203 204 doMouse_cleanup(); 205 } 206 207 void TMouse::scrollMouse() { 208 doMouse(); 209 } 210