#
## Customizable Domestic Advisor Mod v 0.91
## for Sid Meier's Civilization 4
## Copyright Firaxis Games 2005
#
#  Created by Lee Reeves, AKA Taelis on civfanatics.com

## REQUIRES Civilization 4 - Beyond the Sword - PATCH 3.02

## Ported to BtS and modified for BUG by EmperorFool
#
#    - Added BtS columns (e.g. corporations and espionage) and "Liberate Colony" button.
#    - Added other new columns (e.g. turns until culture growth and great person birth).
#    - Added a set of building class columns that show the building type for the civ you're playing.
#    - Added a second set of building type/class columns that show if you have the building or not
#      instead of the effects of the building. These columns are narrower than the originals.
#    - Changed most building columns to use the building's icon instead of its name.
#    - Resource columns now show their icon as the header and their effects as the value.
#    - Fixed crash caused when you have more than 20 or so cities.
#    - Added page switching buttons that wrap around.
#    - Added buttons to move pages while customizing.
#    - Added a button to toggle whether or not to display the controls for changing specialists.
#    - Added base experience for units in production and optional icons/coloring for the producing list.
#
## Credits
#
#    This advisor was inspired by the fantastic work of Homegrown and Requies of civfanatics.com, and all
#    those who contributed to their work. I'd like to thank:
#
#      Cammagno - for extensive help with beta testing, and for developing a complete, optimized configuration file
#
#      Homegrown - for the original domestic advisor mod with its many improvements
#
#      Requies - for the "Special" Domestic Advisor, the basis of this mod. Credits from his mod include:
#
#        terrasol - "for the changes to the color of the text to indicate problem values and for changes 
#                    which fix the non-English language problems and additional small changes"
#        Arkeide - "for the base code to jumping to a city on the list."
#        rendermad - "for the suggestion of making garrison colored when < 1"
#        =DOCTOR= - "for the suggestion of putting in Culture and GP Thresholds"
#        Tubby Rower - "for the unfortunately unimplementable mouseover idea"
#        eotinb - "for the suggestion of putting in the city automation information and for some general 
#                  comments and ideas"
#        sportybrian - "for the suggestion of highlighting with different colors for the 0, and very positive levels."
#
#     Fixaxis, of course, for making CivIV and stealing months of my life. ;)

## Legal Stuff
#
#  THIS MATERIAL IS NOT MADE, GUARANTEED OR SUPPORTED BY THE PUBLISHER OF THE SOFTWARE OR ITS AFFILIATES.
#  THIS MATERIAL IS RELEASED AS-IS. IN NO EVENT WILL THE AUTHOR BE LIABLE FOR SPECIAL, INCIDENTAL OR 
#  CONSEQUENTIAL DAMAGES RESULTING FROM POSSESSION, USE OR MALFUNCTION OF THE SOFTWARE, INCLUDING 
#  DAMAGES TO PROPERTY, LOSS OF GOODWILL, COMPUTER FAILURE OR MALFUNCTION AND, TO THE EXTENT PERMITTED 
#  BY LAW, DAMAGES FOR PERSONAL INJURIES, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 
#  DAMAGES. THE AUTHOR’S LIABILITY SHALL NOT EXCEED THE ACTUAL PRICE PAID FOR USE OF THE MATERIAL. SOME 
#  STATES/COUNTRIES DO NOT ALLOW LIMITATIONS ON HOW LONG AN IMPLIED WARRANTY LASTS AND/OR THE EXCLUSION 
#  OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THE ABOVE LIMITATIONS AND/OR EXCLUSION OR 
#  LIMITATION OF LIABILITY MAY NOT APPLY TO YOU. THIS WARRANTY GIVES YOU SPECIFIC LEGAL RIGHTS, AND 
#  YOU MAY HAVE OTHER RIGHTS THAT VARY FROM JURISDICTION TO JURISDICTION.

###############################################################################################################

from CvPythonExtensions import *

import PyHelpers
import CvUtil
import CvScreenEnums
import CvEventInterface
import Popup as PyPopup

import BugConfigTracker
import BugCore
import BugPath
import BugUtil
import FontUtil
import GameUtil

# BUG - Mac Support - start
BugUtil.fixSets(globals())
# BUG - Mac Support - end

import math

PyPlayer = PyHelpers.PyPlayer

CityScreenOpt = BugCore.game.CityScreen
AdvisorOpt = BugCore.game.CustDomAdv
MainOpt = BugCore.game.MainInterface

# Needed to save changes
import pickle

# Needed to check for non-numbers (specially search function)
import re

import time

gc = CyGlobalContext()

#   IMPORTANT INFORMATION
#   
#   All widget names MUST be unique when creating screens.  If you create
#   a widget named 'Hello', and then try to create another named 'Hello', it
#   will modify the first hello.
#
#   Also, when attaching widgets, 'Background' is a reserve word meant for
#   the background widget.  Do NOT use 'Background' to name any widget, but
#   when attaching to the background, please use the 'Background' keyword.

# globals
gc = CyGlobalContext()
ArtFileMgr = CyArtFileMgr()
localText = CyTranslator()

# Reposition if resolution (or language) changes
g_bMustCreatePositions = True
def forcePositionCalc (*args):
    global g_bMustCreatePositions
    g_bMustCreatePositions = True

# used to access the customizing flag
g_advisor = None
def isCustomizing():
    return g_advisor.customizing

# widget help text
def getEditHelpText(eWidgetType, iData1, iData2, bOption):
    if isCustomizing():
        return BugUtil.getPlainText("TXT_KEY_CDA_STOP_EDITING")
    else:
        return BugUtil.getPlainText("TXT_KEY_CDA_START_EDITING")


# Class CvDomesticAdvisor

class CvCustomizableDomesticAdvisor:
    """Special Domestic Advisor Screen"""

    def __init__(self):
        """
        Basic init function.
        Called when cIV is first booted up and everytime you switch into cIV
        """

        self.isFlavorful = True

        self.PICKLED_VERSION = 1

        self.NO_CITY = -1

        self.runtimeInitDone = False

        self.listSelectedCities = []

        # An event context for renaming pages
        self.renameEventContext = None

        # All size information moved to self.createPositions because they are now
        # all based on the screen resolution and the screen isn't available yet.

        # Names of Widgets
        self.SCREEN_NAME = "DomesticAdvisor"
        self.EXIT_NAME = "DomesticExit"
        self.BACKGROUND_ID = "DomesticAdvisorBG"
        self.PAGES_DD_NAME = "DomPagesDD"

        self.CULTURE_TEXT_NAME = "DomCultureText"
        self.GP_TEXT_NAME = "DomGPText"
        self.NUMBER_TEXT = "NUM"

        self.SPECIALIST_IMAGE_NAME = "DomCitizenImage"
        self.SPECIALIST_PLUS_NAME = "DomIncreaseSpecialist"
        self.SPECIALIST_MINUS_NAME = "DomDecreaseSpecialist"
        self.SPECIALIST_TEXT_NAME = "DomSpecialistText"

        self.CUSTOMIZE_PAGE = "DomCustomize"
        self.COLUMNS_LIST_PAGE = "DomColumnsList"
        
        self.PREV_PAGE_NAME = "DomPagePrevButton"
        self.NEXT_PAGE_NAME = "DomPageNextButton"
        self.START_CUSTOMIZING_NAME = "DomStartCustomizing"
        self.RENAME_PAGE_NAME = "DomRenamePage"
        self.ADD_PAGE_NAME = "DomAddPageButton"
        self.DEL_PAGE_NAME = "DomDelPageButton"
        self.PAGE_UP_NAME = "DomPageUpButton"
        self.PAGE_DOWN_NAME = "DomPageDownButton"
        self.SAVE_NAME = "DomSaveButton"
        self.RELOAD_PAGES_NAME = "DomReloadPages"

        self.COLUMN_SHRINK_NAME = "DomColShrink"
        self.COLUMN_WIDEN_NAME = "DomColWiden"
        self.ADDCOLUMN_NAME = "DomAddCol"
        self.DELCOLUMN_NAME = "DomDelCol"
        self.COLUMNUP_NAME = "DomColUp"
        self.COLUMNDN_NAME = "DomColDn"
        
        self.TOGGLE_SPECS_NAME = "ToggleSpecsCB"

        self.customizing = False
        self.currentPageNum = 0
        
        global g_advisor
        g_advisor = self

        # Special Class variables

        # The currently active page
        self.currentPage = None
        self.visiblePage = None

        self.COLUMNS_LIST = [
                # Name                      Width    Type   CyCityFunction0         CyCityFunction1         Arg                                 selfFunction                            Arg                         Title

                ("NAME",                    95,     "text", CyCity.getName,         None,                   0,                                  None,                                   None,                       "localText.getText(\"TXT_KEY_DOMESTIC_ADVISOR_NAME\", ()).upper()"),
                ("ADVISE_CULTURE",          150,    "text", None,                   None,                   0,                                  self.advise,                            "Culture",                  "localText.getText(\"TXT_KEY_CONCEPT_CULTURE\", ()).upper()"),
                ("ADVISE_MILITARY",         150,    "text", None,                   None,                   0,                                  self.advise,                            "Military",                 "localText.getText(\"TXT_KEY_ADVISOR_MILITARY\", ()).upper()"),
                ("ADVISE_NUTTY",            150,    "text", None,                   None,                   0,                                  self.advise,                            "Nutty",                    "u\"NUTTY\""),
                ("ADVISE_RELIGION",         150,    "text", None,                   None,                   0,                                  self.advise,                            "Religion",                 "localText.getText(\"TXT_KEY_CONCEPT_RELIGION\", ()).upper()"),
                ("ADVISE_RESEARCH",         150,    "text", None,                   None,                   0,                                  self.advise,                            "Research",                 "localText.getText(\"TXT_KEY_COMMERCE_RESEARCH\", ()).upper()"),
                ("ADVISE_SPACESHIP",        150,    "text", None,                   None,                   0,                                  self.advise,                            "Spaceship",                "localText.getText(\"TXT_KEY_CONCEPT_SPACESHIP\", ()).upper()"),
                ("AUTOMATION",              80,     "text", None,                   None,                   0,                                  self.calculateAutomation,               None,                       "u\"AUTO\""),
                ("BASE_COMMERCE",           38,     "int",  None,                   CyCity.getBaseYieldRate, YieldTypes.YIELD_COMMERCE,         None,                                   None,                       "u\"B\" + self.commerceIcon"),
                ("BASE_FOOD",               38,     "int",  None,                   CyCity.getBaseYieldRate, YieldTypes.YIELD_FOOD,             None,                                   None,                       "u\"B\" + self.foodIcon"),
                ("BASE_PRODUCTION",         38,     "int",  None,                   CyCity.getBaseYieldRate, YieldTypes.YIELD_PRODUCTION,       None,                                   None,                       "u\"B\" + self.hammerIcon"),
                ("CONSCRIPT_ANGER",         38,     "int",  None,                   None,                   0,                                  self.calculateConscriptAnger,           None,                       "u\"D\" + self.unhappyIcon"),
                ("CONSCRIPT_UNIT",          90,     "text", None,                   None,                   0,                                  self.calculateConscriptUnit,            None,                       "localText.getText(\"TXT_KEY_CONCEPT_DRAFT\", ()).upper()"),
                ("COULD_CONSCRIPT_UNIT",    90,     "text", None,                   None,                   0,                                  self.calculatePotentialConscriptUnit,   None,                       "localText.getText(\"TXT_KEY_CONCEPT_DRAFT\", ()).upper() + u\"#\""),
                ("CORPORATIONS",            90,     "text", None,                   None,                   0,                                  self.calculateCorporations,             None,                       "localText.getText(\"TXT_KEY_CONCEPT_CORPORATIONS\", ()).upper()"),
                ("CULTURE",                 53,     "int",  None,                   None,                   0,                                  self.calculateTotalCulture,             None,                       "self.cultureIcon"),
                ("CULTURE_RATE",            38,     "int",  None,                   CyCity.getCommerceRate, CommerceTypes.COMMERCE_CULTURE,     None,                                   None,                       "self.cultureIcon + u\"R\""),
                ("CULTURE_TURNS",           38,     "int",  None,                   None,                   None,                               self.calculateCultureTurns,             None,                       "self.cultureIcon + u\"T\""),
                ("DEFENSE",                 60,     "int",  None,                   None,                   0,                                  self.calculateDefense,                  None,                       "self.defenseIcon"),
                ("ESPIONAGE",               38,     "int",  None,                   CyCity.getCommerceRate, CommerceTypes.COMMERCE_ESPIONAGE,   None,                                   None,                       "self.espionageIcon"),
                ("ESPIONAGE_DEF",           60,     "int",  CyCity.getEspionageDefenseModifier, None,       0,                                  self.calculateEspionageDefense,         None,                       "self.espionageIcon + u\"%\""),
                ("FEATURES",                106,    "text", None,                   None,                   0,                                  self.calculateFeatures,                 None,                       "localText.getText(\"TXT_KEY_MISC_FEATURES\", ())"),
                ("FOOD",                    35,     "int",  None,                   None,                   0,                                  self.calculateFood,                     None,                       "self.foodIcon"),
                ("FOUNDED",                 80,     "date", None,                   None,                   0,                                  self.calculateFounded,                  None,                       "localText.getText(\"TXT_KEY_DOMESTIC_ADVISOR_FOUNDED\", ()).upper()"),
                ("FREE_EXPERIENCE_LAND",    30,     "int",  None,                   None,                   0,                                  self.calculateFreeExperience,           "L",                        "self.landIcon"),
                ("FREE_EXPERIENCE_SEA",     30,     "int",  None,                   None,                   0,                                  self.calculateFreeExperience,           "S",                        "self.seaIcon"),
                ("FREE_EXPERIENCE_AIR",     30,     "int",  None,                   None,                   0,                                  self.calculateFreeExperience,           "A",                        "self.airIcon"),
                ("GARRISON",                30,     "int",  CyCity.getMilitaryHappinessUnits,   None,       0,                                  None,                                   None,                       "self.militaryIcon"),
                ("GOLD",                    38,     "int",  None,                   CyCity.getCommerceRate, CommerceTypes.COMMERCE_GOLD,        None,                                   None,                       "self.goldIcon"),
                ("GREATPEOPLE",             45,     "int",  CyCity.getGreatPeopleProgress,  None,           0,                                  None,                                   None,                       "self.figureheadIcon"),
                ("GREATPEOPLE_RATE",        38,     "int",  CyCity.getGreatPeopleRate,      None,           0,                                  None,                                   None,                       "self.figureheadIcon + u\"R\""),
                ("GREATPEOPLE_TURNS",       38,     "int",  None,                   None,                   None,                               self.calculateGreatPeopleTurns,         None,                       "self.figureheadIcon + u\"T\""),
                ("GROWTH",                  35,     "int",  None,                   None,                   0,                                  self.calculateGrowth,                   None,                       "self.redfoodIcon"),
                ("HAPPY",                   30,     "int",  None,                   None,                   0,                                  self.calculateNetHappiness,             None,                       "self.happyIcon"),
                ("HEALTH",                  30,     "int",  None,                   None,                   0,                                  self.calculateNetHealth,                None,                       "self.healthIcon"),
                ("HURRY_GOLD",              38,     "int",  None,                   None,                   0,                                  self.calculateHurryGoldCost,            None,                       "u\"H\" + self.goldIcon"),
                ("HURRY_POP",               38,     "int",  None,                   None,                   0,                                  self.calculateWhipPopulation,           None,                       "u\"H\" + self.angryIcon"),
                ("HURRY_POP_EXTRA",         38,     "int",  None,                   None,                   0,                                  self.calculateWhipOverflowProduction,   None,                       "u\"H\" + self.hammerIcon"),
                ("HURRY_POP_GOLD",          38,     "int",  None,                   None,                   0,                                  self.calculateWhipOverflowGold,         None,                       "u\"H\" + self.goldIcon"),
                ("HURRY_POP_ANGER",         38,     "int",  None,                   None,                   0,                                  self.calculateWhipAnger,                None,                       "u\"H\" + self.unhappyIcon"),
                ("LIBERATE",                35,     "int",  None,                   None,                   0,                                  self.canLiberate,                       None,                       "self.fistIcon"),
                ("MAINTENANCE",             30,     "int",  CyCity.getMaintenance,  None,                   0,                                  None,                                   None,                       "self.redGoldIcon"),
                ("NRANK_BASE_COMMERCE",     42,     "int",  None,                   CyCity.findBaseYieldRateRank, YieldTypes.YIELD_COMMERCE,    None,                                   None,                       "u\"B\" + self.commerceIcon + u\"n\""),
                ("NRANK_BASE_FOOD",         42,     "int",  None,                   CyCity.findBaseYieldRateRank, YieldTypes.YIELD_FOOD,        None,                                   None,                       "u\"B\" + self.foodIcon + u\"n\""),
                ("NRANK_BASE_PRODUCTION",   42,     "int",  None,                   CyCity.findBaseYieldRateRank, YieldTypes.YIELD_PRODUCTION,  None,                                   None,                       "u\"B\" + self.hammerIcon + u\"n\""),
                ("NRANK_COMMERCE",          38,     "int",  None,                   CyCity.findYieldRateRank, YieldTypes.YIELD_COMMERCE,        None,                                   None,                       "self.commerceIcon + u\"n\""),
                ("NRANK_FOOD",              38,     "int",  None,                   CyCity.findYieldRateRank, YieldTypes.YIELD_FOOD,            None,                                   None,                       "self.foodIcon + u\"n\""),
                ("NRANK_PRODUCTION",        38,     "int",  None,                   CyCity.findYieldRateRank, YieldTypes.YIELD_PRODUCTION,      None,                                   None,                       "self.hammerIcon + u\"n\""),
                ("NRANK_CULTURE",           38,     "int",  None,                   CyCity.findCommerceRateRank, CommerceTypes.COMMERCE_CULTURE,    None,                               None,                       "self.cultureIcon + u\"n\""),
                ("NRANK_GOLD",              38,     "int",  None,                   CyCity.findCommerceRateRank, CommerceTypes.COMMERCE_GOLD,   None,                                   None,                       "self.goldIcon + u\"n\""),
                ("NRANK_RESEARCH",          38,     "int",  None,                   CyCity.findCommerceRateRank, CommerceTypes.COMMERCE_RESEARCH,   None,                               None,                       "self.researchIcon + u\"n\""),
                ("NUM_SPECIALIST_GG",       30,     "int",  None,                   None,                   0,                                  self.countFreeSpecialists,              "GREAT_GENERAL",            "self.milInstructorIcon"),
                ("POPULATION",              35,     "int",  CyCity.getPopulation,   None,                   0,                                  None,                                   None,                       "localText.getText(\"TXT_KEY_POPULATION\", ()).upper()"),
                ("POPULATION_REAL",         65,     "int",  CyCity.getRealPopulation,   None,               0,                                  None,                                   None,                       "localText.getText(\"TXT_KEY_POPULATION\", ()).upper() + u\"#\""),
                ("POWER",                   50,     "text", None,                   None,                   0,                                  self.calculatePower,                    None,                       "self.powerIcon"),
                ("PRODUCING",               90,     "text", None,                   None,                   0,                                  self.calculateProducing,                None,                       "localText.getText(\"TXT_KEY_DOMESTIC_ADVISOR_PRODUCING\", ())"),
                ("PRODUCING_TURNS",         33,     "int",  None,                   None,                   0,                                  self.calculateProducingTurns,           None,                       "self.hammerIcon + u\"T\""),
                ("PRODUCTION",              38,     "int",  None,                   None,                   0,                                  self.calculateProduction,               None,                       "self.hammerIcon"),
                ("RELIGIONS",               90,     "text", None,                   None,                   0,                                  self.calculateReligions,                None,                       "localText.getText(\"TXT_KEY_ADVISOR_RELIGION\", ()).upper()"),
                ("RESEARCH",                38,     "int",  None,                   CyCity.getCommerceRate, CommerceTypes.COMMERCE_RESEARCH,    None,                                   None,                       "self.researchIcon"),
                ("SPECIALISTS",             209,    "text", None,                   None,                   0,                                  self.calculateSpecialists,              None,                       "localText.getText(\"TXT_KEY_CONCEPT_SPECIALISTS\", ()).upper()"),
                ("THREATS",                 60,     "text", None,                   None,                   0,                                  self.calculateThreats,                  None,                       "u\"Threats\""),
                ("TRADE",                   30,     "int",  None,                   None,                   0,                                  self.calculateTrade,                    None,                       "self.tradeIcon"),
                ("TRADE_DOMESTIC",          30,     "int",  None,                   None,                   0,                                  self.calculateTrade,                    "D",                        "u\"D\" + self.tradeIcon"),
                ("TRADE_FOREIGN",           30,     "int",  None,                   None,                   0,                                  self.calculateTrade,                    "F",                        "u\"F\" + self.tradeIcon"),
                ("TRADE_ROUTES",            30,     "int",  None,                   None,                   0,                                  self.countTradeRoutes,                  None,                       "u\"#\" + self.tradeIcon"),
                ("TRADE_ROUTES_DOMESTIC",   30,     "int",  None,                   None,                   0,                                  self.countTradeRoutes,                  "D",                        "u\"D#\" + self.tradeIcon"),
                ("TRADE_ROUTES_FOREIGN",    30,     "int",  None,                   None,                   0,                                  self.countTradeRoutes,                  "F",                        "u\"F#\" + self.tradeIcon"),
            ]

        # Values to check to see if we need to color the number as a problem
        self.PROBLEM_VALUES_DICT = {
            "GARRISON" : 0,
            "HAPPY" : -1,
            "HEALTH" : -1,
            "GROWTH" : -1,
            "FOOD" : -1,
            "HURRY_POP_ANGER" : 1,
            }

        # Values to check to see if we need to color the number as neutral
        self.NEUTRAL_VALUES_DICT = {
            "HAPPY" : 0,
            "HEALTH" : 0,
            "GROWTH" : 0,
            "FOOD" : 0,
            }

        # Values to check to see if we need to color the number as great
        self.GREAT_VALUES_DICT = {
            "HAPPY" : 6,
            "HEALTH" : 6,
            "FOOD" : 8,
            }

        # Values for whom coloring comparison is reversed; i.e. higher numbers are worse
        self.COMPARISON_REVERSED = [
            "HURRY_POP_ANGER",
            ]

        # Dictionary of the coloring dictionaries!
        self.COLOR_DICT_DICT = {
            "PROBLEM": self.PROBLEM_VALUES_DICT,
            "NEUTRAL": self.NEUTRAL_VALUES_DICT,
            "GREAT": self.GREAT_VALUES_DICT,            
            }


        # This creates the set of ALL coloring keys.
        # Do NOT touch.
        self.COLOR_SET = set()
        for clDict in self.COLOR_DICT_DICT.values():
            self.COLOR_SET.update (clDict.keys())

        # Values to change on an update
        # (True indicates update when we DON'T switch to/from food production)
        # Most of this MIGHT change because the computer might be switching
        # plots it's working or creating/removing specialists.

        self.UPDATE_DICT = {
            "HAPPY": False,
            "GROWTH" : False,
            "FOOD": False,
            "PRODUCTION": True,
            "BASE_COMMERCE": False,
            "GOLD": False,
            "RESEARCH": False,
            "CULTURE_RATE": False,
            "CULTURE_TURNS": False,
            "ESPIONAGE": False,
            "GREATPEOPLE_RATE": False,
            "GREATPEOPLE_TURNS": False,
            "PRODUCING": True,
            "PRODUCING_TURNS": True,
            "SPECIALISTS": False,
            "AUTOMATION": True
            }

        self.HEADER_DICT = None
        self.SPECIALIST_ICON_DICT = None
        self.AUTOMATION_ICON_DICT = None
        self.COLOR_DICT = None
# BUG - Production Grouping - start
        self.PROD_COLOR_DICT = None
# BUG - Production Grouping - end

        # Input handling functions
        self.DomesticScreenInputMap = {
            self.SPECIALIST_PLUS_NAME   : self.HandleSpecialistPlus,
            self.SPECIALIST_MINUS_NAME  : self.HandleSpecialistMinus,
            self.EXIT_NAME              : self.DomesticExit,
            
            self.ADDCOLUMN_NAME         : self.AddCol,
            self.DELCOLUMN_NAME         : self.DelCol,
            self.COLUMNUP_NAME          : self.MoveColUp,
            self.COLUMNDN_NAME          : self.MoveColDn,
            self.COLUMN_SHRINK_NAME     : self.shrinkCol,
            self.COLUMN_WIDEN_NAME      : self.widenCol,
            
            self.START_CUSTOMIZING_NAME : self.ModifyPage,
            self.SAVE_NAME              : self.save,
            self.ADD_PAGE_NAME          : self.addPage,
            self.DEL_PAGE_NAME          : self.delPage,
            self.PREV_PAGE_NAME         : self.previousPage,
            self.NEXT_PAGE_NAME         : self.nextPage,
            self.PAGE_UP_NAME           : self.upPage,
            self.PAGE_DOWN_NAME         : self.downPage,
            
            self.TOGGLE_SPECS_NAME      : self.toggleShowSpecialistControls,

            self.RELOAD_PAGES_NAME      : self.reloadPages,
            self.RENAME_PAGE_NAME       : self.renamePage,

            }

    def createDictionaries(self):
        """
        Creates Dictionaries we couldn't on init.
        """

        if(self.runtimeInitDone):
            return
        
        self.HURRY_TYPE_POP = gc.getInfoTypeForString("HURRY_POPULATION")
        self.HURRY_TYPE_GOLD = gc.getInfoTypeForString("HURRY_GOLD")
        
        self.angryIcon = u"%c" % CyGame().getSymbolID(FontSymbols.ANGRY_POP_CHAR)
        self.commerceIcon = u"%c" %(gc.getYieldInfo(YieldTypes.YIELD_COMMERCE).getChar())
        self.cultureIcon = u"%c" %(gc.getCommerceInfo(CommerceTypes.COMMERCE_CULTURE).getChar())
        self.defenseIcon = u"%c" % CyGame().getSymbolID(FontSymbols.DEFENSE_CHAR)
        self.espionageIcon = u"%c" %(gc.getCommerceInfo(CommerceTypes.COMMERCE_ESPIONAGE).getChar())
        self.fistIcon = u"%c" % CyGame().getSymbolID(FontSymbols.OCCUPATION_CHAR)
        self.foodIcon = u"%c" %(gc.getYieldInfo(YieldTypes.YIELD_FOOD).getChar())
        self.footIcon = u"%c" % CyGame().getSymbolID(FontSymbols.MOVES_CHAR)
        self.goldIcon = u"%c" %(gc.getCommerceInfo(CommerceTypes.COMMERCE_GOLD).getChar())
        self.redGoldIcon = u"%c" % CyGame().getSymbolID(FontSymbols.BAD_GOLD_CHAR)
        self.figureheadIcon = u"%c" % CyGame().getSymbolID(FontSymbols.GREAT_PEOPLE_CHAR)
        self.hammerIcon = u"%c" %(gc.getYieldInfo(YieldTypes.YIELD_PRODUCTION).getChar())
        self.happyIcon = u"%c" % CyGame().getSymbolID(FontSymbols.HAPPY_CHAR)
        self.healthIcon = u"%c" % CyGame().getSymbolID(FontSymbols.HEALTHY_CHAR)
        self.lawIcon = u"%c" % CyGame().getSymbolID(FontSymbols.DEFENSIVE_PACT_CHAR)
        self.militaryIcon = u"%c" % CyGame().getSymbolID(FontSymbols.STRENGTH_CHAR)
        self.powerIcon = u"%c" % CyGame().getSymbolID(FontSymbols.POWER_CHAR)
        self.redfoodIcon = u"%c" % CyGame().getSymbolID(FontSymbols.BAD_FOOD_CHAR)
        self.religionIcon = u"%c" % CyGame().getSymbolID(FontSymbols.RELIGION_CHAR)
        self.researchIcon = u"%c" %(gc.getCommerceInfo(CommerceTypes.COMMERCE_RESEARCH).getChar())
        self.sickIcon = u"%c" % CyGame().getSymbolID(FontSymbols.UNHEALTHY_CHAR)
        self.tradeIcon = u"%c" % CyGame().getSymbolID(FontSymbols.TRADE_CHAR)
        self.unhappyIcon = u"%c" % CyGame().getSymbolID(FontSymbols.UNHAPPY_CHAR)
        
        self.yieldIcons = {}
        for eYieldType in range(YieldTypes.NUM_YIELD_TYPES):
            info = gc.getYieldInfo(eYieldType)
            self.yieldIcons[eYieldType] = u"%c" % info.getChar()
        
        self.commerceIcons = {}
        for eCommerceType in range(CommerceTypes.NUM_COMMERCE_TYPES):
            info = gc.getCommerceInfo(eCommerceType)
            self.commerceIcons[eCommerceType] = u"%c" % info.getChar()

        self.starIcon = u"%c" % CyGame().getSymbolID(FontSymbols.STAR_CHAR)
        self.silverStarIcon = u"%c" % CyGame().getSymbolID(FontSymbols.SILVER_STAR_CHAR)
        self.bulletIcon = u"%c" % CyGame().getSymbolID(FontSymbols.BULLET_CHAR)

        self.milInstructorIcon = FontUtil.getChar(FontSymbols.MILITARY_INSTRUCTOR_CHAR)
        self.landIcon = FontUtil.getChar(FontSymbols.DOMAIN_LAND_CHAR)
        self.seaIcon = FontUtil.getChar(FontSymbols.DOMAIN_SEA_CHAR)
        self.airIcon = FontUtil.getChar(FontSymbols.DOMAIN_AIR_CHAR)
        self.cancelIcon = FontUtil.getChar(FontSymbols.CANCEL_CHAR)

        # Special symbols for building, wonder and project views
        self.objectIsPresent = "x"
        self.objectIsNotPresent = "-"
        self.objectCanBeBuild = "o"
        self.objectUnderConstruction = self.hammerIcon
        
        # add the colors dependant on the statuses
        self.objectHave = localText.changeTextColor (self.objectIsPresent, gc.getInfoTypeForString("COLOR_GREEN")) #"x"
        self.objectNotPossible = localText.changeTextColor (self.objectIsNotPresent, gc.getInfoTypeForString("COLOR_RED")) #"-"
        self.objectPossible = localText.changeTextColor (self.objectCanBeBuild, gc.getInfoTypeForString("COLOR_BLUE")) #"o"
        self.objectHaveObsolete = localText.changeTextColor (self.objectIsPresent, gc.getInfoTypeForString("COLOR_WHITE")) #"x"
        self.objectNotPossibleConcurrent = localText.changeTextColor (self.objectIsNotPresent, gc.getInfoTypeForString("COLOR_YELLOW")) #"-"
        self.objectPossibleConcurrent = localText.changeTextColor (self.objectCanBeBuild, gc.getInfoTypeForString("COLOR_YELLOW")) #"o"     
        
        # Corporation Yield and Commerce values by Bonus
        # Maps are { bonus -> { yield/commerce -> { corporation -> value } } }
        self.corpMaintPercent = gc.getWorldInfo(gc.getMap().getWorldSize()).getCorporationMaintenancePercent()
        self.bonusCorpYields = {}
        self.bonusCorpCommerces = {}
        for eCorp in range(gc.getNumCorporationInfos()):
            info = gc.getCorporationInfo(eCorp)
            for i in range(gc.getNUM_CORPORATION_PREREQ_BONUSES()):
                eBonus = info.getPrereqBonus(i)
                if (eBonus >= 0):
                    for eYield in range(YieldTypes.NUM_YIELD_TYPES):
                        iYieldValue = info.getYieldProduced(eYield)
                        if (iYieldValue != 0):
                            if (not self.bonusCorpYields.has_key(eBonus)):
                                self.bonusCorpYields[eBonus] = {}
                            if (not self.bonusCorpYields[eBonus].has_key(eYield)):
                                self.bonusCorpYields[eBonus][eYield] = {}
                            if (not self.bonusCorpYields[eBonus][eYield].has_key(eCorp)):
                                self.bonusCorpYields[eBonus][eYield][eCorp] = iYieldValue
                        
                    for eCommerce in range(CommerceTypes.NUM_COMMERCE_TYPES):
                        iCommerceValue = info.getCommerceProduced(eCommerce)
                        if (iCommerceValue != 0):
                            if (not self.bonusCorpCommerces.has_key(eBonus)):
                                self.bonusCorpCommerces[eBonus] = {}
                            if (not self.bonusCorpCommerces[eBonus].has_key(eCommerce)):
                                self.bonusCorpCommerces[eBonus][eCommerce] = {}
                            if (not self.bonusCorpCommerces[eBonus][eCommerce].has_key(eCorp)):
                                self.bonusCorpCommerces[eBonus][eCommerce][eCorp] = iCommerceValue

        self.loadPages()

        self.BUILDING_ICONS_DICT = { }
        self.BUILDING_DICT = { }
        self.BUILDING_INFO_LIST = []

#       extraBldgColumns = []
        for i in range(gc.getNumBuildingInfos()):
            info = gc.getBuildingInfo(i)
            desc = info.getDescription()
            key = self.getBuildingKey(i)

            self.BUILDING_DICT[key] = i
            self.BUILDING_INFO_LIST.append(info)

            icon = u""

            if info.isCapital() > 0:
                icon += self.starIcon
            elif info.isGovernmentCenter() > 0:
                icon += self.silverStarIcon

            if info.getReligionType() != -1:
                if info.getHolyCity() != -1:
                    icon += u"%c" %(gc.getReligionInfo(info.getReligionType()).getHolyCityChar())
                else:
                    icon += u"%c" %(gc.getReligionInfo(info.getReligionType()).getChar())
            
            if info.getFoodKept() > 0 or info.getSeaPlotYieldChange(YieldTypes.YIELD_FOOD) > 0:
                icon += self.foodIcon

            if info.getFreeExperience() > 0 or \
                info.getFreePromotion() != -1 or \
                info.getGlobalFreeExperience() > 0 or \
                info.getDomainFreeExperience(DomainTypes.DOMAIN_LAND) > 0 or \
                info.getDomainFreeExperience(DomainTypes.DOMAIN_SCOUT) > 0 or \
                info.getDomainFreeExperience(DomainTypes.DOMAIN_SEA) > 0 or \
                info.getDomainFreeExperience(DomainTypes.DOMAIN_AIR) > 0:
                icon += self.militaryIcon

            if info.getDefenseModifier() > 0 or \
                info.getAllCityDefenseModifier() > 0 or \
                info.getNukeModifier() < 0 or \
                info.getAirModifier() < 0:
                icon += self.defenseIcon

            if info.isPower() or info.isDirtyPower() or info.isAreaCleanPower():
                icon += self.powerIcon

            if info.getWarWearinessModifier() < 0 or info.getAnarchyModifier() > 0 or info.getGlobalWarWearinessModifier() < 0:
                icon += "[" + self.angryIcon + "]"

            if info.getCommerceModifier(CommerceTypes.COMMERCE_CULTURE) > 0:
                icon += self.cultureIcon

            if info.getCommerceModifier(CommerceTypes.COMMERCE_GOLD) > 0:
                icon += self.goldIcon

            if info.getCommerceModifier(CommerceTypes.COMMERCE_RESEARCH) > 0:
                icon += self.researchIcon

            if info.getCommerceModifier(CommerceTypes.COMMERCE_ESPIONAGE) > 0:
                icon += self.espionageIcon

            if info.getSpaceProductionModifier() > 0 \
                or info.getDomainProductionModifier(DomainTypes.DOMAIN_LAND) > 0 \
                or info.getDomainProductionModifier(DomainTypes.DOMAIN_SCOUT) > 0 \
                or info.getDomainProductionModifier(DomainTypes.DOMAIN_SEA) > 0 \
                or info.getDomainProductionModifier(DomainTypes.DOMAIN_AIR) > 0 \
                or info.getYieldChange(YieldTypes.YIELD_PRODUCTION) > 0:
                icon += self.hammerIcon

            if info.getTradeRouteModifier() > 0 or info.getTradeRoutes() > 0 or info.getCoastalTradeRoutes() > 0 \
            or info.getGlobalTradeRoutes() > 0 or info.getForeignTradeRouteModifier() > 0:
                icon += self.tradeIcon

            if info.getMaintenanceModifier() < 0:
                icon += self.commerceIcon

            if info.isNoUnhappiness():
                icon += self.happyIcon

            if info.isBuildingOnlyHealthy():
                icon += self.healthIcon

            if info.getHealth() < 0 or info.getGlobalHealth() < 0:
                icon += self.sickIcon

            if info.getGreatPeopleRateChange() > 0 or info.getGreatPeopleRateModifier() > 0:
                icon += self.figureheadIcon
            
            if info.getMovie():
                icon += self.starIcon

            self.COLUMNS_LIST.append((key, 50 + 15 * len(icon), "text", None, None, 0, self.calculateValue, None, u"u\"" + desc + u"\""))
            self.BUILDING_ICONS_DICT[key] = icon
#           extraBldgColumns.append(("BLDG_" + key, 22, "bldg", None, None, 0, self.calculateBuilding, i, "u\"%s\"" % desc))
        
        # Duplicate building columns
#       self.COLUMNS_LIST += extraBldgColumns

        # Building classes
        for i in range(gc.getNumBuildingClassInfos()):
            info = gc.getBuildingClassInfo(i)
            key = "BLDGCLASS_" + info.getType()
            desc = info.getDescription()
            self.COLUMNS_LIST.append((key, 22, "bldgclass", None, None, 0, self.calculateBuildingClass, i, "u\"%s\"" % desc))

        # Civ-Specific Buildings
        for i in range(gc.getNumBuildingInfos()):
            info = gc.getBuildingInfo(i)
            classInfo = gc.getBuildingClassInfo(info.getBuildingClassType())
            if (classInfo.getDefaultBuildingIndex() != i):
                # Assume civ-specific if it isn't default building for its class
                key = "BLDGCIV_" + info.getType()
                desc = info.getDescription()
                self.COLUMNS_LIST.append((key, 22, "bldg", None, None, 0, self.calculateBuilding, i, "u\"%s\"" % desc))

        # Hurry types
        for i in range(gc.getNumHurryInfos()):
            header = "self.hammerIcon"
            name = "CAN_HURRY_"
            info = gc.getHurryInfo(i)
            if info.getGoldPerProduction() > 0:
                header += " + self.goldIcon"
                name += "GOLD"
            if info.getProductionPerPopulation() > 0 and info.isAnger():
                header += " + self.angryIcon"
                name += "WHIP"
            elif info.getProductionPerPopulation() > 0:
                header += " + self.happyIcon"
                name += "VOLUNTEERS"

            self.COLUMNS_LIST.append((name, 50, "text", None, None, 0, self.canHurry, i, header))

        # Resources ("bonuses") -- presence
        for i in range(gc.getNumBonusInfos()):
            info = gc.getBonusInfo(i)
            desc = u"%c" % info.getChar()
            key = "HAS_" + self.getBonusKey(i)

            self.COLUMNS_LIST.append((key, 24, "bonus", None, None, 0, self.calculateHasBonus, i, "u\"" + desc + "\""))

        # Resources ("bonuses") -- effects
        for i in range(gc.getNumBonusInfos()):
            info = gc.getBonusInfo(i)
            desc = u"%c" % info.getChar()
            key = self.getBonusKey(i)

            self.COLUMNS_LIST.append((key, 50, "text", None, None, 0, self.calculateBonus, i, "u\"" + desc + "\""))

        self.COLUMNS_INDEX = { }
        self.HEADER_DICT = { }

        for i, column in enumerate(self.COLUMNS_LIST):
            self.COLUMNS_INDEX[column[0]] = i
            self.HEADER_DICT[column[0]] = eval(column[8], globals(), locals())
                    
        if self.SPECIALIST_ICON_DICT == None:
            # Specialist Icon Information (Must be here, because C++ functions aren't
            # available upon startup of CIV)
            self.SPECIALIST_ICON_DICT = {
                0 : self.bulletIcon, # Citizen
                1 : self.happyIcon, # Priest
                2 : self.cultureIcon, # Artist
                3 : self.researchIcon, # Scientist
                4 : self.goldIcon, # Merchant
                5 : self.hammerIcon, # Engineer
                6 : self.espionageIcon, # Engineer
                }

        if self.AUTOMATION_ICON_DICT == None:
            # Automation Information (Must be here, because C++ functions aren't
            # available upon startup of CIV)
            self.AUTOMATION_ICON_DICT = {
                0 : self.foodIcon, # Emphasize Food
                1 : self.hammerIcon, # Emphasize Production
                2 : self.goldIcon, # Emphasize Gold?
                3 : self.researchIcon, # Emphasize Research
                4 : self.figureheadIcon, # Emphasize GP
                5 : self.redfoodIcon, # Emphasize Avoid Growth
                }

        if self.COLOR_DICT == None:
            # Colors to highlight with for each type of number (Must be here,
            #  because C++ functions aren't available upon startup of CIV)
            self.COLOR_DICT = {
                "PROBLEM": gc.getInfoTypeForString("COLOR_RED"),
                "NEUTRAL": gc.getInfoTypeForString("COLOR_YELLOW"),
                "GREAT": gc.getInfoTypeForString("COLOR_GREEN"),
                }

# BUG - Production Grouping - start
        if self.PROD_COLOR_DICT == None:
            # Colors to use for color-coding of production items.
            # ["DEFAULT"] is used if color-coding is off.
            self.PROD_COLOR_DICT = {
                "DEFAULT": gc.getInfoTypeForString("COLOR_WHITE"),
                "NOTHING": gc.getInfoTypeForString("COLOR_RED"),
                "BUILDING": gc.getInfoTypeForString("COLOR_WHITE"),
                "WONDER": gc.getInfoTypeForString("COLOR_CYAN"), 
                "WEALTH": gc.getInfoTypeForString("COLOR_YELLOW"),
                "RESEARCH": gc.getInfoTypeForString("COLOR_GREEN"),
                "CULTURE": gc.getInfoTypeForString("COLOR_MAGENTA"), 
                "PROJECT": gc.getInfoTypeForString("COLOR_CYAN"),
                "UNIT": gc.getInfoTypeForString("COLOR_YIELD_FOOD"),
                }
# BUG - Production Grouping - end

        self.switchPage(self.PAGES[0]["name"])

        self.runtimeInitDone = True

    def createPositions (self, screen):
        """ Calculates the basic positions to draw on. """

        # Borders from BUG Options
        nBorderTop = [0, 23, 52, 105][AdvisorOpt.getSpaceTop()]
        nBorderBottom = 177
        # If the min/max commerce buttons are shown, we need more space on the left
        nBorderLeft = 110
        if (MainOpt.isShowMinMaxCommerceButtons()):
            nBorderLeft = 150
        nBorderLeft = [0, 20, 40, nBorderLeft, nBorderLeft][AdvisorOpt.getSpaceSides()]
        nBorderRight = [0, 20, 40, nBorderLeft, 20][AdvisorOpt.getSpaceSides()]

        # Location/Size of the Overall Screen
        self.nScreenX = nBorderLeft
        self.nScreenWidth = screen.getXResolution() - nBorderLeft - nBorderRight
        self.nScreenY = nBorderTop
        self.nScreenLength = screen.getYResolution() - nBorderTop - nBorderBottom

        # Location/Size of the Panel
        # Panel no longer needs to be offset from screen since borders taken care of already.
        self.nPanelX = 0
        self.nPanelY = 0
        self.nPanelWidth = self.nScreenWidth #- (2 * self.nPanelX)
        self.nPanelLength = self.nScreenLength #- (2 * self.nPanelY)

        # Dimension of the table
        tableXOffset = 12
        tableYOffset = 13
        self.nTableX = self.nPanelX + tableXOffset
        self.nTableY = self.nPanelY + tableYOffset
        self.nTableWidth = self.nPanelWidth - (2 * tableXOffset)
        self.nTableLength = self.nPanelLength - 40 - tableYOffset
        self.nShortTableLength = self.nPanelY + self.nPanelLength - 140 # was 400 when nPanelLength was 562

        self.nSecondHalfTableX = self.nTableX + self.nTableWidth / 2 + 10
        self.nHalfTableWidth = self.nTableWidth / 2 - 10

        self.nCustomizeControlY = self.nPanelY + self.nPanelLength - 120 # was 450 when nPanelLength was 562

        BugUtil.debug("CDA Screen: %d x %d from (%d, %d) to (%d, %d)" %(self.nScreenWidth, self.nScreenLength, self.nScreenX, self.nScreenY, self.nScreenX + self.nScreenWidth, self.nScreenY + self.nScreenLength))
        BugUtil.debug("CDA Panel: %d x %d from (%d, %d) to (%d, %d)" %(self.nPanelWidth, self.nPanelLength, self.nPanelX, self.nPanelY, self.nPanelX + self.nPanelWidth, self.nPanelY + self.nPanelLength))
        BugUtil.debug("CDA Table: %d x %d from (%d, %d) to (%d, %d)" %(self.nTableWidth, self.nTableLength, self.nTableX, self.nTableY, self.nTableX + self.nTableWidth, self.nTableY + self.nTableLength))

        # Location of Text Buttons
        self.X_EXIT = self.nTableX + self.nTableWidth
        self.Y_EXIT = self.nPanelLength + self.nPanelY - 32
        self.Y_TEXT = self.nPanelLength + self.nPanelY - 27
        self.Z_TEXT = -0.1
        self.DX_TEXT = -200

# BUG - Colony Split - start

        # Location of Split Empire Button; make sure it leaves enough room for exit text
        self.SPLIT_NAME = "DomesticSplit"
        nExitTextWidth = CyInterface().determineWidth(localText.getText("TXT_KEY_PEDIA_SCREEN_EXIT", ()).upper())
        nPauseTextWidth = CyInterface().determineWidth(localText.getText("TXT_KEY_MOD_UNPAUSE", ()).upper())
        self.X_SPLIT = self.X_EXIT - 50 - nExitTextWidth
        self.X_SPLITPAUSE = self.X_EXIT - 50 - nPauseTextWidth
        self.Y_SPLIT = self.Y_TEXT - 8

# BUG - Colony Split - end

        # Building Button Headers
        self.BUILDING_BUTTON_X_SIZE = 24
        self.BUILDING_BUTTON_Y_SIZE = 24

        # Location of Specialist Toggle Button
        self.X_SPECIAL = self.nTableX
        self.Y_SPECIAL = self.Y_TEXT - 10
        
        # Width of page dropdown
        self.PAGES_DD_W = 300

        # Location of Culture Threshold Info
        self.nCultureLevelX = self.nPanelX + self.nPanelWidth - 354 # was 670 when nPanelWidth was 1024
        self.nCultureLevelY = self.nPanelY + self.nPanelLength - 120 # was 450 when nPanelLength was 562
        self.nCultureLevelDistance = 15
        self.nCultureLevelTextOffset = 110

        # Location of next GP Threshold Info
        self.nGPLevelX = self.nPanelX + self.nPanelWidth - 154 # was 870 when nPanelWidth was 1024
        self.nGPLevelY = self.nPanelY + self.nPanelLength - 120 # was 450 when nPanelLength was 562
        self.nGPLevelDistance = 30

        self.nControlSize = 28

        # Location/Size of the Specialist Images
        self.nFirstSpecialistX = self.nPanelX + 30
        self.nSpecialistY = self.nPanelY + self.nPanelLength - 120 # was 450 when nPanelLength was 562
        self.nSpecialistWidth = 32
        self.nSpecialistLength = 32
        self.nSpecialistDistance = 70

        # Offset from Specialist Image/Size for the Specialist Plus/Minus buttons
        self.nPlusOffsetX = -4
        self.nMinusOffsetX = 16
        self.nPlusOffsetY = self.nMinusOffsetY = 30
        self.nPlusWidth = self.nPlusHeight = self.nMinusWidth = self.nMinusHeight = 20

        # Offset from Specialist Image for the Specialist Text
        self.nSpecTextOffsetX = 0
        self.nSpecTextOffsetY = 50

        # Flag so that we only do this again if really necessary
        global g_bMustCreatePositions
        g_bMustCreatePositions = False

    def getScreen(self):
        """ Return the screen we draw with. """
        return CyGInterfaceScreen(self.SCREEN_NAME, CvScreenEnums.DOMESTIC_ADVISOR)

    def getCurrentCity (self):
        """ Get the current selected city."""
        screen = self.getScreen()
        iPlayer = PyPlayer(CyGame().getActivePlayer())
        cityList = iPlayer.getCityList()
        for i in range(len(cityList)):
            if screen.isRowSelected(self.currentPage, i):
                for j in range(len(cityList)):
                    if(cityList[j].getName() == screen.getTableText(self.currentPage, 1, i)):
                        return cityList[j].city

        return None

    def getNumSpecialistInfos (self):
        """ Get the number of specialist types (that WE deal with)."""
        try:
            return len (self.SPECIALIST_ICON_DICT)
        except TypeError:
            return 0

    def getNumEmphasizeInfos (self):
        """ Get the number of emphasis types (that WE deal with)."""
        return len (self.AUTOMATION_ICON_DICT)

    def interfaceScreen(self):
        """
        Screen construction function.
        This is the function that's called whenever F1 is pressed.
        """

        # Initialize all the stuff we couldn't in the init function
        self.createDictionaries()

        screen = self.getScreen()
#       screen.setForcedRedraw (True)

        # createPositions determines our size/positions and should only
        # be called if something has changed.
        if g_bMustCreatePositions:
            self.createPositions (screen)

        screen.setDimensions (self.nScreenX, self.nScreenY, self.nScreenWidth, self.nScreenLength)
        screen.showScreen(PopupStates.POPUPSTATE_IMMEDIATE, False)
    
        # Draw the basic screen
        self.drawBasicScreen()

        # Draw the table and the rest based on the mode
        self.drawScreen (self.currentPage)
        
# BUG - Colony Split - start

        player = gc.getActivePlayer()
        if (player.canSplitEmpire()):
            self.bCanLiberate = true
        else:
            self.bCanLiberate = false
            (loopCity, iter) = player.firstCity(false)
            while (loopCity):
                if loopCity.getLiberationPlayer(false) != -1:
                    self.bCanLiberate = true
                    break
                (loopCity, iter) = player.nextCity(iter, false)
        
        if (self.bCanLiberate):
            screen.setImageButton( self.SPLIT_NAME, "", self.X_SPLIT, self.Y_SPLIT, 28, 28, WidgetTypes.WIDGET_ACTION, gc.getControlInfo(ControlTypes.CONTROL_FREE_COLONY).getActionInfoIndex(), -1 )
            screen.setStyle( self.SPLIT_NAME, "Button_HUDAdvisorVictory_Style" )

# BUG - Colony Split - end

    def drawBasicScreen (self):
        """
        Draws the Basic parts common to all Domestic Advisor Screens.
        """
        screen = self.getScreen()

        # Here we set the background widget and exit button, and we show the screen
        screen.addPanel( self.BACKGROUND_ID, u"", u"", True, False, self.nPanelX, self.nPanelY, self.nPanelWidth, self.nPanelLength, PanelStyles.PANEL_STYLE_MAIN )
        #screen.addDDSGFC( self.BACKGROUND_ID, ArtFileMgr.getInterfaceArtInfo("SCREEN_BG").getPath(), 0, 29, 1024, 592, WidgetTypes.WIDGET_GENERAL, -1, -1 )

        # Text Buttons
        screen.setText(self.EXIT_NAME, "Background", localText.getText("TXT_KEY_PEDIA_SCREEN_EXIT", ()).upper(), CvUtil.FONT_RIGHT_JUSTIFY, self.X_EXIT, self.Y_EXIT, self.Z_TEXT, FontTypes.TITLE_FONT, WidgetTypes.WIDGET_CLOSE_SCREEN, -1, -1 )

        # Unpause MOD
        screen.setText("DomesticUnpause", "Background", localText.getText("TXT_KEY_MOD_UNPAUSE", ()).upper(), CvUtil.FONT_LEFT_JUSTIFY, self.X_SPLITPAUSE, self.Y_EXIT, self.Z_TEXT, FontTypes.TITLE_FONT, WidgetTypes.WIDGET_GENERAL, 301311, 2013 )
        x = self.X_SPECIAL + self.PAGES_DD_W + 10

        # Buttons to switch screens
        screen.setImageButton( self.PREV_PAGE_NAME, ArtFileMgr.getInterfaceArtInfo("INTERFACE_BUTTONS_LEFT").getPath(), x, self.Y_SPECIAL, self.nControlSize, self.nControlSize, WidgetTypes.WIDGET_CDA_PREV_PAGE, -1, -1 )
        x += self.nControlSize + 2
        screen.setImageButton( self.NEXT_PAGE_NAME, ArtFileMgr.getInterfaceArtInfo("INTERFACE_BUTTONS_RIGHT").getPath(), x, self.Y_SPECIAL, self.nControlSize, self.nControlSize, WidgetTypes.WIDGET_CDA_NEXT_PAGE, -1, -1 )
        x += self.nControlSize + 12
        screen.addCheckBoxGFC(self.START_CUSTOMIZING_NAME, ArtFileMgr.getInterfaceArtInfo("INTERFACE_BTN_FOREIGN").getPath(), ArtFileMgr.getInterfaceArtInfo("BUTTON_HILITE_SQUARE").getPath(), x, self.Y_SPECIAL, self.nControlSize, self.nControlSize, WidgetTypes.WIDGET_CDA_EDIT_PAGE, -1, -1, ButtonStyles.BUTTON_STYLE_IMAGE )
        x += self.nControlSize + 2
        screen.setImageButton( self.RENAME_PAGE_NAME, ArtFileMgr.getInterfaceArtInfo("INTERFACE_BTN_EVENT_LOG").getPath(), x, self.Y_SPECIAL, self.nControlSize, self.nControlSize, WidgetTypes.WIDGET_CDA_RENAME_PAGE, -1, -1 )
        x += self.nControlSize + 2
        info = gc.getSpecialistInfo(gc.getInfoTypeForString("SPECIALIST_CITIZEN"))
        screen.addCheckBoxGFC(self.TOGGLE_SPECS_NAME, info.getTexture(), ArtFileMgr.getInterfaceArtInfo("BUTTON_HILITE_SQUARE").getPath(), x, self.Y_SPECIAL, self.nControlSize, self.nControlSize, WidgetTypes.WIDGET_CDA_TOGGLE_SPECIALISTS, -1, -1, ButtonStyles.BUTTON_STYLE_IMAGE )
        x += self.nControlSize + 2
        screen.setImageButton( self.ADD_PAGE_NAME, ArtFileMgr.getInterfaceArtInfo("INTERFACE_BUTTONS_PLUS").getPath(), x, self.Y_SPECIAL, self.nControlSize, self.nControlSize, WidgetTypes.WIDGET_CDA_ADD_PAGE, -1, -1 )
        x += self.nControlSize + 2
        screen.setImageButton( self.DEL_PAGE_NAME, ArtFileMgr.getInterfaceArtInfo("INTERFACE_BUTTONS_MINUS").getPath(), x, self.Y_SPECIAL, self.nControlSize, self.nControlSize, WidgetTypes.WIDGET_CDA_REMOVE_PAGE, -1, -1 )
        x += self.nControlSize + 2
        screen.setImageButton( self.PAGE_UP_NAME, ArtFileMgr.getInterfaceArtInfo("INTERFACE_GENERAL_UPARROW").getPath(), x, self.Y_SPECIAL, self.nControlSize, self.nControlSize, WidgetTypes.WIDGET_CDA_MOVE_PAGE_UP, -1, -1 )
        x += self.nControlSize + 2
        screen.setImageButton( self.PAGE_DOWN_NAME, ArtFileMgr.getInterfaceArtInfo("INTERFACE_GENERAL_DOWNARROW").getPath(), x, self.Y_SPECIAL, self.nControlSize, self.nControlSize, WidgetTypes.WIDGET_CDA_MOVE_PAGE_DOWN, -1, -1 )
        x += self.nControlSize + 12
        screen.setImageButton( self.SAVE_NAME, ArtFileMgr.getInterfaceArtInfo("INTERFACE_GENERAL_MENU_ICON").getPath(), x, self.Y_SPECIAL, self.nControlSize, self.nControlSize, WidgetTypes.WIDGET_CDA_SAVE, -1, -1 )
        x += self.nControlSize + 2
        screen.setImageButton( self.RELOAD_PAGES_NAME, ArtFileMgr.getInterfaceArtInfo("INTERFACE_BUTTONS_CANCEL").getPath(), x, self.Y_SPECIAL, self.nControlSize, self.nControlSize, WidgetTypes.WIDGET_CDA_RELOAD, -1, -1 )
        x += self.nControlSize + 2

        # Cultural Levels Text
        screen.setText (self.CULTURE_TEXT_NAME, "Background", self.cultureIcon, CvUtil.FONT_LEFT_JUSTIFY, self.nCultureLevelX, self.nCultureLevelY, self.Z_TEXT, FontTypes.TITLE_FONT, WidgetTypes.WIDGET_GENERAL, -1, -1)

        # Start with 2 because we need it farther from the icon.
        iCount = 2
        # For each cultural level
        for i in range (gc.getNumCultureLevelInfos()):
            pCultureLevel = gc.getCultureLevelInfo (i)
            # Get the value
            nValue = GameUtil.getCultureThreshold(i)
            # Only show non-zero levels
            if (nValue != 0):
                # Set text
                screen.setText (self.CULTURE_TEXT_NAME + str(i), "Background", "<font=2>" + pCultureLevel.getText() + "</font>", CvUtil.FONT_LEFT_JUSTIFY, self.nCultureLevelX, self.nCultureLevelY + (self.nCultureLevelDistance * iCount), self.Z_TEXT, FontTypes.GAME_FONT, WidgetTypes.WIDGET_GENERAL, -1, -1)
                # Set value
                screen.setText (self.CULTURE_TEXT_NAME + self.NUMBER_TEXT + str(i), "Background", "<font=2>" + str(nValue) + "</font>", CvUtil.FONT_RIGHT_JUSTIFY, self.nCultureLevelX + self.nCultureLevelTextOffset, self.nCultureLevelY + (self.nCultureLevelDistance * iCount), self.Z_TEXT, FontTypes.GAME_FONT, WidgetTypes.WIDGET_GENERAL, -1, -1)
                # Increment counter
                iCount += 1

        # get Player
        iPlayer = PyPlayer(CyGame().getActivePlayer())

        # GP Level Text
        screen.setText (self.GP_TEXT_NAME, "Background", self.figureheadIcon, CvUtil.FONT_RIGHT_JUSTIFY, self.nGPLevelX, self.nGPLevelY, self.Z_TEXT, FontTypes.TITLE_FONT, WidgetTypes.WIDGET_GENERAL, -1, -1)
        screen.setText (self.GP_TEXT_NAME + self.NUMBER_TEXT, "Background", "<font=2>" + str (iPlayer.player.greatPeopleThreshold(false)) + "</font>", CvUtil.FONT_RIGHT_JUSTIFY, self.nGPLevelX, self.nGPLevelY + self.nGPLevelDistance, self.Z_TEXT, FontTypes.GAME_FONT, WidgetTypes.WIDGET_GENERAL, -1, -1)

        # Header...
        #szText = "<font=4>" + localText.getText("TXT_KEY_DOMESTIC_ADVISOR_TITLE", ()).upper() + "</font>"
        #screen.setLabel( "DomesticTitleHeader", "Background", szText, CvUtil.FONT_CENTER_JUSTIFY, 472, 40, STANDARD_Z, FontTypes.TITLE_FONT, WidgetTypes.WIDGET_GENERAL, -1, -1 )

        # Draw the specialist (but don't SHOW them)
        self.drawSpecialists()

        # Draw the customization controls (but don't SHOW them)
        self.drawCustomizationControls()

    # Draw the specialist and their increase and decrease buttons
    def drawSpecialists (self):
        """ The function to draw but not show all the specialists."""
        screen = self.getScreen()

        # Citizen Buttons
        for i in range( self.getNumSpecialistInfos() ):
        
            if (gc.getSpecialistInfo(i).isVisible()):
            
                szName = self.SPECIALIST_IMAGE_NAME + str(i)
                screen.setImageButton( szName, gc.getSpecialistInfo(i).getTexture(), self.nFirstSpecialistX + (self.nSpecialistDistance * i), self.nSpecialistY, self.nSpecialistWidth, self.nSpecialistLength, WidgetTypes.WIDGET_CITIZEN, i, -1 )
                screen.hide( szName )

        # Increase Specialists...
        for i in range( self.getNumSpecialistInfos() ):
            if (gc.getSpecialistInfo(i).isVisible()):
                szName = self.SPECIALIST_PLUS_NAME + str(i)
                screen.setButtonGFC( szName, u"", "", self.nFirstSpecialistX + (self.nSpecialistDistance * i) + self.nPlusOffsetX, self.nSpecialistY + self.nPlusOffsetY, self.nPlusWidth, self.nPlusHeight, WidgetTypes.WIDGET_CHANGE_SPECIALIST, i, 1, ButtonStyles.BUTTON_STYLE_CITY_PLUS )
                screen.hide( szName )

        # Decrease specialists
        for i in range( self.getNumSpecialistInfos() ):
            if (gc.getSpecialistInfo(i).isVisible()):
                szName = self.SPECIALIST_MINUS_NAME + str(i)
                screen.setButtonGFC( szName, u"", "", self.nFirstSpecialistX + (self.nSpecialistDistance * i) + self.nMinusOffsetX, self.nSpecialistY + self.nMinusOffsetY, self.nMinusWidth, self.nMinusHeight, WidgetTypes.WIDGET_CHANGE_SPECIALIST, i, -1, ButtonStyles.BUTTON_STYLE_CITY_MINUS )
                screen.hide( szName )

        # Specialist text
        for i in range (self.getNumSpecialistInfos()):
            if (gc.getSpecialistInfo(i).isVisible()):
                szName = self.SPECIALIST_TEXT_NAME + str(i)
                screen.setText (szName, "Background", "", CvUtil.FONT_LEFT_JUSTIFY, self.nFirstSpecialistX + (self.nSpecialistDistance * i) + self.nSpecTextOffsetX, self.nSpecialistY + self.nSpecTextOffsetY, self.Z_TEXT, FontTypes.GAME_FONT, WidgetTypes.WIDGET_GENERAL, -1, -1)
                screen.hide (szName)

    def showSpecialists (self):
        """ Function which shows the specialists."""
        screen = self.getScreen()

        # First, hide the specialists! :D
        self.hideSpecialists()

        # Get the current city
        city = self.getCurrentCity()
        if (city):
            
            # Get values which we will need for each calculation
            nPopulation = city.getPopulation()
            nFreeSpecial = city.totalFreeSpecialists()

            # For each specialist type
            for i in range( self.getNumSpecialistInfos() ):

                # Show all the specialist images
                szName = self.SPECIALIST_IMAGE_NAME + str(i)
                screen.show( szName )

                # Show all the specialist text
                szName = self.SPECIALIST_TEXT_NAME + str(i)
                screen.setText (szName, "Background", str (city.getSpecialistCount(i)) + "/" + str (city.getMaxSpecialistCount(i)) + u" %c" % self.SPECIALIST_ICON_DICT[i], CvUtil.FONT_LEFT_JUSTIFY, self.nFirstSpecialistX + (self.nSpecialistDistance * i) + self.nSpecTextOffsetX, self.nSpecialistY + self.nSpecTextOffsetY, self.Z_TEXT, FontTypes.GAME_FONT, WidgetTypes.WIDGET_GENERAL, -1, -1)
                screen.show (szName)

                # If the specialist is valid and we can increase it
                if (city.isSpecialistValid(i, 1) and (city.getForceSpecialistCount(i) < (nPopulation + nFreeSpecial))):
                    # Show the Plus
                    szName = self.SPECIALIST_PLUS_NAME + str(i)
                    screen.show( szName )

                # if we HAVE specialists already and they're not forced.
                if (city.getSpecialistCount(i) > 0 or city.getForceSpecialistCount(i) > 0 ):
                    # Show the Minus
                    szName = self.SPECIALIST_MINUS_NAME + str(i)
                    screen.show( szName )
                            
    def hideSpecialists (self):
        """ Function to hide all the specialists and the accompanying data."""
        screen = self.getScreen()

        # Hide Everything related to specialists
        for i in range( self.getNumSpecialistInfos() ):
            szName = self.SPECIALIST_IMAGE_NAME + str(i)
            screen.hide (szName)
            szName = self.SPECIALIST_PLUS_NAME + str(i)
            screen.hide (szName)
            szName = self.SPECIALIST_MINUS_NAME + str(i)
            screen.hide (szName)
            szName = self.SPECIALIST_TEXT_NAME + str(i)
            screen.hide (szName)

    def showCultureLegend (self):

        screen = self.getScreen()
        screen.show(self.CULTURE_TEXT_NAME)
        # For each cultural level
        for i in range (gc.getNumCultureLevelInfos()):
                screen.show(self.CULTURE_TEXT_NAME + str(i))
                screen.show(self.CULTURE_TEXT_NAME + self.NUMBER_TEXT + str(i))

    def hideCultureLegend (self):

        screen = self.getScreen()
        screen.hide(self.CULTURE_TEXT_NAME)
        # For each cultural level
        for i in range (gc.getNumCultureLevelInfos()):
                screen.hide(self.CULTURE_TEXT_NAME + str(i))
                screen.hide(self.CULTURE_TEXT_NAME + self.NUMBER_TEXT + str(i))

    def showGPLegend(self):

        screen = self.getScreen()
        screen.show(self.GP_TEXT_NAME)
        screen.show(self.GP_TEXT_NAME + self.NUMBER_TEXT)

    def hideGPLegend(self):

        screen = self.getScreen()
        screen.hide(self.GP_TEXT_NAME)
        screen.hide(self.GP_TEXT_NAME + self.NUMBER_TEXT)

    def drawCustomizationControls(self):
        screen = self.getScreen()
        
        x = self.nTableX + self.nHalfTableWidth - self.nControlSize
        screen.setImageButton( self.COLUMNDN_NAME, ArtFileMgr.getInterfaceArtInfo("INTERFACE_GENERAL_DOWNARROW").getPath(), x, self.nCustomizeControlY, self.nControlSize, self.nControlSize, WidgetTypes.WIDGET_CDA_MOVE_COLUMN_DOWN, -1, -1 )
        x -= self.nControlSize + 2
        screen.setImageButton( self.COLUMNUP_NAME, ArtFileMgr.getInterfaceArtInfo("INTERFACE_GENERAL_UPARROW").getPath(), x, self.nCustomizeControlY, self.nControlSize, self.nControlSize, WidgetTypes.WIDGET_CDA_MOVE_COLUMN_UP, -1, -1 )
        x -= self.nControlSize + 2
        screen.setImageButton( self.DELCOLUMN_NAME, ArtFileMgr.getInterfaceArtInfo("INTERFACE_BUTTONS_MINUS").getPath(), x, self.nCustomizeControlY, self.nControlSize, self.nControlSize, WidgetTypes.WIDGET_CDA_REMOVE_COLUMN, -1, -1 )
        x -= self.nControlSize + 2
        screen.setImageButton( self.ADDCOLUMN_NAME, ArtFileMgr.getInterfaceArtInfo("INTERFACE_BUTTONS_PLUS").getPath(), x, self.nCustomizeControlY, self.nControlSize, self.nControlSize, WidgetTypes.WIDGET_CDA_ADD_COLUMN, -1, -1 )
        x -= self.nControlSize + 2
        screen.setImageButton( self.COLUMN_WIDEN_NAME, ArtFileMgr.getInterfaceArtInfo("INTERFACE_BUTTONS_RIGHT").getPath(), x, self.nCustomizeControlY, self.nControlSize, self.nControlSize, WidgetTypes.WIDGET_CDA_EXPAND_COLUMN, -1, -1 )
        x -= self.nControlSize + 2
        screen.setImageButton( self.COLUMN_SHRINK_NAME, ArtFileMgr.getInterfaceArtInfo("INTERFACE_BUTTONS_LEFT").getPath(), x, self.nCustomizeControlY, self.nControlSize, self.nControlSize, WidgetTypes.WIDGET_CDA_SHRINK_COLUMN, -1, -1 )
        
        self.hideCustomizationControls()

    def showCustomizationControls(self):

        screen = self.getScreen()

        screen.setState(self.START_CUSTOMIZING_NAME, True)

        # No need for screen.show(self.CUSTOMIZE_PAGE) - that table is redrawn.
        screen.show(self.COLUMNS_LIST_PAGE)
        screen.show(self.ADDCOLUMN_NAME)
        screen.show(self.DELCOLUMN_NAME)
        screen.show(self.COLUMNUP_NAME)
        screen.show(self.COLUMNDN_NAME)
        screen.show(self.COLUMN_SHRINK_NAME)
        screen.show(self.COLUMN_WIDEN_NAME)
        
        if self.isFlavorful:

            screen.show(self.RENAME_PAGE_NAME)
            screen.show(self.RENAME_PAGE_NAME)
            screen.show(self.ADD_PAGE_NAME)
            screen.show(self.DEL_PAGE_NAME)
            screen.show(self.PAGE_UP_NAME)
            screen.show(self.PAGE_DOWN_NAME)
            screen.show(self.SAVE_NAME)
            screen.show(self.RELOAD_PAGES_NAME)
            screen.show(self.TOGGLE_SPECS_NAME)
            
            page = self.PAGES[self.currentPageNum]
            screen.setState(self.TOGGLE_SPECS_NAME, page["showSpecControls"])

    def hideCustomizationControls(self):

        screen = self.getScreen()

        screen.setState(self.START_CUSTOMIZING_NAME, False)

        screen.hide(self.CUSTOMIZE_PAGE)
        screen.hide(self.COLUMNS_LIST_PAGE)
        screen.hide(self.ADDCOLUMN_NAME)
        screen.hide(self.DELCOLUMN_NAME)
        screen.hide(self.COLUMNUP_NAME)
        screen.hide(self.COLUMNDN_NAME)
        screen.hide(self.COLUMN_SHRINK_NAME)
        screen.hide(self.COLUMN_WIDEN_NAME)

        if self.isFlavorful:

            screen.hide(self.RENAME_PAGE_NAME)
            screen.hide(self.RENAME_PAGE_NAME)
            screen.hide(self.ADD_PAGE_NAME)
            screen.hide(self.DEL_PAGE_NAME)
            screen.hide(self.PAGE_UP_NAME)
            screen.hide(self.PAGE_DOWN_NAME)
            screen.hide(self.SAVE_NAME)
            screen.hide(self.RELOAD_PAGES_NAME)
            screen.hide(self.TOGGLE_SPECS_NAME)

    def hide (self, screen, page):
        """ Hide function which hides a specific screen."""
        screen.hide (page)
        self.hideSpecialists()
    
    def drawScreen (self, page):
        """ Draw the screen based on which mode we get."""
        screen = self.getScreen()

        # Change the visible page?
        if(not self.customizing and self.visiblePage != self.currentPage):
            if(self.visiblePage):
                screen.hide(self.visiblePage)

            screen.show(self.currentPage)
            self.visiblePage = self.currentPage

        # Hide the menu and Civilopedia buttons
        CyInterface().setDirty(InterfaceDirtyBits.MiscButtons_DIRTY_BIT, True)

        start = time.clock()
        # Draw the city list...
        self.drawContents (page)
        end = time.clock()
        BugUtil.debug("drawContents: " + str(end - start) + "s")

    def calculateFounded (self, city, szKey, arg):

        # City founded date...
        iTurnTime = city.getGameTurnFounded()
        return unicode(CyGameTextMgr().getTimeStr(iTurnTime, false))

    def calculateFeatures (self, city, szKey, arg):

        szReturn = ""

        # First look for Government Centers
        if city.isGovernmentCenter():
            # And distinguish between the Capital and the others (Forbidden Palace
            # and Versailles)
            if city.isCapital():
                szReturn += self.starIcon
            else:
                szReturn += self.silverStarIcon

        # add National Wonders
        for i in range(gc.getNumBuildingInfos()):
            info = gc.getBuildingInfo(i)
            classInfo = gc.getBuildingClassInfo(info.getBuildingClassType())
            if classInfo.getMaxGlobalInstances() == -1 and classInfo.getMaxPlayerInstances() == 1 and city.getNumBuilding(i) > 0 and not info.isCapital():
                # Use bullets as markers for National Wonders
                szReturn += self.bulletIcon

        if city.isDisorder():

            if city.isOccupation():
                szOccu = u"%c" % CyGame().getSymbolID(FontSymbols.OCCUPATION_CHAR)
                szReturn += szOccu +":"+unicode(city.getOccupationTimer())
            else:
                szReturn += self.angryIcon

        pTradeCity = city.getTradeCity(0)
        if (pTradeCity and pTradeCity.getOwner() >= 0):
            szReturn += self.tradeIcon

        return szReturn

    def calculateDefense(self, city, szKey, arg):
        return unicode(city.plot().defenseModifier(-1, True, False)) + u"%"

    def calculateEspionageDefense(self, city, szKey, arg):
        return unicode(city.getEspionageDefenseModifier()) + u"%"

    def calculateThreats(self, city, szKey, arg):

        szReturn = u""

        player = PyPlayer(CyGame().getActivePlayer())

        for i in range(gc.getMAX_PLAYERS()):
            if player.getTeam().isAtWar(gc.getPlayer(i).getTeam()):
                if city.isVisible(gc.getPlayer(i).getTeam(), False):
                    szReturn = self.angryIcon
                    break

        return szReturn

    def calculateNetHappiness (self, city, szKey="", arg=0):
        return city.happyLevel() - city.unhappyLevel(0)

    def calculateNetHealth (self, city, szKey="", arg=0):
        return city.goodHealth() - city.badHealth(False)

    def calculateGrowth (self, city, szKey, arg):
        szReturn = u""

        # Turns til Growth
        nFood = city.foodDifference (True)

        # If this is a food production (i.e., worker or settler)
        if (self.isFoodProduction(city.getProductionName())):
            # We need to indicate there's no growth manually
            szReturn = u"-"
        else:
            # Otherwise, just call FoodTurnsLeft
            szReturn = unicode (city.getFoodTurnsLeft())

        # Not enough food, so calculate how many turns until we starve.
        # We put this here because we still starve if building a food production
        if nFood < 0:
            # Use floor divide (//) because we want the number it'll drop below 0
            # (that's also the reason for the additional 1)
            szReturn = unicode ((city.getFood()+1) // nFood)

        return szReturn

    def calculateFood (self, city, szKey, arg):

        # If this is a food production (i.e., worker or settler)
        if (self.isFoodProduction(city.getProductionName())):
            nFood = city.getCurrentProductionDifference (False, False) - city.getCurrentProductionDifference (True, False)
        else:
            nFood = city.foodDifference (True)
        return nFood

    def calculateProduction (self, city, szKey, arg):
        return unicode(city.getCurrentProductionDifference (True, False))

    def calculateMaintenance (self, city, szKey, arg):
        return unicode(city.getMaintenance())

    def calculateTrade (self, city, szKey, arg):
        """arg: None to sum all, 'D' to count domestic, 'F' to count foreign."""
        nTotalTradeProfit = 0

        # For each trade route possible
        for nTradeRoute in range (gc.getDefineINT("MAX_TRADE_ROUTES")):
            # Get the next trade city
            pTradeCity = city.getTradeCity(nTradeRoute)
            # Not quite sure what this does but it's in the MainInterface
            # and I pretty much C&Ped :p
            if (pTradeCity and pTradeCity.getOwner() >= 0):
                bForeign = city.getOwner() != pTradeCity.getOwner()
                if (not arg or ((arg == "F" and bForeign) or (arg == "D" and not bForeign))):
                    for j in range( YieldTypes.NUM_YIELD_TYPES ):
                        iTradeProfit = city.calculateTradeYield(j, city.calculateTradeProfit(pTradeCity))
    
                        # If the TradeProfit is greater than 0, add it to the total
                        if ( iTradeProfit > 0 ):
                            nTotalTradeProfit += iTradeProfit

        return unicode(nTotalTradeProfit)

    def countTradeRoutes (self, city, szKey, arg):
        """arg: None to count all, 'D' to count domestic, 'F' to count foreign."""
        nRoutes = 0

        # For each trade route possible
        for nTradeRoute in range (gc.getDefineINT("MAX_TRADE_ROUTES")):
            # Get the next trade city
            pTradeCity = city.getTradeCity(nTradeRoute)
            # Not quite sure what this does but it's in the MainInterface
            # and I pretty much C&Ped :p
            if (pTradeCity and pTradeCity.getOwner() >= 0):
                bForeign = city.getOwner() != pTradeCity.getOwner()
                if (not arg or ((arg == "F" and bForeign) or (arg == "D" and not bForeign))):
                    nRoutes += 1

        return unicode(nRoutes)

    def countSpecialists (self, city, szKey, arg):
        """arg: specialist type string (excluding "SPECIALIST_") e.g. use "ARTIST" to count artist specialists"""
        szSpecialistType = "SPECIALIST_" + arg
        nCount = city.getSpecialistCount(gc.getInfoTypeForString(szSpecialistType))
        if nCount > 0:
            return unicode(nCount)
        else:
            return u"-"

    def countFreeSpecialists (self, city, szKey, arg):
        """arg: specialist type string (excluding "SPECIALIST_") e.g. use "ARTIST" to count artist specialists"""
        szSpecialistType = "SPECIALIST_" + arg
        nCount = city.getFreeSpecialistCount(gc.getInfoTypeForString(szSpecialistType))
        if nCount > 0:
            return unicode(nCount)
        else:
            return u"-"

    def calculateProducing (self, city, szKey, arg):

        szReturn = u""
# BUG - Production Grouping - start
        bProdColors = AdvisorOpt.isProductionGroupingColors()
        bProdIcons = AdvisorOpt.isProductionGroupingIcons()
# BUG - Production Grouping - end

        # If there's something in the queue,
        if (city.getOrderQueueLength() > 0):

            # Get the name of whatever it's producing.
            szReturn = city.getProductionName()

# BUG - Base XP for units - start
            # Note this has been separated out so that it is always in effect
            # even if user chooses to disable the production coloring/grouping
            if city.isProductionUnit():
                iUnit = city.getProductionUnit()
                pInfo = gc.getUnitInfo(iUnit)
                if pInfo.getUnitCombatType() != UnitCombatTypes.NO_UNITCOMBAT:
                    iExp = city.getProductionExperience(iUnit)
                    szReturn = szReturn + u" " + localText.getText("TXT_KEY_CDA_BASE_XP", (iExp,))
# BUG - Base XP for units - end

# BUG - Production Grouping - start
            if (bProdColors or bProdIcons):
                szColorKey = "DEFAULT"
                szIcon = self.hammerIcon
                if city.isProductionBuilding():
                    szColorKey = "WONDER"
                    pInfo = gc.getBuildingClassInfo(gc.getBuildingInfo(city.getProductionBuilding()).getBuildingClassType())
                    if pInfo.getMaxGlobalInstances() != -1:
                        szIcon = self.starIcon
                    elif pInfo.getMaxTeamInstances() != -1:
                        szIcon = self.silverStarIcon
                    elif pInfo.getMaxPlayerInstances() != -1:
                        szIcon = self.silverStarIcon
                    else:
                        szColorKey = "BUILDING"
                elif city.isProductionProcess():
                    iType = city.getProductionProcess()
                    if iType == gc.getInfoTypeForString("PROCESS_WEALTH"):
                        szColorKey = "WEALTH"
                        szIcon = self.goldIcon
                    elif iType == gc.getInfoTypeForString("PROCESS_RESEARCH"):
                        szColorKey = "RESEARCH"
                        szIcon = self.researchIcon
                    elif iType == gc.getInfoTypeForString("PROCESS_CULTURE"):
                        szColorKey = "CULTURE"
                        szIcon = self.cultureIcon
                elif city.isProductionProject():
                    szColorKey = "PROJECT"
                    pInfo = gc.getProjectInfo(city.getProductionProject())
                    if pInfo.getMaxGlobalInstances() != -1:
                        szIcon = self.starIcon
                    elif pInfo.getMaxTeamInstances() != -1:
                        szIcon = self.silverStarIcon
                elif city.isProductionUnit():
                    szColorKey = "UNIT"
                    iUnit = city.getProductionUnit()
                    pInfo = gc.getUnitInfo(iUnit)
                    iType = pInfo.getDomainType()
                    if pInfo.getUnitCombatType() != UnitCombatTypes.NO_UNITCOMBAT:
                        szIcon = self.militaryIcon
#                       if iType == DomainTypes.DOMAIN_SEA:
#                           szIcon = self.seaIcon
#                       elif iType == DomainTypes.DOMAIN_LAND:
#                           szIcon = self.landIcon
#                       elif iType == DomainTypes.DOMAIN_AIR:
#                           szIcon = self.airIcon
#                       elif iType == DomainTypes.DOMAIN_IMMOBILE:
#                           szIcon = self.airIcon
                    else:
                        szIcon = self.footIcon
                if bProdIcons:
                    szReturn = szIcon + szReturn
                if bProdColors:
                    szReturn = localText.changeTextColor (szReturn, self.PROD_COLOR_DICT[szColorKey])
# BUG - Production Grouping - end

        # Otherwise we're not producing anything. Leave it blank.
        else:
            szReturn = u"-"
# BUG - Production Grouping - start
            if bProdIcons:
                szReturn = self.cancelIcon + szReturn
            if bProdColors:
                szReturn = localText.changeTextColor (szReturn, self.PROD_COLOR_DICT["NOTHING"])
# BUG - Production Grouping - end

        return szReturn

    def calculateProducingTurns (self, city, szKey, arg):

        szReturn = u""

        # If there's something in the queue,
        if (city.getOrderQueueLength() > 0):

            # If it's not a process (i.e., Wealth, Research, Culture)
            if (not (city.isProductionProcess())):

                szReturn = unicode(city.getProductionTurnsLeft())

        return szReturn

    def calculateWhipPopulation (self, city, szKey, arg):
        
        if (city.canHurry(self.HURRY_TYPE_POP, False)):
            return unicode(city.hurryPopulation(self.HURRY_TYPE_POP))
        else:
            return self.objectNotPossible

    def calculateWhipOverflowProduction (self, city, szKey, arg):
        
        return self.calculateWhipOverflow(city, szKey, arg)[0]

    def calculateWhipOverflowGold (self, city, szKey, arg):
        
        return self.calculateWhipOverflow(city, szKey, arg)[1]

    def calculateWhipOverflow (self, city, szKey, arg):
        
        if (city.canHurry(self.HURRY_TYPE_POP, False)):
            iOverflow = city.hurryProduction(self.HURRY_TYPE_POP) - city.productionLeft()
            if CityScreenOpt.isWhipAssistOverflowCountCurrentProduction():
                iOverflow = iOverflow + city.getCurrentProductionDifference(True, False)
            iMaxOverflow = min(city.getProductionNeeded(), iOverflow)
            iOverflowGold = max(0, iOverflow - iMaxOverflow) * gc.getDefineINT("MAXED_UNIT_GOLD_PERCENT") / 100
            iOverflow =  100 * iMaxOverflow / city.getBaseYieldRateModifier(gc.getInfoTypeForString("YIELD_PRODUCTION"), city.getProductionModifier())
            return unicode(iOverflow), unicode(iOverflowGold)
        else:
            return self.objectNotPossible, self.objectNotPossible

    def calculateWhipAnger (self, city, szKey, arg):
        
        iAnger = city.getHurryAngerTimer()
        if (iAnger > 0 or city.canHurry(self.HURRY_TYPE_POP, False)):
            return iAnger
        else:
            return self.objectNotPossible

    def calculateHurryGoldCost (self, city, szKey, arg):
        
        if (city.canHurry(self.HURRY_TYPE_GOLD, False)):
            return unicode(city.hurryGold(self.HURRY_TYPE_GOLD))
        else:
            return self.objectNotPossible

    def calculateConscriptAnger (self, city, szKey, arg):
        
        iAnger = city.getConscriptAngerTimer()
        if (iAnger > 0 or city.canConscript()):
            return iAnger
        else:
            return self.objectNotPossible

    def calculatePotentialConscriptUnit (self, city, szKey, arg):
        
        szReturn = unicode(gc.getUnitInfo(city.getConscriptUnit()).getDescription() )
        return szReturn

    def calculateConscriptUnit (self, city, szKey, arg):
        
        if(city.canConscript()):
            szReturn = unicode(gc.getUnitInfo(city.getConscriptUnit()).getDescription() )
        else:
            szReturn = u""
        return szReturn

    def calculateReligions (self, city, szKey, arg):

        szReturn = u""

        lHolyCity = []
        lReligions = []
        for i in range(gc.getNumReligionInfos()):
            if city.isHolyCityByType(i):
                lHolyCity.append(i)
            elif city.isHasReligion(i):
                lReligions.append(i)

        for i in range(len(lHolyCity)):
            szReturn += u"%c" %(gc.getReligionInfo(lHolyCity[i]).getHolyCityChar())

        for i in range(len(lReligions)):
            szReturn += u"%c" %(gc.getReligionInfo(lReligions[i]).getChar())

        return szReturn

    def calculateCorporations (self, city, szKey, arg):

        szReturn = u""

        lHeadquarters = []
        lCorps = []
        for i in range(gc.getNumCorporationInfos()):
            if city.isHeadquartersByType(i):
                lHeadquarters.append(i)
            elif city.isHasCorporation(i):
                lCorps.append(i)

        for i in range(len(lHeadquarters)):
            szReturn += u"%c" %(gc.getCorporationInfo(lHeadquarters[i]).getHeadquarterChar())

        for i in range(len(lCorps)):
            szReturn += u"%c" %(gc.getCorporationInfo(lCorps[i]).getChar())

        return szReturn

    def calculateSpecialists (self, city, szKey, arg):

        szReturn = u"<font=1>"

        # For each specialist type
        for i in range( self.getNumSpecialistInfos() ):

            nCount = city.getSpecialistCount (i)
            # If more than one specialist
            if (nCount > 1):
                szReturn += self.SPECIALIST_ICON_DICT[i] + "x" + str(nCount) + " "
            elif (nCount == 1):
                szReturn += self.SPECIALIST_ICON_DICT[i] + " "

        szReturn += u"</font>"

        return szReturn

    def calculateAutomation (self, city, szKey, arg):

        szReturn = u"<font=1>"

        nNumEmphasize = self.getNumEmphasizeInfos()
        if city.isCitizensAutomated():
            szReturn += u"C"
        if city.isProductionAutomated():
            szReturn += u"P"
        for i in range( nNumEmphasize ):
            nNum = nNumEmphasize - i - 1
            if (city.AI_isEmphasize (nNum)):
                szReturn += self.AUTOMATION_ICON_DICT[nNum]

        szReturn += u"</font>"

        return szReturn

    def calculatePower (self, city, szKey, arg):

        szReturn = u""

        if city.isPower():
            szReturn += self.powerIcon

        return szReturn

    def calculateTotalCulture (self, city, szKey, arg):

        return city.getCulture(CyGame().getActivePlayer())

    def calculateCultureTurns (self, city, szKey, arg):

        iCultureTimes100 = city.getCultureTimes100(gc.getGame().getActivePlayer())
        iCultureRateTimes100 = city.getCommerceRateTimes100(CommerceTypes.COMMERCE_CULTURE)
        if iCultureRateTimes100 > 0:
            iCultureLeftTimes100 = 100 * city.getCultureThreshold() - iCultureTimes100
            return (iCultureLeftTimes100 + iCultureRateTimes100 - 1) / iCultureRateTimes100
        else:
            return u"-"

    def calculateGreatPeopleTurns (self, city, szKey, arg):

        iGreatPersonRate = city.getGreatPeopleRate()
        if iGreatPersonRate > 0:
            iGPPLeft = gc.getPlayer(gc.getGame().getActivePlayer()).greatPeopleThreshold(false) - city.getGreatPeopleProgress()
            return (iGPPLeft + iGreatPersonRate - 1) / iGreatPersonRate
        else:
            return u"-"

    def canHurry (self, city, szKey, arg):

        if city.canHurry(arg, False):
            return self.objectHave
        else:
            return self.objectNotPossible

    def canLiberate (self, city, szKey, arg):

        if city.getLiberationPlayer(False) != -1:
            return self.objectHave
        else:
            return self.objectNotPossible

    def calculateValue (self, city, szKey, arg):

        szReturn = u""

        if szKey.find("BUILDING_") == 0:
            if city.getNumActiveBuilding(self.BUILDING_DICT[szKey]) > 0 or city.getProductionName() == self.HEADER_DICT[szKey]:
                # Start with the default icons, and those that never change.
                szReturn += self.BUILDING_ICONS_DICT[szKey]

                buildingNumber = self.BUILDING_DICT[szKey]
                info = self.BUILDING_INFO_LIST[buildingNumber]

                # Indicate bonus military production if applicable
                if info.getMilitaryProductionModifier() > 0 and city.isProductionUnit() and gc.getUnitInfo(city.getProductionUnit()).isMilitaryProduction():
                    if szReturn.find(self.hammerIcon) == -1:
                        szReturn += self.hammerIcon

                # Calculate health and happiness effects - including that from resources.
                iHealth = city.getBuildingHealth(buildingNumber)
                iHappiness = city.getBuildingHappiness(buildingNumber)

                for i in range(gc.getNumBonusInfos()):
                    if city.hasBonus(i):
                        iHealth += info.getBonusHealthChanges(i)
                        iHappiness += info.getBonusHappinessChanges(i)

                if iHealth > 0:
                    szReturn = self.stripStr(szReturn, self.healthIcon)
                    szReturn += u"%d%c" %(iHealth, self.healthIcon)
                elif iHealth < 0:
                    szReturn = self.stripStr(szReturn, self.sickIcon)
                    szReturn += u"%d%c" %( -(iHealth), self.sickIcon )

                # Happiness

                if iHappiness > 0:
                    szReturn = self.stripStr(szReturn, self.happyIcon)
                    szReturn += u"%d%c" %(iHappiness, self.happyIcon)
                elif iHappiness < 0:
                    szReturn = self.stripStr(szReturn, self.unhappyIcon)
                    szReturn += u"%d%c" %( -(iHappiness), self.unhappyIcon )

                # Commerce
                for i in range(CommerceTypes.NUM_COMMERCE_TYPES):
                    iCommerce = city.getBuildingCommerceByBuilding(i, buildingNumber) 
                    if iCommerce > 0:
                        szReturn += u"%d%c" %( iCommerce, gc.getCommerceInfo(i).getChar() )

                if szReturn == "":
                    szReturn = "+"

                if city.getProductionName() == self.HEADER_DICT[szKey]: # In production
                    szReturn = "(" + szReturn + ")"
                                        
            elif city.getNumBuilding(self.BUILDING_DICT[szKey]) > 0: # Obsolete buildings
                if self.BUILDING_ICONS_DICT[szKey].find(self.cultureIcon):
                    szReturn = self.stripStr(szReturn, self.cultureIcon)
                    szReturn += self.cultureIcon
                else:
                    szReturn += u"X"

            elif not city.canConstruct(self.BUILDING_DICT.get(szKey), False, False, False):
                szReturn += u"-"

            else:
                szReturn += u" "

        # return the final value
        return szReturn

    def calculateBuildingClass (self, city, szKey, arg):
        
        # Turn building class into building
        bldg = gc.getCivilizationInfo(city.getCivilizationType()).getCivilizationBuildings(arg)
        return self.calculateBuilding(city, szKey, bldg)

    def calculateBuilding (self, city, szKey, arg):
        
        # Turn building class into building
        if city.getNumBuilding(arg) > 0:
            if city.getNumActiveBuilding(arg) > 0:
                return self.objectHave
            else:
                return self.objectHaveObsolete
        elif city.getFirstBuildingOrder(arg) != -1:
            return self.objectUnderConstruction
        elif city.canConstruct(arg, False, False, False):
            return self.objectPossible
        elif city.canConstruct(arg, True, False, False):
            return self.objectPossibleConcurrent
        else:
            return self.objectNotPossible

    def calculateHasBonus (self, city, szKey, arg):
        
        # Determine whether or not city has the given bonus
        if (city.hasBonus(arg)):
            return self.objectHave
        else:
            return self.objectNotPossible

    def calculateBonus (self, city, szKey, arg):
        
        # Determine the effects of the given bonus (health, happiness, commerce)
        if (not city.hasBonus(arg)):
            return self.objectNotPossible
        
        szEffects = u""
        iEffect = city.getBonusHappiness(arg)
        if (iEffect == 1):
            szEffects += u"%s " % (self.happyIcon)
        elif (iEffect > 1):
            szEffects += u"%d%s " % (iEffect, self.happyIcon)
        elif (iEffect < 0):
            szEffects += u"%d%s " % (-iEffect, self.unhappyIcon)
        
        iEffect = city.getBonusHealth(arg)
        if (iEffect == 1):
            szEffects += u"%s " % (self.healthIcon)
        elif (iEffect > 1):
            szEffects += u"%d%s " % (iEffect, self.healthIcon)
        elif (iEffect < 0):
            szEffects += u"%d%s " % (-iEffect, self.sickIcon)
        
        for eYieldType in range(YieldTypes.NUM_YIELD_TYPES):
            iEffect = city.getBonusYieldRateModifier(eYieldType, arg)
            if (iEffect > 0):
                szEffects += u"%s " % self.yieldIcons[eYieldType]
#           elif (iEffect > 1 or iEffect < 0):
#               szEffects += u"%d%s " % (iEffect, self.yieldIcons[eYieldType])
        
        iNumBonuses = city.getNumBonuses(arg)
        if (self.bonusCorpYields.has_key(arg)):
            yields = self.bonusCorpYields[arg]
            for eYield in range(YieldTypes.NUM_YIELD_TYPES):
                if (yields.has_key(eYield)):
                    iEffect = 0
                    for eCorp, iValue in yields[eYield].iteritems():
                        if (city.isActiveCorporation(eCorp)):
                            iEffect += iValue * iNumBonuses * self.corpMaintPercent / 100
                    iEffect = (iEffect + 99) / 100
                    if (iEffect == 1):
                        szEffects += u"%s " % self.yieldIcons[eYield]
                    elif (iEffect > 1 or iEffect < 0):
                        szEffects += u"%d%s " % (iEffect, self.yieldIcons[eYield])
        
        if (self.bonusCorpCommerces.has_key(arg)):
            commerces = self.bonusCorpCommerces[arg]
            for eCommerce in range(CommerceTypes.NUM_COMMERCE_TYPES):
                if (commerces.has_key(eCommerce)):
                    iEffect = 0
                    for eCorp, iValue in commerces[eCommerce].iteritems():
                        if (city.isActiveCorporation(eCorp)):
                            iEffect += iValue * iNumBonuses * self.corpMaintPercent / 100
                    iEffect = (iEffect + 99) / 100
                    if (iEffect == 1):
                        szEffects += u"%s " % self.commerceIcons[eCommerce]
                    elif (iEffect > 1 or iEffect < 0):
                        szEffects += u"%d%s " % (iEffect, self.commerceIcons[eCommerce])
        
#       for eYieldType in range(YieldTypes.NUM_YIELD_TYPES):
#           if (city.getCorporationYield(eYieldType) > 0):
#               iEffect = 0
#               for eCorporation in range(gc.getNumCorporationInfos()):
#                   if (city.isActiveCorporation(eCorporation)):
#                       info = gc.getCorporationInfo(eCorporation)
#                       for i in range(gc.getNUM_CORPORATION_PREREQ_BONUSES()):
#                           if (info.getPrereqBonus(i) == arg):
#                               iEffect += info.getYieldProduced(eYieldType) * city.getNumBonuses(arg) * self.corpMaintPercent / 100
#               iEffect = (iEffect + 99) / 100
#               if (iEffect == 1):
#                   szEffects += u"%s " % self.yieldIcons[eYieldType]
#               elif (iEffect > 1 or iEffect < 0):
#                   szEffects += u"%d%s " % (iEffect, self.yieldIcons[eYieldType])
#       
#       for eCommerceType in range(CommerceTypes.NUM_COMMERCE_TYPES):
#           if (city.getCorporationCommerce(eCommerceType) > 0):
#               iEffect = 0
#               for eCorporation in range(gc.getNumCorporationInfos()):
#                   if (city.isActiveCorporation(eCorporation)):
#                       info = gc.getCorporationInfo(eCorporation)
#                       for i in range(gc.getNUM_CORPORATION_PREREQ_BONUSES()):
#                           if (info.getPrereqBonus(i) == arg):
#                               iEffect += info.getCommerceProduced(eCommerceType) * city.getNumBonuses(arg) * self.corpMaintPercent / 100
#               iEffect = (iEffect + 99) / 100
#               if (iEffect == 1):
#                   szEffects += u"%s " % self.commerceIcons[eCommerceType]
#               elif (iEffect > 1 or iEffect < 0):
#                   szEffects += u"%d%s " % (iEffect, self.commerceIcons[eCommerceType])
        
        iEffect = city.getBonusPower(arg, False) + city.getBonusPower(arg, True)
        if (iEffect == 1):
            szEffects += u"%s " % (self.powerIcon)
        elif (iEffect > 1):
            szEffects += u"%d%s " % (iEffect, self.powerIcon)
        
        if (szEffects == u""):
            return self.objectHave
        return szEffects.strip()

    def calculateFreeExperience (self, city, szKey, arg):
        """arg: Domain identifier; "L" for Land, "S" for Sea, "A" for Air, "I" for Immobile"""
        # Thanks to MatzeHH for original version of this
        player = gc.getActivePlayer()
        # Generic modifiers first
        freeXP = city.getSpecialistFreeExperience()
        freeXP += city.getFreeExperience()
        freeXP += player.getFreeExperience()
        if (player.getStateReligion() != ReligionTypes.NO_RELIGION):
            if (city.isHasReligion(player.getStateReligion())):
                freeXP += player.getStateReligionFreeExperience()
        # Then tack on the proper domain-based extras
        if (arg == "L"):
            freeXP += city.getDomainFreeExperience(DomainTypes.DOMAIN_LAND)
        elif (arg == "S"):
            freeXP += city.getDomainFreeExperience(DomainTypes.DOMAIN_SEA)
        elif (arg == "A"):
            freeXP += city.getDomainFreeExperience(DomainTypes.DOMAIN_AIR)
        elif (arg == "I"):
            freeXP += city.getDomainFreeExperience(DomainTypes.DOMAIN_IMMOBILE)

        return unicode(freeXP)

    def findGlobalBaseYieldRateRank (self, city, szKey, arg):

        L = []
        for i in range(gc.getMAX_PLAYERS()):
            cl = PyPlayer(i).getCityList()
            for c in cl:
                L.append(c.city.getBaseYieldRate(arg))

        y = city.getBaseYieldRate(arg)
        return len([i for i in L if i > y]) + 1

    def findGlobalYieldRateRank (self, city, szKey, arg):

        L = []
        for i in range(gc.getMAX_PLAYERS()):
            cl = PyPlayer(i).getCityList()
            for c in cl:
                L.append(c.city.getYieldRate(arg))

        y = city.getYieldRate(arg)
        return len([i for i in L if i > y]) + 1

    def findGlobalCommerceRateRank (self, city, szKey, arg):

        L = []
        for i in range(gc.getMAX_PLAYERS()):
            cl = PyPlayer(i).getCityList()
            for c in cl:
                L.append(c.city.getCommerceRate(arg))

        y = city.getCommerceRate(arg)
        return len([i for i in L if i > y]) + 1


    def canAdviseToConstruct(self, city, i):
        
        info = gc.getBuildingInfo(i)
        if not city.canConstruct(i, True, False, False):
            return False
        if info.isGovernmentCenter() or info.isCapital():
            return False

        if info.getObsoleteTech() != TechTypes.NO_TECH and PyPlayer(CyGame().getActivePlayer()).getTeam().isHasTech(info.getObsoleteTech()):
            return False

        sinfo = gc.getSpecialBuildingInfo(info.getSpecialBuildingType())

        if sinfo:
            if sinfo.getObsoleteTech() != TechTypes.NO_TECH and PyPlayer(CyGame().getActivePlayer()).getTeam().isHasTech(sinfo.getObsoleteTech()):
                return False

        return True

    def advise(self, city, szKey, type):

        bestOrder = -1
        bestData = 0.0

        player = PyPlayer(CyGame().getActivePlayer())
        civInfo = gc.getCivilizationInfo(city.getCivilizationType())

        # For all cities, start with growth
        if self.calculateNetHappiness(city) > 2 and self.calculateNetHealth(city) > 2:
            for i in range(gc.getNumBuildingClassInfos()):
                bldg = civInfo.getCivilizationBuildings(i)
                if self.canAdviseToConstruct(city, bldg):
                    info = gc.getBuildingInfo(bldg)
                    value = info.getFoodKept() / float(info.getProductionCost())
                    if(value > bestData):
                        bestOrder = bldg
                        bestData = value

        # then balancing health and happiness for further growth
        if bestOrder == -1:
            for i in range(gc.getNumBuildingClassInfos()):
                bldg = civInfo.getCivilizationBuildings(i)
                if self.canAdviseToConstruct(city, bldg):
                    info = gc.getBuildingInfo(bldg)
                    if self.calculateNetHappiness(city) < 3 and self.calculateNetHappiness(city) - self.calculateNetHealth(city) > 2:
                        iHealth = info.getHealth()
                        for j in range(gc.getNumBonusInfos()):
                            if city.hasBonus(j):
                                iHealth += info.getBonusHealthChanges(j)
                        value = iHealth / float(info.getProductionCost())
                        if(value > bestData):
                            bestOrder = bldg
                            bestData = value
                    elif self.calculateNetHealth(city) < 3 and self.calculateNetHealth(city) - self.calculateNetHappiness(city) > 2:
                        iHappiness = info.getHappiness()
                        for j in range(gc.getNumBonusInfos()):
                            if city.hasBonus(j):
                                iHappiness += info.getBonusHappinessChanges(j)
                        value = iHappiness  / float(info.getProductionCost())
                        if(value > bestData):
                            bestOrder = bldg
                            bestData = value

        # First pass
        if(bestOrder == -1):
            for i in range(gc.getNumBuildingClassInfos()):
                bldg = civInfo.getCivilizationBuildings(i)
                if self.canAdviseToConstruct(city, bldg):
                    info = gc.getBuildingInfo(bldg)

                    if type == "Culture":
                        if city.findBaseYieldRateRank(YieldTypes.YIELD_COMMERCE) < 6:
                            value = info.getCommerceModifier(CommerceTypes.COMMERCE_CULTURE) / float(info.getProductionCost())
                            if value > bestData:
                                bestOrder = bldg
                                bestData = value
                        else:
                            value = info.getPowerValue() / float(info.getProductionCost())
                            if value > bestData:
                                bestOrder = bldg
                                bestData = value
                    elif type == "Military":
                        value = info.getPowerValue() / float(info.getProductionCost())
                        if value > bestData:
                            bestOrder = bldg
                            bestData = value
                    elif type == "Nutty":
                        value = math.sin(float(info.getProductionCost()) * city.getBaseYieldRate(YieldTypes.YIELD_COMMERCE)) + 1
                        if value > bestData:
                            bestOrder = bldg
                            bestData = value
                    elif type == "Religion":
                        bestOrder = -1
                    elif type == "Research":
                        value = info.getCommerceModifier(CommerceTypes.COMMERCE_RESEARCH) / float(info.getProductionCost())
                        if value > bestData:
                            bestOrder = bldg
                            bestData = value
                    elif type == "Spaceship":
                        if not city.isPower():
                            if info.isPower():
                                value = city.getBaseYieldRate(YieldTypes.YIELD_PRODUCTION) / float(info.getProductionCost())
                                if value > bestData:
                                    bestOrder = bldg
                                    bestData = value
                        
                        if city.findBaseYieldRateRank(YieldTypes.YIELD_PRODUCTION) < 12:
                            value = city.getBaseYieldRate(YieldTypes.YIELD_PRODUCTION) * 2 * info.getYieldModifier(YieldTypes.YIELD_PRODUCTION) / float(info.getProductionCost())
                            if value > bestData:
                                bestOrder = bldg
                                bestData = value
                        
                        if city.findBaseYieldRateRank(YieldTypes.YIELD_COMMERCE) < player.getNumCities() / 2:
                            value = city.getBaseYieldRate(YieldTypes.YIELD_COMMERCE) * info.getCommerceModifier(CommerceTypes.COMMERCE_RESEARCH) / float(info.getProductionCost())
                            if value > bestData:
                                bestOrder = bldg
                                bestData = value
                        else:
                            bestOrder = -1

        # Second pass
        if(bestOrder == -1):
            for i in range(gc.getNumBuildingClassInfos()):
                bldg = civInfo.getCivilizationBuildings(i)
                if self.canAdviseToConstruct(city, bldg):
                    info = gc.getBuildingInfo(bldg)

                    if type == "Culture":
                        if city.findBaseYieldRateRank(YieldTypes.YIELD_COMMERCE) < 6:
                            value = info.getPowerValue() / float(info.getProductionCost())
                            if value > bestData:
                                bestOrder = bldg
                                bestData = value
                        else:
                            bestOrder = -1  # In a cultural game, build units in the culturally weak cities
                    elif type == "Military":
                        if city.findBaseYieldRateRank(YieldTypes.YIELD_PRODUCTION) <= 3:
                            value = -1 * info.getMilitaryProductionModifier() / float(info.getProductionCost())
                            BugUtil.debug(info.getDescription() + ": " + str(value))
                            if value > bestData:
                                bestOrder = bldg
                                bestData = value
                        else:
                            value = info.getYieldModifier(YieldTypes.YIELD_PRODUCTION) / float(info.getProductionCost())
                            if value > bestData:
                                bestOrder = bldg
                                bestData = value
                            if not city.isPower():
                                if info.isPower():
                                    value = 1 / float(info.getProductionCost())
                                    if value > bestData:
                                        bestOrder = bldg
                                        bestData = value

                    elif type == "Nutty":
                        bestOrder = -1
                    elif type == "Religion":
                        bestOrder = -1
                    elif type == "Research":
                        value = info.getCommerceModifier(CommerceTypes.COMMERCE_GOLD) / float(info.getProductionCost())
                        if value > bestData:
                            bestOrder = bldg
                            bestData = value
                    elif type == "Spaceship":
                        bestOrder = -1

        szReturn = u""
        if bestOrder != -1:
            szReturn = gc.getBuildingInfo(bestOrder).getDescription()

        if szReturn == city.getProductionName():
            szReturn = u""

        return szReturn

    def ColorCityValues (self, nValue, szKey):
        """Colors city values which we might want to alert the user to."""

        # If the key is one we want to possibly color
        if (szKey in self.COLOR_SET):
            # If we don't have a plain integer
            if (re.search ("[-+]", nValue)):
                # Color it red and return it
                return localText.changeTextColor (nValue, gc.getInfoTypeForString("COLOR_RED"))
            # For each type of comparison
            for szCompareType, clDict in self.COLOR_DICT_DICT.iteritems():
                # Get the color we will use.
                color = self.COLOR_DICT[szCompareType]

                # If the dictionary has the key...
                if (clDict != None and clDict.has_key(szKey)):
                    if (szKey in self.COMPARISON_REVERSED):
                        # ...and the comparison is appropriate...
                        if ((szCompareType == "PROBLEM" and int(nValue) >= clDict[szKey] or szCompareType == "NEUTRAL" and int(nValue) == clDict[szKey] or szCompareType == "GREAT" and int(nValue) <= clDict[szKey])):
                            # ...color and return it
                            return localText.changeTextColor (nValue, color)
                    # ...and the comparison is appropriate...
                    elif ((szCompareType == "PROBLEM" and int(nValue) <= clDict[szKey] or szCompareType == "NEUTRAL" and int(nValue) == clDict[szKey] or szCompareType == "GREAT" and int(nValue) >= clDict[szKey])):
                        # ...color and return it
                        return localText.changeTextColor (nValue, color)

        # Otherwise, just return the regular value
        return nValue

    def drawContents (self, page):
        """ Function to draw the contents of the cityList passed in. """

        screen = self.getScreen()
        iPlayer = PyPlayer(CyGame().getActivePlayer())
        cityList = iPlayer.getCityList()
        
        # Hide building icons
        for i in range(gc.getNumBuildingInfos()):
            szName = "BLDG_BTN_%d" % i
            screen.hide(szName)

        # Fill the pages drop down
        screen.addDropDownBoxGFC(self.PAGES_DD_NAME, self.X_SPECIAL, self.Y_SPECIAL, self.PAGES_DD_W, WidgetTypes.WIDGET_CDA_SELECT_PAGE, -1, -1, FontTypes.GAME_FONT)
        for i, p in enumerate(self.PAGES):
            screen.addPullDownString(self.PAGES_DD_NAME, p["name"], i, i, i == self.currentPageNum )

        if(self.customizing):

            # Build the page definition table
            screen.addTableControlGFC (self.CUSTOMIZE_PAGE, 4, self.nTableX, self.nTableY, self.nHalfTableWidth, self.nShortTableLength, True, False, 32, 32, TableStyles.TABLE_STYLE_STANDARD )
            screen.enableSelect(self.CUSTOMIZE_PAGE, True)
            screen.enableSort (self.CUSTOMIZE_PAGE)
            screen.setStyle(self.CUSTOMIZE_PAGE, "Table_StandardCiv_Style")

            screen.setTableColumnHeader (self.CUSTOMIZE_PAGE, 0, u"<font=2>POS</font>", 40 )
            screen.setTableColumnHeader (self.CUSTOMIZE_PAGE, 1, u"<font=2>NAME</font>", 160 )
            screen.setTableColumnHeader (self.CUSTOMIZE_PAGE, 2, u"<font=2>TITLE</font>", 160 )
            screen.setTableColumnHeader (self.CUSTOMIZE_PAGE, 3, u"<font=2>WIDTH</font>", 80 )

            columns = self.PAGES[self.currentPageNum]["columns"]
            for i, column in enumerate(columns):
                screen.appendTableRow (self.CUSTOMIZE_PAGE)
                screen.setTableInt(self.CUSTOMIZE_PAGE, 0, i, unicode(i+1), "", WidgetTypes.WIDGET_GENERAL, -1, -1, CvUtil.FONT_RIGHT_JUSTIFY)
                screen.setTableText(self.CUSTOMIZE_PAGE, 1, i, unicode(column[0]), "", WidgetTypes.WIDGET_GENERAL, -1, -1, CvUtil.FONT_LEFT_JUSTIFY)
                
                # Catch exceptions generated by missing columns
                try:
                    screen.setTableText(self.CUSTOMIZE_PAGE, 2, i, self.HEADER_DICT[column[0]], "", WidgetTypes.WIDGET_GENERAL, -1, -1, CvUtil.FONT_LEFT_JUSTIFY)
                except KeyError:
                    screen.setTableText(self.CUSTOMIZE_PAGE, 2, i, "", "", WidgetTypes.WIDGET_GENERAL, -1, -1, CvUtil.FONT_LEFT_JUSTIFY)
                except TypeError:
                    screen.setTableText(self.CUSTOMIZE_PAGE, 2, i, "", "", WidgetTypes.WIDGET_GENERAL, -1, -1, CvUtil.FONT_LEFT_JUSTIFY)

                screen.setTableInt(self.CUSTOMIZE_PAGE, 3, i, unicode(column[1]), "", WidgetTypes.WIDGET_GENERAL, -1, -1, CvUtil.FONT_RIGHT_JUSTIFY)

            # Build the available columns table
            if(screen.getTableNumRows(self.COLUMNS_LIST_PAGE) != len(self.COLUMNS_LIST)):

                screen.addTableControlGFC (self.COLUMNS_LIST_PAGE, 4, self.nSecondHalfTableX, self.nTableY, self.nHalfTableWidth, self.nShortTableLength, True, False, 32, 32, TableStyles.TABLE_STYLE_STANDARD )
                screen.enableSelect(self.COLUMNS_LIST_PAGE, True)
                screen.enableSort (self.COLUMNS_LIST_PAGE)
                screen.setStyle(self.COLUMNS_LIST_PAGE, "Table_StandardCiv_Style")

                screen.setTableColumnHeader (self.COLUMNS_LIST_PAGE, 0, u"<font=2>ID</font>", 40 )
                screen.setTableColumnHeader (self.COLUMNS_LIST_PAGE, 1, u"<font=2>NAME</font>", 160 )
                screen.setTableColumnHeader (self.COLUMNS_LIST_PAGE, 2, u"<font=2>TITLE</font>", 160 )
                screen.setTableColumnHeader (self.COLUMNS_LIST_PAGE, 3, u"<font=2>WIDTH</font>", 80 )

                columns = self.COLUMNS_LIST
                for i, column in enumerate(columns):
                    screen.appendTableRow (self.COLUMNS_LIST_PAGE)
                    screen.setTableInt(self.COLUMNS_LIST_PAGE, 0, i, unicode(i), "", WidgetTypes.WIDGET_GENERAL, -1, -1, CvUtil.FONT_RIGHT_JUSTIFY)
                    screen.setTableText(self.COLUMNS_LIST_PAGE, 1, i, unicode(column[0]), "", WidgetTypes.WIDGET_GENERAL, -1, -1, CvUtil.FONT_LEFT_JUSTIFY)
                    try:
                        screen.setTableText(self.COLUMNS_LIST_PAGE, 2, i, unicode(self.HEADER_DICT[column[0]]), "", WidgetTypes.WIDGET_GENERAL, -1, -1, CvUtil.FONT_LEFT_JUSTIFY)
                    except TypeError:
                        screen.setTableText(self.COLUMNS_LIST_PAGE, 2, i, "", "", WidgetTypes.WIDGET_GENERAL, -1, -1, CvUtil.FONT_LEFT_JUSTIFY)
                    except UnicodeDecodeError:
                        screen.setTableText(self.COLUMNS_LIST_PAGE, 2, i, "", "", WidgetTypes.WIDGET_GENERAL, -1, -1, CvUtil.FONT_LEFT_JUSTIFY)

                    screen.setTableInt(self.COLUMNS_LIST_PAGE, 3, i, unicode(column[1]), "", WidgetTypes.WIDGET_GENERAL, -1, -1, CvUtil.FONT_RIGHT_JUSTIFY)

            # This is legacy code. I don't know if it's necessary.
            screen.moveToBack (self.BACKGROUND_ID)

            # Finally, display the customization controls
            self.showCustomizationControls()

            # And hide the regular controls and legends
            screen.hide(self.currentPage)
            self.hideSpecialists()
            self.hideCultureLegend()
            self.hideGPLegend()

        # If displaying the normal advisor screen (not the customization interface)
        else:

            dDict = self.columnDict

            # Bring down the curtain...
            screen.moveToFront( "Background" )

            # Build the table   
            if not self.PAGES[self.currentPageNum]["showSpecControls"] and \
                not self.PAGES[self.currentPageNum]["showCultureLegend"] and \
                not self.PAGES[self.currentPageNum]["showGPLegend"]:
                screen.addTableControlGFC (page, len (dDict) + 1, self.nTableX, self.nTableY, self.nTableWidth, self.nTableLength, True, False, 24, 24, TableStyles.TABLE_STYLE_STANDARD )
            else:
                screen.addTableControlGFC (page, len (dDict) + 1, self.nTableX, self.nTableY, self.nTableWidth, self.nShortTableLength, True, False, 24, 24, TableStyles.TABLE_STYLE_STANDARD )

            screen.enableSelect (page, True)
            screen.enableSort (page)
            screen.setStyle(page, "Table_StandardCiv_Style")

            cityRange = range(len(cityList))

            zoomArt = ArtFileMgr.getInterfaceArtInfo("INTERFACE_BUTTONS_CITYSELECTION").getPath()

            # Add a blank header for the "zoom" column
            screen.setTableColumnHeader (page, 0, "", 30 )

            # Add blank rows to the table
            for i in cityRange:
                screen.appendTableRow (page)
                if (cityList[i].getName() in self.listSelectedCities):
                    screen.selectRow( page, i, True )
#               if not self.PAGES[self.currentPageNum]["showSpecControls"]:
#                   szWidgetName = "ZoomCity" + str(i)
#                   screen.setImageButton( szWidgetName, zoomArt, 0, 0, 24, 24, WidgetTypes.WIDGET_ZOOM_CITY, cityList[i].getOwner(), cityList[i].getID() )
#                   screen.attachControlToTableCell( szWidgetName, page, i, 0 )
                screen.setTableText( page, 0, i, "", zoomArt, WidgetTypes.WIDGET_ZOOM_CITY, cityList[i].getOwner(), cityList[i].getID(), CvUtil.FONT_LEFT_JUSTIFY)

            # Order the columns
            columns = []
            for key, value in self.columnDict.iteritems():
                columns.append((value, key))
            columns.sort()

            iBuildingButtonX = self.nTableX + 30
            iBuildingButtonY = self.nTableY
            civInfo = gc.getCivilizationInfo(gc.getActivePlayer().getCivilizationType())
            
            # Loop through the columns first. This is unintuitive, but faster.
            for value, key in columns:
                
                try:
                    columnDef = self.COLUMNS_LIST[self.COLUMNS_INDEX[key]]
                    type = columnDef[2]
                    if (type == "bldg" or type == "bldgclass"):
                        if (type == "bldg"):
                            building = columnDef[7]
                            buildingInfo = self.BUILDING_INFO_LIST[building]
                            buildingClass = buildingInfo.getBuildingClassType()
                            if (building != civInfo.getCivilizationBuildings(buildingClass)):
                                # Skip column if building isn't available for this civ
                                continue
                        else:
                            buildingClass = columnDef[7]
                            building = civInfo.getCivilizationBuildings(buildingClass)
                            buildingInfo = self.BUILDING_INFO_LIST[building]
                        screen.setTableColumnHeader (page, value + 1, "", self.columnWidth[key])
                        szName = "BLDG_BTN_%d" % building
                        x = iBuildingButtonX + (self.columnWidth[key] - self.BUILDING_BUTTON_X_SIZE) / 2
                        screen.setImageButton (szName, buildingInfo.getButton(), 
                                               x, iBuildingButtonY, self.BUILDING_BUTTON_X_SIZE, self.BUILDING_BUTTON_Y_SIZE, 
                                               WidgetTypes.WIDGET_PEDIA_JUMP_TO_BUILDING, building, -1)
                    else:
                        screen.setTableColumnHeader (page, value + 1, "<font=2>" + self.HEADER_DICT[key] + "</font>", self.columnWidth[key] )

                    iBuildingButtonX += self.columnWidth[key]

                    # And the correct writing function.
                    if (type == "text"):
                        funcTableWrite = screen.setTableText
                        justify = CvUtil.FONT_LEFT_JUSTIFY
                    elif (type == "date"):
                        funcTableWrite = screen.setTableDate
                        justify = CvUtil.FONT_LEFT_JUSTIFY
                    elif (type == "int"):
                        funcTableWrite = screen.setTableInt
                        justify = CvUtil.FONT_RIGHT_JUSTIFY
                    elif (type == "bonus"):
                        funcTableWrite = screen.setTableText
                        justify = CvUtil.FONT_CENTER_JUSTIFY
                    elif (type == "bldg" or type == "bldgclass"):
                        funcTableWrite = screen.setTableText
                        justify = CvUtil.FONT_CENTER_JUSTIFY
                    else:
                        return;

                    colorFunc = self.ColorCityValues

                    if(columnDef[3]):
                        calcFunc = columnDef[3]
                        # Loop through the cities
                        for i in cityRange:
                            szValue = colorFunc(unicode(calcFunc(cityList[i].city)), key)
                            funcTableWrite (page, value + 1, i, szValue, "", WidgetTypes.WIDGET_GENERAL, -1, -1, justify)
                        
                    elif(columnDef[4]):
                        calcFunc = columnDef[4]
                        # Loop through the cities
                        for i in cityRange:
                            szValue = colorFunc(unicode(calcFunc(cityList[i].city, columnDef[5])), key)
                            funcTableWrite (page, value + 1, i, szValue, "", WidgetTypes.WIDGET_GENERAL, -1, -1, justify)

                    else:
                        calcFunc = columnDef[6]
                        
                        # Loop through the cities
                        for i in cityRange:
                            szValue = colorFunc(unicode(calcFunc(cityList[i].city, key, columnDef[7])), key)
                            funcTableWrite (page, value + 1, i, szValue, "", WidgetTypes.WIDGET_GENERAL, -1, -1, justify)

                except KeyError:
                    continue
                except TypeError:
                    continue

            # Finally, display the specialist controls,
            if self.PAGES[self.currentPageNum]["showSpecControls"]:
                self.showSpecialists()
            else:
                self.hideSpecialists()

            # and the legends,
            if self.PAGES[self.currentPageNum]["showCultureLegend"]:
                self.showCultureLegend()
            else:
                self.hideCultureLegend()

            if self.PAGES[self.currentPageNum]["showGPLegend"]:
                self.showGPLegend()
            else:
                self.hideGPLegend()

            # and hide the customization tools.
            self.hideCustomizationControls()

            # Raise the curtain and reveal our masterpiece
            screen.moveToBack (self.BACKGROUND_ID)

            # Now hand off to the C++ API
            self.updateAppropriateCitySelection (page, len( iPlayer.getCityList() ) )

    def HandleSpecialistPlus (self, inputClass):
        """ Handles when any Specialist Plus is pushed."""

        #CyInterface().setDirty(InterfaceDirtyBits.Domestic_Advisor_DIRTY_BIT, True)
        return 0

    def HandleSpecialistMinus (self, inputClass):
        """ Handles when any Specialist Minus is pushed."""

        CyInterface().setDirty(InterfaceDirtyBits.Domestic_Advisor_DIRTY_BIT, True)
        return 0

    def DomesticExit (self, inputClass):
        return 0

    def handleInput (self, inputClass):
        """ Handles the input for this screen..."""

        code = inputClass.getNotifyCode()

        if ( code == NotifyCode.NOTIFY_LISTBOX_ITEM_SELECTED ):

            szWidget = inputClass.getFunctionName() + str(inputClass.getID())

            # I have no clue why + "0" is required here and not in the elif case. It's a mystery.
            if(szWidget == self.PAGES_DD_NAME + "0"):
                if(self.customizing):
                    self.customizingClearSelection()
                self.switchPage(self.PAGES[inputClass.getData()]["name"])
                self.drawScreen(self.currentPage)
                return 1
                
            elif(szWidget == self.currentPage):
                screen = self.getScreen()
                if (inputClass.getMouseX() == 0):
                    screen.hideScreen()
                    
                    CyInterface().selectCity(gc.getPlayer(inputClass.getData1()).getCity(inputClass.getData2()), true);
                    
                    popupInfo = CyPopupInfo()
                    popupInfo.setButtonPopupType(ButtonPopupTypes.BUTTONPOPUP_PYTHON_SCREEN)
                    popupInfo.setText(u"showDomesticAdvisor")
                    popupInfo.addPopup(inputClass.getData1())
                else:
                    city = self.getCurrentCity()
                    if (city):
                        CyInterface().lookAtCityOffset(city.getID())
                    
                    if self.PAGES[self.currentPageNum]["showSpecControls"]:
                        self.showSpecialists()
                    
                    # And pass it back to the screen
                    self.updateAppropriateCitySelection( self.currentPage, len( PyPlayer(CyGame().getActivePlayer()).getCityList() ) )
                    
                    return 1

            else:
                BugUtil.debug(szWidget)
                BugUtil.debug(self.currentPage)

        # Is the input from a mapped button?
        elif (code == NotifyCode.NOTIFY_CLICKED and self.DomesticScreenInputMap.has_key(inputClass.getFunctionName())):
            'Calls function mapped in CvSpecDomesticAdvisor'
            # only get from the map if it has the key

            # get bound function from map and call it (return whatever it returns.)
            return self.DomesticScreenInputMap.get(inputClass.getFunctionName())(inputClass)

        # Is the input from a Zoom City button?
        elif ( inputClass.getNotifyCode() == NotifyCode.NOTIFY_CLICKED ):
            if ( inputClass.getFunctionName() == "ZoomCity" ):
                screen = CyGInterfaceScreen( "DomesticAdvisor", CvScreenEnums.DOMESTIC_ADVISOR )
                screen.hideScreen()
                
                CyInterface().selectCity(gc.getPlayer(inputClass.getData1()).getCity(inputClass.getData2()), true);
                
                popupInfo = CyPopupInfo()
                popupInfo.setButtonPopupType(ButtonPopupTypes.BUTTONPOPUP_PYTHON_SCREEN)
                popupInfo.setText(u"showDomesticAdvisor")
                popupInfo.addPopup(inputClass.getData1())

# BUG - Colony Split - start

            elif (inputClass.getFunctionName() == self.SPLIT_NAME):
                screen = CyGInterfaceScreen( "DomesticAdvisor", CvScreenEnums.DOMESTIC_ADVISOR )
                screen.hideScreen()

            # Remove Pause
            if (inputClass.getData1() == 301311):
                if( gc.getGame().isPaused() and not CyGame().isPitbossHost() ):
                    # Cause crash on PB server is host os is Linux
                    #gc.sendPause(-1)
                    # Workaround.
                    gc.sendChat("RemovePause", ChatTargetTypes.CHATTARGET_ALL)
                    screen = CyGInterfaceScreen( "DomesticAdvisor", CvScreenEnums.DOMESTIC_ADVISOR )
                    screen.hideScreen()

# BUG - Colony Split - end

        # If none of the above, we didn't use the input."
        return 0
    
    def isFoodProduction (self, szProducing):
        """ We determine it's a food production, if it's a worker or settler."""
        return re.search ("Worker|Settler", szProducing)

    def updateScreen(self):
        """ Updates the screen."""

        self.drawContents()

        return

    def update(self, fDelta):
        """ Update the Advisor."""
        if (CyInterface().isDirty(InterfaceDirtyBits.Domestic_Advisor_DIRTY_BIT) == True):
            CyInterface().setDirty(InterfaceDirtyBits.Domestic_Advisor_DIRTY_BIT, False)
            
            self.drawContents(self.currentPage)

        return
            
    def switchPage(self, page):
        
        for i, p in enumerate(self.PAGES):
            if(p["name"] == page):
                self.currentPage = self.getPageID(p["name"])
                self.currentPageNum = i
                self.columnDict = { }
                self.columnWidth = { }
                for i, col in enumerate(p["columns"]):
                    self.columnDict[col[0]] = i
                    self.columnWidth[col[0]] = col[1]
                break

    def isPageActive(self, page):
        return self.currentPage == self.getPageID(page)

    def getPageID(self, page):
        for i, p in enumerate(self.PAGES):
            if(p["name"] == page):
                id = "CDA_PAGE_%d" % i
                return id
            
    def updateAppropriateCitySelection(self, page, nCities):
        screen = self.getScreen()
        screen.updateAppropriateCitySelection( page, nCities, 1 )

        self.listSelectedCities = []
        for i in range(nCities):
            if screen.isRowSelected(page, i):
                self.listSelectedCities.append(screen.getTableText(page, 1, i))
    
    def save(self, inputClass):
        name = BugPath.findIniFile("CustomDomAdv.txt", "CustomDomAdv")
        if (name):
            file = open(name, 'w')
    
            if(file != 0):
                pickle.dump({ "version" : self.PICKLED_VERSION, "pages" : self.PAGES }, file)
                file.close()

        return 1

    def ModifyPage(self, inputClass):

        screen = self.getScreen()

        if(self.customizing):
            self.customizing = False

            self.switchPage(self.PAGES[self.currentPageNum]["name"]) # Force a dictionary rebuild.

            self.drawScreen(self.currentPage)

        else:
            self.customizing = True

            self.drawScreen(self.currentPage)

        return 1

    def getSortedColumnSelection(self, screen):

        list = []
        
        for i in range(len(self.PAGES[self.currentPageNum]["columns"])):
            if screen.isRowSelected(self.CUSTOMIZE_PAGE, i):
                list.append(int(screen.getTableText(self.CUSTOMIZE_PAGE, 0, i)) - 1)

        list.sort()

        return list

    def getReverseSortedColumnSelection(self, screen):

        list = self.getSortedColumnSelection(screen)
        list.reverse()
        return list

    def AddCol(self, inputClass):

        self.customizingSaveSelection()
        screen = self.getScreen()

        for i in range(len(self.COLUMNS_LIST)):
            if screen.isRowSelected(self.COLUMNS_LIST_PAGE, i):
                col = self.COLUMNS_LIST[int(screen.getTableText(self.COLUMNS_LIST_PAGE, 0, i))]
                self.PAGES[self.currentPageNum]["columns"].append((col[0], col[1], col[2]))

        self.drawScreen(self.currentPage)
        self.customizingRestoreSelection()
        return 1

    def DelCol(self, inputClass):

        self.customizingSaveSelection()
        screen = self.getScreen()
        list = self.getReverseSortedColumnSelection(screen)

        for i in list:
            if(i == 0):
                continue
            else:
                del self.PAGES[self.currentPageNum]["columns"][i]

        self.drawScreen(self.currentPage)
        self.customizingRestoreSelection()
        return 1

    def MoveColUp(self, inputClass):

        self.customizingSaveSelection()

        screen = self.getScreen()

        list = self.getSortedColumnSelection(screen)

        top = 1

        for i in list:
            if(i == 0):
                continue
            elif i == top:
                top += 1
            else:
                col = self.PAGES[self.currentPageNum]["columns"][i]
                del self.PAGES[self.currentPageNum]["columns"][i]
                self.PAGES[self.currentPageNum]["columns"].insert(i - 1, col)

        self.drawScreen(self.currentPage)
        self.customizingRestoreSelection()

        return 1

    def MoveColDn(self, inputClass):

        self.customizingSaveSelection()

        screen = self.getScreen()

        list = self.getReverseSortedColumnSelection(screen)

        bottom = len(self.PAGES[self.currentPageNum]["columns"]) - 1

        for i in list:
            if(i == 0):
                continue
            elif i == bottom:
                bottom -= 1
            else:
                col = self.PAGES[self.currentPageNum]["columns"][i]
                del self.PAGES[self.currentPageNum]["columns"][i]
                self.PAGES[self.currentPageNum]["columns"].insert(i + 1, col)

        self.drawScreen(self.currentPage)
        self.customizingRestoreSelection()

        return 1

    def customizingClearSelection(self):
        self.customizingSelection = []

    def customizingSaveSelection(self):
        screen = self.getScreen()
        self.customizingSelection = []
        for i in range(len(self.PAGES[self.currentPageNum]["columns"])):
            if screen.isRowSelected(self.CUSTOMIZE_PAGE, i):
                self.customizingSelection.append(screen.getTableText(self.CUSTOMIZE_PAGE, 1, i))

    def customizingRestoreSelection(self):
        screen = self.getScreen()
        # Unselect before selecting, so that the selected rows are forced onscreen.
        for i in range(len(self.PAGES[self.currentPageNum]["columns"])):
            if not screen.getTableText(self.CUSTOMIZE_PAGE, 1, i) in self.customizingSelection:
                screen.selectRow(self.CUSTOMIZE_PAGE, i, False)
        for i in range(len(self.PAGES[self.currentPageNum]["columns"])):
            if screen.getTableText(self.CUSTOMIZE_PAGE, 1, i) in self.customizingSelection:
                screen.selectRow(self.CUSTOMIZE_PAGE, i, True)

    def shrinkCol(self, inputClass):

        self.customizingSaveSelection()
        screen = self.getScreen()
        columns = self.PAGES[self.currentPageNum]["columns"]

        list = self.getReverseSortedColumnSelection(screen)
        for i in list:
            col = columns[i]
            if(col[1] < 2):
                continue
            shrunken = (col[0], col[1] - 1, col[2])
            del columns[i]
            columns.insert(i, shrunken)

        self.drawScreen(self.currentPage)
        self.customizingRestoreSelection()

        return 1

    def widenCol(self, inputClass):

        self.customizingSaveSelection()
        screen = self.getScreen()
        columns = self.PAGES[self.currentPageNum]["columns"]

        list = self.getReverseSortedColumnSelection(screen)
        for i in list:
            col = columns[i]
            wider  = (col[0], col[1] + 1, col[2])
            del columns[i]
            columns.insert(i, wider)

        self.drawScreen(self.currentPage)
        self.customizingRestoreSelection()

        return 1
    
    def toggleShowSpecialistControls(self, inputClass):
        """
        Toggle the page's 'show specialists' field.
        Also toggles the 'show culture/GP legend' fields (one button).
        """
        page = self.PAGES[self.currentPageNum]
        page["showSpecControls"] = not page["showSpecControls"]
        page["showCultureLegend"] = not page["showCultureLegend"]
        page["showGPLegend"] = not page["showGPLegend"]
#       screen.setState(self.TOGGLE_SPECS_NAME, page["showSpecControls"])
        
        return 1
    
    def toggleShowCultureLegend(self, inputClass):
        """
        Toggle the page's 'show culture legend' field.
        """
        page = self.PAGES[self.currentPageNum]
        page["showCultureLegend"] = not page["showCultureLegend"]
        
        return 1
    
    def toggleShowGPLegend(self, inputClass):
        """
        Toggle the page's 'show GP legend' field.
        """
        page = self.PAGES[self.currentPageNum]
        page["showGPLegend"] = not page["showGPLegend"]
        
        return 1

    def addPage(self, inputClass):

        screen = self.getScreen()
        self.customizingClearSelection()
        name = "New Page %d" % (len(self.PAGES) + 1)
        self.PAGES.append(
            {
                "name" : name,
                "showSpecControls" : False,
                "showCultureLegend" : False,
                "showGPLegend" : False,
                "columns" : [
                    ("NAME", 95, "text")
                ]
            }
            )
        self.switchPage(name)
        self.drawScreen(self.currentPage)

        return 1

    def delPage(self, inputClass):

        if(len(self.PAGES) > 1):
            screen = self.getScreen()
            self.customizingClearSelection()
            del self.PAGES[self.currentPageNum]
            self.switchPage(self.PAGES[0]["name"])
            self.drawScreen(self.currentPage)

        return 1

    def upPage(self, inputClass):
        
        if (self.currentPageNum < 1):
            # Cannot move first page up
            return 1
        curPage = self.currentPageNum
        prevPage = curPage - 1
        temp = self.PAGES[curPage]
        self.PAGES[curPage] = self.PAGES[prevPage]
        self.PAGES[prevPage] = temp
        if(self.customizing):
            self.customizingClearSelection()
        self.switchPage(temp["name"])
        self.drawScreen(self.currentPage)

        return 1

    def downPage(self, inputClass):
        
        if (self.currentPageNum + 1 >= len(self.PAGES)):
            # Cannot move last page down
            return 1
        curPage = self.currentPageNum
        nextPage = curPage + 1
        temp = self.PAGES[curPage]
        self.PAGES[curPage] = self.PAGES[nextPage]
        self.PAGES[nextPage] = temp
        if(self.customizing):
            self.customizingClearSelection()
        self.switchPage(temp["name"])
        self.drawScreen(self.currentPage)

        return 1

    def previousPage(self, inputClass):
        
        if (self.currentPageNum < 1):
            # Already on first page
            return 1
        if(self.customizing):
            self.customizingClearSelection()
        self.switchPage(self.PAGES[self.currentPageNum - 1]["name"])
        self.drawScreen(self.currentPage)

        return 1

    def nextPage(self, inputClass):
        
        if (self.currentPageNum + 1 >= len(self.PAGES)):
            # Already on last page
            return 1
        if(self.customizing):
            self.customizingClearSelection()
        self.switchPage(self.PAGES[self.currentPageNum + 1]["name"])
        self.drawScreen(self.currentPage)

        return 1


    def reloadPages(self, inputClass):
        
        self.currentPageNum = 0
        self.loadPages()
        self.switchPage(self.getPageID(self.PAGES[0]["name"]))
        self.drawScreen(self.currentPage)

        return 1

    def getBuildingKey(self, index):

        info = gc.getBuildingInfo(index)
        desc = info.getType()
        key = "_"
        key = key.join(desc.split())
        key = key.upper()
        return key

    def getBonusKey(self, index):

        info = gc.getBonusInfo(index)
        type = info.getType()
        key = "_"
        key = key.join(type.split())
        key = key.upper()
        return key

    def loadPages(self):

        self.PAGES = None
        name = BugPath.findIniFile("CustomDomAdv.txt", "CustomDomAdv")
        if (not name):
            name = BugPath.findIniFile("CustomDomAdv.txt")
        if (name):
            BugConfigTracker.add("CDA_Config", name)
            try:
                file = open(name, 'r')
                dict = pickle.load(file)
                version = dict["version"]
                self.PAGES = dict["pages"]
                file.close()
    
                if version == 0:
                    for p in self.PAGES:
                        newColumns = []
                        for c in p["columns"]:
                            for i in range(gc.getNumBuildingInfos()):
                                info = gc.getBuildingInfo(i)
                                desc = info.getDescription()
                                key = "_"
                                key = key.join(desc.split())
                                key = "BUILDING_" + key.upper()
                                if c[0] == key:
                                    c = (self.getBuildingKey(i), c[1], c[2])
                                    break
                            for i in range(gc.getNumBonusInfos()):
                                info = gc.getBonusInfo(i)
                                desc = info.getDescription()
                                key = "_"
                                key = key.join(desc.split())
                                key = "BONUS_" + key
                                if c[0] == key:
                                    c = (self.getBonusKey(i), c[1], c[2])
                                    break
                            newColumns.append(c)
                        p["columns"] = newColumns
    
                    # Updated from version 0 to version 1 format. Fall through to update version 1 format in the future
                    version = 1                     
    
                if(version != self.PICKLED_VERSION):
                    self.PAGES = None
    
            except IOError:
                self.PAGES = None
            except IndexError:
                self.PAGES = None
            except ValueError:
                self.PAGES = None
            except TypeError:
                self.PAGES = None

        if(self.PAGES is None):
            if(self.isFlavorful):
                self.PAGES =    [
                    {
                        "name" : "Executive Summary", 
                        "showSpecControls" : False,
                        "showCultureLegend" : False,
                        "showGPLegend" : False,
                        "columns" : [
                            ("NAME", 95, "text"),
                            ("AUTOMATION", 80, "text"),
                            ("FEATURES", 92, "text"),
                            ("POPULATION", 35, "int"),
                            ("GARRISON", 30, "int"),
                            ("HAPPY", 30, "int"),
                            ("HEALTH", 30, "int"),
                            ("GROWTH", 35, "int"),
                            ("FOOD", 35, "int"),
                            ("PRODUCTION", 38, "int"),
                            ("MAINTENANCE", 30, "int"),
                            ("BASE_COMMERCE", 38, "int"),
                            ("GOLD", 38, "int"),
                            ("RESEARCH", 38, "int"),
                            ("CULTURE_RATE", 38, "int"),
                            ("CULTURE", 53, "int"),
                            ("GREATPEOPLE_RATE", 38, "int"),
                            ("GREATPEOPLE", 45, "int"),
                            ("PRODUCING", 90, "text"),
                            ("PRODUCING_TURNS", 33, "int"),
                        ]
                    },
                    {
                        "name" : "Specialization", 
                        "showSpecControls" : True,
                        "showCultureLegend" : True,
                        "showGPLegend" : True,
                        "columns" : [
                            ("NAME", 95, "text"),
                            ("FOUNDED", 80, "date"),
                            ("RELIGIONS", 90, "text"),
                            ("SPECIALISTS", 159, "text"),
                            ("HAPPY", 30, "int"),
                            ("GROWTH", 35, "int"),
                            ("FOOD", 35, "int"),
                            ("PRODUCTION", 38, "int"),
                            ("GOLD", 38, "int"),
                            ("RESEARCH", 38, "int"),
                            ("CULTURE_RATE", 38, "int"),
                            ("CULTURE", 53, "int"),
                            ("GREATPEOPLE_RATE", 38, "int"),
                            ("GREATPEOPLE", 45, "int"),
                            ("PRODUCING", 90, "text"),
                            ("PRODUCING_TURNS", 33, "int"),
                        ]
                    },
                    {
                        "name" : "Top Cities - National", 
                        "showSpecControls" : False,
                        "showCultureLegend" : False,
                        "showGPLegend" : False,
                        "columns" : [
                            ("NAME", 95, "text"),
                            ("POPULATION", 35, "int"),
                            ("FEATURES", 92, "text"),
                            ("RELIGIONS", 90, "text"),
                            ("GOLD", 38, "int"),
                            ("NRANK_GOLD",  38, "int"),
                            ("RESEARCH", 38, "int"),
                            ("NRANK_RESEARCH", 38, "int"),
                            ("CULTURE_RATE", 38, "int"),
                            ("NRANK_CULTURE", 38, "int"),
                            ("CULTURE", 53, "int"),
                            ("PRODUCING", 90, "text"),
                            ("PRODUCING_TURNS", 33, "int"),
                        ]
                    },
                    {
                        "name" : "Top Cities - Global", 
                        "showSpecControls" : False,
                        "showCultureLegend" : False,
                        "showGPLegend" : False,
                        "columns" : [
                            ("NAME", 95, "text"),
                            ("POPULATION", 35, "int"),
                            ("FEATURES", 92, "text"),
                            ("RELIGIONS", 90, "text"),
                            ("GOLD", 38, "int"),
                            ("GRANK_GOLD",  38, "int"),
                            ("RESEARCH", 38, "int"),
                            ("GRANK_RESEARCH", 38, "int"),
                            ("CULTURE_RATE", 38, "int"),
                            ("GRANK_CULTURE", 38, "int"),
                            ("CULTURE", 53, "int"),
                            ("PRODUCING", 90, "text"),
                            ("PRODUCING_TURNS", 33, "int"),
                        ]
                    },
                    {
                        "name" : "Military Overview",
                        "showSpecControls" : False,
                        "showCultureLegend" : False,
                        "showGPLegend" : False,
                        "columns" : [
                            ("NAME", 95, "text"),
                            ("GARRISON", 30, "int"),
                            ("DEFENSE", 60, "int"),
                            ("THREATS", 60, "text"),
                            ("CONSCRIPT_UNIT", 90, "text"),
                            (self.getBuildingKey(3), 70, "text"),
                            (self.getBuildingKey(4), 70, "text"),
                            (self.getBuildingKey(5), 70, "text"),
                            (self.getBuildingKey(6), 70, "text"),
                            (self.getBuildingKey(7), 70, "text"),
                            ("PRODUCING", 90, "text"),
                            ("PRODUCING_TURNS", 33, "int"),
                        ]
                    }
                    ]
            else:
                self.PAGES =    [
                    {
                        "name" : "Default View", 
                        "showSpecControls" : False,
                        "showCultureLegend" : False,
                        "showGPLegend" : False,
                        "columns" : [
                            ("NAME", 95, "text"),
                            ("AUTOMATION", 80, "text"),
                            ("FEATURES", 92, "text"),
                            ("POPULATION", 35, "int"),
                            ("GARRISON", 30, "int"),
                            ("HAPPY", 30, "int"),
                            ("HEALTH", 30, "int"),
                            ("GROWTH", 35, "int"),
                            ("FOOD", 35, "int"),
                            ("PRODUCTION", 38, "int"),
                            ("MAINTENANCE", 30, "int"),
                            ("BASE_COMMERCE", 38, "int"),
                            ("GOLD", 38, "int"),
                            ("RESEARCH", 38, "int"),
                            ("CULTURE_RATE", 38, "int"),
                            ("CULTURE", 53, "int"),
                            ("GREATPEOPLE_RATE", 38, "int"),
                            ("GREATPEOPLE", 45, "int"),
                            ("PRODUCING", 90, "text"),
                            ("PRODUCING_TURNS", 33, "int"),
                        ]
                    },
                    {
                        "name" : "Specialists", 
                        "showSpecControls" : True,
                        "showCultureLegend" : True,
                        "showGPLegend" : True,
                        "columns" : [
                            ("NAME", 95, "text"),
                            ("FOUNDED", 80, "date"),
                            ("RELIGIONS", 90, "text"),
                            ("SPECIALISTS", 159, "text"),
                            ("HAPPY", 30, "int"),
                            ("GROWTH", 35, "int"),
                            ("FOOD", 35, "int"),
                            ("PRODUCTION", 38, "int"),
                            ("GOLD", 38, "int"),
                            ("RESEARCH", 38, "int"),
                            ("CULTURE_RATE", 38, "int"),
                            ("CULTURE", 53, "int"),
                            ("GREATPEOPLE_RATE", 38, "int"),
                            ("GREATPEOPLE", 45, "int"),
                            ("PRODUCING", 90, "text"),
                            ("PRODUCING_TURNS", 33, "int"),
                        ]
                    },
                    {
                        "name" : "Growth", 
                        "showSpecControls" : False,
                        "showCultureLegend" : False,
                        "showGPLegend" : False,
                        "columns" : [
                            ("NAME", 95, "text"),
                            ("POPULATION", 35, "int"),
                            ("HAPPY", 30, "int"),
                            ("HEALTH", 30, "int"),
                            ("GROWTH", 35, "int"),
                            ("FOOD", 35, "int"),
                            (self.getBuildingKey(8), 70, "text"),
                            (self.getBuildingKey(12), 70, "text"),
                            (self.getBuildingKey(9), 70, "text"),
                            (self.getBuildingKey(31), 70, "text"),
                            (self.getBuildingKey(10), 70, "text"),
                            (self.getBuildingKey(11), 70, "text"),
                            (self.getBuildingKey(13), 70, "text"),
                            (self.getBuildingKey(33), 70, "text"),
                            ("PRODUCING", 90, "text"),
                            ("PRODUCING_TURNS", 33, "int"),
                        ]
                    },
                    {
                        "name" : "Military",
                        "showSpecControls" : False,
                        "showCultureLegend" : False,
                        "showGPLegend" : False,
                        "columns" : [
                            ("NAME", 95, "text"),
                            ("GARRISON", 30, "int"),
                            ("DEFENSE", 60, "int"),
                            ("THREATS", 60, "text"),
                            ("CONSCRIPT_UNIT", 90, "text"),
                            (self.getBuildingKey(3), 70, "text"),
                            (self.getBuildingKey(4), 70, "text"),
                            (self.getBuildingKey(5), 70, "text"),
                            (self.getBuildingKey(6), 70, "text"),
                            (self.getBuildingKey(7), 70, "text"),
                            ("PRODUCING", 90, "text"),
                            ("PRODUCING_TURNS", 33, "int"),
                        ]
                    }
                ]

        # Fix and retain configuration from previous versions, when possible.
        for p in self.PAGES:

            if not p.has_key("name"):
                p["name"] = "Unnamed"

            if not p.has_key("showSpecControls"):
                p["showSpecControls"] = False

            if not p.has_key("showCultureLegend"):
                p["showCultureLegend"] = False

            if not p.has_key("showGPLegend"):
                p["showGPLegend"] = False

            if not p.has_key("columns"):
                p["columns"] = [("NAME", 95, "text")]


    def renamePage(self, inputClass):

        eventManager = CvEventInterface.getEventManager()

        if not self.renameEventContext or self.renameEventContext is None:

            for i in range(5000, 6000):
                if not eventManager.Events.has_key(i):
                    self.renameEventContext = i
                    eventManager.Events[self.renameEventContext] = ('DomAdvRenamePage', self.renameApply, self.renameBegin)
                    CvUtil.SilentEvents.append(self.renameEventContext)
                    break

        CvEventInterface.beginEvent(self.renameEventContext)

    def renameBegin(self, argsList):

        popup = PyPopup.PyPopup(self.renameEventContext, EventContextTypes.EVENTCONTEXT_SELF)
        popup.setSize(400,175)
        popup.setUserData( (self.currentPageNum, 0) )
        popup.setHeaderString(u"Rename Domestic Advisor Page")
        popup.setBodyString("Enter a name for this domestic advisor page")
        popup.createEditBox( self.PAGES[self.currentPageNum]["name"], 0 )
        #popup.createRadioButtons(2, 1)
        #popup.setCheckBoxText(0, "Show specialist controls", 1)
        #popup.setCheckBoxText(1, "Hide specialist controls", 1)
        #popup.createRadioButtons(2, 2)
        #popup.setRadioButtonText(0, "Show culture legend", 2)
        #popup.setRadioButtonText(1, "Hide culture legend", 2)
        #popup.createRadioButtons(2, 3)
        #popup.setCheckBoxText(0, "Show great person legend", 3)
        #popup.setCheckBoxText(1, "Hide great person legend", 3)
        popup.launch()

        return 0

    def renameApply(self, playerID, userData, popupReturn):

        pageNum = userData[0]

        self.customizingSaveSelection()
        screen = self.getScreen()

        self.PAGES[pageNum]["name"] = popupReturn.getEditBoxString(0)
        #self.PAGES[pageNum]["showSpecControls"] = bool(popupReturn.getSelectedRadioButton(1))
        #self.PAGES[pageNum]["showCultureLegend"] = bool(popupReturn.getSelectedRadioButton(2))
        #self.PAGES[pageNum]["nshowGPLegendame"] = bool(popupReturn.getSelectedRadioButton(3))

        self.drawScreen(self.currentPage)
        self.customizingRestoreSelection()

        return 0
    
    def stripStr(self, s, out):
        while s.find(out) != -1:
            s = s[0:s.find(out)] + s[s.find(out) + 1:]

        return s
