]> Dogcows Code - chaz/thecheat/blob - MyDocument.m
The Cheat 1.1.1
[chaz/thecheat] / MyDocument.m
1
2 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3 // Project: The Cheat
4 //
5 // File: MyDocument.m
6 // Created: Sun Sep 07 2003
7 //
8 // Copyright: 2003 Chaz McGarvey. All rights reserved.
9 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
10
11 #import "MyDocument.h"
12
13 #import "AppController.h"
14
15 #import "CheatClient.h"
16
17
18 // Internal Functions
19 void TCPlaySound( NSString *name );
20
21
22 @implementation MyDocument
23
24 - (id)init
25 {
26 if ( self = [super init] )
27 {
28 NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
29
30 // initialize stuff
31 sockfd = -1;
32 addressList = [[NSMutableArray alloc] init];
33
34 // notifications to receive
35 [nc addObserver:self selector:@selector(listenerStarted:) name:@"TCListenerStarted" object:nil];
36 [nc addObserver:self selector:@selector(listenerStopped:) name:@"TCListenerStopped" object:nil];
37 [nc addObserver:self selector:@selector(windowsOnTopChanged:) name:@"TCWindowsOnTopChanged" object:nil];
38
39 serverList = [(NSArray *)[NSApp serverList] retain];
40
41 // register to recieve notes from the global browser
42 [nc addObserver:self selector:@selector(browserServerFound:) name:@"TCServerFound" object:nil];
43 [nc addObserver:self selector:@selector(browserServerLost:) name:@"TCServerLost" object:nil];
44
45 [self connectToLocal];
46 }
47
48 return self;
49 }
50
51 - (NSString *)windowNibName
52 {
53 return @"MyDocument";
54 }
55
56 - (NSString *)displayName
57 {
58 return [NSString stringWithFormat:@"The Cheat %i", TCGlobalDocumentCount++];
59 }
60
61 - (void)windowControllerDidLoadNib:(NSWindowController *)controller
62 {
63 [super windowControllerDidLoadNib:controller];
64
65 [self initialInterfaceSetup];
66 }
67
68
69 - (void)close
70 {
71 // closing the window will automatically disconnect the client from the server,
72 // but if the application is quitting, the client may not get a chance to exit.
73 // this _should_ be OK.
74 [self disconnect];
75
76 // clean up status timer stuff.
77 // we do this here because we don't want the timer to fire after the window is gone
78 // since we need to use the window in that method.
79 [savedStatusColor release], savedStatusColor = nil;
80 [savedStatusText release], savedStatusText = nil;
81 [statusTextTimer invalidate];
82 [statusTextTimer release], statusTextTimer = nil;
83
84 [super close];
85 }
86
87
88 - (void)initialInterfaceSetup
89 {
90 NSString *localName = @"Local"; //[NSString stringWithFormat:@"%@ (local)", TCGlobalBroadcastName];
91
92 NSMenuItem *menuItem;
93 int i, top = [serverList count];
94
95 // misc window settings
96 [cheatWindow useOptimizedDrawing:YES];
97 [cheatWindow setFrameAutosaveName:@"TCCheatWindow"];
98
99 // set options
100 if ( TCGlobalWindowsOnTop )
101 {
102 [cheatWindow setLevel:NSPopUpMenuWindowLevel];
103 }
104
105 // set up the server menu default items
106 [serverMenu removeAllItems];
107 [serverMenu addItemWithTitle:@"Not Connected" action:@selector(serverMenuDisconnect:) keyEquivalent:@""];
108 [serverMenu addItemWithTitle:localName action:@selector(serverMenuLocal:) keyEquivalent:@""];
109 [processMenu removeAllItems];
110
111 // update server menu
112 for ( i = 0; i < top; i++ )
113 {
114 menuItem = [[NSMenuItem alloc] initWithTitle:[(NSNetService *)[serverList objectAtIndex:i] name] action:@selector(serverMenuItem:) keyEquivalent:@""];
115
116 [menuItem setTag:i];
117
118 // if this is the first server, add a divider.
119 if ( [serverMenu numberOfItems] <= 2 )
120 {
121 [serverMenu addItem:[NSMenuItem separatorItem]];
122 }
123
124 [serverMenu addItem:[menuItem autorelease]];
125 }
126
127 // give tags to the menu items.
128 [[typeMenu itemWithTitle:@"Integer"] setTag:TYPE_INTEGER];
129 [[typeMenu itemWithTitle:@"String"] setTag:TYPE_STRING];
130 [[typeMenu itemWithTitle:@"Decimal"] setTag:TYPE_DECIMAL];
131 [[typeMenu itemWithTitle:@"Unknown Value"] setTag:TYPE_UNKNOWN];
132 [[stringSizeMenu itemWithTitle:@"8-bit"] setTag:SIZE_8_BIT];
133 [[integerSizeMenu itemWithTitle:@"char"] setTag:SIZE_8_BIT];
134 [[integerSizeMenu itemWithTitle:@"short"] setTag:SIZE_16_BIT];
135 [[integerSizeMenu itemWithTitle:@"long"] setTag:SIZE_32_BIT];
136 [[decimalSizeMenu itemWithTitle:@"float"] setTag:SIZE_32_BIT];
137 [[decimalSizeMenu itemWithTitle:@"double"] setTag:SIZE_64_BIT];
138
139 // set default state
140 [statusText setStringValue:@""];
141 [self setStatusDisconnected];
142
143 // display the initial description text
144 [self updateDescriptionText];
145
146 // change sheet initial interface.
147 [changeSecondsCombo setEnabled:NO];
148 }
149
150 - (void)updateSearchButton
151 {
152 TCtype type = [typePopup indexOfSelectedItem];
153
154 if ( type != TYPE_UNKNOWN )
155 {
156 if ( [[searchTextField stringValue] isEqualToString:@""] )
157 {
158 [searchButton setEnabled:NO];
159 }
160 else
161 {
162 [searchButton setEnabled:YES];
163 }
164 }
165 else
166 {
167 [searchButton setEnabled:YES];
168 }
169 }
170
171 - (void)updatePauseButton
172 {
173 if ( !targetPaused )
174 {
175 [pauseButton setTitle:@"Pause Target"];
176 }
177 else
178 {
179 [pauseButton setTitle:@"Resume Target"];
180 }
181 }
182
183 - (void)updateSearchBoxes
184 {
185 TCtype type = [typePopup indexOfSelectedItem];
186
187 if ( type != TYPE_UNKNOWN )
188 {
189 [searchTextField setEnabled:YES];
190 [searchRadioMatrix setEnabled:NO];
191 }
192 else
193 {
194 [searchTextField setEnabled:NO];
195 [searchRadioMatrix setEnabled:YES];
196 }
197 }
198
199 - (void)updateChangeButton
200 {
201 if ( addressSelected )
202 {
203 [changeButton setEnabled:YES];
204 }
205 else
206 {
207 [changeButton setEnabled:NO];
208 }
209 }
210
211 - (void)updateDescriptionText
212 {
213 TCtype type = [[typePopup selectedItem] tag];
214 TCsize size = [[sizePopup selectedItem] tag];
215
216 switch ( type )
217 {
218 case TYPE_STRING:
219 [descriptionText setStringValue:@"A string is a series of characters.\n\nThis search allows you to find and change words and phrases. Numbers can also be stored as strings, but they aren't recognized as numbers by the computer. Changing strings probably won't change the game in a big way."];
220 break;
221
222 case TYPE_INTEGER:
223 switch ( size )
224 {
225 case SIZE_8_BIT:
226 [descriptionText setStringValue:@"An integer is a non-fraction number.\n\nExamples: 0, 1, 2, 3, 4\nRange: 0 - 255\n\nIntegers usually store variables like score, lives, and remaining ammo."];
227 break;
228
229 case SIZE_16_BIT:
230 [descriptionText setStringValue:@"An integer is a non-fraction number.\n\nExamples: -1, 0, 1, 2, 3\nRange: -32,768 - 32,767\n\nIntegers usually store variables like score, lives, and remaining ammo."];
231 break;
232
233 case SIZE_32_BIT:
234 [descriptionText setStringValue:@"An integer is a non-fraction number.\n\nExamples: -1, 0, 1, 2, 3\nRange: about -2 billion - 2 billion\n\nIntegers usually store variables like score, lives, and remaining ammo. This is the most common size for integer variables."];
235 break;
236 }
237 break;
238
239 case TYPE_DECIMAL:
240 [descriptionText setStringValue:@"A decimal is a fraction number.\n\nFloats and doubles are not often used as variables in games, but there may be other uses for cheating them. Type in as many digits after the decimal place as possible to ensure that your input is matched with the variable you are looking for."];
241 break;
242 }
243 }
244
245
246 - (void)setStatusDisconnected
247 {
248 lastStatus = status;
249 status = STATUS_DISCONNECTED;
250
251 [serverPopup setEnabled:YES];
252 [pauseButton setTitle:@"Pause Target"];
253 [pauseButton setEnabled:NO];
254 [processPopup setEnabled:NO];
255 [typePopup setEnabled:NO];
256 [sizePopup setEnabled:NO];
257 [searchTextField setEnabled:NO];
258 [searchRadioMatrix setEnabled:NO];
259 [searchButton setEnabled:NO];
260 [clearSearchButton setEnabled:NO];
261 [self setStatusText:@"Not Connected" duration:0];
262 [statusText setToolTip:@""];
263 [statusBar stopAnimation:self];
264 [addressTable setEnabled:NO];
265 [changeButton setTitle:@"Change..."];
266 [changeButton setEnabled:NO];
267
268 [[serverMenu itemAtIndex:0] setTitle:@"Not Connected"];
269 }
270
271 - (void)setStatusConnected
272 {
273 lastStatus = status;
274 status = STATUS_CONNECTED;
275
276 [serverPopup setEnabled:YES];
277 [self updatePauseButton];
278 [pauseButton setEnabled:YES];
279 [processPopup setEnabled:YES];
280 [typePopup setEnabled:YES];
281 [sizePopup setEnabled:YES];
282 [self updateSearchBoxes];
283 [self updateSearchButton];
284 [clearSearchButton setEnabled:NO];
285 [self setStatusText:@"Connected" duration:0];
286 [statusText setToolTip:@""];
287 [statusBar stopAnimation:self];
288 [addressTable setEnabled:NO];
289 [changeButton setTitle:@"Change..."];
290 [changeButton setEnabled:NO];
291
292 [[serverMenu itemAtIndex:0] setTitle:@"Disconnect"];
293 }
294
295 - (void)setStatusCheating
296 {
297 lastStatus = status;
298 status = STATUS_CHEATING;
299
300 [serverPopup setEnabled:YES];
301 [self updatePauseButton];
302 [pauseButton setEnabled:YES];
303 [processPopup setEnabled:NO];
304 [typePopup setEnabled:NO];
305 [sizePopup setEnabled:NO];
306 [self updateSearchBoxes];
307 [self updateSearchButton];
308 [clearSearchButton setEnabled:YES];
309 if ( searchResultsAmount < maxSearchResultsAmount )
310 {
311 if ( searchResultsAmount == 1 )
312 {
313 [self setStatusText:[NSString stringWithFormat:@"Results: %i", searchResultsAmount] duration:0 color:[NSColor colorWithCalibratedRed:0.0f green:0.5f blue:0.0f alpha:1.0f]];
314 }
315 else if ( searchResultsAmount == 0 )
316 {
317 [self setStatusText:[NSString stringWithFormat:@"Results: %i", searchResultsAmount] duration:0 color:[NSColor colorWithCalibratedRed:0.5f green:0.0f blue:0.0f alpha:1.0f]];
318 }
319 else
320 {
321 [self setStatusText:[NSString stringWithFormat:@"Results: %i", searchResultsAmount] duration:0];
322 }
323 [statusText setToolTip:@""];
324 }
325 else
326 {
327 [self setStatusText:[NSString stringWithFormat:@"Results: >%i", maxSearchResultsAmount] duration:0];
328 [statusText setToolTip:[NSString stringWithFormat:@"Results: %i", searchResultsAmount]];
329 }
330 [statusBar stopAnimation:self];
331 [addressTable setEnabled:YES];
332 [changeButton setTitle:@"Change..."];
333 [self updateChangeButton];
334
335 [[serverMenu itemAtIndex:0] setTitle:@"Disconnect"];
336 }
337
338 - (void)setStatusSearching
339 {
340 lastStatus = status;
341 status = STATUS_SEARCHING;
342
343 [serverPopup setEnabled:NO];
344 [self updatePauseButton];
345 [pauseButton setEnabled:NO];
346 [processPopup setEnabled:NO];
347 [typePopup setEnabled:NO];
348 [sizePopup setEnabled:NO];
349 [searchTextField setEnabled:NO];
350 [searchRadioMatrix setEnabled:NO];
351 [searchButton setEnabled:NO];
352 [clearSearchButton setEnabled:NO];
353 [self setStatusText:@"Searching..." duration:0];
354 [statusText setToolTip:@""];
355 [statusBar startAnimation:self];
356 [addressTable setEnabled:NO];
357 [changeButton setTitle:@"Change..."];
358 [changeButton setEnabled:NO];
359
360 [[serverMenu itemAtIndex:0] setTitle:@"Disconnect"];
361 }
362
363 - (void)setStatusChanging
364 {
365 lastStatus = status;
366 status = STATUS_CHANGING;
367
368 if ( lastStatus != STATUS_CHANGING_CONTINUOUSLY )
369 {
370 [serverPopup setEnabled:NO];
371 [self updatePauseButton];
372 [pauseButton setEnabled:NO];
373 [processPopup setEnabled:NO];
374 [typePopup setEnabled:NO];
375 [sizePopup setEnabled:NO];
376 [searchTextField setEnabled:NO];
377 [searchRadioMatrix setEnabled:NO];
378 [searchButton setEnabled:NO];
379 [clearSearchButton setEnabled:NO];
380 [statusBar startAnimation:self];
381 [addressTable setEnabled:NO];
382 [changeButton setEnabled:NO];
383
384 [[serverMenu itemAtIndex:0] setTitle:@"Disconnect"];
385 }
386 }
387
388 - (void)setStatusChangingLater
389 {
390 lastStatus = status;
391 status = STATUS_CHANGING_LATER;
392
393 [serverPopup setEnabled:NO];
394 [self updatePauseButton];
395 [pauseButton setEnabled:NO];
396 [processPopup setEnabled:NO];
397 [typePopup setEnabled:NO];
398 [sizePopup setEnabled:NO];
399 [searchTextField setEnabled:NO];
400 [searchRadioMatrix setEnabled:NO];
401 [searchButton setEnabled:NO];
402 [clearSearchButton setEnabled:NO];
403 [self setStatusText:@"Changing Later..." duration:0];
404 [statusText setToolTip:@""];
405 [statusBar startAnimation:self];
406 [addressTable setEnabled:NO];
407 [changeButton setTitle:@"Cancel Change"];
408 [changeButton setEnabled:YES];
409
410 [[serverMenu itemAtIndex:0] setTitle:@"Disconnect"];
411 }
412
413 - (void)setStatusChangingContinuously
414 {
415 lastStatus = status;
416 status = STATUS_CHANGING_CONTINUOUSLY;
417
418 [serverPopup setEnabled:NO];
419 [self updatePauseButton];
420 [pauseButton setEnabled:YES];
421 [processPopup setEnabled:NO];
422 [typePopup setEnabled:NO];
423 [sizePopup setEnabled:NO];
424 [searchTextField setEnabled:NO];
425 [searchRadioMatrix setEnabled:NO];
426 [searchButton setEnabled:NO];
427 [clearSearchButton setEnabled:NO];
428 [self setStatusText:@"Repeating Change..." duration:0];
429 [statusText setToolTip:@""];
430 [statusBar startAnimation:self];
431 [addressTable setEnabled:NO];
432 [changeButton setTitle:@"Stop Change"];
433 [changeButton setEnabled:YES];
434
435 [[serverMenu itemAtIndex:0] setTitle:@"Disconnect"];
436 }
437
438 - (void)setStatusUndoing
439 {
440 lastStatus = status;
441 status = STATUS_UNDOING;
442
443 [serverPopup setEnabled:NO];
444 [self updatePauseButton];
445 [pauseButton setEnabled:NO];
446 [processPopup setEnabled:NO];
447 [typePopup setEnabled:NO];
448 [sizePopup setEnabled:NO];
449 [searchTextField setEnabled:NO];
450 [searchRadioMatrix setEnabled:NO];
451 [searchButton setEnabled:NO];
452 [clearSearchButton setEnabled:NO];
453 [self setStatusText:@"Undoing..." duration:0];
454 [statusBar startAnimation:self];
455 [addressTable setEnabled:NO];
456 [changeButton setTitle:@"Change..."];
457 [changeButton setEnabled:NO];
458
459 [[serverMenu itemAtIndex:0] setTitle:@"Disconnect"];
460 }
461
462 - (void)setStatusRedoing
463 {
464 lastStatus = status;
465 status = STATUS_REDOING;
466
467 [serverPopup setEnabled:NO];
468 [self updatePauseButton];
469 [pauseButton setEnabled:NO];
470 [processPopup setEnabled:NO];
471 [typePopup setEnabled:NO];
472 [sizePopup setEnabled:NO];
473 [searchTextField setEnabled:NO];
474 [searchRadioMatrix setEnabled:NO];
475 [searchButton setEnabled:NO];
476 [clearSearchButton setEnabled:NO];
477 [self setStatusText:@"Redoing..." duration:0];
478 [statusText setToolTip:@""];
479 [statusBar startAnimation:self];
480 [addressTable setEnabled:NO];
481 [changeButton setTitle:@"Change..."];
482 [changeButton setEnabled:NO];
483
484 [[serverMenu itemAtIndex:0] setTitle:@"Disconnect"];
485 }
486
487 - (void)setStatusToLast
488 {
489 switch ( lastStatus )
490 {
491 case STATUS_DISCONNECTED:
492 [self setStatusDisconnected];
493 break;
494
495 case STATUS_CONNECTED:
496 [self setStatusConnected];
497 break;
498
499 case STATUS_CHEATING:
500 [self setStatusCheating];
501 break;
502
503 case STATUS_SEARCHING:
504 [self setStatusSearching];
505 break;
506
507 case STATUS_CHANGING:
508 [self setStatusChanging];
509 break;
510
511 case STATUS_CHANGING_LATER:
512 [self setStatusChangingLater];
513 break;
514
515 case STATUS_CHANGING_CONTINUOUSLY:
516 [self setStatusChangingContinuously];
517 break;
518
519 case STATUS_UNDOING:
520 [self setStatusUndoing];
521 break;
522
523 case STATUS_REDOING:
524 [self setStatusRedoing];
525 break;
526 }
527 }
528
529 - (void)setStatusText:(NSString *)msg duration:(NSTimeInterval)seconds
530 {
531 [self setStatusText:msg duration:seconds color:[NSColor blackColor]];
532 }
533
534 - (void)setStatusText:(NSString *)msg duration:(NSTimeInterval)seconds color:(NSColor *)color
535 {
536 if ( statusTextTimer )
537 {
538 [statusTextTimer invalidate];
539 [statusTextTimer release], statusTextTimer = nil;
540 }
541 else
542 {
543 [savedStatusText release];
544 [savedStatusColor release];
545 savedStatusText = [[statusText stringValue] retain];
546 savedStatusColor = [[statusText textColor] retain];
547 }
548
549 [statusText setTextColor:color];
550 [statusText setStringValue:msg];
551
552 if ( seconds != 0.0 )
553 {
554 statusTextTimer = [[NSTimer scheduledTimerWithTimeInterval:seconds target:self selector:@selector(statusTextTimer:) userInfo:nil repeats:NO] retain];
555 }
556 }
557
558 - (void)statusTextTimer:(NSTimer *)timer
559 {
560 [statusText setTextColor:savedStatusColor];
561 [statusText setStringValue:savedStatusText];
562
563 [savedStatusColor release], savedStatusColor = nil;
564 [savedStatusText release], savedStatusText = nil;
565 [statusTextTimer invalidate];
566 [statusTextTimer release], statusTextTimer = nil;
567 }
568
569
570 - (void)connectToLocal
571 {
572 NSString *localName = @"Local"; //[NSString stringWithFormat:@"%@ (local)", TCGlobalBroadcastName];
573
574 // depending on how the listener is listening, we need to use different means to connect to local
575 if ( TCGlobalListening )
576 {
577 if ( TCGlobalAllowRemote )
578 {
579 struct sockaddr_in addr;
580
581 addr.sin_family = AF_INET;
582 addr.sin_port = htonl( TCGlobalListenPort );
583 addr.sin_addr.s_addr = INADDR_ANY;
584
585 [self connectToServer:[NSData dataWithBytes:&addr length:sizeof(addr)] name:localName];
586 }
587 else
588 {
589 struct sockaddr_un addr;
590
591 addr.sun_family = AF_UNIX;
592 strncpy( addr.sun_path, TCDefaultListenPath, 103 );
593
594 [self connectToServer:[NSData dataWithBytes:&addr length:sizeof(addr)] name:localName];
595 }
596 }
597 }
598
599 - (void)connectToServer:(NSData *)addr name:(NSString *)name
600 {
601 everConnected = YES;
602
603 if ( connection )
604 {
605 [self disconnect];
606
607 waitingToConnect = YES;
608 connectionAddress = [addr retain];
609 connectionName = [name retain];
610 }
611 else
612 {
613 connection = [[CheatClient clientWithDelegate:self server:addr name:name] retain];
614 connectionAddress = [addr retain];
615 connectionName = [name retain];
616 }
617
618 [self setStatusConnected];
619 }
620
621 - (void)disconnect
622 {
623 if ( connection )
624 {
625 [connection release], connection = nil;
626 close( sockfd );
627
628 [self clearSearch];
629
630 [connectionAddress release], connectionAddress = nil;
631 [connectionName release], connectionName = nil;
632
633 [processMenu removeAllItems];
634
635 [serverPopup selectItemAtIndex:0];
636 [self setStatusDisconnected];
637 }
638 }
639
640
641 - (void)sendProcessListRequest
642 {
643 PacketHeader header;
644 int length = sizeof(header);
645
646 header.checksum = RandomChecksum();
647 header.function = 1;
648 header.size = 0;
649
650 if ( SendBuffer( sockfd, (char *)(&header), &length ) == -1 || length != sizeof(header) )
651 {
652 NSLog( @"sendProcessListRequest failed on socket %i", sockfd );
653 }
654 }
655
656 - (void)sendClearSearch
657 {
658 PacketHeader header;
659 int length = sizeof(header);
660
661 header.checksum = RandomChecksum();
662 header.function = 3;
663 header.size = 0;
664
665 if ( SendBuffer( sockfd, (char *)(&header), &length ) == -1 || length != sizeof(header) )
666 {
667 NSLog( @"sendClearSearch failed on socket %i", sockfd );
668 }
669 }
670
671 - (void)sendSearch:(char const *)data size:(int)size
672 {
673 PacketHeader header;
674 int length = sizeof(header) + size;
675 int lengthAfter = length;
676
677 char *buffer, *ptr;
678
679 header.checksum = RandomChecksum();
680 header.function = 5;
681 header.size = size;
682
683 if ( (buffer = (char *)malloc( length )) == NULL )
684 {
685 NSLog( @"sendSearch:size: failed" );
686 }
687
688 ptr = buffer;
689
690 COPY_TO_BUFFER( ptr, &header, sizeof(header) );
691 COPY_TO_BUFFER( ptr, data, size );
692
693 if ( SendBuffer( sockfd, buffer, &lengthAfter ) == -1 || lengthAfter != length )
694 {
695 NSLog( @"sendSearch:size: failed" );
696 }
697
698 free( buffer );
699 }
700
701 - (void)sendChange:(char const *)data size:(int)size
702 {
703 PacketHeader header;
704 int length = sizeof(header) + size;
705 int lengthAfter = length;
706
707 char *buffer, *ptr;
708
709 header.checksum = RandomChecksum();
710 header.function = 8;
711 header.size = size;
712
713 if ( (buffer = (char *)malloc( length )) == NULL )
714 {
715 NSLog( @"sendChange:size: failed" );
716 }
717
718 ptr = buffer;
719
720 COPY_TO_BUFFER( ptr, &header, sizeof(header) );
721 COPY_TO_BUFFER( ptr, data, size );
722
723 if ( SendBuffer( sockfd, buffer, &lengthAfter ) == -1 || lengthAfter != length )
724 {
725 NSLog( @"sendChange:size: failed" );
726 }
727
728 free( buffer );
729 }
730
731 - (void)sendPauseTarget;
732 {
733 PacketHeader header;
734 int length = sizeof(header);
735
736 header.checksum = RandomChecksum();
737 header.function = 10;
738 header.size = 0;
739
740 if ( SendBuffer( sockfd, (char *)(&header), &length ) == -1 || length != sizeof(header) )
741 {
742 NSLog( @"sendPauseTarget failed" );
743 }
744 }
745
746 - (void)sendVariableValueRequest
747 {
748
749 }
750
751 - (void)sendUndoRequest
752 {
753 PacketHeader header;
754 int length = sizeof(header);
755
756 header.checksum = RandomChecksum();
757 header.function = 14;
758 header.size = 0;
759
760 if ( SendBuffer( sockfd, (char *)(&header), &length ) == -1 || length != sizeof(header) )
761 {
762 NSLog( @"sendUndoRequest failed" );
763 }
764 }
765
766 - (void)sendRedoRequest
767 {
768 PacketHeader header;
769 int length = sizeof(header);
770
771 header.checksum = RandomChecksum();
772 header.function = 16;
773 header.size = 0;
774
775 if ( SendBuffer( sockfd, (char *)(&header), &length ) == -1 || length != sizeof(header) )
776 {
777 NSLog( @"sendRedoRequest failed" );
778 }
779 }
780
781 - (void)sendSetTargetPID:(int)pid
782 {
783 PacketHeader header;
784 int length = sizeof(header) + sizeof(u_int32_t);
785 int lengthAfter = length;
786
787 u_int32_t tarPID = (u_int32_t)pid;
788
789 char *buffer, *ptr;
790
791 header.checksum = RandomChecksum();
792 header.function = 18;
793 header.size = sizeof(u_int32_t);
794
795 if ( (buffer = (char *)malloc( length )) == NULL )
796 {
797 NSLog( @"sendSetTargetPID: failed" );
798 }
799
800 ptr = buffer;
801
802 COPY_TO_BUFFER( ptr, &header, sizeof(header) );
803 COPY_TO_BUFFER( ptr, &tarPID, sizeof(tarPID) );
804
805 if ( SendBuffer( sockfd, buffer, &lengthAfter ) == -1 || lengthAfter != length )
806 {
807 NSLog( @"sendSetTargetPID: failed" );
808 }
809
810 free( buffer );
811 }
812
813
814 - (void)receivedProcessList:(NSData *)data
815 {
816 NSMenuItem *item;
817 u_int32_t processCount = 0;
818
819 char *ptr = (char *)[data bytes];
820 int i, max;
821
822 COPY_FROM_BUFFER( &processCount, ptr, sizeof(processCount) );
823
824 max = (int)processCount;
825
826 for ( i = 0; i < max; i++ )
827 {
828 u_int32_t pid;
829 NSString *name;
830
831 COPY_FROM_BUFFER( &pid, ptr, sizeof(pid) );
832 name = [NSString stringWithCString:ptr], ptr += [name length] + 1;
833
834 item = [[NSMenuItem alloc] initWithTitle:name action:@selector(processMenuItem:) keyEquivalent:@""];
835 [item setTag:(int)pid];
836
837 [processMenu addItem:[item autorelease]];
838 }
839 }
840
841 - (void)receivedSearchFinished
842 {
843 if ( searchResultsAmount == 1 )
844 {
845 TCPlaySound( @"Submarine" );
846 }
847 else if ( searchResultsAmount == 0 )
848 {
849 TCPlaySound( @"Basso" );
850 }
851
852 [self setStatusToLast];
853 //[self setStatusText:@"Search Finished" duration:1.5];
854 [cheatWindow makeFirstResponder:searchTextField];
855 }
856
857 - (void)receivedVariableList:(NSData *)data
858 {
859 char *ptr = (char *)[data bytes];
860
861 [self destroyResults];
862
863 COPY_FROM_BUFFER( &searchResultsAmount, ptr, sizeof(searchResultsAmount) );
864 COPY_FROM_BUFFER( &maxSearchResultsAmount, ptr, sizeof(maxSearchResultsAmount) );
865
866 if ( searchResultsAmount > 0 )
867 {
868 int memSize = TCAddressSize*maxSearchResultsAmount;
869
870 if ( (searchResults = (TCaddress *)malloc( memSize )) == NULL )
871 {
872 NSLog( @"receivedVariableList failed: malloc failed" );
873 searchResultsAmount = 0;
874 return;
875 }
876
877 COPY_FROM_BUFFER( searchResults, ptr, memSize );
878 }
879
880 [addressTable reloadData];
881 }
882
883 - (void)receivedChangeFinished
884 {
885 [self setStatusToLast];
886
887 if ( status == STATUS_CHANGING_CONTINUOUSLY )
888 {
889 [self setStatusText:@"Change Occured" duration:1.5];
890 }
891 else
892 {
893 TCPlaySound( @"Tink" );
894 }
895 }
896
897 - (void)receivedError:(NSData *)data
898 {
899 u_int32_t fatal;
900 NSString *msg;
901
902 char *ptr = (char *)[data bytes];
903
904 COPY_FROM_BUFFER( &fatal, ptr, sizeof(fatal) );
905
906 msg = [NSString stringWithCString:ptr];
907
908 // alert the user.
909 [self handleErrorMessage:msg fatal:fatal];
910 }
911
912 - (void)receivedUndoFinished
913 {
914 [self setStatusToLast];
915 }
916
917 - (void)receivedRedoFinished
918 {
919 [self setStatusToLast];
920 }
921
922 - (void)receivedUndoRedoStatus:(NSData *)data
923 {
924 char *ptr = (char *)[data bytes];
925
926 COPY_FROM_BUFFER( &undoCount, ptr, sizeof(undoCount) );
927 COPY_FROM_BUFFER( &redoCount, ptr, sizeof(redoCount) );
928
929 NSLog( @"UNDO: %i, REDO: %i", undoCount, redoCount );
930 }
931
932 - (void)receivedAppLaunched:(NSData *)data
933 {
934 NSMenuItem *item;
935
936 char *ptr = (char *)[data bytes];
937
938 u_int32_t pid;
939 NSString *name;
940
941 COPY_FROM_BUFFER( &pid, ptr, sizeof(pid) );
942 name = [NSString stringWithCString:ptr], ptr += [name length] + 1;
943
944 item = [[NSMenuItem alloc] initWithTitle:name action:@selector(processMenuItem:) keyEquivalent:@""];
945 [item setTag:(int)pid];
946
947 [processMenu addItem:[item autorelease]];
948 }
949
950 - (void)receivedAppQuit:(NSData *)data
951 {
952 u_int32_t pid;
953
954 char *ptr = (char *)[data bytes];
955
956 COPY_FROM_BUFFER( &pid, ptr, sizeof(pid) );
957
958 [processMenu removeItemWithTag:pid];
959 }
960
961 - (void)receivedTargetQuit
962 {
963 [self clearSearch];
964 [self sendClearSearch];
965
966 // tell the server that the first app is now the target.
967 targetPID = [[processMenu itemAtIndex:0] tag];
968 [self sendSetTargetPID:targetPID];
969
970 // alert the user.
971 [self handleErrorMessage:@"The application that was being cheated has quit." fatal:NO];
972
973 [self setStatusConnected];
974 }
975
976 - (void)receivedPauseFinished:(NSData *)data
977 {
978 char *ptr = (char *)[data bytes];
979
980 COPY_FROM_BUFFER( &targetPaused, ptr, sizeof(targetPaused) );
981
982 [self updatePauseButton];
983 }
984
985
986 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
987 %%%%%%%%%%%%%%%%%%%%%% Searching & Changing
988 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
989
990
991 - (void)search
992 {
993 TCtype type = [[typePopup selectedItem] tag];
994 TCsize size = [[sizePopup selectedItem] tag];
995
996 char *data, *ptr;
997 int dataSize = sizeof(type) + sizeof(size) + sizeof(TCGlobalHitsDisplayed);
998
999 data = (char *)malloc( dataSize );
1000 ptr = data;
1001
1002 // copy the size and type of the variable.
1003 COPY_TO_BUFFER( ptr, &type, sizeof(type) );
1004 COPY_TO_BUFFER( ptr, &size, sizeof(size) );
1005
1006 // copy the number of results to return.
1007 COPY_TO_BUFFER( ptr, &TCGlobalHitsDisplayed, sizeof(TCGlobalHitsDisplayed) );
1008
1009 NSLog( @"type: %i, size: %i", type, size );
1010
1011 // switch to cheating mode if this is the first search.
1012 if ( status == STATUS_CONNECTED )
1013 {
1014 [self setStatusCheating];
1015 }
1016
1017 // copy the value to search for.
1018 switch ( type )
1019 {
1020 case TYPE_STRING:
1021 {
1022 switch ( size )
1023 {
1024 case SIZE_8_BIT:
1025 {
1026 NSString *string = [searchTextField stringValue];
1027 int stringLength = [string length] + 1;
1028
1029 data = (char *)realloc( data, dataSize + stringLength );
1030 ptr = data + dataSize;
1031 dataSize += stringLength;
1032
1033 COPY_TO_BUFFER( ptr, [string cString], stringLength );
1034 }
1035 break;
1036 }
1037 }
1038 break;
1039
1040 case TYPE_INTEGER:
1041 {
1042 switch ( size )
1043 {
1044 case SIZE_8_BIT:
1045 {
1046 int8_t value = [searchTextField intValue];
1047
1048 data = (char *)realloc( data, dataSize + sizeof(value) );
1049 ptr = data + dataSize;
1050 dataSize += sizeof(value);
1051
1052 COPY_TO_BUFFER( ptr, &value, sizeof(value) );
1053 }
1054 break;
1055
1056 case SIZE_16_BIT:
1057 {
1058 int16_t value = [searchTextField intValue];
1059
1060 data = (char *)realloc( data, dataSize + sizeof(value) );
1061 ptr = data + dataSize;
1062 dataSize += sizeof(value);
1063
1064 COPY_TO_BUFFER( ptr, &value, sizeof(value) );
1065 }
1066 break;
1067
1068 case SIZE_32_BIT:
1069 {
1070 int32_t value = [searchTextField intValue];
1071
1072 data = (char *)realloc( data, dataSize + sizeof(value) );
1073 ptr = data + dataSize;
1074 dataSize += sizeof(value);
1075
1076 COPY_TO_BUFFER( ptr, &value, sizeof(value) );
1077 }
1078 break;
1079 }
1080 }
1081 break;
1082
1083 case TYPE_DECIMAL:
1084 {
1085 switch ( size )
1086 {
1087 case SIZE_32_BIT:
1088 {
1089 float value = [searchTextField floatValue];
1090
1091 data = (char *)realloc( data, dataSize + sizeof(value) );
1092 ptr = data + dataSize;
1093 dataSize += sizeof(value);
1094
1095 COPY_TO_BUFFER( ptr, &value, sizeof(value) );
1096 }
1097 break;
1098
1099 case SIZE_64_BIT:
1100 {
1101 double value = [searchTextField doubleValue];
1102
1103 data = (char *)realloc( data, dataSize + sizeof(value) );
1104 ptr = data + dataSize;
1105 dataSize += sizeof(value);
1106
1107 COPY_TO_BUFFER( ptr, &value, sizeof(value) );
1108 }
1109 break;
1110 }
1111 }
1112 break;
1113
1114 case TYPE_UNKNOWN:
1115 {
1116 u_int32_t value = 0;//[searchTextField intValue];
1117
1118 data = (char *)realloc( data, dataSize + sizeof(value) );
1119 ptr = data + dataSize;
1120 dataSize += sizeof(value);
1121
1122 COPY_TO_BUFFER( ptr, &value, sizeof(value) );
1123 }
1124 break;
1125 }
1126
1127 [self sendSearch:data size:dataSize];
1128 free( data );
1129
1130 [self setStatusSearching];
1131 }
1132
1133 - (void)change
1134 {
1135 TCtype type = [[typePopup selectedItem] tag];
1136 TCsize size = [[sizePopup selectedItem] tag];
1137
1138 int i, addressCount = [changeSelectedItems count];
1139
1140 char *data, *ptr;
1141 int dataSize = sizeof(type) + sizeof(size) + sizeof(addressCount) + TCAddressSize*addressCount;
1142
1143 data = (char *)malloc( dataSize );
1144 ptr = data;
1145
1146 // copy the size and type of the variable.
1147 COPY_TO_BUFFER( ptr, &type, sizeof(type) );
1148 COPY_TO_BUFFER( ptr, &size, sizeof(size) );
1149
1150 // copy the amount and the list of addresses to change.
1151 COPY_TO_BUFFER( ptr, &addressCount, sizeof(addressCount) );
1152 for ( i = 0; i < addressCount; i++ )
1153 {
1154 COPY_TO_BUFFER( ptr, &((TCaddress *)searchResults)[ [[changeSelectedItems objectAtIndex:i] intValue] ], sizeof(TCaddress) );
1155 }
1156
1157 // copy the new value.
1158 switch ( type )
1159 {
1160 case TYPE_STRING:
1161 {
1162 switch ( size )
1163 {
1164 case SIZE_8_BIT:
1165 {
1166 NSString *string = [changeTextField stringValue];
1167 int stringLength = [string length] + 1;
1168
1169 data = (char *)realloc( data, dataSize + stringLength );
1170 ptr = data + dataSize;
1171 dataSize += stringLength;
1172
1173 COPY_TO_BUFFER( ptr, [string cString], stringLength );
1174 }
1175 break;
1176 }
1177 }
1178 break;
1179
1180 case TYPE_INTEGER:
1181 {
1182 switch ( size )
1183 {
1184 case SIZE_8_BIT:
1185 {
1186 int8_t value = [changeTextField intValue];
1187
1188 data = (char *)realloc( data, dataSize + sizeof(value) );
1189 ptr = data + dataSize;
1190 dataSize += sizeof(value);
1191
1192 COPY_TO_BUFFER( ptr, &value, sizeof(value) );
1193 }
1194 break;
1195
1196 case SIZE_16_BIT:
1197 {
1198 int16_t value = [changeTextField intValue];
1199
1200 data = (char *)realloc( data, dataSize + sizeof(value) );
1201 ptr = data + dataSize;
1202 dataSize += sizeof(value);
1203
1204 COPY_TO_BUFFER( ptr, &value, sizeof(value) );
1205 }
1206 break;
1207
1208 case SIZE_32_BIT:
1209 {
1210 int32_t value = [changeTextField intValue];
1211
1212 data = (char *)realloc( data, dataSize + sizeof(value) );
1213 ptr = data + dataSize;
1214 dataSize += sizeof(value);
1215
1216 COPY_TO_BUFFER( ptr, &value, sizeof(value) );
1217 }
1218 break;
1219 }
1220 }
1221 break;
1222
1223 case TYPE_DECIMAL:
1224 {
1225 switch ( size )
1226 {
1227 case SIZE_32_BIT:
1228 {
1229 float value = [changeTextField floatValue];
1230
1231 data = (char *)realloc( data, dataSize + sizeof(value) );
1232 ptr = data + dataSize;
1233 dataSize += sizeof(value);
1234
1235 COPY_TO_BUFFER( ptr, &value, sizeof(value) );
1236 }
1237 break;
1238
1239 case SIZE_64_BIT:
1240 {
1241 double value = [changeTextField doubleValue];
1242
1243 data = (char *)realloc( data, dataSize + sizeof(value) );
1244 ptr = data + dataSize;
1245 dataSize += sizeof(value);
1246
1247 COPY_TO_BUFFER( ptr, &value, sizeof(value) );
1248 }
1249 break;
1250 }
1251 }
1252 break;
1253
1254 case TYPE_UNKNOWN:
1255 {
1256 u_int32_t value = 0;//[searchTextField intValue];
1257
1258 data = (char *)realloc( data, dataSize + sizeof(value) );
1259 ptr = data + dataSize;
1260 dataSize += sizeof(value);
1261
1262 COPY_TO_BUFFER( ptr, &value, sizeof(value) );
1263 }
1264 break;
1265 }
1266
1267 [self sendChange:data size:dataSize];
1268 free( data );
1269
1270 [self setStatusChanging];
1271 }
1272
1273
1274 - (void)changeSheet:(NSWindow *)sheet returned:(int)returned context:(void *)context
1275 {
1276 if ( returned == 1 )
1277 {
1278 [changeSelectedItems release], changeSelectedItems = [[[addressTable selectedRowEnumerator] allObjects] retain];
1279
1280 if ( [recurringChangeButton state] == NSOnState )
1281 {
1282 float seconds = [changeSecondsCombo floatValue];
1283
1284 [self setStatusChangingContinuously];
1285
1286 [self change];
1287
1288 changeTimer = [[NSTimer scheduledTimerWithTimeInterval:seconds target:self selector:@selector(changeTimer:) userInfo:nil repeats:YES] retain];
1289 }
1290 else
1291 {
1292 [self change];
1293 }
1294 }
1295 }
1296
1297
1298 - (void)changeTimer:(NSTimer *)timer
1299 {
1300 [self change];
1301 }
1302
1303
1304 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1305 %%%%%%%%%%%%%%%%%%%%%% Cheat Window Interface
1306 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
1307
1308
1309 - (IBAction)typePopup:(id)sender
1310 {
1311 switch ( [typePopup indexOfSelectedItem] )
1312 {
1313 case TYPE_STRING:
1314 [sizePopup setMenu:stringSizeMenu];
1315 break;
1316
1317 case TYPE_INTEGER:
1318 case TYPE_UNKNOWN:
1319 [sizePopup setMenu:integerSizeMenu];
1320 break;
1321
1322 case TYPE_DECIMAL:
1323 [sizePopup setMenu:decimalSizeMenu];
1324 break;
1325 }
1326
1327 [self updateSearchBoxes];
1328 [self updateSearchButton];
1329 [self updateDescriptionText];
1330 }
1331
1332 - (IBAction)sizePopup:(id)sender
1333 {
1334 [self updateDescriptionText];
1335 }
1336
1337
1338 - (IBAction)searchButton:(id)sender
1339 {
1340 /*if ( [searchTextField intValue] == 0 )
1341 {
1342 if ( NSRunAlertPanel( @"Warning", @"Performing a search with this value will probably take a long time. You should try to search for the variable at a different value.", @"Search Anyway", @"Cancel", nil ) == NSAlertAlternateReturn )
1343 {
1344 return;
1345 }
1346 }*/
1347
1348 [self search];
1349 }
1350
1351 - (IBAction)clearSearchButton:(id)sender
1352 {
1353 [self clearSearch];
1354
1355 [self setStatusConnected];
1356 [self setStatusText:@"Search Cleared" duration:1.5];
1357
1358 [self sendClearSearch];
1359 }
1360
1361
1362 - (IBAction)changeButton:(id)sender
1363 {
1364 [changeTimer invalidate];
1365 [changeTimer release], changeTimer = nil;
1366
1367 if ( status == STATUS_CHANGING_CONTINUOUSLY )
1368 {
1369 [changeSelectedItems release], changeSelectedItems = nil;
1370
1371 [self setStatusCheating];
1372 }
1373 else if ( status == STATUS_CHEATING )
1374 {
1375 [NSApp beginSheet:changeSheet modalForWindow:cheatWindow modalDelegate:self didEndSelector:@selector(changeSheet:returned:context:) contextInfo:NULL];
1376 //[NSApp runModalForWindow:changeSheet];
1377 //[NSApp endSheet:changeSheet];
1378 //[changeSheet orderOut:self];
1379 }
1380 }
1381
1382
1383 - (IBAction)serverMenuItem:(id)sender
1384 {
1385 NSData *data = [[[serverList objectAtIndex:[sender tag]] addresses] objectAtIndex:0];
1386 /* struct sockaddr_in addr;
1387
1388 [data getBytes:&addr];*/
1389
1390 [self connectToServer:data name:[serverPopup titleOfSelectedItem]];
1391 }
1392
1393 - (IBAction)serverMenuDisconnect:(id)sender
1394 {
1395 [self disconnect];
1396 }
1397
1398 - (IBAction)serverMenuLocal:(id)sender
1399 {
1400 [self connectToLocal];
1401 }
1402
1403 - (IBAction)processMenuItem:(id)sender
1404 {
1405 targetPID = [sender tag];
1406
1407 [self sendSetTargetPID:targetPID];
1408
1409 [self setStatusText:[NSString stringWithFormat:@"PID: %i", targetPID] duration:0];
1410 }
1411
1412
1413 - (IBAction)pauseButton:(id)sender
1414 {
1415 [self sendPauseTarget];
1416 }
1417
1418
1419 - (void)undoMenu:(id)sender
1420 {
1421 if ( undoCount == 1 )
1422 {
1423 [self clearSearchButton:self];
1424 }
1425 else
1426 {
1427 [self sendUndoRequest];
1428
1429 [self setStatusUndoing];
1430 }
1431 }
1432
1433 - (void)redoMenu:(id)sender
1434 {
1435 [self sendRedoRequest];
1436
1437 [self setStatusRedoing];
1438 }
1439
1440 - (BOOL)respondsToSelector:(SEL)aSelector
1441 {
1442 if ( aSelector == @selector(undoMenu:) )
1443 {
1444 if ( status == STATUS_CHEATING && undoCount > 0 )
1445 {
1446 return YES;
1447 }
1448 else
1449 {
1450 return NO;
1451 }
1452 }
1453
1454 if ( aSelector == @selector(redoMenu:) )
1455 {
1456 if ( status == STATUS_CHEATING && redoCount > 0 )
1457 {
1458 return YES;
1459 }
1460 else
1461 {
1462 return NO;
1463 }
1464 }
1465
1466 return [super respondsToSelector:aSelector];
1467 }
1468
1469
1470 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1471 %%%%%%%%%%%%%%%%%%%%%% Change Sheet Interface
1472 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
1473
1474
1475 - (IBAction)cancelButton:(id)sender
1476 {
1477 [changeSheet orderOut:sender];
1478 [NSApp endSheet:changeSheet returnCode:0];
1479 //[NSApp stopModal];
1480 }
1481
1482 - (IBAction)okButton:(id)sender
1483 {
1484 [changeSheet orderOut:sender];
1485 [NSApp endSheet:changeSheet returnCode:1];
1486 //[NSApp stopModal];
1487 }
1488
1489
1490 - (IBAction)recurringChangeButton:(id)sender
1491 {
1492 if ( [recurringChangeButton state] == NSOnState )
1493 {
1494 [changeSecondsCombo setEnabled:YES];
1495 }
1496 else
1497 {
1498 [changeSecondsCombo setEnabled:NO];
1499 }
1500 }
1501
1502
1503 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1504 %%%%%%%%%%%%%%%%%%%%%% Cleaning Up
1505 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
1506
1507
1508 - (void)clearSearch
1509 {
1510 undoCount = 0;
1511 redoCount = 0;
1512
1513 targetPaused = NO;
1514
1515 [changeTimer invalidate];
1516 [changeTimer release], changeTimer = nil;
1517
1518 [self destroyResults];
1519 [addressTable reloadData];
1520 }
1521
1522 - (void)destroyResults
1523 {
1524 if ( searchResultsAmount > 0 )
1525 {
1526 free( searchResults );
1527
1528 searchResultsAmount = 0;
1529 }
1530 }
1531
1532
1533 - (void)dealloc
1534 {
1535 [[NSNotificationCenter defaultCenter] removeObserver:self];
1536
1537 [self disconnect];
1538
1539 // clean up status timer stuff
1540 [savedStatusColor release];
1541 [savedStatusText release];
1542 [statusTextTimer invalidate];
1543 [statusTextTimer release];
1544
1545 [changeTimer invalidate];
1546 [changeTimer release];
1547
1548 [self destroyResults];
1549
1550 [changeSelectedItems release];
1551
1552 [serverList release];
1553 [addressList release];
1554
1555 [super dealloc];
1556 }
1557
1558
1559 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1560 %%%%%%%%%%%%%%%%%%%%%% TCListener Notifications
1561 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
1562
1563
1564 - (void)listenerStarted:(NSNotification *)note
1565 {
1566 if ( !everConnected )
1567 {
1568 [self connectToLocal];
1569 }
1570 }
1571
1572 - (void)listenerStopped:(NSNotification *)note
1573 {
1574
1575 }
1576
1577
1578 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1579 %%%%%%%%%%%%%%%%%%%%%% TCWindowsOnTopChanged Notification
1580 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
1581
1582
1583 - (void)windowsOnTopChanged:(NSNotification *)note
1584 {
1585 if ( [[note object] boolValue] )
1586 {
1587 [cheatWindow setLevel:NSPopUpMenuWindowLevel];
1588 }
1589 else
1590 {
1591 [cheatWindow setLevel:NSNormalWindowLevel];
1592 }
1593 }
1594
1595
1596 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1597 %%%%%%%%%%%%%%%%%%%%%% TCWindowsOnTopChanged Notification
1598 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
1599
1600
1601 - (void)handleErrorMessage:(NSString *)msg fatal:(BOOL)fatal
1602 {
1603 NSLog( @"error received" );
1604 // close the change sheet if it's open.
1605 if ( [cheatWindow attachedSheet] )
1606 {
1607 [changeSheet orderOut:self];
1608 [NSApp endSheet:changeSheet returnCode:0];
1609 }
1610
1611 // show message.
1612 NSBeginAlertSheet( fatal? @"Fatal Error":@"Error", @"OK", nil, nil, cheatWindow, nil, nil, nil, 0, msg );
1613 }
1614
1615
1616 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1617 %%%%%%%%%%%%%%%%%%%%%% Cheat Window Delegate
1618 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
1619
1620
1621 - (BOOL)windowShouldClose:(id)sender
1622 {
1623 if ( sender == cheatWindow && ( status == STATUS_SEARCHING || status == STATUS_CHANGING ) )
1624 {
1625 NSBeep();
1626 return NO;
1627 }
1628
1629 return YES;
1630 }
1631
1632
1633 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1634 %%%%%%%%%%%%%%%%%%%%%% ClientDelegate
1635 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
1636
1637
1638 - (void)clientConnectedWithSocket:(int)sock name:(NSString *)name
1639 {
1640 // the client is reporting that a connection has been made.
1641 sockfd = sock;
1642
1643 [self sendProcessListRequest];
1644
1645 [serverPopup selectItemWithTitle:name];
1646
1647 [self setStatusConnected];
1648 }
1649
1650 - (void)clientDisconnected
1651 {
1652 // if there is a pending connection, connect now.
1653 if ( waitingToConnect )
1654 {
1655 waitingToConnect = NO;
1656 connection = [[CheatClient clientWithDelegate:self server:connectionAddress name:connectionName] retain];
1657 }
1658 // if our connection variable is still valid, we were disconnected unexpectedly.
1659 else if ( connection )
1660 {
1661 [self disconnect];
1662 NSBeginAlertSheet( @"Network Failure", @"OK", nil, nil, cheatWindow, nil, nil, nil, 0, @"The server has disconnected you." );
1663 }
1664 }
1665
1666 - (void)clientError:(NSString *)error message:(NSString *)message
1667 {
1668 NSBeginAlertSheet( error, @"OK", nil, nil, cheatWindow, nil, nil, nil, 0, message );
1669 }
1670
1671
1672 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1673 %%%%%%%%%%%%%%%%%%%%%% NSToolbar Delegate
1674 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
1675
1676 /*
1677 *** A toolbar is no longer used, but the code still remains for possible future use. ***
1678
1679 - (NSToolbarItem *)toolbar:(NSToolbar *)toolbar itemForItemIdentifier:(NSString *)itemIdentifier willBeInsertedIntoToolbar:(BOOL)flag
1680 {
1681 NSToolbarItem *item = [[NSToolbarItem alloc] initWithItemIdentifier:itemIdentifier];
1682
1683 if ( [itemIdentifier isEqualToString:@"Disconnect"] )
1684 {
1685 disconnectButton = item;
1686
1687 [item setLabel:@"Disconnect"];
1688 [item setPaletteLabel:[item label]];
1689 [item setImage:[NSImage imageNamed:@"disconnect"]];
1690 [item setTarget:self];
1691 [item setToolTip:@"Click here to pause or unpause the program being cheated."];
1692 }
1693 else if ( [itemIdentifier isEqualToString:@"ServerPopup"] )
1694 {
1695 NSRect fRect = [typePopup frame];
1696 NSSize fSize = NSMakeSize( FLT_MAX, fRect.size.height );
1697 NSMenuItem *menu = [[NSMenuItem alloc] initWithTitle:@"Server" action:@selector(serverPopup:) keyEquivalent:@""];
1698
1699 [menu setSubmenu:[serverPopup menu]];
1700
1701 [item setLabel:@"Server"];
1702 [item setPaletteLabel:[item label]];
1703 [item setView:serverPopup];
1704 [item setMinSize:fRect.size];
1705 [item setMaxSize:fSize];
1706 [item setMenuFormRepresentation:[menu autorelease]];
1707 [item autorelease];
1708 }
1709
1710 return item;
1711 }
1712
1713 - (NSArray *)toolbarAllowedItemIdentifiers:(NSToolbar*)toolbar
1714 {
1715 return [NSArray arrayWithObjects:NSToolbarSeparatorItemIdentifier,
1716 NSToolbarSpaceItemIdentifier,
1717 NSToolbarFlexibleSpaceItemIdentifier,
1718 NSToolbarCustomizeToolbarItemIdentifier,
1719 @"Disconnect", @"ServerPopup", nil];
1720 }
1721
1722 - (NSArray *)toolbarDefaultItemIdentifiers:(NSToolbar*)toolbar
1723 {
1724 return [NSArray arrayWithObjects:@"Disconnect", @"ServerPopup", nil];
1725 }*/
1726
1727
1728 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1729 %%%%%%%%%%%%%%%%%%%%%% NSTableView Data Source/Delegate
1730 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
1731
1732
1733 - (void)controlTextDidChange:(NSNotification *)aNotification
1734 {
1735 [self updateSearchButton];
1736 }
1737
1738
1739 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1740 %%%%%%%%%%%%%%%%%%%%%% NSTableView Data Source/Delegate
1741 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
1742
1743
1744 - (int)numberOfRowsInTableView:(NSTableView *)table
1745 {
1746 return (searchResultsAmount <= maxSearchResultsAmount) ? searchResultsAmount : maxSearchResultsAmount;
1747 }
1748
1749 - (id)tableView:(NSTableView *)table objectValueForTableColumn:(NSTableColumn *)column row:(int)row
1750 {
1751 return [NSString stringWithFormat:@"%0.8X", ((TCaddress *)searchResults)[row]];
1752 }
1753
1754 - (void)tableView:(NSTableView *) setObjectValue:(id)object forTableColumn:(NSTableColumn *)column row:(int)row
1755 {
1756 return;
1757 }
1758
1759 - (void)tableViewSelectionDidChange:(NSNotification *)note
1760 {
1761 if ( [addressTable selectedRow] != -1 )
1762 {
1763 addressSelected = YES;
1764 }
1765 else
1766 {
1767 addressSelected = NO;
1768 }
1769
1770 [self updateChangeButton];
1771 }
1772
1773
1774 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1775 %%%%%%%%%%%%%%%%%%%%%% Global Browser Notifications
1776 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
1777
1778
1779 - (void)browserServerFound:(NSNotification *)note
1780 {
1781 NSNetService *service = (NSNetService *)[note object];
1782
1783 NSString *name = [service name];
1784 int tag = [serverList count] - 1;
1785 NSMenuItem *item;
1786
1787 NSLog( @"server found" );
1788
1789 if ( [serverMenu itemWithTitle:name] == nil )
1790 {
1791 item = [[NSMenuItem alloc] initWithTitle:[service name] action:@selector(serverMenuItem:) keyEquivalent:@""];
1792
1793 [item setTag:tag];
1794
1795 // if this is the first server, add a divider.
1796 if ( [serverMenu numberOfItems] <= 2 )
1797 {
1798 [serverMenu addItem:[NSMenuItem separatorItem]];
1799 }
1800
1801 //[serverList addObject:service];
1802 [serverMenu addItem:[item autorelease]];
1803
1804 // select the item if we are already connected to the server.
1805 // this could happen if the server rebroadcast as a different name.
1806 if ( connection && [[[service addresses] objectAtIndex:0] isEqualToData:connectionAddress] )
1807 {
1808 [serverPopup selectItemWithTitle:[service name]];
1809 }
1810 }
1811 }
1812
1813 - (void)browserServerLost:(NSNotification *)note
1814 {
1815 NSNetService *service = (NSNetService *)[note object];
1816 NSString *name = [service name];
1817
1818 int i, top = [serverMenu numberOfItems];
1819
1820 for ( i = [serverMenu indexOfItemWithTitle:name] + 1; i < top; i++ )
1821 {
1822 [[serverMenu itemWithTitle:name] setTag:[[serverMenu itemWithTitle:name] tag] - 1];
1823 }
1824
1825 [serverMenu removeAllItemsWithTitle:name];
1826
1827 // if this is the last broadcast server, take away the divider.
1828 if ( [serverMenu numberOfItems] == 3 )
1829 {
1830 [serverMenu removeItemAtIndex:2];
1831 }
1832 }
1833
1834
1835 @end
1836
1837
1838 // Internal Functions
1839 void TCPlaySound( NSString *name )
1840 {
1841 if ( TCGlobalPlaySounds )
1842 {
1843 [[NSSound soundNamed:name] play];
1844 }
1845 }
This page took 0.115148 seconds and 4 git commands to generate.