tscroll.cpp
上传用户:tigerk9
上传日期:2020-03-10
资源大小:237k
文件大小:11k
源码类别:

Telnet客户端

开发平台:

Visual C++

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //Telnet Win32 : an ANSI telnet client.
  3. //Copyright (C) 1998-2000 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. //
  27. // Module: tscroll.cpp
  28. //
  29. // Contents: Telnet Handler
  30. //
  31. // Product: telnet
  32. //
  33. // Revisions: Dec. 5, 1998 Paul Brannan <pbranna@clemson.edu>
  34. //            June 15, 1998 Paul Brannan
  35. //
  36. //            This is code originally from tnclass.cpp and ansiprsr.cpp
  37. //
  38. ///////////////////////////////////////////////////////////////////////////////
  39. #include <windows.h>
  40. #include <string.h>
  41. #include <ctype.h>
  42. #include "tscroll.h"
  43. #include "tncon.h"
  44. #include "tconsole.h"
  45. #include "tnconfig.h"
  46. enum {
  47. HEX,
  48. DUMP,
  49. DUMPB,
  50. TEXTB,
  51. };
  52. int DummyStripBuffer(char *start, char *end, int width) {return 0;}
  53. TScroller::TScroller(TMouse &M, int size) : Mouse(M) {
  54. iScrollSize = size;
  55. pcScrollData = new char[iScrollSize];
  56. iScrollEnd = 0;
  57. iPastEnd = 0;
  58. memset(pcScrollData, ' ', iScrollSize);
  59. if(stricmp(ini.get_scroll_mode(), "hex") == 0) iDisplay = HEX;
  60. else if(stricmp(ini.get_scroll_mode(), "dump") == 0) iDisplay = DUMP;
  61. else if(stricmp(ini.get_scroll_mode(), "dumpb") == 0) iDisplay = DUMPB;
  62. else if(stricmp(ini.get_scroll_mode(), "text") == 0) iDisplay = TEXTB;
  63. else iDisplay = DUMP;
  64. strip = &DummyStripBuffer;
  65. }
  66. TScroller::~TScroller() {
  67. delete[] pcScrollData;
  68. }
  69. void TScroller::init(stripfunc *s) {
  70. strip = s;
  71. }
  72. // Fixed update of circular buffer (Paul Brannan 12/4/98)
  73. // Note: iScrollEnd is one character beyond the end
  74. void TScroller::update(const char *pszHead, const char *pszTail) {
  75. if ((iScrollEnd)+(pszTail-pszHead) < iScrollSize) {
  76. memcpy(&pcScrollData[iScrollEnd], pszHead, pszTail-pszHead);
  77. } else if (pszTail-pszHead > iScrollSize) {
  78. memcpy(pcScrollData, pszTail-iScrollSize, iScrollSize);
  79. iScrollEnd = 0;
  80. } else {
  81. memcpy(&pcScrollData[iScrollEnd], pszHead, iScrollSize-iScrollEnd);
  82. memcpy(&pcScrollData[0], pszHead + (iScrollSize-iScrollEnd),
  83. pszTail-pszHead-(iScrollSize-iScrollEnd));
  84. }
  85. // This could probably be optimized better, but it's probably not worth it
  86. int temp = iScrollEnd;
  87. iScrollEnd = ((iScrollEnd)+(pszTail-pszHead))%iScrollSize;
  88. if(iScrollEnd < temp) iPastEnd = 1;
  89. }
  90. // Perhaps this should be moved to Tconsole.cpp? (Paul Brannan 6/12/98)
  91. static BOOL WriteConsoleOutputCharAndAttribute(
  92. HANDLE  hConsoleOutput, // handle of a console screen buffer
  93. CHAR * lpWriteBuffer,
  94. WORD wAttrib,
  95. SHORT sX,
  96. SHORT sY ){
  97. // we ought to allocate memory before writing to an address (PB 5/12/98)
  98. DWORD cWritten;
  99. const LPDWORD lpcWritten = &cWritten;
  100. DWORD  cWriteCells = strlen(lpWriteBuffer);
  101. COORD  coordWrite = {sX,sY};
  102. LPWORD lpwAttribute = new WORD[cWriteCells];
  103. for (unsigned int i = 0; i < cWriteCells; i++)
  104. lpwAttribute[i] = wAttrib;
  105. WriteConsoleOutputAttribute(
  106. hConsoleOutput, // handle of a console screen buffer
  107. lpwAttribute, // address of buffer to write attributes from
  108. cWriteCells, // number of character cells to write to
  109. coordWrite, // coordinates of first cell to write to
  110. lpcWritten // address of number of cells written to
  111. );
  112. WriteConsoleOutputCharacter(
  113. hConsoleOutput, // handle of a console screen buffer
  114. lpWriteBuffer, // address of buffer to write characters from
  115. cWriteCells, // number of character cells to write to
  116. coordWrite, // coordinates of first cell to write to
  117. lpcWritten // address of number of cells written to
  118. );
  119. delete [] lpwAttribute;
  120. return 1;
  121. }
  122. static void hexify(int x, char *str, int len) {
  123. for(int j = len - 1; j >= 0; j--) {
  124. str[j] = x % 16;
  125. if(str[j] > 9) str[j] += 'A' - 10;
  126. else str[j] += '0';
  127. x /= 16;
  128. }
  129. }
  130. static int setmaxlines(int iDisplay, int iScrollSize, int strippedlines,
  131. int con_width) {
  132. switch(iDisplay) {
  133. case HEX: return(iScrollSize / 16); break;
  134. case DUMP: 
  135. case DUMPB: return(iScrollSize / con_width); break;
  136. case TEXTB: return(strippedlines); break;
  137. }
  138. return 0;
  139. }
  140. static void setstatusline(char *szStatusLine, int len, int iDisplay) {
  141. memset(szStatusLine, ' ', len);
  142. memcpy(&szStatusLine[1], "Scrollback Mode", 15);
  143. switch(iDisplay) {
  144. case HEX: memcpy(&szStatusLine[len / 2 - 1], "HEX", 3); break;
  145. case DUMP: memcpy(&szStatusLine[len / 2 - 2], "DUMP", 4); break;
  146. case DUMPB: memcpy(&szStatusLine[len / 2 - 5], "BINARY DUMP", 11); break;
  147. case TEXTB: memcpy(&szStatusLine[len / 2 - 2], "TEXT", 4); break;
  148. }
  149. memcpy(&szStatusLine[len - 6], "READY", 5);
  150. szStatusLine[len] = 0;
  151. }
  152. void TScroller::ScrollBack(){
  153. char p;
  154. int r,c;
  155. // define colors (Paul Brannan 7/5/98)
  156. int normal = (ini.get_scroll_bg() << 4) | ini.get_scroll_fg();
  157. // int inverse = (ini.get_scroll_fg() << 4) | ini.get_scroll_bg();
  158. int status = (ini.get_status_bg() << 4) | ini.get_status_fg();
  159. CHAR_INFO* chiBuffer;
  160. chiBuffer = newBuffer();
  161. saveScreen(chiBuffer);
  162. HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
  163. CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo;
  164. GetConsoleScreenBufferInfo(hStdout, &ConsoleInfo);
  165. // Update iScrollBegin -- necessary in case the buffer isn't full yet
  166. long iScrollBegin, iScrollLast;
  167. if(iPastEnd == 0) {
  168. iScrollBegin = 0;
  169. iScrollLast = iScrollEnd - 1;
  170. } else {
  171. iScrollBegin = iScrollEnd;
  172. iScrollLast = iScrollSize - 1;
  173. }
  174. // Create buffer with ANSI codes stripped
  175. // Fixed this to work properly with a circular buffer (PB 12/4/98)
  176. char *stripped = new char[iScrollSize];
  177. memcpy(stripped, pcScrollData + iScrollBegin, iScrollSize - 
  178. iScrollBegin);
  179. if(iScrollBegin != 0) memcpy(stripped + (iScrollSize - iScrollBegin),
  180. pcScrollData, iScrollBegin - 1);
  181. int strippedlines = (*strip)(stripped, stripped + iScrollLast,
  182. CON_COLS);
  183. // Calculate the last line of the scroll buffer (Paul Brannan 12/4/98)
  184. int maxlines = setmaxlines(iDisplay, iScrollLast + 1, strippedlines,
  185. CON_COLS);
  186. // init scroll position
  187. int current = maxlines - CON_HEIGHT + 1;
  188. if(current < 0) current = 0;
  189. // paint border and info
  190.     // paint last two lines black on white
  191.     char * szStatusLine;
  192.     szStatusLine = new char[CON_WIDTH+2];
  193. setstatusline(szStatusLine, CON_COLS, iDisplay);
  194.     WriteConsoleOutputCharAndAttribute(hStdout, szStatusLine, status,
  195. CON_LEFT, CON_BOTTOM);
  196. // loop while not done
  197. BOOL done = FALSE;
  198. while (!done){
  199. switch (iDisplay){
  200. case HEX:
  201. memset(szStatusLine, ' ', CON_COLS);
  202. szStatusLine[8] = ':';
  203. szStatusLine[34] = '-';
  204.             for (r = 0; r < CON_HEIGHT; r++) {
  205. hexify((r + current) * 16, &szStatusLine[2], 6);
  206. for (c = 0; c < 16; c++){
  207. if (c+(16*(r+current)) >= iScrollLast)
  208. p = 0;
  209. else
  210. p = pcScrollData[(c+16*(r+current) + iScrollBegin) %
  211. iScrollSize];
  212. hexify((char)p, &szStatusLine[11 + 3*c], 2);
  213. if (!iscntrl(p)) {
  214. szStatusLine[60 + c] = (char)p;
  215. } else {
  216. szStatusLine[60 + c] = '.';
  217. }
  218. }
  219. for(int j = 0; j < 16; j++) {
  220. }
  221. szStatusLine[CON_COLS] = '';
  222. WriteConsoleOutputCharAndAttribute(hStdout, szStatusLine,
  223. normal, CON_LEFT, r+CON_TOP);
  224.             }
  225.             break;
  226. case DUMP:
  227.             for (r = 0; r < CON_HEIGHT; r++) {
  228. for (c = 0; c <= CON_WIDTH; c++) {
  229. if (c+((CON_COLS)*(r+current)) >= iScrollLast) p = ' ';
  230. else p = pcScrollData[(c+((CON_COLS)*(r+current))
  231. + iScrollBegin) % iScrollSize];
  232. if (!iscntrl(p))
  233. szStatusLine[c] = p;
  234. else
  235. szStatusLine[c] = '.';
  236. }
  237. szStatusLine[c] = '';
  238. WriteConsoleOutputCharAndAttribute(hStdout, szStatusLine,
  239. normal, CON_LEFT, r+CON_TOP);
  240.             }
  241.             break;
  242. case DUMPB:
  243. for (r = 0; r < CON_HEIGHT; r++) {
  244. for (c = 0; c <= CON_WIDTH; c++) {
  245. if (c+((CON_COLS)*(r+current)) >= iScrollLast) p = ' ';
  246. else p = pcScrollData[  (c+((CON_COLS)*(r+current))
  247. + iScrollBegin) % iScrollSize];
  248. if (p != 0)
  249. szStatusLine[c] = p;
  250. else
  251. szStatusLine[c] = ' ';
  252. }
  253. szStatusLine[c] = '';
  254. WriteConsoleOutputCharAndAttribute(hStdout, szStatusLine,
  255. normal, CON_LEFT, r+CON_TOP);
  256.             }
  257.             break;
  258. case TEXTB: {
  259. int ch, lines, x;
  260. // Find the starting position
  261. for(ch = 0, lines = 0, x = 1; ch < iScrollSize &&
  262. lines < current; ch++, x++) {
  263. if(stripped[ch] == 'n') lines++;
  264. if(stripped[ch] == 'r') x = 1;
  265. }
  266. for (r = 0; r < CON_HEIGHT; r++) {
  267. memset(szStatusLine, ' ', CON_COLS);
  268. for(c = 0; c <= CON_WIDTH; c++) {
  269. int done = FALSE;
  270. if (ch >= iScrollSize) p = ' ';
  271. else p = stripped[ch];
  272. switch(p) {
  273. case 10: done = TRUE; break;
  274. case 13: c = 0; break;
  275. default: szStatusLine[c] = p;
  276. }
  277. ch++;
  278. if(done) break;
  279. }
  280. szStatusLine[CON_COLS] = '';
  281. WriteConsoleOutputCharAndAttribute(hStdout, szStatusLine,
  282. normal, CON_LEFT, r+CON_TOP);
  283. }
  284. }
  285.             break;
  286. }
  287. setstatusline(szStatusLine, CON_COLS, iDisplay);
  288. WriteConsoleOutputCharAndAttribute(hStdout, szStatusLine, status,
  289. CON_LEFT, CON_BOTTOM);
  290. // paint scroll back data
  291. // get key input
  292. switch(scrollkeys()){
  293. case VK_ESCAPE:
  294. done = TRUE;
  295. break;
  296. case VK_PRIOR:
  297. if ( current > CON_HEIGHT)
  298. current-= CON_HEIGHT;
  299. else
  300. current = 0;
  301. break;
  302. case VK_NEXT:
  303. if ( current < maxlines - 2*CON_HEIGHT + 2)
  304. current += CON_HEIGHT;
  305. else
  306. current = maxlines - CON_HEIGHT + 1;
  307. break;
  308. case VK_DOWN:
  309. if (current <= maxlines - CON_HEIGHT) current++;
  310. break;
  311. case VK_UP:
  312. if ( current > 0) current--;
  313. break;
  314. case VK_TAB:
  315. iDisplay = (iDisplay+1)%4;
  316. maxlines = setmaxlines(iDisplay, iScrollLast + 1, strippedlines,
  317. CON_COLS);
  318. if(current > maxlines) current = maxlines - 1;
  319. if(current < 0) current = 0;
  320. break;
  321. case VK_END:
  322. current = maxlines - CON_HEIGHT + 1;
  323. if(current < 0) current = 0;
  324. break;
  325. case VK_HOME:
  326. current = 0;
  327. break;
  328. case SC_MOUSE:
  329. Mouse.scrollMouse();
  330. break;
  331. }
  332. }
  333. // Clean up
  334. restoreScreen(chiBuffer);
  335. delete[] szStatusLine;
  336. delete[] chiBuffer;
  337. delete[] stripped;
  338. }