Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

570 lines
18 KiB

  1. /*
  2. * Copyright (c) Microsoft Corporation
  3. *
  4. * Module Name :
  5. * parser.c
  6. *
  7. * This is the file containing the client code for parsing vt100 escape sequences
  8. * into console mode output.
  9. *
  10. *
  11. * Sadagopan Rajaram -- Nov 3, 1999
  12. *
  13. */
  14. #include "tcclnt.h"
  15. CHAR FinalCharacters[] = "mHJKr";
  16. HANDLE hConsoleOutput;
  17. BOOLEAN InEscape=FALSE;
  18. BOOLEAN lastCharM = FALSE;
  19. CHAR EscapeBuffer[MAX_TERMINAL_WIDTH];
  20. int index=0;
  21. SHORT ScrollTop = 0;
  22. SHORT ScrollBottom = MAX_TERMINAL_HEIGHT -1;
  23. #ifdef UNICODE
  24. int DBCSIndex = 0;
  25. CHAR DBCSArray[MB_CUR_MAX+1];
  26. #endif
  27. VOID (*AttributeFunction)(PCHAR, int);
  28. VOID
  29. PrintChar(
  30. CHAR c
  31. )
  32. {
  33. // A boolean variable to check if we are processing an escape sequence
  34. if(c == '\033'){
  35. InEscape = TRUE;
  36. EscapeBuffer[0] = c;
  37. index = 1;
  38. return;
  39. }
  40. if(InEscape == TRUE){
  41. if(index == MAX_TERMINAL_WIDTH){
  42. // vague escape sequence,give up processing
  43. InEscape = FALSE;
  44. index=0;
  45. return;
  46. }
  47. EscapeBuffer[index]=c;
  48. index++;
  49. if(FinalCharacter(c)){
  50. if(c=='m'){
  51. // maybe getting \017
  52. lastCharM = TRUE;
  53. }
  54. ProcessEscapeSequence(EscapeBuffer, index);
  55. InEscape = FALSE;
  56. index=0;
  57. }
  58. return;
  59. }
  60. if(lastCharM && c == '\017'){
  61. lastCharM = FALSE;
  62. return;
  63. }
  64. OutputConsole(c);
  65. return;
  66. }
  67. BOOLEAN
  68. FinalCharacter(
  69. CHAR c
  70. )
  71. {
  72. if(strchr(FinalCharacters,c)){
  73. return TRUE;
  74. }
  75. return FALSE;
  76. }
  77. VOID
  78. ProcessEscapeSequence(
  79. PCHAR Buffer,
  80. int length
  81. )
  82. {
  83. // BUGBUG - Function too big, can optimize code size by having
  84. // an action variable which is initialized when the strings are
  85. // compared, so that cut and paste code can be eliminated.
  86. CONSOLE_SCREEN_BUFFER_INFO csbInfo;
  87. ULONG charsToWrite;
  88. ULONG charsWritten;
  89. PCHAR pTemp;
  90. int RetVal;
  91. if (length == 3) {
  92. // One of the home cursor or clear to end of display
  93. if (strncmp(Buffer,"\033[H",length)==0) {
  94. // Home the cursor
  95. csbInfo.dwCursorPosition.X = 0;
  96. csbInfo.dwCursorPosition.Y = 0;
  97. SetConsoleCursorPosition(hConsoleOutput,
  98. csbInfo.dwCursorPosition
  99. );
  100. return;
  101. }
  102. if(strncmp(Buffer,"\033[J", length) == 0){
  103. // clear to end of display assuming 80 X 24 size
  104. RetVal = GetConsoleScreenBufferInfo(hConsoleOutput,
  105. &csbInfo
  106. );
  107. if (RetVal == FALSE) {
  108. return;
  109. }
  110. SetConsoleMode(hConsoleOutput,
  111. ENABLE_WRAP_AT_EOL_OUTPUT|ENABLE_PROCESSED_OUTPUT
  112. );
  113. charsToWrite = (MAX_TERMINAL_HEIGHT -
  114. csbInfo.dwCursorPosition.Y)*MAX_TERMINAL_WIDTH -
  115. csbInfo.dwCursorPosition.X;
  116. RetVal = FillConsoleOutputAttribute(hConsoleOutput,
  117. csbInfo.wAttributes,
  118. charsToWrite,
  119. csbInfo.dwCursorPosition,
  120. &charsWritten
  121. );
  122. RetVal = FillConsoleOutputCharacter(hConsoleOutput,
  123. 0,
  124. charsToWrite,
  125. csbInfo.dwCursorPosition,
  126. &charsWritten
  127. );
  128. SetConsoleMode(hConsoleOutput,
  129. ENABLE_PROCESSED_OUTPUT
  130. );
  131. SetConsoleCursorPosition(hConsoleOutput,
  132. csbInfo.dwCursorPosition
  133. );
  134. return;
  135. }
  136. if(strncmp(Buffer,"\033[K", length) == 0){
  137. // clear to end of line assuming 80 X 24 size
  138. RetVal = GetConsoleScreenBufferInfo(hConsoleOutput,
  139. &csbInfo
  140. );
  141. if (RetVal == FALSE) {
  142. return;
  143. }
  144. charsToWrite = (MAX_TERMINAL_WIDTH - csbInfo.dwCursorPosition.X);
  145. RetVal = FillConsoleOutputAttribute(hConsoleOutput,
  146. csbInfo.wAttributes,
  147. charsToWrite,
  148. csbInfo.dwCursorPosition,
  149. &charsWritten
  150. );
  151. RetVal = FillConsoleOutputCharacter(hConsoleOutput,
  152. 0,
  153. charsToWrite,
  154. csbInfo.dwCursorPosition,
  155. &charsWritten
  156. );
  157. SetConsoleCursorPosition(hConsoleOutput,
  158. csbInfo.dwCursorPosition
  159. );
  160. return;
  161. }
  162. if (strncmp(Buffer,"\033[r", length) == 0) {
  163. ScrollTop = 0;
  164. ScrollBottom = MAX_TERMINAL_HEIGHT -1;
  165. }
  166. }
  167. if (length == 4) {
  168. // One of the home cursor or clear to end of display
  169. if (strncmp(Buffer,"\033[0H",length)==0) {
  170. // Home the cursor
  171. csbInfo.dwCursorPosition.X = 0;
  172. csbInfo.dwCursorPosition.Y = 0;
  173. SetConsoleCursorPosition(hConsoleOutput,
  174. csbInfo.dwCursorPosition
  175. );
  176. return;
  177. }
  178. if(strncmp(Buffer,"\033[2J",length) == 0){
  179. // Home the cursor
  180. csbInfo.dwCursorPosition.X = 0;
  181. csbInfo.dwCursorPosition.Y = 0;
  182. SetConsoleCursorPosition(hConsoleOutput,
  183. csbInfo.dwCursorPosition
  184. );
  185. sprintf(Buffer, "\033[0J");
  186. }
  187. if(strncmp(Buffer,"\033[0J", length) == 0){
  188. // clear to end of display assuming 80 X 24 size
  189. RetVal = GetConsoleScreenBufferInfo(hConsoleOutput,
  190. &csbInfo
  191. );
  192. if (RetVal == FALSE) {
  193. return;
  194. }
  195. SetConsoleMode(hConsoleOutput,
  196. ENABLE_WRAP_AT_EOL_OUTPUT|ENABLE_PROCESSED_OUTPUT
  197. );
  198. charsToWrite = (MAX_TERMINAL_HEIGHT -
  199. csbInfo.dwCursorPosition.Y)*MAX_TERMINAL_WIDTH -
  200. csbInfo.dwCursorPosition.X;
  201. RetVal = FillConsoleOutputAttribute(hConsoleOutput,
  202. csbInfo.wAttributes,
  203. charsToWrite,
  204. csbInfo.dwCursorPosition,
  205. &charsWritten
  206. );
  207. RetVal = FillConsoleOutputCharacter(hConsoleOutput,
  208. 0,
  209. charsToWrite,
  210. csbInfo.dwCursorPosition,
  211. &charsWritten
  212. );
  213. SetConsoleMode(hConsoleOutput,
  214. ENABLE_PROCESSED_OUTPUT
  215. );
  216. SetConsoleCursorPosition(hConsoleOutput,
  217. csbInfo.dwCursorPosition
  218. );
  219. return;
  220. }
  221. if((strncmp(Buffer,"\033[0K", length) == 0) ||
  222. (strncmp(Buffer,"\033[2K",length) == 0)){
  223. // clear to end of line assuming 80 X 24 size
  224. RetVal = GetConsoleScreenBufferInfo(hConsoleOutput,
  225. &csbInfo
  226. );
  227. if (RetVal == FALSE) {
  228. return;
  229. }
  230. charsToWrite = (MAX_TERMINAL_WIDTH - csbInfo.dwCursorPosition.X);
  231. RetVal = FillConsoleOutputAttribute(hConsoleOutput,
  232. csbInfo.wAttributes,
  233. charsToWrite,
  234. csbInfo.dwCursorPosition,
  235. &charsWritten
  236. );
  237. RetVal = FillConsoleOutputCharacter(hConsoleOutput,
  238. 0,
  239. charsToWrite,
  240. csbInfo.dwCursorPosition,
  241. &charsWritten
  242. );
  243. SetConsoleCursorPosition(hConsoleOutput,
  244. csbInfo.dwCursorPosition
  245. );
  246. return;
  247. }
  248. if((strncmp(Buffer,"\033[0m", length) == 0)||
  249. (strncmp(Buffer,"\033[m\017", length) == 0)){
  250. // clear all attributes and set Text attributes to black on white
  251. SetConsoleTextAttribute(hConsoleOutput,
  252. FOREGROUND_RED |FOREGROUND_BLUE |FOREGROUND_GREEN
  253. );
  254. return;
  255. }
  256. }
  257. if(Buffer[length-1] == 'm'){
  258. //set the text attributes
  259. // clear all attributes and set Text attributes to white on black
  260. SetConsoleTextAttribute(hConsoleOutput,
  261. FOREGROUND_RED |FOREGROUND_BLUE |FOREGROUND_GREEN
  262. );
  263. AttributeFunction(Buffer, length);
  264. return;
  265. }
  266. if(Buffer[length -1] == 'H'){
  267. // Set cursor position
  268. if (sscanf(Buffer,"\033[%d;%d", &charsToWrite, &charsWritten) == 2) {
  269. csbInfo.dwCursorPosition.Y = (SHORT)(charsToWrite -1);
  270. csbInfo.dwCursorPosition.X = (SHORT)(charsWritten -1);
  271. SetConsoleCursorPosition(hConsoleOutput,
  272. csbInfo.dwCursorPosition
  273. );
  274. }
  275. return;
  276. }
  277. if(Buffer[length -1] == 'r'){
  278. // Set scroll region
  279. sscanf(Buffer,"\033[%d;%d", &charsToWrite,&charsWritten);
  280. if ((charsToWrite < 1)
  281. || (charsToWrite > MAX_TERMINAL_HEIGHT)
  282. || (charsWritten < charsToWrite)) {
  283. return;
  284. }
  285. ScrollTop = (SHORT)(charsToWrite -1);
  286. ScrollBottom = (SHORT)(charsWritten -1);
  287. }
  288. return;
  289. }
  290. VOID
  291. ProcessTextAttributes(
  292. PCHAR Buffer,
  293. int length
  294. )
  295. {
  296. PCHAR CurrLoc = Buffer;
  297. ULONG Attribute;
  298. WORD TextAttribute = 0;
  299. BOOLEAN Reverse = FALSE;
  300. PCHAR pTemp;
  301. while(*CurrLoc != 'm'){
  302. if((*CurrLoc < '0') || (*CurrLoc >'9' )){
  303. CurrLoc ++;
  304. }else{
  305. if (sscanf(CurrLoc,"%d", &Attribute) != 1) {
  306. return;
  307. }
  308. switch(Attribute){
  309. case 1:
  310. TextAttribute = TextAttribute | FOREGROUND_INTENSITY;
  311. break;
  312. case 37:
  313. TextAttribute = TextAttribute|FOREGROUND_RED |FOREGROUND_BLUE |FOREGROUND_GREEN;
  314. break;
  315. case 47:
  316. TextAttribute = TextAttribute|BACKGROUND_RED |BACKGROUND_BLUE |BACKGROUND_GREEN;
  317. break;
  318. case 34:
  319. TextAttribute = TextAttribute|FOREGROUND_BLUE;
  320. break;
  321. case 44:
  322. TextAttribute = TextAttribute|BACKGROUND_BLUE;
  323. break;
  324. case 31:
  325. TextAttribute = TextAttribute|FOREGROUND_RED;
  326. break;
  327. case 41:
  328. TextAttribute = TextAttribute|BACKGROUND_RED;
  329. break;
  330. case 33:
  331. TextAttribute = TextAttribute|FOREGROUND_GREEN|FOREGROUND_BLUE;
  332. break;
  333. case 43:
  334. TextAttribute = TextAttribute|BACKGROUND_GREEN|BACKGROUND_BLUE;
  335. break;
  336. case 7:
  337. // Reverse the background and foreground colors
  338. Reverse=TRUE;
  339. default:
  340. break;
  341. }
  342. pTemp = strchr(CurrLoc, ';');
  343. if(pTemp == NULL){
  344. pTemp = strchr(CurrLoc, 'm');
  345. }
  346. if(pTemp == NULL) {
  347. break;
  348. }
  349. CurrLoc = pTemp;
  350. }
  351. }
  352. if (Reverse) {
  353. if ((!TextAttribute) ||
  354. (TextAttribute == FOREGROUND_INTENSITY)) {
  355. // Reverse vt100 escape sequence.
  356. TextAttribute = TextAttribute |
  357. BACKGROUND_RED |BACKGROUND_BLUE |BACKGROUND_GREEN;
  358. }
  359. }
  360. if(TextAttribute){
  361. SetConsoleTextAttribute(hConsoleOutput,
  362. TextAttribute
  363. );
  364. }
  365. return;
  366. }
  367. VOID
  368. vt100Attributes(
  369. PCHAR Buffer,
  370. int length
  371. )
  372. {
  373. PCHAR CurrLoc = Buffer;
  374. ULONG Attribute;
  375. WORD TextAttribute = 0;
  376. PCHAR pTemp;
  377. while(*CurrLoc != 'm'){
  378. if((*CurrLoc < '0') || (*CurrLoc >'9' )){
  379. CurrLoc ++;
  380. }else{
  381. if (sscanf(CurrLoc,"%d", &Attribute) != 1) {
  382. return;
  383. }
  384. switch(Attribute){
  385. case 1:
  386. TextAttribute = TextAttribute | FOREGROUND_INTENSITY;
  387. break;
  388. case 5:
  389. TextAttribute = TextAttribute | BACKGROUND_INTENSITY;
  390. break;
  391. case 7:
  392. TextAttribute = TextAttribute |
  393. BACKGROUND_RED |BACKGROUND_BLUE |BACKGROUND_GREEN;
  394. break;
  395. default:
  396. break;
  397. }
  398. pTemp = strchr(CurrLoc, ';');
  399. if(pTemp == NULL){
  400. pTemp = strchr(CurrLoc, 'm');
  401. }
  402. if(pTemp == NULL) {
  403. break;
  404. }
  405. CurrLoc = pTemp;
  406. }
  407. }
  408. if(TextAttribute){
  409. SetConsoleTextAttribute(hConsoleOutput,
  410. TextAttribute
  411. );
  412. }
  413. return;
  414. }
  415. VOID
  416. OutputConsole(
  417. CHAR byte
  418. )
  419. {
  420. CONSOLE_SCREEN_BUFFER_INFO csbInfo;
  421. COORD dwBufferCoord;
  422. SMALL_RECT sRect;
  423. BOOL RetVal;
  424. TCHAR Char;
  425. SHORT ypos;
  426. CHAR_INFO Fill;
  427. DWORD charsWritten;
  428. if (byte == '\n'){
  429. RetVal = GetConsoleScreenBufferInfo(hConsoleOutput,
  430. &csbInfo
  431. );
  432. if (RetVal == FALSE) {
  433. return;
  434. }
  435. ypos = csbInfo.dwCursorPosition.Y;
  436. if ((ypos == ScrollBottom ) || (ypos == MAX_TERMINAL_HEIGHT -1 )) {
  437. // Do the scrolling
  438. dwBufferCoord.X = 0;
  439. dwBufferCoord.Y = ScrollBottom;
  440. Fill.Char.UnicodeChar = (WCHAR) 0;
  441. Fill.Attributes = FOREGROUND_RED |FOREGROUND_BLUE |FOREGROUND_GREEN;
  442. if ((ypos == ScrollBottom)
  443. && (ScrollTop != ScrollBottom)) {
  444. sRect.Left = 0;
  445. sRect.Top = ScrollTop + 1;
  446. sRect.Right = MAX_TERMINAL_WIDTH-1;
  447. sRect.Bottom = ScrollBottom;
  448. dwBufferCoord.Y = ScrollTop;
  449. dwBufferCoord.X = 0;
  450. RetVal = ScrollConsoleScreenBuffer(hConsoleOutput,
  451. &sRect,
  452. NULL,
  453. dwBufferCoord,
  454. &Fill
  455. );
  456. dwBufferCoord.Y = ScrollBottom;
  457. } else {
  458. if (ypos == MAX_TERMINAL_HEIGHT -1){
  459. sRect.Left = 0;
  460. sRect.Top = 1;
  461. sRect.Right = MAX_TERMINAL_WIDTH-1;
  462. sRect.Bottom = MAX_TERMINAL_HEIGHT - 1;
  463. dwBufferCoord.Y = 0;
  464. dwBufferCoord.X = 0;
  465. RetVal = ScrollConsoleScreenBuffer(hConsoleOutput,
  466. &sRect,
  467. NULL,
  468. dwBufferCoord,
  469. &Fill
  470. );
  471. dwBufferCoord.Y = MAX_TERMINAL_HEIGHT -1;
  472. }
  473. }
  474. RetVal = FillConsoleOutputCharacter(hConsoleOutput,
  475. (TCHAR) 0,
  476. MAX_TERMINAL_WIDTH,
  477. dwBufferCoord,
  478. &charsWritten
  479. );
  480. return;
  481. } else {
  482. csbInfo.dwCursorPosition.Y = ypos + 1;
  483. SetConsoleCursorPosition(hConsoleOutput,
  484. csbInfo.dwCursorPosition
  485. );
  486. }
  487. return;
  488. }
  489. if (byte == '\r'){
  490. RetVal = GetConsoleScreenBufferInfo(hConsoleOutput,
  491. &csbInfo
  492. );
  493. if (RetVal == FALSE) {
  494. return;
  495. }
  496. csbInfo.dwCursorPosition.X = 0;
  497. SetConsoleCursorPosition(hConsoleOutput,
  498. csbInfo.dwCursorPosition
  499. );
  500. return;
  501. }
  502. Char = (TCHAR) byte;
  503. #ifdef UNICODE
  504. DBCSArray[DBCSIndex] = byte;
  505. if(DBCSIndex ==0){
  506. if(isleadbyte(byte)){
  507. DBCSIndex ++;
  508. return;
  509. }
  510. }
  511. else{
  512. mbtowc(&Char, DBCSArray, 2);
  513. DBCSIndex = 0;
  514. }
  515. #endif
  516. _tprintf(_T("%c"),Char);
  517. return;
  518. }