1/* functions.m
2 * Common Cenon functions
3 *
4 * Copyright (C) 1996-2012 by vhf interservice GmbH
5 * Author:   Georg Fleischmann
6 *
7 * created:  1996-01-25
8 * modified: 2012-01-05 (NSMenuItem)
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the vhf Public License as
12 * published by vhf interservice GmbH. Among other things, the
13 * License requires that the copyright notices and this notice
14 * be preserved on all copies.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 * See the vhf Public License for more details.
20 *
21 * You should have received a copy of the vhf Public License along
22 * with this program; see the file LICENSE. If not, write to vhf.
23 *
24 * vhf interservice GmbH, Im Marxle 3, 72119 Altingen, Germany
25 * eMail: info@vhf.de
26 * http://www.vhf.de
27 */
28
29#include <AppKit/AppKit.h>
30#include <VHFShared/types.h>
31#include <VHFShared/vhfCommonFunctions.h>
32#include <VHFShared/VHFDictionaryAdditions.h>
33#include "functions.h"
34#include "locations.h"
35
36/* return library paths
37 * modified: 2008-02-28
38 */
39NSString *localLibrary(void)
40{
41#   if defined(GNUSTEP_BASE_VERSION) || defined(__APPLE__)
42    NSFileManager	*fileManager = [NSFileManager defaultManager];
43    NSString		*lPath, *sPath;
44
45    /* we return the local path or the system path, whichever exists - local has priority */
46    /* "/Library/Application Support/Cenon" */
47    lPath = vhfPathWithPathComponents(
48            [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSLocalDomainMask, YES) objectAtIndex:0],
49            @"Application Support", APPNAME, nil);
50    if ( lPath && [fileManager fileExistsAtPath:lPath] )
51        return lPath;
52    /* "/Library/Cenon" (Default) */
53    lPath = [[NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSLocalDomainMask, YES) objectAtIndex:0]
54             stringByAppendingPathComponent:APPNAME];
55    if ( lPath && [fileManager fileExistsAtPath:lPath] )
56        return lPath;
57    /* "/System/Library/Cenon" */
58    sPath = [[NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSSystemDomainMask, YES) objectAtIndex:0]
59             stringByAppendingPathComponent:APPNAME];
60    if ( sPath && [fileManager fileExistsAtPath:sPath] )
61        return sPath;
62    return lPath;
63#   else
64    return LOCALLIBRARY;
65#   endif
66}
67NSString *userLibrary(void)
68{
69#   if defined(GNUSTEP_BASE_VERSION) || defined(__APPLE__)
70    NSFileManager	*fileManager = [NSFileManager defaultManager];
71    NSString		*lPath;
72
73    /* "Library/Application Support/Cenon" */
74    lPath = vhfPathWithPathComponents(
75            [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex:0],
76            @"Application Support", APPNAME, nil);
77    if ( lPath && [fileManager fileExistsAtPath:lPath] )
78        return lPath;
79    /* "Library/Cenon" (Default) */
80    return [[NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex:0]
81            stringByAppendingPathComponent:APPNAME];
82#   else
83    return vhfPathWithPathComponents(NSHomeDirectory(), HOMELIBRARY, nil);
84#   endif
85}
86
87NSString *localBundlePath(void)
88{
89#   if defined(GNUSTEP_BASE_VERSION) || defined(__APPLE__)
90    return [[NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSLocalDomainMask, YES) objectAtIndex:0]
91            stringByAppendingPathComponent:BUNDLEFOLDER];
92#   else
93    return vhfPathWithPathComponents(@"/LocalLibrary", BUNDLEFOLDER, nil);
94#   endif
95}
96NSString *systemBundlePath(void)
97{
98#   if defined(__APPLE__)
99    return nil; // we don't have any business here
100#   elif defined(GNUSTEP_BASE_VERSION)
101    return [[NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSSystemDomainMask, YES) objectAtIndex:0]
102            stringByAppendingPathComponent:BUNDLEFOLDER];
103#   else	// OpenStep
104    return vhfPathWithPathComponents(@"/NextLibrary", BUNDLEFOLDER, nil);
105#   endif
106}
107NSString *userBundlePath(void)
108{
109#   if defined(GNUSTEP_BASE_VERSION) || defined(__APPLE__)
110    return [[NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex:0]
111            stringByAppendingPathComponent:BUNDLEFOLDER];
112#   else
113    return vhfPathWithPathComponents(NSHomeDirectory(), @"Library", BUNDLEFOLDER, nil);
114#   endif
115}
116
117/*
118 * fill the device popup 'devicePopup' with menu cells
119 * containing all devices ".dev" inside the appropriate folder ("Devices/xyz").
120 * Search the folder 'path' in all library directories.
121 *
122 * begin:    1993-01-17
123 * modified: 2012-03-09 (sub-folders, clean-up, don't add directories with extension)
124 *           2005-11-16 (appendPathComponent)
125 *
126 * popup	the popup button
127 * folder	the folder
128 * ext 		the extension of the files
129 * removeIx     the index of the first item of the popuplist to be removed
130 */
131void fillPopup(NSPopUpButton *popup, NSString *folder, NSString *ext, int removeIx, BOOL searchSubFolders)
132{   NSString        *path;
133    int             i, j, selectedIx = [popup indexOfSelectedItem];
134    NSFileManager   *fileManager = [NSFileManager defaultManager];
135
136    if (!folder)
137    {	[popup setEnabled:NO];
138        return;
139    }
140
141    /* remove entries from popup list, but keep items before removeIx */
142    if (removeIx == 0)
143        [popup removeAllItems];
144    else
145        while ( [popup numberOfItems] > removeIx )
146            [popup removeItemAtIndex:[popup numberOfItems]-1];
147
148    /* search the files in several directories
149     * add devices in these folders to popup list
150     */
151    for (i=0; i < 3 ;i++)
152    {	NSArray *array;
153
154        switch ( i )
155        {
156            case 0: // 1. application bundle
157                path = [[NSBundle mainBundle] resourcePath]; break;
158            case 1: // 2. local library
159                path = localLibrary(); break;
160            case 2: // 3. user local library
161                path = userLibrary();  break;
162            default:
163                path = nil;
164        }
165        if ( ! path )
166            break;
167        path = [path stringByAppendingPathComponent:folder];
168
169        array = [fileManager directoryContentsAtPath:path];
170        for ( j = [array count]-1; j >= 0; j-- )
171        {   NSString	*name = [array objectAtIndex:j];
172            NSString    *filePath = [path stringByAppendingPathComponent:name];
173            BOOL        isDir;
174
175            /* A. files directly in folder */
176            if ( [fileManager fileExistsAtPath:filePath isDirectory:&isDir] && !isDir )
177            {
178                if ( [name hasSuffix:ext] )
179                {   NSString *title;
180
181                    title = [name substringToIndex:[name rangeOfString:ext].location];
182                    if ([popup indexOfItemWithTitle:title] < 0)
183                        [popup addItemWithTitle:title];
184                }
185            }
186            /* B. files in sub-folders */
187            else if ( searchSubFolders )    // sub-folder
188            {   NSString    *subpath = vhfPathWithPathComponents(path, name, nil);
189                NSArray     *subArray = [fileManager directoryContentsAtPath:subpath];
190                int         s;
191
192                for ( s = [subArray count]-1; s >= 0; s-- )
193                {   NSString	*subName = [subArray objectAtIndex:s];
194                    NSString    *filePath = [subpath stringByAppendingPathComponent:subName];
195
196                    if ( [subName hasSuffix:ext] &&
197                        [fileManager fileExistsAtPath:filePath isDirectory:&isDir] && !isDir )
198                    {   NSString *title;
199
200                        title = [subName substringToIndex:[subName rangeOfString:ext].location];
201                        if ([popup indexOfItemWithTitle:title] < 0)
202                            [popup addItemWithTitle:title];
203                    }
204                }
205            }
206        }
207    }
208    sortPopup( popup, removeIx );
209
210    /* enable popup list when having any entries */
211    [popup setEnabled:([popup numberOfItems]) ? YES : NO];
212    if ( [popup numberOfItems] > selectedIx )
213        [popup selectItemAtIndex:selectedIx];
214}
215
216BOOL vhfUpdateMenuItem(NSMenuItem *menuItem, NSString *zeroItem, NSString *oneItem, BOOL state)
217{
218    if (state)
219    {
220        if ([menuItem tag] != 0)
221        {
222            [menuItem setTitleWithMnemonic:zeroItem];
223            [menuItem setTag:0];
224            [menuItem setEnabled:NO];	// causes it to get redrawn
225        }
226    }
227    else if ([menuItem tag] != 1)
228    {
229        [menuItem setTitleWithMnemonic:oneItem];
230        [menuItem setTag:1];
231        [menuItem setEnabled:NO];	// causes it to get redrawn
232    }
233    return YES;
234}
235
236NSDictionary *dictionaryFromFolder(NSString *folder, NSString *name)
237{   NSDictionary	*dict;
238    int			i;
239
240    for (i=0;  ;i++)
241    {   NSString	*path;
242
243        if (!i)		// application resource directory
244            path = [[NSBundle mainBundle] resourcePath];
245        else if (i==1)	// local library
246            path = localLibrary();
247        else if (i==2)	// user local library
248            path = userLibrary();
249        else
250            break;
251        path = vhfPathWithPathComponents(path, folder, name, nil);
252
253        if ( (dict = [NSDictionary dictionaryWithContentsOfFile:path]) )
254            return dict;
255    }
256
257    return nil;
258}
259
260
261/* DEPRECATED: use [document convertToUnit:uValue]
262 * converts a value from internal unit (1/72 inch) to the current unit
263 */
264float convertToUnit(float value)
265{
266    switch ( [[NSUserDefaults standardUserDefaults] integerForKey:@"unit"] )
267    {
268        case UNIT_MM:		return (value*25.4/72.0);
269        case UNIT_INCH:		return (value / 72.0);
270        case UNIT_POINT:	return value;
271    }
272    return value;
273}
274
275/* DEPRECATED: use [document convertFrUnit:iValue]
276 * converts a value from the current unit to internal unit (1/72 inch)
277 */
278float convertFromUnit(float value)
279{
280    switch ( [[NSUserDefaults standardUserDefaults] integerForKey:@"unit"] )
281    {
282        case UNIT_MM:		return (value/25.4*72.0);
283        case UNIT_INCH:		return (value * 72.0);
284        case UNIT_POINT:	return value;
285    }
286    return value;
287}
288
289/* DEPRECATED: use [document convertMMToUnit:mmValue]
290 * converts a value from mm to the current unit
291 */
292float convertMMToUnit(float value)
293{
294    switch ( [[NSUserDefaults standardUserDefaults] integerForKey:@"unit"] )
295    {
296        case UNIT_MM:		return value;
297        case UNIT_INCH:		return value / 25.4;
298        case UNIT_POINT:	return value*72.0/25.4;
299    }
300    return value;
301}
302
303/* DEPRECATED: use [document convertUnitToMM:uValue]
304 * converts a value from the current unit to mm
305 */
306float convertUnitToMM(float value)
307{
308    switch ( [[NSUserDefaults standardUserDefaults] integerForKey:@"unit"] )
309    {
310        case UNIT_MM:		return value;
311        case UNIT_INCH:		return value * 25.4;
312        case UNIT_POINT:	return value/72.0*25.4;
313    }
314    return value;
315}
316
317/* color/string functions
318 */
319NSString *vhfStringFromRGBColor(NSColor *color)
320{
321    if (![[color colorSpaceName] isEqualToString:NSCalibratedRGBColorSpace])
322        color = [color colorUsingColorSpaceName:NSCalibratedRGBColorSpace];
323    return [NSString stringWithFormat:@"%.3f %.3f %.3f", [color redComponent], [color greenComponent], [color blueComponent]];
324}
325NSColor *vhfRGBColorFromString(NSString *string)
326{   NSScanner	*scanner;
327    float	r, g, b;
328
329    if (!string)
330    {   NSLog(@"vhfRGBColorFromString(): string != nil expected !");
331        return nil;
332    }
333    scanner = [NSScanner scannerWithString:string];
334    [scanner scanFloat:&r];
335    [scanner scanFloat:&g];
336    [scanner scanFloat:&b];
337    return [NSColor colorWithCalibratedRed:r green:g blue:b alpha:1.0];
338}
339