merge
authorkoda
Mon, 27 Sep 2010 04:58:26 +0200
changeset 3913 f9cb69eecefe
parent 3912 e11df2de6af2 (diff)
parent 3909 4ba25a3d15af (current diff)
child 3914 c5c903c6225b
merge
--- a/hedgewars/uConsts.pas	Sun Sep 26 19:06:59 2010 -0400
+++ b/hedgewars/uConsts.pas	Mon Sep 27 04:58:26 2010 +0200
@@ -40,7 +40,7 @@
 
     TPathType = (ptNone, ptData, ptGraphics, ptThemes, ptCurrTheme, ptTeams, ptMaps,
             ptMapCurrent, ptDemos, ptSounds, ptGraves, ptFonts, ptForts,
-            ptLocale, ptAmmoMenu, ptHedgehog, ptVoices, ptHats, ptFlags);
+            ptLocale, ptAmmoMenu, ptHedgehog, ptVoices, ptHats, ptFlags, ptMissionMaps);
 
     TSprite = (sprWater, sprCloud, sprBomb, sprBigDigit, sprFrame,
             sprLag, sprArrow, sprGrenade, sprTargetP, sprBee,
@@ -460,7 +460,8 @@
         'Graphics/Hedgehog',             // ptHedgehog
         'Sounds/voices',                 // ptVoices
         'Graphics/Hats',                 // ptHats
-        'Graphics/Flags'                 // ptFlags
+        'Graphics/Flags',                // ptFlags
+        'Missions/Maps'                  // ptMissionMaps
     );
 
     cTagsMasks : array[0..15] of byte = (7, 0, 0, 0, 15, 6, 4, 5, 0, 0, 0, 0, 0, 14, 12, 13);
--- a/hedgewars/uLand.pas	Sun Sep 26 19:06:59 2010 -0400
+++ b/hedgewars/uLand.pas	Mon Sep 27 04:58:26 2010 +0200
@@ -52,7 +52,7 @@
 function  LandBackPixel(x, y: LongInt): LongWord;
 
 implementation
-uses uConsole, uStore, uMisc, uRandom, uTeams, uLandObjects, Adler32, uIO, uLandTexture;
+uses uConsole, uStore, uMisc, uRandom, uTeams, uLandObjects, Adler32, uIO, uLandTexture, sysutils;
 
 operator=(const a, b: direction) c: Boolean;
 begin
@@ -1165,22 +1165,35 @@
 var tmpsurf: PSDL_Surface;
     s: shortstring;
     f: textfile;
+    mapName: shortstring;
 begin
 isMap:= true;
 WriteLnToConsole('Loading land from file...');
 AddProgress;
-tmpsurf:= LoadImage(Pathz[ptMapCurrent] + '/map', ifAlpha or ifCritical or ifTransparent or ifIgnoreCaps);
+tmpsurf:= LoadImage(Pathz[ptMapCurrent] + '/map', ifAlpha or ifTransparent or ifIgnoreCaps);
+if tmpsurf = nil then
+begin
+    mapName:= ExtractFileName(Pathz[ptMapCurrent]);
+    tmpsurf:= LoadImage(Pathz[ptMissionMaps] + '/' + mapName + '/map', ifAlpha or ifCritical or ifTransparent or ifIgnoreCaps);
+end;
 TryDo((tmpsurf^.w <= LAND_WIDTH) and (tmpsurf^.h <= LAND_HEIGHT), 'Map dimensions too big!', true);
 
 // unC0Rr - should this be passed from the GUI? I am not sure which layer does what
 s:= Pathz[ptMapCurrent] + '/map.cfg';
 WriteLnToConsole('Fetching map HH limit');
+{$I-}
 Assign(f, s);
 filemode:= 0; // readonly
 Reset(f);
+if IOResult <> 0 then
+begin
+    s:= Pathz[ptMissionMaps] + '/' + mapName + '/map.cfg';
+    Assign(f, s);
+    Reset(f);
+end;
 Readln(f);
 if not eof(f) then Readln(f, MaxHedgehogs);
-
+{$I+}
 if (MaxHedgehogs = 0) then MaxHedgehogs:= 18;
 
 playHeight:= tmpsurf^.h;
--- a/project_files/HedgewarsMobile/Classes/CommodityFunctions.h	Sun Sep 26 19:06:59 2010 -0400
+++ b/project_files/HedgewarsMobile/Classes/CommodityFunctions.h	Mon Sep 27 04:58:26 2010 +0200
@@ -21,7 +21,8 @@
 
 #import <Foundation/Foundation.h>
 
-#define MAX_HOGS 8
+#define MAX_HOGS                8
+#define CURRENT_AMMOSIZE        48      // also add a line in SingleWeaponViewController array
 
 #define DOCUMENTS_FOLDER()      [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]
 
@@ -40,15 +41,14 @@
 #define BTN_DIRECTORY()         [[[NSBundle mainBundle] resourcePath] stringByAppendingString:@"/Data/Graphics/Btn"]
 #define FLAGS_DIRECTORY()       [[[NSBundle mainBundle] resourcePath] stringByAppendingString:@"/Data/Graphics/Flags/"]
 #define FORTS_DIRECTORY()       [[[NSBundle mainBundle] resourcePath] stringByAppendingString:@"/Data/Forts/"]
+#define VOICES_DIRECTORY()      [[[NSBundle mainBundle] resourcePath] stringByAppendingString:@"/Data/Sounds/voices/"]
 #define THEMES_DIRECTORY()      [[[NSBundle mainBundle] resourcePath] stringByAppendingString:@"/Data/Themes/"]
 #define MAPS_DIRECTORY()        [[[NSBundle mainBundle] resourcePath] stringByAppendingString:@"/Data/Maps/"]
-#define VOICES_DIRECTORY()      [[[NSBundle mainBundle] resourcePath] stringByAppendingString:@"/Data/Sounds/voices/"]
+#define MISSIONS_DIRECTORY()    [[[NSBundle mainBundle] resourcePath] stringByAppendingString:@"/Data/Missions/Maps/"]
 
 #define MSG_MEMCLEAN()          DLog(@"has cleaned up some memory");
 #define MSG_DIDUNLOAD()         DLog(@"unloaded");
 
-#define CURRENT_AMMOSIZE        48      // also add a line in SingleWeaponViewController array
-
 #define UICOLOR_HW_YELLOW_BODER [UIColor colorWithRed:(CGFloat)0xFE/255 green:(CGFloat)0xC0/255 blue:0 alpha:1]
 #define UICOLOR_HW_YELLOW_TEXT  [UIColor colorWithRed:(CGFloat)0xF0/255 green:(CGFloat)0xD0/255 blue:0 alpha:1]
 #define UICOLOR_HW_DARKBLUE     [UIColor colorWithRed:(CGFloat)0x0F/255 green:0 blue:(CGFloat)0x42/255 alpha:1]
@@ -56,10 +56,10 @@
 void createTeamNamed (NSString *nameWithoutExt);
 void createWeaponNamed (NSString *nameWithoutExt, int type);
 void createSchemeNamed (NSString *nameWithoutExt);
-BOOL rotationManager (UIInterfaceOrientation interfaceOrientation);
-NSInteger randomPort ();
+void print_free_memory ();
+void playSound (NSString *snd);
 void popError (const char *title, const char *message);
-void print_free_memory ();
+BOOL rotationManager (UIInterfaceOrientation interfaceOrientation);
 BOOL isPhone ();
+NSInteger randomPort ();
 NSString *modelType ();
-void playSound (NSString *snd);
--- a/project_files/HedgewarsMobile/Classes/GameConfigViewController.m	Sun Sep 26 19:06:59 2010 -0400
+++ b/project_files/HedgewarsMobile/Classes/GameConfigViewController.m	Mon Sep 27 04:58:26 2010 +0200
@@ -183,6 +183,7 @@
                                                                       mapConfigViewController.mazeSizeCommand,@"mazesize_command",
                                                                       mapConfigViewController.themeCommand,@"theme_command",
                                                                       mapConfigViewController.staticMapCommand,@"staticmap_command",
+                                                                      mapConfigViewController.missionCommand,@"mission_command",  
                                                                       teamConfigViewController.listOfSelectedTeams,@"teams_list",
                                                                       schemeWeaponConfigViewController.selectedScheme,@"scheme",
                                                                       schemeWeaponConfigViewController.selectedWeapon,@"weapon",
@@ -191,10 +192,13 @@
     // finally launch game and remove this controller
     DLog(@"sending config %@", gameDictionary);
 
-    if ([[gameDictionary allKeys] count] == 9) {
+    if ([[gameDictionary allKeys] count] == 10) {
         NSDictionary *allDataNecessary = [NSDictionary dictionaryWithObjectsAndKeys:gameDictionary,@"game_dictionary", @"",@"savefile",
                                                                                     [NSNumber numberWithBool:NO],@"netgame", nil];
         [[SDLUIKitDelegate sharedAppDelegate] startSDLgame:allDataNecessary];
+        
+        // tell controllers that they're being reloaded
+        [mapConfigViewController viewWillAppear:YES];
     } else {
         DLog(@"gameconfig data not complete!!\nmapConfigViewController = %@\nteamConfigViewController = %@\nschemeWeaponConfigViewController = %@\n",
              mapConfigViewController, teamConfigViewController, schemeWeaponConfigViewController);
--- a/project_files/HedgewarsMobile/Classes/GameSetup.m	Sun Sep 26 19:06:59 2010 -0400
+++ b/project_files/HedgewarsMobile/Classes/GameSetup.m	Mon Sep 27 04:58:26 2010 +0200
@@ -251,11 +251,21 @@
     [NSThread detachNewThreadSelector:usage toTarget:self withObject:nil];
 }
 
+-(void) dumpRawData:(const uint8_t*)buffer ofSize:(uint8_t) length {
+    // is it performant to reopen the stream every time?
+    NSOutputStream *os = [[NSOutputStream alloc] initToFileAtPath:self.savePath append:YES];
+    [os open];
+    [os write:&length maxLength:1];
+    [os write:buffer maxLength:length];
+    [os close];
+    [os release];
+}
+
 // wrapper that computes the length of the message and then sends the command string, saving the command on a file
 -(int) sendToEngine: (NSString *)string {
     uint8_t length = [string length];
 
-    [[NSString stringWithFormat:@"%c%@",length,string] appendToFile:savePath];
+    [self dumpRawData:(const uint8_t *)[string UTF8String] ofSize:length];
     SDLNet_TCP_Send(csd, &length, 1);
     return SDLNet_TCP_Send(csd, [string UTF8String], length);
 }
@@ -304,8 +314,6 @@
     SDLNet_TCP_Close(sd);
 
     while (!clientQuit) {
-        NSString *msgToSave = nil;
-        NSOutputStream *os = nil;
         msgSize = 0;
         memset(buffer, '\0', BUFFER_SIZE);
         if (SDLNet_TCP_Recv(csd, &msgSize, sizeof(uint8_t)) <= 0)
@@ -322,7 +330,7 @@
                 else
                     [self sendToEngineNoSave:@"TL"];
                 NSString *saveHeader = @"TS";
-                [[NSString stringWithFormat:@"%c%@",[saveHeader length], saveHeader] appendToFile:savePath];
+                [self dumpRawData:(const uint8_t *)[saveHeader UTF8String] ofSize:[saveHeader length]];
 
                 // seed info
                 [self sendToEngine:[self.gameConfig objectForKey:@"seed_command"]];
@@ -337,6 +345,11 @@
                 if ([staticMap length] != 0)
                     [self sendToEngine:staticMap];
 
+                // lua script (if set)
+                NSString *script = [self.gameConfig objectForKey:@"mission_command"];
+                if ([script length] != 0)
+                    [self sendToEngine:script];
+                
                 // theme info
                 [self sendToEngine:[self.gameConfig objectForKey:@"theme_command"]];
 
@@ -362,9 +375,8 @@
                 clientQuit = YES;
                 break;
             case 'e':
-                msgToSave = [NSString stringWithFormat:@"%c%s",msgSize,buffer];                
-                [msgToSave appendToFile:self.savePath];
-                
+                [self dumpRawData:buffer ofSize:msgSize];
+
                 sscanf((char *)buffer, "%*s %d", &eProto);
                 short int netProto = 0;
                 char *versionStr;
@@ -399,13 +411,7 @@
                 setGameRunning(NO);
                 break;
             default:
-                // is it performant to reopen the stream every time? 
-                os = [[NSOutputStream alloc] initToFileAtPath:self.savePath append:YES];
-                [os open];
-                [os write:&msgSize maxLength:1];
-                [os write:buffer maxLength:msgSize];
-                [os close];
-                [os release];
+                [self dumpRawData:buffer ofSize:msgSize];
                 break;
         }
     }
--- a/project_files/HedgewarsMobile/Classes/MapConfigViewController.h	Sun Sep 26 19:06:59 2010 -0400
+++ b/project_files/HedgewarsMobile/Classes/MapConfigViewController.h	Mon Sep 27 04:58:26 2010 +0200
@@ -20,7 +20,7 @@
 
 
 #import <UIKit/UIKit.h>
-#import "SDL_net.h"
+#import "MapPreviewButtonView.h"
 
 @protocol MapConfigDelegate <NSObject>
 
@@ -29,10 +29,9 @@
 @end
 
 
-@interface MapConfigViewController : UIViewController <UITableViewDelegate, UITableViewDataSource> {
+@interface MapConfigViewController : UIViewController <UITableViewDelegate, UITableViewDataSource, MapPreviewViewDelegate> {
     id<MapConfigDelegate> delegate;
     
-    TCPsocket sd, csd;
     NSInteger oldValue;  //slider
     NSInteger oldPage;   //segmented control
     BOOL busy;
@@ -45,9 +44,10 @@
     NSString *mazeSizeCommand;
     NSString *themeCommand;
     NSString *staticMapCommand;
+    NSString *missionCommand;
 
     // various widgets in the view
-    UIButton *previewButton;
+    MapPreviewButtonView *previewButton;
     UITableView *tableView;
     UILabel *maxLabel;
     UILabel *sizeLabel;
@@ -56,22 +56,22 @@
 
     // internal objects
     NSIndexPath *lastIndexPath;
-    NSArray *themeArray;
-    NSArray *mapArray;
+    NSArray *dataSourceArray;
 }
 
 @property (nonatomic,retain) id<MapConfigDelegate> delegate;
 
-@property (nonatomic) NSInteger maxHogs;
-@property (nonatomic) BOOL busy;
+@property (nonatomic,assign) NSInteger maxHogs;
+@property (nonatomic,assign) BOOL busy;
 @property (nonatomic,retain) NSString *seedCommand;
 @property (nonatomic,retain) NSString *templateFilterCommand;
 @property (nonatomic,retain) NSString *mapGenCommand;
 @property (nonatomic,retain) NSString *mazeSizeCommand;
 @property (nonatomic,retain) NSString *themeCommand;
 @property (nonatomic,retain) NSString *staticMapCommand;
+@property (nonatomic,retain) NSString *missionCommand;
 
-@property (nonatomic,retain) IBOutlet UIButton *previewButton;
+@property (nonatomic,retain) IBOutlet MapPreviewButtonView *previewButton;
 @property (nonatomic,retain) IBOutlet UITableView *tableView;
 @property (nonatomic,retain) IBOutlet UILabel *maxLabel;
 @property (nonatomic,retain) IBOutlet UILabel *sizeLabel;
@@ -79,8 +79,7 @@
 @property (nonatomic,retain) IBOutlet UISlider *slider;
 
 @property (nonatomic,retain) NSIndexPath *lastIndexPath;
-@property (nonatomic,retain) NSArray *themeArray;
-@property (nonatomic,retain) NSArray *mapArray;
+@property (nonatomic,retain) NSArray *dataSourceArray;
 
 -(IBAction) buttonPressed:(id) sender;
 
@@ -92,10 +91,6 @@
 -(void) turnOnWidgets;
 -(void) turnOffWidgets;
 -(void) setLabelText:(NSString *)str;
--(void) setButtonImage:(UIImage *)img;
 -(void) updatePreview;
--(void) updatePreviewWithMap:(NSInteger) index;
-
--(const uint8_t *)engineProtocol:(NSInteger) port;
 
 @end
--- a/project_files/HedgewarsMobile/Classes/MapConfigViewController.m	Sun Sep 26 19:06:59 2010 -0400
+++ b/project_files/HedgewarsMobile/Classes/MapConfigViewController.m	Mon Sep 27 04:58:26 2010 +0200
@@ -23,144 +23,19 @@
 #import "PascalImports.h"
 #import "CommodityFunctions.h"
 #import "UIImageExtra.h"
-#import "SDL_net.h"
-#import <pthread.h>
 
-#define INDICATOR_TAG 7654
+#define scIndex         self.segmentedControl.selectedSegmentIndex
+#define isRandomness()  (segmentedControl.selectedSegmentIndex == 0 || segmentedControl.selectedSegmentIndex == 2)
 
 @implementation MapConfigViewController
 @synthesize previewButton, maxHogs, seedCommand, templateFilterCommand, mapGenCommand, mazeSizeCommand, themeCommand, staticMapCommand,
-            tableView, maxLabel, sizeLabel, segmentedControl, slider, lastIndexPath, themeArray, mapArray, busy, delegate;
+            missionCommand, tableView, maxLabel, sizeLabel, segmentedControl, slider, lastIndexPath, dataSourceArray, busy, delegate;
 
 
 -(BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
     return rotationManager(interfaceOrientation);
 }
 
-#pragma mark -
-#pragma mark Preview Handling
--(int) sendToEngine: (NSString *)string {
-    unsigned char length = [string length];
-
-    SDLNet_TCP_Send(csd, &length , 1);
-    return SDLNet_TCP_Send(csd, [string UTF8String], length);
-}
-
--(const uint8_t *)engineProtocol:(NSInteger) port {
-    IPaddress ip;
-    BOOL serverQuit = NO;
-    static uint8_t map[128*32];
-
-    if (SDLNet_Init() < 0) {
-        DLog(@"SDLNet_Init: %s", SDLNet_GetError());
-        serverQuit = YES;
-    }
-
-    // Resolving the host using NULL make network interface to listen
-    if (SDLNet_ResolveHost(&ip, NULL, port) < 0) {
-        DLog(@"SDLNet_ResolveHost: %s\n", SDLNet_GetError());
-        serverQuit = YES;
-    }
-
-    // Open a connection with the IP provided (listen on the host's port)
-    if (!(sd = SDLNet_TCP_Open(&ip))) {
-        DLog(@"SDLNet_TCP_Open: %s %\n", SDLNet_GetError(), port);
-        serverQuit = YES;
-    }
-
-    // launch the preview here so that we're sure the tcp channel is open
-    pthread_t thread_id;
-    pthread_create(&thread_id, NULL, (void *)GenLandPreview, (void *)port);
-    pthread_detach(thread_id);
-
-    DLog(@"Waiting for a client on port %d", port);
-    while (!serverQuit) {
-        /* This check the sd if there is a pending connection.
-         * If there is one, accept that, and open a new socket for communicating */
-        csd = SDLNet_TCP_Accept(sd);
-        if (NULL != csd) {
-            DLog(@"Client found");
-
-            [self sendToEngine:self.seedCommand];
-            [self sendToEngine:self.templateFilterCommand];
-            [self sendToEngine:self.mapGenCommand];
-            [self sendToEngine:self.mazeSizeCommand];
-            [self sendToEngine:@"!"];
-
-            memset(map, 0, 128*32);
-            SDLNet_TCP_Recv(csd, map, 128*32);
-            SDLNet_TCP_Recv(csd, &maxHogs, sizeof(uint8_t));
-
-            SDLNet_TCP_Close(csd);
-            serverQuit = YES;
-        }
-    }
-
-    SDLNet_TCP_Close(sd);
-    SDLNet_Quit();
-    return map;
-}
-
--(void) drawingThread {
-    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-
-    // select the port for IPC and launch the preview generation through engineProtocol:
-    int port = randomPort();
-    const uint8_t *map = [self engineProtocol:port];
-    uint8_t mapExp[128*32*8];
-
-    // draw the buffer (1 pixel per component, 0= transparent 1= color)
-    int k = 0;
-    for (int i = 0; i < 32*128; i++) {
-        unsigned char byte = map[i];
-        for (int j = 0; j < 8; j++) {
-            // select the color based on the leftmost bit
-            if ((byte & 0x80) != 0)
-                mapExp[k] = 100;
-            else
-                mapExp[k] = 255;
-            // shift to next bit
-            byte <<= 1;
-            k++;
-        }
-    }
-    CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceGray();
-    CGContextRef bitmapImage = CGBitmapContextCreate(mapExp, 256, 128, 8, 256, colorspace, kCGImageAlphaNone);
-    CGColorSpaceRelease(colorspace);
-
-    CGImageRef previewCGImage = CGBitmapContextCreateImage(bitmapImage);
-    CGContextRelease(bitmapImage);
-    UIImage *previewImage = [[UIImage alloc] initWithCGImage:previewCGImage];
-    CGImageRelease(previewCGImage);
-    previewCGImage = nil;
-
-    // set the preview image (autoreleased) in the button and the maxhog label on the main thread to prevent a leak
-    [self performSelectorOnMainThread:@selector(setButtonImage:) withObject:[previewImage makeRoundCornersOfSize:CGSizeMake(12, 12)] waitUntilDone:NO];
-    [previewImage release];
-    [self performSelectorOnMainThread:@selector(setLabelText:) withObject:[NSString stringWithFormat:@"%d", maxHogs] waitUntilDone:NO];
-
-    // restore functionality of button and remove the spinning wheel on the main thread to prevent a leak
-    [self performSelectorOnMainThread:@selector(turnOnWidgets) withObject:nil waitUntilDone:NO];
-
-    [pool release];
-    //Invoking this method should be avoided as it does not give your thread a chance to clean up any resources it allocated during its execution.
-    //[NSThread exit];
-
-    /*
-    // http://developer.apple.com/mac/library/qa/qa2001/qa1037.html
-    UIGraphicsBeginImageContext(CGSizeMake(256,128));
-    CGContextRef context = UIGraphicsGetCurrentContext();
-    UIGraphicsPushContext(context);
-
-    CGContextSetRGBFillColor(context, 0.5, 0.5, 0.7, 1.0);
-    CGContextFillRect(context,CGRectMake(xc,yc,1,1));
-
-    UIGraphicsPopContext();
-    UIImage *previewImage = UIGraphicsGetImageFromCurrentImageContext();
-    UIGraphicsEndImageContext();
-    */
-}
-
 -(IBAction) mapButtonPressed {
     playSound(@"clickSound");
     [self updatePreview];
@@ -176,77 +51,27 @@
     NSString *seed = (NSString *)CFUUIDCreateString(kCFAllocatorDefault, uuid);
     CFRelease(uuid);
     NSString *seedCmd = [[NSString alloc] initWithFormat:@"eseed {%@}", seed];
-    [seed release];
     self.seedCommand = seedCmd;
     [seedCmd release];
 
+    NSArray *source = [self.dataSourceArray objectAtIndex:scIndex];
     NSIndexPath *theIndex;
-    if (segmentedControl.selectedSegmentIndex != 1) {
-        // remove the current preview and title
-        [self.previewButton setImage:nil forState:UIControlStateNormal];
-        [self.previewButton setTitle:nil forState:UIControlStateNormal];
-
-        // don't display preview on slower device, too slow and memory hog
-        NSString *modelId = modelType();
-        if ([modelId hasPrefix:@"iPhone1"] || [modelId hasPrefix:@"iPod1,1"] || [modelId hasPrefix:@"iPod2,1"]) {
-            busy = NO;
-            [self.previewButton setTitle:NSLocalizedString(@"Preview not available",@"") forState:UIControlStateNormal];
-        } else {
-            // prevent other events and add an activity while the preview is beign generated
-            [self turnOffWidgets];
+    if (isRandomness()) {
+        // prevent other events and add an activity while the preview is beign generated
+        [self turnOffWidgets];
+        [self.previewButton updatePreviewWithSeed:seed];
+        theIndex = [NSIndexPath indexPathForRow:(random()%[source count]) inSection:0];
+    } else {
+        theIndex = [NSIndexPath indexPathForRow:(random()%[source count]) inSection:0];
+        // the preview for static maps is loaded in didSelectRowAtIndexPath
+    }
+    [seed release];
 
-            // add a very nice spinning wheel
-            UIActivityIndicatorView *indicator = [[UIActivityIndicatorView alloc]
-                                                  initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
-            indicator.center = CGPointMake(previewButton.bounds.size.width / 2, previewButton.bounds.size.height / 2);
-            indicator.tag = INDICATOR_TAG;
-            [indicator startAnimating];
-            [self.previewButton addSubview:indicator];
-            [indicator release];
-
-            // let's draw in a separate thread so the gui can work; at the end it restore other widgets
-            [NSThread detachNewThreadSelector:@selector(drawingThread) toTarget:self withObject:nil];
-        }
-
-        theIndex = [NSIndexPath indexPathForRow:(random()%[self.themeArray count]) inSection:0];
-    } else {
-        theIndex = [NSIndexPath indexPathForRow:(random()%[self.mapArray count]) inSection:0];
-    }
-    [self.tableView reloadData];
+    // perform as if user clicked on an entry
     [self tableView:self.tableView didSelectRowAtIndexPath:theIndex];
     [self.tableView scrollToRowAtIndexPath:theIndex atScrollPosition:UITableViewScrollPositionNone animated:YES];
 }
 
-// instead of drawing a random map we load an image; this function is called by didSelectRowAtIndexPath only
--(void) updatePreviewWithMap:(NSInteger) index {
-    // change the preview button
-    NSString *fileImage = [[NSString alloc] initWithFormat:@"%@/%@/preview.png", MAPS_DIRECTORY(),[self.mapArray objectAtIndex:index]];
-    UIImage *image = [[UIImage alloc] initWithContentsOfFile:fileImage];
-    [fileImage release];
-    [self.previewButton setImage:[image makeRoundCornersOfSize:CGSizeMake(12, 12)] forState:UIControlStateNormal];
-    [image release];
-
-    // update label
-    maxHogs = 18;
-    NSString *fileCfg = [[NSString alloc] initWithFormat:@"%@/%@/map.cfg", MAPS_DIRECTORY(),[self.mapArray objectAtIndex:index]];
-    NSString *contents = [[NSString alloc] initWithContentsOfFile:fileCfg encoding:NSUTF8StringEncoding error:NULL];
-    [fileCfg release];
-    NSArray *split = [contents componentsSeparatedByString:@"\n"];
-    [contents release];
-
-    // set the theme and map here
-    self.themeCommand = [NSString stringWithFormat:@"etheme %@", [split objectAtIndex:0]];
-    self.staticMapCommand = [NSString stringWithFormat:@"emap %@", [self.mapArray objectAtIndex:index]];
-
-    // if the number is not set we keep 18 standard;
-    // sometimes it's not set but there are trailing characters, we get around them with the second equation
-    if ([split count] > 1 && [[split objectAtIndex:1] intValue] > 0)
-        maxHogs = [[split objectAtIndex:1] intValue];
-    NSString *max = [[NSString alloc] initWithFormat:@"%d",maxHogs];
-    self.maxLabel.text = max;
-    [max release];
-}
-
 -(void) turnOffWidgets {
     busy = YES;
     self.previewButton.alpha = 0.5f;
@@ -262,35 +87,21 @@
     self.segmentedControl.enabled = YES;
     self.slider.enabled = YES;
     busy = NO;
-
-    UIActivityIndicatorView *indicator = (UIActivityIndicatorView *)[self.previewButton viewWithTag:INDICATOR_TAG];
-    if (indicator) {
-        [indicator stopAnimating];
-        [indicator removeFromSuperview];
-    }
 }
 
 -(void) setLabelText:(NSString *)str {
+    self.maxHogs = [str intValue];
     self.maxLabel.text = str;
 }
 
--(void) setButtonImage:(UIImage *)img {
-    [self.previewButton setBackgroundImage:img forState:UIControlStateNormal];
-}
-
--(void) restoreBackgroundImage {
-    // white rounded rectangle as background image for previewButton
-    UIGraphicsBeginImageContext(CGSizeMake(256,128));
-    CGContextRef context = UIGraphicsGetCurrentContext();
-    UIGraphicsPushContext(context);
-
-    CGContextSetRGBFillColor(context, 1.0, 1.0, 1.0, 1.0);
-    CGContextFillRect(context,CGRectMake(0,0,256,128));
-
-    UIGraphicsPopContext();
-    UIImage *bkgImg = UIGraphicsGetImageFromCurrentImageContext();
-    UIGraphicsEndImageContext();
-    [self.previewButton setBackgroundImage:[bkgImg makeRoundCornersOfSize:CGSizeMake(12, 12)] forState:UIControlStateNormal];
+-(NSDictionary *)getDataForEngine {
+    NSDictionary *dictForEngine = [NSDictionary dictionaryWithObjectsAndKeys:
+                                   self.seedCommand,@"seedCommand",
+                                   self.templateFilterCommand,@"templateFilterCommand",
+                                   self.mapGenCommand,@"mapGenCommand",
+                                   self.mazeSizeCommand,@"mazeSizeCommand",
+                                   nil];
+    return dictForEngine;
 }
 
 #pragma mark -
@@ -300,10 +111,7 @@
 }
 
 -(NSInteger) tableView:(UITableView *)aTableView numberOfRowsInSection:(NSInteger) section {
-    if (self.segmentedControl.selectedSegmentIndex != 1)
-        return [themeArray count];
-    else
-        return [mapArray count];
+    return [[self.dataSourceArray objectAtIndex:scIndex] count];
 }
 
 -(UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
@@ -317,17 +125,17 @@
     if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
         cell.textLabel.textColor = UICOLOR_HW_YELLOW_TEXT;
 
-    if (self.segmentedControl.selectedSegmentIndex != 1) {
-        // the % prevents a strange bug that occurs sporadically
-        NSString *themeName = [self.themeArray objectAtIndex:row % [self.themeArray count]];
-        cell.textLabel.text = themeName;
-        UIImage *image = [[UIImage alloc] initWithContentsOfFile:[NSString stringWithFormat:@"%@/%@/icon.png",THEMES_DIRECTORY(),themeName]];
+    NSArray *source = [self.dataSourceArray objectAtIndex:scIndex];
+
+    NSString *labelString = [source objectAtIndex:row];
+    cell.textLabel.text = labelString;
+
+    if (isRandomness()) {
+        UIImage *image = [[UIImage alloc] initWithContentsOfFile:[NSString stringWithFormat:@"%@/%@/icon.png",THEMES_DIRECTORY(),labelString]];
         cell.imageView.image = image;
         [image release];
-    } else {
-        cell.textLabel.text = [self.mapArray objectAtIndex:row];
+    } else
         cell.imageView.image = nil;
-    }
 
     if (row == [self.lastIndexPath row]) {
         UIImageView *checkbox = [[UIImageView alloc] initWithImage:[UIImage imageWithContentsOfFile:@"checkbox.png"]];
@@ -340,6 +148,35 @@
     return cell;
 }
 
+// this set details for a static map (called by didSelectRowAtIndexPath)
+-(void) setDetailsForStaticMap:(NSInteger) index {
+    NSArray *source = [self.dataSourceArray objectAtIndex:scIndex];
+    
+    NSString *fileCfg = [[NSString alloc] initWithFormat:@"%@/%@/map.cfg", 
+                         (scIndex == 1) ? MAPS_DIRECTORY() : MISSIONS_DIRECTORY(),[source objectAtIndex:index]];
+    NSString *contents = [[NSString alloc] initWithContentsOfFile:fileCfg encoding:NSUTF8StringEncoding error:NULL];
+    [fileCfg release];
+    NSArray *split = [contents componentsSeparatedByString:@"\n"];
+    [contents release];
+
+    // if the number is not set we keep 18 standard;
+    // sometimes it's not set but there are trailing characters, we get around them with the second equation
+    if ([split count] > 1 && [[split objectAtIndex:1] intValue] > 0)
+        maxHogs = [[split objectAtIndex:1] intValue];
+    else
+        maxHogs = 18;
+    NSString *max = [[NSString alloc] initWithFormat:@"%d",maxHogs];
+    self.maxLabel.text = max;
+    [max release];
+    
+    self.themeCommand = [NSString stringWithFormat:@"etheme %@", [split objectAtIndex:0]];
+    self.staticMapCommand = [NSString stringWithFormat:@"emap %@", [source objectAtIndex:index]];
+
+    if (scIndex != 3)
+        self.missionCommand = @"";
+    else
+        self.missionCommand = [NSString stringWithFormat:@"escript %@/%@/map.lua",MISSIONS_DIRECTORY(),[source objectAtIndex:index]];
+}
 
 #pragma mark -
 #pragma mark Table view delegate
@@ -348,12 +185,15 @@
     int oldRow = (lastIndexPath != nil) ? [lastIndexPath row] : -1;
 
     if (newRow != oldRow) {
-        if (self.segmentedControl.selectedSegmentIndex != 1) {
-            NSString *theme = [self.themeArray objectAtIndex:newRow];
-            self.themeCommand = [NSString stringWithFormat:@"etheme %@", theme];
+        NSArray *source = [self.dataSourceArray objectAtIndex:scIndex];
+        if (isRandomness()) {
+            // just change the theme, don't update preview
+            self.themeCommand = [NSString stringWithFormat:@"etheme %@", [source objectAtIndex:newRow]];
         } else {
-            // theme and map are set in the function below
-            [self updatePreviewWithMap:newRow];
+            NSString *fileImage = [NSString stringWithFormat:@"%@/%@/preview.png",
+                                   (scIndex == 1) ? MAPS_DIRECTORY() : MISSIONS_DIRECTORY(),[source objectAtIndex:newRow]];
+            [self.previewButton updatePreviewWithFile:fileImage];
+            [self setDetailsForStaticMap:newRow];
         }
 
         UITableViewCell *newCell = [aTableView cellForRowAtIndexPath:indexPath];
@@ -456,10 +296,9 @@
 }
 
 // perform actions based on the activated section, then call updatePreview to visually update the selection
-// updatePreview will call didSelectRowAtIndexPath which will call the right update routine)
 // and if necessary update the table with a slide animation
 -(IBAction) segmentedControlChanged:(id) sender {
-    NSString *mapgen, *staticmap;
+    NSString *mapgen, *staticmap, *mission;
     NSInteger newPage = self.segmentedControl.selectedSegmentIndex;
 
     playSound(@"selSound");
@@ -467,22 +306,25 @@
         case 0: // Random
             mapgen = @"e$mapgen 0";
             staticmap = @"";
+            mission = @"";
             [self sliderChanged:nil];
             self.slider.enabled = YES;
             break;
 
         case 1: // Map
+        case 3: // Mission
             mapgen = @"e$mapgen 0";
-            // dummy value, everything is set by -updatePreview -> -didSelectRowAtIndexPath -> -updatePreviewWithMap
+            // dummy values, these are set by -updatePreview -> -didSelectRowAtIndexPath -> -setDetailsForStaticMap
             staticmap = @"map Bamboo";
+            mission = @"";
             self.slider.enabled = NO;
             self.sizeLabel.text = NSLocalizedString(@"No filter",@"");
-            [self restoreBackgroundImage];
             break;
 
         case 2: // Maze
             mapgen = @"e$mapgen 1";
             staticmap = @"";
+            mission = @"";
             [self sliderChanged:nil];
             self.slider.enabled = YES;
             break;
@@ -490,31 +332,52 @@
         default:
             mapgen = nil;
             staticmap = nil;
+            mission = nil;
             break;
     }
     self.mapGenCommand = mapgen;
     self.staticMapCommand = staticmap;
-    [self updatePreview];
+    self.missionCommand = mission;
 
     // nice animation for updating the table when appropriate (on iphone)
     if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
-        if (((oldPage == 0 || oldPage == 2) && newPage == 1) ||
-            (oldPage == 1 && (newPage == 0 || newPage == 2))) {
-            [UIView beginAnimations:@"moving out table" context:NULL];
+        if (((oldPage == 0 || oldPage == 2) && (newPage == 1 || newPage == 3)) ||
+            ((oldPage == 1 || oldPage == 3) && (newPage == 0 || newPage == 2)) ||
+            ((oldPage == 1 && newPage == 3) || (oldPage == 3 || newPage == 1))) {
             self.tableView.frame = CGRectMake(480, 0, 185, 276);
+            [UIView beginAnimations:@"moving in table" context:NULL];
+            self.tableView.frame = CGRectMake(295, 0, 185, 276);
             [UIView commitAnimations];
-            [self performSelector:@selector(moveTable) withObject:nil afterDelay:0.2];
         }
+
+    [self.tableView reloadData];
+    [self updatePreview];
     oldPage = newPage;
 }
 
-// update data when table is not visible and then show it
--(void) moveTable {
-    [self.tableView reloadData];
+#pragma mark -
+#pragma mark delegate functions for iPad
+-(IBAction) buttonPressed:(id) sender {
+    if (self.delegate != nil && [delegate respondsToSelector:@selector(buttonPressed:)])
+        [self.delegate buttonPressed:(UIButton *)sender];
+}
 
-    [UIView beginAnimations:@"moving in table" context:NULL];
-    self.tableView.frame = CGRectMake(295, 0, 185, 276);
-    [UIView commitAnimations];
+-(void) loadDataSourceArray {
+    // themes.cfg contains all the user-selectable themes
+    NSString *string = [[NSString alloc] initWithContentsOfFile:[THEMES_DIRECTORY() stringByAppendingString:@"/themes.cfg"]
+                                                       encoding:NSUTF8StringEncoding
+                                                          error:NULL];
+    NSMutableArray *themeArray = [[NSMutableArray alloc] initWithArray:[string componentsSeparatedByString:@"\n"]];
+    [string release];
+    // remove a trailing "" element
+    [themeArray removeLastObject];
+    NSArray *mapArray = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:MAPS_DIRECTORY() error:NULL];
+    NSArray *missionArray = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:MISSIONS_DIRECTORY() error:NULL];
+    
+    NSArray *array = [[NSArray alloc] initWithObjects:themeArray,mapArray,themeArray,missionArray,nil];
+    self.dataSourceArray = array;
+    [array release];
+    [themeArray release];
 }
 
 #pragma mark -
@@ -526,30 +389,18 @@
 
     CGSize screenSize = [[UIScreen mainScreen] bounds].size;
     self.view.frame = CGRectMake(0, 0, screenSize.height, screenSize.width - 44);
-
-    // themes.cfg contains all the user-selectable themes
-    NSString *string = [[NSString alloc] initWithContentsOfFile:[THEMES_DIRECTORY() stringByAppendingString:@"/themes.cfg"]
-                                                       encoding:NSUTF8StringEncoding
-                                                          error:NULL];
-    NSMutableArray *array = [[NSMutableArray alloc] initWithArray:[string componentsSeparatedByString:@"\n"]];
-    [string release];
-    // remove a trailing "" element
-    [array removeLastObject];
-    self.themeArray = array;
-    [array release];
-    self.mapArray = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:MAPS_DIRECTORY() error:NULL];
-
-    busy = NO;
-
-    // draw a white background
-    [self restoreBackgroundImage];
-
+    
     // initialize some "default" values
     self.sizeLabel.text = NSLocalizedString(@"All",@"");
     self.slider.value = 0.05f;
-
+    oldValue = 5;
+    
+    busy = NO;
+    [self loadDataSourceArray];
+    self.lastIndexPath = [NSIndexPath indexPathForRow:-1 inSection:0];
+    
     // select a map at first because it's faster - done in IB
-    //self.segmentedControl.selectedSegmentIndex = 1;
+    oldPage = 1;
     if (self.segmentedControl.selectedSegmentIndex == 1) {
         self.slider.enabled = NO;
         self.sizeLabel.text = NSLocalizedString(@"No filter",@"");
@@ -559,12 +410,8 @@
     self.mazeSizeCommand = @"e$maze_size 0";
     self.mapGenCommand = @"e$mapgen 0";
     self.staticMapCommand = @"";
-
-    self.lastIndexPath = [NSIndexPath indexPathForRow:-1 inSection:0];
+    self.missionCommand = @"";
 
-    oldValue = 5;
-    oldPage = 0;
-    
     if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
         [self.tableView setBackgroundView:nil];
         self.view.backgroundColor = [UIColor clearColor];
@@ -574,23 +421,15 @@
     }
 }
 
--(void) viewDidAppear:(BOOL) animated {
-    [super viewDidAppear:animated];
-    [self updatePreview];
+-(void) viewWillAppear:(BOOL)animated {
+    if (self.dataSourceArray == nil)
+        [self loadDataSourceArray];
+    [super viewWillAppear:animated];
 }
 
-#pragma mark -
-#pragma mark delegate functions for iPad
--(IBAction) buttonPressed:(id) sender {
-    if (self.delegate != nil && [delegate respondsToSelector:@selector(buttonPressed:)])
-        [self.delegate buttonPressed:(UIButton *)sender];
-}
-
-#pragma mark -
--(void) didReceiveMemoryWarning {
-    [super didReceiveMemoryWarning];
-    //[previewButton setImage:nil forState:UIControlStateNormal];
-    MSG_MEMCLEAN();
+-(void) viewDidAppear:(BOOL) animated {
+    [self updatePreview];
+    [super viewDidAppear:animated];
 }
 
 -(void) viewDidUnload {
@@ -603,6 +442,7 @@
     self.mazeSizeCommand = nil;
     self.themeCommand = nil;
     self.staticMapCommand = nil;
+    self.missionCommand = nil;
 
     self.previewButton = nil;
     self.tableView = nil;
@@ -612,13 +452,19 @@
     self.slider = nil;
 
     self.lastIndexPath = nil;
-    self.themeArray = nil;
-    self.mapArray = nil;
+    self.dataSourceArray = nil;
 
     MSG_DIDUNLOAD();
     [super viewDidUnload];
 }
 
+-(void) didReceiveMemoryWarning {
+    [super didReceiveMemoryWarning];
+    self.dataSourceArray = nil;
+    // maybe we can save some more
+    MSG_MEMCLEAN();
+}
+
 -(void) dealloc {
     self.delegate = nil;
     
@@ -628,6 +474,7 @@
     [mazeSizeCommand release];
     [themeCommand release];
     [staticMapCommand release];
+    [missionCommand release];
 
     [previewButton release];
     [tableView release];
@@ -637,11 +484,9 @@
     [slider release];
 
     [lastIndexPath release];
-    [themeArray release];
-    [mapArray release];
+    [dataSourceArray release];
 
     [super dealloc];
 }
 
-
 @end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/HedgewarsMobile/Classes/MapPreviewButtonView.h	Mon Sep 27 04:58:26 2010 +0200
@@ -0,0 +1,49 @@
+/*
+ * Hedgewars-iOS, a Hedgewars port for iOS devices
+ * Copyright (c) 2009-2010 Vittorio Giovara <vittorio.giovara@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * File created on 26/09/2010.
+ */
+
+
+#import <UIKit/UIKit.h>
+#import "SDL_net.h"
+
+@protocol MapPreviewViewDelegate <NSObject>
+
+-(void) turnOnWidgets;
+-(void) setLabelText:(NSString *)string;
+-(NSDictionary *)getDataForEngine;
+
+@end
+
+@interface MapPreviewButtonView : UIButton {
+    id<MapPreviewViewDelegate> delegate;
+    TCPsocket sd, csd;
+    NSInteger maxHogs;
+}
+
+@property (nonatomic,assign) id<MapPreviewViewDelegate> delegate;
+
+
+-(void) setBackgroundImageRounded:(UIImage *)image forState:(UIControlState)state;
+-(void) setImageRounded:(UIImage *)image forState:(UIControlState)state;
+-(void) setImageRoundedForNormalState:(UIImage *)image;
+-(void) updatePreviewWithSeed:(NSString *)seed;
+-(void) updatePreviewWithFile:(NSString *)filePath;
+-(NSDictionary *)getDataForEngine;
+
+@end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/HedgewarsMobile/Classes/MapPreviewButtonView.m	Mon Sep 27 04:58:26 2010 +0200
@@ -0,0 +1,246 @@
+/*
+ * Hedgewars-iOS, a Hedgewars port for iOS devices
+ * Copyright (c) 2009-2010 Vittorio Giovara <vittorio.giovara@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * File created on 26/09/2010.
+ */
+
+
+#import "MapPreviewButtonView.h"
+#import "MapConfigViewController.h"
+#import "UIImageExtra.h"
+#import <pthread.h>
+
+#define INDICATOR_TAG 7654
+
+@implementation MapPreviewButtonView
+@synthesize delegate;
+
+-(id) initWithFrame:(CGRect)frame {
+    if ((self = [super initWithFrame:frame])) {
+        delegate = nil;
+        [self setBackgroundImageRounded:[UIImage whiteImage:frame.size] forState:UIControlStateNormal];
+    }
+    return self;
+}
+
+-(id) initWithCoder:(NSCoder *)aDecoder {
+    if ((self = [super initWithCoder:aDecoder])) {
+        delegate = nil;
+        [self setBackgroundImageRounded:[UIImage whiteImage:self.frame.size] forState:UIControlStateNormal];
+    }
+    return self;
+}
+
+-(void) dealloc {
+    self.delegate = nil;
+    [super dealloc];
+}
+
+#pragma mark -
+#pragma mark image wrappers
+-(void) setBackgroundImageRounded:(UIImage *)image forState:(UIControlState)state {
+    [self setBackgroundImage:[image makeRoundCornersOfSize:CGSizeMake(12, 12)] forState:UIControlStateNormal];    
+}
+
+-(void) setImageRounded:(UIImage *)image forState:(UIControlState)state {
+    [self setImage:[image makeRoundCornersOfSize:CGSizeMake(12, 12)] forState:UIControlStateNormal];    
+}
+
+-(void) setImageRoundedForNormalState:(UIImage *)image {
+    [self setImageRounded:image forState:UIControlStateNormal];
+}
+
+#pragma mark -
+#pragma mark preview 
+-(int) sendToEngine:(NSString *)string {
+    unsigned char length = [string length];
+
+    SDLNet_TCP_Send(csd, &length, 1);
+    return SDLNet_TCP_Send(csd, [string UTF8String], length);
+}
+
+-(const uint8_t *)engineProtocol {
+    IPaddress ip;
+    BOOL serverQuit = NO;
+    static uint8_t map[128*32];
+    int port = randomPort();
+
+    if (SDLNet_Init() < 0) {
+        DLog(@"SDLNet_Init: %s", SDLNet_GetError());
+        serverQuit = YES;
+    }
+
+    // Resolving the host using NULL make network interface to listen
+    if (SDLNet_ResolveHost(&ip, NULL, port) < 0) {
+        DLog(@"SDLNet_ResolveHost: %s\n", SDLNet_GetError());
+        serverQuit = YES;
+    }
+
+    // Open a connection with the IP provided (listen on the host's port)
+    if (!(sd = SDLNet_TCP_Open(&ip))) {
+        DLog(@"SDLNet_TCP_Open: %s %\n", SDLNet_GetError(), port);
+        serverQuit = YES;
+    }
+
+    // launch the preview here so that we're sure the tcp channel is open
+    pthread_t thread_id;
+    pthread_create(&thread_id, NULL, (void *)GenLandPreview, (void *)port);
+    pthread_detach(thread_id);
+
+    DLog(@"Waiting for a client on port %d", port);
+    while (!serverQuit) {
+        /* This check the sd if there is a pending connection.
+         * If there is one, accept that, and open a new socket for communicating */
+        csd = SDLNet_TCP_Accept(sd);
+        if (NULL != csd) {
+            DLog(@"Client found");
+
+            NSDictionary *dictForEngine = [self getDataForEngine];
+            [self sendToEngine:[dictForEngine objectForKey:@"seedCommand"]];
+            [self sendToEngine:[dictForEngine objectForKey:@"templateFilterCommand"]];
+            [self sendToEngine:[dictForEngine objectForKey:@"mapGenCommand"]];
+            [self sendToEngine:[dictForEngine objectForKey:@"mazeSizeCommand"]];
+            [self sendToEngine:@"!"];
+
+            memset(map, 0, 128*32);
+            SDLNet_TCP_Recv(csd, map, 128*32);
+            SDLNet_TCP_Recv(csd, &maxHogs, sizeof(uint8_t));
+
+            SDLNet_TCP_Close(csd);
+            serverQuit = YES;
+        }
+    }
+
+    SDLNet_TCP_Close(sd);
+    SDLNet_Quit();
+    return map;
+}
+
+-(void) drawingThread {
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+    const uint8_t *map = [self engineProtocol];
+    uint8_t mapExp[128*32*8];
+
+    // draw the buffer (1 pixel per component, 0= transparent 1= color)
+    int k = 0;
+    for (int i = 0; i < 32*128; i++) {
+        unsigned char byte = map[i];
+        for (int j = 0; j < 8; j++) {
+            // select the color based on the leftmost bit
+            if ((byte & 0x80) != 0)
+                mapExp[k] = 100;
+            else
+                mapExp[k] = 255;
+            // shift to next bit
+            byte <<= 1;
+            k++;
+        }
+    }
+    CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceGray();
+    CGContextRef bitmapImage = CGBitmapContextCreate(mapExp, 256, 128, 8, 256, colorspace, kCGImageAlphaNone);
+    CGColorSpaceRelease(colorspace);
+
+    CGImageRef previewCGImage = CGBitmapContextCreateImage(bitmapImage);
+    CGContextRelease(bitmapImage);
+    UIImage *previewImage = [[UIImage alloc] initWithCGImage:previewCGImage];
+    CGImageRelease(previewCGImage);
+    previewCGImage = nil;
+
+    // all these are performed on the main thread to prevent a leak
+    [self performSelectorOnMainThread:@selector(setImageRoundedForNormalState:)
+                           withObject:previewImage
+                        waitUntilDone:NO];
+    [previewImage release];
+    [self performSelectorOnMainThread:@selector(setLabelText:)
+                           withObject:[NSString stringWithFormat:@"%d", maxHogs]
+                        waitUntilDone:NO];
+    [self performSelectorOnMainThread:@selector(turnOnWidgets)
+                           withObject:nil
+                        waitUntilDone:NO];
+    [self performSelectorOnMainThread:@selector(removeIndicator)
+                           withObject:nil
+                        waitUntilDone:NO];
+    
+    [pool release];
+
+    /*
+    // http://developer.apple.com/mac/library/qa/qa2001/qa1037.html
+    UIGraphicsBeginImageContext(CGSizeMake(256,128));
+    CGContextRef context = UIGraphicsGetCurrentContext();
+    UIGraphicsPushContext(context);
+    CGContextSetRGBFillColor(context, 0.5, 0.5, 0.7, 1.0);
+    CGContextFillRect(context,CGRectMake(xc,yc,1,1));
+    UIGraphicsPopContext();
+    UIImage *previewImage = UIGraphicsGetImageFromCurrentImageContext();
+    UIGraphicsEndImageContext();
+    */
+}
+
+-(void) updatePreviewWithSeed:(NSString *)seed {
+    // remove the current preview and title
+    [self setImage:nil forState:UIControlStateNormal];
+    [self setTitle:nil forState:UIControlStateNormal];
+    
+    // don't display preview on slower device, too slow and memory hog
+    NSString *modelId = modelType();
+    if ([modelId hasPrefix:@"iPhone1"] || [modelId hasPrefix:@"iPod1,1"] || [modelId hasPrefix:@"iPod2,1"]) {
+        //self.delegate.busy = NO;
+        [self setTitle:NSLocalizedString(@"Preview not available",@"") forState:UIControlStateNormal];
+    } else {        
+        // add a very nice spinning wheel
+        UIActivityIndicatorView *indicator = [[UIActivityIndicatorView alloc]
+                                              initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
+        indicator.center = CGPointMake(self.bounds.size.width / 2, self.bounds.size.height / 2);
+        indicator.tag = INDICATOR_TAG;
+        [indicator startAnimating];
+        [self addSubview:indicator];
+        [indicator release];
+        
+        // let's draw in a separate thread so the gui can work; at the end it restore other widgets
+        [NSThread detachNewThreadSelector:@selector(drawingThread) toTarget:self withObject:nil];
+    }
+}
+
+-(void) updatePreviewWithFile:(NSString *)filePath {
+    UIImage *image = [[UIImage alloc] initWithContentsOfFile:filePath];
+    [self setImageRounded:image forState:UIControlStateNormal];
+    [image release];
+}
+
+-(void) removeIndicator {
+    UIActivityIndicatorView *indicator = (UIActivityIndicatorView *)[self viewWithTag:INDICATOR_TAG];
+    if (indicator) {
+        [indicator stopAnimating];
+        [indicator removeFromSuperview];
+    }
+}
+
+#pragma mark -
+#pragma mark delegate
+-(void) turnOnWidgets {
+    [self.delegate turnOnWidgets];
+}
+
+-(void) setLabelText:(NSString *)string {
+    [self.delegate setLabelText:string];
+}
+
+-(NSDictionary *)getDataForEngine {
+    return [self.delegate getDataForEngine];
+}
+
+@end
--- a/project_files/HedgewarsMobile/Classes/NSStringExtra.h	Sun Sep 26 19:06:59 2010 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,29 +0,0 @@
-/*
- * Hedgewars-iOS, a Hedgewars port for iOS devices
- * Copyright (c) 2009-2010 Vittorio Giovara <vittorio.giovara@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * File created on 21/09/2010.
- */
-
-
-#import <UIKit/UIKit.h>
-
-@interface NSString (extra)
-
--(BOOL) appendToFile:(NSString *)path;
--(BOOL) appendToFile:(NSString *)path usingEncoding:(NSStringEncoding) encoding;
-
-@end
--- a/project_files/HedgewarsMobile/Classes/NSStringExtra.m	Sun Sep 26 19:06:59 2010 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
-/*
- * Hedgewars-iOS, a Hedgewars port for iOS devices
- * Copyright (c) 2009-2010 Vittorio Giovara <vittorio.giovara@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * File created on 21/09/2010.
- */
-
-
-#import "NSStringExtra.h"
-
-@implementation NSString (extra)
-
--(BOOL) appendToFile:(NSString *)path {
-    NSOutputStream* os = [[NSOutputStream alloc] initToFileAtPath:path append:YES];
-    NSData *allData = [self dataUsingEncoding:NSUTF8StringEncoding];
-
-    [os open];
-    [os write:[allData bytes] maxLength:[allData length]];
-    [os close];
-    
-    [os release];
-    return YES;
-}
-
--(BOOL) appendToFile:(NSString *)path usingStream:(NSOutputStream *)os {
-    NSData *allData = [self dataUsingEncoding:NSUTF8StringEncoding];
-    [os write:[allData bytes] maxLength:[allData length]];
-    return YES;
-}
-
-// by http://iphonedevelopment.blogspot.com/2010/08/nsstring-appendtofileusingencoding.html
--(BOOL) appendToFile:(NSString *)path usingEncoding:(NSStringEncoding) encoding {
-    NSFileHandle *fh = [NSFileHandle fileHandleForWritingAtPath:path]; 
-    if (fh == nil)
-        return [self writeToFile:path atomically:YES encoding:encoding error:nil];
-    
-    [fh truncateFileAtOffset:[fh seekToEndOfFile]];
-    NSData *encoded = [self dataUsingEncoding:encoding];
-    
-    if (encoded == nil) 
-        return NO;
-    
-    [fh writeData:encoded];
-    return YES;
-}
-
-@end
--- a/project_files/HedgewarsMobile/Classes/SDL_uikitappdelegate.h	Sun Sep 26 19:06:59 2010 -0400
+++ b/project_files/HedgewarsMobile/Classes/SDL_uikitappdelegate.h	Mon Sep 27 04:58:26 2010 +0200
@@ -35,7 +35,7 @@
 
 +(SDLUIKitDelegate *)sharedAppDelegate;
 -(void) startSDLgame:(NSDictionary *)gameDictionary;
--(void) displayOverlayLater;
+-(void) displayOverlayLater:(NSNumber *)isNetGame ;
 
 @end
 
--- a/project_files/HedgewarsMobile/Classes/UIImageExtra.h	Sun Sep 26 19:06:59 2010 -0400
+++ b/project_files/HedgewarsMobile/Classes/UIImageExtra.h	Mon Sep 27 04:58:26 2010 +0200
@@ -33,5 +33,6 @@
 -(UIImage *)convertToNegative;
 -(UIImage *)maskImageWith:(UIImage *)maskImage;
 -(UIImage *)makeRoundCornersOfSize:(CGSize) sizewh;
++(UIImage *)whiteImage:(CGSize) ofSize;
 
 @end
--- a/project_files/HedgewarsMobile/Classes/UIImageExtra.m	Sun Sep 26 19:06:59 2010 -0400
+++ b/project_files/HedgewarsMobile/Classes/UIImageExtra.m	Mon Sep 27 04:58:26 2010 +0200
@@ -220,4 +220,19 @@
     return result;
 }
 
++(UIImage *)whiteImage:(CGSize) ofSize {
+    // white rounded rectangle as background image for previewButton
+    UIGraphicsBeginImageContext(ofSize);
+    CGContextRef context = UIGraphicsGetCurrentContext();
+    UIGraphicsPushContext(context);
+
+    CGContextSetRGBFillColor(context, 1.0, 1.0, 1.0, 1.0);
+    CGContextFillRect(context,CGRectMake(0,0,ofSize.width,ofSize.height));
+
+    UIGraphicsPopContext();
+    UIImage *bkgImg = UIGraphicsGetImageFromCurrentImageContext();
+    UIGraphicsEndImageContext();
+    return bkgImg;
+}
+
 @end
--- a/project_files/HedgewarsMobile/Hedgewars.xcodeproj/project.pbxproj	Sun Sep 26 19:06:59 2010 -0400
+++ b/project_files/HedgewarsMobile/Hedgewars.xcodeproj/project.pbxproj	Mon Sep 27 04:58:26 2010 +0200
@@ -25,7 +25,6 @@
 		1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; settings = {ATTRIBUTES = (Weak, ); }; };
 		28FD15000DC6FC520079059D /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 28FD14FF0DC6FC520079059D /* OpenGLES.framework */; };
 		28FD15080DC6FC5B0079059D /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 28FD15070DC6FC5B0079059D /* QuartzCore.framework */; settings = {ATTRIBUTES = (Required, ); }; };
-		611D9B12124949D000008271 /* NSStringExtra.m in Sources */ = {isa = PBXBuildFile; fileRef = 611D9B11124949D000008271 /* NSStringExtra.m */; };
 		611D9BFB12497E9800008271 /* SavedGamesViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 611D9BF912497E9800008271 /* SavedGamesViewController.m */; };
 		611D9BFC12497E9800008271 /* SavedGamesViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 611D9BFA12497E9800008271 /* SavedGamesViewController.xib */; };
 		611DA031124E2BC500008271 /* background_med.png in Resources */ = {isa = PBXBuildFile; fileRef = 611DA030124E2BC500008271 /* background_med.png */; };
@@ -138,6 +137,7 @@
 		6199E86D12464A8E00DADF8C /* surpise.png in Resources */ = {isa = PBXBuildFile; fileRef = 6199E86C12464A8E00DADF8C /* surpise.png */; };
 		619C5ACF124F7DE200D041AE /* libLua.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 619C5ACE124F7DDF00D041AE /* libLua.a */; };
 		619C5AF4124F7E3100D041AE /* LuaPas.pas in Sources */ = {isa = PBXBuildFile; fileRef = 619C5AF3124F7E3100D041AE /* LuaPas.pas */; };
+		619C5BA2124FA59000D041AE /* MapPreviewButtonView.m in Sources */ = {isa = PBXBuildFile; fileRef = 619C5BA1124FA59000D041AE /* MapPreviewButtonView.m */; };
 		61A1188511683A8C00359010 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 61A117FE1168322700359010 /* CoreGraphics.framework */; settings = {ATTRIBUTES = (Required, ); }; };
 		61A118D311683CD100359010 /* HedgewarsTitle.png in Resources */ = {isa = PBXBuildFile; fileRef = 611FD9CB1155A28C00C2203D /* HedgewarsTitle.png */; };
 		61B3D71C11EA6F2700EC7420 /* uKeys.pas in Sources */ = {isa = PBXBuildFile; fileRef = 617987FE114AA34C00BA94A9 /* uKeys.pas */; };
@@ -687,21 +687,21 @@
 			isa = PBXContainerItemProxy;
 			containerPortal = 619C5AC0124F7DDF00D041AE /* Lua.xcodeproj */;
 			proxyType = 2;
-			remoteGlobalIDString = 1D6058910D05DD3D006BFB54 /* Lua.app */;
+			remoteGlobalIDString = 1D6058910D05DD3D006BFB54;
 			remoteInfo = "Test Lua";
 		};
 		619C5ACB124F7DDF00D041AE /* PBXContainerItemProxy */ = {
 			isa = PBXContainerItemProxy;
 			containerPortal = 619C5AC0124F7DDF00D041AE /* Lua.xcodeproj */;
 			proxyType = 2;
-			remoteGlobalIDString = 506EE05E10304ED200A389B3 /* libcocos2d libraries.a */;
+			remoteGlobalIDString = 506EE05E10304ED200A389B3;
 			remoteInfo = "cocos2d libraries";
 		};
 		619C5ACD124F7DDF00D041AE /* PBXContainerItemProxy */ = {
 			isa = PBXContainerItemProxy;
 			containerPortal = 619C5AC0124F7DDF00D041AE /* Lua.xcodeproj */;
 			proxyType = 2;
-			remoteGlobalIDString = E14CF7C110ABC177005470B6 /* libLua.a */;
+			remoteGlobalIDString = E14CF7C110ABC177005470B6;
 			remoteInfo = Lua;
 		};
 		928301590F10E41300CC5A3C /* PBXContainerItemProxy */ = {
@@ -720,8 +720,6 @@
 		28FD14FF0DC6FC520079059D /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = System/Library/Frameworks/OpenGLES.framework; sourceTree = SDKROOT; };
 		28FD15070DC6FC5B0079059D /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
 		32CA4F630368D1EE00C91783 /* Hedgewars_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Hedgewars_Prefix.pch; sourceTree = "<group>"; };
-		611D9B10124949D000008271 /* NSStringExtra.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NSStringExtra.h; path = Classes/NSStringExtra.h; sourceTree = "<group>"; };
-		611D9B11124949D000008271 /* NSStringExtra.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = NSStringExtra.m; path = Classes/NSStringExtra.m; sourceTree = "<group>"; };
 		611D9BF812497E9800008271 /* SavedGamesViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SavedGamesViewController.h; sourceTree = "<group>"; };
 		611D9BF912497E9800008271 /* SavedGamesViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SavedGamesViewController.m; sourceTree = "<group>"; };
 		611D9BFA12497E9800008271 /* SavedGamesViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = SavedGamesViewController.xib; sourceTree = "<group>"; };
@@ -878,6 +876,8 @@
 		619C09E911E8B8D600F1DF16 /* title_small.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = title_small.png; path = "Resources/Frontend-iPhone/title_small.png"; sourceTree = "<group>"; };
 		619C5AC0124F7DDF00D041AE /* Lua.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Lua.xcodeproj; path = ../../../Library/Lua/Lua.xcodeproj; sourceTree = SOURCE_ROOT; };
 		619C5AF3124F7E3100D041AE /* LuaPas.pas */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.pascal; name = LuaPas.pas; path = ../../hedgewars/LuaPas.pas; sourceTree = SOURCE_ROOT; };
+		619C5BA0124FA59000D041AE /* MapPreviewButtonView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MapPreviewButtonView.h; path = Classes/MapPreviewButtonView.h; sourceTree = "<group>"; };
+		619C5BA1124FA59000D041AE /* MapPreviewButtonView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MapPreviewButtonView.m; path = Classes/MapPreviewButtonView.m; sourceTree = "<group>"; };
 		61A117FE1168322700359010 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
 		61C079E211F35A300072BF46 /* EditableCellView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EditableCellView.h; sourceTree = "<group>"; };
 		61C079E311F35A300072BF46 /* EditableCellView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EditableCellView.m; sourceTree = "<group>"; };
@@ -1011,8 +1011,8 @@
 				6165922B11CA9BD500D6E256 /* SquareButtonView.m */,
 				6165922C11CA9BD500D6E256 /* UIImageExtra.h */,
 				6165922D11CA9BD500D6E256 /* UIImageExtra.m */,
-				611D9B10124949D000008271 /* NSStringExtra.h */,
-				611D9B11124949D000008271 /* NSStringExtra.m */,
+				619C5BA0124FA59000D041AE /* MapPreviewButtonView.h */,
+				619C5BA1124FA59000D041AE /* MapPreviewButtonView.m */,
 			);
 			name = "Other Sources";
 			sourceTree = "<group>";
@@ -2139,7 +2139,7 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
-			shellScript = "#copy new stuff over old stuff\nrm -rf ${PROJECT_DIR}/Data\ncp -R ${PROJECT_DIR}/../../share/hedgewars/Data ${PROJECT_DIR}/Data\n\n#copy some files from QTfrontend/res\nmkdir ${PROJECT_DIR}/Data/Graphics/Btn\ncp ${PROJECT_DIR}/../../QTfrontend/res/btn*.png ${PROJECT_DIR}/Data/Graphics/Btn\ncp ${PROJECT_DIR}/../../QTfrontend/res/ammopic.png ${PROJECT_DIR}/Data/Graphics/Btn/iconAmmo.png\ncp ${PROJECT_DIR}/../../QTfrontend/res/icon*.png ${PROJECT_DIR}/Data/Graphics/Btn\ncp -R ${PROJECT_DIR}/../../QTfrontend/res/botlevels ${PROJECT_DIR}/Data/Graphics/Hedgehog/botlevels\n\n#delete all CMakeLists.txt and image source files\nfind ${PROJECT_DIR}/Data -name CMakeLists.txt -delete\nfind ${PROJECT_DIR}/Data -name *.svg -delete\nfind ${PROJECT_DIR}/Data -name *.sifz -delete\nfind ${PROJECT_DIR}/Data -name *.xcf -delete\n\n#delete desktop frontend translation\nrm -rf ${PROJECT_DIR}/Data/Locale/hedgewars_*\n\n#delete dummy maps and hats\nrm -rf ${PROJECT_DIR}/Data/Maps/{test*,Ruler}\nrm -rf ${PROJECT_DIR}/Data/Hats/{TeamCap,TeamHeadband,TeamHair}\n\ncp -R ${PROJECT_DIR}/audio/* ${PROJECT_DIR}/Data/\n\n#the following ones must be removed when their support is implemented\nrm -rf ${PROJECT_DIR}/Data/Maps/{Cheese,FlightJoust}\n\n#move Lua maps in Missions\nmkdir ${PROJECT_DIR}/Data/Missions/Maps/\nmv ${PROJECT_DIR}/Data/Maps/{Basketball,Knockball} ${PROJECT_DIR}/Data/Missions/Maps/\n\n#reduce the number of flakes for City\nawk '{if ($1 == 1500) $1=40; print $0}' < ${PROJECT_DIR}/Data/Themes/City/theme.cfg > /tmp/tempfile\nmv /tmp/tempfile ${PROJECT_DIR}/Data/Themes/City/theme.cfg\n\n#remove Isalnd from the list of Themes\nawk '{if ($1 != \"Island\") print $0}' < ${PROJECT_DIR}/Data/Themes/themes.cfg > /tmp/tempfile && mv /tmp/tempfile ${PROJECT_DIR}/Data/Themes/themes.cfg\n\n#remove Isalnd from the Maps and themes\nrm -rf ${PROJECT_DIR}/Data/Themes/Island\nawk '{if ($1 == \"Island\") print \"Nature\"}' < ${PROJECT_DIR}/Data/Maps/Cave/map.cfg > /tmp/tempfile && mv /tmp/tempfile ${PROJECT_DIR}/Data/Maps/Cave/map.cfg\nawk '{if ($1 == \"Island\") print \"Nature\"}' < ${PROJECT_DIR}/Data/Maps/Lonely_Island/map.cfg > /tmp/tempfile && mv /tmp/tempfile ${PROJECT_DIR}/Data/Maps/Lonely_Island/map.cfg\nawk '{if ($1 == \"Island\") print \"Nature\"}' < ${PROJECT_DIR}/Data/Maps/PirateFlag/map.cfg > /tmp/tempfile && mv /tmp/tempfile ${PROJECT_DIR}/Data/Maps/PirateFlag/map.cfg\n\n#delete the Classic voice\nrm -rf ${PROJECT_DIR}/Data/Sounds/voices/Classic\n\n#delete useless fonts\nrm -rf ${PROJECT_DIR}/Data/Fonts/{wqy-zenhei.ttc,DroidSansFallback.ttf}\n\n#delete all names, reserved hats\nrm -rf ${PROJECT_DIR}/Data/Names/\nrm -rf ${PROJECT_DIR}/Data/Graphics/Hats/Reserved/\n";
+			shellScript = "#copy new stuff over old stuff\nrm -rf ${PROJECT_DIR}/Data\ncp -R ${PROJECT_DIR}/../../share/hedgewars/Data ${PROJECT_DIR}/Data\n\n#copy some files from QTfrontend/res\nmkdir ${PROJECT_DIR}/Data/Graphics/Btn\ncp ${PROJECT_DIR}/../../QTfrontend/res/btn*.png ${PROJECT_DIR}/Data/Graphics/Btn\ncp ${PROJECT_DIR}/../../QTfrontend/res/ammopic.png ${PROJECT_DIR}/Data/Graphics/Btn/iconAmmo.png\ncp ${PROJECT_DIR}/../../QTfrontend/res/icon*.png ${PROJECT_DIR}/Data/Graphics/Btn\ncp -R ${PROJECT_DIR}/../../QTfrontend/res/botlevels ${PROJECT_DIR}/Data/Graphics/Hedgehog/botlevels\n\n#delete all CMakeLists.txt and image source files\nfind ${PROJECT_DIR}/Data -name CMakeLists.txt -delete\nfind ${PROJECT_DIR}/Data -name *.svg -delete\nfind ${PROJECT_DIR}/Data -name *.sifz -delete\nfind ${PROJECT_DIR}/Data -name *.xcf -delete\n\n#delete desktop frontend translation\nrm -rf ${PROJECT_DIR}/Data/Locale/hedgewars_*\n\n#delete dummy maps and hats\nrm -rf ${PROJECT_DIR}/Data/Maps/{test*,Ruler}\nrm -rf ${PROJECT_DIR}/Data/Hats/{TeamCap,TeamHeadband,TeamHair}\n\n#copy mono audio\ncp -R ${PROJECT_DIR}/audio/* ${PROJECT_DIR}/Data/\n\n#the following ones must be removed when their support is implemented\nrm -rf ${PROJECT_DIR}/Data/Maps/{Cheese,FlightJoust}\n\n#move Lua maps in Missions\nmkdir ${PROJECT_DIR}/Data/Missions/Maps/\nmv ${PROJECT_DIR}/Data/Maps/{Basketball,Knockball} ${PROJECT_DIR}/Data/Missions/Maps/\n\n#reduce the number of flakes for City\nawk '{if ($1 == 1500) $1=40; print $0}' < ${PROJECT_DIR}/Data/Themes/City/theme.cfg > /tmp/tempfile\nmv /tmp/tempfile ${PROJECT_DIR}/Data/Themes/City/theme.cfg\n\n#remove Isalnd from the list of Themes\nawk '{if ($1 != \"Island\") print $0}' < ${PROJECT_DIR}/Data/Themes/themes.cfg > /tmp/tempfile && mv /tmp/tempfile ${PROJECT_DIR}/Data/Themes/themes.cfg\n\n#remove Isalnd from the Maps and themes\nrm -rf ${PROJECT_DIR}/Data/Themes/Island\nawk '{if ($1 == \"Island\") print \"Nature\"}' < ${PROJECT_DIR}/Data/Maps/Cave/map.cfg > /tmp/tempfile && mv /tmp/tempfile ${PROJECT_DIR}/Data/Maps/Cave/map.cfg\nawk '{if ($1 == \"Island\") print \"Nature\"}' < ${PROJECT_DIR}/Data/Maps/Lonely_Island/map.cfg > /tmp/tempfile && mv /tmp/tempfile ${PROJECT_DIR}/Data/Maps/Lonely_Island/map.cfg\nawk '{if ($1 == \"Island\") print \"Nature\"}' < ${PROJECT_DIR}/Data/Maps/PirateFlag/map.cfg > /tmp/tempfile && mv /tmp/tempfile ${PROJECT_DIR}/Data/Maps/PirateFlag/map.cfg\n\n#delete the Classic voice\nrm -rf ${PROJECT_DIR}/Data/Sounds/voices/Classic\n\n#delete useless fonts\nrm -rf ${PROJECT_DIR}/Data/Fonts/{wqy-zenhei.ttc,DroidSansFallback.ttf}\n\n#delete all names, reserved hats\nrm -rf ${PROJECT_DIR}/Data/Names/\nrm -rf ${PROJECT_DIR}/Data/Graphics/Hats/Reserved/\n";
 			showEnvVarsInLog = 0;
 		};
 		9283011B0F10CB2D00CC5A3C /* Build libfpc.a */ = {
@@ -2248,9 +2248,9 @@
 				61F2E7CE1205EDE0005734F7 /* AboutViewController.m in Sources */,
 				611EEAEE122B2A4D00DF6938 /* HelpPageViewController.m in Sources */,
 				6199E839124647DE00DADF8C /* SupportViewController.m in Sources */,
-				611D9B12124949D000008271 /* NSStringExtra.m in Sources */,
 				611D9BFB12497E9800008271 /* SavedGamesViewController.m in Sources */,
 				619C5AF4124F7E3100D041AE /* LuaPas.pas in Sources */,
+				619C5BA2124FA59000D041AE /* MapPreviewButtonView.m in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
--- a/project_files/HedgewarsMobile/Resources/MapConfigViewController-iPad.xib	Sun Sep 26 19:06:59 2010 -0400
+++ b/project_files/HedgewarsMobile/Resources/MapConfigViewController-iPad.xib	Mon Sep 27 04:58:26 2010 +0200
@@ -148,42 +148,47 @@
 					<object class="IBUISegmentedControl" id="88728219">
 						<reference key="NSNextResponder" ref="191373211"/>
 						<int key="NSvFlags">289</int>
-						<string key="NSFrame">{{744, 166}, {240, 30}}</string>
+						<string key="NSFrame">{{725, 166}, {277, 30}}</string>
 						<reference key="NSSuperview" ref="191373211"/>
 						<bool key="IBUIOpaque">NO</bool>
 						<string key="targetRuntimeIdentifier">IBIPadFramework</string>
 						<int key="IBSegmentControlStyle">2</int>
-						<int key="IBNumberOfSegments">3</int>
+						<int key="IBNumberOfSegments">4</int>
 						<int key="IBSelectedSegmentIndex">1</int>
 						<object class="NSArray" key="IBSegmentTitles">
 							<bool key="EncodedWithXMLCoder">YES</bool>
 							<string>Random</string>
 							<string>Map</string>
 							<string>Maze</string>
+							<string>Mission</string>
 						</object>
 						<object class="NSMutableArray" key="IBSegmentWidths">
 							<bool key="EncodedWithXMLCoder">YES</bool>
 							<real value="0.0"/>
 							<real value="0.0"/>
 							<real value="0.0"/>
+							<real value="0.0"/>
 						</object>
 						<object class="NSMutableArray" key="IBSegmentEnabledStates">
 							<bool key="EncodedWithXMLCoder">YES</bool>
 							<boolean value="YES"/>
 							<boolean value="YES"/>
 							<boolean value="YES"/>
+							<boolean value="YES"/>
 						</object>
 						<object class="NSMutableArray" key="IBSegmentContentOffsets">
 							<bool key="EncodedWithXMLCoder">YES</bool>
 							<string>{0, 0}</string>
 							<string>{0, 0}</string>
 							<string>{0, 0}</string>
+							<string>{0, 0}</string>
 						</object>
 						<object class="NSMutableArray" key="IBSegmentImages">
 							<bool key="EncodedWithXMLCoder">YES</bool>
 							<object class="NSNull" id="4"/>
 							<reference ref="4"/>
 							<reference ref="4"/>
+							<reference ref="4"/>
 						</object>
 						<object class="NSColor" key="IBTintColor">
 							<int key="NSColorSpace">1</int>
@@ -565,6 +570,14 @@
 					</object>
 					<int key="connectionID">113</int>
 				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBCocoaTouchOutletConnection" key="connection">
+						<string key="label">delegate</string>
+						<reference key="source" ref="326163764"/>
+						<reference key="destination" ref="372490531"/>
+					</object>
+					<int key="connectionID">114</int>
+				</object>
 			</object>
 			<object class="IBMutableOrderedSet" key="objectRecords">
 				<object class="NSArray" key="orderedObjects">
@@ -602,7 +615,6 @@
 							<reference ref="634417433"/>
 							<reference ref="326163764"/>
 							<reference ref="938256702"/>
-							<reference ref="88728219"/>
 							<reference ref="848132519"/>
 							<reference ref="696928530"/>
 							<reference ref="742028380"/>
@@ -611,6 +623,7 @@
 							<reference ref="867832822"/>
 							<reference ref="553937568"/>
 							<reference ref="420136851"/>
+							<reference ref="88728219"/>
 						</object>
 						<reference key="parent" ref="0"/>
 					</object>
@@ -743,13 +756,14 @@
 					<string>79.IBPluginDependency</string>
 					<string>8.IBPluginDependency</string>
 					<string>80.IBPluginDependency</string>
+					<string>9.CustomClassName</string>
 					<string>9.IBPluginDependency</string>
 				</object>
 				<object class="NSMutableArray" key="dict.values">
 					<bool key="EncodedWithXMLCoder">YES</bool>
 					<string>MapConfigViewController</string>
 					<string>UIResponder</string>
-					<string>{{288, 290}, {1024, 768}}</string>
+					<string>{{205, 295}, {1024, 768}}</string>
 					<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
 					<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
 					<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
@@ -770,6 +784,7 @@
 					<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
 					<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
 					<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+					<string>MapPreviewButtonView</string>
 					<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
 				</object>
 			</object>
@@ -789,7 +804,7 @@
 				</object>
 			</object>
 			<nil key="sourceID"/>
-			<int key="maxID">113</int>
+			<int key="maxID">114</int>
 		</object>
 		<object class="IBClassDescriber" key="IBDocument.Classes">
 			<object class="NSMutableArray" key="referencedPartialClassDescriptions">
@@ -866,7 +881,7 @@
 							<bool key="EncodedWithXMLCoder">YES</bool>
 							<string>id</string>
 							<string>UILabel</string>
-							<string>UIButton</string>
+							<string>MapPreviewButtonView</string>
 							<string>UISegmentedControl</string>
 							<string>UILabel</string>
 							<string>UISlider</string>
@@ -897,7 +912,7 @@
 							</object>
 							<object class="IBToOneOutletInfo">
 								<string key="name">previewButton</string>
-								<string key="candidateClassName">UIButton</string>
+								<string key="candidateClassName">MapPreviewButtonView</string>
 							</object>
 							<object class="IBToOneOutletInfo">
 								<string key="name">segmentedControl</string>
@@ -922,6 +937,25 @@
 						<string key="minorKey">Classes/MapConfigViewController.h</string>
 					</object>
 				</object>
+				<object class="IBPartialClassDescription">
+					<string key="className">MapPreviewButtonView</string>
+					<string key="superclassName">UIButton</string>
+					<object class="NSMutableDictionary" key="outlets">
+						<string key="NS.key.0">delegate</string>
+						<string key="NS.object.0">id</string>
+					</object>
+					<object class="NSMutableDictionary" key="toOneOutletInfosByName">
+						<string key="NS.key.0">delegate</string>
+						<object class="IBToOneOutletInfo" key="NS.object.0">
+							<string key="name">delegate</string>
+							<string key="candidateClassName">id</string>
+						</object>
+					</object>
+					<object class="IBClassDescriptionSource" key="sourceIdentifier">
+						<string key="majorKey">IBProjectSource</string>
+						<string key="minorKey">Classes/MapPreviewButtonView.h</string>
+					</object>
+				</object>
 			</object>
 			<object class="NSMutableArray" key="referencedPartialClassDescriptionsV3.2+">
 				<bool key="EncodedWithXMLCoder">YES</bool>
--- a/project_files/HedgewarsMobile/Resources/MapConfigViewController-iPhone.xib	Sun Sep 26 19:06:59 2010 -0400
+++ b/project_files/HedgewarsMobile/Resources/MapConfigViewController-iPhone.xib	Mon Sep 27 04:58:26 2010 +0200
@@ -45,42 +45,47 @@
 					<object class="IBUISegmentedControl" id="88728219">
 						<reference key="NSNextResponder" ref="191373211"/>
 						<int key="NSvFlags">292</int>
-						<string key="NSFrame">{{28, 166}, {240, 30}}</string>
+						<string key="NSFrame">{{20, 166}, {256, 30}}</string>
 						<reference key="NSSuperview" ref="191373211"/>
 						<bool key="IBUIOpaque">NO</bool>
 						<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
 						<int key="IBSegmentControlStyle">2</int>
-						<int key="IBNumberOfSegments">3</int>
+						<int key="IBNumberOfSegments">4</int>
 						<int key="IBSelectedSegmentIndex">0</int>
 						<object class="NSArray" key="IBSegmentTitles">
 							<bool key="EncodedWithXMLCoder">YES</bool>
 							<string>Random</string>
 							<string>Map</string>
 							<string>Maze</string>
+							<string>Mission</string>
 						</object>
 						<object class="NSMutableArray" key="IBSegmentWidths">
 							<bool key="EncodedWithXMLCoder">YES</bool>
 							<real value="0.0"/>
 							<real value="0.0"/>
 							<real value="0.0"/>
+							<real value="0.0"/>
 						</object>
 						<object class="NSMutableArray" key="IBSegmentEnabledStates">
 							<bool key="EncodedWithXMLCoder">YES</bool>
 							<boolean value="YES"/>
 							<boolean value="YES"/>
 							<boolean value="YES"/>
+							<boolean value="YES"/>
 						</object>
 						<object class="NSMutableArray" key="IBSegmentContentOffsets">
 							<bool key="EncodedWithXMLCoder">YES</bool>
 							<string>{0, 0}</string>
 							<string>{0, 0}</string>
 							<string>{0, 0}</string>
+							<string>{0, 0}</string>
 						</object>
 						<object class="NSMutableArray" key="IBSegmentImages">
 							<bool key="EncodedWithXMLCoder">YES</bool>
 							<object class="NSNull" id="4"/>
 							<reference ref="4"/>
 							<reference ref="4"/>
+							<reference ref="4"/>
 						</object>
 					</object>
 					<object class="IBUISlider" id="938256702">
@@ -302,6 +307,14 @@
 					</object>
 					<int key="connectionID">33</int>
 				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBCocoaTouchOutletConnection" key="connection">
+						<string key="label">delegate</string>
+						<reference key="source" ref="326163764"/>
+						<reference key="destination" ref="372490531"/>
+					</object>
+					<int key="connectionID">34</int>
+				</object>
 			</object>
 			<object class="IBMutableOrderedSet" key="objectRecords">
 				<object class="NSArray" key="orderedObjects">
@@ -319,10 +332,10 @@
 							<bool key="EncodedWithXMLCoder">YES</bool>
 							<reference ref="326163764"/>
 							<reference ref="634417433"/>
-							<reference ref="88728219"/>
 							<reference ref="565214171"/>
 							<reference ref="743202682"/>
 							<reference ref="938256702"/>
+							<reference ref="88728219"/>
 						</object>
 						<reference key="parent" ref="0"/>
 					</object>
@@ -383,6 +396,7 @@
 					<string>25.IBPluginDependency</string>
 					<string>7.IBPluginDependency</string>
 					<string>8.IBPluginDependency</string>
+					<string>9.CustomClassName</string>
 					<string>9.IBPluginDependency</string>
 				</object>
 				<object class="NSMutableArray" key="dict.values">
@@ -396,6 +410,7 @@
 					<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
 					<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
 					<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+					<string>MapPreviewButtonView</string>
 					<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
 				</object>
 			</object>
@@ -415,7 +430,7 @@
 				</object>
 			</object>
 			<nil key="sourceID"/>
-			<int key="maxID">33</int>
+			<int key="maxID">34</int>
 		</object>
 		<object class="IBClassDescriber" key="IBDocument.Classes">
 			<object class="NSMutableArray" key="referencedPartialClassDescriptions">
@@ -492,7 +507,7 @@
 							<bool key="EncodedWithXMLCoder">YES</bool>
 							<string>id</string>
 							<string>UILabel</string>
-							<string>UIButton</string>
+							<string>MapPreviewButtonView</string>
 							<string>UISegmentedControl</string>
 							<string>UILabel</string>
 							<string>UISlider</string>
@@ -523,7 +538,7 @@
 							</object>
 							<object class="IBToOneOutletInfo">
 								<string key="name">previewButton</string>
-								<string key="candidateClassName">UIButton</string>
+								<string key="candidateClassName">MapPreviewButtonView</string>
 							</object>
 							<object class="IBToOneOutletInfo">
 								<string key="name">segmentedControl</string>
@@ -548,6 +563,25 @@
 						<string key="minorKey">Classes/MapConfigViewController.h</string>
 					</object>
 				</object>
+				<object class="IBPartialClassDescription">
+					<string key="className">MapPreviewButtonView</string>
+					<string key="superclassName">UIButton</string>
+					<object class="NSMutableDictionary" key="outlets">
+						<string key="NS.key.0">delegate</string>
+						<string key="NS.object.0">id</string>
+					</object>
+					<object class="NSMutableDictionary" key="toOneOutletInfosByName">
+						<string key="NS.key.0">delegate</string>
+						<object class="IBToOneOutletInfo" key="NS.object.0">
+							<string key="name">delegate</string>
+							<string key="candidateClassName">id</string>
+						</object>
+					</object>
+					<object class="IBClassDescriptionSource" key="sourceIdentifier">
+						<string key="majorKey">IBProjectSource</string>
+						<string key="minorKey">Classes/MapPreviewButtonView.h</string>
+					</object>
+				</object>
 			</object>
 			<object class="NSMutableArray" key="referencedPartialClassDescriptionsV3.2+">
 				<bool key="EncodedWithXMLCoder">YES</bool>