source: trunk/Lucide/SOURCE/gui/luutils.cpp @ 133

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

cleanup, small fixes

File size: 15.5 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#define INCL_GPI
38#include <os2.h>
39
40#include <time.h>
41#include <stdio.h>
42#include <string.h>
43#include <strstrea.h>
44#include <string>
45
46#include "luutils.h"
47#include "messages.h"
48
49bool initCountryInfo();
50
51static COUNTRYINFO CtryInfo;
52static bool countryInfoLoaded = initCountryInfo();
53
54
55afbuf::afbuf( unsigned int s )
56{
57    size = s;
58    buffer = new char[ s ];
59    memset( buffer, 0, s );
60}
61
62
63BOOL CreateGraphicsBuffer( HAB hab, PRECTL prectl, HPS hps,
64                           HPS *phpsBuffer, HDC *phdcBuffer )
65{
66    LONG cPlanes;
67    LONG cBitCount;
68    ULONG ulFlags;
69    HBITMAP hbm;
70    BITMAPINFOHEADER bmp;
71    SIZEL sizl;
72    FONTMETRICS fm;
73    FATTRS fat;
74    SIZEF sizf;
75    HPS hpsBuffer;
76    HDC hdc, hdcBuffer;
77    hdc = GpiQueryDevice( hps );
78    ulFlags = GpiQueryPS( hps, &sizl );
79
80    hdcBuffer = DevOpenDC( hab, OD_MEMORY, "*",  0L, NULL, hdc );
81    if ( hdcBuffer )
82    {
83        sizl.cx = sizl.cy = 0;
84
85        hpsBuffer = GpiCreatePS( hab, hdcBuffer, &sizl, ulFlags | GPIA_ASSOC );
86
87        *phpsBuffer = hpsBuffer;
88        *phdcBuffer = hdcBuffer;
89
90        DevQueryCaps( hdc, CAPS_COLOR_PLANES, 1L, &cPlanes );
91        DevQueryCaps( hdc, CAPS_COLOR_BITCOUNT, 1L, &cBitCount );
92
93        bmp.cbFix     = sizeof( BITMAPINFOHEADER );
94        bmp.cx        = (SHORT)( prectl->xRight - prectl->xLeft );
95        bmp.cy        = (SHORT)( prectl->yTop - prectl->yBottom );
96        bmp.cPlanes   = (SHORT)cPlanes;
97        bmp.cBitCount = (SHORT)cBitCount;
98
99        hbm = GpiCreateBitmap( hpsBuffer, (PBITMAPINFOHEADER2)&bmp,
100                               0x0000, NULL, NULL );
101        if ( hbm )
102        {
103            GpiSetBitmap( hpsBuffer, hbm );
104            GpiQueryFontMetrics( hps, sizeof( FONTMETRICS ), &fm );
105
106            memset( &fat, 0, sizeof( fat ) );
107
108            fat.usRecordLength = sizeof( FATTRS );
109            fat.lMatch = fm.lMatch;
110            strcpy( fat.szFacename, fm.szFacename );
111
112            GpiDeleteSetId( hpsBuffer, 1L );
113            GpiCreateLogFont( hpsBuffer, 0, 1L, &fat );
114            GpiSetCharSet( hpsBuffer, 1L );
115
116            sizf.cx = MAKEFIXED( fm.lEmInc, 0 );
117            sizf.cy = MAKEFIXED( fm.lMaxBaselineExt, 0 );
118            GpiSetCharBox( hpsBuffer, &sizf );
119
120            return TRUE;
121        }
122
123        GpiDestroyPS( hpsBuffer );
124        DevCloseDC( hdcBuffer );
125        hpsBuffer = hdcBuffer = NULLHANDLE;
126    }
127
128    return FALSE;
129}
130
131void BlitGraphicsBuffer( HPS hps, HPS hpsBuffer, PRECTL prclPaint )
132{
133    POINTL aptl[ 3 ];
134
135    aptl[ 0 ].x = prclPaint->xLeft;
136    aptl[ 0 ].y = prclPaint->yBottom;
137    aptl[ 1 ].x = prclPaint->xRight;
138    aptl[ 1 ].y = prclPaint->yTop;
139    aptl[ 2 ].x = prclPaint->xLeft;
140    aptl[ 2 ].y = prclPaint->yBottom;
141
142    GpiBitBlt( hps, hpsBuffer, 3L, aptl, ROP_SRCCOPY, BBO_IGNORE );
143}
144
145void DestroyGraphicsBuffer( HPS hpsBuffer, HDC hdcBuffer )
146{
147    if( hpsBuffer && hdcBuffer )
148    {
149        HBITMAP hbm = GpiSetBitmap( hpsBuffer, NULLHANDLE );
150
151        if ( hbm != NULLHANDLE ) {
152            GpiDeleteBitmap( hbm );
153        }
154
155        GpiDestroyPS( hpsBuffer );
156        DevCloseDC( hdcBuffer );
157
158        hpsBuffer = hdcBuffer = NULLHANDLE;
159    }
160}
161
162
163char *newstrdup( const char *s )
164{
165    if ( s == NULL ) {
166        return NULL;
167    }
168    char *temp = new char[ strlen( s ) + 1 ];
169    strcpy( temp, s );
170    return temp;
171}
172
173
174struct ER_WINDOW_POS
175{
176    SWP    Swp;
177    USHORT XRestore;
178    USHORT YRestore;
179    USHORT CXRestore;
180    USHORT CYRestore;
181    USHORT XMinimize;
182    USHORT YMinimize;
183};
184
185
186BOOL PMRestoreWindowPos( PCSZ pIniName, PCSZ pAppName, PCSZ pKeyName,
187                         HWND hwnd, BOOL activate, BOOL chkCoord,
188                         BOOL min, BOOL max, BOOL hide )
189{
190    HINI          hini;
191    ER_WINDOW_POS wp;
192    ULONG         ulWpSize = sizeof( ER_WINDOW_POS );
193    ULONG         SwpOptions = SWP_MOVE | SWP_SIZE | SWP_SHOW;
194    BOOL          rval = FALSE;
195
196    if ( activate && !hide ) {
197        SwpOptions |= SWP_ACTIVATE;
198    }
199
200    if ( pIniName == NULL ) { // ¯šè¥¬ ¢ user profile
201        hini = HINI_USER;
202    }
203    else {
204        hini = PrfOpenProfile( WinQueryAnchorBlock( hwnd ), pIniName );
205    }
206
207    if ( hini != NULLHANDLE )
208    {
209        if ( PrfQueryProfileData( hini, pAppName, pKeyName, &wp, &ulWpSize ) )
210        {
211            if ( wp.Swp.fl & SWP_MAXIMIZE ) {
212                SwpOptions |= SWP_MAXIMIZE;
213            }
214            else if ( wp.Swp.fl & SWP_MINIMIZE ) {
215                SwpOptions |= SWP_MINIMIZE;
216            }
217
218            if ( min ) {
219                SwpOptions &= ~SWP_MAXIMIZE;
220                SwpOptions |= SWP_MINIMIZE;
221            }
222            if ( max ) {
223                SwpOptions &= ~SWP_MINIMIZE;
224                SwpOptions |= SWP_MAXIMIZE;
225            }
226            if ( hide ) {
227                SwpOptions &= ~SWP_SHOW;
228                SwpOptions |= SWP_HIDE;
229            }
230
231            if ( chkCoord )
232            {
233                LONG sx, sy;
234                sx = WinQuerySysValue( HWND_DESKTOP, SV_CXSCREEN );
235                sy = WinQuerySysValue( HWND_DESKTOP, SV_CYSCREEN );
236
237                if ( wp.Swp.x > sx ) {
238                    wp.Swp.x = sx - wp.Swp.cx;
239                }
240                if ( wp.Swp.y > sy ) {
241                    wp.Swp.y = sy - wp.Swp.cy;
242                }
243            }
244
245            WinSetWindowPos( hwnd, NULLHANDLE,
246                             wp.Swp.x, wp.Swp.y, wp.Swp.cx, wp.Swp.cy,
247                             SwpOptions );
248
249            WinSetWindowUShort( hwnd, QWS_XRESTORE,  wp.XRestore );
250            WinSetWindowUShort( hwnd, QWS_YRESTORE,  wp.YRestore );
251            WinSetWindowUShort( hwnd, QWS_CXRESTORE, wp.CXRestore );
252            WinSetWindowUShort( hwnd, QWS_CYRESTORE, wp.CYRestore );
253            WinSetWindowUShort( hwnd, QWS_XMINIMIZE, wp.XMinimize );
254            WinSetWindowUShort( hwnd, QWS_YMINIMIZE, wp.YMinimize );
255            rval = TRUE;
256        }
257
258        if ( pIniName != NULL ) {
259            PrfCloseProfile( hini );
260        }
261    }
262    return rval;
263}
264
265void PMStoreWindowPosI( HINI ini, PCSZ pAppName, PCSZ pKeyName, HWND hwnd )
266{
267    ER_WINDOW_POS wp;
268
269    WinQueryWindowPos( hwnd, &wp.Swp );
270    wp.XRestore  = WinQueryWindowUShort( hwnd, QWS_XRESTORE );
271    wp.YRestore  = WinQueryWindowUShort( hwnd, QWS_YRESTORE );
272    wp.CXRestore = WinQueryWindowUShort( hwnd, QWS_CXRESTORE );
273    wp.CYRestore = WinQueryWindowUShort( hwnd, QWS_CYRESTORE );
274    wp.XMinimize = WinQueryWindowUShort( hwnd, QWS_XMINIMIZE );
275    wp.YMinimize = WinQueryWindowUShort( hwnd, QWS_YMINIMIZE );
276
277    PrfWriteProfileData( ini, pAppName, pKeyName, &wp, sizeof( wp ) );
278}
279
280BOOL PMStoreWindowPos( PCSZ pIniName, PCSZ pAppName, PCSZ pKeyName, HWND hwnd )
281{
282    HAB           hab = WinQueryAnchorBlock( hwnd );
283    HINI          hini;
284    BOOL          rval = FALSE;
285
286    if ( pIniName == NULL )
287    {
288        PMStoreWindowPosI( HINI_USER, pAppName, pKeyName, hwnd );
289        rval = TRUE;
290    }
291    else
292    {
293        if ( ( hini = PrfOpenProfile( hab, pIniName ) ) != NULLHANDLE )
294        {
295            PMStoreWindowPosI( hini, pAppName, pKeyName, hwnd );
296            PrfCloseProfile( hini );
297            rval = TRUE;
298        }
299    }
300    return rval;
301}
302
303
304SHORT getStringPixSize( HPS hps, PCSZ str )
305{
306    POINTL ptl[ 3 ] = { 0 };
307    GpiQueryTextBox( hps, strlen( str ), (PSZ)str, 3, ptl );
308    return (SHORT)( ptl[ 2 ].x - ptl[ 0 ].x );
309}
310
311
312static void end_zeros_trim( char *s )
313{
314    size_t l = strlen( s );
315    char *end_str = ( s + l ) - 1;
316
317    while ( *end_str == '0' ) {
318        *end_str-- = 0;
319    }
320
321    if ( *end_str == '.' ) {
322        *end_str = 0;
323    }
324}
325
326std::string str( double n )
327{
328    char *pt;
329    char buf[ 60 ];
330    memset( buf, 0, sizeof buf );
331
332    ostrstream o( buf, sizeof buf );
333    o.flags( ios::dec | ios::showpoint | ios::fixed );
334    o << n;
335    end_zeros_trim( buf );
336
337    return buf;
338}
339
340
341void centerWindow( HWND parent, HWND hwnd )
342{
343    SWP swpf;
344    WinQueryWindowPos( parent, &swpf );
345    SWP swp;
346    WinQueryWindowPos( hwnd, &swp );
347    POINTL ptl = { ( swpf.cx - swp.cx ) / 2, ( swpf.cy - swp.cy ) / 2 };
348    WinMapWindowPoints( parent, HWND_DESKTOP, &ptl, 1 );
349    WinSetWindowPos( hwnd, HWND_TOP, ptl.x, ptl.y, 0, 0, SWP_MOVE );
350}
351
352
353static bool initCountryInfo()
354{
355    static const char *pmnkey = "PM_National";
356
357    memset( &CtryInfo, 0, sizeof( COUNTRYINFO ) );
358    COUNTRYCODE Country   = {0};
359    ULONG       ulInfoLen = 0;
360
361    DosQueryCtryInfo( sizeof( CtryInfo ), &Country, &CtryInfo, &ulInfoLen );
362
363    char buf[ 10 ];
364    PrfQueryProfileString( HINI_USERPROFILE, pmnkey, "sDate",
365                           CtryInfo.szDateSeparator, buf, sizeof( buf ) );
366    CtryInfo.szDateSeparator[ 0 ] = buf[ 0 ];
367    PrfQueryProfileString( HINI_USERPROFILE, pmnkey, "sTime",
368                           CtryInfo.szTimeSeparator, buf, sizeof( buf ) );
369    CtryInfo.szTimeSeparator[ 0 ] = buf[ 0 ];
370    PrfQueryProfileString( HINI_USERPROFILE, pmnkey, "sDecimal",
371                           CtryInfo.szDecimal, buf, sizeof( buf ) );
372    CtryInfo.szDecimal[ 0 ] = buf[ 0 ];
373    PrfQueryProfileString( HINI_USERPROFILE, pmnkey, "sThousand",
374                           CtryInfo.szThousandsSeparator, buf, sizeof( buf ) );
375    CtryInfo.szThousandsSeparator[ 0 ] = buf[ 0 ];
376    PrfQueryProfileString( HINI_USERPROFILE, pmnkey, "sList",
377                           CtryInfo.szDataSeparator, buf, sizeof( buf ) );
378    CtryInfo.szDataSeparator[ 0 ] = buf[ 0 ];
379
380    return true;
381}
382
383
384static const char *format01 = "%02d%s%02d%s%04d";
385static const char *format23 = "%04d%s%02d%s%02d";
386
387static void dateToStr( struct tm *tmbuf, char *buf, int buflen )
388{
389    switch ( CtryInfo.fsDateFmt )
390    {
391        case 0:
392            snprintf( buf, buflen, format01,
393                      tmbuf->tm_mon + 1, CtryInfo.szDateSeparator, tmbuf->tm_mday,
394                      CtryInfo.szDateSeparator, tmbuf->tm_year + 1900 );
395            break;
396        case 1:
397            snprintf( buf, buflen, format01,
398                      tmbuf->tm_mday, CtryInfo.szDateSeparator, tmbuf->tm_mon + 1,
399                      CtryInfo.szDateSeparator, tmbuf->tm_year + 1900 );
400            break;
401        case 2:
402            snprintf( buf, buflen, format23,
403                      tmbuf->tm_year + 1900, CtryInfo.szDateSeparator,
404                      tmbuf->tm_mon + 1, CtryInfo.szDateSeparator, tmbuf->tm_mday );
405            break;
406        case 3:
407            snprintf( buf, buflen, format23,
408                      tmbuf->tm_year + 1900, CtryInfo.szDateSeparator,
409                      tmbuf->tm_mday, CtryInfo.szDateSeparator, tmbuf->tm_mon + 1 );
410            break;
411    }
412}
413
414static const char *format0 = "%d%s%02d%s%02d %s";
415static const char *format1 = "%02d%s%02d%s%02d";
416
417static void timeToStr( struct tm *tmbuf, char *buf, int buflen )
418{
419    switch ( CtryInfo.fsTimeFmt )
420    {
421        case 0:
422            snprintf( buf, buflen, format0,
423                      (int)( ( tmbuf->tm_hour > 12 ) ? ( tmbuf->tm_hour - 12 ) :
424                                                         tmbuf->tm_hour ),
425                      CtryInfo.szTimeSeparator, (int)tmbuf->tm_min,
426                      CtryInfo.szTimeSeparator, (int)tmbuf->tm_sec,
427                      (char *)( ( tmbuf->tm_hour < 12 ) ? "AM" : "PM" ) );
428            break;
429        case 1:
430            snprintf( buf, buflen, format1, tmbuf->tm_hour,
431                      CtryInfo.szTimeSeparator, tmbuf->tm_min,
432                      CtryInfo.szTimeSeparator, tmbuf->tm_sec );
433            break;
434    }
435}
436
437std::string time2string( unsigned long time )
438{
439    struct tm tmbuf = { 0 };
440    _localtime( &time, &tmbuf );
441    char datbuf[ 16 ] = "";
442    char timbuf[ 16 ] = "";
443    dateToStr( &tmbuf, datbuf, sizeof( datbuf ) );
444    timeToStr( &tmbuf, timbuf, sizeof( timbuf ) );
445
446    std::string s = datbuf;
447    s += "  ";
448    s += timbuf;
449
450    return s;
451}
452
453SHORT setZoomValues( HWND lbox )
454{
455    char *actsizetext = newstrdupL( TBHINT_ACTUAL_SIZE );
456    char *fitwindtext = newstrdupL( TBHINT_FIT_WINDOW );
457    char *fitwidthtext = newstrdupL( TBHINT_FIT_WIDTH );
458    WinSetWindowText( lbox, actsizetext );
459    WinInsertLboxItem( lbox, LIT_END, actsizetext );
460    WinInsertLboxItem( lbox, LIT_END, fitwindtext );
461    WinInsertLboxItem( lbox, LIT_END, fitwidthtext );
462    WinInsertLboxItem( lbox, LIT_END, "12.5%" );
463    WinInsertLboxItem( lbox, LIT_END, "25%" );
464    WinInsertLboxItem( lbox, LIT_END, "50%" );
465    WinInsertLboxItem( lbox, LIT_END, "100%" );
466    WinInsertLboxItem( lbox, LIT_END, "125%" );
467    WinInsertLboxItem( lbox, LIT_END, "150%" );
468    WinInsertLboxItem( lbox, LIT_END, "200%" );
469    WinInsertLboxItem( lbox, LIT_END, "300%" );
470    WinInsertLboxItem( lbox, LIT_END, "400%" );
471    WinInsertLboxItem( lbox, LIT_END, "800%" );
472    WinInsertLboxItem( lbox, LIT_END, "1600%" );
473
474    HPS hps = WinGetPS( lbox );
475    SHORT actsizelen = getStringPixSize( hps, actsizetext );
476    SHORT fitwindlen = getStringPixSize( hps, fitwindtext );
477    SHORT fitwidthlen = getStringPixSize( hps, fitwidthtext );
478    WinReleasePS( hps );
479
480    delete fitwidthtext;
481    delete fitwindtext;
482    delete actsizetext;
483
484    return __max( actsizelen, __max( fitwindlen, fitwidthlen ) );
485}
486
487double convZoom( SHORT v )
488{
489    double z = -3;
490    switch ( v )
491    {
492        case 0:   z = 1;      break;
493        case 1:   z = -2;     break;
494        case 2:   z = -1;     break;
495        case 3:   z = 0.125;  break;
496        case 4:   z = 0.25;   break;
497        case 5:   z = 0.5;    break;
498        case 6:   z = 1;      break;
499        case 7:   z = 1.25;   break;
500        case 8:   z = 1.5;    break;
501        case 9:   z = 2;      break;
502        case 10:  z = 3;      break;
503        case 11:  z = 4;      break;
504        case 12:  z = 8;      break;
505        case 13:  z = 16;     break;
506    }
507    return z;
508}
Note: See TracBrowser for help on using the repository browser.