Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygentconsole.cpp
Go to the documentation of this file.
00001 00002 //Telnet Win32 : an ANSI telnet client. 00003 //Copyright (C) 1998-2000 Paul Brannan 00004 //Copyright (C) 1998 I.Ioannou 00005 //Copyright (C) 1997 Brad Johnson 00006 // 00007 //This program is free software; you can redistribute it and/or 00008 //modify it under the terms of the GNU General Public License 00009 //as published by the Free Software Foundation; either version 2 00010 //of the License, or (at your option) any later version. 00011 // 00012 //This program is distributed in the hope that it will be useful, 00013 //but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 //MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 //GNU General Public License for more details. 00016 // 00017 //You should have received a copy of the GNU General Public License 00018 //along with this program; if not, write to the Free Software 00019 //Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00020 // 00021 //I.Ioannou 00022 //roryt@hol.gr 00023 // 00025 00027 // 00028 // Module: tconsole.cpp 00029 // 00030 // Contents: screen functions 00031 // 00032 // Product: telnet 00033 // 00034 // 00035 // Revisions: Mar. 29, 2000 pbranna@clemson (Paul Brannan) 00036 // June 15, 1998 pbranna@clemson.edu 00037 // May 16, 1998 pbranna@clemson.edu 00038 // 05. Sep.1997 roryt@hol.gr (I.Ioannou) 00039 // 11.May,1997 roryt@hol.gr 00040 // 06.April,1997 roryt@hol.gr 00041 // 30.M„rz.1997 Titus_Boxberg@public.uni-hamburg.de 00042 // 5.Dec.1996 jbj@nounname.com 00043 // Version 2.0 00044 // 02.Apr.1995 igor.milavec@uni-lj.si 00045 // Original code 00046 // 00048 00049 #include "precomp.h" 00050 00051 // argsused doesn't work on MSVC++ 00052 #ifdef __BORLANDC__ 00053 #pragma argsused 00054 #endif 00055 00056 TConsole::TConsole(HANDLE h) { 00057 hConsole = h; 00058 00059 GetConsoleScreenBufferInfo(hConsole, &ConsoleInfo); 00060 00061 // Start with correct colors 00062 int color_fg = ini.get_normal_fg(); 00063 int color_bg = ini.get_normal_bg(); 00064 if(color_fg == -1) 00065 color_fg = defaultfg = origfg = ConsoleInfo.wAttributes & 0xF; 00066 else 00067 defaultfg = origfg = color_fg; 00068 if(color_bg == -1) 00069 color_bg = defaultbg = origbg = (ConsoleInfo.wAttributes >> 4) & 0xF; 00070 else 00071 defaultbg = origbg = color_bg; 00072 wAttributes = color_fg | (color_bg << 4); 00073 reverse = blink = underline = false; 00074 SetConsoleTextAttribute(hConsole, wAttributes); 00075 00076 insert_mode = 0; 00077 00078 // Set the screen size 00079 SetWindowSize(ini.get_term_width(), ini.get_term_height()); 00080 00081 iScrollStart = -1; 00082 iScrollEnd = -1; 00083 } 00084 00085 TConsole::~TConsole() { 00086 wAttributes = origfg | (origbg << 4); 00087 SetCursorPosition(0, CON_HEIGHT); 00088 SetConsoleTextAttribute(hConsole, wAttributes); 00089 WriteCtrlChar('\x0a'); 00090 } 00091 00092 // Paul Brannan 8/2/98 00093 void TConsole::SetWindowSize(int width, int height) { 00094 SMALL_RECT sr = { 00095 CON_LEFT, 00096 CON_TOP, 00097 (width == -1) ? CON_RIGHT : CON_LEFT + width - 1, 00098 (height == -1) ? CON_BOTTOM : CON_TOP + height - 1 00099 }; 00100 ConsoleInfo.dwSize.X = width; 00101 if(ConsoleInfo.dwSize.Y < height) ConsoleInfo.dwSize.Y = height; 00102 SetConsoleScreenBufferSize(hConsole, ConsoleInfo.dwSize); 00103 SetConsoleWindowInfo(hConsole, TRUE, &sr); 00104 SetConsoleScreenBufferSize(hConsole, ConsoleInfo.dwSize); 00105 sync(); 00106 } 00107 00108 // Paul Brannan 5/15/98 00109 void TConsole::sync() { 00110 GetConsoleScreenBufferInfo(hConsole, &ConsoleInfo); 00111 } 00112 00113 void TConsole::HighVideo() { 00114 wAttributes = wAttributes | (unsigned char) 8; 00115 } 00116 00117 void TConsole::LowVideo() { 00118 wAttributes = wAttributes & (unsigned char) (0xff-8); 00119 } 00120 00121 void TConsole::Normal() { 00122 // I.Ioannou 11 May 1997 00123 // Color 7 is correct on some systems (for example Linux) 00124 // but not with others (for example SCO) 00125 // we must preserve the colors : 00126 // 06/04/98 thanks to Paul a .ini parameter from now on 00127 00128 BlinkOff(); 00129 UnderlineOff(); 00130 if(ini.get_preserve_colors()) { 00131 ReverseOff(); 00132 LowVideo(); 00133 } else { 00134 fg = defaultfg; 00135 bg = defaultbg; 00136 wAttributes = (unsigned char)fg | (bg << 4); 00137 reverse = false; 00138 } 00139 } 00140 00141 void TConsole::SetForeground(unsigned char wAttrib) { 00142 if(reverse) bg = wAttrib; else fg = wAttrib; 00143 wAttributes = (wAttributes & (unsigned char)0x88) | 00144 (unsigned char)fg | (bg << 4); 00145 } 00146 00147 void TConsole::SetBackground(unsigned char wAttrib) { 00148 if(reverse) fg = wAttrib; else bg = wAttrib; 00149 wAttributes = (wAttributes & (unsigned char)0x88) | 00150 (unsigned char)fg | (bg << 4); 00151 } 00152 00153 // As far as I can tell, there's no such thing as blink in Windows Console. 00154 // I tried using some inline asm to turn off high-intensity backgrounds, 00155 // but I got a BSOD. Perhaps there is an undocumented function? 00156 // (Paul Brannan 6/27/98) 00157 void TConsole::BlinkOn() { 00158 blink = 1; 00159 if(underline) { 00160 UlBlinkOn(); 00161 } else { 00162 if(ini.get_blink_bg() != -1) { 00163 wAttributes &= 0x8f; // turn off bg 00164 wAttributes |= ini.get_blink_bg() << 4; 00165 } 00166 if(ini.get_blink_fg() != -1) { 00167 wAttributes &= 0xf8; // turn off fg 00168 wAttributes |= ini.get_blink_fg(); 00169 } 00170 if(ini.get_blink_bg() == -1 && ini.get_blink_fg() == -1) 00171 wAttributes |= 0x80; 00172 } 00173 } 00174 00175 // Added by I.Ioannou 06 April, 1997 00176 void TConsole::BlinkOff() { 00177 blink = 0; 00178 if(underline) { 00179 UlBlinkOff(); 00180 } else { 00181 if(ini.get_blink_bg() != -1) { 00182 wAttributes &= 0x8f; // turn off bg 00183 wAttributes |= defaultbg << 4; 00184 } 00185 if(ini.get_blink_fg() != -1) { 00186 wAttributes &= 0xf8; // turn off fg 00187 wAttributes |= defaultfg; 00188 } 00189 if(ini.get_blink_bg() == -1 && ini.get_blink_fg() == -1) 00190 wAttributes &= 0x7f; 00191 } 00192 } 00193 00194 // Paul Brannan 6/27/98 00195 void TConsole::UnderlineOn() { 00196 underline = 1; 00197 if(blink) { 00198 UlBlinkOn(); 00199 } else { 00200 if(ini.get_underline_bg() != -1) { 00201 wAttributes &= 0x8f; // turn off bg 00202 wAttributes |= ini.get_underline_bg() << 4; 00203 } 00204 if(ini.get_underline_fg() != -1) { 00205 wAttributes &= 0xf8; // turn off fg 00206 wAttributes |= ini.get_underline_fg(); 00207 } 00208 if(ini.get_underline_bg() == -1 && ini.get_underline_fg() == -1) 00209 wAttributes |= 0x80; 00210 } 00211 } 00212 00213 // Paul Brannan 6/27/98 00214 void TConsole::UnderlineOff() { 00215 underline = 0; 00216 if(blink) { 00217 UlBlinkOff(); 00218 } else { 00219 if(ini.get_blink_bg() != -1) { 00220 wAttributes &= 0x8f; // turn off bg 00221 wAttributes |= defaultbg << 4; 00222 } 00223 if(ini.get_blink_fg() != -1) { 00224 wAttributes &= 0xf8; // turn off fg 00225 wAttributes |= defaultfg; 00226 } 00227 if(ini.get_blink_bg() == -1 && ini.get_blink_fg() == -1) 00228 wAttributes &= 0x7f; 00229 } 00230 } 00231 00232 // Paul Brannan 6/27/98 00233 void TConsole::UlBlinkOn() { 00234 if(ini.get_ulblink_bg() != -1) { 00235 wAttributes &= 0x8f; // turn off bg 00236 wAttributes |= ini.get_ulblink_bg() << 4; 00237 } 00238 if(ini.get_ulblink_fg() != -1) { 00239 wAttributes &= 0xf8; // turn off fg 00240 wAttributes |= ini.get_ulblink_fg(); 00241 } 00242 if(ini.get_ulblink_bg() == -1 && ini.get_ulblink_fg() == -1) 00243 wAttributes |= 0x80; 00244 } 00245 00246 // Paul Brannan 6/27/98 00247 void TConsole::UlBlinkOff() { 00248 if(blink) { 00249 BlinkOn(); 00250 } else if(underline) { 00251 UnderlineOn(); 00252 } else { 00253 Normal(); 00254 } 00255 } 00256 00257 // Paul Brannan 6/26/98 00258 void TConsole::Lightbg() { 00259 WORD *pAttributes = new WORD[CON_COLS]; 00260 DWORD Result; 00261 00262 // Paul Brannan 8/5/98 00263 // Correction: processing more than one line at a time causes a segfault 00264 // if the screen width != 80 00265 for(int i = CON_TOP; i <= CON_BOTTOM; i++) { 00266 COORD Coord = {CON_LEFT, i}; 00267 00268 ReadConsoleOutputAttribute(hConsole, pAttributes, (DWORD)(CON_COLS), 00269 Coord, &Result); 00270 00271 for(DWORD j = 0; j < Result; j++) pAttributes[j] |= 0x80; 00272 00273 WriteConsoleOutputAttribute(hConsole, pAttributes, Result, Coord, 00274 &Result); 00275 } 00276 00277 delete[] pAttributes; // clean up 00278 00279 wAttributes |= (unsigned char)0x80; 00280 bg |= 8; 00281 } 00282 00283 // Paul Brannan 6/26/98 00284 void TConsole::Darkbg() { 00285 WORD *pAttributes = new WORD[CON_COLS]; 00286 DWORD Result; 00287 00288 // Paul Brannan 8/5/98 00289 // Correction: processing more than one line at a time causes a segfault 00290 // if the screen width != 80 00291 for(int i = CON_TOP; i <= CON_BOTTOM; i++) { 00292 COORD Coord = {CON_LEFT, i}; 00293 00294 ReadConsoleOutputAttribute(hConsole, pAttributes, (DWORD)(CON_COLS), 00295 Coord, &Result); 00296 00297 for(DWORD j = 0; j < Result; j++) pAttributes[j] &= 0x7f; 00298 00299 WriteConsoleOutputAttribute(hConsole, pAttributes, Result, Coord, 00300 &Result); 00301 } 00302 00303 delete[] pAttributes; // clean up 00304 00305 00306 wAttributes &= (unsigned char)0x7f; 00307 bg &= 7; 00308 } 00309 00310 // Added by I.Ioannou 11.May,1997 00311 void TConsole::ReverseOn() { 00312 if (!reverse) { 00313 reverse = true; 00314 00315 // atl : forground attributes without the intensity 00316 // ath : backgound attributes without the blink 00317 // bl : the blink state 00318 // ints : the intensity 00319 unsigned char atl = wAttributes & (unsigned char) 0x07; 00320 unsigned char ath = wAttributes & (unsigned char) 0x70; 00321 unsigned char bl = wAttributes & (unsigned char) 0x80; 00322 unsigned char ints = wAttributes & (unsigned char) 0x08; 00323 wAttributes = bl | (atl << 4) | ints | (ath >> 4); 00324 } 00325 } 00326 00327 // Added by I.Ioannou 11.May,1997 00328 void TConsole::ReverseOff() { 00329 if (reverse) { 00330 reverse = false; 00331 wAttributes = fg | (bg << 4); 00332 } 00333 } 00334 00335 unsigned long TConsole::WriteText(const char *pszString, unsigned long cbString) { 00336 DWORD Result; 00337 00338 if(insert_mode) { 00339 InsertCharacter(cbString); 00340 } 00341 00342 WriteConsoleOutputCharacter(hConsole, (char *)pszString, cbString, 00343 ConsoleInfo.dwCursorPosition, &Result); 00344 FillConsoleOutputAttribute(hConsole, wAttributes, cbString, 00345 ConsoleInfo.dwCursorPosition, &Result); 00346 return Result; 00347 } 00348 00349 // Formerly ConWriteString (Paul Brannan 6/28/98) 00350 unsigned long TConsole::WriteStringFast(const char* pszString, unsigned long cbString) { 00351 DWORD Result; 00352 00353 SetConsoleTextAttribute(hConsole, wAttributes); 00354 00355 //check to see if the line is longer than the display 00356 if (!getLineWrap() && ((unsigned)CON_CUR_X + cbString) >= (unsigned)CON_COLS) { 00357 // Take care of the last line last colum exception... 00358 // The display scrolls up if you use the normal char out 00359 // function even if you only write to the last place 00360 // on the line. :-( 00361 if ((unsigned)CON_CUR_Y >= (unsigned)CON_HEIGHT) { 00362 unsigned long iFakeResult = cbString; 00363 cbString = CON_COLS - CON_CUR_X - 1; 00364 00365 // FIX ME !!! This will avoid the exception when cbString 00366 // is <= 0 but still doesn't work :-( 00367 if (cbString > 0) 00368 WriteConsole(hConsole, pszString, cbString, &Result, 0); 00369 00370 COORD dwBufferCoord; 00371 dwBufferCoord.X = 0; 00372 dwBufferCoord.Y = 0; 00373 00374 CHAR_INFO ciBuffer; 00375 ciBuffer.Char.AsciiChar = *(pszString+cbString); 00376 ciBuffer.Attributes = wAttributes; 00377 SMALL_RECT srWriteRegion; 00378 srWriteRegion.Top = (SHORT) CON_BOTTOM; 00379 srWriteRegion.Bottom = (SHORT) CON_BOTTOM; 00380 srWriteRegion.Left = (SHORT) CON_RIGHT; 00381 srWriteRegion.Right = (SHORT) CON_RIGHT; 00382 00383 COORD bufSize = {1,1}; 00384 00385 WriteConsoleOutput(hConsole, &ciBuffer, bufSize, 00386 dwBufferCoord, &srWriteRegion); 00387 00388 // We need to update the ConsoleInfo struct now (Paul Brannan 5/9/98) 00389 ConsoleInfo.dwCursorPosition.X = CON_RIGHT; 00390 00391 return iFakeResult; // Skip the chars that did not fit 00392 } 00393 // just write the line up to the end 00394 else { 00395 int iFakeResult = cbString; 00396 cbString = CON_COLS - CON_CUR_X; 00397 00398 if(cbString > 0) { 00399 WriteConsole(hConsole, pszString, cbString, &Result, 0); 00400 00401 // We need to update the ConsoleInfo struct now (Paul Brannan 5/9/98) 00402 ConsoleInfo.dwCursorPosition.X += (unsigned short)Result; 00403 } 00404 00405 return iFakeResult; // Skip the chars that did not fit 00406 } 00407 } else { 00408 // If custom scrolling is enabled we must take care of it 00409 if(iScrollStart != -1 || iScrollEnd != -1) { 00410 return WriteString(pszString, cbString); 00411 } 00412 00413 // Apparently VT100 terminals have an invisible "81st" column that 00414 // can hold a cursor until another character is printed. I'm not sure 00415 // exactly how to handle this, but here's a hack (Paul Brannan 5/28/98) 00416 if(ini.get_vt100_mode() && cbString + (unsigned)CON_CUR_X == (unsigned)CON_COLS) { 00417 00418 cbString--; 00419 if((long)cbString >= 0) WriteConsole(hConsole, pszString, cbString, &Result, 0); 00420 00421 COORD dwBufferCoord; 00422 dwBufferCoord.X = 0; 00423 dwBufferCoord.Y = 0; 00424 00425 CHAR_INFO ciBuffer; 00426 ciBuffer.Char.AsciiChar = *(pszString+cbString); 00427 ciBuffer.Attributes = wAttributes; 00428 SMALL_RECT srWriteRegion; 00429 srWriteRegion.Top = (SHORT) ConsoleInfo.dwCursorPosition.Y; 00430 srWriteRegion.Bottom = (SHORT) ConsoleInfo.dwCursorPosition.Y; 00431 srWriteRegion.Left = (SHORT) CON_RIGHT; 00432 srWriteRegion.Right = (SHORT) CON_RIGHT; 00433 00434 COORD bufSize = {1,1}; 00435 00436 WriteConsoleOutput(hConsole, &ciBuffer, bufSize, 00437 dwBufferCoord, &srWriteRegion); 00438 00439 // Update the ConsoleInfo struct 00440 ConsoleInfo.dwCursorPosition.X = CON_RIGHT + 1; 00441 00442 return Result + 1; 00443 } 00444 00445 // normal line will wrap normally or not to the end of buffer 00446 WriteConsole(hConsole, pszString, cbString, &Result, 0); 00447 00448 // We need to update the ConsoleInfo struct now (Paul Brannan 5/9/98) 00449 // FIX ME!!! This is susceptible to the same problem as above. 00450 // (e.g. we write out 160 characters) 00451 ConsoleInfo.dwCursorPosition.X += (unsigned short)Result; 00452 while(CON_CUR_X > CON_WIDTH) { 00453 ConsoleInfo.dwCursorPosition.X -= ConsoleInfo.dwSize.X; 00454 if((unsigned)CON_CUR_Y < (unsigned)CON_HEIGHT) { 00455 ConsoleInfo.dwCursorPosition.Y++; 00456 } else { 00457 // If we aren't at the bottom of the window, then we need to 00458 // scroll down (Paul Brannan 4/14/2000) 00459 if(ConsoleInfo.srWindow.Bottom < ConsoleInfo.dwSize.Y - 1) { 00460 ConsoleInfo.srWindow.Top++; 00461 ConsoleInfo.srWindow.Bottom++; 00462 ConsoleInfo.dwCursorPosition.Y++; 00463 SetConsoleWindowInfo(hConsole, TRUE, &ConsoleInfo.srWindow); 00464 } 00465 } 00466 } 00467 } 00468 00469 return Result; 00470 00471 } 00472 00473 unsigned long TConsole::WriteString(const char* pszString, unsigned long cbString) { 00474 DWORD Result = 0; 00475 00476 SetConsoleTextAttribute(hConsole, wAttributes); 00477 00478 //check to see if the line is longer than the display 00479 if (!getLineWrap()){ 00480 unsigned long iFakeResult = cbString; 00481 if((CON_CUR_X + cbString) >= (unsigned int)CON_COLS) 00482 cbString = CON_COLS - CON_CUR_X; 00483 if(cbString > 0) 00484 Result = WriteText(pszString, cbString); 00485 00486 // We need to update the ConsoleInfo struct now (Paul Brannan 5/9/98) 00487 ConsoleInfo.dwCursorPosition.X += (unsigned short)Result; 00488 SetConsoleCursorPosition(hConsole, ConsoleInfo.dwCursorPosition); 00489 00490 return iFakeResult; // Skip the chars that did not fit 00491 } else { 00492 // Write up to the end of the line 00493 unsigned long temp = cbString; 00494 if((CON_CUR_X + temp) > (unsigned int)CON_COLS) { 00495 temp = CON_COLS - CON_CUR_X; 00496 } else { 00497 Result = WriteText(pszString, temp); 00498 ConsoleInfo.dwCursorPosition.X += (unsigned short)Result; 00499 SetConsoleCursorPosition(hConsole, ConsoleInfo.dwCursorPosition); 00500 return Result; 00501 } 00502 if(temp > 0) { 00503 Result = WriteText(pszString, temp); 00504 ConsoleInfo.dwCursorPosition.X += (unsigned short)Result; 00505 temp = (unsigned short)Result; 00506 } 00507 00508 // keep writing lines until we get to less than 80 chars left 00509 while((temp + (unsigned int)CON_COLS) < cbString) { 00510 index(); // LF 00511 ConsoleInfo.dwCursorPosition.X = 0; // CR 00512 Result = WriteText(&pszString[temp], CON_COLS); 00513 temp += (unsigned short)Result; 00514 } 00515 00516 // write out the last bit 00517 if(temp < cbString) { 00518 index(); 00519 ConsoleInfo.dwCursorPosition.X = 0; 00520 Result = WriteText(&pszString[temp], cbString - temp); 00521 temp += (unsigned short)Result; 00522 } 00523 00524 // Apparently VT100 terminals have an invisible "81st" column that 00525 // can hold a cursor until another character is printed. I'm not sure 00526 // exactly how to handle this, but here's a hack (Paul Brannan 5/28/98) 00527 if(!ini.get_vt100_mode() && cbString + (unsigned)ConsoleInfo.dwCursorPosition.X 00528 == (unsigned int)CON_COLS) { 00529 index(); 00530 ConsoleInfo.dwCursorPosition.X = 0; 00531 } 00532 00533 SetConsoleCursorPosition(hConsole, ConsoleInfo.dwCursorPosition); 00534 00535 return temp; 00536 } 00537 00538 return 0; 00539 } 00540 00541 // This is for multi-character control strings (Paul Brannan 6/26/98) 00542 unsigned long TConsole::WriteCtrlString(const char *pszString, unsigned long cbString) { 00543 unsigned long total = 0; 00544 while(total < cbString) { 00545 unsigned long Result = WriteCtrlChar(*(pszString + total)); 00546 if(Result == 0) { 00547 Result = WriteStringFast(pszString + total, 1); 00548 if(Result == 0) return total; 00549 } 00550 total += Result; 00551 } 00552 return total; 00553 } 00554 00555 // This is for printing single control characters 00556 // WriteCtrlString uses this (Paul Brannan 6/26/98) 00557 unsigned long TConsole::WriteCtrlChar(char c) { 00558 // The console does not handel the CR/LF chars as we might expect 00559 // when using color. The attributes are not set correctly, so we 00560 // must interpret them manualy to preserve the colors on the screen. 00561 00562 unsigned long Result = 0; // just in case (Paul Brannan 6/26/98) 00563 switch (c) { 00564 case '\x09': // horizontal tab 00565 SetCursorPosition((((CON_CUR_X/8)+1)*8), CON_CUR_Y); 00566 Result = 1; 00567 break; 00568 00569 case '\x0a': // line feed 00570 index(); 00571 Result = 1; 00572 break; 00573 case '\x0d': // carrage return 00574 SetCursorPosition(CON_LEFT, CON_CUR_Y); // move to beginning of line 00575 Result = 1; 00576 break; 00577 case '\b': // backspace 00578 // Added support for backspace so the cursor position can be changed 00579 // (Paul Brannan 5/25/98) 00580 MoveCursorPosition(-1, 0); 00581 Result = 1; 00582 default : // else just write it like normal 00583 break; 00584 } 00585 00586 return Result; 00587 } 00588 00589 void TConsole::index() { 00590 // if on the last line scroll up 00591 // This must work with scrolling (Paul Brannan 5/13/98) 00592 if(iScrollEnd != -1 && (signed)CON_CUR_Y >= iScrollEnd) { 00593 ScrollDown(iScrollStart, iScrollEnd, -1); 00594 } else if ((iScrollEnd == -1 && (signed)CON_CUR_Y >= (signed)CON_HEIGHT)) { 00595 DWORD Result; 00596 WriteConsole(hConsole, "\n", 1, &Result, NULL); 00597 00598 // If we aren't at the bottom of the buffer, then we need to 00599 // scroll down (Paul Brannan 4/14/2000) 00600 if(iScrollEnd == -1 && ConsoleInfo.srWindow.Bottom < ConsoleInfo.dwSize.Y - 1) { 00601 ConsoleInfo.srWindow.Top++; 00602 ConsoleInfo.srWindow.Bottom++; 00603 ConsoleInfo.dwCursorPosition.Y++; 00604 // SetConsoleWindowInfo(hConsole, TRUE, &ConsoleInfo.srWindow); 00605 } else { 00606 ClearLine(); 00607 } 00608 } else { // else move cursor down to the next line 00609 SetCursorPosition(CON_CUR_X, CON_CUR_Y + 1); 00610 } 00611 } 00612 00613 void TConsole::reverse_index() { 00614 // if on the top line scroll down 00615 // This must work with scrolling (Paul Brannan 5/13/98) 00616 // We should be comparing against iScrollStart, not iScrollEnd (PB 12/2/98) 00617 if (iScrollStart == -1 && (signed)CON_CUR_Y <= 0) { 00618 ScrollDown(iScrollStart, -1, 1); 00619 } else if (iScrollStart != -1 && (signed)CON_CUR_Y <= iScrollStart) { 00620 ScrollDown(iScrollStart, iScrollEnd, 1); 00621 } else // else move cursor up to the previous line 00622 SetCursorPosition(CON_CUR_X,CON_CUR_Y - 1); 00623 } 00624 00625 void TConsole::ScrollDown( int iStartRow , int iEndRow, int bUp ){ 00626 CHAR_INFO ciChar; 00627 SMALL_RECT srScrollWindow; 00628 00629 // Correction from I.Ioannou 11 May 1997 00630 // check the scroll region 00631 if (iStartRow < iScrollStart) iStartRow = iScrollStart; 00632 00633 // Correction from I.Ioannou 11 May 1997 00634 // this will make Top the CON_TOP 00635 if ( iStartRow == -1) iStartRow = 0; 00636 00637 // Correction from I.Ioannou 18 Aug 97 00638 if ( iEndRow == -1) { 00639 if ( iScrollEnd == -1 ) 00640 iEndRow = CON_HEIGHT; 00641 else 00642 iEndRow = ((CON_HEIGHT <= iScrollEnd) ? CON_HEIGHT : iScrollEnd); 00643 } 00644 // 00645 00646 if ( iStartRow > CON_HEIGHT) iStartRow = CON_HEIGHT; 00647 if ( iEndRow > CON_HEIGHT) iEndRow = CON_HEIGHT; 00648 00649 srScrollWindow.Left = (CON_LEFT); 00650 srScrollWindow.Right = (SHORT) (CON_RIGHT); 00651 srScrollWindow.Top = (SHORT) (CON_TOP + iStartRow ); 00652 srScrollWindow.Bottom = (SHORT) (CON_TOP + iEndRow); // don't subtract 1 (PB 5/28) 00653 00654 ciChar.Char.AsciiChar = ' '; // fill with spaces 00655 ciChar.Attributes = wAttributes; // fill with current attrib 00656 00657 // This should speed things up (Paul Brannan 9/2/98) 00658 COORD dwDestOrg = {srScrollWindow.Left, srScrollWindow.Top + bUp}; 00659 00660 // Note that iEndRow and iStartRow had better not be equal to -1 at this 00661 // point. There are four cases to consider for out of bounds. Two of 00662 // these cause the scroll window to be cleared; the others cause the 00663 // scroll region to be modified. (Paul Brannan 12/3/98) 00664 if(dwDestOrg.Y > CON_TOP + iEndRow) { 00665 // We are scrolling past the end of the scroll region, so just 00666 // clear the window instead (Paul Brannan 12/3/98) 00667 ClearWindow(CON_TOP + iStartRow, CON_TOP + iEndRow); 00668 return; 00669 } else if(dwDestOrg.Y + (iEndRow-iStartRow+1) < CON_TOP + iStartRow) { 00670 // We are scrolling past the end of the scroll region, so just 00671 // clear the window instead (Paul Brannan 12/3/98) 00672 ClearWindow(CON_TOP + iStartRow, CON_TOP + iEndRow); 00673 return; 00674 } else if(dwDestOrg.Y < CON_TOP + iStartRow) { 00675 // Modify the scroll region (Paul Brannan 12/3/98) 00676 dwDestOrg.Y = CON_TOP + iStartRow; 00677 srScrollWindow.Top -= bUp; 00678 } else if(dwDestOrg.Y + (iEndRow-iStartRow+1) > CON_TOP + iEndRow) { 00679 // Modify the scroll region (Paul Brannan 12/3/98) 00680 srScrollWindow.Bottom -= bUp; 00681 } 00682 00683 ScrollConsoleScreenBuffer(hConsole, &srScrollWindow, 00684 0, dwDestOrg, &ciChar); 00685 } 00686 00687 // This allows us to clear the screen with an arbitrary character 00688 // (Paul Brannan 6/26/98) 00689 void TConsole::ClearScreen(char c) { 00690 DWORD dwWritten; 00691 COORD Coord = {CON_LEFT, CON_TOP}; 00692 FillConsoleOutputCharacter(hConsole, c, (DWORD)(CON_COLS)* 00693 (DWORD)(CON_LINES), Coord, &dwWritten); 00694 FillConsoleOutputAttribute(hConsole, wAttributes, (DWORD)(CON_COLS)* 00695 (DWORD)(CON_LINES), Coord, &dwWritten); 00696 } 00697 00698 // Same as clear screen, but only affects the scroll region 00699 void TConsole::ClearWindow(int iStartRow, int iEndRow, char c) { 00700 DWORD dwWritten; 00701 COORD Coord = {CON_LEFT, CON_TOP + iStartRow}; 00702 FillConsoleOutputCharacter(hConsole, c, (DWORD)(CON_COLS)* 00703 (DWORD)(iEndRow-iStartRow+1), Coord, &dwWritten); 00704 FillConsoleOutputAttribute(hConsole, wAttributes, (DWORD)(CON_COLS)* 00705 (DWORD)(CON_LINES), Coord, &dwWritten); 00706 } 00707 00708 // Clear from cursor to end of screen 00709 void TConsole::ClearEOScreen(char c) 00710 { 00711 DWORD dwWritten; 00712 COORD Coord = {CON_LEFT, CON_TOP + CON_CUR_Y + 1}; 00713 FillConsoleOutputCharacter(hConsole, c, (DWORD)(CON_COLS)* 00714 (DWORD)(CON_HEIGHT - CON_CUR_Y), Coord, &dwWritten); 00715 FillConsoleOutputAttribute(hConsole, wAttributes, (DWORD)(CON_COLS)* 00716 (DWORD)(CON_LINES - CON_CUR_Y), Coord, &dwWritten); 00717 ClearEOLine(); 00718 } 00719 00720 // Clear from beginning of screen to cursor 00721 void TConsole::ClearBOScreen(char c) 00722 { 00723 DWORD dwWritten; 00724 COORD Coord = {CON_LEFT, CON_TOP}; 00725 FillConsoleOutputCharacter(hConsole, c, (DWORD)(CON_COLS)* 00726 (DWORD)(CON_CUR_Y), Coord, &dwWritten); 00727 FillConsoleOutputAttribute(hConsole, wAttributes, (DWORD)(CON_COLS)* 00728 (DWORD)(CON_CUR_Y), Coord, &dwWritten); 00729 ClearBOLine(); 00730 } 00731 00732 void TConsole::ClearLine(char c) 00733 { 00734 DWORD dwWritten; 00735 COORD Coord = {CON_LEFT, CON_TOP + CON_CUR_Y}; 00736 FillConsoleOutputCharacter(hConsole, c, (DWORD)(CON_COLS), 00737 Coord, &dwWritten); 00738 FillConsoleOutputAttribute(hConsole, wAttributes, (DWORD)(CON_COLS), 00739 Coord, &dwWritten); 00740 GetConsoleScreenBufferInfo(hConsole, &ConsoleInfo); 00741 } 00742 00743 void TConsole::ClearEOLine(char c) 00744 { 00745 DWORD dwWritten; 00746 COORD Coord = {CON_LEFT + CON_CUR_X, CON_TOP + CON_CUR_Y}; 00747 FillConsoleOutputAttribute(hConsole, wAttributes, 00748 (DWORD)(CON_RIGHT - CON_CUR_X) +1, Coord, &dwWritten); 00749 FillConsoleOutputCharacter(hConsole, c, (DWORD)(CON_RIGHT - CON_CUR_X) +1, 00750 Coord, &dwWritten); 00751 GetConsoleScreenBufferInfo(hConsole, &ConsoleInfo); 00752 } 00753 00754 void TConsole::ClearBOLine(char c) 00755 { 00756 DWORD dwWritten; 00757 COORD Coord = {CON_LEFT, CON_TOP + CON_CUR_Y}; 00758 FillConsoleOutputCharacter(hConsole, c, (DWORD)(CON_CUR_X) + 1, Coord, 00759 &dwWritten); 00760 FillConsoleOutputAttribute(hConsole, wAttributes, (DWORD)(CON_CUR_X) + 1, 00761 Coord, &dwWritten); 00762 GetConsoleScreenBufferInfo(hConsole, &ConsoleInfo); 00763 } 00764 00765 00766 // Inserts blank lines to the cursor-y-position 00767 // scrolls down the rest. CURSOR MOVEMENT (to Col#1) ??? 00768 void TConsole::InsertLine(int numlines) 00769 { 00770 COORD to; 00771 SMALL_RECT from; 00772 SMALL_RECT clip; 00773 CHAR_INFO fill; 00774 int acty; 00775 00776 // Rest of screen would be deleted 00777 if ( (acty = GetCursorY()) >= CON_LINES - numlines ) { 00778 ClearEOScreen(); // delete rest of screen 00779 return; 00780 } /* IF */ 00781 00782 // Else scroll down the part of the screen which is below the 00783 // cursor. 00784 from.Left = CON_LEFT; 00785 from.Top = CON_TOP + (SHORT)acty; 00786 from.Right = CON_LEFT + (SHORT)CON_COLS; 00787 from.Bottom = CON_TOP + (SHORT)CON_LINES; 00788 00789 clip = from; 00790 to.X = 0; 00791 to.Y = (SHORT)(from.Top + numlines); 00792 00793 fill.Char.AsciiChar = ' '; 00794 fill.Attributes = 7; // WHICH ATTRIBUTES TO TAKE FOR BLANK LINE ?? 00795 00796 ScrollConsoleScreenBuffer(hConsole, &from, &clip, to, &fill); 00797 } /* InsertLine */ 00798 00799 // Inserts blank characters under the cursor 00800 void TConsole::InsertCharacter(int numchar) 00801 { 00802 int actx; 00803 SMALL_RECT from; 00804 SMALL_RECT clip; 00805 COORD to; 00806 CHAR_INFO fill; 00807 00808 if ( (actx = GetCursorX()) >= CON_COLS - numchar ) { 00809 ClearEOLine(); 00810 return; 00811 } /* IF */ 00812 00813 from.Left = CON_LEFT + (SHORT)actx; 00814 from.Top = CON_TOP + (SHORT)GetCursorY(); 00815 from.Right = CON_LEFT + (SHORT)CON_COLS; 00816 from.Bottom = CON_TOP + (SHORT)from.Top; 00817 00818 clip = from; 00819 to.X = (SHORT)(actx + numchar); 00820 to.Y = from.Top; 00821 00822 fill.Char.AsciiChar = ' '; 00823 fill.Attributes = wAttributes; // WHICH ATTRIBUTES TO TAKE FOR BLANK CHAR ?? 00824 00825 ScrollConsoleScreenBuffer(hConsole, &from, &clip, to, &fill); 00826 } /* InsertCharacter */ 00827 00828 // Deletes characters under the cursor 00829 // Note that there are cases in which all the following lines should shift by 00830 // a character, but we don't handle these. This could break some 00831 // VT102-applications, but it shouldn't be too much of an issue. 00832 void TConsole::DeleteCharacter(int numchar) 00833 { 00834 int actx; 00835 SMALL_RECT from; 00836 SMALL_RECT clip; 00837 COORD to; 00838 CHAR_INFO fill; 00839 00840 if ( (actx = GetCursorX()) >= CON_COLS - numchar ) { 00841 ClearEOLine(); 00842 return; 00843 } /* IF */ 00844 00845 from.Left = CON_LEFT + (SHORT)actx; 00846 from.Top = CON_TOP + (SHORT)GetCursorY(); 00847 from.Right = CON_LEFT + (SHORT)CON_COLS; 00848 from.Bottom = CON_TOP + from.Top; 00849 00850 clip = from; 00851 to.X = (SHORT)(actx - numchar); 00852 to.Y = from.Top; 00853 00854 fill.Char.AsciiChar = ' '; 00855 fill.Attributes = wAttributes; // WHICH ATTRIBUTES TO TAKE FOR BLANK CHAR ?? 00856 00857 ScrollConsoleScreenBuffer(hConsole, &from, &clip, to, &fill); 00858 } /* DeleteCharacter */ 00859 00860 void TConsole::SetRawCursorPosition(int x, int y) { 00861 if (x > CON_WIDTH) x = CON_WIDTH; 00862 if (x < 0) x = 0; 00863 if (y > CON_HEIGHT) y = CON_HEIGHT; 00864 if (y < 0) y = 0; 00865 COORD Coord = {(short)(CON_LEFT + x), (short)(CON_TOP + y)}; 00866 SetConsoleCursorPosition(hConsole, Coord); 00867 00868 // Update the ConsoleInfo struct (Paul Brannan 5/9/98) 00869 ConsoleInfo.dwCursorPosition.Y = Coord.Y; 00870 ConsoleInfo.dwCursorPosition.X = Coord.X; 00871 00872 // bug fix in case we went too far (Paul Brannan 5/25/98) 00873 if(ConsoleInfo.dwCursorPosition.X < CON_LEFT) 00874 ConsoleInfo.dwCursorPosition.X = CON_LEFT; 00875 if(ConsoleInfo.dwCursorPosition.X > CON_RIGHT) 00876 ConsoleInfo.dwCursorPosition.X = CON_RIGHT; 00877 if(ConsoleInfo.dwCursorPosition.Y < CON_TOP) 00878 ConsoleInfo.dwCursorPosition.Y = CON_TOP; 00879 if(ConsoleInfo.dwCursorPosition.Y > CON_BOTTOM) 00880 ConsoleInfo.dwCursorPosition.Y = CON_BOTTOM; 00881 } 00882 00883 // The new SetCursorPosition takes scroll regions into consideration 00884 // (Paul Brannan 6/27/98) 00885 void TConsole::SetCursorPosition(int x, int y) { 00886 if (x > CON_WIDTH) x = CON_WIDTH; 00887 if (x < 0) x = 0; 00888 if(iScrollEnd != -1) { 00889 if(y > iScrollEnd) y = iScrollEnd; 00890 } else { 00891 if(y > CON_HEIGHT) y = CON_HEIGHT; 00892 } 00893 if(iScrollStart != -1) { 00894 if(y < iScrollStart) y = iScrollStart; 00895 } else { 00896 if(y < 0) y = 0; 00897 } 00898 00899 COORD Coord = {(short)(CON_LEFT + x), (short)(CON_TOP + y)}; 00900 SetConsoleCursorPosition(hConsole, Coord); 00901 00902 // Update the ConsoleInfo struct 00903 ConsoleInfo.dwCursorPosition.Y = Coord.Y; 00904 ConsoleInfo.dwCursorPosition.X = Coord.X; 00905 } 00906 00907 void TConsole::MoveCursorPosition(int x, int y) { 00908 SetCursorPosition(CON_CUR_X + x, CON_CUR_Y + y); 00909 } 00910 00911 void TConsole::SetExtendedMode(int iFunction, BOOL bEnable) 00912 { 00913 // Probably should do something here... 00914 // Should change the screen mode, but do we need this? 00915 } 00916 00917 void TConsole::SetScroll(int start, int end) { 00918 iScrollStart = start; 00919 iScrollEnd = end; 00920 } 00921 00922 void TConsole::Beep() { 00923 if(ini.get_do_beep()) { 00924 if(!ini.get_speaker_beep()) printit("\a"); 00925 else ::Beep(400, 100); 00926 } 00927 } 00928 00929 void TConsole::SetCursorSize(int pct) { 00930 CONSOLE_CURSOR_INFO ci = {(pct != 0)?pct:1, pct != 0}; 00931 SetConsoleCursorInfo(hConsole, &ci); 00932 } 00933 00934 void saveScreen(CHAR_INFO *chiBuffer) { 00935 HANDLE hStdout; 00936 CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo; 00937 SMALL_RECT srctReadRect; 00938 COORD coordBufSize; 00939 COORD coordBufCoord; 00940 00941 hStdout = GetStdHandle(STD_OUTPUT_HANDLE); 00942 GetConsoleScreenBufferInfo(hStdout, &ConsoleInfo); 00943 00944 srctReadRect.Top = CON_TOP; /* top left: row 0, col 0 */ 00945 srctReadRect.Left = CON_LEFT; 00946 srctReadRect.Bottom = CON_BOTTOM; /* bot. right: row 1, col 79 */ 00947 srctReadRect.Right = CON_RIGHT; 00948 00949 coordBufSize.Y = CON_BOTTOM-CON_TOP+1; 00950 coordBufSize.X = CON_RIGHT-CON_LEFT+1; 00951 00952 coordBufCoord.X = CON_TOP; 00953 coordBufCoord.Y = CON_LEFT; 00954 00955 ReadConsoleOutput( 00956 hStdout, /* screen buffer to read from */ 00957 chiBuffer, /* buffer to copy into */ 00958 coordBufSize, /* col-row size of chiBuffer */ 00959 00960 coordBufCoord, /* top left dest. cell in chiBuffer */ 00961 &srctReadRect); /* screen buffer source rectangle */ 00962 } 00963 00964 void restoreScreen(CHAR_INFO *chiBuffer) { 00965 HANDLE hStdout; 00966 CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo; 00967 SMALL_RECT srctReadRect; 00968 COORD coordBufSize; 00969 COORD coordBufCoord; 00970 00971 hStdout = GetStdHandle(STD_OUTPUT_HANDLE); 00972 GetConsoleScreenBufferInfo(hStdout, &ConsoleInfo); 00973 00974 // restore screen 00975 srctReadRect.Top = CON_TOP; /* top left: row 0, col 0 */ 00976 srctReadRect.Left = CON_LEFT; 00977 srctReadRect.Bottom = CON_BOTTOM; /* bot. right: row 1, col 79 */ 00978 srctReadRect.Right = CON_RIGHT; 00979 00980 coordBufSize.Y = CON_BOTTOM-CON_TOP+1; 00981 coordBufSize.X = CON_RIGHT-CON_LEFT+1; 00982 00983 coordBufCoord.X = CON_TOP; 00984 coordBufCoord.Y = CON_LEFT; 00985 WriteConsoleOutput( 00986 hStdout, /* screen buffer to write to */ 00987 chiBuffer, /* buffer to copy from */ 00988 coordBufSize, /* col-row size of chiBuffer */ 00989 coordBufCoord, /* top left src cell in chiBuffer */ 00990 &srctReadRect); /* dest. screen buffer rectangle */ 00991 // end restore screen 00992 00993 } 00994 00995 CHAR_INFO* newBuffer() { 00996 CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo; 00997 HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE); 00998 GetConsoleScreenBufferInfo(hStdout, &ConsoleInfo); 00999 CHAR_INFO * chiBuffer; 01000 chiBuffer = new CHAR_INFO[(CON_BOTTOM-CON_TOP+1)*(CON_RIGHT-CON_LEFT+1)]; 01001 return chiBuffer; 01002 } 01003 01004 void deleteBuffer(CHAR_INFO* chiBuffer) { 01005 delete[] chiBuffer; 01006 } 01007 Generated on Sun May 27 2012 04:17:16 for ReactOS by
1.7.6.1
|