source: trunk/Lucide/SOURCE/gui/intern.cpp @ 242

Last change on this file since 242 was 136, checked in by Eugene Romanenko, 15 years ago

macro for .lng files

File size: 9.1 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#define INCL_DOS
36#define INCL_WIN
37#include <os2.h>
38
39#include <fstream>
40#include <map>
41#include <string>
42using namespace std;
43
44#include <stdlib.h>
45#include <stdio.h>
46#include <string.h>
47#include <io.h>
48
49#include "globals.h"
50#include "wwbtn.h"
51#include "luutils.h"
52
53#define LINEBUF_LEN     4096
54
55static bool langLoaded = false;
56
57static map<string,string> *langDefault = NULL;
58static map<string,string> *langCurrent = NULL;
59
60
61#define NUM_ESCAPES 3
62static const char *escapes[NUM_ESCAPES][2] = {
63    { "\\t", "\t" }, { "\\r", "\r" }, { "%APPNAME%", appName } };
64
65static string unescapeControls( const char *s )
66{
67    string r = s;
68    for ( int i = 0; i < NUM_ESCAPES; i++ )
69    {
70        string::size_type startpos = 0;
71        string::size_type findpos = string::npos;
72        while ( ( findpos = r.find( escapes[i][0], startpos ) ) != string::npos ) {
73            r.replace( findpos, strlen( escapes[i][0] ), escapes[i][1] );
74            startpos = findpos + 1;
75        }
76    }
77    return r;
78}
79
80
81static void loadLng( map<string,string> *array, const char *file, bool exitOnError )
82{
83    ifstream lngFile( file );
84    if ( !lngFile )
85    {
86        if ( exitOnError )
87        {
88            char msgbuf1[ 500 ];
89            char msgbuf2[ 100 ];
90            snprintf( msgbuf1, sizeof( msgbuf1 ),
91                      "Default language file \"%s\" not found!", file );
92            snprintf( msgbuf2, sizeof( msgbuf2 ), "%s error!", appName );
93
94            WinMessageBox( HWND_DESKTOP, HWND_DESKTOP, msgbuf1, msgbuf2,
95                           10000, MB_CANCEL | MB_ERROR | MB_ICONHAND | MB_MOVEABLE );
96
97            DosExit( EXIT_PROCESS, 1 );  // ??? exit() crashes
98        }
99        return;
100    }
101    else
102    {
103        char *line = new char[ LINEBUF_LEN ];
104
105        while ( !lngFile.eof() )
106        {
107            char ch;
108            lngFile.get( line, LINEBUF_LEN );
109            lngFile.get( ch );
110            if ( ( line[ 0 ] != '#' ) && ( line[ 0 ] != ' ' ) )
111            {
112                char *eqpos = NULL;
113                if ( ( eqpos = strchr( line, '=' ) ) != NULL )
114                {
115                    *eqpos = '\0';
116                    string key   = line;
117                    string value = unescapeControls( eqpos + 1 );
118                    (*array)[ key ] = value;
119                }
120            }
121        }
122
123        /*map<string,string>::const_iterator iter;
124        for ( iter=array->begin(); iter != array->end(); iter++ )
125        {
126            cout << "K:" << (*iter).first.c_str()
127                 << " V:" << (*iter).second.c_str() << endl;
128        }*/
129    }
130}
131
132static const char *lfilespec1 = "%sLUCIDE_%s_%s.LNG";
133static const char *lfilespec2 = "%sLUCIDE_%s.LNG";
134static const char *lfilespec3 = "%sLUCIDE.LNG";
135
136void loadLang()
137{
138    if ( langLoaded ) {
139        return;
140    }
141    langLoaded = true;
142
143    char appdir[ _MAX_PATH ];
144    char drive[ _MAX_DRIVE ];
145    char dir[ _MAX_DIR ];
146    _splitpath( __argv[0], drive, dir, NULL, NULL );
147    _makepath( appdir, drive, dir, NULL, NULL );
148
149    langDefault = new map<string,string>;
150    langCurrent = new map<string,string>;
151
152    afbuf lfile( _MAX_PATH );
153
154    snprintf( lfile.buffer, lfile.getSize(), lfilespec2, appdir, "EN" );
155    if ( access( lfile.buffer, F_OK ) == 0 ) {
156        loadLng( langDefault, lfile.buffer, true );
157    }
158    else {
159        snprintf( lfile.buffer, lfile.getSize(), lfilespec3, appdir );
160        loadLng( langDefault, lfile.buffer, true );
161    }
162
163    char *lng = getenv( "LANG" );
164    if ( lng == NULL ) {
165        return;
166    }
167
168    // Find language specifier
169    char *upos = strchr( lng, '_' );
170    if ( upos == NULL ) {
171        return;
172    }
173    int lngSpecLen = upos - lng;
174    if ( lngSpecLen > 2 ) {
175        return;
176    }
177    char lngSpec[ 4 ];
178    memset( lngSpec, 0, sizeof( lngSpec ) );
179    strncpy( lngSpec, lng, lngSpecLen );
180
181    // Find territory specifier
182    char *lrest = upos + 1;
183    char terrSpec[ 4 ];
184    memset( terrSpec, 0, sizeof( terrSpec ) );
185    if ( strlen( lrest ) >= 2 ) {
186        strncpy( terrSpec, lrest, 2 );
187    }
188
189    bool nlsLoaded = false;
190    if ( terrSpec[0] != 0 )
191    {
192        // First, search the file with territory specifier
193        snprintf( lfile.buffer, lfile.getSize(), lfilespec1, appdir, lngSpec, terrSpec );
194        if ( access( lfile.buffer, F_OK ) == 0 ) {
195            // File with territory specifier exist, load it
196            loadLng( langCurrent, lfile.buffer, false );
197            nlsLoaded = true;
198        }
199
200    }
201    if ( !nlsLoaded )
202    {
203        // File with territory specifier not found, load file without territory specifier
204        snprintf( lfile.buffer, lfile.getSize(), lfilespec2, appdir, lngSpec );
205        loadLng( langCurrent, lfile.buffer, false );
206    }
207}
208
209void localizeMenu( HWND hmenu )
210{
211    if ( hmenu == NULLHANDLE ) {
212        return;
213    }
214
215    afbuf mtext( 1024 );
216
217    SHORT id, len;
218    SHORT cnt = (SHORT)WinSendMsg( hmenu, MM_QUERYITEMCOUNT, MPVOID, MPVOID );
219    for ( SHORT i = 0; i < cnt; i++ )
220    {
221        id = (SHORT)WinSendMsg( hmenu, MM_ITEMIDFROMPOSITION, MPFROMSHORT( i ), MPVOID );
222
223        len = (SHORT)WinSendMsg( hmenu, MM_QUERYITEMTEXT, MPFROM2SHORT( id, mtext.getSize() ),
224                                 MPFROMP( mtext.buffer ) );
225
226        if ( len > 0 )
227        {
228            string r = getLocalizedString( mtext.buffer );
229            if ( r != mtext.buffer ) {
230                WinSendMsg( hmenu, MM_SETITEMTEXT, MPFROMSHORT( id ), MPFROMP( r.c_str() ) );
231            }
232        }
233
234        MENUITEM mitem = { 0 };
235        BOOL itemQueried = (BOOL)WinSendMsg( hmenu, MM_QUERYITEM, MPFROM2SHORT( id, FALSE ),
236                                             MPFROMP( &mitem ) );
237        if ( itemQueried )
238        {
239            if ( mitem.afStyle & MIS_SUBMENU ) {
240                localizeMenu( mitem.hwndSubMenu );
241            }
242        }
243    }
244}
245
246void localizeDialog( HWND hdlg )
247{
248    if ( hdlg == NULLHANDLE ) {
249        return;
250    }
251
252    afbuf itemtext( 256 );
253
254    HWND  hwndNext;
255    LONG  lText;
256    HENUM henum = WinBeginEnumWindows( hdlg );
257
258    while ( ( hwndNext = WinGetNextWindow( henum ) ) != NULLHANDLE )
259    {
260        char clname[ 5 ];
261        WinQueryClassName( hwndNext, sizeof( clname ), clname );
262
263        if ( clname[0] == '#' )
264        {
265            lText = WinQueryWindowText( hwndNext, itemtext.getSize(), itemtext.buffer );
266            if ( lText )
267            {
268                string r = getLocalizedString( itemtext.buffer );
269                if ( r != itemtext.buffer )
270                {
271                    if ( clname[1] == '5' ) { // static
272                        if ( WinQueryWindowULong( hwndNext, QWL_STYLE ) & SS_TEXT ) {
273                            toWordWrapLabel( hwndNext );
274                        }
275                    }
276
277                    WinSetWindowText( hwndNext, r.c_str() );
278                }
279            }
280        }
281    }
282    WinEndEnumWindows( henum );
283}
284
285string getLocalizedString( const char *t )
286{
287    map<string,string>::const_iterator iter;
288
289    if ( ( iter = langCurrent->find( t ) ) == langCurrent->end() )
290    {
291        if ( ( iter = langDefault->find( t ) ) == langDefault->end() ) {
292            return t;
293        }
294    }
295
296    return (*iter).second;
297}
298
299void getLocalizedString( const char *key, LONG maxLen, char *buf )
300{
301    strncpy( buf, getLocalizedString( key ).c_str(), maxLen - 1 );
302}
303
304char *newstrdupL( const char *key )
305{
306    return newstrdup( getLocalizedString( key ).c_str() );
307}
308
Note: See TracBrowser for help on using the repository browser.