src/video/uikit/SDL_uikitview.m
author Alex Szpakowski <slime73@gmail.com>
Wed, 23 Jul 2014 01:28:24 -0300
branchiOS-improvements
changeset 9499 6fe9b44b2d84
parent 9488 f15520430c94
child 9501 574db299498f
permissions -rw-r--r--
Updated the iOS Objective-C code to use NSDictionary/NSArray/NSNumber literals and subscripting, for improved code clarity.

This requires at least Xcode 4.5 and the iOS 6 SDK to build, but it doesn't change the minimum supported runtime version (iOS 5.1). Less than 2% of iOS users are running iOS 5, so I hope developers aren't trying to build SDL using an SDK which doesn't support iOS 6/7...
slouken@6079
     1
 /*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@8149
     3
  Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
slouken@5262
     4
slouken@5535
     5
  This software is provided 'as-is', without any express or implied
slouken@5535
     6
  warranty.  In no event will the authors be held liable for any damages
slouken@5535
     7
  arising from the use of this software.
slouken@5262
     8
slouken@5535
     9
  Permission is granted to anyone to use this software for any purpose,
slouken@5535
    10
  including commercial applications, and to alter it and redistribute it
slouken@5535
    11
  freely, subject to the following restrictions:
slouken@5262
    12
slouken@5535
    13
  1. The origin of this software must not be misrepresented; you must not
slouken@5535
    14
     claim that you wrote the original software. If you use this software
slouken@5535
    15
     in a product, an acknowledgment in the product documentation would be
slouken@5535
    16
     appreciated but is not required.
slouken@5535
    17
  2. Altered source versions must be plainly marked as such, and must not be
slouken@5535
    18
     misrepresented as being the original software.
slouken@5535
    19
  3. This notice may not be removed or altered from any source distribution.
slouken@5262
    20
*/
icculus@8093
    21
#include "../../SDL_internal.h"
slouken@6044
    22
slouken@6044
    23
#if SDL_VIDEO_DRIVER_UIKIT
slouken@2765
    24
slouken@6518
    25
#include "SDL_uikitview.h"
slouken@2765
    26
slouken@4490
    27
#include "../../events/SDL_keyboard_c.h"
slouken@4490
    28
#include "../../events/SDL_mouse_c.h"
jimtla@4677
    29
#include "../../events/SDL_touch_c.h"
slouken@4490
    30
slouken@2765
    31
#if SDL_IPHONE_KEYBOARD
slouken@6518
    32
#include "keyinfotable.h"
urkle@7111
    33
#endif
slouken@6518
    34
#include "SDL_uikitappdelegate.h"
slouken@6518
    35
#include "SDL_uikitmodes.h"
slouken@6518
    36
#include "SDL_uikitwindow.h"
slouken@2765
    37
slime73@9487
    38
void _uikit_keyboard_init();
slouken@7962
    39
slouken@2765
    40
@implementation SDL_uikitview
slouken@2765
    41
kees@6003
    42
- (void)dealloc
kees@6003
    43
{
slouken@5131
    44
    [super dealloc];
slouken@2765
    45
}
slouken@2765
    46
kees@6003
    47
- (id)initWithFrame:(CGRect)frame
kees@6003
    48
{
slouken@5131
    49
    self = [super initWithFrame: frame];
kees@6001
    50
slouken@2765
    51
#if SDL_IPHONE_KEYBOARD
slouken@5131
    52
    [self initializeKeyboard];
kees@6001
    53
#endif
slouken@2765
    54
slouken@5445
    55
    self.multipleTouchEnabled = YES;
slouken@5445
    56
slouken@6951
    57
    touchId = 1;
slouken@6951
    58
    SDL_AddTouch(touchId, "");
slouken@4661
    59
slouken@5131
    60
    return self;
slouken@2765
    61
slouken@2765
    62
}
slouken@2765
    63
slouken@6436
    64
- (CGPoint)touchLocation:(UITouch *)touch shouldNormalize:(BOOL)normalize
slouken@6079
    65
{
slouken@6079
    66
    CGPoint point = [touch locationInView: self];
slouken@6436
    67
slouken@6436
    68
    if (normalize) {
slouken@6439
    69
        CGRect bounds = [self bounds];
slouken@6439
    70
        point.x /= bounds.size.width;
slouken@6439
    71
        point.y /= bounds.size.height;
slouken@6436
    72
    }
slime73@9488
    73
slouken@6079
    74
    return point;
slouken@6079
    75
}
slouken@6079
    76
kees@6003
    77
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
kees@6003
    78
{
slime73@9487
    79
    for (UITouch *touch in touches) {
slouken@6597
    80
        if (!leftFingerDown) {
slouken@6597
    81
            CGPoint locationInView = [self touchLocation:touch shouldNormalize:NO];
kees@6001
    82
slouken@6597
    83
            /* send moved event */
slime73@9487
    84
            SDL_SendMouseMotion(viewcontroller.window, SDL_TOUCH_MOUSEID, 0, locationInView.x, locationInView.y);
slouken@4488
    85
slouken@6597
    86
            /* send mouse down event */
slime73@9487
    87
            SDL_SendMouseButton(viewcontroller.window, SDL_TOUCH_MOUSEID, SDL_PRESSED, SDL_BUTTON_LEFT);
jim@4660
    88
icculus@7050
    89
            leftFingerDown = touch;
slouken@6597
    90
        }
slouken@6597
    91
slouken@6436
    92
        CGPoint locationInView = [self touchLocation:touch shouldNormalize:YES];
jim@4662
    93
#ifdef IPHONE_TOUCH_EFFICIENT_DANGEROUS
slouken@7191
    94
        /* FIXME: TODO: Using touch as the fingerId is potentially dangerous
slouken@7191
    95
         * It is also much more efficient than storing the UITouch pointer
slouken@7191
    96
         * and comparing it to the incoming event.
slouken@7191
    97
         */
icculus@7050
    98
        SDL_SendTouch(touchId, (SDL_FingerID)((size_t)touch),
slouken@6951
    99
                      SDL_TRUE, locationInView.x, locationInView.y, 1.0f);
jim@4662
   100
#else
kees@6003
   101
        int i;
kees@6003
   102
        for(i = 0; i < MAX_SIMULTANEOUS_TOUCHES; i++) {
kees@6003
   103
            if (finger[i] == NULL) {
kees@6003
   104
                finger[i] = touch;
slouken@6951
   105
                SDL_SendTouch(touchId, i,
slouken@6951
   106
                              SDL_TRUE, locationInView.x, locationInView.y, 1.0f);
kees@6003
   107
                break;
kees@6003
   108
            }
slouken@5131
   109
        }
jim@4662
   110
#endif
slouken@5131
   111
    }
slouken@2765
   112
}
slouken@2765
   113
kees@6003
   114
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
kees@6003
   115
{
slime73@9487
   116
    for (UITouch *touch in touches) {
icculus@7050
   117
        if (touch == leftFingerDown) {
slouken@6597
   118
            /* send mouse up */
slime73@9487
   119
            SDL_SendMouseButton(viewcontroller.window, SDL_TOUCH_MOUSEID, SDL_RELEASED, SDL_BUTTON_LEFT);
icculus@7050
   120
            leftFingerDown = nil;
slouken@6597
   121
        }
slouken@4661
   122
slouken@6436
   123
        CGPoint locationInView = [self touchLocation:touch shouldNormalize:YES];
jim@4662
   124
#ifdef IPHONE_TOUCH_EFFICIENT_DANGEROUS
slouken@6951
   125
        SDL_SendTouch(touchId, (long)touch,
slouken@6951
   126
                      SDL_FALSE, locationInView.x, locationInView.y, 1.0f);
jim@4662
   127
#else
kees@6003
   128
        int i;
kees@6003
   129
        for (i = 0; i < MAX_SIMULTANEOUS_TOUCHES; i++) {
kees@6003
   130
            if (finger[i] == touch) {
slouken@6951
   131
                SDL_SendTouch(touchId, i,
slouken@6951
   132
                              SDL_FALSE, locationInView.x, locationInView.y, 1.0f);
kees@6003
   133
                finger[i] = NULL;
kees@6003
   134
                break;
kees@6003
   135
            }
slouken@5131
   136
        }
jim@4662
   137
#endif
slouken@5131
   138
    }
slouken@2765
   139
}
slouken@2765
   140
kees@6003
   141
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
kees@6003
   142
{
slouken@5131
   143
    /*
slouken@5131
   144
        this can happen if the user puts more than 5 touches on the screen
slouken@5131
   145
        at once, or perhaps in other circumstances.  Usually (it seems)
slouken@5131
   146
        all active touches are canceled.
slouken@5131
   147
    */
slouken@5131
   148
    [self touchesEnded: touches withEvent: event];
slouken@2765
   149
}
slouken@2765
   150
kees@6003
   151
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
kees@6003
   152
{
slime73@9487
   153
    for (UITouch *touch in touches) {
icculus@7050
   154
        if (touch == leftFingerDown) {
slouken@6597
   155
            CGPoint locationInView = [self touchLocation:touch shouldNormalize:NO];
slouken@4488
   156
slouken@6597
   157
            /* send moved event */
slime73@9487
   158
            SDL_SendMouseMotion(viewcontroller.window, SDL_TOUCH_MOUSEID, 0, locationInView.x, locationInView.y);
slouken@6597
   159
        }
jim@4660
   160
slouken@6436
   161
        CGPoint locationInView = [self touchLocation:touch shouldNormalize:YES];
jim@4662
   162
#ifdef IPHONE_TOUCH_EFFICIENT_DANGEROUS
kees@6003
   163
        SDL_SendTouchMotion(touchId, (long)touch,
slouken@6951
   164
                            locationInView.x, locationInView.y, 1.0f);
jim@4662
   165
#else
kees@6003
   166
        int i;
kees@6003
   167
        for (i = 0; i < MAX_SIMULTANEOUS_TOUCHES; i++) {
kees@6003
   168
            if (finger[i] == touch) {
kees@6003
   169
                SDL_SendTouchMotion(touchId, i,
slouken@6951
   170
                                    locationInView.x, locationInView.y, 1.0f);
kees@6003
   171
                break;
kees@6003
   172
            }
slouken@5131
   173
        }
jim@4662
   174
#endif
slouken@5131
   175
    }
slouken@2765
   176
}
slouken@2765
   177
slouken@2765
   178
/*
slouken@5131
   179
    ---- Keyboard related functionality below this line ----
slouken@2765
   180
*/
slouken@2765
   181
#if SDL_IPHONE_KEYBOARD
slouken@2765
   182
slouken@7962
   183
@synthesize textInputRect = textInputRect;
slouken@7962
   184
@synthesize keyboardHeight = keyboardHeight;
slouken@7962
   185
slouken@2765
   186
/* Is the iPhone virtual keyboard visible onscreen? */
kees@6003
   187
- (BOOL)keyboardVisible
kees@6003
   188
{
slouken@5131
   189
    return keyboardVisible;
slouken@2765
   190
}
slouken@2765
   191
slouken@2765
   192
/* Set ourselves up as a UITextFieldDelegate */
kees@6003
   193
- (void)initializeKeyboard
kees@6003
   194
{
slouken@5131
   195
    textField = [[UITextField alloc] initWithFrame: CGRectZero];
slouken@5131
   196
    textField.delegate = self;
slouken@5131
   197
    /* placeholder so there is something to delete! */
kees@6001
   198
    textField.text = @" ";
kees@6001
   199
slouken@5131
   200
    /* set UITextInputTrait properties, mostly to defaults */
slouken@5131
   201
    textField.autocapitalizationType = UITextAutocapitalizationTypeNone;
slouken@5131
   202
    textField.autocorrectionType = UITextAutocorrectionTypeNo;
slouken@5131
   203
    textField.enablesReturnKeyAutomatically = NO;
slouken@5131
   204
    textField.keyboardAppearance = UIKeyboardAppearanceDefault;
slouken@5131
   205
    textField.keyboardType = UIKeyboardTypeDefault;
slouken@5131
   206
    textField.returnKeyType = UIReturnKeyDefault;
kees@6001
   207
    textField.secureTextEntry = NO;
kees@6001
   208
slouken@5131
   209
    textField.hidden = YES;
slouken@5131
   210
    keyboardVisible = NO;
slouken@5131
   211
    /* add the UITextField (hidden) to our view */
slouken@5131
   212
    [self addSubview: textField];
slouken@5131
   213
    [textField release];
slouken@7962
   214
    
slouken@7962
   215
    _uikit_keyboard_init();
slouken@2765
   216
}
slouken@2765
   217
slouken@2765
   218
/* reveal onscreen virtual keyboard */
kees@6003
   219
- (void)showKeyboard
kees@6003
   220
{
slouken@5131
   221
    keyboardVisible = YES;
slouken@5131
   222
    [textField becomeFirstResponder];
slouken@2765
   223
}
slouken@2765
   224
slouken@2765
   225
/* hide onscreen virtual keyboard */
kees@6003
   226
- (void)hideKeyboard
kees@6003
   227
{
slouken@5131
   228
    keyboardVisible = NO;
slouken@5131
   229
    [textField resignFirstResponder];
slouken@2765
   230
}
slouken@2765
   231
slouken@2765
   232
/* UITextFieldDelegate method.  Invoked when user types something. */
kees@6003
   233
- (BOOL)textField:(UITextField *)_textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
kees@6003
   234
{
slouken@5131
   235
    if ([string length] == 0) {
slouken@5131
   236
        /* it wants to replace text with nothing, ie a delete */
icculus@7774
   237
        SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_BACKSPACE);
icculus@7774
   238
        SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_BACKSPACE);
slouken@5131
   239
    }
slouken@5131
   240
    else {
slouken@5131
   241
        /* go through all the characters in the string we've been sent
slouken@5131
   242
           and convert them to key presses */
slouken@5131
   243
        int i;
kees@6003
   244
        for (i = 0; i < [string length]; i++) {
kees@6001
   245
slouken@5131
   246
            unichar c = [string characterAtIndex: i];
kees@6001
   247
slouken@5131
   248
            Uint16 mod = 0;
slouken@5218
   249
            SDL_Scancode code;
kees@6001
   250
slouken@5131
   251
            if (c < 127) {
slouken@5218
   252
                /* figure out the SDL_Scancode and SDL_keymod for this unichar */
slouken@5131
   253
                code = unicharToUIKeyInfoTable[c].code;
slouken@5131
   254
                mod  = unicharToUIKeyInfoTable[c].mod;
slouken@5131
   255
            }
slouken@5131
   256
            else {
slouken@5131
   257
                /* we only deal with ASCII right now */
slouken@5131
   258
                code = SDL_SCANCODE_UNKNOWN;
slouken@5131
   259
                mod = 0;
slouken@5131
   260
            }
kees@6001
   261
slouken@5131
   262
            if (mod & KMOD_SHIFT) {
slouken@5131
   263
                /* If character uses shift, press shift down */
slouken@5131
   264
                SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_LSHIFT);
slouken@5131
   265
            }
slouken@5131
   266
            /* send a keydown and keyup even for the character */
slouken@5131
   267
            SDL_SendKeyboardKey(SDL_PRESSED, code);
slouken@5131
   268
            SDL_SendKeyboardKey(SDL_RELEASED, code);
slouken@5131
   269
            if (mod & KMOD_SHIFT) {
slouken@5131
   270
                /* If character uses shift, press shift back up */
slouken@5131
   271
                SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_LSHIFT);
kees@6001
   272
            }
slouken@5131
   273
        }
slouken@5461
   274
        SDL_SendKeyboardText([string UTF8String]);
slouken@5131
   275
    }
slouken@5131
   276
    return NO; /* don't allow the edit! (keep placeholder text there) */
slouken@2765
   277
}
slouken@2765
   278
slouken@2765
   279
/* Terminates the editing session */
kees@6003
   280
- (BOOL)textFieldShouldReturn:(UITextField*)_textField
kees@6003
   281
{
slouken@5134
   282
    SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_RETURN);
slouken@6054
   283
    SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_RETURN);
slouken@6654
   284
    SDL_StopTextInput();
slouken@5131
   285
    return YES;
slouken@2765
   286
}
slouken@2765
   287
slouken@2765
   288
#endif
slouken@2765
   289
slouken@2765
   290
@end
slouken@2765
   291
slouken@2765
   292
/* iPhone keyboard addition functions */
slouken@2765
   293
#if SDL_IPHONE_KEYBOARD
slouken@2765
   294
slouken@6044
   295
static SDL_uikitview * getWindowView(SDL_Window * window)
kees@6010
   296
{
kees@6010
   297
    if (window == NULL) {
kees@6010
   298
        SDL_SetError("Window does not exist");
kees@6010
   299
        return nil;
kees@6010
   300
    }
kees@6010
   301
kees@6010
   302
    SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
kees@6010
   303
    SDL_uikitview *view = data != NULL ? data->view : nil;
kees@6010
   304
kees@6010
   305
    if (view == nil) {
kees@6010
   306
        SDL_SetError("Window has no view");
kees@6010
   307
    }
kees@6010
   308
kees@6010
   309
    return view;
kees@6010
   310
}
kees@6010
   311
slouken@6654
   312
SDL_bool UIKit_HasScreenKeyboardSupport(_THIS)
slouken@6392
   313
{
slouken@6392
   314
    return SDL_TRUE;
slouken@6392
   315
}
slouken@6392
   316
slouken@6654
   317
void UIKit_ShowScreenKeyboard(_THIS, SDL_Window *window)
kees@6003
   318
{
kees@6010
   319
    SDL_uikitview *view = getWindowView(window);
slouken@6654
   320
    if (view != nil) {
slouken@6654
   321
        [view showKeyboard];
slouken@5131
   322
    }
slouken@2765
   323
}
slouken@2765
   324
slouken@6654
   325
void UIKit_HideScreenKeyboard(_THIS, SDL_Window *window)
kees@6003
   326
{
kees@6010
   327
    SDL_uikitview *view = getWindowView(window);
slouken@6654
   328
    if (view != nil) {
slouken@6654
   329
        [view hideKeyboard];
kees@6001
   330
    }
slouken@2765
   331
}
slouken@2765
   332
slouken@6392
   333
SDL_bool UIKit_IsScreenKeyboardShown(_THIS, SDL_Window *window)
kees@6003
   334
{
kees@6010
   335
    SDL_uikitview *view = getWindowView(window);
kees@6010
   336
    if (view == nil) {
kees@6010
   337
        return 0;
kees@6001
   338
    }
kees@6001
   339
kees@6010
   340
    return view.keyboardVisible;
slouken@2765
   341
}
slouken@2765
   342
slouken@7962
   343
slouken@7962
   344
void _uikit_keyboard_update() {
slouken@7962
   345
    SDL_Window *window = SDL_GetFocusWindow();
slouken@7962
   346
    if (!window) { return; }
slouken@7962
   347
    SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
slouken@7962
   348
    if (!data) { return; }
slouken@7962
   349
    SDL_uikitview *view = data->view;
slouken@7962
   350
    if (!view) { return; }
slouken@7962
   351
    
slouken@7962
   352
    SDL_Rect r = view.textInputRect;
slouken@7962
   353
    int height = view.keyboardHeight;
slouken@7962
   354
    int offsetx = 0;
slouken@7962
   355
    int offsety = 0;
slouken@7962
   356
    if (height) {
slouken@7962
   357
        int sw,sh;
slouken@7962
   358
        SDL_GetWindowSize(window,&sw,&sh);
slouken@7962
   359
        int bottom = (r.y + r.h);
slouken@7962
   360
        int kbottom = sh - height;
slouken@7962
   361
        if (kbottom < bottom) {
slouken@7962
   362
            offsety = kbottom-bottom;
slouken@7962
   363
        }
slouken@7962
   364
    }
slouken@7962
   365
    UIInterfaceOrientation ui_orient = [[UIApplication sharedApplication] statusBarOrientation];
slouken@7962
   366
    if (ui_orient == UIInterfaceOrientationLandscapeLeft) {
slouken@7962
   367
        int tmp = offsetx; offsetx = offsety; offsety = tmp;
slouken@7962
   368
    }
slouken@7962
   369
    if (ui_orient == UIInterfaceOrientationLandscapeRight) {
slouken@7962
   370
        offsety = -offsety;
slouken@7962
   371
        int tmp = offsetx; offsetx = offsety; offsety = tmp;
slouken@7962
   372
    }
slouken@7962
   373
    if (ui_orient == UIInterfaceOrientationPortraitUpsideDown) {
slouken@7962
   374
        offsety = -offsety;
slouken@7962
   375
    }
slouken@8891
   376
slouken@7962
   377
    view.frame = CGRectMake(offsetx,offsety,view.frame.size.width,view.frame.size.height);
slouken@7962
   378
}
slouken@7962
   379
slouken@7962
   380
void _uikit_keyboard_set_height(int height) {
slouken@7962
   381
    SDL_uikitview *view = getWindowView(SDL_GetFocusWindow());
slouken@7962
   382
    if (view == nil) {
slouken@7962
   383
        return ;
slouken@7962
   384
    }
slouken@7962
   385
    
slouken@7962
   386
    view.keyboardHeight = height;
slouken@7962
   387
    _uikit_keyboard_update();
slouken@7962
   388
}
slouken@7962
   389
slouken@7962
   390
void _uikit_keyboard_init() {
slouken@7962
   391
    NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
slouken@7962
   392
    NSOperationQueue *queue = [NSOperationQueue mainQueue];
slouken@7962
   393
    [center addObserverForName:UIKeyboardWillShowNotification
slouken@7962
   394
                        object:nil
slouken@7962
   395
                         queue:queue
slouken@7962
   396
                    usingBlock:^(NSNotification *notification) {
slouken@7962
   397
                        int height = 0;
slime73@9499
   398
                        CGSize keyboardSize = [[notification userInfo][UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
slouken@7962
   399
                        height = keyboardSize.height;
slouken@7962
   400
                        UIInterfaceOrientation ui_orient = [[UIApplication sharedApplication] statusBarOrientation];
slouken@7962
   401
                        if (ui_orient == UIInterfaceOrientationLandscapeRight || ui_orient == UIInterfaceOrientationLandscapeLeft) {
slouken@7962
   402
                            height = keyboardSize.width;
slouken@7962
   403
                        }
slouken@7962
   404
                        _uikit_keyboard_set_height(height);
slouken@7962
   405
                    }
slouken@7962
   406
     ];
slouken@7962
   407
    [center addObserverForName:UIKeyboardDidHideNotification
slouken@7962
   408
                        object:nil
slouken@7962
   409
                         queue:queue
slouken@7962
   410
                    usingBlock:^(NSNotification *notification) {
slouken@7962
   411
                        _uikit_keyboard_set_height(0);
slouken@7962
   412
                    }
slouken@7962
   413
     ];
slouken@7962
   414
}
slouken@7962
   415
slouken@7962
   416
void
slouken@7962
   417
UIKit_SetTextInputRect(_THIS, SDL_Rect *rect)
slouken@7962
   418
{
slouken@7962
   419
    if (!rect) {
slouken@7962
   420
        SDL_InvalidParamError("rect");
slouken@7962
   421
        return;
slouken@7962
   422
    }
slouken@7962
   423
    
slouken@7962
   424
    SDL_uikitview *view = getWindowView(SDL_GetFocusWindow());
slouken@7962
   425
    if (view == nil) {
slouken@7962
   426
        return ;
slouken@7962
   427
    }
slouken@7962
   428
slouken@7962
   429
    view.textInputRect = *rect;
slouken@7962
   430
}
slouken@7962
   431
slouken@7962
   432
slouken@5132
   433
#endif /* SDL_IPHONE_KEYBOARD */
slouken@2765
   434
slouken@6044
   435
#endif /* SDL_VIDEO_DRIVER_UIKIT */
slouken@6044
   436
slouken@5132
   437
/* vi: set ts=4 sw=4 expandtab: */