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