UNIXworkcode

1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 * 4 * Copyright 2012 Olaf Wintermann. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #import <stdio.h> 30 #import <stdlib.h> 31 #import <sys/stat.h> 32 #import <sys/types.h> 33 #import <errno.h> 34 35 #import "../common/context.h" 36 #import "../common/document.h" 37 #import "../common/properties.h" 38 39 #import "toolkit.h" 40 #import "window.h" 41 #import "menu.h" 42 #import "toolbar.h" 43 #import "stock.h" 44 45 NSAutoreleasePool *pool; 46 47 static char *application_name; 48 49 static ui_callback appclose_fnc; 50 static void *appclose_udata; 51 52 static ui_callback openfile_fnc; 53 static void *openfile_udata; 54 55 void ui_init(char *appname, int argc, char **argv) { 56 pool = [[NSAutoreleasePool alloc] init]; 57 [NSApplication sharedApplication]; 58 [NSBundle loadNibNamed:@"MainMenu" owner:NSApp]; 59 60 UiApplicationDelegate *delegate = [[UiApplicationDelegate alloc]init]; 61 [NSApp setDelegate: delegate]; 62 63 64 uic_docmgr_init(); 65 ui_menu_init(); 66 ui_toolbar_init(); 67 ui_stock_init(); 68 69 uic_load_app_properties(); 70 } 71 72 char* ui_appname() { 73 return application_name; 74 } 75 76 void ui_exitfunc(ui_callback f, void *userdata) { 77 appclose_fnc = f; 78 appclose_udata = userdata; 79 } 80 81 void ui_openfilefunc(ui_callback f, void *userdata) { 82 openfile_fnc = f; 83 openfile_udata = userdata; 84 } 85 86 void ui_show(UiObject *obj) { 87 uic_check_group_widgets(obj->ctx); 88 if([obj->widget class] == [UiCocoaWindow class]) { 89 UiCocoaWindow *window = (UiCocoaWindow*)obj->widget; 90 [window makeKeyAndOrderFront:nil]; 91 } else { 92 printf("Error: ui_show: Object is not a Window!\n"); 93 } 94 } 95 96 void ui_set_show_all(UIWIDGET widget, int value) { 97 // TODO 98 } 99 100 void ui_set_visible(UIWIDGET widget, int visible) { 101 // TODO 102 } 103 104 void ui_set_enabled(UIWIDGET widget, int enabled) { 105 [(id)widget setEnabled: enabled]; 106 } 107 108 109 110 void ui_job(UiObject *obj, ui_threadfunc tf, void *td, ui_callback f, void *fd) { 111 UiThread *thread = [[UiThread alloc]initWithObject:obj]; 112 [thread setJobFunction:tf]; 113 [thread setJobData:td]; 114 [thread setFinishCallback:f]; 115 [thread setFinishData:fd]; 116 [thread start]; 117 } 118 119 void ui_main() { 120 [NSApp run]; 121 [pool release]; 122 } 123 124 125 void ui_clipboard_set(char *str) { 126 NSString *string = [[NSString alloc] initWithUTF8String:str]; 127 NSPasteboard * pasteBoard = [NSPasteboard generalPasteboard]; 128 [pasteBoard declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:nil]; 129 [pasteBoard setString:string forType:NSStringPboardType]; 130 } 131 132 char* ui_clipboard_get() { 133 NSPasteboard * pasteBoard = [NSPasteboard generalPasteboard]; 134 NSArray *classes = [[NSArray alloc] initWithObjects:[NSString class], nil]; 135 NSDictionary *options = [NSDictionary dictionary]; 136 NSArray *data = [pasteBoard readObjectsForClasses:classes options:options]; 137 138 if(data != nil) { 139 NSString *str = [data componentsJoinedByString: @""]; 140 141 // copy C string 142 size_t length = [str lengthOfBytesUsingEncoding:NSUTF8StringEncoding]; 143 const char *cstr = [str UTF8String]; 144 char *value = malloc(length + 1); 145 memcpy(value, cstr, length); 146 value[length] = '\0'; 147 148 return value; 149 } else { 150 return NULL; 151 } 152 } 153 154 155 @implementation UiApplicationDelegate 156 157 - (void)applicationWillTerminate:(NSNotification*)notification { 158 printf("terminate\n"); 159 } 160 161 - (BOOL)applicationShouldHandleReopen:(NSApplication *)app hasVisibleWindows:(BOOL)visible; { 162 if(!visible) { 163 printf("reopen\n"); 164 } 165 return NO; 166 } 167 168 - (BOOL)application:(NSApplication*)application openFile:(NSString*)filename { 169 if(openfile_fnc) { 170 UiEvent event; 171 event.obj = NULL; 172 event.document = NULL; 173 event.window = NULL; 174 event.eventdata = (void*)[filename UTF8String]; 175 event.intval = 0; 176 openfile_fnc(&event, openfile_udata); 177 } 178 179 return NO; 180 } 181 182 @end 183 184 185 @implementation EventWrapper 186 187 - (EventWrapper*) initWithData: (void*)d callback:(ui_callback) f { 188 data = d; 189 callback = f; 190 value = 0; 191 return self; 192 } 193 194 195 - (void*) data { 196 return data; 197 } 198 199 - (void) setData:(void*)d { 200 data = d; 201 } 202 203 204 - (ui_callback) callback { 205 return callback; 206 } 207 208 - (void) setCallback: (ui_callback)f { 209 callback = f; 210 } 211 212 - (int) intval { 213 return value; 214 } 215 216 - (void) setIntval:(int)i { 217 value = i; 218 } 219 220 221 - (BOOL)handleEvent:(id)sender { 222 NSWindow *activeWindow = [NSApp keyWindow]; 223 224 UiEvent event; 225 event.eventdata = NULL; 226 if([activeWindow class] == [UiCocoaWindow class]) { 227 event.obj = [(UiCocoaWindow*)activeWindow object]; 228 event.window = event.obj->window; 229 event.document = event.obj->ctx->document; 230 event.intval = value; 231 } 232 if(callback) { 233 callback(&event, data); 234 } 235 236 return true; 237 } 238 239 - (BOOL)handleStateEvent:(id)sender { 240 NSWindow *activeWindow = [NSApp keyWindow]; 241 int state = [sender state] ? NSOffState : NSOnState; 242 243 UiEvent event; 244 event.intval = state; 245 event.eventdata = NULL; 246 if([activeWindow class] == [UiCocoaWindow class]) { 247 event.obj = [(UiCocoaWindow*)activeWindow object]; 248 event.window = event.obj->window; 249 event.document = event.obj->ctx->document; 250 // if the sender is a menu item, we have to save the state for this 251 // window 252 UiMenuItem *wmi = [(UiCocoaWindow*)activeWindow getMenuItem: sender]; 253 if(wmi) { 254 // update state in window data 255 wmi->state = state; 256 } 257 } else { 258 event.window = NULL; 259 event.document = NULL; 260 } 261 if(callback) { 262 callback(&event, data); 263 } 264 [sender setState: state]; 265 266 return true; 267 } 268 269 - (BOOL)handleToggleEvent:(id)sender { 270 NSWindow *activeWindow = [NSApp keyWindow]; 271 272 UiEvent event; 273 event.intval = [sender state]; 274 event.eventdata = NULL; 275 if([activeWindow class] == [UiCocoaWindow class]) { 276 event.obj = [(UiCocoaWindow*)activeWindow object]; 277 event.window = event.obj->window; 278 event.document = event.obj->ctx->document; 279 } else { 280 event.window = NULL; 281 event.document = NULL; 282 } 283 if(callback) { 284 callback(&event, data); 285 } 286 287 return true; 288 } 289 290 @end 291 292 @implementation UiThread 293 294 - (id) initWithObject:(UiObject*)object { 295 obj = object; 296 job_func = NULL; 297 job_data = NULL; 298 finish_callback = NULL; 299 finish_data = NULL; 300 return self; 301 } 302 303 - (void) setJobFunction:(ui_threadfunc)func { 304 job_func = func; 305 } 306 307 - (void) setJobData:(void*)data { 308 job_data = data; 309 } 310 311 - (void) setFinishCallback:(ui_callback)callback { 312 finish_callback = callback; 313 } 314 315 - (void) setFinishData:(void*)data { 316 finish_data = data; 317 } 318 319 - (void) start { 320 [NSThread detachNewThreadSelector:@selector(runJob:) 321 toTarget:self 322 withObject:nil]; 323 } 324 325 - (void) runJob:(id)n { 326 int result = job_func(job_data); 327 if(!result) { 328 [self performSelectorOnMainThread:@selector(finish:) 329 withObject:nil 330 waitUntilDone:NO]; 331 } 332 } 333 334 - (void) finish:(id)n { 335 UiEvent event; 336 event.obj = obj; 337 event.window = obj->window; 338 event.document = obj->ctx->document; 339 event.eventdata = NULL; 340 event.intval = 0; 341 finish_callback(&event, finish_data); 342 } 343 344 @end 345 346 347