]> git.tdb.fi Git - ext/subsurface.git/blob - macos.c
Merge branch 'mac' of git://git.hohndel.org/subsurface
[ext/subsurface.git] / macos.c
1 /* macos.c */
2 /* implements Mac OS X specific functions */
3 #include "display-gtk.h"
4 #include <CoreFoundation/CoreFoundation.h>
5 #include <mach-o/dyld.h>
6 #include "gtkosxapplication.h"
7
8
9 static CFURLRef fileURL;
10 static CFPropertyListRef propertyList;
11 static CFMutableDictionaryRef dict = NULL;
12 static GtkOSXApplication *theApp;
13
14 /* macos defines CFSTR to create a CFString object from a constant,
15  * but no similar macros if a C string variable is supposed to be
16  * the argument. We add this here (hardcoding the default allocator
17  * and MacRoman encoding */
18 #define CFSTR_VAR(_var) CFStringCreateWithCStringNoCopy(kCFAllocatorDefault,    \
19                                         (_var), kCFStringEncodingMacRoman,      \
20                                         kCFAllocatorNull)
21
22 #define SUBSURFACE_PREFERENCES "~/Library/Preferences/org.hohndel.subsurface.plist"
23 #define REL_ICON_PATH "Resources/Subsurface.icns"
24 #define UI_FONT "Arial Unicode MS 12"
25 #define DIVELIST_MAC_DEFAULT_FONT "Arial Unicode MS 9"
26
27 static void show_error(SInt32 errorCode, char *action)
28 {
29         char *errortext;
30
31         switch(errorCode) {
32         case -11: errortext = "kCFURLUnknownSchemeError";
33                 break;
34         case -12: errortext = "kCFURLResourceNotFoundError";
35                 break;
36         case -13: errortext = "kCFURLResourceAccessViolationError";
37                 break;
38         case -14: errortext = "kCFURLRemoteHostUnavailableError";
39                 break;
40         case -15: errortext = "kCFURLImproperArgumentsError";
41                 break;
42         case -16: errortext = "kCFURLUnknownPropertyKeyError";
43                 break;
44         case -17: errortext = "kCFURLPropertyKeyUnavailableError";
45                 break;
46         case -18: errortext = "kCFURLTimeoutError";
47                 break;
48         default: errortext = "kCFURLUnknownError";
49         };
50         fprintf(stderr, "Error %s preferences: %s\n", action, errortext);
51 }
52
53 void subsurface_open_conf(void)
54 {
55         CFStringRef errorString;
56         CFDataRef resourceData;
57         Boolean status;
58         SInt32 errorCode;
59
60         fileURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault,
61                                                 CFSTR(SUBSURFACE_PREFERENCES),// file path name
62                                                 kCFURLPOSIXPathStyle,    // interpret as POSIX path
63                                                 false );                 // is it a directory?
64
65         status = CFURLCreateDataAndPropertiesFromResource(kCFAllocatorDefault,
66                                                         fileURL, &resourceData,
67                                                         NULL, NULL, &errorCode);
68         if (status) {
69                 propertyList = CFPropertyListCreateFromXMLData(kCFAllocatorDefault,
70                                                         resourceData, kCFPropertyListImmutable,
71                                                         &errorString);
72                 CFRelease(resourceData);
73         } else {
74                 show_error(errorCode, "reading");
75         }
76 }
77
78 void subsurface_set_conf(char *name, pref_type_t type, const void *value)
79 {
80         if (!dict)
81                 dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
82                                                 &kCFTypeDictionaryKeyCallBacks,
83                                                 &kCFTypeDictionaryValueCallBacks);
84         switch (type) {
85         case PREF_BOOL:
86                 CFDictionarySetValue(dict, CFSTR_VAR(name), value == NULL ? CFSTR("0") : CFSTR("1"));
87                 break;
88         case PREF_STRING:
89                 CFDictionarySetValue(dict, CFSTR_VAR(name), CFSTR_VAR(value));
90         }
91 }
92 const void *subsurface_get_conf(char *name, pref_type_t type)
93 {
94         CFStringRef dict_entry;
95
96         /* if no settings exist, we return the value for FALSE */
97         if (!propertyList)
98                 return NULL;
99
100         switch (type) {
101         case PREF_BOOL:
102                 dict_entry = CFDictionaryGetValue(propertyList, CFSTR_VAR(name));
103                 if (dict_entry && ! CFStringCompare(CFSTR("1"), dict_entry, 0))
104                         return (void *) 1;
105                 else
106                         return NULL;
107         case PREF_STRING:
108                 return CFStringGetCStringPtr(CFDictionaryGetValue(propertyList,
109                                                 CFSTR_VAR(name)), kCFStringEncodingMacRoman);
110         }
111         /* we shouldn't get here, but having this line makes the compiler happy */
112         return NULL;
113 }
114
115 void subsurface_close_conf(void)
116 {
117         Boolean status;
118         SInt32 errorCode;
119         CFDataRef xmlData;
120
121         propertyList = dict;
122         dict = NULL;
123         xmlData = CFPropertyListCreateXMLData(kCFAllocatorDefault, propertyList);
124         status = CFURLWriteDataAndPropertiesToResource (fileURL, xmlData, NULL, &errorCode);
125         if (!status) {
126                 show_error(errorCode, "writing");
127         }
128         CFRelease(xmlData);
129         CFRelease(propertyList);
130 }
131
132 const char *subsurface_USB_name()
133 {
134         return "/dev/tty.SLAB_USBtoUART";
135 }
136
137 const char *subsurface_icon_name()
138 {
139         static char path[1024];
140         char *ptr1, *ptr2;
141         uint32_t size = sizeof(path); /* need extra space to copy icon path */
142         if (_NSGetExecutablePath(path, &size) == 0) {
143                 ptr1 = strcasestr(path,"MacOS/subsurface");
144                 ptr2 = strcasestr(path,"Contents");
145                 if (ptr1 && ptr2) {
146                         /* we are running as installed app from a bundle */
147                         if (ptr1 - path < size - strlen(REL_ICON_PATH)) {
148                                 strcpy(ptr1,REL_ICON_PATH);
149                                 return path;
150                         }
151                 }
152         }
153         return "packaging/macosx/Subsurface.icns";
154 }
155
156 void subsurface_ui_setup(GtkSettings *settings, GtkWidget *menubar,
157                 GtkWidget *vbox)
158 {
159         if (!divelist_font)
160                 divelist_font = DIVELIST_MAC_DEFAULT_FONT;
161         g_object_set(G_OBJECT(settings), "gtk-font-name", UI_FONT, NULL);
162
163         theApp = g_object_new(GTK_TYPE_OSX_APPLICATION, NULL);
164         gtk_widget_hide (menubar);
165         gtk_osxapplication_set_menu_bar(theApp, GTK_MENU_SHELL(menubar));
166         gtk_osxapplication_set_use_quartz_accelerators(theApp, TRUE);
167         gtk_osxapplication_ready(theApp);
168
169 }