git.y1.nz

SameBoy

Accurate GB/GBC emulator
download: https://git.y1.nz/archives/sameboy.tar.gz
README | Files | Log | Refs | LICENSE

Cocoa/GBTerminalTextFieldCell.m

      1 #import <Carbon/Carbon.h>
      2 #import "GBTerminalTextFieldCell.h"
      3 #import "NSTextFieldCell+Inset.h"
      4 
      5 @interface GBTerminalTextView : NSTextView
      6 {
      7     @public __weak NSTextField *_field;
      8 }
      9 @property GB_gameboy_t *gb;
     10 @end
     11 
     12 @implementation GBTerminalTextFieldCell
     13 {
     14     GBTerminalTextView *_fieldEditor;
     15 }
     16 
     17 - (NSTextView *)fieldEditorForView:(NSTextField *)controlView
     18 {
     19     if (_fieldEditor) {
     20         _fieldEditor.gb = self.gb;
     21         return _fieldEditor;
     22     }
     23     _fieldEditor = [[GBTerminalTextView alloc] init];
     24     [_fieldEditor setFieldEditor:true];
     25     _fieldEditor.gb = self.gb;
     26     _fieldEditor->_field = (NSTextField *)controlView;
     27     ((NSTextFieldCell *)controlView.cell).textInset =
     28         _fieldEditor.textContainerInset =
     29         NSMakeSize(7, 2);
     30     return _fieldEditor;
     31 }
     32 
     33 @end
     34 
     35 @implementation GBTerminalTextView
     36 {
     37     NSMutableOrderedSet *lines;
     38     NSUInteger current_line;
     39     bool reverse_search_mode;
     40     NSRange auto_complete_range;
     41     uintptr_t auto_complete_context;
     42 }
     43 
     44 - (instancetype)init
     45 {
     46     self = [super init];
     47     if (!self) {
     48         return nil;
     49     }
     50     lines = [[NSMutableOrderedSet alloc] init];
     51     return self;
     52 }
     53 
     54 - (void)moveUp:(id)sender
     55 {
     56     reverse_search_mode = false;
     57     if (current_line != 0) {
     58         current_line--;
     59         [self setString:[lines objectAtIndex:current_line]];
     60     }
     61     else {
     62         [self setSelectedRange:NSMakeRange(0, 0)];
     63         NSBeep();
     64     }
     65 }
     66 
     67 - (void)moveDown:(id)sender
     68 {
     69     reverse_search_mode = false;
     70     if (current_line == [lines count]) {
     71         [self setString:@""];
     72         NSBeep();
     73         return;
     74     }
     75     current_line++;
     76     if (current_line == [lines count]) {
     77         [self setString:@""];
     78     }
     79     else {
     80         [self setString:[lines objectAtIndex:current_line]];
     81     }
     82 }
     83 
     84 -(void)insertNewline:(id)sender
     85 {
     86     if ([self.string length]) {
     87         NSString *string = [self.string copy];
     88         [lines removeObject:string];
     89         [lines addObject:string];
     90     }
     91     [super insertNewline:sender];
     92     current_line = [lines count];
     93     reverse_search_mode = false;
     94 }
     95 
     96 - (void)keyDown:(NSEvent *)event
     97 {
     98     if (event.keyCode == kVK_ANSI_R && (event.modifierFlags & NSEventModifierFlagDeviceIndependentFlagsMask) == NSEventModifierFlagControl) {
     99         if ([lines count] == 0) {
    100             NSBeep();
    101             return;
    102         }
    103         if (!reverse_search_mode) {
    104             [self selectAll:self];
    105             current_line = [lines count] - 1;
    106         }
    107         else {
    108             if (current_line != 0) {
    109                 current_line--;
    110             }
    111             else {
    112                 NSBeep();
    113             }
    114         }
    115         
    116         if (self.string.length) {
    117             [self updateReverseSearch];
    118         }
    119         else {
    120             [self setNeedsDisplay:true];
    121             reverse_search_mode = true;
    122         }
    123 
    124     }
    125     else {
    126         [super keyDown:event];
    127     }
    128 }
    129 
    130 - (void) updateReverseSearch
    131 {
    132     NSUInteger old_line = current_line;
    133     reverse_search_mode = false;
    134     NSString *substring = [self.string substringWithRange:self.selectedRange];
    135     do {
    136         NSString *line = [lines objectAtIndex:current_line];
    137         NSRange range = [line rangeOfString:substring];
    138         if (range.location != NSNotFound) {
    139             self.string = line;
    140             [self setSelectedRange:range];
    141             reverse_search_mode = true;
    142             return;
    143         }
    144     } while (current_line--);
    145     current_line = old_line;
    146     reverse_search_mode = true;
    147     NSBeep();
    148 }
    149 
    150 - (void) insertText:(NSString *)string replacementRange:(NSRange)range
    151 {
    152     if (reverse_search_mode) {
    153         range = self.selectedRange;
    154         self.string = [[self.string substringWithRange:range] stringByAppendingString:string];
    155         [self selectAll:nil];
    156         [self updateReverseSearch];
    157     }
    158     else {
    159         [super insertText:string replacementRange:range];
    160     }
    161 }
    162 
    163 -(void)deleteBackward:(id)sender
    164 {
    165     if (reverse_search_mode && self.string.length) {
    166         NSRange range = self.selectedRange;
    167         range.length--;
    168         self.string = [self.string substringWithRange:range];
    169         if (range.length) {
    170             [self selectAll:nil];
    171             [self updateReverseSearch];
    172         }
    173         else {
    174             reverse_search_mode = true;
    175             current_line = [lines count] - 1;
    176         }
    177     }
    178     else {
    179         [super deleteBackward:sender];
    180     }
    181 }
    182 
    183 -(void)setSelectedRanges:(NSArray<NSValue *> *)ranges affinity:(NSSelectionAffinity)affinity stillSelecting:(BOOL)stillSelectingFlag
    184 {
    185     reverse_search_mode = false;
    186     auto_complete_context = 0;
    187     [super setSelectedRanges:ranges affinity:affinity stillSelecting:stillSelectingFlag];
    188 }
    189 
    190 - (BOOL)resignFirstResponder 
    191 {
    192     reverse_search_mode = false;
    193     return [super resignFirstResponder];
    194 }
    195 
    196 - (NSColor *)backgroundColor
    197 {
    198     return nil;
    199 }
    200 
    201 - (void)drawRect:(NSRect)dirtyRect
    202 {
    203     if (reverse_search_mode && [super string].length == 0) {
    204         NSMutableDictionary *attributes = [self.typingAttributes mutableCopy];
    205         NSColor *color = [attributes[NSForegroundColorAttributeName] colorWithAlphaComponent:0.5];
    206         [attributes setObject:color forKey:NSForegroundColorAttributeName];
    207         [[[NSAttributedString alloc] initWithString:@"Reverse search..." attributes:attributes] drawAtPoint:NSMakePoint(9, 2)];
    208     }
    209     else {
    210         [super drawRect:dirtyRect];
    211     }
    212 }
    213 
    214 /* Todo: lazy design, make it use a delegate instead of having a gb reference*/
    215 
    216 - (void)insertTab:(id)sender
    217 {
    218     if (auto_complete_context == 0) {
    219         NSRange selection = self.selectedRange;
    220         if (selection.length) {
    221             [self delete:nil];
    222         }
    223         auto_complete_range = NSMakeRange(selection.location, 0);
    224     }
    225     char *substring = strdup([self.string substringToIndex:auto_complete_range.location].UTF8String);
    226     uintptr_t context = auto_complete_context;
    227     char *completion = GB_debugger_complete_substring(self.gb, substring, &context);
    228     free(substring);
    229     if (completion) {
    230         NSString *ns_completion = @(completion);
    231         free(completion);
    232         if (!ns_completion) {
    233             goto error;
    234         }
    235         self.selectedRange = auto_complete_range;
    236         auto_complete_range.length = ns_completion.length;
    237         [self replaceCharactersInRange:self.selectedRange withString:ns_completion];
    238         auto_complete_context = context;
    239         return;
    240     }
    241 error:
    242     auto_complete_context = context;
    243     NSBeep();
    244 }
    245 
    246 @end

This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.