You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

401 rivejä
11 KiB

  1. /*
  2. * libcaca Colour ASCII-Art library
  3. * Copyright (c) 2006 Olivier Gutknecht <olg@no-distance.net>
  4. * 2006 Sam Hocevar <sam@zoy.org>
  5. * All Rights Reserved
  6. *
  7. * $Id$
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the Do What The Fuck You Want To
  11. * Public License, Version 2, as published by Sam Hocevar. See
  12. * http://sam.zoy.org/wtfpl/COPYING for more details.
  13. */
  14. /*
  15. * This file contains the libcaca Cocoa input and output driver
  16. */
  17. #include "config.h"
  18. #include "common.h"
  19. #if defined USE_COCOA
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #import <Carbon/Carbon.h>
  23. #include <Cocoa/Cocoa.h>
  24. #include "caca.h"
  25. #include "caca_internals.h"
  26. #include "cucul.h"
  27. #include "cucul_internals.h"
  28. @interface CacaView : NSView
  29. {
  30. NSFont* _font;
  31. NSRect _r;
  32. int xx;
  33. int h, w;
  34. uint32_t *_attrs;
  35. uint32_t *_chars;
  36. CFMutableDictionaryRef _cache;
  37. }
  38. - (void)setFont:(NSFont *)aFont;
  39. - (void)updateBuffersFromCaca:(caca_display_t *)dp;
  40. @end
  41. @implementation CacaView
  42. - (void)keyDown:(NSEvent *)theEvent
  43. {
  44. NSLog(@"key %@", theEvent);
  45. }
  46. - (void)mouseMoved:(NSEvent *)theEvent
  47. {
  48. NSLog(@"mouse %@", theEvent);
  49. }
  50. - (void)setupNewSize
  51. {
  52. int fw = _r.size.width;
  53. int fh = _r.size.height;
  54. w = [self bounds].size.width /fw;
  55. h = [self bounds].size.height / fh;
  56. // NSLog(@"W %f %f %f %d %f", [self bounds].size.width , _r.size.width, [self bounds].size.width / _r.size.width, w, [self bounds].size.width-(w*fw));
  57. // NSLog(@"H %f %f %f %d %f", [self bounds].size.height , _r.size.height, [self bounds].size.height / _r.size.height, h, [self bounds].size.height-(h*fh));
  58. }
  59. - (id)initWithFrame:(NSRect)frameRect
  60. {
  61. if((self = [super initWithFrame:frameRect]) != nil) {
  62. [[self window] makeFirstResponder:self];
  63. }
  64. return self;
  65. }
  66. - (NSFont *)font
  67. {
  68. return _font;
  69. }
  70. - (void)setFont:(NSFont *)aFont
  71. {
  72. [_font release];
  73. _font = [aFont retain];
  74. _r = [_font boundingRectForFont];
  75. _r = NSMakeRect(0, 0, ceilf(_r.size.width), ceilf(_r.size.height));
  76. [self setupNewSize];
  77. [aFont set];
  78. }
  79. - (void)updateBuffersFromCaca:(caca_display_t *)dp
  80. {
  81. NSLog(@"update buffers");
  82. if(_attrs)
  83. free(_attrs);
  84. _attrs = malloc(dp->cv->width * dp->cv->height * sizeof(uint32_t) * 2);
  85. _chars = _attrs + dp->cv->width * dp->cv->height;
  86. memcpy(_attrs, dp->cv->attrs, dp->cv->width * dp->cv->height * sizeof(uint32_t));
  87. memcpy(_chars, dp->cv->chars, dp->cv->width * dp->cv->height * sizeof(uint32_t));
  88. w = dp->cv->width;
  89. h = dp->cv->height;
  90. [self setNeedsDisplay:TRUE];
  91. }
  92. - (void)drawRect:(NSRect)rect
  93. {
  94. //if([self inLiveResize]) [self setupNewSize];
  95. int x, y;
  96. int fw = _r.size.width;
  97. int fh = _r.size.height;
  98. uint32_t *attrs = _attrs;
  99. uint32_t *chars = _chars;
  100. NSGraphicsContext* viewContext = [NSGraphicsContext currentContext];
  101. if(!attrs || !chars)
  102. {
  103. [[NSColor blueColor] set];
  104. NSRectFill(rect);
  105. return;
  106. }
  107. [[NSColor blackColor] set];
  108. NSRectFill(rect);
  109. for(y = 0; y < h; y++)
  110. {
  111. for(x = 0; x < w; x++)
  112. {
  113. unichar c = *chars++;
  114. uint8_t argb[8];
  115. _cucul_attr_to_argb4(*attrs++, argb);
  116. /* FIXME: factorise this colour stuff */
  117. NSRect r = NSMakeRect(x * fw, y * fh, fw, fh);
  118. [[NSColor colorWithDeviceRed: (float)argb[1] / 255.0
  119. green: (float)argb[2] / 255.0
  120. blue: (float)argb[3] / 255.0
  121. alpha: 1.0] setFill];
  122. [[NSColor colorWithDeviceRed: (float)argb[5] / 255.0
  123. green: (float)argb[6] / 255.0
  124. blue: (float)argb[7] / 255.0
  125. alpha: 1.0] setStroke];
  126. NSRectFill(r);
  127. // NSLog(@"%d %d %C %d %d %@ %@ %@", x, y, c, fg, bg, NSStringFromRect(r), _colormap[fg], _colormap[bg]);
  128. // [[NSString stringWithCharacters:&c length:1] drawInRect:r withAttributes:[NSDictionary dictionaryWithObject:_colormap[fg] forKey:NSForegroundColorAttributeName]];
  129. [[NSColor colorWithDeviceRed: (float)argb[5] / 255.0
  130. green: (float)argb[6] / 255.0
  131. blue: (float)argb[7] / 255.0
  132. alpha: 1.0] setFill];
  133. [[NSColor colorWithDeviceRed: (float)argb[5] / 255.0
  134. green: (float)argb[6] / 255.0
  135. blue: (float)argb[7] / 255.0
  136. alpha: 1.0] setStroke];
  137. [[NSString stringWithCharacters:&c length:1] drawInRect:r withAttributes:nil];
  138. // [[NSString stringWithCharacters:&c length:1] drawInRect:r withAttributes:[NSDictionary dictionaryWithObjectsAndKeys:
  139. // _colormap[fg], NSForegroundColorAttributeName, _colormap[bg], NSBackgroundColorAttributeName, nil]];
  140. }
  141. }
  142. [NSGraphicsContext setCurrentContext:viewContext];
  143. }
  144. @end
  145. struct driver_private
  146. {
  147. NSWindow* window;
  148. id view;
  149. NSFont* font;
  150. NSAutoreleasePool* pool;
  151. };
  152. //--------------------------------------------------------------------------------------------
  153. static OSStatus
  154. AppEventHandler(EventHandlerCallRef inCaller, EventRef inEvent, void* inRefcon)
  155. {
  156. OSStatus result = eventNotHandledErr;
  157. switch(GetEventClass(inEvent))
  158. {
  159. case kEventClassCommand:
  160. {
  161. HICommandExtended cmd;
  162. verify_noerr(GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(cmd), NULL, &cmd));
  163. switch(GetEventKind(inEvent))
  164. {
  165. case kEventCommandProcess:
  166. switch(cmd.commandID)
  167. {
  168. default:
  169. break;
  170. }
  171. break;
  172. }
  173. break;
  174. }
  175. default:
  176. break;
  177. }
  178. return result;
  179. }
  180. static OSStatus
  181. WindowEventHandler(EventHandlerCallRef inCaller, EventRef inEvent, void* inRefcon)
  182. {
  183. OSStatus err = eventNotHandledErr;
  184. switch(GetEventClass(inEvent))
  185. {
  186. case kEventClassCommand:
  187. {
  188. HICommandExtended cmd;
  189. verify_noerr(GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(cmd), NULL, &cmd));
  190. switch(GetEventKind(inEvent))
  191. {
  192. case kEventCommandProcess:
  193. switch(cmd.commandID)
  194. {
  195. // Add your own command-handling cases here
  196. default:
  197. break;
  198. }
  199. break;
  200. }
  201. break;
  202. }
  203. default:
  204. break;
  205. }
  206. return err;
  207. }
  208. static int cocoa_init_graphics(caca_display_t *dp)
  209. {
  210. int i;
  211. dp->drv.p = malloc(sizeof(struct driver_private));
  212. if(dp->drv.p == NULL)
  213. return -1;
  214. Handle aHand = GetNewMBar(128);
  215. SetMenuBar(aHand);
  216. MenuHandle menu = GetMenuHandle(128);
  217. CreateStandardWindowMenu(0, &menu);
  218. InsertMenu(menu, 0);
  219. DrawMenuBar();
  220. DisposeHandle(aHand);
  221. NSAutoreleasePool* p = [[NSAutoreleasePool alloc] init];
  222. // [NSApplication sharedApplication];
  223. NSApplicationLoad();
  224. NSLog(@"Start");
  225. NSFont* f = [NSFont fontWithName:@"Monaco" size:10];
  226. NSRect r = [f boundingRectForFont];
  227. NSRect windowRect = NSMakeRect(0, 0, dp->cv->width * r.size.width,
  228. dp->cv->height * r.size.height);
  229. CacaView* v = [[[CacaView alloc] initWithFrame:windowRect] autorelease];
  230. // [NSApp setMainMenu:[[[NSMenu alloc] initWithTitle:@"Caca"] autorelease]];
  231. //[NSApp setAppleMenu:[[[NSMenu alloc] initWithTitle:@"ca"] autorelease]];
  232. //[NSApp setDelegate:v];
  233. NSWindow* w = [[NSWindow alloc]
  234. initWithContentRect:windowRect
  235. styleMask:NSTitledWindowMask
  236. |NSResizableWindowMask
  237. |NSClosableWindowMask
  238. |NSWindowMiniaturizeButton
  239. backing:NSBackingStoreBuffered
  240. defer:NO];
  241. [w setContentView:v];
  242. [v setFont:f];
  243. [v setupNewSize];
  244. [w setFrameTopLeftPoint:NSMakePoint(650, 650)];
  245. [w makeKeyAndOrderFront:w];
  246. [w setLevel:NSFloatingWindowLevel];
  247. [w orderFrontRegardless];
  248. dp->drv.p->window = w;
  249. dp->drv.p->view = v;
  250. dp->drv.p->font = f;
  251. dp->drv.p->pool = p;
  252. // NSLog(@"update4 %d %d", w, h);
  253. // _cucul_set_size(dp->cv, windowRect.size.width, windowRect.size.height);
  254. OSStatus err;
  255. static const EventTypeSpec kAppEvents[] =
  256. {
  257. { kEventClassCommand, kEventCommandProcess }
  258. };
  259. InstallApplicationEventHandler(NewEventHandlerUPP(AppEventHandler),
  260. GetEventTypeCount(kAppEvents), kAppEvents,
  261. 0, NULL);
  262. NSLog(@"a");
  263. /* Should not be run here, should it? */
  264. RunApplicationEventLoop();
  265. NSLog(@"ab");
  266. return 0;
  267. }
  268. static void cocoa_display(caca_display_t *dp)
  269. {
  270. //NSLog(@"display1");
  271. [dp->drv.p->view updateBuffersFromCaca:dp];
  272. #if 1
  273. [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate date]];
  274. #else
  275. [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[[NSCalendarDate date]
  276. dateByAddingYears:0 months:(int)0 days:(int)0 hours:(int)0 minutes:(int)0 seconds:(int)5]];
  277. #endif
  278. //NSLog(@"display2");
  279. }
  280. static void cocoa_handle_resize(caca_display_t *dp)
  281. {
  282. dp->resize.w = dp->cv->width;
  283. dp->resize.h = dp->cv->height;
  284. }
  285. static int cocoa_get_event(caca_display_t *dp, struct caca_event *ev)
  286. {
  287. [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
  288. beforeDate:[NSDate date]];
  289. ev->type = CACA_EVENT_NONE;
  290. return 0;
  291. }
  292. static int cocoa_set_display_title(caca_display_t *dp, char const *title)
  293. {
  294. [dp->drv.p->window setTitle:[NSString stringWithUTF8String:title]];
  295. return 0;
  296. }
  297. static unsigned int cocoa_get_display_width(caca_display_t *dp)
  298. {
  299. return [dp->drv.p->window frame].size.width;
  300. }
  301. static unsigned int cocoa_get_display_height(caca_display_t *dp)
  302. {
  303. return [dp->drv.p->window frame].size.height;
  304. }
  305. static void cocoa_set_mouse(caca_display_t *dp, int flag)
  306. {
  307. if(flag)
  308. [[NSCursor arrowCursor] set];
  309. else {
  310. [[NSCursor disappearingItemCursor] set];
  311. }
  312. }
  313. static int cocoa_end_graphics(caca_display_t *dp)
  314. {
  315. [dp->drv.p->window close];
  316. [dp->drv.p->window release];
  317. [dp->drv.p->pool release];
  318. [dp->drv.p->font release];
  319. free(dp->drv.p);
  320. return 0;
  321. }
  322. /*
  323. * Driver initialisation
  324. */
  325. int cocoa_install(caca_display_t *dp)
  326. {
  327. dp->drv.driver = CACA_DRIVER_RAW;
  328. dp->drv.init_graphics = cocoa_init_graphics;
  329. dp->drv.end_graphics = cocoa_end_graphics;
  330. dp->drv.set_display_title = cocoa_set_display_title;
  331. dp->drv.get_display_width = cocoa_get_display_width;
  332. dp->drv.get_display_height = cocoa_get_display_height;
  333. dp->drv.display = cocoa_display;
  334. dp->drv.handle_resize = cocoa_handle_resize;
  335. dp->drv.get_event = cocoa_get_event;
  336. dp->drv.set_mouse = cocoa_set_mouse;
  337. return 0;
  338. }
  339. #endif /* USE_COCOA */