Add a section to mkfiles.pl to build a makefile that compiles the OS X
[sgt/puzzles] / osx.m
diff --git a/osx.m b/osx.m
index 9279c05..d9b1cf5 100644 (file)
--- a/osx.m
+++ b/osx.m
@@ -77,6 +77,8 @@
  *    recreate it.
  */
 
+#define COMBINED /* we put all the puzzles in one binary in this port */
+
 #include <ctype.h>
 #include <sys/time.h>
 #import <Cocoa/Cocoa.h>
@@ -123,7 +125,7 @@ void fatal(char *fmt, ...)
     } else {
        alert = [[alert init] autorelease];
        [alert addButtonWithTitle:@"Oh dear"];
-       [alert setInformativeText:[NSString stringWithCString:errorbuf]];
+       [alert setInformativeText:[NSString stringWithUTF8String:errorbuf]];
        [alert runModal];
     }
     exit(1);
@@ -209,7 +211,7 @@ void document_add_puzzle(document *doc, const game *game, game_params *par,
 NSMenu *newmenu(const char *title)
 {
     return [[[NSMenu allocWithZone:[NSMenu menuZone]]
-            initWithTitle:[NSString stringWithCString:title]]
+            initWithTitle:[NSString stringWithUTF8String:title]]
            autorelease];
 }
 
@@ -219,7 +221,7 @@ NSMenu *newsubmenu(NSMenu *parent, const char *title)
     NSMenu *child;
 
     item = [[[NSMenuItem allocWithZone:[NSMenu menuZone]]
-            initWithTitle:[NSString stringWithCString:title]
+            initWithTitle:[NSString stringWithUTF8String:title]
             action:NULL
             keyEquivalent:@""]
            autorelease];
@@ -249,9 +251,9 @@ id initnewitem(NSMenuItem *item, NSMenu *parent, const char *title,
            key++;
     }
 
-    item = [[item initWithTitle:[NSString stringWithCString:title]
+    item = [[item initWithTitle:[NSString stringWithUTF8String:title]
             action:NULL
-            keyEquivalent:[NSString stringWithCString:key]]
+            keyEquivalent:[NSString stringWithUTF8String:key]]
            autorelease];
 
     if (*key)
@@ -325,7 +327,7 @@ NSMenuItem *newitem(NSMenu *parent, char *title, char *key,
     [tf setBordered:NO];
     [tf setDrawsBackground:NO];
     [tf setFont:font1];
-    [tf setStringValue:[NSString stringWithCString:ver]];
+    [tf setStringValue:[NSString stringWithUTF8String:ver]];
     [tf sizeToFit];
     views[nviews++] = tf;
 
@@ -426,6 +428,7 @@ struct frontend {
 - (void)deactivateTimer;
 - (void)setStatusLine:(char *)text;
 - (void)resizeForNewGameParams;
+- (void)updateTypeMenuTick;
 @end
 
 @implementation MyImageView
@@ -575,7 +578,7 @@ struct frontend {
                       NSClosableWindowMask)
            backing:NSBackingStoreBuffered
            defer:YES];
-    [self setTitle:[NSString stringWithCString:ourgame->name]];
+    [self setTitle:[NSString stringWithUTF8String:ourgame->name]];
 
     {
        float *colours;
@@ -707,7 +710,7 @@ struct frontend {
 
     alert = [[[NSAlert alloc] init] autorelease];
     [alert addButtonWithTitle:@"Bah"];
-    [alert setInformativeText:[NSString stringWithCString:message]];
+    [alert setInformativeText:[NSString stringWithUTF8String:message]];
     [alert beginSheetModalForWindow:self modalDelegate:nil
      didEndSelector:nil contextInfo:nil];
 }
@@ -766,6 +769,7 @@ struct frontend {
         }
 
        [self resizeForNewGameParams];
+       [self updateTypeMenuTick];
     }
 }
 - (void)undoMove:(id)sender
@@ -785,7 +789,7 @@ struct frontend {
        NSPasteboard *pb = [NSPasteboard generalPasteboard];
        NSArray *a = [NSArray arrayWithObject:NSStringPboardType];
        [pb declareTypes:a owner:nil];
-       [pb setString:[NSString stringWithCString:text]
+       [pb setString:[NSString stringWithUTF8String:text]
         forType:NSStringPboardType];
     } else
        NSBeep();
@@ -804,7 +808,8 @@ struct frontend {
 - (BOOL)validateMenuItem:(NSMenuItem *)item
 {
     if ([item action] == @selector(copy:))
-       return (ourgame->can_format_as_text ? YES : NO);
+       return (ourgame->can_format_as_text_ever &&
+               midend_can_format_as_text_now(me) ? YES : NO);
     else if ([item action] == @selector(solveGame:))
        return (ourgame->can_solve ? YES : NO);
     else
@@ -815,6 +820,19 @@ struct frontend {
 {
     while ([typemenu numberOfItems] > 1)
        [typemenu removeItemAtIndex:0];
+    [[typemenu itemAtIndex:0] setState:NSOffState];
+}
+
+- (void)updateTypeMenuTick
+{
+    int i, total, n;
+
+    total = [typemenu numberOfItems];
+    n = midend_which_preset(me);
+    if (n < 0)
+       n = total - 1;                 /* that's always where "Custom" lives */
+    for (i = 0; i < total; i++)
+       [[typemenu itemAtIndex:i] setState:(i == n ? NSOnState : NSOffState)];
 }
 
 - (void)becomeKeyWindow
@@ -837,7 +855,7 @@ struct frontend {
            midend_fetch_preset(me, n, &name, &params);
 
            item = [[[DataMenuItem alloc]
-                    initWithTitle:[NSString stringWithCString:name]
+                    initWithTitle:[NSString stringWithUTF8String:name]
                     action:NULL keyEquivalent:@""]
                    autorelease];
 
@@ -849,6 +867,8 @@ struct frontend {
            [typemenu insertItem:item atIndex:0];
        }
     }
+
+    [self updateTypeMenuTick];
 }
 
 - (void)resignKeyWindow
@@ -894,6 +914,7 @@ struct frontend {
     midend_new_game(me);
 
     [self resizeForNewGameParams];
+    [self updateTypeMenuTick];
 }
 
 - (void)startConfigureSheet:(int)which
@@ -981,7 +1002,7 @@ struct frontend {
            [tf setSelectable:NO];
            [tf setBordered:NO];
            [tf setDrawsBackground:NO];
-           [[tf cell] setTitle:[NSString stringWithCString:i->name]];
+           [[tf cell] setTitle:[NSString stringWithUTF8String:i->name]];
            [tf sizeToFit];
            rect = [tf frame];
            if (thish < rect.size.height + 1) thish = rect.size.height + 1;
@@ -992,7 +1013,7 @@ struct frontend {
            [tf setEditable:YES];
            [tf setSelectable:YES];
            [tf setBordered:YES];
-           [[tf cell] setTitle:[NSString stringWithCString:i->sval]];
+           [[tf cell] setTitle:[NSString stringWithUTF8String:i->sval]];
            [tf sizeToFit];
            rect = [tf frame];
            /*
@@ -1019,7 +1040,7 @@ struct frontend {
            b = [[NSButton alloc] initWithFrame:tmprect];
            [b setBezelStyle:NSRoundedBezelStyle];
            [b setButtonType:NSSwitchButton];
-           [b setTitle:[NSString stringWithCString:i->name]];
+           [b setTitle:[NSString stringWithUTF8String:i->name]];
            [b sizeToFit];
            [b setState:(i->ival ? NSOnState : NSOffState)];
            rect = [b frame];
@@ -1040,7 +1061,7 @@ struct frontend {
            [tf setSelectable:NO];
            [tf setBordered:NO];
            [tf setDrawsBackground:NO];
-           [[tf cell] setTitle:[NSString stringWithCString:i->name]];
+           [[tf cell] setTitle:[NSString stringWithUTF8String:i->name]];
            [tf sizeToFit];
            rect = [tf frame];
            if (thish < rect.size.height + 1) thish = rect.size.height + 1;
@@ -1055,13 +1076,15 @@ struct frontend {
                p = i->sval;
                c = *p++;
                while (*p) {
-                   char *q;
+                   char cc, *q;
 
                    q = p;
                    while (*p && *p != c) p++;
 
-                   [pb addItemWithTitle:[NSString stringWithCString:q
-                                         length:p-q]];
+                   cc = *p;
+                   *p = '\0';
+                   [pb addItemWithTitle:[NSString stringWithUTF8String:q]];
+                   *p = cc;
 
                    if (*p) p++;
                }
@@ -1209,12 +1232,13 @@ struct frontend {
        if (error) {
            NSAlert *alert = [[[NSAlert alloc] init] autorelease];
            [alert addButtonWithTitle:@"Bah"];
-           [alert setInformativeText:[NSString stringWithCString:error]];
+           [alert setInformativeText:[NSString stringWithUTF8String:error]];
            [alert beginSheetModalForWindow:self modalDelegate:nil
             didEndSelector:nil contextInfo:nil];
        } else {
            midend_new_game(me);
            [self resizeForNewGameParams];
+           [self updateTypeMenuTick];
        }
     }
     sfree(cfg_controls);
@@ -1231,7 +1255,7 @@ struct frontend {
 
 - (void)setStatusLine:(char *)text
 {
-    [[status cell] setTitle:[NSString stringWithCString:text]];
+    [[status cell] setTitle:[NSString stringWithUTF8String:text]];
 }
 
 @end
@@ -1322,7 +1346,7 @@ static void osx_draw_text(void *handle, int x, int y, int fonttype,
                          int fontsize, int align, int colour, char *text)
 {
     frontend *fe = (frontend *)handle;
-    NSString *string = [NSString stringWithCString:text];
+    NSString *string = [NSString stringWithUTF8String:text];
     NSDictionary *attr;
     NSFont *font;
     NSSize size;
@@ -1356,6 +1380,15 @@ static void osx_draw_text(void *handle, int x, int y, int fonttype,
 
     [string drawAtPoint:point withAttributes:attr];
 }
+static char *osx_text_fallback(void *handle, const char *const *strings,
+                              int nstrings)
+{
+    /*
+     * We assume OS X can cope with any UTF-8 likely to be emitted
+     * by a puzzle.
+     */
+    return dupstr(strings[0]);
+}
 struct blitter {
     int w, h;
     int x, y;
@@ -1456,7 +1489,8 @@ const struct drawing_api osx_drawing = {
     osx_blitter_save,
     osx_blitter_load,
     NULL, NULL, NULL, NULL, NULL, NULL, /* {begin,end}_{doc,page,puzzle} */
-    NULL,                             /* line_width */
+    NULL, NULL,                               /* line_width, line_dotted */
+    osx_text_fallback,
 };
 
 void deactivate_timer(frontend *fe)