source: trunk/Lucide/gui/intern.cpp @ 367

Last change on this file since 367 was 367, checked in by dmik, 11 years ago

Merged bramches/kmk (r294:365) to trunk.

File size: 9.4 KB
Line 
1/* ***** BEGIN LICENSE BLOCK *****
2 * Version: CDDL 1.0/LGPL 2.1
3 *
4 * The contents of this file are subject to the COMMON DEVELOPMENT AND
5 * DISTRIBUTION LICENSE (CDDL) Version 1.0 (the "License"); you may not use
6 * this file except in compliance with the License. You may obtain a copy of
7 * the License at http://www.sun.com/cddl/
8 *
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
12 * License.
13 *
14 * The Initial Developer of the Original Code is
15 * Eugene Romanenko, netlabs.org.
16 * Portions created by the Initial Developer are Copyright (C) 2006
17 * the Initial Developer. All Rights Reserved.
18 *
19 * Contributor(s):
20 *
21 * Alternatively, the contents of this file may be used under the terms of
22 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
23 * in which case the provisions of the LGPL are applicable instead of those
24 * above. If you wish to allow use of your version of this file only under the
25 * terms of the LGPL, and not to allow others to use your version of this file
26 * under the terms of the CDDL, indicate your decision by deleting the
27 * provisions above and replace them with the notice and other provisions
28 * required by the LGPL. If you do not delete the provisions above, a recipient
29 * may use your version of this file under the terms of any one of the CDDL
30 * or the LGPL.
31 *
32 * ***** END LICENSE BLOCK ***** */
33
34
35#include "os2all.h"
36
37#include <fstream>
38#include <map>
39#include <string>
40using namespace std;
41
42#include <stdlib.h>
43#include <stdio.h>
44#include <string.h>
45#include <io.h>
46#if !defined(__WATCOM__)
47#include <unistd.h>
48#endif
49
50#include "globals.h"
51#include "wwbtn.h"
52#include "luutils.h"
53
54#define LINEBUF_LEN     4096
55
56static bool langLoaded = false;
57
58static map<string,string> *langDefault = NULL;
59static map<string,string> *langCurrent = NULL;
60
61
62#define NUM_ESCAPES 3
63static const char *escapes[NUM_ESCAPES][2] = {
64    { "\\t", "\t" }, { "\\r", "\r" }, { "%APPNAME%", appName } };
65
66static string unescapeControls( const char *s )
67{
68    string r = s;
69    for ( int i = 0; i < NUM_ESCAPES; i++ )
70    {
71        string::size_type startpos = 0;
72        string::size_type findpos = string::npos;
73        while ( ( findpos = r.find( escapes[i][0], startpos ) ) != string::npos ) {
74            r.replace( findpos, strlen( escapes[i][0] ), escapes[i][1] );
75            startpos = findpos + 1;
76        }
77    }
78    return r;
79}
80
81
82static void loadLng( map<string,string> *array, const char *file, bool exitOnError )
83{
84    ifstream lngFile( file );
85    if ( !lngFile )
86    {
87        if ( exitOnError )
88        {
89            char msgbuf1[ 500 ];
90            char msgbuf2[ 100 ];
91            snprintf( msgbuf1, sizeof( msgbuf1 ),
92                      "Default language file \"%s\" not found!", file );
93            snprintf( msgbuf2, sizeof( msgbuf2 ), "%s error!", appName );
94
95            WinMessageBox( HWND_DESKTOP, HWND_DESKTOP, msgbuf1, msgbuf2,
96                           10000, MB_CANCEL | MB_ERROR | MB_ICONHAND | MB_MOVEABLE );
97
98            DosExit( EXIT_PROCESS, 1 );  // ??? exit() crashes
99        }
100        return;
101    }
102    else
103    {
104        char line[ LINEBUF_LEN ];
105
106        while ( !lngFile.eof() )
107        {
108            // @todo this code will treat the rest of the line which is longer
109            // than LINEBUF_LEN-1 chars as a new line which is wrong
110            lngFile.getline( line, LINEBUF_LEN );
111            if ( ( line[ 0 ] != '#' ) && ( line[ 0 ] != ' ' ) )
112            {
113                char *eqpos = NULL;
114                if ( ( eqpos = strchr( line, '=' ) ) != NULL )
115                {
116                    *eqpos = '\0';
117                    string key   = line;
118                    string value = unescapeControls( eqpos + 1 );
119                    (*array)[ key ] = value;
120                }
121            }
122        }
123
124        /*map<string,string>::const_iterator iter;
125        for ( iter=array->begin(); iter != array->end(); iter++ )
126        {
127            cout << "K:" << (*iter).first.c_str()
128                 << " V:" << (*iter).second.c_str() << endl;
129        }*/
130    }
131}
132
133static const char *lfilespec1 = "%sLUCIDE_%s_%s.LNG";
134static const char *lfilespec2 = "%sLUCIDE_%s.LNG";
135static const char *lfilespec3 = "%sLUCIDE.LNG";
136
137void loadLang()
138{
139    if ( langLoaded ) {
140        return;
141    }
142    langLoaded = true;
143
144    char appdir[ _MAX_PATH ];
145    char drive[ _MAX_DRIVE ];
146    char dir[ _MAX_DIR ];
147#if defined(__WATCOM__)
148    _splitpath( __argv[0], drive, dir, NULL, NULL );
149#else
150    _execname( appdir, sizeof(appdir) );
151    _splitpath( appdir, drive, dir, NULL, NULL );
152#endif
153    _makepath( appdir, drive, dir, NULL, NULL );
154
155    langDefault = new map<string,string>;
156    langCurrent = new map<string,string>;
157
158    afbuf lfile( _MAX_PATH );
159
160    snprintf( lfile.buffer, lfile.getSize(), lfilespec2, appdir, "EN" );
161    if ( access( lfile.buffer, F_OK ) == 0 ) {
162        loadLng( langDefault, lfile.buffer, true );
163    }
164    else {
165        snprintf( lfile.buffer, lfile.getSize(), lfilespec3, appdir );
166        loadLng( langDefault, lfile.buffer, true );
167    }
168
169    char *lng = getenv( "LANG" );
170    if ( lng == NULL ) {
171        return;
172    }
173
174    // Find language specifier
175    char *upos = strchr( lng, '_' );
176    if ( upos == NULL ) {
177        return;
178    }
179    int lngSpecLen = upos - lng;
180    if ( lngSpecLen > 2 ) {
181        return;
182    }
183    char lngSpec[ 4 ];
184    memset( lngSpec, 0, sizeof( lngSpec ) );
185    strncpy( lngSpec, lng, lngSpecLen );
186
187    // Find territory specifier
188    char *lrest = upos + 1;
189    char terrSpec[ 4 ];
190    memset( terrSpec, 0, sizeof( terrSpec ) );
191    if ( strlen( lrest ) >= 2 ) {
192        strncpy( terrSpec, lrest, 2 );
193    }
194
195    bool nlsLoaded = false;
196    if ( terrSpec[0] != 0 )
197    {
198        // First, search the file with territory specifier
199        snprintf( lfile.buffer, lfile.getSize(), lfilespec1, appdir, lngSpec, terrSpec );
200        if ( access( lfile.buffer, F_OK ) == 0 ) {
201            // File with territory specifier exist, load it
202            loadLng( langCurrent, lfile.buffer, false );
203            nlsLoaded = true;
204        }
205
206    }
207    if ( !nlsLoaded )
208    {
209        // File with territory specifier not found, load file without territory specifier
210        snprintf( lfile.buffer, lfile.getSize(), lfilespec2, appdir, lngSpec );
211        loadLng( langCurrent, lfile.buffer, false );
212    }
213}
214
215void localizeMenu( HWND hmenu )
216{
217    if ( hmenu == NULLHANDLE ) {
218        return;
219    }
220
221    afbuf mtext( 1024 );
222
223    SHORT id, len;
224    SHORT cnt = SHORT1FROMMR( WinSendMsg( hmenu, MM_QUERYITEMCOUNT, MPVOID, MPVOID ) );
225    for ( SHORT i = 0; i < cnt; i++ )
226    {
227        id = SHORT1FROMMR( WinSendMsg( hmenu, MM_ITEMIDFROMPOSITION, MPFROMSHORT( i ), MPVOID ) );
228
229        len = SHORT1FROMMR( WinSendMsg( hmenu, MM_QUERYITEMTEXT, MPFROM2SHORT( id, mtext.getSize() ),
230                                        MPFROMP( mtext.buffer ) ) );
231
232        if ( len > 0 )
233        {
234            string r = getLocalizedString( mtext.buffer );
235            if ( r != mtext.buffer ) {
236                WinSendMsg( hmenu, MM_SETITEMTEXT, MPFROMSHORT( id ), MPFROMP( r.c_str() ) );
237            }
238        }
239
240        MENUITEM mitem = { 0 };
241        BOOL itemQueried = (BOOL)WinSendMsg( hmenu, MM_QUERYITEM, MPFROM2SHORT( id, FALSE ),
242                                             MPFROMP( &mitem ) );
243        if ( itemQueried )
244        {
245            if ( mitem.afStyle & MIS_SUBMENU ) {
246                localizeMenu( mitem.hwndSubMenu );
247            }
248        }
249    }
250}
251
252void localizeDialog( HWND hdlg )
253{
254    if ( hdlg == NULLHANDLE ) {
255        return;
256    }
257
258    afbuf itemtext( 256 );
259
260    HWND  hwndNext;
261    LONG  lText;
262    HENUM henum = WinBeginEnumWindows( hdlg );
263
264    while ( ( hwndNext = WinGetNextWindow( henum ) ) != NULLHANDLE )
265    {
266        char clname[ 5 ];
267        WinQueryClassName( hwndNext, sizeof( clname ), clname );
268
269        if ( clname[0] == '#' )
270        {
271            lText = WinQueryWindowText( hwndNext, itemtext.getSize(), itemtext.buffer );
272            if ( lText )
273            {
274                string r = getLocalizedString( itemtext.buffer );
275                if ( r != itemtext.buffer )
276                {
277                    if ( clname[1] == '5' ) { // static
278                        if ( WinQueryWindowULong( hwndNext, QWL_STYLE ) & SS_TEXT ) {
279                            toWordWrapLabel( hwndNext );
280                        }
281                    }
282
283                    WinSetWindowText( hwndNext, r.c_str() );
284                }
285            }
286        }
287    }
288    WinEndEnumWindows( henum );
289}
290
291string getLocalizedString( const char *t )
292{
293    map<string,string>::const_iterator iter;
294
295    if ( ( iter = langCurrent->find( t ) ) == langCurrent->end() )
296    {
297        if ( ( iter = langDefault->find( t ) ) == langDefault->end() ) {
298            return t;
299        }
300    }
301
302    return (*iter).second;
303}
304
305void getLocalizedString( const char *key, LONG maxLen, char *buf )
306{
307    strncpy( buf, getLocalizedString( key ).c_str(), maxLen - 1 );
308}
309
310char *newstrdupL( const char *key )
311{
312    return newstrdup( getLocalizedString( key ).c_str() );
313}
314
Note: See TracBrowser for help on using the repository browser.