@ -51,16 +51,20 @@ using namespace DFHack;
 
		
	
		
			
				
 
		
	
		
			
				# include  "dfhack/SDL_fakes/events.h"  
		
	
		
			
				
 
		
	
		
			
				# include  "dfhack/df/ui.h"  
		
	
		
			
				# include  "dfhack/df/world.h"  
		
	
		
			
				# include  "dfhack/df/world_data.h"  
		
	
		
			
				# include  "dfhack/df/interface.h"  
		
	
		
			
				# include  "dfhack/df/viewscreen_dwarfmodest.h"  
		
	
		
			
				
 
		
	
		
			
				# include  <stdio.h>  
		
	
		
			
				# include  <iomanip>  
		
	
		
			
				# include  <stdlib.h>  
		
	
		
			
				# include  <fstream>  
		
	
		
			
				# include  "tinythread.h"  
		
	
		
			
				using  namespace  tthread ;  
		
	
		
			
				
 
		
	
		
			
				using  namespace  tthread ;  
		
	
		
			
				using  namespace  df : : enums ;  
		
	
		
			
				
 
		
	
		
			
				struct  Core : : Cond  
		
	
		
			
				{  
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
			
			@ -204,6 +208,7 @@ static void runInteractiveCommand(Core *core, PluginManager *plug_mgr, int &clue
 
		
	
		
			
				                          "   cls                   - Clear the console. \n " 
 
		
	
		
			
				                          "   fpause                - Force DF to pause. \n " 
 
		
	
		
			
				                          "   die                   - Force DF to close immediately \n " 
 
		
	
		
			
				                          "   keybinding            - Modify bindings of commands to keys \n " 
 
		
	
		
			
				                          " Plugin management (useful for developers): \n " 
 
		
	
		
			
				                          //"  belongs COMMAND       - Tell which plugin a command belongs to.\n"
 
 
		
	
		
			
				                          "   plug [PLUGIN|v]       - List plugin state and description. \n " 
 
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
			
			@ -354,6 +359,40 @@ static void runInteractiveCommand(Core *core, PluginManager *plug_mgr, int &clue
 
		
	
		
			
				                con . print ( " %s \n " ,  plug - > getName ( ) . c_str ( ) ) ; 
 
		
	
		
			
				            } 
 
		
	
		
			
				        } 
 
		
	
		
			
				        else  if ( first  = =  " keybinding " ) 
 
		
	
		
			
				        { 
 
		
	
		
			
				            if  ( parts . size ( )  > =  3  & &  ( parts [ 0 ]  = =  " set "  | |  parts [ 0 ]  = =  " add " ) ) 
 
		
	
		
			
				            { 
 
		
	
		
			
				                std : : string  keystr  =  parts [ 1 ] ; 
 
		
	
		
			
				                if  ( parts [ 0 ]  = =  " set " ) 
 
		
	
		
			
				                    core - > ClearKeyBindings ( keystr ) ; 
 
		
	
		
			
				                for  ( int  i  =  parts . size ( ) - 1 ;  i  > =  2 ;  i - - )  
 
		
	
		
			
				                { 
 
		
	
		
			
				                    if  ( ! core - > AddKeyBinding ( keystr ,  parts [ i ] ) )  { 
 
		
	
		
			
				                        con . printerr ( " Invalid key spec: %s \n " ,  keystr . c_str ( ) ) ; 
 
		
	
		
			
				                        break ; 
 
		
	
		
			
				                    } 
 
		
	
		
			
				                } 
 
		
	
		
			
				            } 
 
		
	
		
			
				            else  if  ( parts . size ( )  > =  2  & &  parts [ 0 ]  = =  " clear " ) 
 
		
	
		
			
				            { 
 
		
	
		
			
				                for  ( unsigned  i  =  1 ;  i  <  parts . size ( ) ;  i + + ) 
 
		
	
		
			
				                { 
 
		
	
		
			
				                    if  ( ! core - > ClearKeyBindings ( parts [ i ] ) )  { 
 
		
	
		
			
				                        con . printerr ( " Invalid key spec: %s \n " ,  parts [ i ] . c_str ( ) ) ; 
 
		
	
		
			
				                        break ; 
 
		
	
		
			
				                    } 
 
		
	
		
			
				                } 
 
		
	
		
			
				            } 
 
		
	
		
			
				            else 
 
		
	
		
			
				            { 
 
		
	
		
			
				                con  < <  " Usage: "  < <  endl 
 
		
	
		
			
				                    < <  "   keybinding clear <key> <key>... "  < <  endl 
 
		
	
		
			
				                    < <  "   keybinding set <key>  \" cmdline \"   \" cmdline \" ... "  < <  endl 
 
		
	
		
			
				                    < <  "   keybinding add <key>  \" cmdline \"   \" cmdline \" ... "  < <  endl 
 
		
	
		
			
				                    < <  " Later adds, and earlier items within one command have priority. "  < <  endl ; 
 
		
	
		
			
				            } 
 
		
	
		
			
				        } 
 
		
	
		
			
				        else  if ( first  = =  " fpause " ) 
 
		
	
		
			
				        { 
 
		
	
		
			
				            World  *  w  =  core - > getWorld ( ) ; 
 
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
			
			@ -482,12 +521,12 @@ Core::Core()
 
		
	
		
			
				    StackMutex  =  0 ; 
 
		
	
		
			
				    core_cond  =  0 ; 
 
		
	
		
			
				    // set up hotkey capture
 
 
		
	
		
			
				    memset ( hotkey_states , 0 , sizeof ( hotkey_states ) ) ; 
 
		
	
		
			
				    hotkey_set  =  false ; 
 
		
	
		
			
				    HotkeyMutex  =  0 ; 
 
		
	
		
			
				    HotkeyCond  =  0 ; 
 
		
	
		
			
				    misc_data_mutex = 0 ; 
 
		
	
		
			
				    last_world_data_ptr  =  NULL ; 
 
		
	
		
			
				    top_viewscreen  =  NULL ; 
 
		
	
		
			
				} ;  
		
	
		
			
				
 
		
	
		
			
				void  Core : : fatal  ( std : : string  output ,  bool  deactivate )  
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
			
			@ -694,6 +733,19 @@ int Core::Update()
 
		
	
		
			
				        plug_mgr - > OnStateChange ( new_wdata  ?  SC_GAME_LOADED  :  SC_GAME_UNLOADED ) ; 
 
		
	
		
			
				    } 
 
		
	
		
			
				
 
		
	
		
			
				    // detect if the viewscreen changed
 
 
		
	
		
			
				    if  ( df : : global : : gview )  
 
		
	
		
			
				    { 
 
		
	
		
			
				        df : : viewscreen  * screen  =  & df : : global : : gview - > view ; 
 
		
	
		
			
				        while  ( screen - > child ) 
 
		
	
		
			
				            screen  =  screen - > child ; 
 
		
	
		
			
				        if  ( screen  ! =  top_viewscreen )  
 
		
	
		
			
				        { 
 
		
	
		
			
				            top_viewscreen  =  screen ; 
 
		
	
		
			
				            plug_mgr - > OnStateChange ( SC_VIEWSCREEN_CHANGED ) ; 
 
		
	
		
			
				        } 
 
		
	
		
			
				    } 
 
		
	
		
			
				
 
		
	
		
			
				    // notify all the plugins that a game tick is finished
 
 
		
	
		
			
				    plug_mgr - > OnUpdate ( ) ; 
 
		
	
		
			
				
 
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
			
			@ -785,37 +837,149 @@ int Core::SDL_Event(SDL::Event* ev, int orig_return)
 
		
	
		
			
				    if ( ev  & &  ev - > type  = =  SDL : : ET_KEYDOWN  | |  ev - > type  = =  SDL : : ET_KEYUP ) 
 
		
	
		
			
				    { 
 
		
	
		
			
				        SDL : : KeyboardEvent  *  ke  =  ( SDL : : KeyboardEvent  * ) ev ; 
 
		
	
		
			
				        bool  shift  =  ke - > ksym . mod  &  SDL : : KMOD_SHIFT ; 
 
		
	
		
			
				        // consuming F1 .. F8
 
 
		
	
		
			
				        int  idx  =  ke - > ksym . sym  -  SDL : : K_F1 ; 
 
		
	
		
			
				        if ( idx  <  0  | |  idx  >  7 ) 
 
		
	
		
			
				            return  orig_return ; 
 
		
	
		
			
				        idx  + =  8 * shift ; 
 
		
	
		
			
				        // now we have the real index...
 
 
		
	
		
			
				        if ( ke - > state  = =  SDL : : BTN_PRESSED  & &  ! hotkey_states [ idx ] ) 
 
		
	
		
			
				        
 
		
	
		
			
				        if ( ke - > state  = =  SDL : : BTN_PRESSED  & &  ! hotkey_states [ ke - > ksym . sym ] ) 
 
		
	
		
			
				        { 
 
		
	
		
			
				            hotkey_states [ idx ]  =  1 ; 
 
		
	
		
			
				            Gui  *  g  =  getGui ( ) ; 
 
		
	
		
			
				            if ( g - > hotkeys  & &  g - > df_interface  & &  g - > df_menu_state ) 
 
		
	
		
			
				            hotkey_states [ ke - > ksym . sym ]  =  true ; 
 
		
	
		
			
				
 
		
	
		
			
				            int  mod  =  0 ; 
 
		
	
		
			
				            if  ( ke - > ksym . mod  &  SDL : : KMOD_SHIFT )  mod  | =  1 ; 
 
		
	
		
			
				            if  ( ke - > ksym . mod  &  SDL : : KMOD_CTRL )  mod  | =  2 ; 
 
		
	
		
			
				            if  ( ke - > ksym . mod  &  SDL : : KMOD_ALT )  mod  | =  4 ; 
 
		
	
		
			
				
 
		
	
		
			
				            SelectHotkey ( ke - > ksym . sym ,  mod ) ; 
 
		
	
		
			
				        } 
 
		
	
		
			
				        else  if ( ke - > state  = =  SDL : : BTN_RELEASED ) 
 
		
	
		
			
				        { 
 
		
	
		
			
				                t_viewscreen  *  ws  =  g - > GetCurrentScreen ( ) ; 
 
		
	
		
			
				                // FIXME: put hardcoded values into memory.xml
 
 
		
	
		
			
				                if ( ws - > getClassName ( )  = =  " viewscreen_dwarfmodest "  & &  * g - > df_menu_state  = =  0x23 ) 
 
		
	
		
			
				            hotkey_states [ ke - > ksym . sym ]  =  false ; 
 
		
	
		
			
				        } 
 
		
	
		
			
				    } 
 
		
	
		
			
				    return  orig_return ; 
 
		
	
		
			
				                else 
 
		
	
		
			
				    // do stuff with the events...
 
 
		
	
		
			
				}  
		
	
		
			
				
 
		
	
		
			
				bool  Core : : SelectHotkey ( int  sym ,  int  modifiers )  
		
	
		
			
				{  
		
	
		
			
				    // Find the topmost viewscreen
 
 
		
	
		
			
				    if  ( ! df : : global : : gview  | |  ! df : : global : : ui ) 
 
		
	
		
			
				        return  false ; 
 
		
	
		
			
				
 
		
	
		
			
				    df : : viewscreen  * screen  =  & df : : global : : gview - > view ; 
 
		
	
		
			
				    while  ( screen - > child ) 
 
		
	
		
			
				        screen  =  screen - > child ; 
 
		
	
		
			
				
 
		
	
		
			
				    std : : string  cmd ; 
 
		
	
		
			
				    
 
		
	
		
			
				    { 
 
		
	
		
			
				                    t_hotkey  &  hotkey  =  ( * g - > hotkeys ) [ idx ] ; 
 
		
	
		
			
				                    setHotkeyCmd ( hotkey . name ) ; 
 
		
	
		
			
				        tthread : : lock_guard < tthread : : mutex >  lock ( * HotkeyMutex ) ; 
 
		
	
		
			
				    
 
		
	
		
			
				        // Check the internal keybindings
 
 
		
	
		
			
				        std : : vector < KeyBinding >  & bindings  =  key_bindings [ sym ] ; 
 
		
	
		
			
				        for  ( int  i  =  bindings . size ( ) - 1 ;  i  > =  0 ;  - - i )  { 
 
		
	
		
			
				            if  ( bindings [ i ] . modifiers  ! =  modifiers ) 
 
		
	
		
			
				                continue ; 
 
		
	
		
			
				            if  ( ! plug_mgr - > CanInvokeHotkey ( bindings [ i ] . command [ 0 ] ,  screen ) ) 
 
		
	
		
			
				                continue ; 
 
		
	
		
			
				            cmd  =  bindings [ i ] . cmdline ; 
 
		
	
		
			
				            break ; 
 
		
	
		
			
				        } 
 
		
	
		
			
				
 
		
	
		
			
				        if  ( cmd . empty ( ) )  { 
 
		
	
		
			
				            // Check the hotkey keybindings
 
 
		
	
		
			
				            int  idx  =  sym  -  SDL : : K_F1 ; 
 
		
	
		
			
				            if ( idx  > =  0  & &  idx  <  8 ) 
 
		
	
		
			
				            { 
 
		
	
		
			
				                if  ( modifiers  &  1 ) 
 
		
	
		
			
				                    idx  + =  8 ; 
 
		
	
		
			
				
 
		
	
		
			
				                if  ( ! strict_virtual_cast < df : : viewscreen_dwarfmodest > ( screen )  | | 
 
		
	
		
			
				                    df : : global : : ui - > main . mode  ! =  ui_sidebar_mode : : Hotkeys ) 
 
		
	
		
			
				                { 
 
		
	
		
			
				                    cmd  =  df : : global : : ui - > main . hotkeys [ idx ] . name ; 
 
		
	
		
			
				                } 
 
		
	
		
			
				            } 
 
		
	
		
			
				        else  if ( ke - > state  = =  SDL : : BTN_RELEASED ) 
 
		
	
		
			
				        { 
 
		
	
		
			
				            hotkey_states [ idx ]  =  0 ; 
 
		
	
		
			
				        } 
 
		
	
		
			
				    } 
 
		
	
		
			
				    return  orig_return ; 
 
		
	
		
			
				    // do stuff with the events...
 
 
		
	
		
			
				
 
		
	
		
			
				    if  ( ! cmd . empty ( ) )  { 
 
		
	
		
			
				        setHotkeyCmd ( cmd ) ; 
 
		
	
		
			
				        return  true ; 
 
		
	
		
			
				    } 
 
		
	
		
			
				    else 
 
		
	
		
			
				        return  false ; 
 
		
	
		
			
				}  
		
	
		
			
				
 
		
	
		
			
				static  bool  parseKeySpec ( std : : string  keyspec ,  int  * psym ,  int  * pmod )  
		
	
		
			
				{  
		
	
		
			
				    * pmod  =  0 ; 
 
		
	
		
			
				
 
		
	
		
			
				    // ugh, ugly
 
 
		
	
		
			
				    for  ( ; ; )  { 
 
		
	
		
			
				        if  ( keyspec . size ( )  >  6  & &  keyspec . substr ( 0 ,  6 )  = =  " Shift- " )  { 
 
		
	
		
			
				            * pmod  | =  1 ; 
 
		
	
		
			
				            keyspec  =  keyspec . substr ( 6 ) ; 
 
		
	
		
			
				        }  else  if  ( keyspec . size ( )  >  5  & &  keyspec . substr ( 0 ,  5 )  = =  " Ctrl- " )  { 
 
		
	
		
			
				            * pmod  | =  2 ; 
 
		
	
		
			
				            keyspec  =  keyspec . substr ( 5 ) ; 
 
		
	
		
			
				        }  else  if  ( keyspec . size ( )  >  4  & &  keyspec . substr ( 0 ,  4 )  = =  " Alt- " )  { 
 
		
	
		
			
				            * pmod  | =  4 ; 
 
		
	
		
			
				            keyspec  =  keyspec . substr ( 4 ) ; 
 
		
	
		
			
				        }  else  
 
		
	
		
			
				            break ; 
 
		
	
		
			
				    } 
 
		
	
		
			
				
 
		
	
		
			
				    if  ( keyspec . size ( )  = =  1  & &  keyspec [ 0 ]  > =  ' A '  & &  keyspec [ 0 ]  < =  ' Z ' )  { 
 
		
	
		
			
				        * psym  =  SDL : : K_a  +  ( keyspec [ 0 ] - ' A ' ) ; 
 
		
	
		
			
				        return  true ; 
 
		
	
		
			
				    }  else  if  ( keyspec . size ( )  = =  2  & &  keyspec [ 0 ]  = =  ' F '  & &  keyspec [ 1 ]  > =  ' 1 '  & &  keyspec [ 1 ]  < =  ' 9 ' )  { 
 
		
	
		
			
				        * psym  =  SDL : : K_F1  +  ( keyspec [ 1 ] - ' 1 ' ) ; 
 
		
	
		
			
				        return  true ; 
 
		
	
		
			
				    }  else 
 
		
	
		
			
				        return  false ;     
 
		
	
		
			
				}  
		
	
		
			
				
 
		
	
		
			
				bool  Core : : ClearKeyBindings ( std : : string  keyspec )  
		
	
		
			
				{  
		
	
		
			
				    int  sym ,  mod ; 
 
		
	
		
			
				    if  ( ! parseKeySpec ( keyspec ,  & sym ,  & mod ) ) 
 
		
	
		
			
				        return  false ; 
 
		
	
		
			
				
 
		
	
		
			
				    tthread : : lock_guard < tthread : : mutex >  lock ( * HotkeyMutex ) ; 
 
		
	
		
			
				
 
		
	
		
			
				    std : : vector < KeyBinding >  & bindings  =  key_bindings [ sym ] ; 
 
		
	
		
			
				    for  ( int  i  =  bindings . size ( ) - 1 ;  i  > =  0 ;  - - i )  { 
 
		
	
		
			
				        if  ( bindings [ i ] . modifiers  = =  mod ) 
 
		
	
		
			
				            bindings . erase ( bindings . begin ( ) + i ) ; 
 
		
	
		
			
				    } 
 
		
	
		
			
				
 
		
	
		
			
				    return  true ; 
 
		
	
		
			
				}  
		
	
		
			
				
 
		
	
		
			
				bool  Core : : AddKeyBinding ( std : : string  keyspec ,  std : : string  cmdline )  
		
	
		
			
				{  
		
	
		
			
				    int  sym ; 
 
		
	
		
			
				    KeyBinding  binding ; 
 
		
	
		
			
				    if  ( ! parseKeySpec ( keyspec ,  & sym ,  & binding . modifiers ) ) 
 
		
	
		
			
				        return  false ; 
 
		
	
		
			
				
 
		
	
		
			
				    cheap_tokenise ( cmdline ,  binding . command ) ; 
 
		
	
		
			
				    if  ( binding . command . empty ( ) ) 
 
		
	
		
			
				        return  false ; 
 
		
	
		
			
				
 
		
	
		
			
				    tthread : : lock_guard < tthread : : mutex >  lock ( * HotkeyMutex ) ; 
 
		
	
		
			
				
 
		
	
		
			
				    binding . cmdline  =  cmdline ; 
 
		
	
		
			
				    key_bindings [ sym ] . push_back ( binding ) ; 
 
		
	
		
			
				    return  true ; 
 
		
	
		
			
				}  
		
	
		
			
				
 
		
	
		
			
				bool  DFHack : : default_hotkey ( Core  * ,  df : : viewscreen  * top )  
		
	
		
			
				{  
		
	
		
			
				    // Default hotkey guard function
 
 
		
	
		
			
				    for  ( ; top  ; top  =  top - > parent ) 
 
		
	
		
			
				        if  ( strict_virtual_cast < df : : viewscreen_dwarfmodest > ( top ) ) 
 
		
	
		
			
				            return  true ; 
 
		
	
		
			
				    return  false ; 
 
		
	
		
			
				}  
		
	
		
			
				
 
		
	
		
			
				////////////////