@ -204,7 +204,8 @@ static bool ParseSpec(color_ostream &out, lua_State *L, const char *type, vector
}
}
# define PARSE_SPEC(type, params) \
# define PARSE_SPEC(type, params) \
if ( ! ParseSpec ( * pout , L , type , params ) ) return false ;
std : : vector < unsigned > order ; \
if ( ! ParseSpec ( * pout , L , type , params ) ) return ;
static bool prepare_sort ( color_ostream * pout , lua_State * L )
static bool prepare_sort ( color_ostream * pout , lua_State * L )
{
{
@ -230,310 +231,226 @@ static df::layer_object_listst *getLayerList(df::viewscreen_layerst *layer, int
return virtual_cast < df : : layer_object_listst > ( vector_get ( layer - > layer_objects , idx ) ) ;
return virtual_cast < df : : layer_object_listst > ( vector_get ( layer - > layer_objects , idx ) ) ;
}
}
static bool maybe_sort_units ( color_ostream * pout , lua_State * L ,
typedef void ( * SortHandler ) ( color_ostream * pout , lua_State * L , int top ,
df : : viewscreen * screen , vector < string > & parameters )
df : : viewscreen * screen , vector < string > & parameters ) ;
{
Lua : : StackUnwinder top ( L ) ;
if ( ! prepare_sort ( pout , L ) )
# define VIEWSCREEN(name) df::viewscreen_##name##st
return false ;
# define DEFINE_SORT_HANDLER(map, screen_type, tail, screen) \
static void CONCAT_TOKENS ( SortHandler_ # # screen_type , __LINE__ ) \
( color_ostream * pout , lua_State * L , int top , \
VIEWSCREEN ( screen_type ) * screen , vector < string > & parameters ) ; \
DFHACK_STATIC_ADD_TO_MAP ( & map , # screen_type tail , \
( SortHandler ) CONCAT_TOKENS ( SortHandler_ # # screen_type , __LINE__ ) ) ; \
static void CONCAT_TOKENS ( SortHandler_ # # screen_type , __LINE__ ) \
( color_ostream * pout , lua_State * L , int top , \
VIEWSCREEN ( screen_type ) * screen , vector < string > & parameters )
std : : vector < unsigned > order ;
static std : : map < std : : string , SortHandler > unit_sorters ;
if ( auto units = strict_virtual_cast < df : : viewscreen_unitlistst > ( screen ) )
/*
{
* Sort units in the ' u ' nit list screen .
if ( ! L ) return true ;
*/
/*
DEFINE_SORT_HANDLER ( unit_sorters , unitlist , " " , units )
* Sort units in the ' u ' nit list screen .
{
*/
PARSE_SPEC ( " units " , parameters ) ;
PARSE_SPEC ( " units " , parameters ) ;
int page = units - > page ;
int page = units - > page ;
if ( compute_order ( * pout , L , top , & order , units - > units [ page ] ) )
{
reorder_cursor ( & units - > cursor_pos [ page ] , order ) ;
reorder_vector ( & units - > units [ page ] , order ) ;
reorder_vector ( & units - > jobs [ page ] , order ) ;
}
}
if ( compute_order ( * pout , L , top , & order , units - > units [ page ] ) )
/*
{
* Sort units in the ' j ' ob list screen .
reorder_cursor ( & units - > cursor_pos [ page ] , order ) ;
*/
reorder_vector ( & units - > units [ page ] , order ) ;
reorder_vector ( & units - > jobs [ page ] , order ) ;
}
return true ;
DEFINE_SORT_HANDLER ( unit_sorters , joblist , " " , jobs )
}
{
else if ( auto jobs = strict_virtual_cast < df : : viewscreen_joblistst > ( screen ) )
PARSE_SPEC ( " units " , parameters ) ;
if ( compute_order ( * pout , L , top , & order , jobs - > units ) )
{
{
if ( ! L ) return true ;
reorder_cursor ( & jobs - > cursor_pos , order ) ;
reorder_vector ( & jobs - > units , order ) ;
reorder_vector ( & jobs - > jobs , order ) ;
}
}
/*
/*
* Sort units in the ' j ' ob list screen .
* Sort candidate units in the ' p' osition page of the ' m ' ilitary screen .
*/
*/
PARSE_SPEC ( " units " , parameters ) ;
DEFINE_SORT_HANDLER ( unit_sorters , layer_military , " /Positions/Candidates " , military )
{
auto & candidates = military - > positions . candidates ;
auto list3 = getLayerList ( military , 2 ) ;
if ( compute_order ( * pout , L , top , & order , jobs - > units ) )
PARSE_SPEC ( " units " , parameters ) ;
{
reorder_cursor ( & jobs - > cursor_pos , order ) ;
reorder_vector ( & jobs - > units , order ) ;
reorder_vector ( & jobs - > jobs , order ) ;
}
return true ;
if ( compute_order ( * pout , L , top , & order , candidates ) )
}
else if ( auto military = strict_virtual_cast < df : : viewscreen_layer_militaryst > ( screen ) )
{
{
switch ( military - > page )
reorder_cursor ( & list3 - > cursor , order ) ;
{
reorder_vector ( & candidates , order ) ;
case df : : viewscreen_layer_militaryst : : Positions :
}
{
}
auto & candidates = military - > positions . candidates ;
auto list3 = getLayerList ( military , 2 ) ;
/*
* Sort candidate units in the ' p ' osition page of the ' m ' ilitary screen .
*/
if ( list3 & & ! candidates . empty ( ) & & list3 - > bright )
/*
{
* Sort units in the workshop ' q ' uery ' P ' rofile modification screen .
if ( ! L ) return true ;
*/
PARSE_SPEC ( " units " , parameters ) ;
DEFINE_SORT_HANDLER ( unit_sorters , layer_workshop_profile , " /Unit " , profile )
{
auto list1 = getLayerList ( profile , 0 ) ;
if ( compute_order ( * pout , L , top , & order , candidates ) )
PARSE_SPEC ( " units " , parameters ) ;
{
reorder_cursor ( & list3 - > cursor , order ) ;
reorder_vector ( & candidates , order ) ;
}
return true ;
if ( compute_order ( * pout , L , top , & order , profile - > workers ) )
}
{
reorder_cursor ( & list1 - > cursor , order ) ;
reorder_vector ( & profile - > workers , order ) ;
}
}
return false ;
DEFINE_SORT_HANDLER ( unit_sorters , layer_noblelist , " /Appoint " , nobles )
}
{
auto list2 = getLayerList ( nobles , 1 ) ;
default :
sort_null_first ( parameters ) ;
return false ;
PARSE_SPEC ( " units " , parameters ) ;
}
}
else if ( auto profile = strict_virtual_cast < df : : viewscreen_layer_workshop_profilest > ( screen ) )
{
auto list1 = getLayerList ( profile , 0 ) ;
if ( ! list1 ) return false ;
std : : vector < df : : unit * > units ;
if ( ! L ) return true ;
for ( size_t i = 0 ; i < nobles - > candidates . size ( ) ; i + + )
units . push_back ( nobles - > candidates [ i ] - > unit ) ;
/*
if ( compute_order ( * pout , L , top , & order , units ) )
* Sort units in the workshop ' q ' uery ' P ' rofile modification screen .
{
*/
reorder_cursor ( & list2 - > cursor , order ) ;
reorder_vector ( & nobles - > candidates , order ) ;
}
}
PARSE_SPEC ( " units " , parameters ) ;
/*
* Sort animal units in the Animal page of the ' z ' status screen .
*/
if ( compute_order ( * pout , L , top , & order , profile - > workers ) )
DEFINE_SORT_HANDLER ( unit_sorters , pet , " /List " , animals )
{
{
reorder_cursor ( & list1 - > cursor , order ) ;
PARSE_SPEC ( " units " , parameters ) ;
reorder_vector ( & profile - > workers , order ) ;
}
return true ;
std : : vector < df : : unit * > units ;
}
for ( size_t i = 0 ; i < animals - > animal . size ( ) ; i + + )
else if ( auto nobles = strict_virtual_cast < df : : viewscreen_layer_noblelistst > ( screen ) )
units . push_back ( animals - > is_vermin [ i ] ? NULL : ( df : : unit * ) animals - > animal [ i ] ) ;
{
switch ( nobles - > mode )
{
case df : : viewscreen_layer_noblelistst : : Appoint :
{
auto list2 = getLayerList ( nobles , 1 ) ;
/*
if ( compute_order ( * pout , L , top , & order , units ) )
* Sort units in the appointment candidate list of the ' n ' obles screen .
{
*/
reorder_cursor ( & animals - > cursor , order ) ;
reorder_vector ( & animals - > animal , order ) ;
reorder_vector ( & animals - > is_vermin , order ) ;
reorder_vector ( & animals - > pet_info , order ) ;
reorder_vector ( & animals - > is_tame , order ) ;
reorder_vector ( & animals - > is_adopting , order ) ;
}
}
if ( list2 )
/*
{
* Sort candidate trainers in the Animal page of the ' z ' status screen .
if ( ! L ) return true ;
*/
sort_null_first ( parameters ) ;
DEFINE_SORT_HANDLER ( unit_sorters , pet , " /SelectTrainer " , animals )
PARSE_SPEC ( " units " , parameters ) ;
{
sort_null_first ( parameters ) ;
PARSE_SPEC ( " units " , parameters ) ;
std : : vector < df : : unit * > units ;
if ( compute_order ( * pout , L , top , & order , animals - > trainer_unit ) )
for ( size_t i = 0 ; i < nobles - > candidates . size ( ) ; i + + )
{
units . push_back ( nobles - > candidates [ i ] - > unit ) ;
reorder_cursor ( & animals - > trainer_cursor , order ) ;
reorder_vector ( & animals - > trainer_unit , order ) ;
reorder_vector ( & animals - > trainer_mode , order ) ;
}
}
if ( compute_order ( * pout , L , top , & order , units ) )
/*
{
* Sort units in the Health page of the ' z ' status screen .
reorder_cursor ( & list2 - > cursor , order ) ;
*/
reorder_vector ( & nobles - > candidates , order ) ;
}
return true ;
DEFINE_SORT_HANDLER ( unit_sorters , layer_overall_health , " /Units " , health )
}
{
auto list1 = getLayerList ( health , 0 ) ;
return false ;
PARSE_SPEC ( " units " , parameters ) ;
}
default :
if ( compute_order ( * pout , L , top , & order , health - > unit ) )
return false ;
}
}
else if ( auto animals = strict_virtual_cast < df : : viewscreen_petst > ( screen ) )
{
{
switch ( animals - > mode )
reorder_cursor ( & list1 - > cursor , order ) ;
{
reorder_vector ( & health - > unit , order ) ;
case df : : viewscreen_petst : : List :
reorder_vector ( & health - > bits1 , order ) ;
{
reorder_vector ( & health - > bits2 , order ) ;
if ( ! L ) return true ;
reorder_vector ( & health - > bits3 , order ) ;
/*
* Sort animal units in the Animal page of the ' z ' status screen .
*/
PARSE_SPEC ( " units " , parameters ) ;
std : : vector < df : : unit * > units ;
for ( size_t i = 0 ; i < animals - > animal . size ( ) ; i + + )
units . push_back ( animals - > is_vermin [ i ] ? NULL : ( df : : unit * ) animals - > animal [ i ] ) ;
if ( compute_order ( * pout , L , top , & order , units ) )
{
reorder_cursor ( & animals - > cursor , order ) ;
reorder_vector ( & animals - > animal , order ) ;
reorder_vector ( & animals - > is_vermin , order ) ;
reorder_vector ( & animals - > pet_info , order ) ;
reorder_vector ( & animals - > is_tame , order ) ;
reorder_vector ( & animals - > is_adopting , order ) ;
}
return true ;
}
case df : : viewscreen_petst : : SelectTrainer :
{
if ( ! L ) return true ;
/*
* Sort candidate trainers in the Animal page of the ' z ' status screen .
*/
sort_null_first ( parameters ) ;
PARSE_SPEC ( " units " , parameters ) ;
if ( compute_order ( * pout , L , top , & order , animals - > trainer_unit ) )
{
reorder_cursor ( & animals - > trainer_cursor , order ) ;
reorder_vector ( & animals - > trainer_unit , order ) ;
reorder_vector ( & animals - > trainer_mode , order ) ;
}
return true ;
}
default :
return false ;
}
}
}
else if ( auto health = strict_virtual_cast < df : : viewscreen_layer_overall_healthst > ( screen ) )
}
{
auto list1 = getLayerList ( health , 0 ) ;
/*
* Sort burrow member candidate units in the ' w ' sidebar mode .
*/
DEFINE_SORT_HANDLER ( unit_sorters , dwarfmode , " /Burrows/AddUnits " , screen )
{
PARSE_SPEC ( " units " , parameters ) ;
if ( ! list1 ) return false ;
if ( compute_order ( * pout , L , top , & order , ui - > burrows . list_units ) )
if ( ! L ) return true ;
{
reorder_cursor ( & ui - > burrows . unit_cursor_pos , order ) ;
reorder_vector ( & ui - > burrows . list_units , order ) ;
reorder_vector ( & ui - > burrows . sel_units , order ) ;
}
}
/*
/*
* Sort units in the Health page of the ' z ' status screen .
* Sort building owner candidate units in the ' q ' sidebar mode , or cage assignment .
*/
*/
PARSE_SPEC ( " units " , parameters ) ;
DEFINE_SORT_HANDLER ( unit_sorters , dwarfmode , " /QueryBuilding/Some/Assign " , screen )
{
sort_null_first ( parameters ) ;
if ( compute_order ( * pout , L , top , & order , health - > unit ) )
PARSE_SPEC ( " units " , parameters ) ;
{
reorder_cursor ( & list1 - > cursor , order ) ;
reorder_vector ( & health - > unit , order ) ;
reorder_vector ( & health - > bits1 , order ) ;
reorder_vector ( & health - > bits2 , order ) ;
reorder_vector ( & health - > bits3 , order ) ;
}
return true ;
if ( compute_order ( * pout , L , top , & order , * ui_building_assign_units ) )
}
else if ( strict_virtual_cast < df : : viewscreen_dwarfmodest > ( screen ) )
{
{
switch ( ui - > main . mode )
reorder_cursor ( ui_building_item_cursor , order ) ;
{
reorder_vector ( ui_building_assign_type , order ) ;
case ui_sidebar_mode : : Burrows :
reorder_vector ( ui_building_assign_units , order ) ;
if ( ! L ) return true ;
}
}
/*
* Sort burrow member candidate units in the ' w ' sidebar mode .
*/
PARSE_SPEC ( " units " , parameters ) ;
if ( compute_order ( * pout , L , top , & order , ui - > burrows . list_units ) )
{
reorder_cursor ( & ui - > burrows . unit_cursor_pos , order ) ;
reorder_vector ( & ui - > burrows . list_units , order ) ;
reorder_vector ( & ui - > burrows . sel_units , order ) ;
}
return true ;
case ui_sidebar_mode : : QueryBuilding :
if ( ! ui_building_in_assign | | ! * ui_building_in_assign )
return false ;
// fall through for building owner / chain assign animal
case ui_sidebar_mode : : ZonesPenInfo :
if ( ui_building_item_cursor & &
ui_building_assign_type & &
ui_building_assign_is_marked & &
ui_building_assign_units & &
ui_building_assign_items & &
ui_building_assign_type - > size ( ) = = ui_building_assign_units - > size ( ) & &
! ui_building_assign_type - > empty ( ) )
{
if ( ! L ) return true ;
/*
* Sort building owner candidate units in the ' q ' sidebar mode ,
* or pen assignment candidate units in ' z ' - > ' N ' , or cage assignment .
*/
// TODO: better way
bool is_assign_owner = ( ( * ui_building_assign_type ) [ 0 ] = = - 1 ) ;
if ( is_assign_owner )
sort_null_first ( parameters ) ;
PARSE_SPEC ( " units " , parameters ) ;
if ( compute_order ( * pout , L , top , & order , * ui_building_assign_units ) )
{
reorder_cursor ( ui_building_item_cursor , order ) ;
reorder_vector ( ui_building_assign_type , order ) ;
reorder_vector ( ui_building_assign_units , order ) ;
if ( ui_building_assign_units - > size ( ) = = ui_building_assign_items - > size ( ) )
reorder_vector ( ui_building_assign_items , order ) ;
if ( ui_building_assign_units - > size ( ) = = ui_building_assign_is_marked - > size ( ) )
reorder_vector ( ui_building_assign_is_marked , order ) ;
}
return true ;
}
return false ;
default :
/*
return false ;
* Sort pen assignment candidate units in ' z ' - > ' N ' .
}
*/
DEFINE_SORT_HANDLER ( unit_sorters , dwarfmode , " /ZonesPenInfo/Assign " , screen )
{
PARSE_SPEC ( " units " , parameters ) ;
if ( compute_order ( * pout , L , top , & order , * ui_building_assign_units ) )
{
reorder_cursor ( ui_building_item_cursor , order ) ;
reorder_vector ( ui_building_assign_type , order ) ;
reorder_vector ( ui_building_assign_units , order ) ;
reorder_vector ( ui_building_assign_items , order ) ;
reorder_vector ( ui_building_assign_is_marked , order ) ;
}
}
else
return false ;
}
}
static bool unit_list_hotkey ( df : : viewscreen * screen )
static bool unit_list_hotkey ( df : : viewscreen * screen )
{
{
vector < string > dummy ;
auto focus = Gui : : getFocusString ( screen ) ;
return maybe_sort_units ( NULL , NULL , screen , dummy ) ;
return findPrefixInMap ( unit_sorters , focus ) ! = NULL ;
}
}
static command_result sort_units ( color_ostream & out , vector < string > & parameters )
static command_result sort_units ( color_ostream & out , vector < string > & parameters )
@ -544,89 +461,75 @@ static command_result sort_units(color_ostream &out, vector <string> ¶meters
auto L = Lua : : Core : : State ;
auto L = Lua : : Core : : State ;
auto screen = Core : : getInstance ( ) . getTopViewscreen ( ) ;
auto screen = Core : : getInstance ( ) . getTopViewscreen ( ) ;
if ( ! maybe_sort_units ( & out , L , screen , parameters ) )
Lua : : StackUnwinder top ( L ) ;
if ( ! prepare_sort ( & out , L ) )
return CR_WRONG_USAGE ;
return CR_WRONG_USAGE ;
auto focus = Gui : : getFocusString ( screen ) ;
auto handler = findPrefixInMap ( unit_sorters , focus ) ;
if ( ! handler )
return CR_WRONG_USAGE ;
else
handler ( & out , L , top , screen , parameters ) ;
return CR_OK ;
return CR_OK ;
}
}
static bool maybe_sort_items ( color_ostream * pout , lua_State * L ,
static std : : map < std : : string , SortHandler > item_sorters ;
df : : viewscreen * screen , vector < string > & parameters )
{
Lua : : StackUnwinder top ( L ) ;
if ( ! prepare_sort ( pout , L ) )
return false ;
std : : vector < unsigned > order ;
DEFINE_SORT_HANDLER ( item_sorters , tradegoods , " /Items/Broker " , trade )
{
PARSE_SPEC ( " items " , parameters ) ;
if ( auto trade = strict_virtual_cast < df : : viewscreen_tradegoodsst > ( screen ) )
if ( compute_order ( * pout , L , top , & order , trade - > broker_items ) )
{
{
if ( ! L ) return true ;
reorder_cursor ( & trade - > broker_cursor , order ) ;
reorder_vector ( & trade - > broker_items , order ) ;
PARSE_SPEC ( " items " , parameters ) ;
reorder_vector ( & trade - > broker_selected , order ) ;
reorder_vector ( & trade - > broker_count , order ) ;
if ( trade - > in_right_pane )
{
if ( compute_order ( * pout , L , top , & order , trade - > broker_items ) )
{
reorder_cursor ( & trade - > broker_cursor , order ) ;
reorder_vector ( & trade - > broker_items , order ) ;
reorder_vector ( & trade - > broker_selected , order ) ;
reorder_vector ( & trade - > broker_count , order ) ;
}
}
else
{
if ( compute_order ( * pout , L , top , & order , trade - > trader_items ) )
{
reorder_cursor ( & trade - > trader_cursor , order ) ;
reorder_vector ( & trade - > trader_items , order ) ;
reorder_vector ( & trade - > trader_selected , order ) ;
reorder_vector ( & trade - > trader_count , order ) ;
}
}
return true ;
}
}
else if ( auto bring = strict_virtual_cast < df : : viewscreen_layer_assigntradest > ( screen ) )
}
{
auto list1 = getLayerList ( bring , 0 ) ;
auto list2 = getLayerList ( bring , 1 ) ;
if ( ! list1 | | ! list2 | | ! list2 - > bright )
return false ;
int list_idx = vector_get ( bring - > visible_lists , list1 - > cursor , ( int16_t ) - 1 ) ;
DEFINE_SORT_HANDLER ( item_sorters , tradegoods , " /Items/Trader " , trade )
unsigned num_lists = sizeof ( bring - > lists ) / sizeof ( std : : vector < int32_t > ) ;
{
if ( unsigned ( list_idx ) > = num_lists )
PARSE_SPEC ( " items " , parameters ) ;
return false ;
if ( ! L ) return true ;
if ( compute_order ( * pout , L , top , & order , trade - > trader_items ) )
{
reorder_cursor ( & trade - > trader_cursor , order ) ;
reorder_vector ( & trade - > trader_items , order ) ;
reorder_vector ( & trade - > trader_selected , order ) ;
reorder_vector ( & trade - > trader_count , order ) ;
}
}
PARSE_SPEC ( " items " , parameters ) ;
DEFINE_SORT_HANDLER ( item_sorters , layer_assigntrade , " /Items " , bring )
{
auto list1 = getLayerList ( bring , 0 ) ;
auto list2 = getLayerList ( bring , 1 ) ;
int list_idx = vector_get ( bring - > visible_lists , list1 - > cursor , ( int16_t ) - 1 ) ;
auto & vec = bring - > lists [ list_idx ] ;
PARSE_SPEC ( " items " , parameters ) ;
std : : vector < df : : item * > items ;
auto & vec = bring - > lists [ list_idx ] ;
for ( size_t i = 0 ; i < vec . size ( ) ; i + + )
items . push_back ( bring - > info [ vec [ i ] ] - > item ) ;
if ( compute_order ( * pout , L , top , & order , items ) )
std : : vector < df : : item * > items ;
{
for ( size_t i = 0 ; i < vec . size ( ) ; i + + )
reorder_cursor ( & list2 - > cursor , order ) ;
items . push_back ( bring - > info [ vec [ i ] ] - > item ) ;
reorder_vector ( & vec , order ) ;
}
return true ;
if ( compute_order ( * pout , L , top , & order , items ) )
{
reorder_cursor ( & list2 - > cursor , order ) ;
reorder_vector ( & vec , order ) ;
}
}
else
return false ;
}
}
static bool item_list_hotkey ( df : : viewscreen * screen )
static bool item_list_hotkey ( df : : viewscreen * screen )
{
{
vector < string > dummy ;
auto focus = Gui : : getFocusString ( screen ) ;
return maybe_sort_items( NULL , NULL , screen , dummy ) ;
return findPrefixInMap( item_sorters , focus ) ! = NULL ;
}
}
static command_result sort_items ( color_ostream & out , vector < string > & parameters )
static command_result sort_items ( color_ostream & out , vector < string > & parameters )
@ -637,8 +540,18 @@ static command_result sort_items(color_ostream &out, vector <string> ¶meters
auto L = Lua : : Core : : State ;
auto L = Lua : : Core : : State ;
auto screen = Core : : getInstance ( ) . getTopViewscreen ( ) ;
auto screen = Core : : getInstance ( ) . getTopViewscreen ( ) ;
if ( ! maybe_sort_items ( & out , L , screen , parameters ) )
Lua : : StackUnwinder top ( L ) ;
if ( ! prepare_sort ( & out , L ) )
return CR_WRONG_USAGE ;
return CR_WRONG_USAGE ;
auto focus = Gui : : getFocusString ( screen ) ;
auto handler = findPrefixInMap ( item_sorters , focus ) ;
if ( ! handler )
return CR_WRONG_USAGE ;
else
handler ( & out , L , top , screen , parameters ) ;
return CR_OK ;
return CR_OK ;
}
}