ReactOS  0.4.13-dev-544-gede3fdd
Console.cpp
Go to the documentation of this file.
1 /*
2  * regexpl - Console Registry Explorer
3  *
4  * Copyright (C) 2000-2005 Nedko Arnaudov <nedko@users.sourceforge.net>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; see the file COPYING. If not, write to
18  * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21 
22 // Console.cpp: implementation of the CConsole class.
23 //
25 
26 #include "ph.h"
27 #include "Console.h"
28 
29 #define TAB_WIDTH 8
30 #define MORE_STRING _T("-- Press space to view more. Press q or Ctrl+break to cancel.--")
31 #define MORE_EMPTY_STRING _T(" ")
32 
33 /*
34 TCHAR * _tcsnchr(const TCHAR *string, TCHAR ch, int count)
35 {
36  while (count--)
37  {
38  if (*string == 0) return NULL;
39  if (*string == ch) return const_cast <char *>(string);
40  string++;
41  }
42  return NULL;
43 }*/
44 
45 
47 // Construction/Destruction
49 
51 {
54  m_blnInsetMode = TRUE; // Insert
55 // m_blnInsetMode = FALSE; // Overwrite
58 // m_Lines = 0;
59  m_pchBuffer = NULL;
64  m_dwOldInputMode = 0;
68 }
69 
71 {
72  if (m_pchBuffer)
73  delete[] m_pchBuffer;
74  if (m_pchBuffer1)
75  delete[] m_pchBuffer1;
76  if (m_pchBuffer2)
77  delete[] m_pchBuffer2;
78 
83 
88 }
89 
90 BOOL CConsole::Write(const TCHAR *p, DWORD dwChars)
91 {
93  return FALSE;
95  return FALSE;
96  if (p == NULL)
97  {
98  ASSERT(FALSE);
99  return FALSE;
100  }
101  DWORD dwCharsToWrite = (dwChars)?dwChars:_tcslen(p);
102  DWORD dwCharsWrittenAdd = 0;
103  BOOL ret = TRUE;
104  while (dwCharsToWrite && (!m_blnDisableWrite))
105  {
106  switch(p[dwCharsWrittenAdd])
107  {
108  case _T('\n'):
110  m_CursorPosition.X = 0;
111  break;
112  case _T('\r'):
113  dwCharsWrittenAdd++;
114  dwCharsToWrite--;
115  continue;
116  case _T('\t'):
117  do
118  {
119  if (!Write(_T(" "))) return FALSE;
120  }
121  while ((m_CursorPosition.X % TAB_WIDTH) && (!m_blnDisableWrite));
122  dwCharsWrittenAdd++;
123  dwCharsToWrite--;
124  continue;
125  default:
126  {
127  if (!WriteChar(p[dwCharsWrittenAdd])) return FALSE;
129  }
130  }
132  {
134  m_CursorPosition.X = 0;
135  }
137  {
138  ASSERT(m_CursorPosition.X == 0);
139  SMALL_RECT Src;
140  Src.Left = 0;
141  Src.Right = (SHORT)(m_BufferSize.X-1);
142  Src.Top = 1;
143  Src.Bottom = (SHORT)(m_BufferSize.Y-1);
144  CHAR_INFO ci;
145 #ifdef UNICODE
146  ci.Char.UnicodeChar = L' ';
147 #else
148  ci.Char.AsciiChar = ' ';
149 #endif
150  ci.Attributes = 0;
151  COORD Dest;
152  Dest.X = 0;
153  Dest.Y = 0;
154  if (!ScrollConsoleScreenBuffer(m_hStdOut,&Src,NULL,Dest,&ci)) return FALSE;
156  m_LinesScrolled++;
157  }
159  VERIFY(WriteChar(_T(' ')));
160  if ((m_blnMoreMode)&&(m_CursorPosition.X == 0))
161  {
162  m_Lines++;
163  if (m_Lines >= m_BufferSize.Y-1)
164  {
166  m_Lines = 0;
169 
171  cci.bVisible = FALSE;
172  cci.dwSize = 100;
174 
175  INPUT_RECORD InputRecord;
176  DWORD dwRecordsReaded;
177  while ((ret = ReadConsoleInput(m_hStdIn,&InputRecord,1,&dwRecordsReaded)) != FALSE)
178  {
179  ASSERT(dwRecordsReaded == 1);
180  if (dwRecordsReaded != 1)
181  break;
182  if (InputRecord.EventType != KEY_EVENT)
183  continue;
184  if (!InputRecord.Event.KeyEvent.bKeyDown)
185  continue;
186 
187  if ((InputRecord.Event.KeyEvent.wVirtualKeyCode == VK_CANCEL)||
188  (InputRecord.Event.KeyEvent.wVirtualKeyCode == _T('Q')))
189  {
191  continue;
192  }
193 #ifdef UNICODE
194  TCHAR ch = InputRecord.Event.KeyEvent.uChar.UnicodeChar;
195 #else
196  TCHAR ch = InputRecord.Event.KeyEvent.uChar.AsciiChar;
197 #endif
198  if (ch)
199  break;
200  }
201 
202  // delete "more" msg
204  m_CursorPosition.X = 0;
205 
206  cci.bVisible = TRUE;
209  }
210  }
211  dwCharsWrittenAdd++;
212  dwCharsToWrite--;
213  }
214  return ret;
215 }
216 
217 unsigned int CConsole::GetTabWidth()
218 {
219  return TAB_WIDTH;
220 }
221 
223 {
224  return SetConsoleTitle(p);
225 }
226 
228 {
229  m_wAttributes = wAttributes;
230  return TRUE;
231 }
232 /*
233 BOOL CConsole::SetInputMode(DWORD dwMode)
234 {
235  return SetConsoleMode(m_hStdIn,dwMode);
236 }
237 
238 BOOL CConsole::SetOutputMode(DWORD dwMode)
239 {
240  return SetConsoleMode(m_hStdOut,dwMode);
241 }*/
242 
244 {
245  if (m_hStdIn == INVALID_HANDLE_VALUE) return FALSE;
247 }
248 
250 {
251  if (m_hStdIn == INVALID_HANDLE_VALUE) return FALSE;
252  if (m_hStdOut == INVALID_HANDLE_VALUE) return FALSE;
253  if (m_dwBufferSize == 0)
254  {
255  ASSERT(FALSE);
256  return FALSE;
257  }
258  if (m_pchBuffer == NULL)
259  {
260  ASSERT(FALSE);
261  return FALSE;
262  }
263  if (m_pchBuffer1 == NULL)
264  {
265  ASSERT(FALSE);
266  return FALSE;
267  }
268  if (!FlushConsoleInputBuffer(m_hStdIn)) return FALSE;
269 
270  COORD FristCharCursorPosition = m_CursorPosition;
271 #define X_CURSOR_POSITION_FROM_OFFSET(ofs) USHORT(((FristCharCursorPosition.X + ofs)%m_BufferSize.X))
272 #define Y_CURSOR_POSITION_FROM_OFFSET(ofs) USHORT((FristCharCursorPosition.Y + (FristCharCursorPosition.X + ofs)/m_BufferSize.X))
273 //#define OFFSET_FROM_CURSOR_POSITION(pos) ((pos.Y-FristCharCursorPosition.Y)*m_BufferSize.X+pos.X-FristCharCursorPosition.X)
274 
275  DWORD dwRecordsReaded;
276  DWORD dwCurrentCharOffset = 0;
277  DWORD dwLastCharOffset = 0;
278  BOOL ret;
279 
280  BOOL blnCompletionMode = FALSE;
281 // unsigned __int64 nCompletionIndex = 0;
282  unsigned long long nCompletionIndex = 0;
283  DWORD dwCompletionOffset = 0;
284  DWORD dwCompletionStringSize = 0;
285  COORD CompletionPosition = FristCharCursorPosition;
286 
287  m_LinesScrolled = 0;
288  BOOL blnOldMoreMode = m_blnMoreMode;
290 
291  DWORD dwHistoryIndex = 0;
292 
293  INPUT_RECORD InputRecord;
294  while ((ret = ReadConsoleInput(m_hStdIn,&InputRecord,1,&dwRecordsReaded)) != FALSE)
295  {
296  ASSERT(dwRecordsReaded == 1);
297  if (dwRecordsReaded != 1) return FALSE;
298  if (InputRecord.EventType != KEY_EVENT) continue;
299  if (!InputRecord.Event.KeyEvent.bKeyDown) continue;
300 #ifdef UNICODE
301  TCHAR ch = InputRecord.Event.KeyEvent.uChar.UnicodeChar;
302 #else
303  TCHAR ch = InputRecord.Event.KeyEvent.uChar.AsciiChar;
304 #endif
305 KeyRepeat:
306  if (m_LinesScrolled)
307  {
308  if (m_LinesScrolled > FristCharCursorPosition.Y) return FALSE;
309  FristCharCursorPosition.Y = SHORT(FristCharCursorPosition.Y - m_LinesScrolled);
310  if (m_LinesScrolled > CompletionPosition.Y) return FALSE;
311  CompletionPosition.Y = SHORT(CompletionPosition.Y - m_LinesScrolled);
312  m_LinesScrolled = 0;
313  }
314 // char Buf[1024];
315 // sprintf(Buf,"wVirtualKeyCode = %u\nchar = %u\n\n",InputRecord.Event.KeyEvent.wVirtualKeyCode,ch);
316 // OutputDebugString(Buf);
317 
318 #ifndef NO_PASTE
319  if ((ch == 0x16)&&(InputRecord.Event.KeyEvent.wVirtualKeyCode == 'V'))
320  {
321  goto Paste;
322  }
323  else
324 #endif
325  if (ch == 0)
326  {
327 #ifndef NO_PASTE
328  if (InputRecord.Event.KeyEvent.wVirtualKeyCode == VK_INSERT)
329  {
330  if (!(InputRecord.Event.KeyEvent.dwControlKeyState & SHIFT_PRESSED))
331  {
333  }
334  else
335  {
336  if (blnCompletionMode) blnCompletionMode = FALSE;
337 
338 Paste:
340 #ifdef UNICODE
342 #else
343  CF_TEXT
344 #endif
345  ))
346  continue;
347  if (!OpenClipboard(NULL))
348  continue;
349 
350  const TCHAR *pch = NULL;
351 
352  HANDLE hglb = GetClipboardData(
353 #ifdef UNICODE
355 #else
356  CF_TEXT
357 #endif
358  );
359  if (hglb != NULL)
360  {
361  LPTSTR lptstr = (LPTSTR)GlobalLock(hglb);
362  if (lptstr != NULL)
363  {
366  pch = m_pchBuffer1;
367  GlobalUnlock(hglb);
368  }
369  }
370  CloseClipboard();
371 
372  if (pch == NULL) continue;
373 
374  while (*pch)
375  {
376  if (_istprint(*pch))
377  {
378  if (dwLastCharOffset >= m_dwBufferSize-1)
379  {
380  ASSERT(dwLastCharOffset == m_dwBufferSize-1);
381  // Beep(1000,100);
382  break;
383  }
384  TCHAR ch1;
385  //if (m_blnInsetMode)
386  ch1 = m_pchBuffer[dwCurrentCharOffset];
387  m_pchBuffer[dwCurrentCharOffset] = *pch;
388  if ((m_blnInsetMode)||(dwCurrentCharOffset == dwLastCharOffset)) dwLastCharOffset++;
389  dwCurrentCharOffset++;
390  if (!Write(pch,1)) return FALSE;
391  if (m_blnInsetMode)
392  {
393  COORD Cursor = m_CursorPosition;
394  DWORD ofs = dwCurrentCharOffset;
395 
396  while(ofs <= dwLastCharOffset)
397  {
398  ch = m_pchBuffer[ofs];
399  m_pchBuffer[ofs] = ch1;
400  ch1 = ch;
401  ofs++;
402  }
403 
404  if (dwCurrentCharOffset < dwLastCharOffset)
405  {
406  if (!Write(m_pchBuffer+dwCurrentCharOffset,dwLastCharOffset-dwCurrentCharOffset)) return FALSE;
407 
408  if (m_LinesScrolled)
409  {
410  if (m_LinesScrolled > FristCharCursorPosition.Y) return FALSE;
411  Cursor.Y = SHORT(Cursor.Y - m_LinesScrolled);
412  }
413  // Update cursor position
414  m_CursorPosition = Cursor;
416  }
417  }
418  }
419  pch++;
420  }
421  }
422  }
423  else
424 #endif
425  if (InputRecord.Event.KeyEvent.wVirtualKeyCode == VK_LEFT)
426  {
427  if (blnCompletionMode) blnCompletionMode = FALSE;
428  if (dwCurrentCharOffset)
429  {
431  {
432  TCHAR *pchWordBegin = m_pchBuffer+dwCurrentCharOffset-1;
433 
434  while (pchWordBegin > m_pchBuffer)
435  {
436  if (!_istspace(*pchWordBegin)) break;
437  pchWordBegin--;
438  }
439 
440  while (pchWordBegin > m_pchBuffer)
441  {
442  if (_istspace(*(pchWordBegin-1))) break;
443  pchWordBegin--;
444  }
445 
446  ASSERT(pchWordBegin >= m_pchBuffer);
447  dwCurrentCharOffset = pchWordBegin - m_pchBuffer;
448 
449  ASSERT(dwCurrentCharOffset < dwLastCharOffset);
450 
451  m_CursorPosition.X = X_CURSOR_POSITION_FROM_OFFSET(dwCurrentCharOffset);
452  m_CursorPosition.Y = Y_CURSOR_POSITION_FROM_OFFSET(dwCurrentCharOffset);
454  }
455  else
456  {
457  dwCurrentCharOffset--;
458  if (m_CursorPosition.X)
459  {
461  }
462  else
463  {
467  }
469  }
470  }
471  }
472  else if (InputRecord.Event.KeyEvent.wVirtualKeyCode == VK_RIGHT)
473  {
474  if (blnCompletionMode) blnCompletionMode = FALSE;
475  if (dwCurrentCharOffset < dwLastCharOffset)
476  {
478  {
479  TCHAR *pchWordBegin = m_pchBuffer+dwCurrentCharOffset;
480 
481  while ((DWORD)(pchWordBegin - m_pchBuffer) < dwLastCharOffset)
482  {
483  if (_istspace(*pchWordBegin)) break;
484  pchWordBegin++;
485  }
486 
487  while ((DWORD)(pchWordBegin - m_pchBuffer) < dwLastCharOffset)
488  {
489  if (!_istspace(*pchWordBegin)) break;
490  pchWordBegin++;
491  }
492 
493  dwCurrentCharOffset = pchWordBegin - m_pchBuffer;
494  ASSERT(dwCurrentCharOffset <= dwLastCharOffset);
495  m_CursorPosition.X = X_CURSOR_POSITION_FROM_OFFSET(dwCurrentCharOffset);
496  m_CursorPosition.Y = Y_CURSOR_POSITION_FROM_OFFSET(dwCurrentCharOffset);
498  }
499  else
500  {
501  dwCurrentCharOffset++;
504  {
506  m_CursorPosition.X = 0;
507  }
509  }
510  }
511  }
512  else if (InputRecord.Event.KeyEvent.wVirtualKeyCode == VK_HOME)
513  {
514  if (blnCompletionMode) blnCompletionMode = FALSE;
515  dwCurrentCharOffset = 0;
516  m_CursorPosition = FristCharCursorPosition;
518  }
519  else if (InputRecord.Event.KeyEvent.wVirtualKeyCode == VK_END)
520  {
521  if (blnCompletionMode) blnCompletionMode = FALSE;
522  dwCurrentCharOffset = dwLastCharOffset;
526  }
527  else if (InputRecord.Event.KeyEvent.wVirtualKeyCode == VK_UP)
528  {
529  if (blnCompletionMode) blnCompletionMode = FALSE;
530  dwHistoryIndex++;
531  const TCHAR *pchHistoryLine = m_History.GetHistoryLine(dwHistoryIndex-1);
532  if (pchHistoryLine)
533  {
534  if (dwLastCharOffset)
535  {
536  _tcsnset(m_pchBuffer,_T(' '),dwLastCharOffset);
537  m_CursorPosition = FristCharCursorPosition;
539  VERIFY(Write(m_pchBuffer,dwLastCharOffset));
540  dwCurrentCharOffset = dwLastCharOffset = 0;
541  m_CursorPosition = FristCharCursorPosition;
543  }
544  dwCurrentCharOffset = dwLastCharOffset = _tcslen(pchHistoryLine);
545  if (dwLastCharOffset >= m_dwBufferSize)
546  {
547  ASSERT(FALSE);
548  return FALSE;
549  }
550  _tcscpy(m_pchBuffer,pchHistoryLine);
551  if (!Write(m_pchBuffer)) return FALSE;
552  }
553  else
554  {
555  dwHistoryIndex--;
556  }
557  }
558  else if (InputRecord.Event.KeyEvent.wVirtualKeyCode == VK_DOWN)
559  {
560  if (blnCompletionMode) blnCompletionMode = FALSE;
561  if (dwHistoryIndex)
562  {
563  dwHistoryIndex--;
564  const TCHAR *pchHistoryLine = m_History.GetHistoryLine(dwHistoryIndex-1);
565  if (dwLastCharOffset)
566  {
567  _tcsnset(m_pchBuffer,_T(' '),dwLastCharOffset);
568  m_CursorPosition = FristCharCursorPosition;
570  VERIFY(Write(m_pchBuffer,dwLastCharOffset));
571  dwCurrentCharOffset = dwLastCharOffset = 0;
572  m_CursorPosition = FristCharCursorPosition;
574  }
575  if (pchHistoryLine)
576  {
577  dwCurrentCharOffset = dwLastCharOffset = _tcslen(pchHistoryLine);
578  if (dwLastCharOffset >= m_dwBufferSize)
579  {
580  ASSERT(FALSE);
581  return FALSE;
582  }
583  _tcscpy(m_pchBuffer,pchHistoryLine);
584  if (!Write(m_pchBuffer)) return FALSE;
585  }
586  }
587  }
588  else if ((InputRecord.Event.KeyEvent.wVirtualKeyCode == VK_DELETE)&&
589  (dwLastCharOffset))
590  {
591  // Move the characters if any...
592  ASSERT(dwLastCharOffset);
593  DWORD dwCharOffset = dwCurrentCharOffset;
594  if (dwCharOffset < dwLastCharOffset)
595  {
596  while(dwCharOffset < dwLastCharOffset)
597  {
598  m_pchBuffer[dwCharOffset] = m_pchBuffer[dwCharOffset+1];
599  dwCharOffset++;
600  }
601 
602  m_pchBuffer[dwLastCharOffset-1] = _T(' ');
603 
604  // Save cursor position
605  COORD Cursor = m_CursorPosition;
606 
607  if (!Write(m_pchBuffer+dwCurrentCharOffset,dwLastCharOffset-dwCurrentCharOffset)) return FALSE;
608 
609  dwLastCharOffset--;
610 
611  // Update cursor position
612  m_CursorPosition = Cursor;
614  }
615 
616  }
617 // else if ((InputRecord.Event.KeyEvent.wVirtualKeyCode == VK_PAUSE)&&
618 // (InputRecord.Event.KeyEvent.dwControlKeyState & (LEFT_CTRL_PRESSED|RIGHT_CTRL_PRESSED)))
619 // {
620 // if (!GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT,0)) return FALSE;
621 // }
622  }
623  else if ((ch == 27) && dwLastCharOffset &&
624  (InputRecord.Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE))
625  {
626  if (blnCompletionMode) blnCompletionMode = FALSE;
627  _tcsnset(m_pchBuffer,_T(' '),dwLastCharOffset);
628  m_CursorPosition = FristCharCursorPosition;
630  VERIFY(Write(m_pchBuffer,dwLastCharOffset));
631  dwCurrentCharOffset = dwLastCharOffset = 0;
632  m_CursorPosition = FristCharCursorPosition;
634  }
635  else if (ch == _T('\r'))
636  { // carriage return
637  if (!SetConsoleCursorPosition(m_hStdOut,m_CursorPosition = FristCharCursorPosition)) return FALSE;
638  ASSERT(dwLastCharOffset <= m_dwBufferSize);
639  m_pchBuffer[dwLastCharOffset] = 0; // terminate string in buffer
640  ret = Write(m_pchBuffer);
642  static TCHAR strLF[] = _T("\n");
643  ret = Write(strLF);
644  break;
645  }
646  else if (ch == _T('\b'))
647  { // backspace
648  if (blnCompletionMode) blnCompletionMode = FALSE;
649  if ((dwCurrentCharOffset) && ((m_CursorPosition.X != 0) || (m_CursorPosition.Y != 0)))
650  {
651  // Calculate new cursor position
652  COORD NewCursorPosition;
653  if (m_CursorPosition.X)
654  {
655  NewCursorPosition.X = SHORT(m_CursorPosition.X-1);
656  NewCursorPosition.Y = m_CursorPosition.Y;
657  }
658  else
659  {
661  NewCursorPosition.X = SHORT(m_BufferSize.X-1);
663  NewCursorPosition.Y = SHORT(m_CursorPosition.Y-1);
664  }
665 
666  // Move the characters if any...
667  ASSERT(dwLastCharOffset);
668  DWORD dwCharOffset = dwCurrentCharOffset-1;
669  while(dwCharOffset < dwLastCharOffset-1)
670  {
671  m_pchBuffer[dwCharOffset] = m_pchBuffer[dwCharOffset+1];
672  dwCharOffset++;
673  }
674 
675  m_pchBuffer[dwLastCharOffset-1] = _T(' ');
676 
677  dwCurrentCharOffset--;
678  m_CursorPosition = NewCursorPosition;
679  if (!Write(m_pchBuffer+dwCurrentCharOffset,dwLastCharOffset-dwCurrentCharOffset)) return FALSE;
680 
681  // Update cursor position
682  m_CursorPosition = NewCursorPosition;
684 
685  dwLastCharOffset--;
686  }
687  }
688  else if (ch == _T('\t'))
689  { // Tab
690 
691  if (!blnCompletionMode) // If tab was pressed after non-tab. We enter in completion mode.
692  {
693  // Initialize completion index
694  if (InputRecord.Event.KeyEvent.dwControlKeyState & SHIFT_PRESSED) // If shift was pressed
695  nCompletionIndex = (unsigned long long) -1; // Last completion
696  else
697  nCompletionIndex = 0; // First completion
698 
699  // Find completion offset. It points at char after first non-quoted whitespace.
700  dwCompletionOffset = dwCurrentCharOffset;
701  BOOL blnQuotedParameter = FALSE;
702  while(dwCompletionOffset)
703  {
704  dwCompletionOffset--;
705  if (m_pchBuffer[dwCompletionOffset] == _T('\"'))
706  {
707  blnQuotedParameter = !blnQuotedParameter;
708  }
709  else if (!blnQuotedParameter && _istspace(m_pchBuffer[dwCompletionOffset]))
710  { // Found ! We are not inside quored parameter and we are on whitespace.
711  dwCompletionOffset++; // dwCompletionOffset must point at char AFTER first non-quoted whitespace.
712  break;
713  }
714  }
715 
716  ASSERT(dwCompletionOffset <= dwCurrentCharOffset);
717 
718  // Save not changing part (context) of completion in m_pchBuffer1
719  _tcsncpy(m_pchBuffer1,m_pchBuffer,dwCompletionOffset);
720  m_pchBuffer1[dwCompletionOffset] = 0;
721 
722  // Size of changing part
723  dwCompletionStringSize = dwCurrentCharOffset-dwCompletionOffset;
724 
725  // Save intial changing part of completion in m_pchBuffer2
726  if (dwCompletionStringSize)
727  _tcsncpy(m_pchBuffer2,m_pchBuffer+dwCompletionOffset,dwCompletionStringSize);
728  m_pchBuffer2[dwCompletionStringSize] = 0;
729 
730  // Calculate cursor position of point between changing and not changing ports
731  CompletionPosition.X = X_CURSOR_POSITION_FROM_OFFSET(dwCompletionOffset);
732  CompletionPosition.Y = Y_CURSOR_POSITION_FROM_OFFSET(dwCompletionOffset);
733  } // if first time tab
734 
735  const TCHAR *pchCompletion = NULL;
736 
737  // Direction
738  BOOL blnForward = !(InputRecord.Event.KeyEvent.dwControlKeyState & SHIFT_PRESSED);
739 
740  if (m_pfReplaceCompletionCallback) // If we are using replace completion callback
741  pchCompletion = m_pfReplaceCompletionCallback(nCompletionIndex,
742  blnCompletionMode?&blnForward:NULL, // If this is first time we call the completion callback, do not change completion index
744 
745  if (pchCompletion) // If completion found
746  {
747  // Set cursor position to compeltion position
748  m_CursorPosition = CompletionPosition;
750  return FALSE;
751 
752  // Calculate buffer free space
753  ASSERT(m_dwBufferSize > dwCompletionOffset);
754  DWORD dwFree = m_dwBufferSize - dwCompletionOffset - 1;
755 
756  // Save old completion string size
757  DWORD dwOldCompletionStringSize = dwCompletionStringSize;
758 
759  // Write completion string to buffer
760  dwCompletionStringSize = _tcslen(pchCompletion);
761 
762  // If there is not enough space in buffer, so we truncate the completion
763  if (dwCompletionStringSize > dwFree)
764  dwCompletionStringSize = dwFree;
765 
766  if (dwCompletionStringSize)
767  {
768  // Copy competion into main buffer
769  _tcsncpy(m_pchBuffer+dwCompletionOffset,pchCompletion,dwCompletionStringSize);
770 
771  // Write completion string to console
772  if (!Write(m_pchBuffer+dwCompletionOffset,dwCompletionStringSize))
773  return FALSE;
774 
775  // Set new offsets
776  dwCurrentCharOffset = dwLastCharOffset = dwCompletionOffset + dwCompletionStringSize;
777 
778  ASSERT(dwLastCharOffset < m_dwBufferSize);
779  }
780 
781  // Erase rest from previous completion string, if the new completion is shorter than old
782  if (dwOldCompletionStringSize > dwCompletionStringSize)
783  {
784  _tcsnset(m_pchBuffer+dwCompletionOffset+dwCompletionStringSize,_T(' '),
785  dwOldCompletionStringSize - dwCompletionStringSize);
786 
787  // Save cursor position
789 
790  if (!Write(m_pchBuffer+dwCompletionOffset+dwCompletionStringSize,
791  dwOldCompletionStringSize - dwCompletionStringSize))
792  return FALSE;
793 
794  // Set cursor position
797  return FALSE;
798  }
799  } // If completion found
800 
801  // Ok, we are in completion mode
802  blnCompletionMode = TRUE;
803  }
804  else if (_istprint(ch))
805  {
806  if (blnCompletionMode) blnCompletionMode = FALSE;
807  if (dwLastCharOffset >= m_dwBufferSize-1)
808  {
809  ASSERT(dwLastCharOffset == m_dwBufferSize-1);
810 // Beep(1000,100);
811  continue;
812  }
813  TCHAR ch1;
814  //if (m_blnInsetMode)
815  ch1 = m_pchBuffer[dwCurrentCharOffset];
816  m_pchBuffer[dwCurrentCharOffset] = ch;
817  if ((m_blnInsetMode)||(dwCurrentCharOffset == dwLastCharOffset)) dwLastCharOffset++;
818  dwCurrentCharOffset++;
819  if (!Write(&ch,1)) return FALSE;
820  if (m_blnInsetMode)
821  {
822  COORD Cursor = m_CursorPosition;
823  DWORD ofs = dwCurrentCharOffset;
824 
825  while(ofs <= dwLastCharOffset)
826  {
827  ch = m_pchBuffer[ofs];
828  m_pchBuffer[ofs] = ch1;
829  ch1 = ch;
830  ofs++;
831  }
832 
833  if (dwCurrentCharOffset < dwLastCharOffset)
834  {
835  if (!Write(m_pchBuffer+dwCurrentCharOffset,dwLastCharOffset-dwCurrentCharOffset)) return FALSE;
836 
837  if (m_LinesScrolled)
838  {
839  if (m_LinesScrolled > FristCharCursorPosition.Y) return FALSE;
840  Cursor.Y = SHORT(Cursor.Y - m_LinesScrolled);
841  }
842  // Update cursor position
843  m_CursorPosition = Cursor;
845  }
846  }
847  }
848  ASSERT(InputRecord.Event.KeyEvent.wRepeatCount);
849  if (!InputRecord.Event.KeyEvent.wRepeatCount) return FALSE;
850  if (--InputRecord.Event.KeyEvent.wRepeatCount) goto KeyRepeat;
851  }
852  m_blnMoreMode = blnOldMoreMode;
853  return TRUE;
854 }
855 
857 {
858  rwAttributes = m_wAttributes;
859  return TRUE;
860 }
861 
862 // Parameters:
863 // dwBufferSize - size in chars of the input line buffer
864 //
865 // Rerturns:
866 // NULL - Failed.
867 // pointer to the input buffer
868 TCHAR * CConsole::Init(DWORD dwBufferSize, DWORD dwMaxHistoryLines)
869 {
872 
874 
876  {
877 // _ftprintf(stderr,_T("GetStdHandle(STD_INPUT_HANDLE) failed. GetLastError return 0x%X\n"),(unsigned)GetLastError());
878  goto Abort;
879  }
880 
882 
884  {
885 // _ftprintf(stderr,_T("GetStdHandle(STD_OUTPUT_HANDLE) failed. GetLastError return 0x%X\n"),(unsigned)GetLastError());
886  goto Abort;
887  }
888 
891  {
892 // _ftprintf(stderr,_T("GetConsoleScreenBufferInfo(m_hStdOut,&info) failed. GetLastError return 0x%X\n"),(unsigned)GetLastError());
893  if (GetLastError() == 6) // redirected output
894  _ftprintf(stderr,_T("Redirection is not supported.\n"));
895 
896  goto Abort;
897  }
898  m_wAttributes = info.wAttributes;
899 
901  {
903  {
904  if (GetLastError() == 6) // redirected input
905  _ftprintf(stderr,_T("Redirection is not supported.\n"));
906 // _ftprintf(stderr,_T("GetConsoleMode(0x%X,&m_dwOldINputMode) failed. GetLastError() returns 0x%X\n"),(int)m_hStdIn,GetLastError());
907  goto Abort;
908  }
909 
911  }
912 
913 // _ftprintf(stderr,_T("Calling GetConsoleMode(0x%X,&m_dwOldOutputMode) ...\n"),(int)m_hStdOut);
915  {
917  goto Abort;
918 // _ftprintf(stderr,_T("Calling GetConsoleMode(0x%X,&m_dwOldOutputMode) done.\n"),(int)m_hStdOut);
920  }
921 
922 // _ftprintf(stderr,_T("Calling SetConsoleMode(0x%X,0) ...\n"),(int)m_hStdIn);
923  if (!SetConsoleMode(m_hStdIn,0))
924  goto Abort;
925  if (!SetConsoleMode(m_hStdOut,0))
926  goto Abort;
927 
928  m_CursorPosition = info.dwCursorPosition;
929  m_BufferSize = info.dwSize;
930 
932  cci.bVisible = TRUE;
934 
935  if (!SetConsoleCursorInfo(m_hStdOut,&cci)) goto Abort;
936 
937  m_dwBufferSize = dwBufferSize;
938 
939  if (m_pchBuffer) delete m_pchBuffer;
940  m_pchBuffer = NULL;
941 
942  if (m_pchBuffer1) delete m_pchBuffer1;
943  m_pchBuffer1 = NULL;
944 
945  if (m_pchBuffer2) delete m_pchBuffer2;
946  m_pchBuffer2 = NULL;
947 
948  m_pchBuffer = new (std::nothrow) TCHAR [dwBufferSize];
949  if (!m_pchBuffer) goto Abort;
950  m_pchBuffer[dwBufferSize-1] = 0;
951 
952  m_pchBuffer1 = new (std::nothrow) TCHAR [dwBufferSize];
953  if (!m_pchBuffer1) goto Abort;
954  m_pchBuffer1[dwBufferSize-1] = 0;
955 
956  m_pchBuffer2 = new (std::nothrow) TCHAR [dwBufferSize];
957  if (!m_pchBuffer2) goto Abort;
958  m_pchBuffer2[dwBufferSize-1] = 0;
959 
960  if (dwMaxHistoryLines)
961  {
962  if (!m_History.Init(dwBufferSize,dwMaxHistoryLines)) goto Abort;
963  }
964 
965  return m_pchBuffer;
966 
967 Abort:
970 
973 
974  if (m_pchBuffer) delete[] m_pchBuffer;
975  m_pchBuffer = NULL;
976 
977  if (m_pchBuffer1) delete[] m_pchBuffer1;
978  m_pchBuffer1 = NULL;
979 
980  if (m_pchBuffer2) delete[] m_pchBuffer2;
981  m_pchBuffer2 = NULL;
982 
983  m_dwBufferSize = 0;
984 
985  return NULL;
986 }
987 
989 {
990  CHAR_INFO ci;
992 #ifdef UNICODE
993  ci.Char.UnicodeChar = ch;
994 #else
995  ci.Char.AsciiChar = ch;
996 #endif
997  static COORD BufferSize = {1,1};
998  static COORD BufferCoord = {0,0};
999  SMALL_RECT Dest;
1000  Dest.Bottom = Dest.Top = m_CursorPosition.Y;
1001  Dest.Left = Dest.Right = m_CursorPosition.X;
1002  return WriteConsoleOutput(m_hStdOut,&ci,BufferSize,BufferCoord,&Dest);
1003 }
1004 
1006 {
1007  m_Lines = 0;
1008 }
1009 
1011 {
1012  CHAR_INFO ciBuffer[256];
1013  int nSize = _tcslen(pchString);
1014  if ((nSize > 256)||(nSize <= 0))
1015  {
1016  ASSERT(FALSE);
1017  return FALSE;
1018  }
1019 
1020  COORD BufferSize;
1021  BufferSize.X = (SHORT)nSize;
1022  BufferSize.Y = 1;
1023  static COORD BufferCoord = {0,0};
1024  SMALL_RECT Dest;
1025  Dest.Bottom = Dest.Top = Position.Y;
1026  Dest.Right = SHORT((Dest.Left = Position.X) + nSize - 1);
1027 
1028  while(nSize--)
1029  {
1030  ciBuffer[nSize].Attributes = m_wAttributes;
1031 #ifdef UNICODE
1032  ciBuffer[nSize].Char.UnicodeChar = pchString[nSize];
1033 #else
1034  ciBuffer[nSize].Char.AsciiChar = pchString[nSize];
1035 #endif
1036  }
1037 
1038  return WriteConsoleOutput(m_hStdOut,ciBuffer,BufferSize,BufferCoord,&Dest);
1039 }
1040 
1042 {
1043  if (m_hStdOut == INVALID_HANDLE_VALUE) return FALSE;
1044 
1045  CONSOLE_CURSOR_INFO cci;
1046  cci.bVisible = TRUE;
1048 
1050  if (ret) m_blnInsetMode = blnInsetMode;
1051  return ret;
1052 }
1053 
1054 
1055 
1057 {
1058  m_pfReplaceCompletionCallback = pfCallback;
1059 }
1060 
1061 
1063 {
1065  INPUT_RECORD InputRecord;
1066  DWORD dwRecordsWriten;
1067  InputRecord.EventType = KEY_EVENT;
1068  InputRecord.Event.KeyEvent.bKeyDown = TRUE;
1069 #ifdef UNICODE
1070  InputRecord.Event.KeyEvent.uChar.UnicodeChar = L' ';
1071 #else
1072  InputRecord.Event.KeyEvent.uChar.AsciiChar = ' ';
1073 #endif
1074  BOOL ret = WriteConsoleInput(m_hStdIn,&InputRecord,1,&dwRecordsWriten);
1075  ASSERT(ret);
1076 }
1077 
1079 {
1081 }
BOOL m_blnOldOutputModeSaved
Definition: Console.h:57
void DisableWrite()
Definition: Console.cpp:1062
COORD m_BufferSize
Definition: Console.h:37
wchar_t UNICODE
Definition: ms-dtyp.idl:111
#define TRUE
Definition: types.h:120
#define CloseHandle
Definition: compat.h:398
WCHAR UnicodeChar
Definition: wincon.h:230
BOOL ReadLine()
Definition: Console.cpp:249
SHORT m_Lines
Definition: Console.h:39
ReplaceCompletionCallback m_pfReplaceCompletionCallback
Definition: Console.h:49
BOOL WINAPI IsClipboardFormatAvailable(_In_ UINT)
DWORD m_dwOverwriteModeCursorHeight
Definition: Console.h:44
CHAR AsciiChar
Definition: wincon.h:170
static VOID Paste(PGUI_CONSOLE_DATA GuiData)
Definition: conwnd.c:1983
DWORD m_dwInsertModeCursorHeight
Definition: Console.h:43
void EnableWrite()
Definition: Console.cpp:1078
static COORD Position
Definition: mouse.c:34
WCHAR UnicodeChar
Definition: wincon.h:169
void BeginScrollingOperation()
Definition: Console.cpp:1005
BOOL WINAPI GetConsoleMode(HANDLE hConsoleHandle, LPDWORD lpMode)
Definition: console.c:1571
_TCHAR * _tcsncpy(_TCHAR *dst, const _TCHAR *src, size_t n)
Definition: tcsncpy.h:9
#define WriteConsoleInput
Definition: wincon.h:773
*nSize LPSTR _Inout_ LPDWORD nSize
Definition: winbase.h:2024
DWORD dwControlKeyState
Definition: wincon.h:233
#define CTRL_C_EVENT
Definition: wincon.h:65
SHORT m_LinesScrolled
Definition: Console.h:50
#define VK_LEFT
Definition: winuser.h:2178
#define INVALID_HANDLE_VALUE
Definition: compat.h:391
_TCHAR * _tcscpy(_TCHAR *to, const _TCHAR *from)
Definition: tcscpy.h:8
BOOL WINAPI FlushConsoleInputBuffer(IN HANDLE hConsoleInput)
Definition: console.c:169
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
#define MORE_EMPTY_STRING
Definition: Console.cpp:31
HANDLE WINAPI GetStdHandle(IN DWORD nStdHandle)
Definition: console.c:152
#define MORE_STRING
Definition: Console.cpp:30
#define VK_DOWN
Definition: winuser.h:2181
#define VK_INSERT
Definition: winuser.h:2186
#define Y_CURSOR_POSITION_FROM_OFFSET(ofs)
#define SHIFT_PRESSED
Definition: wincon.h:135
#define VK_ESCAPE
Definition: winuser.h:2168
BOOL SetTitle(const TCHAR *p)
Definition: Console.cpp:222
CHAR * LPTSTR
Definition: xmlstorage.h:192
#define pch(ap)
Definition: match.c:418
#define WriteConsoleOutput
Definition: wincon.h:775
TCHAR * m_pchBuffer1
Definition: Console.h:46
DWORD m_dwBufferSize
Definition: Console.h:48
WORD wVirtualKeyCode
Definition: wincon.h:227
struct _test_info info[]
Definition: SetCursorPos.c:19
#define VK_HOME
Definition: winuser.h:2177
WORD wRepeatCount
Definition: wincon.h:226
#define VK_UP
Definition: winuser.h:2179
BOOL WINAPI DECLSPEC_HOTPATCH GenerateConsoleCtrlEvent(DWORD dwCtrlEvent, DWORD dwProcessGroupId)
Definition: console.c:2134
BOOL SetTextAttribute(WORD wAttributes)
Definition: Console.cpp:227
HANDLE m_hStdIn
Definition: Console.h:34
unsigned int BOOL
Definition: ntddk_ex.h:94
#define ReadConsoleInput
Definition: wincon.h:766
BOOL WINAPI DECLSPEC_HOTPATCH SetConsoleMode(HANDLE hConsoleHandle, DWORD dwMode)
Definition: console.c:1608
short SHORT
Definition: pedump.c:59
#define KEY_EVENT
Definition: wincon.h:122
#define CF_UNICODETEXT
Definition: constants.h:408
size_t __cdecl _tcslen(const _TCHAR *str)
Definition: tcslen.h:9
CConsole()
Definition: Console.cpp:50
smooth NULL
Definition: ftsmooth.c:416
BOOL SetInsertMode(BOOL blnInsetMode)
Definition: Console.cpp:1041
BOOL WINAPI SetConsoleCursorPosition(IN HANDLE hConsoleOutput, IN COORD dwCursorPosition)
Definition: console.c:590
BOOL FlushInputBuffer()
Definition: Console.cpp:243
COORD m_CursorPosition
Definition: Console.h:36
#define STD_INPUT_HANDLE
Definition: winbase.h:264
#define _ftprintf
Definition: tchar.h:518
#define VK_DELETE
Definition: winuser.h:2187
BOOL WINAPI GetConsoleScreenBufferInfo(IN HANDLE hConsoleOutput, OUT PCONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo)
Definition: console.c:544
#define CF_TEXT
Definition: constants.h:396
const TCHAR * GetHistoryLine(DWORD dwIndex)
Definition: TextHistory.cpp:83
SHORT Left
Definition: blue.h:25
ULONG X
Definition: bl.h:1340
#define X_CURSOR_POSITION_FROM_OFFSET(ofs)
DWORD m_dwOldOutputMode
Definition: Console.h:54
unsigned int GetTabWidth()
Definition: Console.cpp:217
BOOL GetTextAttribute(WORD &rwAttributes)
Definition: Console.cpp:856
char TCHAR
Definition: xmlstorage.h:189
#define _T(x)
Definition: vfdio.h:22
BOOLEAN bVisible
Definition: blue.h:41
SHORT Bottom
Definition: blue.h:28
BOOL WINAPI SetConsoleCursorInfo(IN HANDLE hConsoleOutput, IN const CONSOLE_CURSOR_INFO *lpConsoleCursorInfo)
Definition: console.c:567
WORD Attributes
Definition: wincon.h:172
void AddHistoryLine(const TCHAR *pchLine)
Definition: TextHistory.cpp:62
TCHAR * m_pchBuffer2
Definition: Console.h:47
BOOL Init(DWORD dwMaxHistoryLineSize, DWORD dwMaxHistoryLines)
Definition: TextHistory.cpp:44
KEY_EVENT_RECORD KeyEvent
Definition: wincon.h:263
#define BufferSize
Definition: classpnp.h:419
unsigned short WORD
Definition: ntddk_ex.h:93
#define VERIFY(e)
Definition: ph.h:34
unsigned long DWORD
Definition: ntddk_ex.h:95
HANDLE m_hStdOut
Definition: Console.h:33
SHORT Top
Definition: blue.h:26
virtual ~CConsole()
Definition: Console.cpp:70
BOOL WINAPI CloseClipboard(void)
Definition: ntwrapper.h:178
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define VK_CANCEL
Definition: winuser.h:2146
union _CHAR_INFO::@3150 Char
int ret
#define LEFT_CTRL_PRESSED
Definition: wincon.h:134
DWORD m_dwOldInputMode
Definition: Console.h:55
static const WCHAR L[]
Definition: oid.c:1250
LPVOID NTAPI GlobalLock(HGLOBAL hMem)
Definition: heapmem.c:755
void SetReplaceCompletionCallback(ReplaceCompletionCallback pfCallback)
Definition: Console.cpp:1056
#define _istprint
Definition: tchar.h:1500
#define STD_OUTPUT_HANDLE
Definition: winbase.h:265
TCHAR * m_pchBuffer
Definition: Console.h:45
BOOL m_blnDisableWrite
Definition: Console.h:53
Definition: bl.h:1338
#define TAB_WIDTH
Definition: Console.cpp:29
#define VK_RIGHT
Definition: winuser.h:2180
BOOL Write(const TCHAR *p, DWORD dwChars=0)
Definition: Console.cpp:90
#define ScrollConsoleScreenBuffer
Definition: wincon.h:770
#define SetConsoleTitle
Definition: wincon.h:771
BOOL WriteChar(TCHAR ch)
Definition: Console.cpp:988
#define long
Definition: qsort.c:33
union _KEY_EVENT_RECORD::@3151 uChar
TCHAR * Init(DWORD dwBufferSize, DWORD dwMaxHistoryLines=0)
Definition: Console.cpp:868
BOOL m_blnOldInputModeSaved
Definition: Console.h:56
BOOL NTAPI GlobalUnlock(HGLOBAL hMem)
Definition: heapmem.c:1190
HANDLE WINAPI GetClipboardData(_In_ UINT)
BOOL m_blnMoreMode
Definition: Console.h:51
WORD EventType
Definition: wincon.h:261
CTextHistory m_History
Definition: Console.h:52
const TCHAR *(* ReplaceCompletionCallback)(unsigned __int64 &rnIndex, const BOOL *pblnForward, const TCHAR *pchContext, const TCHAR *pchBegin)
Definition: Completion.h:7
WORD m_wAttributes
Definition: Console.h:38
#define _istspace
Definition: tchar.h:1504
FILE * stderr
#define RIGHT_CTRL_PRESSED
Definition: wincon.h:133
BOOL WINAPI OpenClipboard(_In_opt_ HWND)
GLfloat GLfloat p
Definition: glext.h:8902
SHORT Right
Definition: blue.h:27
ULONG Y
Definition: bl.h:1341
BOOL m_blnInsetMode
Definition: Console.h:42
#define VK_END
Definition: winuser.h:2176
union _INPUT_RECORD::@3152 Event
#define _tcsnset
Definition: tchar.h:1419
BOOL WriteString(const TCHAR *pchString, COORD Position)
Definition: Console.cpp:1010