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 [statusBar stopAnimation
:self];
263 [addressTable setEnabled
:NO
];
264 [changeButton setTitle
:@
"Change..."];
265 [changeButton setEnabled
:NO
];
267 [[serverMenu itemAtIndex
:0] setTitle
:@
"Not Connected"];
270 - (void)setStatusConnected
273 status
= STATUS_CONNECTED
;
275 [serverPopup setEnabled
:YES
];
276 [self updatePauseButton
];
277 [pauseButton setEnabled
:YES
];
278 [processPopup setEnabled
:YES
];
279 [typePopup setEnabled
:YES
];
280 [sizePopup setEnabled
:YES
];
281 [self updateSearchBoxes
];
282 [self updateSearchButton
];
283 [clearSearchButton setEnabled
:NO
];
284 [self setStatusText
:@
"Connected" duration
:0];
285 [statusBar stopAnimation
:self];
286 [addressTable setEnabled
:NO
];
287 [changeButton setTitle
:@
"Change..."];
288 [changeButton setEnabled
:NO
];
290 [[serverMenu itemAtIndex
:0] setTitle
:@
"Disconnect"];
293 - (void)setStatusCheating
296 status
= STATUS_CHEATING
;
298 [serverPopup setEnabled
:YES
];
299 [self updatePauseButton
];
300 [pauseButton setEnabled
:YES
];
301 [processPopup setEnabled
:NO
];
302 [typePopup setEnabled
:NO
];
303 [sizePopup setEnabled
:NO
];
304 [self updateSearchBoxes
];
305 [self updateSearchButton
];
306 [clearSearchButton setEnabled
:YES
];
307 if ( searchResultsAmount
< TCMaxSearchResults
)
309 if ( searchResultsAmount
== 1 )
311 [self setStatusText
:[NSString stringWithFormat
:@
"Results: %i", searchResultsAmount
] duration
:0 color
:[NSColor colorWithCalibratedRed
:0.0f green
:0.5f blue
:0.0f alpha
:1.0f
]];
313 else if ( searchResultsAmount
== 0 )
315 [self setStatusText
:[NSString stringWithFormat
:@
"Results: %i", searchResultsAmount
] duration
:0 color
:[NSColor colorWithCalibratedRed
:0.5f green
:0.0f blue
:0.0f alpha
:1.0f
]];
319 [self setStatusText
:[NSString stringWithFormat
:@
"Results: %i", searchResultsAmount
] duration
:0];
324 [self setStatusText
:[NSString stringWithFormat
:@
"Results: >%i", TCMaxSearchResults
] duration
:0];
326 [statusBar stopAnimation
:self];
327 [addressTable setEnabled
:YES
];
328 [changeButton setTitle
:@
"Change..."];
329 [self updateChangeButton
];
331 [[serverMenu itemAtIndex
:0] setTitle
:@
"Disconnect"];
334 - (void)setStatusSearching
337 status
= STATUS_SEARCHING
;
339 [serverPopup setEnabled
:NO
];
340 [self updatePauseButton
];
341 [pauseButton setEnabled
:NO
];
342 [processPopup setEnabled
:NO
];
343 [typePopup setEnabled
:NO
];
344 [sizePopup setEnabled
:NO
];
345 [searchTextField setEnabled
:NO
];
346 [searchRadioMatrix setEnabled
:NO
];
347 [searchButton setEnabled
:NO
];
348 [clearSearchButton setEnabled
:NO
];
349 [self setStatusText
:@
"Searching..." duration
:0];
350 [statusBar startAnimation
:self];
351 [addressTable setEnabled
:NO
];
352 [changeButton setTitle
:@
"Change..."];
353 [changeButton setEnabled
:NO
];
355 [[serverMenu itemAtIndex
:0] setTitle
:@
"Disconnect"];
358 - (void)setStatusChanging
361 status
= STATUS_CHANGING
;
363 if ( lastStatus
!= STATUS_CHANGING_CONTINUOUSLY
)
365 [serverPopup setEnabled
:NO
];
366 [self updatePauseButton
];
367 [pauseButton setEnabled
:NO
];
368 [processPopup setEnabled
:NO
];
369 [typePopup setEnabled
:NO
];
370 [sizePopup setEnabled
:NO
];
371 [searchTextField setEnabled
:NO
];
372 [searchRadioMatrix setEnabled
:NO
];
373 [searchButton setEnabled
:NO
];
374 [clearSearchButton setEnabled
:NO
];
375 [statusBar startAnimation
:self];
376 [addressTable setEnabled
:NO
];
377 [changeButton setEnabled
:NO
];
379 [[serverMenu itemAtIndex
:0] setTitle
:@
"Disconnect"];
383 - (void)setStatusChangingLater
386 status
= STATUS_CHANGING_LATER
;
388 [serverPopup setEnabled
:NO
];
389 [self updatePauseButton
];
390 [pauseButton setEnabled
:NO
];
391 [processPopup setEnabled
:NO
];
392 [typePopup setEnabled
:NO
];
393 [sizePopup setEnabled
:NO
];
394 [searchTextField setEnabled
:NO
];
395 [searchRadioMatrix setEnabled
:NO
];
396 [searchButton setEnabled
:NO
];
397 [clearSearchButton setEnabled
:NO
];
398 [self setStatusText
:@
"Changing Later..." duration
:0];
399 [statusBar startAnimation
:self];
400 [addressTable setEnabled
:NO
];
401 [changeButton setTitle
:@
"Cancel Change"];
402 [changeButton setEnabled
:YES
];
404 [[serverMenu itemAtIndex
:0] setTitle
:@
"Disconnect"];
407 - (void)setStatusChangingContinuously
410 status
= STATUS_CHANGING_CONTINUOUSLY
;
412 [serverPopup setEnabled
:NO
];
413 [self updatePauseButton
];
414 [pauseButton setEnabled
:YES
];
415 [processPopup setEnabled
:NO
];
416 [typePopup setEnabled
:NO
];
417 [sizePopup setEnabled
:NO
];
418 [searchTextField setEnabled
:NO
];
419 [searchRadioMatrix setEnabled
:NO
];
420 [searchButton setEnabled
:NO
];
421 [clearSearchButton setEnabled
:NO
];
422 [self setStatusText
:@
"Repeating Change..." duration
:0];
423 [statusBar startAnimation
:self];
424 [addressTable setEnabled
:NO
];
425 [changeButton setTitle
:@
"Stop Change"];
426 [changeButton setEnabled
:YES
];
428 [[serverMenu itemAtIndex
:0] setTitle
:@
"Disconnect"];
431 - (void)setStatusUndoing
434 status
= STATUS_UNDOING
;
436 [serverPopup setEnabled
:NO
];
437 [self updatePauseButton
];
438 [pauseButton setEnabled
:NO
];
439 [processPopup setEnabled
:NO
];
440 [typePopup setEnabled
:NO
];
441 [sizePopup setEnabled
:NO
];
442 [searchTextField setEnabled
:NO
];
443 [searchRadioMatrix setEnabled
:NO
];
444 [searchButton setEnabled
:NO
];
445 [clearSearchButton setEnabled
:NO
];
446 [self setStatusText
:@
"Undoing..." duration
:0];
447 [statusBar startAnimation
:self];
448 [addressTable setEnabled
:NO
];
449 [changeButton setTitle
:@
"Change..."];
450 [changeButton setEnabled
:NO
];
452 [[serverMenu itemAtIndex
:0] setTitle
:@
"Disconnect"];
455 - (void)setStatusRedoing
458 status
= STATUS_REDOING
;
460 [serverPopup setEnabled
:NO
];
461 [self updatePauseButton
];
462 [pauseButton setEnabled
:NO
];
463 [processPopup setEnabled
:NO
];
464 [typePopup setEnabled
:NO
];
465 [sizePopup setEnabled
:NO
];
466 [searchTextField setEnabled
:NO
];
467 [searchRadioMatrix setEnabled
:NO
];
468 [searchButton setEnabled
:NO
];
469 [clearSearchButton setEnabled
:NO
];
470 [self setStatusText
:@
"Redoing..." duration
:0];
471 [statusBar startAnimation
:self];
472 [addressTable setEnabled
:NO
];
473 [changeButton setTitle
:@
"Change..."];
474 [changeButton setEnabled
:NO
];
476 [[serverMenu itemAtIndex
:0] setTitle
:@
"Disconnect"];
479 - (void)setStatusToLast
481 switch ( lastStatus
)
483 case STATUS_DISCONNECTED
:
484 [self setStatusDisconnected
];
487 case STATUS_CONNECTED
:
488 [self setStatusConnected
];
491 case STATUS_CHEATING
:
492 [self setStatusCheating
];
495 case STATUS_SEARCHING
:
496 [self setStatusSearching
];
499 case STATUS_CHANGING
:
500 [self setStatusChanging
];
503 case STATUS_CHANGING_LATER
:
504 [self setStatusChangingLater
];
507 case STATUS_CHANGING_CONTINUOUSLY
:
508 [self setStatusChangingContinuously
];
512 [self setStatusUndoing
];
516 [self setStatusRedoing
];
521 - (void)setStatusText
:(NSString
*)msg duration
:(NSTimeInterval
)seconds
523 [self setStatusText
:msg duration
:seconds color
:[NSColor blackColor
]];
526 - (void)setStatusText
:(NSString
*)msg duration
:(NSTimeInterval
)seconds color
:(NSColor
*)color
528 if ( statusTextTimer
)
530 [statusTextTimer invalidate
];
531 [statusTextTimer release
], statusTextTimer
= nil;
535 [savedStatusText release
];
536 [savedStatusColor release
];
537 savedStatusText
= [[statusText stringValue
] retain
];
538 savedStatusColor
= [[statusText textColor
] retain
];
541 [statusText setTextColor
:color
];
542 [statusText setStringValue
:msg
];
544 if ( seconds
!= 0.0 )
546 statusTextTimer
= [[NSTimer scheduledTimerWithTimeInterval
:seconds target
:self selector
:@selector(statusTextTimer
:) userInfo
:nil repeats
:NO
] retain
];
550 - (void)statusTextTimer
:(NSTimer
*)timer
552 [statusText setTextColor
:savedStatusColor
];
553 [statusText setStringValue
:savedStatusText
];
555 [savedStatusColor release
], savedStatusColor
= nil;
556 [savedStatusText release
], savedStatusText
= nil;
557 [statusTextTimer invalidate
];
558 [statusTextTimer release
], statusTextTimer
= nil;
562 - (void)connectToLocal
564 NSString
*localName
= @
"Local"; //[NSString stringWithFormat:@"%@ (local)", TCGlobalBroadcastName];
566 // depending on how the listener is listening, we need to use different means to connect to local
567 if ( TCGlobalListening
)
569 if ( TCGlobalAllowRemote
)
571 struct sockaddr_in addr
;
573 addr.sin_family
= AF_INET
;
574 addr.sin_port
= htonl( TCGlobalListenPort
);
575 addr.sin_addr.s_addr
= INADDR_ANY
;
577 [self connectToServer
:[NSData dataWithBytes
:&addr length
:sizeof(addr
)] name
:localName
];
581 struct sockaddr_un addr
;
583 addr.sun_family
= AF_UNIX
;
584 strncpy( addr.sun_path
, TCDefaultListenPath
, 103 );
586 [self connectToServer
:[NSData dataWithBytes
:&addr length
:sizeof(addr
)] name
:localName
];
591 - (void)connectToServer
:(NSData
*)addr name
:(NSString
*)name
599 waitingToConnect
= YES
;
600 connectionAddress
= [addr retain
];
601 connectionName
= [name retain
];
605 connection
= [[CheatClient clientWithDelegate
:self server
:addr name
:name
] retain
];
606 connectionAddress
= [addr retain
];
607 connectionName
= [name retain
];
610 [self setStatusConnected
];
617 [connection release
], connection
= nil;
622 [connectionAddress release
], connectionAddress
= nil;
623 [connectionName release
], connectionName
= nil;
625 [processMenu removeAllItems
];
627 [serverPopup selectItemAtIndex
:0];
628 [self setStatusDisconnected
];
633 - (void)sendProcessListRequest
636 int length
= sizeof(header
);
638 header.checksum
= RandomChecksum();
642 if ( SendBuffer( sockfd
, (char *)(&header
), &length
) == -1 || length
!= sizeof(header
) )
644 NSLog( @
"sendProcessListRequest failed on socket %i", sockfd
);
648 - (void)sendClearSearch
651 int length
= sizeof(header
);
653 header.checksum
= RandomChecksum();
657 if ( SendBuffer( sockfd
, (char *)(&header
), &length
) == -1 || length
!= sizeof(header
) )
659 NSLog( @
"sendClearSearch failed on socket %i", sockfd
);
663 - (void)sendSearch
:(char const *)data size
:(int)size
666 int length
= sizeof(header
) + size
;
667 int lengthAfter
= length
;
671 header.checksum
= RandomChecksum();
675 if ( (buffer
= (char *)malloc( length
)) == NULL
)
677 NSLog( @
"sendSearch:size: failed" );
682 COPY_TO_BUFFER( ptr
, &header
, sizeof(header
) );
683 COPY_TO_BUFFER( ptr
, data
, size
);
685 if ( SendBuffer( sockfd
, buffer
, &lengthAfter
) == -1 || lengthAfter
!= length
)
687 NSLog( @
"sendSearch:size: failed" );
693 - (void)sendChange
:(char const *)data size
:(int)size
696 int length
= sizeof(header
) + size
;
697 int lengthAfter
= length
;
701 header.checksum
= RandomChecksum();
705 if ( (buffer
= (char *)malloc( length
)) == NULL
)
707 NSLog( @
"sendChange:size: failed" );
712 COPY_TO_BUFFER( ptr
, &header
, sizeof(header
) );
713 COPY_TO_BUFFER( ptr
, data
, size
);
715 if ( SendBuffer( sockfd
, buffer
, &lengthAfter
) == -1 || lengthAfter
!= length
)
717 NSLog( @
"sendChange:size: failed" );
723 - (void)sendPauseTarget
;
726 int length
= sizeof(header
);
728 header.checksum
= RandomChecksum();
729 header.function
= 10;
732 if ( SendBuffer( sockfd
, (char *)(&header
), &length
) == -1 || length
!= sizeof(header
) )
734 NSLog( @
"sendPauseTarget failed" );
738 - (void)sendVariableValueRequest
743 - (void)sendUndoRequest
746 int length
= sizeof(header
);
748 header.checksum
= RandomChecksum();
749 header.function
= 14;
752 if ( SendBuffer( sockfd
, (char *)(&header
), &length
) == -1 || length
!= sizeof(header
) )
754 NSLog( @
"sendUndoRequest failed" );
758 - (void)sendRedoRequest
761 int length
= sizeof(header
);
763 header.checksum
= RandomChecksum();
764 header.function
= 16;
767 if ( SendBuffer( sockfd
, (char *)(&header
), &length
) == -1 || length
!= sizeof(header
) )
769 NSLog( @
"sendRedoRequest failed" );
773 - (void)sendSetTargetPID
:(int)pid
776 int length
= sizeof(header
) + sizeof(u_int32_t
);
777 int lengthAfter
= length
;
779 u_int32_t tarPID
= (u_int32_t
)pid
;
783 header.checksum
= RandomChecksum();
784 header.function
= 18;
785 header.size
= sizeof(u_int32_t
);
787 if ( (buffer
= (char *)malloc( length
)) == NULL
)
789 NSLog( @
"sendSetTargetPID: failed" );
794 COPY_TO_BUFFER( ptr
, &header
, sizeof(header
) );
795 COPY_TO_BUFFER( ptr
, &tarPID
, sizeof(tarPID
) );
797 if ( SendBuffer( sockfd
, buffer
, &lengthAfter
) == -1 || lengthAfter
!= length
)
799 NSLog( @
"sendSetTargetPID: failed" );
806 - (void)receivedProcessList
:(NSData
*)data
809 u_int32_t processCount
= 0;
811 char *ptr
= (char *)[data bytes
];
814 COPY_FROM_BUFFER( &processCount
, ptr
, sizeof(processCount
) );
816 max
= (int)processCount
;
818 for ( i
= 0; i
< max
; i
++ )
823 COPY_FROM_BUFFER( &pid
, ptr
, sizeof(pid
) );
824 name
= [NSString stringWithCString
:ptr
], ptr
+= [name length
] + 1;
826 item
= [[NSMenuItem alloc
] initWithTitle
:name action
:@selector(processMenuItem
:) keyEquivalent
:@
""];
827 [item setTag
:(int)pid
];
829 [processMenu addItem
:[item autorelease
]];
833 - (void)receivedSearchFinished
835 if ( searchResultsAmount
== 1 )
837 TCPlaySound( @
"Submarine" );
839 else if ( searchResultsAmount
== 0 )
841 TCPlaySound( @
"Basso" );
844 [self setStatusToLast
];
845 //[self setStatusText:@"Search Finished" duration:1.5];
846 [cheatWindow makeFirstResponder
:searchTextField
];
849 - (void)receivedVariableList
:(NSData
*)data
851 char *ptr
= (char *)[data bytes
];
853 [self destroyResults
];
855 COPY_FROM_BUFFER( &searchResultsAmount
, ptr
, sizeof(searchResultsAmount
) );
857 if ( searchResultsAmount
> 0 )
859 int memSize
= TCAddressSize
*searchResultsAmount
;
861 if ( (searchResults
= (TCaddress
*)malloc( memSize
)) == NULL
)
863 NSLog( @
"receivedVariableList failed: malloc failed" );
864 searchResultsAmount
= 0;
868 COPY_FROM_BUFFER( searchResults
, ptr
, memSize
);
871 [addressTable reloadData
];
874 - (void)receivedChangeFinished
876 [self setStatusToLast
];
878 if ( status
== STATUS_CHANGING_CONTINUOUSLY
)
880 [self setStatusText
:@
"Change Occured" duration
:1.5];
884 TCPlaySound( @
"Tink" );
888 - (void)receivedError
:(NSData
*)data
893 char *ptr
= (char *)[data bytes
];
895 COPY_FROM_BUFFER( &fatal
, ptr
, sizeof(fatal
) );
897 msg
= [NSString stringWithCString
:ptr
];
900 [self handleErrorMessage
:msg fatal
:fatal
];
903 - (void)receivedUndoFinished
905 [self setStatusToLast
];
908 - (void)receivedRedoFinished
910 [self setStatusToLast
];
913 - (void)receivedUndoRedoStatus
:(NSData
*)data
915 char *ptr
= (char *)[data bytes
];
917 COPY_FROM_BUFFER( &undoCount
, ptr
, sizeof(undoCount
) );
918 COPY_FROM_BUFFER( &redoCount
, ptr
, sizeof(redoCount
) );
920 NSLog( @
"UNDO: %i, REDO: %i", undoCount
, redoCount
);
923 - (void)receivedAppLaunched
:(NSData
*)data
927 char *ptr
= (char *)[data bytes
];
932 COPY_FROM_BUFFER( &pid
, ptr
, sizeof(pid
) );
933 name
= [NSString stringWithCString
:ptr
], ptr
+= [name length
] + 1;
935 item
= [[NSMenuItem alloc
] initWithTitle
:name action
:@selector(processMenuItem
:) keyEquivalent
:@
""];
936 [item setTag
:(int)pid
];
938 [processMenu addItem
:[item autorelease
]];
941 - (void)receivedAppQuit
:(NSData
*)data
945 char *ptr
= (char *)[data bytes
];
947 COPY_FROM_BUFFER( &pid
, ptr
, sizeof(pid
) );
949 [processMenu removeItemWithTag
:pid
];
952 - (void)receivedTargetQuit
955 [self sendClearSearch
];
957 // tell the server that the first app is now the target.
958 targetPID
= [[processMenu itemAtIndex
:0] tag
];
959 [self sendSetTargetPID
:targetPID
];
962 [self handleErrorMessage
:@
"The application that was being cheated has quit." fatal
:NO
];
964 [self setStatusConnected
];
967 - (void)receivedPauseFinished
:(NSData
*)data
969 char *ptr
= (char *)[data bytes
];
971 COPY_FROM_BUFFER( &targetPaused
, ptr
, sizeof(targetPaused
) );
973 [self updatePauseButton
];
977 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
978 %%%%%%%%%%%%%%%%%%%%%% Searching & Changing
979 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
984 TCtype type
= [[typePopup selectedItem
] tag
];
985 TCsize size
= [[sizePopup selectedItem
] tag
];
988 int dataSize
= sizeof(type
) + sizeof(size
);
990 data
= (char *)malloc( dataSize
);
993 // copy the size and type of the variable.
994 COPY_TO_BUFFER( ptr
, &type
, sizeof(type
) );
995 COPY_TO_BUFFER( ptr
, &size
, sizeof(size
) );
997 NSLog( @
"type: %i, size: %i", type
, size
);
999 // switch to cheating mode if this is the first search.
1000 if ( status
== STATUS_CONNECTED
)
1002 [self setStatusCheating
];
1005 // copy the value to search for.
1014 NSString
*string
= [searchTextField stringValue
];
1015 int stringLength
= [string length
] + 1;
1017 data
= (char *)realloc( data
, dataSize
+ stringLength
);
1018 ptr
= data
+ dataSize
;
1019 dataSize
+= stringLength
;
1021 COPY_TO_BUFFER( ptr
, [string cString
], stringLength
);
1034 int8_t value
= [searchTextField intValue
];
1036 data
= (char *)realloc( data
, dataSize
+ sizeof(value
) );
1037 ptr
= data
+ dataSize
;
1038 dataSize
+= sizeof(value
);
1040 COPY_TO_BUFFER( ptr
, &value
, sizeof(value
) );
1046 int16_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 int32_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
) );
1077 float value
= [searchTextField floatValue
];
1079 data
= (char *)realloc( data
, dataSize
+ sizeof(value
) );
1080 ptr
= data
+ dataSize
;
1081 dataSize
+= sizeof(value
);
1083 COPY_TO_BUFFER( ptr
, &value
, sizeof(value
) );
1089 double value
= [searchTextField doubleValue
];
1091 data
= (char *)realloc( data
, dataSize
+ sizeof(value
) );
1092 ptr
= data
+ dataSize
;
1093 dataSize
+= sizeof(value
);
1095 COPY_TO_BUFFER( ptr
, &value
, sizeof(value
) );
1104 u_int32_t value
= 0;//[searchTextField intValue];
1106 data
= (char *)realloc( data
, dataSize
+ sizeof(value
) );
1107 ptr
= data
+ dataSize
;
1108 dataSize
+= sizeof(value
);
1110 COPY_TO_BUFFER( ptr
, &value
, sizeof(value
) );
1115 [self sendSearch
:data size
:dataSize
];
1118 [self setStatusSearching
];
1123 TCtype type
= [[typePopup selectedItem
] tag
];
1124 TCsize size
= [[sizePopup selectedItem
] tag
];
1126 int i
, addressCount
= [changeSelectedItems count
];
1129 int dataSize
= sizeof(type
) + sizeof(size
) + sizeof(addressCount
) + TCAddressSize
*addressCount
;
1131 data
= (char *)malloc( dataSize
);
1134 // copy the size and type of the variable.
1135 COPY_TO_BUFFER( ptr
, &type
, sizeof(type
) );
1136 COPY_TO_BUFFER( ptr
, &size
, sizeof(size
) );
1138 // copy the amount and the list of addresses to change.
1139 COPY_TO_BUFFER( ptr
, &addressCount
, sizeof(addressCount
) );
1140 for ( i
= 0; i
< addressCount
; i
++ )
1142 COPY_TO_BUFFER( ptr
, &((TCaddress
*)searchResults
)[ [[changeSelectedItems objectAtIndex
:i
] intValue
] ], sizeof(TCaddress
) );
1145 // copy the new value.
1154 NSString
*string
= [changeTextField stringValue
];
1155 int stringLength
= [string length
] + 1;
1157 data
= (char *)realloc( data
, dataSize
+ stringLength
);
1158 ptr
= data
+ dataSize
;
1159 dataSize
+= stringLength
;
1161 COPY_TO_BUFFER( ptr
, [string cString
], stringLength
);
1174 int8_t value
= [changeTextField intValue
];
1176 data
= (char *)realloc( data
, dataSize
+ sizeof(value
) );
1177 ptr
= data
+ dataSize
;
1178 dataSize
+= sizeof(value
);
1180 COPY_TO_BUFFER( ptr
, &value
, sizeof(value
) );
1186 int16_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 int32_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
) );
1217 float value
= [changeTextField floatValue
];
1219 data
= (char *)realloc( data
, dataSize
+ sizeof(value
) );
1220 ptr
= data
+ dataSize
;
1221 dataSize
+= sizeof(value
);
1223 COPY_TO_BUFFER( ptr
, &value
, sizeof(value
) );
1229 double value
= [changeTextField doubleValue
];
1231 data
= (char *)realloc( data
, dataSize
+ sizeof(value
) );
1232 ptr
= data
+ dataSize
;
1233 dataSize
+= sizeof(value
);
1235 COPY_TO_BUFFER( ptr
, &value
, sizeof(value
) );
1244 u_int32_t value
= 0;//[searchTextField intValue];
1246 data
= (char *)realloc( data
, dataSize
+ sizeof(value
) );
1247 ptr
= data
+ dataSize
;
1248 dataSize
+= sizeof(value
);
1250 COPY_TO_BUFFER( ptr
, &value
, sizeof(value
) );
1255 [self sendChange
:data size
:dataSize
];
1258 [self setStatusChanging
];
1262 - (void)changeSheet
:(NSWindow
*)sheet returned
:(int)returned context
:(void *)context
1264 if ( returned
== 1 )
1266 [changeSelectedItems release
], changeSelectedItems
= [[[addressTable selectedRowEnumerator
] allObjects
] retain
];
1268 if ( [recurringChangeButton state
] == NSOnState
)
1270 float seconds
= [changeSecondsCombo floatValue
];
1272 [self setStatusChangingContinuously
];
1276 changeTimer
= [[NSTimer scheduledTimerWithTimeInterval
:seconds target
:self selector
:@selector(changeTimer
:) userInfo
:nil repeats
:YES
] retain
];
1286 - (void)changeTimer
:(NSTimer
*)timer
1292 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1293 %%%%%%%%%%%%%%%%%%%%%% Cheat Window Interface
1294 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
1297 - (IBAction
)typePopup
:(id)sender
1299 switch ( [typePopup indexOfSelectedItem
] )
1302 [sizePopup setMenu
:stringSizeMenu
];
1307 [sizePopup setMenu
:integerSizeMenu
];
1311 [sizePopup setMenu
:decimalSizeMenu
];
1315 [self updateSearchBoxes
];
1316 [self updateSearchButton
];
1317 [self updateDescriptionText
];
1320 - (IBAction
)sizePopup
:(id)sender
1322 [self updateDescriptionText
];
1326 - (IBAction
)searchButton
:(id)sender
1328 /*if ( [searchTextField intValue] == 0 )
1330 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 )
1339 - (IBAction
)clearSearchButton
:(id)sender
1343 [self setStatusConnected
];
1344 [self setStatusText
:@
"Search Cleared" duration
:1.5];
1346 [self sendClearSearch
];
1350 - (IBAction
)changeButton
:(id)sender
1352 [changeTimer invalidate
];
1353 [changeTimer release
], changeTimer
= nil;
1355 if ( status
== STATUS_CHANGING_CONTINUOUSLY
)
1357 [changeSelectedItems release
], changeSelectedItems
= nil;
1359 [self setStatusCheating
];
1361 else if ( status
== STATUS_CHEATING
)
1363 [NSApp beginSheet
:changeSheet modalForWindow
:cheatWindow modalDelegate
:self didEndSelector
:@selector(changeSheet
:returned
:context
:) contextInfo
:NULL
];
1364 //[NSApp runModalForWindow:changeSheet];
1365 //[NSApp endSheet:changeSheet];
1366 //[changeSheet orderOut:self];
1371 - (IBAction
)serverMenuItem
:(id)sender
1373 NSData
*data
= [[[serverList objectAtIndex
:[sender tag
]] addresses
] objectAtIndex
:0];
1374 /* struct sockaddr_in addr;
1376 [data getBytes:&addr];*/
1378 [self connectToServer
:data name
:[serverPopup titleOfSelectedItem
]];
1381 - (IBAction
)serverMenuDisconnect
:(id)sender
1386 - (IBAction
)serverMenuLocal
:(id)sender
1388 [self connectToLocal
];
1391 - (IBAction
)processMenuItem
:(id)sender
1393 targetPID
= [sender tag
];
1395 [self sendSetTargetPID
:targetPID
];
1397 [self setStatusText
:[NSString stringWithFormat
:@
"PID: %i", targetPID
] duration
:0];
1401 - (IBAction
)pauseButton
:(id)sender
1403 [self sendPauseTarget
];
1407 - (void)undoMenu
:(id)sender
1409 if ( undoCount
== 1 )
1411 [self clearSearchButton
:self];
1415 [self sendUndoRequest
];
1417 [self setStatusUndoing
];
1421 - (void)redoMenu
:(id)sender
1423 [self sendRedoRequest
];
1425 [self setStatusRedoing
];
1428 - (BOOL)respondsToSelector
:(SEL)aSelector
1430 if ( aSelector
== @selector(undoMenu
:) )
1432 if ( status
== STATUS_CHEATING
&& undoCount
> 0 )
1442 if ( aSelector
== @selector(redoMenu
:) )
1444 if ( status
== STATUS_CHEATING
&& redoCount
> 0 )
1454 return [super respondsToSelector
:aSelector
];
1458 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1459 %%%%%%%%%%%%%%%%%%%%%% Change Sheet Interface
1460 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
1463 - (IBAction
)cancelButton
:(id)sender
1465 [changeSheet orderOut
:sender
];
1466 [NSApp endSheet
:changeSheet returnCode
:0];
1467 //[NSApp stopModal];
1470 - (IBAction
)okButton
:(id)sender
1472 [changeSheet orderOut
:sender
];
1473 [NSApp endSheet
:changeSheet returnCode
:1];
1474 //[NSApp stopModal];
1478 - (IBAction
)recurringChangeButton
:(id)sender
1480 if ( [recurringChangeButton state
] == NSOnState
)
1482 [changeSecondsCombo setEnabled
:YES
];
1486 [changeSecondsCombo setEnabled
:NO
];
1491 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1492 %%%%%%%%%%%%%%%%%%%%%% Cleaning Up
1493 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
1503 [changeTimer invalidate
];
1504 [changeTimer release
], changeTimer
= nil;
1506 [self destroyResults
];
1507 [addressTable reloadData
];
1510 - (void)destroyResults
1512 if ( searchResultsAmount
> 0 )
1514 free( searchResults
);
1516 searchResultsAmount
= 0;
1523 [[NSNotificationCenter defaultCenter
] removeObserver
:self];
1527 // clean up status timer stuff
1528 [savedStatusColor release
];
1529 [savedStatusText release
];
1530 [statusTextTimer invalidate
];
1531 [statusTextTimer release
];
1533 [changeTimer invalidate
];
1534 [changeTimer release
];
1536 [self destroyResults
];
1538 [changeSelectedItems release
];
1540 [serverList release
];
1541 [addressList release
];
1547 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1548 %%%%%%%%%%%%%%%%%%%%%% TCListener Notifications
1549 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
1552 - (void)listenerStarted
:(NSNotification
*)note
1554 if ( !everConnected
)
1556 [self connectToLocal
];
1560 - (void)listenerStopped
:(NSNotification
*)note
1566 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1567 %%%%%%%%%%%%%%%%%%%%%% TCWindowsOnTopChanged Notification
1568 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
1571 - (void)windowsOnTopChanged
:(NSNotification
*)note
1573 if ( TCGlobalWindowsOnTop
)
1575 [cheatWindow setLevel
:NSPopUpMenuWindowLevel
];
1579 [cheatWindow setLevel
:NSNormalWindowLevel
];
1584 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1585 %%%%%%%%%%%%%%%%%%%%%% TCWindowsOnTopChanged Notification
1586 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
1589 - (void)handleErrorMessage
:(NSString
*)msg fatal
:(BOOL)fatal
1591 NSLog( @
"error received" );
1592 // close the change sheet if it's open.
1593 if ( [cheatWindow attachedSheet
] )
1595 [changeSheet orderOut
:self];
1596 [NSApp endSheet
:changeSheet returnCode
:0];
1600 NSBeginAlertSheet( fatal? @
"Fatal Error":@
"Error", @
"OK", nil, nil, cheatWindow
, nil, nil, nil, 0, msg
);
1604 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1605 %%%%%%%%%%%%%%%%%%%%%% Cheat Window Delegate
1606 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
1609 - (BOOL)windowShouldClose
:(id)sender
1611 if ( sender
== cheatWindow
&& ( status
== STATUS_SEARCHING || status
== STATUS_CHANGING
) )
1621 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1622 %%%%%%%%%%%%%%%%%%%%%% ClientDelegate
1623 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
1626 - (void)clientConnectedWithSocket
:(int)sock name
:(NSString
*)name
1628 // the client is reporting that a connection has been made.
1631 [self sendProcessListRequest
];
1633 [serverPopup selectItemWithTitle
:name
];
1635 [self setStatusConnected
];
1638 - (void)clientDisconnected
1640 // if there is a pending connection, connect now.
1641 if ( waitingToConnect
)
1643 waitingToConnect
= NO
;
1644 connection
= [[CheatClient clientWithDelegate
:self server
:connectionAddress name
:connectionName
] retain
];
1646 // if our connection variable is still valid, we were disconnected unexpectedly.
1647 else if ( connection
)
1650 NSBeginAlertSheet( @
"Network Failure", @
"OK", nil, nil, cheatWindow
, nil, nil, nil, 0, @
"The server has disconnected you." );
1654 - (void)clientError
:(NSString
*)error message
:(NSString
*)message
1656 NSBeginAlertSheet( error
, @
"OK", nil, nil, cheatWindow
, nil, nil, nil, 0, message
);
1660 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1661 %%%%%%%%%%%%%%%%%%%%%% NSToolbar Delegate
1662 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
1665 *** A toolbar is no longer used, but the code still remains for possible future use. ***
1667 - (NSToolbarItem *)toolbar:(NSToolbar *)toolbar itemForItemIdentifier:(NSString *)itemIdentifier willBeInsertedIntoToolbar:(BOOL)flag
1669 NSToolbarItem *item = [[NSToolbarItem alloc] initWithItemIdentifier:itemIdentifier];
1671 if ( [itemIdentifier isEqualToString:@"Disconnect"] )
1673 disconnectButton = item;
1675 [item setLabel:@"Disconnect"];
1676 [item setPaletteLabel:[item label]];
1677 [item setImage:[NSImage imageNamed:@"disconnect"]];
1678 [item setTarget:self];
1679 [item setToolTip:@"Click here to pause or unpause the program being cheated."];
1681 else if ( [itemIdentifier isEqualToString:@"ServerPopup"] )
1683 NSRect fRect = [typePopup frame];
1684 NSSize fSize = NSMakeSize( FLT_MAX, fRect.size.height );
1685 NSMenuItem *menu = [[NSMenuItem alloc] initWithTitle:@"Server" action:@selector(serverPopup:) keyEquivalent:@""];
1687 [menu setSubmenu:[serverPopup menu]];
1689 [item setLabel:@"Server"];
1690 [item setPaletteLabel:[item label]];
1691 [item setView:serverPopup];
1692 [item setMinSize:fRect.size];
1693 [item setMaxSize:fSize];
1694 [item setMenuFormRepresentation:[menu autorelease]];
1701 - (NSArray *)toolbarAllowedItemIdentifiers:(NSToolbar*)toolbar
1703 return [NSArray arrayWithObjects:NSToolbarSeparatorItemIdentifier,
1704 NSToolbarSpaceItemIdentifier,
1705 NSToolbarFlexibleSpaceItemIdentifier,
1706 NSToolbarCustomizeToolbarItemIdentifier,
1707 @"Disconnect", @"ServerPopup", nil];
1710 - (NSArray *)toolbarDefaultItemIdentifiers:(NSToolbar*)toolbar
1712 return [NSArray arrayWithObjects:@"Disconnect", @"ServerPopup", nil];
1716 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1717 %%%%%%%%%%%%%%%%%%%%%% NSTableView Data Source/Delegate
1718 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
1721 - (void)controlTextDidChange
:(NSNotification
*)aNotification
1723 [self updateSearchButton
];
1727 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1728 %%%%%%%%%%%%%%%%%%%%%% NSTableView Data Source/Delegate
1729 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
1732 - (int)numberOfRowsInTableView
:(NSTableView
*)table
1734 return (searchResultsAmount
<= TCMaxSearchResults
) ? searchResultsAmount
: TCMaxSearchResults
;
1737 - (id)tableView
:(NSTableView
*)table objectValueForTableColumn
:(NSTableColumn
*)column row
:(int)row
1739 return [NSString stringWithFormat
:@
"%0.8X", ((TCaddress
*)searchResults
)[row
]];
1742 - (void)tableView
:(NSTableView
*) setObjectValue
:(id)object forTableColumn
:(NSTableColumn
*)column row
:(int)row
1747 - (void)tableViewSelectionDidChange
:(NSNotification
*)note
1749 if ( [addressTable selectedRow
] != -1 )
1751 addressSelected
= YES
;
1755 addressSelected
= NO
;
1758 [self updateChangeButton
];
1762 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1763 %%%%%%%%%%%%%%%%%%%%%% Global Browser Notifications
1764 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
1767 - (void)browserServerFound
:(NSNotification
*)note
1769 NSNetService
*service
= (NSNetService
*)[note object
];
1771 NSString
*name
= [service name
];
1772 int tag
= [serverList count
] - 1;
1775 NSLog( @
"server found" );
1777 if ( [serverMenu itemWithTitle
:name
] == nil )
1779 item
= [[NSMenuItem alloc
] initWithTitle
:[service name
] action
:@selector(serverMenuItem
:) keyEquivalent
:@
""];
1783 // if this is the first server, add a divider.
1784 if ( [serverMenu numberOfItems
] <= 2 )
1786 [serverMenu addItem
:[NSMenuItem separatorItem
]];
1789 //[serverList addObject:service];
1790 [serverMenu addItem
:[item autorelease
]];
1792 // select the item if we are already connected to the server.
1793 // this could happen if the server rebroadcast as a different name.
1794 if ( connection
&& [[[service addresses
] objectAtIndex
:0] isEqualToData
:connectionAddress
] )
1796 [serverPopup selectItemWithTitle
:[service name
]];
1801 - (void)browserServerLost
:(NSNotification
*)note
1803 NSNetService
*service
= (NSNetService
*)[note object
];
1804 NSString
*name
= [service name
];
1806 int i
, top
= [serverMenu numberOfItems
];
1808 for ( i
= [serverMenu indexOfItemWithTitle
:name
] + 1; i
< top
; i
++ )
1810 [[serverMenu itemWithTitle
:name
] setTag
:[[serverMenu itemWithTitle
:name
] tag
] - 1];
1813 [serverMenu removeAllItemsWithTitle
:name
];
1815 // if this is the last broadcast server, take away the divider.
1816 if ( [serverMenu numberOfItems
] == 3 )
1818 [serverMenu removeItemAtIndex
:2];
1826 // Internal Functions
1827 void TCPlaySound( NSString
*name
)
1829 if ( TCGlobalPlaySounds
)
1831 [[NSSound soundNamed
:name
] play
];