2 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
6 // Created: Sun Sep 07 2003
8 // Copyright: 2003 Chaz McGarvey. All rights reserved.
9 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
11 #import "MyDocument.h"
13 #import "AppController.h"
15 #import "CheatClient.h"
19 void TCPlaySound( NSString
*name
);
22 @implementation MyDocument
26 if ( self = [super init
] )
28 NSNotificationCenter
*nc
= [NSNotificationCenter defaultCenter
];
32 addressList
= [[NSMutableArray alloc
] init
];
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];
39 serverList
= [(NSArray
*)[NSApp serverList
] retain
];
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];
45 [self connectToLocal
];
51 - (NSString
*)windowNibName
56 - (NSString
*)displayName
58 return [NSString stringWithFormat
:@
"The Cheat %i", TCGlobalDocumentCount
++];
61 - (void)windowControllerDidLoadNib
:(NSWindowController
*)controller
63 [super windowControllerDidLoadNib
:controller
];
65 [self initialInterfaceSetup
];
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.
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;
88 - (void)initialInterfaceSetup
90 NSString
*localName
= @
"Local"; //[NSString stringWithFormat:@"%@ (local)", TCGlobalBroadcastName];
93 int i
, top
= [serverList count
];
95 // misc window settings
96 [cheatWindow useOptimizedDrawing
:YES
];
97 [cheatWindow setFrameAutosaveName
:@
"TCCheatWindow"];
100 if ( TCGlobalWindowsOnTop
)
102 [cheatWindow setLevel
:NSPopUpMenuWindowLevel
];
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
];
111 // update server menu
112 for ( i
= 0; i
< top
; i
++ )
114 menuItem
= [[NSMenuItem alloc
] initWithTitle
:[(NSNetService
*)[serverList objectAtIndex
:i
] name
] action
:@selector(serverMenuItem
:) keyEquivalent
:@
""];
118 // if this is the first server, add a divider.
119 if ( [serverMenu numberOfItems
] <= 2 )
121 [serverMenu addItem
:[NSMenuItem separatorItem
]];
124 [serverMenu addItem
:[menuItem autorelease
]];
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
];
140 [statusText setStringValue
:@
""];
141 [self setStatusDisconnected
];
143 // display the initial description text
144 [self updateDescriptionText
];
146 // change sheet initial interface.
147 [changeSecondsCombo setEnabled
:NO
];
150 - (void)updateSearchButton
152 TCtype type
= [typePopup indexOfSelectedItem
];
154 if ( type
!= TYPE_UNKNOWN
)
156 if ( [[searchTextField stringValue
] isEqualToString
:@
""] )
158 [searchButton setEnabled
:NO
];
162 [searchButton setEnabled
:YES
];
167 [searchButton setEnabled
:YES
];
171 - (void)updatePauseButton
175 [pauseButton setTitle
:@
"Pause Target"];
179 [pauseButton setTitle
:@
"Resume Target"];
183 - (void)updateSearchBoxes
185 TCtype type
= [typePopup indexOfSelectedItem
];
187 if ( type
!= TYPE_UNKNOWN
)
189 [searchTextField setEnabled
:YES
];
190 [searchRadioMatrix setEnabled
:NO
];
194 [searchTextField setEnabled
:NO
];
195 [searchRadioMatrix setEnabled
:YES
];
199 - (void)updateChangeButton
201 if ( addressSelected
)
203 [changeButton setEnabled
:YES
];
207 [changeButton setEnabled
:NO
];
211 - (void)updateDescriptionText
213 TCtype type
= [[typePopup selectedItem
] tag
];
214 TCsize size
= [[sizePopup selectedItem
] tag
];
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."];
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."];
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."];
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."];
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."];
246 - (void)setStatusDisconnected
249 status
= STATUS_DISCONNECTED
;
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
];
268 [[serverMenu itemAtIndex
:0] setTitle
:@
"Not Connected"];
271 - (void)setStatusConnected
274 status
= STATUS_CONNECTED
;
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
];
292 [[serverMenu itemAtIndex
:0] setTitle
:@
"Disconnect"];
295 - (void)setStatusCheating
298 status
= STATUS_CHEATING
;
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
)
311 if ( searchResultsAmount
== 1 )
313 [self setStatusText
:[NSString stringWithFormat
:@
"Results: %i", searchResultsAmount
] duration
:0 color
:[NSColor colorWithCalibratedRed
:0.0f green
:0.5f blue
:0.0f alpha
:1.0f
]];
315 else if ( searchResultsAmount
== 0 )
317 [self setStatusText
:[NSString stringWithFormat
:@
"Results: %i", searchResultsAmount
] duration
:0 color
:[NSColor colorWithCalibratedRed
:0.5f green
:0.0f blue
:0.0f alpha
:1.0f
]];
321 [self setStatusText
:[NSString stringWithFormat
:@
"Results: %i", searchResultsAmount
] duration
:0];
323 [statusText setToolTip
:@
""];
327 [self setStatusText
:[NSString stringWithFormat
:@
"Results: >%i", maxSearchResultsAmount
] duration
:0];
328 [statusText setToolTip
:[NSString stringWithFormat
:@
"Results: %i", searchResultsAmount
]];
330 [statusBar stopAnimation
:self];
331 [addressTable setEnabled
:YES
];
332 [changeButton setTitle
:@
"Change..."];
333 [self updateChangeButton
];
335 [[serverMenu itemAtIndex
:0] setTitle
:@
"Disconnect"];
338 - (void)setStatusSearching
341 status
= STATUS_SEARCHING
;
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
];
360 [[serverMenu itemAtIndex
:0] setTitle
:@
"Disconnect"];
363 - (void)setStatusChanging
366 status
= STATUS_CHANGING
;
368 if ( lastStatus
!= STATUS_CHANGING_CONTINUOUSLY
)
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
];
384 [[serverMenu itemAtIndex
:0] setTitle
:@
"Disconnect"];
388 - (void)setStatusChangingLater
391 status
= STATUS_CHANGING_LATER
;
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
];
410 [[serverMenu itemAtIndex
:0] setTitle
:@
"Disconnect"];
413 - (void)setStatusChangingContinuously
416 status
= STATUS_CHANGING_CONTINUOUSLY
;
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
];
435 [[serverMenu itemAtIndex
:0] setTitle
:@
"Disconnect"];
438 - (void)setStatusUndoing
441 status
= STATUS_UNDOING
;
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
];
459 [[serverMenu itemAtIndex
:0] setTitle
:@
"Disconnect"];
462 - (void)setStatusRedoing
465 status
= STATUS_REDOING
;
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
];
484 [[serverMenu itemAtIndex
:0] setTitle
:@
"Disconnect"];
487 - (void)setStatusToLast
489 switch ( lastStatus
)
491 case STATUS_DISCONNECTED
:
492 [self setStatusDisconnected
];
495 case STATUS_CONNECTED
:
496 [self setStatusConnected
];
499 case STATUS_CHEATING
:
500 [self setStatusCheating
];
503 case STATUS_SEARCHING
:
504 [self setStatusSearching
];
507 case STATUS_CHANGING
:
508 [self setStatusChanging
];
511 case STATUS_CHANGING_LATER
:
512 [self setStatusChangingLater
];
515 case STATUS_CHANGING_CONTINUOUSLY
:
516 [self setStatusChangingContinuously
];
520 [self setStatusUndoing
];
524 [self setStatusRedoing
];
529 - (void)setStatusText
:(NSString
*)msg duration
:(NSTimeInterval
)seconds
531 [self setStatusText
:msg duration
:seconds color
:[NSColor blackColor
]];
534 - (void)setStatusText
:(NSString
*)msg duration
:(NSTimeInterval
)seconds color
:(NSColor
*)color
536 if ( statusTextTimer
)
538 [statusTextTimer invalidate
];
539 [statusTextTimer release
], statusTextTimer
= nil;
543 [savedStatusText release
];
544 [savedStatusColor release
];
545 savedStatusText
= [[statusText stringValue
] retain
];
546 savedStatusColor
= [[statusText textColor
] retain
];
549 [statusText setTextColor
:color
];
550 [statusText setStringValue
:msg
];
552 if ( seconds
!= 0.0 )
554 statusTextTimer
= [[NSTimer scheduledTimerWithTimeInterval
:seconds target
:self selector
:@selector(statusTextTimer
:) userInfo
:nil repeats
:NO
] retain
];
558 - (void)statusTextTimer
:(NSTimer
*)timer
560 [statusText setTextColor
:savedStatusColor
];
561 [statusText setStringValue
:savedStatusText
];
563 [savedStatusColor release
], savedStatusColor
= nil;
564 [savedStatusText release
], savedStatusText
= nil;
565 [statusTextTimer invalidate
];
566 [statusTextTimer release
], statusTextTimer
= nil;
570 - (void)connectToLocal
572 NSString
*localName
= @
"Local"; //[NSString stringWithFormat:@"%@ (local)", TCGlobalBroadcastName];
574 // depending on how the listener is listening, we need to use different means to connect to local
575 if ( TCGlobalListening
)
577 if ( TCGlobalAllowRemote
)
579 struct sockaddr_in addr
;
581 addr.sin_family
= AF_INET
;
582 addr.sin_port
= htonl( TCGlobalListenPort
);
583 addr.sin_addr.s_addr
= INADDR_ANY
;
585 [self connectToServer
:[NSData dataWithBytes
:&addr length
:sizeof(addr
)] name
:localName
];
589 struct sockaddr_un addr
;
591 addr.sun_family
= AF_UNIX
;
592 strncpy( addr.sun_path
, TCDefaultListenPath
, 103 );
594 [self connectToServer
:[NSData dataWithBytes
:&addr length
:sizeof(addr
)] name
:localName
];
599 - (void)connectToServer
:(NSData
*)addr name
:(NSString
*)name
607 waitingToConnect
= YES
;
608 connectionAddress
= [addr retain
];
609 connectionName
= [name retain
];
613 connection
= [[CheatClient clientWithDelegate
:self server
:addr name
:name
] retain
];
614 connectionAddress
= [addr retain
];
615 connectionName
= [name retain
];
618 [self setStatusConnected
];
625 [connection release
], connection
= nil;
630 [connectionAddress release
], connectionAddress
= nil;
631 [connectionName release
], connectionName
= nil;
633 [processMenu removeAllItems
];
635 [serverPopup selectItemAtIndex
:0];
636 [self setStatusDisconnected
];
641 - (void)sendProcessListRequest
644 int length
= sizeof(header
);
646 header.checksum
= RandomChecksum();
650 if ( SendBuffer( sockfd
, (char *)(&header
), &length
) == -1 || length
!= sizeof(header
) )
652 NSLog( @
"sendProcessListRequest failed on socket %i", sockfd
);
656 - (void)sendClearSearch
659 int length
= sizeof(header
);
661 header.checksum
= RandomChecksum();
665 if ( SendBuffer( sockfd
, (char *)(&header
), &length
) == -1 || length
!= sizeof(header
) )
667 NSLog( @
"sendClearSearch failed on socket %i", sockfd
);
671 - (void)sendSearch
:(char const *)data size
:(int)size
674 int length
= sizeof(header
) + size
;
675 int lengthAfter
= length
;
679 header.checksum
= RandomChecksum();
683 if ( (buffer
= (char *)malloc( length
)) == NULL
)
685 NSLog( @
"sendSearch:size: failed" );
690 COPY_TO_BUFFER( ptr
, &header
, sizeof(header
) );
691 COPY_TO_BUFFER( ptr
, data
, size
);
693 if ( SendBuffer( sockfd
, buffer
, &lengthAfter
) == -1 || lengthAfter
!= length
)
695 NSLog( @
"sendSearch:size: failed" );
701 - (void)sendChange
:(char const *)data size
:(int)size
704 int length
= sizeof(header
) + size
;
705 int lengthAfter
= length
;
709 header.checksum
= RandomChecksum();
713 if ( (buffer
= (char *)malloc( length
)) == NULL
)
715 NSLog( @
"sendChange:size: failed" );
720 COPY_TO_BUFFER( ptr
, &header
, sizeof(header
) );
721 COPY_TO_BUFFER( ptr
, data
, size
);
723 if ( SendBuffer( sockfd
, buffer
, &lengthAfter
) == -1 || lengthAfter
!= length
)
725 NSLog( @
"sendChange:size: failed" );
731 - (void)sendPauseTarget
;
734 int length
= sizeof(header
);
736 header.checksum
= RandomChecksum();
737 header.function
= 10;
740 if ( SendBuffer( sockfd
, (char *)(&header
), &length
) == -1 || length
!= sizeof(header
) )
742 NSLog( @
"sendPauseTarget failed" );
746 - (void)sendVariableValueRequest
751 - (void)sendUndoRequest
754 int length
= sizeof(header
);
756 header.checksum
= RandomChecksum();
757 header.function
= 14;
760 if ( SendBuffer( sockfd
, (char *)(&header
), &length
) == -1 || length
!= sizeof(header
) )
762 NSLog( @
"sendUndoRequest failed" );
766 - (void)sendRedoRequest
769 int length
= sizeof(header
);
771 header.checksum
= RandomChecksum();
772 header.function
= 16;
775 if ( SendBuffer( sockfd
, (char *)(&header
), &length
) == -1 || length
!= sizeof(header
) )
777 NSLog( @
"sendRedoRequest failed" );
781 - (void)sendSetTargetPID
:(int)pid
784 int length
= sizeof(header
) + sizeof(u_int32_t
);
785 int lengthAfter
= length
;
787 u_int32_t tarPID
= (u_int32_t
)pid
;
791 header.checksum
= RandomChecksum();
792 header.function
= 18;
793 header.size
= sizeof(u_int32_t
);
795 if ( (buffer
= (char *)malloc( length
)) == NULL
)
797 NSLog( @
"sendSetTargetPID: failed" );
802 COPY_TO_BUFFER( ptr
, &header
, sizeof(header
) );
803 COPY_TO_BUFFER( ptr
, &tarPID
, sizeof(tarPID
) );
805 if ( SendBuffer( sockfd
, buffer
, &lengthAfter
) == -1 || lengthAfter
!= length
)
807 NSLog( @
"sendSetTargetPID: failed" );
814 - (void)receivedProcessList
:(NSData
*)data
817 u_int32_t processCount
= 0;
819 char *ptr
= (char *)[data bytes
];
822 COPY_FROM_BUFFER( &processCount
, ptr
, sizeof(processCount
) );
824 max
= (int)processCount
;
826 for ( i
= 0; i
< max
; i
++ )
831 COPY_FROM_BUFFER( &pid
, ptr
, sizeof(pid
) );
832 name
= [NSString stringWithCString
:ptr
], ptr
+= [name length
] + 1;
834 item
= [[NSMenuItem alloc
] initWithTitle
:name action
:@selector(processMenuItem
:) keyEquivalent
:@
""];
835 [item setTag
:(int)pid
];
837 [processMenu addItem
:[item autorelease
]];
841 - (void)receivedSearchFinished
843 if ( searchResultsAmount
== 1 )
845 TCPlaySound( @
"Submarine" );
847 else if ( searchResultsAmount
== 0 )
849 TCPlaySound( @
"Basso" );
852 [self setStatusToLast
];
853 //[self setStatusText:@"Search Finished" duration:1.5];
854 [cheatWindow makeFirstResponder
:searchTextField
];
857 - (void)receivedVariableList
:(NSData
*)data
859 char *ptr
= (char *)[data bytes
];
861 [self destroyResults
];
863 COPY_FROM_BUFFER( &searchResultsAmount
, ptr
, sizeof(searchResultsAmount
) );
864 COPY_FROM_BUFFER( &maxSearchResultsAmount
, ptr
, sizeof(maxSearchResultsAmount
) );
866 if ( searchResultsAmount
> 0 )
868 int memSize
= TCAddressSize
*maxSearchResultsAmount
;
870 if ( (searchResults
= (TCaddress
*)malloc( memSize
)) == NULL
)
872 NSLog( @
"receivedVariableList failed: malloc failed" );
873 searchResultsAmount
= 0;
877 COPY_FROM_BUFFER( searchResults
, ptr
, memSize
);
880 [addressTable reloadData
];
883 - (void)receivedChangeFinished
885 [self setStatusToLast
];
887 if ( status
== STATUS_CHANGING_CONTINUOUSLY
)
889 [self setStatusText
:@
"Change Occured" duration
:1.5];
893 TCPlaySound( @
"Tink" );
897 - (void)receivedError
:(NSData
*)data
902 char *ptr
= (char *)[data bytes
];
904 COPY_FROM_BUFFER( &fatal
, ptr
, sizeof(fatal
) );
906 msg
= [NSString stringWithCString
:ptr
];
909 [self handleErrorMessage
:msg fatal
:fatal
];
912 - (void)receivedUndoFinished
914 [self setStatusToLast
];
917 - (void)receivedRedoFinished
919 [self setStatusToLast
];
922 - (void)receivedUndoRedoStatus
:(NSData
*)data
924 char *ptr
= (char *)[data bytes
];
926 COPY_FROM_BUFFER( &undoCount
, ptr
, sizeof(undoCount
) );
927 COPY_FROM_BUFFER( &redoCount
, ptr
, sizeof(redoCount
) );
929 NSLog( @
"UNDO: %i, REDO: %i", undoCount
, redoCount
);
932 - (void)receivedAppLaunched
:(NSData
*)data
936 char *ptr
= (char *)[data bytes
];
941 COPY_FROM_BUFFER( &pid
, ptr
, sizeof(pid
) );
942 name
= [NSString stringWithCString
:ptr
], ptr
+= [name length
] + 1;
944 item
= [[NSMenuItem alloc
] initWithTitle
:name action
:@selector(processMenuItem
:) keyEquivalent
:@
""];
945 [item setTag
:(int)pid
];
947 [processMenu addItem
:[item autorelease
]];
950 - (void)receivedAppQuit
:(NSData
*)data
954 char *ptr
= (char *)[data bytes
];
956 COPY_FROM_BUFFER( &pid
, ptr
, sizeof(pid
) );
958 [processMenu removeItemWithTag
:pid
];
961 - (void)receivedTargetQuit
964 [self sendClearSearch
];
966 // tell the server that the first app is now the target.
967 targetPID
= [[processMenu itemAtIndex
:0] tag
];
968 [self sendSetTargetPID
:targetPID
];
971 [self handleErrorMessage
:@
"The application that was being cheated has quit." fatal
:NO
];
973 [self setStatusConnected
];
976 - (void)receivedPauseFinished
:(NSData
*)data
978 char *ptr
= (char *)[data bytes
];
980 COPY_FROM_BUFFER( &targetPaused
, ptr
, sizeof(targetPaused
) );
982 [self updatePauseButton
];
986 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
987 %%%%%%%%%%%%%%%%%%%%%% Searching & Changing
988 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
993 TCtype type
= [[typePopup selectedItem
] tag
];
994 TCsize size
= [[sizePopup selectedItem
] tag
];
997 int dataSize
= sizeof(type
) + sizeof(size
) + sizeof(TCGlobalHitsDisplayed
);
999 data
= (char *)malloc( dataSize
);
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
) );
1006 // copy the number of results to return.
1007 COPY_TO_BUFFER( ptr
, &TCGlobalHitsDisplayed
, sizeof(TCGlobalHitsDisplayed
) );
1009 NSLog( @
"type: %i, size: %i", type
, size
);
1011 // switch to cheating mode if this is the first search.
1012 if ( status
== STATUS_CONNECTED
)
1014 [self setStatusCheating
];
1017 // copy the value to search for.
1026 NSString
*string
= [searchTextField stringValue
];
1027 int stringLength
= [string length
] + 1;
1029 data
= (char *)realloc( data
, dataSize
+ stringLength
);
1030 ptr
= data
+ dataSize
;
1031 dataSize
+= stringLength
;
1033 COPY_TO_BUFFER( ptr
, [string cString
], stringLength
);
1046 int8_t value
= [searchTextField intValue
];
1048 data
= (char *)realloc( data
, dataSize
+ sizeof(value
) );
1049 ptr
= data
+ dataSize
;
1050 dataSize
+= sizeof(value
);
1052 COPY_TO_BUFFER( ptr
, &value
, sizeof(value
) );
1058 int16_t value
= [searchTextField intValue
];
1060 data
= (char *)realloc( data
, dataSize
+ sizeof(value
) );
1061 ptr
= data
+ dataSize
;
1062 dataSize
+= sizeof(value
);
1064 COPY_TO_BUFFER( ptr
, &value
, sizeof(value
) );
1070 int32_t value
= [searchTextField intValue
];
1072 data
= (char *)realloc( data
, dataSize
+ sizeof(value
) );
1073 ptr
= data
+ dataSize
;
1074 dataSize
+= sizeof(value
);
1076 COPY_TO_BUFFER( ptr
, &value
, sizeof(value
) );
1089 float value
= [searchTextField floatValue
];
1091 data
= (char *)realloc( data
, dataSize
+ sizeof(value
) );
1092 ptr
= data
+ dataSize
;
1093 dataSize
+= sizeof(value
);
1095 COPY_TO_BUFFER( ptr
, &value
, sizeof(value
) );
1101 double value
= [searchTextField doubleValue
];
1103 data
= (char *)realloc( data
, dataSize
+ sizeof(value
) );
1104 ptr
= data
+ dataSize
;
1105 dataSize
+= sizeof(value
);
1107 COPY_TO_BUFFER( ptr
, &value
, sizeof(value
) );
1116 u_int32_t value
= 0;//[searchTextField intValue];
1118 data
= (char *)realloc( data
, dataSize
+ sizeof(value
) );
1119 ptr
= data
+ dataSize
;
1120 dataSize
+= sizeof(value
);
1122 COPY_TO_BUFFER( ptr
, &value
, sizeof(value
) );
1127 [self sendSearch
:data size
:dataSize
];
1130 [self setStatusSearching
];
1135 TCtype type
= [[typePopup selectedItem
] tag
];
1136 TCsize size
= [[sizePopup selectedItem
] tag
];
1138 int i
, addressCount
= [changeSelectedItems count
];
1141 int dataSize
= sizeof(type
) + sizeof(size
) + sizeof(addressCount
) + TCAddressSize
*addressCount
;
1143 data
= (char *)malloc( dataSize
);
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
) );
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
++ )
1154 COPY_TO_BUFFER( ptr
, &((TCaddress
*)searchResults
)[ [[changeSelectedItems objectAtIndex
:i
] intValue
] ], sizeof(TCaddress
) );
1157 // copy the new value.
1166 NSString
*string
= [changeTextField stringValue
];
1167 int stringLength
= [string length
] + 1;
1169 data
= (char *)realloc( data
, dataSize
+ stringLength
);
1170 ptr
= data
+ dataSize
;
1171 dataSize
+= stringLength
;
1173 COPY_TO_BUFFER( ptr
, [string cString
], stringLength
);
1186 int8_t value
= [changeTextField intValue
];
1188 data
= (char *)realloc( data
, dataSize
+ sizeof(value
) );
1189 ptr
= data
+ dataSize
;
1190 dataSize
+= sizeof(value
);
1192 COPY_TO_BUFFER( ptr
, &value
, sizeof(value
) );
1198 int16_t value
= [changeTextField intValue
];
1200 data
= (char *)realloc( data
, dataSize
+ sizeof(value
) );
1201 ptr
= data
+ dataSize
;
1202 dataSize
+= sizeof(value
);
1204 COPY_TO_BUFFER( ptr
, &value
, sizeof(value
) );
1210 int32_t value
= [changeTextField intValue
];
1212 data
= (char *)realloc( data
, dataSize
+ sizeof(value
) );
1213 ptr
= data
+ dataSize
;
1214 dataSize
+= sizeof(value
);
1216 COPY_TO_BUFFER( ptr
, &value
, sizeof(value
) );
1229 float value
= [changeTextField floatValue
];
1231 data
= (char *)realloc( data
, dataSize
+ sizeof(value
) );
1232 ptr
= data
+ dataSize
;
1233 dataSize
+= sizeof(value
);
1235 COPY_TO_BUFFER( ptr
, &value
, sizeof(value
) );
1241 double value
= [changeTextField doubleValue
];
1243 data
= (char *)realloc( data
, dataSize
+ sizeof(value
) );
1244 ptr
= data
+ dataSize
;
1245 dataSize
+= sizeof(value
);
1247 COPY_TO_BUFFER( ptr
, &value
, sizeof(value
) );
1256 u_int32_t value
= 0;//[searchTextField intValue];
1258 data
= (char *)realloc( data
, dataSize
+ sizeof(value
) );
1259 ptr
= data
+ dataSize
;
1260 dataSize
+= sizeof(value
);
1262 COPY_TO_BUFFER( ptr
, &value
, sizeof(value
) );
1267 [self sendChange
:data size
:dataSize
];
1270 [self setStatusChanging
];
1274 - (void)changeSheet
:(NSWindow
*)sheet returned
:(int)returned context
:(void *)context
1276 if ( returned
== 1 )
1278 [changeSelectedItems release
], changeSelectedItems
= [[[addressTable selectedRowEnumerator
] allObjects
] retain
];
1280 if ( [recurringChangeButton state
] == NSOnState
)
1282 float seconds
= [changeSecondsCombo floatValue
];
1284 [self setStatusChangingContinuously
];
1288 changeTimer
= [[NSTimer scheduledTimerWithTimeInterval
:seconds target
:self selector
:@selector(changeTimer
:) userInfo
:nil repeats
:YES
] retain
];
1298 - (void)changeTimer
:(NSTimer
*)timer
1304 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1305 %%%%%%%%%%%%%%%%%%%%%% Cheat Window Interface
1306 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
1309 - (IBAction
)typePopup
:(id)sender
1311 switch ( [typePopup indexOfSelectedItem
] )
1314 [sizePopup setMenu
:stringSizeMenu
];
1319 [sizePopup setMenu
:integerSizeMenu
];
1323 [sizePopup setMenu
:decimalSizeMenu
];
1327 [self updateSearchBoxes
];
1328 [self updateSearchButton
];
1329 [self updateDescriptionText
];
1332 - (IBAction
)sizePopup
:(id)sender
1334 [self updateDescriptionText
];
1338 - (IBAction
)searchButton
:(id)sender
1340 /*if ( [searchTextField intValue] == 0 )
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 )
1351 - (IBAction
)clearSearchButton
:(id)sender
1355 [self setStatusConnected
];
1356 [self setStatusText
:@
"Search Cleared" duration
:1.5];
1358 [self sendClearSearch
];
1362 - (IBAction
)changeButton
:(id)sender
1364 [changeTimer invalidate
];
1365 [changeTimer release
], changeTimer
= nil;
1367 if ( status
== STATUS_CHANGING_CONTINUOUSLY
)
1369 [changeSelectedItems release
], changeSelectedItems
= nil;
1371 [self setStatusCheating
];
1373 else if ( status
== STATUS_CHEATING
)
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];
1383 - (IBAction
)serverMenuItem
:(id)sender
1385 NSData
*data
= [[[serverList objectAtIndex
:[sender tag
]] addresses
] objectAtIndex
:0];
1386 /* struct sockaddr_in addr;
1388 [data getBytes:&addr];*/
1390 [self connectToServer
:data name
:[serverPopup titleOfSelectedItem
]];
1393 - (IBAction
)serverMenuDisconnect
:(id)sender
1398 - (IBAction
)serverMenuLocal
:(id)sender
1400 [self connectToLocal
];
1403 - (IBAction
)processMenuItem
:(id)sender
1405 targetPID
= [sender tag
];
1407 [self sendSetTargetPID
:targetPID
];
1409 [self setStatusText
:[NSString stringWithFormat
:@
"PID: %i", targetPID
] duration
:0];
1413 - (IBAction
)pauseButton
:(id)sender
1415 [self sendPauseTarget
];
1419 - (void)undoMenu
:(id)sender
1421 if ( undoCount
== 1 )
1423 [self clearSearchButton
:self];
1427 [self sendUndoRequest
];
1429 [self setStatusUndoing
];
1433 - (void)redoMenu
:(id)sender
1435 [self sendRedoRequest
];
1437 [self setStatusRedoing
];
1440 - (BOOL)respondsToSelector
:(SEL)aSelector
1442 if ( aSelector
== @selector(undoMenu
:) )
1444 if ( status
== STATUS_CHEATING
&& undoCount
> 0 )
1454 if ( aSelector
== @selector(redoMenu
:) )
1456 if ( status
== STATUS_CHEATING
&& redoCount
> 0 )
1466 return [super respondsToSelector
:aSelector
];
1470 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1471 %%%%%%%%%%%%%%%%%%%%%% Change Sheet Interface
1472 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
1475 - (IBAction
)cancelButton
:(id)sender
1477 [changeSheet orderOut
:sender
];
1478 [NSApp endSheet
:changeSheet returnCode
:0];
1479 //[NSApp stopModal];
1482 - (IBAction
)okButton
:(id)sender
1484 [changeSheet orderOut
:sender
];
1485 [NSApp endSheet
:changeSheet returnCode
:1];
1486 //[NSApp stopModal];
1490 - (IBAction
)recurringChangeButton
:(id)sender
1492 if ( [recurringChangeButton state
] == NSOnState
)
1494 [changeSecondsCombo setEnabled
:YES
];
1498 [changeSecondsCombo setEnabled
:NO
];
1503 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1504 %%%%%%%%%%%%%%%%%%%%%% Cleaning Up
1505 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
1515 [changeTimer invalidate
];
1516 [changeTimer release
], changeTimer
= nil;
1518 [self destroyResults
];
1519 [addressTable reloadData
];
1522 - (void)destroyResults
1524 if ( searchResultsAmount
> 0 )
1526 free( searchResults
);
1528 searchResultsAmount
= 0;
1535 [[NSNotificationCenter defaultCenter
] removeObserver
:self];
1539 // clean up status timer stuff
1540 [savedStatusColor release
];
1541 [savedStatusText release
];
1542 [statusTextTimer invalidate
];
1543 [statusTextTimer release
];
1545 [changeTimer invalidate
];
1546 [changeTimer release
];
1548 [self destroyResults
];
1550 [changeSelectedItems release
];
1552 [serverList release
];
1553 [addressList release
];
1559 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1560 %%%%%%%%%%%%%%%%%%%%%% TCListener Notifications
1561 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
1564 - (void)listenerStarted
:(NSNotification
*)note
1566 if ( !everConnected
)
1568 [self connectToLocal
];
1572 - (void)listenerStopped
:(NSNotification
*)note
1578 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1579 %%%%%%%%%%%%%%%%%%%%%% TCWindowsOnTopChanged Notification
1580 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
1583 - (void)windowsOnTopChanged
:(NSNotification
*)note
1585 if ( TCGlobalWindowsOnTop
)
1587 [cheatWindow setLevel
:NSPopUpMenuWindowLevel
];
1591 [cheatWindow setLevel
:NSNormalWindowLevel
];
1596 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1597 %%%%%%%%%%%%%%%%%%%%%% TCWindowsOnTopChanged Notification
1598 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
1601 - (void)handleErrorMessage
:(NSString
*)msg fatal
:(BOOL)fatal
1603 NSLog( @
"error received" );
1604 // close the change sheet if it's open.
1605 if ( [cheatWindow attachedSheet
] )
1607 [changeSheet orderOut
:self];
1608 [NSApp endSheet
:changeSheet returnCode
:0];
1612 NSBeginAlertSheet( fatal? @
"Fatal Error":@
"Error", @
"OK", nil, nil, cheatWindow
, nil, nil, nil, 0, msg
);
1616 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1617 %%%%%%%%%%%%%%%%%%%%%% Cheat Window Delegate
1618 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
1621 - (BOOL)windowShouldClose
:(id)sender
1623 if ( sender
== cheatWindow
&& ( status
== STATUS_SEARCHING || status
== STATUS_CHANGING
) )
1633 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1634 %%%%%%%%%%%%%%%%%%%%%% ClientDelegate
1635 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
1638 - (void)clientConnectedWithSocket
:(int)sock name
:(NSString
*)name
1640 // the client is reporting that a connection has been made.
1643 [self sendProcessListRequest
];
1645 [serverPopup selectItemWithTitle
:name
];
1647 [self setStatusConnected
];
1650 - (void)clientDisconnected
1652 // if there is a pending connection, connect now.
1653 if ( waitingToConnect
)
1655 waitingToConnect
= NO
;
1656 connection
= [[CheatClient clientWithDelegate
:self server
:connectionAddress name
:connectionName
] retain
];
1658 // if our connection variable is still valid, we were disconnected unexpectedly.
1659 else if ( connection
)
1662 NSBeginAlertSheet( @
"Network Failure", @
"OK", nil, nil, cheatWindow
, nil, nil, nil, 0, @
"The server has disconnected you." );
1666 - (void)clientError
:(NSString
*)error message
:(NSString
*)message
1668 NSBeginAlertSheet( error
, @
"OK", nil, nil, cheatWindow
, nil, nil, nil, 0, message
);
1672 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1673 %%%%%%%%%%%%%%%%%%%%%% NSToolbar Delegate
1674 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
1677 *** A toolbar is no longer used, but the code still remains for possible future use. ***
1679 - (NSToolbarItem *)toolbar:(NSToolbar *)toolbar itemForItemIdentifier:(NSString *)itemIdentifier willBeInsertedIntoToolbar:(BOOL)flag
1681 NSToolbarItem *item = [[NSToolbarItem alloc] initWithItemIdentifier:itemIdentifier];
1683 if ( [itemIdentifier isEqualToString:@"Disconnect"] )
1685 disconnectButton = item;
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."];
1693 else if ( [itemIdentifier isEqualToString:@"ServerPopup"] )
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:@""];
1699 [menu setSubmenu:[serverPopup menu]];
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]];
1713 - (NSArray *)toolbarAllowedItemIdentifiers:(NSToolbar*)toolbar
1715 return [NSArray arrayWithObjects:NSToolbarSeparatorItemIdentifier,
1716 NSToolbarSpaceItemIdentifier,
1717 NSToolbarFlexibleSpaceItemIdentifier,
1718 NSToolbarCustomizeToolbarItemIdentifier,
1719 @"Disconnect", @"ServerPopup", nil];
1722 - (NSArray *)toolbarDefaultItemIdentifiers:(NSToolbar*)toolbar
1724 return [NSArray arrayWithObjects:@"Disconnect", @"ServerPopup", nil];
1728 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1729 %%%%%%%%%%%%%%%%%%%%%% NSTableView Data Source/Delegate
1730 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
1733 - (void)controlTextDidChange
:(NSNotification
*)aNotification
1735 [self updateSearchButton
];
1739 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1740 %%%%%%%%%%%%%%%%%%%%%% NSTableView Data Source/Delegate
1741 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
1744 - (int)numberOfRowsInTableView
:(NSTableView
*)table
1746 return (searchResultsAmount
<= maxSearchResultsAmount
) ? searchResultsAmount
: maxSearchResultsAmount
;
1749 - (id)tableView
:(NSTableView
*)table objectValueForTableColumn
:(NSTableColumn
*)column row
:(int)row
1751 return [NSString stringWithFormat
:@
"%0.8X", ((TCaddress
*)searchResults
)[row
]];
1754 - (void)tableView
:(NSTableView
*) setObjectValue
:(id)object forTableColumn
:(NSTableColumn
*)column row
:(int)row
1759 - (void)tableViewSelectionDidChange
:(NSNotification
*)note
1761 if ( [addressTable selectedRow
] != -1 )
1763 addressSelected
= YES
;
1767 addressSelected
= NO
;
1770 [self updateChangeButton
];
1774 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1775 %%%%%%%%%%%%%%%%%%%%%% Global Browser Notifications
1776 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
1779 - (void)browserServerFound
:(NSNotification
*)note
1781 NSNetService
*service
= (NSNetService
*)[note object
];
1783 NSString
*name
= [service name
];
1784 int tag
= [serverList count
] - 1;
1787 NSLog( @
"server found" );
1789 if ( [serverMenu itemWithTitle
:name
] == nil )
1791 item
= [[NSMenuItem alloc
] initWithTitle
:[service name
] action
:@selector(serverMenuItem
:) keyEquivalent
:@
""];
1795 // if this is the first server, add a divider.
1796 if ( [serverMenu numberOfItems
] <= 2 )
1798 [serverMenu addItem
:[NSMenuItem separatorItem
]];
1801 //[serverList addObject:service];
1802 [serverMenu addItem
:[item autorelease
]];
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
] )
1808 [serverPopup selectItemWithTitle
:[service name
]];
1813 - (void)browserServerLost
:(NSNotification
*)note
1815 NSNetService
*service
= (NSNetService
*)[note object
];
1816 NSString
*name
= [service name
];
1818 int i
, top
= [serverMenu numberOfItems
];
1820 for ( i
= [serverMenu indexOfItemWithTitle
:name
] + 1; i
< top
; i
++ )
1822 [[serverMenu itemWithTitle
:name
] setTag
:[[serverMenu itemWithTitle
:name
] tag
] - 1];
1825 [serverMenu removeAllItemsWithTitle
:name
];
1827 // if this is the last broadcast server, take away the divider.
1828 if ( [serverMenu numberOfItems
] == 3 )
1830 [serverMenu removeItemAtIndex
:2];
1838 // Internal Functions
1839 void TCPlaySound( NSString
*name
)
1841 if ( TCGlobalPlaySounds
)
1843 [[NSSound soundNamed
:name
] play
];