2 * This file is part of MPlayer.
4 * MPlayer is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * MPlayer is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 #include "osdep/getch2.h"
27 #ifdef CONFIG_TRANSLATION
40 #define WIN32_LEAN_AND_MEAN
43 short stdoutAttrs
= 0;
44 HANDLE hConOut
= INVALID_HANDLE_VALUE
;
45 static const unsigned char ansi2win32
[10]=
50 FOREGROUND_GREEN
| FOREGROUND_RED
,
52 FOREGROUND_BLUE
| FOREGROUND_RED
,
53 FOREGROUND_BLUE
| FOREGROUND_GREEN
,
54 FOREGROUND_BLUE
| FOREGROUND_GREEN
| FOREGROUND_RED
,
55 FOREGROUND_BLUE
| FOREGROUND_GREEN
| FOREGROUND_RED
,
56 FOREGROUND_BLUE
| FOREGROUND_GREEN
| FOREGROUND_RED
60 /* maximum message length of mp_msg */
61 #define MSGSIZE_MAX 3072
63 int mp_msg_levels
[MSGT_MAX
]; // verbose level of this module. initialized to -2
64 int mp_msg_level_all
= MSGL_STATUS
;
67 int mp_msg_module
= 0;
69 char *mp_msg_charset
= NULL
;
70 static char *old_charset
= NULL
;
71 static iconv_t msgiconv
;
74 const char* filename_recode(const char* filename
)
76 #if !defined(CONFIG_ICONV) || !defined(MSG_CHARSET)
79 static iconv_t inv_msgiconv
= (iconv_t
)(-1);
80 static char recoded_filename
[MSGSIZE_MAX
];
81 size_t filename_len
, max_path
;
83 if (!mp_msg_charset
||
84 !strcasecmp(mp_msg_charset
, MSG_CHARSET
) ||
85 !strcasecmp(mp_msg_charset
, "noconv"))
87 if (inv_msgiconv
== (iconv_t
)(-1)) {
88 inv_msgiconv
= iconv_open(MSG_CHARSET
, mp_msg_charset
);
89 if (inv_msgiconv
== (iconv_t
)(-1))
92 filename_len
= strlen(filename
);
93 max_path
= MSGSIZE_MAX
- 4;
94 precoded
= recoded_filename
;
95 if (iconv(inv_msgiconv
, &filename
, &filename_len
,
96 &precoded
, &max_path
) == (size_t)(-1) && errno
== E2BIG
) {
97 precoded
[0] = precoded
[1] = precoded
[2] = '.';
101 return recoded_filename
;
105 void mp_msg_init(void){
107 char *env
= getenv("MPLAYER_VERBOSE");
110 for(i
=0;i
<MSGT_MAX
;i
++) mp_msg_levels
[i
] = -2;
111 mp_msg_levels
[MSGT_IDENTIFY
] = -1; // no -identify output by default
113 mp_msg_charset
= getenv("MPLAYER_CHARSET");
115 mp_msg_charset
= get_term_charset();
117 #ifdef CONFIG_TRANSLATION
118 textdomain("mplayer");
119 char *localedir
= getenv("MPLAYER_LOCALEDIR");
120 if (localedir
== NULL
&& strlen(MPLAYER_LOCALEDIR
))
121 localedir
= MPLAYER_LOCALEDIR
;
122 bindtextdomain("mplayer", localedir
);
123 bind_textdomain_codeset("mplayer", "UTF-8");
127 CONSOLE_SCREEN_BUFFER_INFO cinfo
;
130 hConOut
= GetStdHandle(STD_OUTPUT_HANDLE
);
131 if ((hConOut
== NULL
) || (hConOut
== INVALID_HANDLE_VALUE
))
134 fprintf(stderr
, "Cannot get Console handle of stdout\n");
138 GetConsoleMode(hConOut
, &cmode
);
139 cmode
|= (ENABLE_PROCESSED_OUTPUT
| ENABLE_WRAP_AT_EOL_OUTPUT
);
140 SetConsoleMode(hConOut
, cmode
);
142 GetConsoleScreenBufferInfo(hConOut
, &cinfo
);
143 stdoutAttrs
= cinfo
.wAttributes
;
148 int mp_msg_test(int mod
, int lev
)
150 return lev
<= (mp_msg_levels
[mod
] == -2 ? mp_msg_level_all
+ verbose
: mp_msg_levels
[mod
]);
153 static void set_msg_color(FILE* stream
, int lev
)
155 static const unsigned char v_colors
[10] = {9, 1, 3, 15, 7, 2, 2, 8, 8, 8};
156 int c
= v_colors
[lev
];
158 /* that's only a silly color test */
163 for(c
= 0; c
< 24; c
++)
164 printf("\033[%d;3%dm*** COLOR TEST %d ***\n", c
>7, c
&7, c
);
171 SetConsoleTextAttribute(hConOut
, ansi2win32
[c
] | FOREGROUND_INTENSITY
);
174 fprintf(stream
, "\033[%d;3%dm", c
>> 3, c
& 7);
178 static void print_msg_module(FILE* stream
, int mod
)
180 static const char *module_text
[MSGT_MAX
] = {
228 int c2
= (mod
+ 1) % 15 + 1;
233 SetConsoleTextAttribute(hConOut
, ansi2win32
[c2
&7] | FOREGROUND_INTENSITY
);
234 fprintf(stream
, "%9s", module_text
[mod
]);
236 SetConsoleTextAttribute(hConOut
, stdoutAttrs
);
239 fprintf(stream
, "\033[%d;3%dm", c2
>> 3, c2
& 7);
240 fprintf(stream
, "%9s", module_text
[mod
]);
242 fprintf(stream
, "\033[0;37m");
244 fprintf(stream
, ": ");
247 void mp_msg_va(int mod
, int lev
, const char *format
, va_list va
)
249 char tmp
[MSGSIZE_MAX
];
250 FILE *stream
= lev
<= MSGL_WARN
? stderr
: stdout
;
251 static int header
= 1;
253 if (!mp_msg_test(mod
, lev
)) return; // do not display
254 vsnprintf(tmp
, MSGSIZE_MAX
, format
, va
);
255 tmp
[MSGSIZE_MAX
-2] = '\n';
256 tmp
[MSGSIZE_MAX
-1] = 0;
258 #if defined(CONFIG_ICONV) && defined(MSG_CHARSET)
259 if (mp_msg_charset
&& strcasecmp(mp_msg_charset
, "noconv")) {
260 char tmp2
[MSGSIZE_MAX
];
261 size_t inlen
= strlen(tmp
), outlen
= MSGSIZE_MAX
;
262 char *in
= tmp
, *out
= tmp2
;
263 if (!old_charset
|| strcmp(old_charset
, mp_msg_charset
)) {
266 iconv_close(msgiconv
);
268 msgiconv
= iconv_open(mp_msg_charset
, MSG_CHARSET
);
269 old_charset
= strdup(mp_msg_charset
);
271 if (msgiconv
== (iconv_t
)(-1)) {
272 fprintf(stderr
,"iconv: conversion from %s to %s unsupported\n"
273 ,MSG_CHARSET
,mp_msg_charset
);
275 memset(tmp2
, 0, MSGSIZE_MAX
);
276 while (iconv(msgiconv
, &in
, &inlen
, &out
, &outlen
) == -1) {
277 if (!inlen
|| !outlen
)
282 strncpy(tmp
, tmp2
, MSGSIZE_MAX
);
283 tmp
[MSGSIZE_MAX
-1] = 0;
284 tmp
[MSGSIZE_MAX
-2] = '\n';
290 print_msg_module(stream
, mod
);
291 set_msg_color(stream
, lev
);
292 header
= tmp
[strlen(tmp
)-1] == '\n' || tmp
[strlen(tmp
)-1] == '\r';
294 fprintf(stream
, "%s", tmp
);
296 fprintf(stream
, "\033[0m");
300 void mp_msg(int mod
, int lev
, const char *format
, ...)
303 va_start(va
, format
);
304 mp_msg_va(mod
, lev
, format
, va
);
308 char *mp_gtext(const char *string
)
310 #ifdef CONFIG_TRANSLATION
311 /* gettext expects the global locale to be set with
312 * setlocale(LC_ALL, ""). However doing that would suck for a
313 * couple of reasons (locale stuff is badly designed and sucks in
316 * First setting the locale, especially LC_CTYPE, changes the
317 * behavior of various C functions and we don't want that - we
318 * want isalpha() for example to always behave like in the C
321 * Second, there is no way to enforce a sane character set. All
322 * strings inside MPlayer must always be in utf-8, not in the
323 * character set specified by the system locale which could be
324 * something different and completely insane. The locale system
325 * lacks any way to say "set LC_CTYPE to utf-8, ignoring the
326 * default system locale if it specifies something different". We
327 * could try to work around that flaw by leaving LC_CTYPE to the C
328 * locale and only setting LC_MESSAGES (which is the variable that
329 * must be set to tell gettext which language to translate
330 * to). However if we leave LC_MESSAGES set then things like
331 * strerror() may produce completely garbled output when they try
332 * to translate their results but then try to convert some
333 * translated non-ASCII text to the character set specified by
334 * LC_CTYPE which would still be in the C locale (this doesn't
335 * affect gettext itself because it supports specifying the
336 * character set directly with bind_textdomain_codeset()).
338 * So the only solution (at leat short of trying to work around
339 * things possibly producing non-utf-8 output) is to leave all the
340 * locale variables unset. Note that this means it's not possible
341 * to get translated output from any libraries we call if they
342 * only rely on the broken locale system to specify the language
343 * to use; this is the case with libc for example.
345 * The locale changing below is rather ugly, but hard to avoid.
346 * gettext doesn't support specifying the translation target
347 * directly, only through locale.
348 * The main actual problem this could cause is interference with
349 * other threads; that could be avoided with thread-specific
350 * locale changes, but such functionality is less standard and I
351 * think it's not worth adding pre-emptively unless someone sees
352 * an actual problem case.
354 setlocale(LC_MESSAGES
, "");
355 string
= gettext(string
);
356 setlocale(LC_MESSAGES
, "C");
361 void mp_tmsg(int mod
, int lev
, const char *format
, ...)
364 va_start(va
, format
);
365 mp_msg_va(mod
, lev
, mp_gtext(format
), va
);