xref: /reactos/base/setup/usetup/mui.c (revision a1fc312a)
1 /*
2  *  ReactOS kernel
3  *  Copyright (C) 2008 ReactOS Team
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License along
16  *  with this program; if not, write to the Free Software Foundation, Inc.,
17  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  */
19 /*
20  * COPYRIGHT:       See COPYING in the top level directory
21  * PROJECT:         ReactOS text-mode setup
22  * FILE:            base/setup/usetup/mui.c
23  * PURPOSE:         Text-mode setup
24  * PROGRAMMER:
25  */
26 
27 #include "usetup.h"
28 #include "muilanguages.h"
29 
30 #define NDEBUG
31 #include <debug.h>
32 
33 static
34 ULONG
35 FindLanguageIndex(VOID)
36 {
37     ULONG lngIndex = 0;
38 
39     if (SelectedLanguageId == NULL)
40     {
41         /* Default to en-US */
42         return 0;   // FIXME!!
43         // SelectedLanguageId = L"00000409";
44     }
45 
46     while (ResourceList[lngIndex].MuiPages != NULL)
47     {
48         if (_wcsicmp(ResourceList[lngIndex].LanguageID, SelectedLanguageId) == 0)
49         {
50             return lngIndex;
51         }
52 
53         lngIndex++;
54     }
55 
56     return 0;
57 }
58 
59 
60 #if 0
61 BOOLEAN
62 IsLanguageAvailable(
63     PWCHAR LanguageId)
64 {
65     ULONG lngIndex = 0;
66 
67     while (ResourceList[lngIndex].MuiPages != NULL)
68     {
69         if (_wcsicmp(ResourceList[lngIndex].LanguageID, LanguageId) == 0)
70             return TRUE;
71 
72         lngIndex++;
73     }
74 
75     return FALSE;
76 }
77 #endif
78 
79 
80 static
81 const MUI_ENTRY *
82 FindMUIEntriesOfPage(
83     IN ULONG PageNumber)
84 {
85     ULONG muiIndex = 0;
86     ULONG lngIndex;
87     const MUI_PAGE * Pages = NULL;
88 
89     lngIndex = max(FindLanguageIndex(), 0);
90     Pages = ResourceList[lngIndex].MuiPages;
91 
92     while (Pages[muiIndex].MuiEntry != NULL)
93     {
94         if (Pages[muiIndex].Number == PageNumber)
95             return Pages[muiIndex].MuiEntry;
96 
97         muiIndex++;
98     }
99 
100     return NULL;
101 }
102 
103 static
104 const MUI_ERROR *
105 FindMUIErrorEntries(VOID)
106 {
107     ULONG lngIndex = max(FindLanguageIndex(), 0);
108     return ResourceList[lngIndex].MuiErrors;
109 }
110 
111 static
112 const MUI_STRING *
113 FindMUIStringEntries(VOID)
114 {
115     ULONG lngIndex = max(FindLanguageIndex(), 0);
116     return ResourceList[lngIndex].MuiStrings;
117 }
118 
119 
120 VOID
121 MUIClearPage(
122     IN ULONG page)
123 {
124     const MUI_ENTRY * entry;
125     ULONG index;
126 
127     entry = FindMUIEntriesOfPage(page);
128     if (!entry)
129     {
130         PopupError("Error: Failed to find translated page",
131                    NULL,
132                    NULL,
133                    POPUP_WAIT_NONE);
134         return;
135     }
136 
137     index = 0;
138     while (entry[index].Buffer != NULL)
139     {
140         CONSOLE_ClearStyledText(entry[index].X,
141                                 entry[index].Y,
142                                 entry[index].Flags,
143                                 strlen(entry[index].Buffer));
144         index++;
145     }
146 }
147 
148 VOID
149 MUIDisplayPage(
150     IN ULONG page)
151 {
152     const MUI_ENTRY * entry;
153     ULONG index;
154 
155     entry = FindMUIEntriesOfPage(page);
156     if (!entry)
157     {
158         PopupError("Error: Failed to find translated page",
159                    NULL,
160                    NULL,
161                    POPUP_WAIT_NONE);
162         return;
163     }
164 
165     index = 0;
166     while (entry[index].Buffer != NULL)
167     {
168         CONSOLE_SetStyledText(entry[index].X,
169                               entry[index].Y,
170                               entry[index].Flags,
171                               entry[index].Buffer);
172 
173         index++;
174     }
175 }
176 
177 VOID
178 MUIDisplayErrorV(
179     IN ULONG ErrorNum,
180     OUT PINPUT_RECORD Ir,
181     IN ULONG WaitEvent,
182     IN va_list args)
183 {
184     const MUI_ERROR* entry;
185     CHAR Buffer[2048];
186 
187     if (ErrorNum >= ERROR_LAST_ERROR_CODE)
188     {
189         PopupError("Invalid error number provided",
190                    "Press ENTER to continue",
191                    Ir,
192                    POPUP_WAIT_ENTER);
193         return;
194     }
195 
196     entry = FindMUIErrorEntries();
197     if (!entry)
198     {
199         PopupError("Error: Failed to find translated error message",
200                    NULL,
201                    NULL,
202                    POPUP_WAIT_NONE);
203         return;
204     }
205 
206     vsprintf(Buffer, entry[ErrorNum].ErrorText, args);
207 
208     PopupError(Buffer,
209                entry[ErrorNum].ErrorStatus,
210                Ir,
211                WaitEvent);
212 }
213 
214 VOID
215 __cdecl
216 MUIDisplayError(
217     IN ULONG ErrorNum,
218     OUT PINPUT_RECORD Ir,
219     IN ULONG WaitEvent,
220     ...)
221 {
222     va_list arg_ptr;
223 
224     va_start(arg_ptr, WaitEvent);
225     MUIDisplayErrorV(ErrorNum, Ir, WaitEvent, arg_ptr);
226     va_end(arg_ptr);
227 }
228 
229 PCSTR
230 MUIGetString(
231     ULONG Number)
232 {
233     ULONG i;
234     const MUI_STRING * entry;
235     CHAR szErr[128];
236 
237     entry = FindMUIStringEntries();
238     if (entry)
239     {
240         for (i = 0; entry[i].Number != 0; i++)
241         {
242             if (entry[i].Number == Number)
243             {
244                 return entry[i].String;
245             }
246         }
247     }
248 
249     sprintf(szErr, "Error: failed find string id %lu for language index %lu\n", Number, FindLanguageIndex());
250 
251     PopupError(szErr,
252                NULL,
253                NULL,
254                POPUP_WAIT_NONE);
255 
256     return "<nostring>";
257 }
258 
259 /**
260  * @MUIGetEntry
261  *
262  * Retrieves a MUI entry of a page, given the page number and the text ID.
263  *
264  * @param[in]   Page
265  *     The MUI (Multilingual User Interface) entry page number, as a unsigned long integer.
266  *
267  * @param[in]   TextID
268  *      The text identification number (ID), as a unsigned integer. The parameter is used to identify
269  *      its MUI properties like the coordinates, text style flag and its buffer content.
270  *
271  * @return
272  *     Returns a constant MUI entry.
273  *
274  */
275 const MUI_ENTRY *
276 MUIGetEntry(
277     IN ULONG Page,
278     IN INT TextID)
279 {
280     const MUI_ENTRY * entry;
281     ULONG index;
282 
283     /* Retrieve the entries of a MUI page */
284     entry = FindMUIEntriesOfPage(Page);
285     if (!entry)
286     {
287         DPRINT("MUIGetEntryData(): Failed to get the translated entry page!\n");
288         return NULL;
289     }
290 
291     /* Loop over the ID entries and check if it matches with one of them */
292     for (index = 0; entry[index].Buffer != NULL; index++)
293     {
294         if (entry[index].TextID == TextID)
295         {
296             /* They match so return the MUI entry */
297             return &entry[index];
298         }
299     }
300 
301     /* Page number or ID are incorrect so in this case bail out */
302     DPRINT("Couldn't get the MUI entry field from the page!\n");
303     return NULL;
304 }
305 
306 /**
307  * @MUIClearText
308  *
309  * Clears a portion of text from the console output.
310  *
311  * @param[in]   Page
312  *     The MUI (Multilingual User Interface) entry page number, as a unsigned long integer.
313  *
314  * @param[in]   TextID
315  *      The text identification number (ID), as an integer. The parameter is used to identify
316  *      its MUI properties like the coordinates, text style flag and its buffer content.
317  *
318  * @return
319  *     Nothing.
320  *
321  */
322 VOID
323 MUIClearText(
324     IN ULONG Page,
325     IN INT TextID)
326 {
327     const MUI_ENTRY * entry;
328 
329     /* Get the MUI entry */
330     entry = MUIGetEntry(Page, TextID);
331 
332     if (!entry)
333         return;
334 
335     /* Remove the text by using CONSOLE_ClearTextXY() */
336     CONSOLE_ClearTextXY(
337         entry->X,
338         entry->Y,
339         (ULONG)strlen(entry->Buffer));
340 }
341 
342 /**
343  * @MUIClearStyledText
344  *
345  * Clears a portion of text from the console output, given the actual state style flag of the text.
346  *
347  * @param[in]   Page
348  *     The MUI (Multilingual User Interface) entry page number, as a unsigned long integer.
349  *
350  * @param[in]   TextID
351  *      The text identification number (ID), as an integer. The parameter is used to identify
352  *      its MUI properties like the coordinates, text style flag and its buffer content.
353  *
354  * @param[in]   Flags
355  *      The text style flag, as an integer. The flag determines the style of the text, such
356  *      as being highlighted, underlined, high padding and so on.
357  *
358  * @return
359  *     Nothing.
360  *
361  */
362 VOID
363 MUIClearStyledText(
364     IN ULONG Page,
365     IN INT TextID,
366     IN INT Flags)
367 {
368     const MUI_ENTRY * entry;
369 
370     /* Get the MUI entry */
371     entry = MUIGetEntry(Page, TextID);
372 
373     if (!entry)
374         return;
375 
376     /* Now, begin removing the text by calling CONSOLE_ClearStyledText() */
377     CONSOLE_ClearStyledText(
378         entry->X,
379         entry->Y,
380         Flags,
381         (ULONG)strlen(entry->Buffer));
382 }
383 
384 /**
385  * @MUISetText
386  *
387  * Prints a text to the console output.
388  *
389  * @param[in]   Page
390  *     The MUI (Multilingual User Interface) entry page number, as a unsigned long integer.
391  *
392  * @param[in]   TextID
393  *      The text identification number (ID), as an integer. The parameter is used to identify
394  *      its MUI properties like the coordinates, text style flag and its buffer content.
395  *
396  * @return
397  *     Nothing.
398  *
399  */
400 VOID
401 MUISetText(
402     IN ULONG Page,
403     IN INT TextID)
404 {
405     const MUI_ENTRY * entry;
406 
407     /* Get the MUI entry */
408     entry = MUIGetEntry(Page, TextID);
409 
410     if (!entry)
411         return;
412 
413     /* Print the text to the console output by calling CONSOLE_SetTextXY() */
414     CONSOLE_SetTextXY(entry->X, entry->Y, entry->Buffer);
415 }
416 
417 /**
418  * @MUISetStyledText
419  *
420  * Prints a text to the console output, with a style for it.
421  *
422  * @param[in]   Page
423  *     The MUI (Multilingual User Interface) entry page number, as a unsigned long integer.
424  *
425  * @param[in]   TextID
426  *      The text identification number (ID), as an integer. The parameter is used to identify
427  *      its MUI properties like the coordinates, text style flag and its buffer content.
428  *
429  *  @param[in]   Flags
430  *      The text style flag, as an integer. The flag determines the style of the text, such
431  *      as being highlighted, underlined, high padding and so on.
432  *
433  * @return
434  *     Nothing.
435  *
436  */
437 VOID
438 MUISetStyledText(
439     IN ULONG Page,
440     IN INT TextID,
441     IN INT Flags)
442 {
443     const MUI_ENTRY * entry;
444 
445     /* Get the MUI entry */
446     entry = MUIGetEntry(Page, TextID);
447 
448     if (!entry)
449         return;
450 
451     /* Print the text to the console output by calling CONSOLE_SetStyledText() */
452     CONSOLE_SetStyledText(entry->X, entry->Y, Flags, entry->Buffer);
453 }
454 
455 VOID
456 SetConsoleCodePage(VOID)
457 {
458     UINT wCodePage;
459 
460 #if 0
461     ULONG lngIndex = 0;
462 
463     while (ResourceList[lngIndex].MuiPages != NULL)
464     {
465         if (_wcsicmp(ResourceList[lngIndex].LanguageID, SelectedLanguageId) == 0)
466         {
467             wCodePage = (UINT) wcstoul(ResourceList[lngIndex].OEMCPage, NULL, 10);
468             SetConsoleOutputCP(wCodePage);
469             return;
470         }
471 
472         lngIndex++;
473     }
474 #else
475     wCodePage = (UINT)wcstoul(MUIGetOEMCodePage(SelectedLanguageId), NULL, 10);
476     SetConsoleOutputCP(wCodePage);
477 #endif
478 }
479 
480 /* EOF */
481