xref: /reactos/base/shell/cmd/prompt.c (revision 019f21ee)
1 /*
2  *  PROMPT.C - prompt handling.
3  *
4  *
5  *  History:
6  *
7  *    14/01/95 (Tim Normal)
8  *        started.
9  *
10  *    08/08/95 (Matt Rains)
11  *        i have cleaned up the source code. changes now bring this source
12  *        into guidelines for recommended programming practice.
13  *
14  *    01/06/96 (Tim Norman)
15  *        added day of the week printing (oops, forgot about that!)
16  *
17  *    08/07/96 (Steffan Kaiser)
18  *        small changes for speed
19  *
20  *    20-Jul-1998 (John P Price <linux-guru@gcfl.net>)
21  *        removed redundant day strings. Use ones defined in date.c.
22  *
23  *    27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
24  *        added config.h include
25  *
26  *    28-Jul-1998 (John P Price <linux-guru@gcfl.net>)
27  *        moved cmd_prompt from internal.c to here
28  *
29  *    09-Dec-1998 (Eric Kohl)
30  *        Added help text ("/?").
31  *
32  *    14-Dec-1998 (Eric Kohl)
33  *        Added "$+" option.
34  *
35  *    09-Jan-1999 (Eric Kohl)
36  *        Added "$A", "$C" and "$F" option.
37  *        Added locale support.
38  *        Fixed "$V" option.
39  *
40  *    20-Jan-1999 (Eric Kohl)
41  *        Unicode and redirection safe!
42  *
43  *    24-Jan-1999 (Eric Kohl)
44  *        Fixed Win32 environment handling.
45  *
46  *    30-Apr-2005 (Magnus Olsen <magnus@greatlord.com>)
47  *        Remove all hardcoded strings in En.rc
48  */
49 #include "precomp.h"
50 
51 /* The default prompt */
52 static TCHAR DefaultPrompt[] = _T("$P$G");
53 
54 /*
55  * Initialize prompt support.
56  */
57 VOID InitPrompt(VOID)
58 {
59     TCHAR Buffer[2];
60 
61     /*
62      * Set the PROMPT environment variable if it doesn't exist already.
63      * You can change the PROMPT environment variable before cmd starts.
64      */
65     if (GetEnvironmentVariable(_T("PROMPT"), Buffer, _countof(Buffer)) == 0)
66         SetEnvironmentVariable(_T("PROMPT"), DefaultPrompt);
67 }
68 
69 /*
70  * Print an information line on top of the screen.
71  */
72 VOID PrintInfoLine(VOID)
73 {
74 #define FOREGROUND_WHITE (FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY)
75 
76     HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
77     CONSOLE_SCREEN_BUFFER_INFO csbi;
78     COORD coPos;
79     DWORD dwWritten;
80 
81     PTSTR pszInfoLine = NULL;
82     INT iInfoLineLen;
83 
84     /* Return directly if the output handle is not a console handle */
85     if (!GetConsoleScreenBufferInfo(hOutput, &csbi))
86         return;
87 
88     iInfoLineLen = LoadString(CMD_ModuleHandle, STRING_CMD_INFOLINE, (PTSTR)&pszInfoLine, 0);
89     if (!pszInfoLine || iInfoLineLen == 0)
90         return;
91 
92     /* Display the localized information line */
93     coPos.X = 0;
94     coPos.Y = 0;
95     FillConsoleOutputAttribute(hOutput, BACKGROUND_BLUE | FOREGROUND_WHITE,
96                                csbi.dwSize.X,
97                                coPos, &dwWritten);
98     FillConsoleOutputCharacter(hOutput, _T(' '),
99                                csbi.dwSize.X,
100                                coPos, &dwWritten);
101 
102     WriteConsoleOutputCharacter(hOutput, pszInfoLine, iInfoLineLen,
103                                 coPos, &dwWritten);
104 }
105 
106 /*
107  * Print the command-line prompt.
108  */
109 VOID PrintPrompt(VOID)
110 {
111     LPTSTR pr, Prompt;
112     TCHAR szPrompt[256];
113     TCHAR szPath[MAX_PATH];
114 
115     if (GetEnvironmentVariable(_T("PROMPT"), szPrompt, _countof(szPrompt)))
116         Prompt = szPrompt;
117     else
118         Prompt = DefaultPrompt;
119 
120     /*
121      * Special pre-handling for $I: If the information line is displayed
122      * on top of the screen, ensure that the prompt won't be hidden below it.
123      */
124     for (pr = Prompt; *pr;)
125     {
126         if (*pr++ != _T('$'))
127             continue;
128         if (!*pr || _totupper(*pr++) != _T('I'))
129             continue;
130 
131         if (GetCursorY() == 0)
132             ConOutChar(_T('\n'));
133         break;
134     }
135 
136     /* Parse the prompt string */
137     for (pr = Prompt; *pr; ++pr)
138     {
139         if (*pr != _T('$'))
140         {
141             ConOutChar(*pr);
142         }
143         else
144         {
145             ++pr;
146             if (!*pr) break;
147             switch (_totupper(*pr))
148             {
149                 case _T('A'):
150                     ConOutChar(_T('&'));
151                     break;
152 
153                 case _T('B'):
154                     ConOutChar(_T('|'));
155                     break;
156 
157                 case _T('C'):
158                     ConOutChar(_T('('));
159                     break;
160 
161                 case _T('D'):
162                     ConOutPrintf(_T("%s"), GetDateString());
163                     break;
164 
165                 case _T('E'):
166                     ConOutChar(_T('\x1B'));
167                     break;
168 
169                 case _T('F'):
170                     ConOutChar(_T(')'));
171                     break;
172 
173                 case _T('G'):
174                     ConOutChar(_T('>'));
175                     break;
176 
177                 case _T('H'):
178                     ConOutPuts(_T("\x08 \x08"));
179                     break;
180 
181                 case _T('I'):
182                     PrintInfoLine();
183                     break;
184 
185                 case _T('L'):
186                     ConOutChar(_T('<'));
187                     break;
188 
189                 case _T('N'):
190                 {
191                     GetCurrentDirectory(_countof(szPath), szPath);
192                     ConOutChar(szPath[0]);
193                     break;
194                 }
195 
196                 case _T('P'):
197                 {
198                     GetCurrentDirectory(_countof(szPath), szPath);
199                     ConOutPrintf(_T("%s"), szPath);
200                     break;
201                 }
202 
203                 case _T('Q'):
204                     ConOutChar(_T('='));
205                     break;
206 
207                 case _T('S'):
208                     ConOutChar(_T(' '));
209                     break;
210 
211                 case _T('T'):
212                     ConOutPrintf(_T("%s"), GetTimeString());
213                     break;
214 
215                 case _T('V'):
216                     PrintOSVersion();
217                     break;
218 
219                 case _T('_'):
220                     ConOutChar(_T('\n'));
221                     break;
222 
223                 case _T('$'):
224                     ConOutChar(_T('$'));
225                     break;
226 
227 #ifdef FEATURE_DIRECTORY_STACK
228                 case _T('+'):
229                 {
230                     INT i;
231                     for (i = 0; i < GetDirectoryStackDepth(); i++)
232                         ConOutChar(_T('+'));
233                     break;
234                 }
235 #endif
236             }
237         }
238     }
239 }
240 
241 
242 #ifdef INCLUDE_CMD_PROMPT
243 
244 INT cmd_prompt(LPTSTR param)
245 {
246     if (!_tcsncmp(param, _T("/?"), 2))
247     {
248         ConOutResPaging(TRUE, STRING_PROMPT_HELP1);
249 
250 #ifdef FEATURE_DIRECTORY_STACK
251         ConOutResPaging(FALSE, STRING_PROMPT_HELP2);
252 #endif
253         ConOutResPaging(FALSE, STRING_PROMPT_HELP3);
254         return 0;
255     }
256 
257     /*
258      * Set the PROMPT environment variable. If 'param' is NULL or is
259      * an empty string (the user entered "prompt" only), then remove
260      * the environment variable and therefore use the default prompt.
261      * Otherwise, use the new prompt.
262      */
263     if (!SetEnvironmentVariable(_T("PROMPT"),
264                                 (param && param[0] != _T('\0') ? param : NULL)))
265     {
266         return 1;
267     }
268 
269     return 0;
270 }
271 #endif
272 
273 /* EOF */
274