xref: /reactos/sdk/lib/conutils/screen.c (revision c2c66aff)
1 /*
2  * COPYRIGHT:       See COPYING in the top level directory
3  * PROJECT:         ReactOS Console Utilities Library
4  * FILE:            sdk/lib/conutils/screen.c
5  * PURPOSE:         Console/terminal screen management.
6  * PROGRAMMERS:     - Hermes Belusca-Maito (for the library);
7  *                  - All programmers who wrote the different console applications
8  *                    from which I took those functions and improved them.
9  */
10 
11 /* FIXME: Temporary HACK before we cleanly support UNICODE functions */
12 #define UNICODE
13 #define _UNICODE
14 
15 #include <stdlib.h> // limits.h // For MB_LEN_MAX
16 
17 #include <windef.h>
18 #include <winbase.h>
19 // #include <winnls.h>
20 #include <wincon.h>  // Console APIs (only if kernel32 support included)
21 #include <strsafe.h>
22 
23 #include "conutils.h"
24 #include "stream.h"
25 #include "screen.h"
26 
27 // Temporary HACK
28 #define CON_STREAM_WRITE    ConStreamWrite
29 
30 
31 #if 0
32 
33 VOID
34 ConClearLine(IN PCON_STREAM Stream)
35 {
36     HANDLE hOutput = ConStreamGetOSHandle(Stream);
37 
38     /*
39      * Erase the full line where the cursor is, and move
40      * the cursor back to the beginning of the line.
41      */
42 
43     if (IsConsoleHandle(hOutput))
44     {
45         CONSOLE_SCREEN_BUFFER_INFO csbi;
46         DWORD dwWritten;
47 
48         GetConsoleScreenBufferInfo(hOutput, &csbi);
49 
50         csbi.dwCursorPosition.X = 0;
51         // csbi.dwCursorPosition.Y;
52 
53         FillConsoleOutputCharacterW(hOutput, L' ',
54                                     csbi.dwSize.X,
55                                     csbi.dwCursorPosition,
56                                     &dwWritten);
57         SetConsoleCursorPosition(hOutput, csbi.dwCursorPosition);
58     }
59     else if (IsTTYHandle(hOutput))
60     {
61         ConPuts(Stream, L"\x1B[2K\x1B[1G"); // FIXME: Just use WriteFile
62     }
63     // else, do nothing for files
64 }
65 
66 #endif
67 
68 
69 BOOL
70 ConGetScreenInfo(
71     IN PCON_SCREEN Screen,
72     OUT PCONSOLE_SCREEN_BUFFER_INFO pcsbi)
73 {
74     BOOL Success;
75     HANDLE hOutput;
76 
77     /* Parameters validation */
78     if (!Screen || !pcsbi)
79         return FALSE;
80 
81     hOutput = ConStreamGetOSHandle(Screen->Stream);
82 
83     /* Screen handle must be of TTY type (console or TTY) */
84     if (!IsTTYHandle(hOutput))
85         return FALSE;
86 
87     /* Update cached screen information */
88     if (IsConsoleHandle(hOutput))
89     {
90         Success = GetConsoleScreenBufferInfo(hOutput, &Screen->csbi);
91     }
92     else
93     {
94 #if 0
95         /* TODO: Do something adequate for TTYs */
96         // FIXME: At the moment we return hardcoded info.
97         Screen->csbi.dwSize.X = 80;
98         Screen->csbi.dwSize.Y = 25;
99 
100         // Screen->csbi.dwCursorPosition;
101         // Screen->csbi.wAttributes;
102         // Screen->csbi.srWindow;
103         Screen->csbi.dwMaximumWindowSize = Screen->csbi.dwSize;
104 #else
105         hOutput = CreateFileW(L"CONOUT$", GENERIC_READ|GENERIC_WRITE,
106                              FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,
107                              OPEN_EXISTING, 0, NULL);
108 
109         Success = IsConsoleHandle(hOutput) &&
110                   GetConsoleScreenBufferInfo(hOutput, &Screen->csbi);
111 
112         CloseHandle(hOutput);
113 #endif
114     }
115 
116     if (Success)
117     {
118         /* Return it to the caller */
119         *pcsbi = Screen->csbi;
120     }
121 
122     return Success;
123 }
124 
125 // For real consoles, erase everything, otherwise (TTY) erase just the "screen".
126 // FIXME: Or we can add a BOOL flag?
127 VOID
128 ConClearScreen(IN PCON_SCREEN Screen)
129 {
130     HANDLE hOutput;
131 
132     /* Parameters validation */
133     if (!Screen) return;
134 
135 #if 0
136     /* Get the size of the visual screen */
137     if (!ConGetScreenInfo(Screen, &csbi))
138     {
139         /* We assume it's a file handle */
140         return;
141     }
142 #endif
143 
144     hOutput = ConStreamGetOSHandle(Screen->Stream);
145 
146     if (IsConsoleHandle(hOutput))
147     {
148         CONSOLE_SCREEN_BUFFER_INFO csbi;
149         COORD coPos;
150         DWORD dwWritten;
151 
152         GetConsoleScreenBufferInfo(hOutput, &csbi);
153 
154         coPos.X = 0;
155         coPos.Y = 0;
156         FillConsoleOutputAttribute(hOutput, csbi.wAttributes,
157                                    csbi.dwSize.X * csbi.dwSize.Y,
158                                    coPos, &dwWritten);
159         FillConsoleOutputCharacterW(hOutput, L' ',
160                                     csbi.dwSize.X * csbi.dwSize.Y,
161                                     coPos, &dwWritten);
162         SetConsoleCursorPosition(hOutput, coPos);
163     }
164     else if (IsTTYHandle(hOutput))
165     {
166         /* Clear the full screen and move the cursor to (0,0) */
167         ConPuts(Screen->Stream, L"\x1B[2J\x1B[1;1H");
168     }
169     else
170     {
171         /* Issue a Form-Feed control */
172         WCHAR ch = L'\f';
173         CON_STREAM_WRITE(Screen->Stream, &ch, 1);
174     }
175 }
176