xref: /reactos/base/setup/usetup/mui.c (revision 05c39d8d)
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                                 (USHORT)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     ULONG Index = 0;
329 
330     /* Get the MUI entry */
331     entry = MUIGetEntry(Page, TextID);
332 
333     if (!entry)
334         return;
335 
336     /* Ensure that the text string given by the text ID and page is not NULL */
337     while (entry[Index].Buffer != NULL)
338     {
339         /* If text ID is not correct, skip the entry */
340         if (entry[Index].TextID != TextID)
341         {
342             Index++;
343             continue;
344         }
345 
346         /* Remove the text by using CONSOLE_ClearTextXY() */
347         CONSOLE_ClearTextXY(
348             entry[Index].X,
349             entry[Index].Y,
350             (USHORT)strlen(entry[Index].Buffer));
351 
352         /* Increment the index and loop over next entires with the same ID */
353         Index++;
354     }
355 }
356 
357 /**
358  * @MUIClearStyledText
359  *
360  * Clears a portion of text from the console output, given the actual state style flag of the text.
361  *
362  * @param[in]   Page
363  *     The MUI (Multilingual User Interface) entry page number, as a unsigned long integer.
364  *
365  * @param[in]   TextID
366  *      The text identification number (ID), as an integer. The parameter is used to identify
367  *      its MUI properties like the coordinates, text style flag and its buffer content.
368  *
369  * @param[in]   Flags
370  *      The text style flag, as an integer. The flag determines the style of the text, such
371  *      as being highlighted, underlined, high padding and so on.
372  *
373  * @return
374  *     Nothing.
375  *
376  */
377 VOID
378 MUIClearStyledText(
379     IN ULONG Page,
380     IN INT TextID,
381     IN INT Flags)
382 {
383     const MUI_ENTRY * entry;
384     ULONG Index = 0;
385 
386     /* Get the MUI entry */
387     entry = MUIGetEntry(Page, TextID);
388 
389     if (!entry)
390         return;
391 
392     /* Ensure that the text string given by the text ID and page is not NULL */
393     while (entry[Index].Buffer != NULL)
394     {
395         /* If text ID is not correct, skip the entry */
396         if (entry[Index].TextID != TextID)
397         {
398             Index++;
399             continue;
400         }
401 
402         /* Now, begin removing the text by calling CONSOLE_ClearStyledText() */
403         CONSOLE_ClearStyledText(
404             entry[Index].X,
405             entry[Index].Y,
406             Flags,
407             (USHORT)strlen(entry[Index].Buffer));
408 
409         /* Increment the index and loop over next entires with the same ID */
410         Index++;
411     }
412 }
413 
414 /**
415  * @MUISetText
416  *
417  * Prints a text to the console output.
418  *
419  * @param[in]   Page
420  *     The MUI (Multilingual User Interface) entry page number, as a unsigned long integer.
421  *
422  * @param[in]   TextID
423  *      The text identification number (ID), as an integer. The parameter is used to identify
424  *      its MUI properties like the coordinates, text style flag and its buffer content.
425  *
426  * @return
427  *     Nothing.
428  *
429  */
430 VOID
431 MUISetText(
432     IN ULONG Page,
433     IN INT TextID)
434 {
435     const MUI_ENTRY * entry;
436     ULONG Index = 0;
437 
438     /* Get the MUI entry */
439     entry = MUIGetEntry(Page, TextID);
440 
441     if (!entry)
442         return;
443 
444     /* Ensure that the text string given by the text ID and page is not NULL */
445     while (entry[Index].Buffer != NULL)
446     {
447         /* If text ID is not correct, skip the entry */
448         if (entry[Index].TextID != TextID)
449         {
450             Index++;
451             continue;
452         }
453 
454         /* Print the text to the console output by calling CONSOLE_SetTextXY() */
455         CONSOLE_SetTextXY(entry[Index].X, entry[Index].Y, entry[Index].Buffer);
456 
457         /* Increment the index and loop over next entires with the same ID */
458         Index++;
459     }
460 }
461 
462 /**
463  * @MUISetStyledText
464  *
465  * Prints a text to the console output, with a style for it.
466  *
467  * @param[in]   Page
468  *     The MUI (Multilingual User Interface) entry page number, as a unsigned long integer.
469  *
470  * @param[in]   TextID
471  *      The text identification number (ID), as an integer. The parameter is used to identify
472  *      its MUI properties like the coordinates, text style flag and its buffer content.
473  *
474  *  @param[in]   Flags
475  *      The text style flag, as an integer. The flag determines the style of the text, such
476  *      as being highlighted, underlined, high padding and so on.
477  *
478  * @return
479  *     Nothing.
480  *
481  */
482 VOID
483 MUISetStyledText(
484     IN ULONG Page,
485     IN INT TextID,
486     IN INT Flags)
487 {
488     const MUI_ENTRY * entry;
489     ULONG Index = 0;
490 
491     /* Get the MUI entry */
492     entry = MUIGetEntry(Page, TextID);
493 
494     if (!entry)
495         return;
496 
497     /* Ensure that the text string given by the text ID and page is not NULL */
498     while (entry[Index].Buffer != NULL)
499     {
500         /* If text ID is not correct, skip the entry */
501         if (entry[Index].TextID != TextID)
502         {
503             Index++;
504             continue;
505         }
506 
507         /* Print the text to the console output by calling CONSOLE_SetStyledText() */
508         CONSOLE_SetStyledText(entry[Index].X, entry[Index].Y, Flags, entry[Index].Buffer);
509 
510         /* Increment the index and loop over next entires with the same ID */
511         Index++;
512     }
513 }
514 
515 VOID
516 SetConsoleCodePage(VOID)
517 {
518     UINT wCodePage;
519 
520 #if 0
521     ULONG lngIndex = 0;
522 
523     while (ResourceList[lngIndex].MuiPages != NULL)
524     {
525         if (_wcsicmp(ResourceList[lngIndex].LanguageID, SelectedLanguageId) == 0)
526         {
527             wCodePage = (UINT) wcstoul(ResourceList[lngIndex].OEMCPage, NULL, 10);
528             SetConsoleOutputCP(wCodePage);
529             return;
530         }
531 
532         lngIndex++;
533     }
534 #else
535     wCodePage = (UINT)wcstoul(MUIGetOEMCodePage(SelectedLanguageId), NULL, 10);
536     SetConsoleOutputCP(wCodePage);
537 #endif
538 }
539 
540 /* EOF */
541