ReactOS 0.4.15-dev-7842-g558ab78
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/*
34TCHAR * _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;
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
91{
93 return FALSE;
95 return FALSE;
96 if (p == NULL)
97 {
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'):
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 }
122 dwCharsWrittenAdd++;
123 dwCharsToWrite--;
124 continue;
125 default:
126 {
127 if (!WriteChar(p[dwCharsWrittenAdd])) return FALSE;
129 }
130 }
132 {
135 }
137 {
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;
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
205
206 cci.bVisible = TRUE;
209 }
210 }
211 dwCharsWrittenAdd++;
212 dwCharsToWrite--;
213 }
214 return ret;
215}
216
218{
219 return TAB_WIDTH;
220}
221
223{
224 return SetConsoleTitle(p);
225}
226
228{
229 m_wAttributes = wAttributes;
230 return TRUE;
231}
232/*
233BOOL CConsole::SetInputMode(DWORD dwMode)
234{
235 return SetConsoleMode(m_hStdIn,dwMode);
236}
237
238BOOL 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 }
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
305KeyRepeat:
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
338Paste:
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
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 {
367 GlobalUnlock(hglb);
368 }
369 }
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--;
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 {
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
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;
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
720 // FIXME: dwCompletionOffset is always 0 here
721 // _tcsncpy(m_pchBuffer1,m_pchBuffer,dwCompletionOffset);
722 m_pchBuffer1[dwCompletionOffset] = 0;
723
724 // Size of changing part
725 dwCompletionStringSize = dwCurrentCharOffset-dwCompletionOffset;
726
727 // Save intial changing part of completion in m_pchBuffer2
728 if (dwCompletionStringSize)
729 _tcsncpy(m_pchBuffer2,m_pchBuffer+dwCompletionOffset,dwCompletionStringSize);
730 m_pchBuffer2[dwCompletionStringSize] = 0;
731
732 // Calculate cursor position of point between changing and not changing ports
733 CompletionPosition.X = X_CURSOR_POSITION_FROM_OFFSET(dwCompletionOffset);
734 CompletionPosition.Y = Y_CURSOR_POSITION_FROM_OFFSET(dwCompletionOffset);
735 } // if first time tab
736
737 const TCHAR *pchCompletion = NULL;
738
739 // Direction
740 BOOL blnForward = !(InputRecord.Event.KeyEvent.dwControlKeyState & SHIFT_PRESSED);
741
742 if (m_pfReplaceCompletionCallback) // If we are using replace completion callback
743 pchCompletion = m_pfReplaceCompletionCallback(nCompletionIndex,
744 blnCompletionMode?&blnForward:NULL, // If this is first time we call the completion callback, do not change completion index
746
747 if (pchCompletion) // If completion found
748 {
749 // Set cursor position to compeltion position
750 m_CursorPosition = CompletionPosition;
752 return FALSE;
753
754 // Calculate buffer free space
755 ASSERT(m_dwBufferSize > dwCompletionOffset);
756 DWORD dwFree = m_dwBufferSize - dwCompletionOffset - 1;
757
758 // Save old completion string size
759 DWORD dwOldCompletionStringSize = dwCompletionStringSize;
760
761 // Write completion string to buffer
762 dwCompletionStringSize = _tcslen(pchCompletion);
763
764 // If there is not enough space in buffer, so we truncate the completion
765 if (dwCompletionStringSize > dwFree)
766 dwCompletionStringSize = dwFree;
767
768 if (dwCompletionStringSize)
769 {
770 // Copy competion into main buffer
771 _tcsncpy(m_pchBuffer+dwCompletionOffset,pchCompletion,dwCompletionStringSize);
772
773 // Write completion string to console
774 if (!Write(m_pchBuffer+dwCompletionOffset,dwCompletionStringSize))
775 return FALSE;
776
777 // Set new offsets
778 dwCurrentCharOffset = dwLastCharOffset = dwCompletionOffset + dwCompletionStringSize;
779
780 ASSERT(dwLastCharOffset < m_dwBufferSize);
781 }
782
783 // Erase rest from previous completion string, if the new completion is shorter than old
784 if (dwOldCompletionStringSize > dwCompletionStringSize)
785 {
786 _tcsnset(m_pchBuffer+dwCompletionOffset+dwCompletionStringSize,_T(' '),
787 dwOldCompletionStringSize - dwCompletionStringSize);
788
789 // Save cursor position
791
792 if (!Write(m_pchBuffer+dwCompletionOffset+dwCompletionStringSize,
793 dwOldCompletionStringSize - dwCompletionStringSize))
794 return FALSE;
795
796 // Set cursor position
799 return FALSE;
800 }
801 } // If completion found
802
803 // Ok, we are in completion mode
804 blnCompletionMode = TRUE;
805 }
806 else if (_istprint(ch))
807 {
808 if (blnCompletionMode) blnCompletionMode = FALSE;
809 if (dwLastCharOffset >= m_dwBufferSize-1)
810 {
811 ASSERT(dwLastCharOffset == m_dwBufferSize-1);
812// Beep(1000,100);
813 continue;
814 }
815 TCHAR ch1;
816 //if (m_blnInsetMode)
817 ch1 = m_pchBuffer[dwCurrentCharOffset];
818 m_pchBuffer[dwCurrentCharOffset] = ch;
819 if ((m_blnInsetMode)||(dwCurrentCharOffset == dwLastCharOffset)) dwLastCharOffset++;
820 dwCurrentCharOffset++;
821 if (!Write(&ch,1)) return FALSE;
822 if (m_blnInsetMode)
823 {
824 COORD Cursor = m_CursorPosition;
825 DWORD ofs = dwCurrentCharOffset;
826
827 while(ofs <= dwLastCharOffset)
828 {
829 ch = m_pchBuffer[ofs];
830 m_pchBuffer[ofs] = ch1;
831 ch1 = ch;
832 ofs++;
833 }
834
835 if (dwCurrentCharOffset < dwLastCharOffset)
836 {
837 if (!Write(m_pchBuffer+dwCurrentCharOffset,dwLastCharOffset-dwCurrentCharOffset)) return FALSE;
838
839 if (m_LinesScrolled)
840 {
841 if (m_LinesScrolled > FristCharCursorPosition.Y) return FALSE;
842 Cursor.Y = SHORT(Cursor.Y - m_LinesScrolled);
843 }
844 // Update cursor position
845 m_CursorPosition = Cursor;
847 }
848 }
849 }
850 ASSERT(InputRecord.Event.KeyEvent.wRepeatCount);
851 if (!InputRecord.Event.KeyEvent.wRepeatCount) return FALSE;
852 if (--InputRecord.Event.KeyEvent.wRepeatCount) goto KeyRepeat;
853 }
854 m_blnMoreMode = blnOldMoreMode;
855 return TRUE;
856}
857
859{
860 rwAttributes = m_wAttributes;
861 return TRUE;
862}
863
864// Parameters:
865// dwBufferSize - size in chars of the input line buffer
866//
867// Rerturns:
868// NULL - Failed.
869// pointer to the input buffer
870TCHAR * CConsole::Init(DWORD dwBufferSize, DWORD dwMaxHistoryLines)
871{
874
876
878 {
879// _ftprintf(stderr,_T("GetStdHandle(STD_INPUT_HANDLE) failed. GetLastError return 0x%X\n"),(unsigned)GetLastError());
880 goto Abort;
881 }
882
884
886 {
887// _ftprintf(stderr,_T("GetStdHandle(STD_OUTPUT_HANDLE) failed. GetLastError return 0x%X\n"),(unsigned)GetLastError());
888 goto Abort;
889 }
890
893 {
894// _ftprintf(stderr,_T("GetConsoleScreenBufferInfo(m_hStdOut,&info) failed. GetLastError return 0x%X\n"),(unsigned)GetLastError());
895 if (GetLastError() == 6) // redirected output
896 _ftprintf(stderr,_T("Redirection is not supported.\n"));
897
898 goto Abort;
899 }
900 m_wAttributes = info.wAttributes;
901
903 {
905 {
906 if (GetLastError() == 6) // redirected input
907 _ftprintf(stderr,_T("Redirection is not supported.\n"));
908// _ftprintf(stderr,_T("GetConsoleMode(0x%X,&m_dwOldINputMode) failed. GetLastError() returns 0x%X\n"),(int)m_hStdIn,GetLastError());
909 goto Abort;
910 }
911
913 }
914
915// _ftprintf(stderr,_T("Calling GetConsoleMode(0x%X,&m_dwOldOutputMode) ...\n"),(int)m_hStdOut);
917 {
919 goto Abort;
920// _ftprintf(stderr,_T("Calling GetConsoleMode(0x%X,&m_dwOldOutputMode) done.\n"),(int)m_hStdOut);
922 }
923
924// _ftprintf(stderr,_T("Calling SetConsoleMode(0x%X,0) ...\n"),(int)m_hStdIn);
925 if (!SetConsoleMode(m_hStdIn,0))
926 goto Abort;
928 goto Abort;
929
930 m_CursorPosition = info.dwCursorPosition;
931 m_BufferSize = info.dwSize;
932
934 cci.bVisible = TRUE;
936
937 if (!SetConsoleCursorInfo(m_hStdOut,&cci)) goto Abort;
938
939 m_dwBufferSize = dwBufferSize;
940
941 if (m_pchBuffer) delete m_pchBuffer;
943
944 if (m_pchBuffer1) delete m_pchBuffer1;
946
947 if (m_pchBuffer2) delete m_pchBuffer2;
949
950 m_pchBuffer = new (std::nothrow) TCHAR [dwBufferSize];
951 if (!m_pchBuffer) goto Abort;
952 m_pchBuffer[dwBufferSize-1] = 0;
953
954 m_pchBuffer1 = new (std::nothrow) TCHAR [dwBufferSize];
955 if (!m_pchBuffer1) goto Abort;
956 m_pchBuffer1[dwBufferSize-1] = 0;
957
958 m_pchBuffer2 = new (std::nothrow) TCHAR [dwBufferSize];
959 if (!m_pchBuffer2) goto Abort;
960 m_pchBuffer2[dwBufferSize-1] = 0;
961
962 if (dwMaxHistoryLines)
963 {
964 if (!m_History.Init(dwBufferSize,dwMaxHistoryLines)) goto Abort;
965 }
966
967 return m_pchBuffer;
968
969Abort:
972
975
976 if (m_pchBuffer) delete[] m_pchBuffer;
978
979 if (m_pchBuffer1) delete[] m_pchBuffer1;
981
982 if (m_pchBuffer2) delete[] m_pchBuffer2;
984
985 m_dwBufferSize = 0;
986
987 return NULL;
988}
989
991{
992 CHAR_INFO ci;
994#ifdef UNICODE
995 ci.Char.UnicodeChar = ch;
996#else
997 ci.Char.AsciiChar = ch;
998#endif
999 static COORD BufferSize = {1,1};
1000 static COORD BufferCoord = {0,0};
1001 SMALL_RECT Dest;
1002 Dest.Bottom = Dest.Top = m_CursorPosition.Y;
1003 Dest.Left = Dest.Right = m_CursorPosition.X;
1004 return WriteConsoleOutput(m_hStdOut,&ci,BufferSize,BufferCoord,&Dest);
1005}
1006
1008{
1009 m_Lines = 0;
1010}
1011
1013{
1014 CHAR_INFO ciBuffer[256];
1015 int nSize = _tcslen(pchString);
1016 if ((nSize > 256)||(nSize <= 0))
1017 {
1018 ASSERT(FALSE);
1019 return FALSE;
1020 }
1021
1023 BufferSize.X = (SHORT)nSize;
1024 BufferSize.Y = 1;
1025 static COORD BufferCoord = {0,0};
1026 SMALL_RECT Dest;
1027 Dest.Bottom = Dest.Top = Position.Y;
1028 Dest.Right = SHORT((Dest.Left = Position.X) + nSize - 1);
1029
1030 while(nSize--)
1031 {
1032 ciBuffer[nSize].Attributes = m_wAttributes;
1033#ifdef UNICODE
1034 ciBuffer[nSize].Char.UnicodeChar = pchString[nSize];
1035#else
1036 ciBuffer[nSize].Char.AsciiChar = pchString[nSize];
1037#endif
1038 }
1039
1040 return WriteConsoleOutput(m_hStdOut,ciBuffer,BufferSize,BufferCoord,&Dest);
1041}
1042
1044{
1045 if (m_hStdOut == INVALID_HANDLE_VALUE) return FALSE;
1046
1048 cci.bVisible = TRUE;
1050
1052 if (ret) m_blnInsetMode = blnInsetMode;
1053 return ret;
1054}
1055
1056
1057
1059{
1060 m_pfReplaceCompletionCallback = pfCallback;
1061}
1062
1063
1065{
1067 INPUT_RECORD InputRecord;
1068 DWORD dwRecordsWriten;
1069 InputRecord.EventType = KEY_EVENT;
1070 InputRecord.Event.KeyEvent.bKeyDown = TRUE;
1071#ifdef UNICODE
1072 InputRecord.Event.KeyEvent.uChar.UnicodeChar = L' ';
1073#else
1074 InputRecord.Event.KeyEvent.uChar.AsciiChar = ' ';
1075#endif
1076 BOOL ret = WriteConsoleInput(m_hStdIn,&InputRecord,1,&dwRecordsWriten);
1077 ASSERT(ret);
1078}
1079
1081{
1083}
const TCHAR *(* ReplaceCompletionCallback)(unsigned __int64 &rnIndex, const BOOL *pblnForward, const TCHAR *pchContext, const TCHAR *pchBegin)
Definition: Completion.h:7
#define Y_CURSOR_POSITION_FROM_OFFSET(ofs)
#define X_CURSOR_POSITION_FROM_OFFSET(ofs)
#define MORE_EMPTY_STRING
Definition: Console.cpp:31
#define MORE_STRING
Definition: Console.cpp:30
#define TAB_WIDTH
Definition: text.h:125
#define CF_UNICODETEXT
Definition: constants.h:408
#define CF_TEXT
Definition: constants.h:396
BOOL WINAPI FlushConsoleInputBuffer(IN HANDLE hConsoleInput)
Definition: console.c:220
BOOL WINAPI SetConsoleCursorPosition(IN HANDLE hConsoleOutput, IN COORD dwCursorPosition)
Definition: console.c:641
HANDLE WINAPI GetStdHandle(IN DWORD nStdHandle)
Definition: console.c:203
BOOL WINAPI SetConsoleCursorInfo(IN HANDLE hConsoleOutput, IN const CONSOLE_CURSOR_INFO *lpConsoleCursorInfo)
Definition: console.c:618
BOOL WINAPI GetConsoleScreenBufferInfo(IN HANDLE hConsoleOutput, OUT PCONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo)
Definition: console.c:595
ReplaceCompletionCallback m_pfReplaceCompletionCallback
Definition: Console.h:49
SHORT m_LinesScrolled
Definition: Console.h:50
CTextHistory m_History
Definition: Console.h:52
BOOL m_blnOldInputModeSaved
Definition: Console.h:56
virtual ~CConsole()
Definition: Console.cpp:70
DWORD m_dwOldInputMode
Definition: Console.h:55
BOOL SetInsertMode(BOOL blnInsetMode)
Definition: Console.cpp:1043
DWORD m_dwOldOutputMode
Definition: Console.h:54
BOOL SetTitle(const TCHAR *p)
Definition: Console.cpp:222
TCHAR * m_pchBuffer1
Definition: Console.h:46
unsigned int GetTabWidth()
Definition: Console.cpp:217
BOOL WriteString(const TCHAR *pchString, COORD Position)
Definition: Console.cpp:1012
BOOL FlushInputBuffer()
Definition: Console.cpp:243
void BeginScrollingOperation()
Definition: Console.cpp:1007
HANDLE m_hStdIn
Definition: Console.h:34
WORD m_wAttributes
Definition: Console.h:38
BOOL m_blnMoreMode
Definition: Console.h:51
BOOL SetTextAttribute(WORD wAttributes)
Definition: Console.cpp:227
TCHAR * Init(DWORD dwBufferSize, DWORD dwMaxHistoryLines=0)
Definition: Console.cpp:870
BOOL m_blnOldOutputModeSaved
Definition: Console.h:57
HANDLE m_hStdOut
Definition: Console.h:33
SHORT m_Lines
Definition: Console.h:39
TCHAR * m_pchBuffer
Definition: Console.h:45
COORD m_CursorPosition
Definition: Console.h:36
BOOL GetTextAttribute(WORD &rwAttributes)
Definition: Console.cpp:858
TCHAR * m_pchBuffer2
Definition: Console.h:47
BOOL WriteChar(TCHAR ch)
Definition: Console.cpp:990
CConsole()
Definition: Console.cpp:50
BOOL m_blnInsetMode
Definition: Console.h:42
void DisableWrite()
Definition: Console.cpp:1064
DWORD m_dwOverwriteModeCursorHeight
Definition: Console.h:44
BOOL ReadLine()
Definition: Console.cpp:249
COORD m_BufferSize
Definition: Console.h:37
BOOL Write(const TCHAR *p, DWORD dwChars=0)
Definition: Console.cpp:90
DWORD m_dwInsertModeCursorHeight
Definition: Console.h:43
BOOL m_blnDisableWrite
Definition: Console.h:53
void EnableWrite()
Definition: Console.cpp:1080
DWORD m_dwBufferSize
Definition: Console.h:48
void SetReplaceCompletionCallback(ReplaceCompletionCallback pfCallback)
Definition: Console.cpp:1058
void AddHistoryLine(const TCHAR *pchLine)
Definition: TextHistory.cpp:62
BOOL Init(DWORD dwMaxHistoryLineSize, DWORD dwMaxHistoryLines)
Definition: TextHistory.cpp:44
const TCHAR * GetHistoryLine(DWORD dwIndex)
Definition: TextHistory.cpp:83
static VOID Paste(PGUI_CONSOLE_DATA GuiData)
Definition: conwnd.c:2080
#define BufferSize
Definition: mmc.h:75
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define CloseHandle
Definition: compat.h:739
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
BOOL WINAPI GetConsoleMode(HANDLE hConsoleHandle, LPDWORD lpMode)
Definition: console.c:1569
BOOL WINAPI DECLSPEC_HOTPATCH SetConsoleMode(HANDLE hConsoleHandle, DWORD dwMode)
Definition: console.c:1606
BOOL WINAPI DECLSPEC_HOTPATCH GenerateConsoleCtrlEvent(DWORD dwCtrlEvent, DWORD dwProcessGroupId)
Definition: console.c:2132
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
unsigned short WORD
Definition: ntddk_ex.h:93
GLfloat GLfloat p
Definition: glext.h:8902
LPVOID NTAPI GlobalLock(HGLOBAL hMem)
Definition: heapmem.c:755
BOOL NTAPI GlobalUnlock(HGLOBAL hMem)
Definition: heapmem.c:1190
#define stderr
Definition: stdio.h:100
#define _istspace
Definition: tchar.h:1504
#define _tcsnset
Definition: tchar.h:1419
#define _tcscpy
Definition: tchar.h:623
#define _tcsncpy
Definition: tchar.h:1410
#define _ftprintf
Definition: tchar.h:518
#define _istprint
Definition: tchar.h:1500
#define pch(ap)
Definition: match.c:418
#define ASSERT(a)
Definition: mode.c:44
wchar_t UNICODE
Definition: ms-dtyp.idl:111
#define L(x)
Definition: ntvdm.h:50
short SHORT
Definition: pedump.c:59
#define long
Definition: qsort.c:33
CHAR AsciiChar
Definition: wincon.h:185
WCHAR UnicodeChar
Definition: wincon.h:184
union _CHAR_INFO::@3285 Char
WORD Attributes
Definition: wincon.h:187
Definition: bl.h:1338
ULONG Y
Definition: bl.h:1340
ULONG X
Definition: bl.h:1339
union _INPUT_RECORD::@3287 Event
WORD EventType
Definition: wincon.h:273
KEY_EVENT_RECORD KeyEvent
Definition: wincon.h:275
DWORD dwControlKeyState
Definition: wincon.h:248
WORD wVirtualKeyCode
Definition: wincon.h:242
WORD wRepeatCount
Definition: wincon.h:241
union _KEY_EVENT_RECORD::@3286 uChar
WCHAR UnicodeChar
Definition: wincon.h:245
SHORT Top
Definition: tui.c:25
SHORT Right
Definition: tui.c:26
SHORT Left
Definition: tui.c:24
SHORT Bottom
Definition: tui.c:27
static COORD Position
Definition: mouse.c:34
#define VERIFY(e)
Definition: ph.h:34
#define _T(x)
Definition: vfdio.h:22
int ret
_In_ WDFMEMORY _Out_opt_ size_t * BufferSize
Definition: wdfmemory.h:254
#define STD_OUTPUT_HANDLE
Definition: winbase.h:268
#define STD_INPUT_HANDLE
Definition: winbase.h:267
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
*nSize LPSTR _Inout_ LPDWORD nSize
Definition: winbase.h:2084
#define CTRL_C_EVENT
Definition: wincon.h:68
#define LEFT_CTRL_PRESSED
Definition: wincon.h:140
#define SHIFT_PRESSED
Definition: wincon.h:141
#define ReadConsoleInput
Definition: wincon.h:778
#define KEY_EVENT
Definition: wincon.h:128
#define RIGHT_CTRL_PRESSED
Definition: wincon.h:139
#define SetConsoleTitle
Definition: wincon.h:783
#define WriteConsoleInput
Definition: wincon.h:785
#define ScrollConsoleScreenBuffer
Definition: wincon.h:782
#define WriteConsoleOutput
Definition: wincon.h:787
BOOL WINAPI CloseClipboard(void)
Definition: ntwrapper.h:178
#define VK_CANCEL
Definition: winuser.h:2192
#define VK_UP
Definition: winuser.h:2225
BOOL WINAPI OpenClipboard(_In_opt_ HWND)
HANDLE WINAPI GetClipboardData(_In_ UINT)
#define VK_END
Definition: winuser.h:2222
#define VK_HOME
Definition: winuser.h:2223
#define VK_LEFT
Definition: winuser.h:2224
#define VK_RIGHT
Definition: winuser.h:2226
#define VK_DOWN
Definition: winuser.h:2227
#define VK_DELETE
Definition: winuser.h:2233
#define VK_ESCAPE
Definition: winuser.h:2214
BOOL WINAPI IsClipboardFormatAvailable(_In_ UINT)
#define VK_INSERT
Definition: winuser.h:2232
char TCHAR
Definition: xmlstorage.h:189
CHAR * LPTSTR
Definition: xmlstorage.h:192
#define _tcslen
Definition: xmlstorage.h:198