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