<commit_before># Orca
#
# Copyright 2004-2009 Sun Microsystems Inc.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
# Boston MA  02110-1301 USA.

"""Manages the formatting settings for Orca."""

__id__        = "$Id:$"
__version__   = "$Revision:$"
__date__      = "$Date:$"
__copyright__ = "Copyright (c) 2004-2009 Sun Microsystems Inc."
__license__   = "LGPL"

import copy

import pyatspi

from . import object_properties
from . import settings

# pylint: disable-msg=C0301

TUTORIAL = '(tutorial and (pause + tutorial) or [])'
MNEMONIC = '(mnemonic and (pause + mnemonic + lineBreak) or [])'

BRAILLE_TEXT = '[Text(obj, asString(labelOrName + placeholderText), asString(eol))]\
                + (required and [Region(" " + asString(required))])\
                + (readOnly and [Region(" " + asString(readOnly))])'

formatting = {

    ####################################################################
    #                                                                  #
    # Strings Orca includes on its own (versus getting them from the   #
    # application.                                                     #
    #                                                                  #
    ####################################################################

    'strings' : {
        'speech': {
            'required': object_properties.STATE_REQUIRED_SPEECH,
            'readonly': object_properties.STATE_READ_ONLY_SPEECH,
            'insensitive': object_properties.STATE_INSENSITIVE_SPEECH,
            'checkbox': object_properties.CHECK_BOX_INDICATORS_SPEECH,
            'radiobutton': object_properties.RADIO_BUTTON_INDICATORS_SPEECH,
            'togglebutton': object_properties.TOGGLE_BUTTON_INDICATORS_SPEECH,
            'expansion': object_properties.EXPANSION_INDICATORS_SPEECH,
            'nodelevel': object_properties.NODE_LEVEL_SPEECH,
            'nestinglevel': object_properties.NESTING_LEVEL_SPEECH,
            'multiselect': object_properties.STATE_MULTISELECT_SPEECH,
            'iconindex': object_properties.ICON_INDEX_SPEECH,
            'groupindex': object_properties.GROUP_INDEX_SPEECH,
            'clickable': object_properties.STATE_CLICKABLE,
            'haslongdesc': object_properties.STATE_HAS_LONGDESC,
        },
        'braille': {
            'eol': object_properties.EOL_INDICATOR_BRAILLE,
            'required': object_properties.STATE_REQUIRED_BRAILLE,
            'readonly': object_properties.STATE_READ_ONLY_BRAILLE,
            'insensitive': object_properties.STATE_INSENSITIVE_BRAILLE,
            'checkbox': object_properties.CHECK_BOX_INDICATORS_BRAILLE,
            'radiobutton': object_properties.RADIO_BUTTON_INDICATORS_BRAILLE,
            'togglebutton': object_properties.TOGGLE_BUTTON_INDICATORS_BRAILLE,
            'expansion': object_properties.EXPANSION_INDICATORS_BRAILLE,
            'nodelevel': object_properties.NODE_LEVEL_BRAILLE,
            'nestinglevel': object_properties.NESTING_LEVEL_BRAILLE,
        },
    },

    ####################################################################
    #                                                                  #
    # Formatting for speech.                                           #
    #                                                                  #
    ####################################################################

    'speech': {
        'prefix': {
            'focused': '[]',
            'unfocused': 'oldAncestors + newAncestors',
            'basicWhereAmI': 'toolbar',
            'detailedWhereAmI' : '[]'
            },
        'suffix': {
            'focused': '[]',
            'unfocused': 'newNodeLevel + unselectedCell + ' + TUTORIAL,
            'basicWhereAmI': TUTORIAL + ' + description',
            'detailedWhereAmI' : '[]'
            },
        'default': {
            'focused': '[]',
            'unfocused': 'labelAndName + allTextSelection + roleName + availability + ' + MNEMONIC + ' + accelerator + childWidget',
            'basicWhereAmI': 'labelAndName + roleName',
            'detailedWhereAmI' : '[]'
            },
        pyatspi.ROLE_ALERT: {
            'unfocused': 'labelAndName + unrelatedLabels'
            },
        pyatspi.ROLE_ANIMATION: {
            'unfocused': 'labelAndName'
            },
        pyatspi.ROLE_CANVAS: {
            'focused': 'labelAndName + imageDescription + roleName + positionInList',
            'unfocused': 'labelAndName + imageDescription + roleName + positionInList',
            'basicWhereAmI': 'parentRoleName + labelAndName + selectedItemCount',
            'detailedWhereAmI': 'parentRoleName + labelAndName + selectedItemCount + selectedItems'
            },
        pyatspi.ROLE_CHECK_BOX: {
            'focused': 'checkedState',
            'unfocused': 'labelAndName + roleName + checkedState + required + availability + ' + MNEMONIC + ' + accelerator',
            'basicWhereAmI': 'namedContainingPanel + labelAndName + roleName + checkedState + ' + MNEMONIC + ' + accelerator + required'
            },
        pyatspi.ROLE_CHECK_MENU_ITEM: {
            'focused': 'checkedState',
            'unfocused': 'labelAndName + roleName + checkedState + required + availability + ' + MNEMONIC + ' + accelerator + positionInList',
            'basicWhereAmI': 'ancestors + labelAndName + roleName + checkedState + accelerator + positionInList + ' + MNEMONIC
            },
        pyatspi.ROLE_COLOR_CHOOSER: {
            'focused': 'value',
            'unfocused': 'label + roleName + value + required + availability + ' + MNEMONIC,
            'basicWhereAmI': 'label + roleName + value + percentage + ' + MNEMONIC + ' + accelerator + required'
            },
        pyatspi.ROLE_COMBO_BOX: {
            'focused': 'expandableState',
            'unfocused': 'label + name + roleName + positionInList + ' + MNEMONIC + ' + accelerator',
            'basicWhereAmI': 'label + roleName + name + positionInList + ' + MNEMONIC + ' + accelerator'
            },
        pyatspi.ROLE_DIAL: {
            'focused': 'value',
            'unfocused': 'labelOrName + roleName + value + required + availability + ' + MNEMONIC,
            'basicWhereAmI': 'labelOrName + roleName + value + percentage + ' + MNEMONIC + ' + accelerator + required'
            },
        pyatspi.ROLE_DIALOG: {
            'unfocused': 'labelAndName + unrelatedLabels'
            },
        pyatspi.ROLE_DOCUMENT_FRAME: {
            'basicWhereAmI': 'label + readOnly + textRole + textContent + anyTextSelection + ' + MNEMONIC,
            'detailedWhereAmI': 'label + readOnly + textRole + textContentWithAttributes + anyTextSelection + ' + MNEMONIC + ' + ' + TUTORIAL
            },
        pyatspi.ROLE_EMBEDDED: {
            'focused': 'embedded',
            'unfocused': 'embedded'
            },
        pyatspi.ROLE_ENTRY: {
            'focused': 'labelOrName + placeholderText + readOnly + textRole + currentLineText + allTextSelection',
            'unfocused': 'labelOrName + placeholderText + readOnly + textRole + currentLineText + allTextSelection + ' + MNEMONIC,
            'basicWhereAmI': 'labelOrName + placeholderText + readOnly + textRole + textContent + anyTextSelection + ' + MNEMONIC,
            'detailedWhereAmI': 'labelOrName + placeholderText + readOnly + textRole + textContentWithAttributes + anyTextSelection + ' + MNEMONIC + ' + ' + TUTORIAL
            },
        pyatspi.ROLE_FRAME: {
            'focused': 'labelAndName + roleName',
            'unfocused': 'labelAndName + allTextSelection + roleName + unfocusedDialogCount + availability'
            },
        pyatspi.ROLE_HEADING: {
            'basicWhereAmI': 'label + readOnly + textRole + textContent + anyTextSelection + ' + MNEMONIC,
            'detailedWhereAmI': 'label + readOnly + textRole + textContentWithAttributes + anyTextSelection + ' + MNEMONIC + ' + ' + TUTORIAL
            },
        pyatspi.ROLE_ICON: {
            'focused': 'labelAndName + imageDescription + roleName + positionInList',
            'unfocused': 'labelAndName + imageDescription + roleName + positionInList',
            'basicWhereAmI': 'parentRoleName + labelAndName + selectedItemCount',
            'detailedWhereAmI': 'parentRoleName + labelAndName + selectedItemCount + selectedItems'
            },
        pyatspi.ROLE_INFO_BAR: {
            'unfocused': 'labelAndName + unrelatedLabels'
            },
        pyatspi.ROLE_LABEL: {
            'basicWhereAmI': 'labelAndName + allTextSelection + roleName'
            },
        pyatspi.ROLE_LAYERED_PANE: {
            'focused': 'labelAndName + allTextSelection + roleName + availability + noShowingChildren',
            'unfocused': 'labelAndName + allTextSelection + roleName + availability + noShowingChildren',
            'basicWhereAmI': 'labelAndName + roleName + selectedItemCount',
            'detailedWhereAmI': 'labelAndName + roleName + selectedItemCount + selectedItems'
            },
        pyatspi.ROLE_LINK: {
            'unfocused': 'labelAndName + roleName + expandableState + availability + ' + MNEMONIC,
            'basicWhereAmI': 'linkInfo + siteDescription + fileSize + ' + MNEMONIC
            },
        pyatspi.ROLE_LIST: {
            'focused': 'labelOrName + multiselectableState + numberOfChildren',
            'unfocused': 'labelOrName + focusedItem + multiselectableState + numberOfChildren'
            },
        pyatspi.ROLE_LIST_BOX: {
            'focused': 'labelOrName + multiselectableState + numberOfChildren',
            'unfocused': 'labelOrName + focusedItem + multiselectableState + numberOfChildren'
            },
        pyatspi.ROLE_LIST_ITEM: {
            'focused': 'expandableState + availability',
            'unfocused': 'labelAndName + allTextSelection + expandableState + availability + positionInList + childWidget',
            'basicWhereAmI': 'label + roleName + name + positionInList + expandableState + (nodeLevel or nestingLevel)'
            },
        pyatspi.ROLE_MENU: {
            'focused': 'labelAndName + roleName',
            'unfocused': 'labelAndName + allTextSelection + roleName + availability + ' + MNEMONIC + ' + accelerator + positionInList',
            'basicWhereAmI': '(ancestors or parentRoleName) + labelAndName + roleName +  positionInList + ' + MNEMONIC
            },
        pyatspi.ROLE_MENU_ITEM: {
            'focused': 'expandableState',
            'unfocused': 'labelAndName + menuItemCheckedState + expandableState + availability + ' + MNEMONIC + ' + accelerator + positionInList',
            'basicWhereAmI': 'ancestors + labelAndName + accelerator + positionInList + ' + MNEMONIC
            },
        pyatspi.ROLE_NOTIFICATION: {
            'unfocused': 'roleName + unrelatedLabels'
            },
        pyatspi.ROLE_PAGE: {
            'focused': 'label + readOnly + currentLineText + anyTextSelection',
            'unfocused': 'label + readOnly + currentLineText + anyTextSelection + ' + MNEMONIC,
            'basicWhereAmI': 'label + readOnly + textRole + textContent + anyTextSelection + ' + MNEMONIC,
            'detailedWhereAmI': 'label + readOnly + textRole + textContentWithAttributes + anyTextSelection + ' + MNEMONIC
            },
        pyatspi.ROLE_PAGE_TAB: {
            'focused': 'labelAndName + roleName + positionInList + ' + MNEMONIC + ' + accelerator',
            'unfocused': 'labelAndName + roleName + positionInList + ' + MNEMONIC + ' + accelerator',
            'basicWhereAmI': 'parentRoleName + labelAndName + roleName + positionInList + ' + MNEMONIC + ' + accelerator'
            },
        pyatspi.ROLE_PANEL: {
            'focused': 'labelAndName + roleName',
            },
        pyatspi.ROLE_PARAGRAPH: {
            'focused': 'labelOrName + readOnly + textRole + currentLineText + allTextSelection',
            'unfocused': 'labelOrName + readOnly + textRole + currentLineText + allTextSelection + ' + MNEMONIC,
            'basicWhereAmI': 'label + readOnly + textRole + textContent + anyTextSelection + ' + MNEMONIC,
            'detailedWhereAmI': 'label + readOnly + textRole + textContentWithAttributes + anyTextSelection + ' + MNEMONIC + ' + ' + TUTORIAL
            },
        pyatspi.ROLE_PASSWORD_TEXT: {
            'focused': 'labelOrName + readOnly + textRole + currentLineText + allTextSelection',
            'unfocused': 'labelOrName + readOnly + textRole + currentLineText + allTextSelection + ' + MNEMONIC,
            'basicWhereAmI': 'label + readOnly + textRole + textContent + anyTextSelection + ' + MNEMONIC,
            'detailedWhereAmI': 'label + readOnly + textRole + textContentWithAttributes + anyTextSelection + ' + MNEMONIC + ' + ' + TUTORIAL
            },
        pyatspi.ROLE_PROGRESS_BAR: {
            'focused': 'percentage',
            'unfocused': 'labelAndName + percentage'
            },
        pyatspi.ROLE_PUSH_BUTTON: {
            'focused': 'expandableState',
            'unfocused': 'labelAndName + expandableState + roleName + availability + ' + MNEMONIC + ' + accelerator',
            'basicWhereAmI': 'labelAndName + expandableState + roleName + ' + MNEMONIC + ' + accelerator'
            },
        pyatspi.ROLE_RADIO_BUTTON: {
            'focused': 'radioState',
            'unfocused': 'labelAndName + radioState + roleName + availability + ' + MNEMONIC + ' + accelerator + positionInList',
            'basicWhereAmI': 'radioButtonGroup + labelAndName + roleName + radioState + positionInGroup + ' + MNEMONIC + ' + accelerator'
            },
        pyatspi.ROLE_RADIO_MENU_ITEM: {
            # OpenOffice check menu items currently have a role of "menu item"
            # rather then "check menu item", so we need to test if one of the
            # states is CHECKED. If it is, then add that in to the list of
            # speech utterances. Note that we can't tell if this is a "check
            # menu item" that is currently unchecked and speak that state.
            # See Orca bug #433398 for more details.
            #
            'focused': 'labelAndName + radioState + roleName + availability + positionInList',
            'unfocused': 'labelAndName + radioState + roleName + availability + ' + MNEMONIC + ' + accelerator + positionInList',
            'basicWhereAmI': 'ancestors + labelAndName + roleName + radioState + accelerator + positionInList + ' + MNEMONIC
            },
        pyatspi.ROLE_SCROLL_BAR: {
            'focused': 'value',
            'unfocused': 'labelOrName + roleName + value + required + availability + ' + MNEMONIC,
            'basicWhereAmI': 'labelOrName + roleName + value + percentage + ' + MNEMONIC + ' + accelerator + required'
            },
        pyatspi.ROLE_SECTION: {
            'basicWhereAmI': 'label + readOnly + textRole + textContent + anyTextSelection + ' + MNEMONIC,
            'detailedWhereAmI': 'label + readOnly + textRole + textContentWithAttributes + anyTextSelection + ' + MNEMONIC + ' + ' + TUTORIAL
            },
        pyatspi.ROLE_SLIDER: {
            'focused': 'value',
            'unfocused': 'labelOrName + roleName + value + required + availability + ' + MNEMONIC,
            'basicWhereAmI': 'labelOrName + roleName + value + percentage + ' + MNEMONIC + ' + accelerator + required'
            },
        pyatspi.ROLE_SPIN_BUTTON: {
            'focused': 'name',
            'unfocused': 'labelAndName + allTextSelection + roleName + availability + ' + MNEMONIC + ' + required',
            'basicWhereAmI': 'label + roleName + name + allTextSelection + ' + MNEMONIC + ' + accelerator + required'
            },
        pyatspi.ROLE_SPLIT_PANE: {
            'focused': 'value',
            'unfocused': 'labelAndName + roleName + value + availability + ' + MNEMONIC,
            'basicWhereAmI' : 'labelAndName + roleName + value'
            },
        pyatspi.ROLE_TABLE: {
            'focused': 'labelAndName + table',
            'unfocused': 'labelAndName + table',
            'basicWhereAmI': 'labelAndName + table'
            },
        pyatspi.ROLE_TABLE_CELL: {
            'focused': '(tableCell2ChildLabel + tableCell2ChildToggle)\
                        or (cellCheckedState + (expandableState and (expandableState + numberOfChildren)))',
            'unfocused': 'tableCellRow',
            'basicWhereAmI': 'parentRoleName + columnHeader + rowHeader + roleName + cellCheckedState + (realActiveDescendantDisplayedText or imageDescription + image) + columnAndRow + expandableState + nodeLevel',
            'detailedWhereAmI': 'parentRoleName + columnHeader + rowHeader + roleName + cellCheckedState + (realActiveDescendantDisplayedText or imageDescription + image) + columnAndRow + tableCellRow + expandableState + nodeLevel'
            },
        'REAL_ROLE_TABLE_CELL': {
            # the real cell information
            # note that pyatspi.ROLE_TABLE_CELL is used to work out if we need to
            # read a whole row. It calls REAL_ROLE_TABLE_CELL internally.
            # maybe it can be done in a cleaner way?
            #
            'focused':   '(tableCell2ChildLabel + tableCell2ChildToggle)\
                          or (cellCheckedState + (expandableState and (expandableState + numberOfChildren)))',
            'unfocused': '(tableCell2ChildLabel + tableCell2ChildToggle)\
                          or (newRowHeader + (newColumnHeader or columnHeaderIfToggleAndNoText) \
                              + cellCheckedState\
                              + (realActiveDescendantDisplayedText or imageDescription + image)\
                              + (expandableState and (expandableState + numberOfChildren))\
                              + required)'
            },
        pyatspi.ROLE_TEAROFF_MENU_ITEM: {
            'focused': '[]',
            'unfocused': 'labelAndName + allTextSelection + roleName + availability '
            },
        pyatspi.ROLE_TERMINAL: {
            'focused': 'terminal',
            'unfocused': 'terminal',
            'basicWhereAmI': 'label + readOnly + textRole + textContent + anyTextSelection + ' + MNEMONIC,
            'detailedWhereAmI': 'label + readOnly + textRole + textContentWithAttributes + anyTextSelection + ' + MNEMONIC + ' + ' + TUTORIAL
            },
        pyatspi.ROLE_TEXT: {
            'focused': 'labelOrName + placeholderText + readOnly + textRole + textIndentation + currentLineText + allTextSelection',
            'unfocused': 'labelOrName + placeholderText + readOnly + textRole + textIndentation + currentLineText + allTextSelection + ' + MNEMONIC,
            'basicWhereAmI': 'label + placeholderText + readOnly + textRole + textContent + anyTextSelection + ' + MNEMONIC,
            'detailedWhereAmI': 'label + placeholderText + readOnly + textRole + textContentWithAttributes + anyTextSelection + ' + MNEMONIC + ' + ' + TUTORIAL
            },
        pyatspi.ROLE_TOGGLE_BUTTON: {
            'focused': 'expandableState or toggleState',
            'unfocused': 'labelAndName + roleName + (expandableState or toggleState) + availability + ' + MNEMONIC + ' + accelerator',
            'basicWhereAmI': 'labelAndName + roleName + (expandableState or toggleState)'
            },
        pyatspi.ROLE_TOOL_TIP: {
            'unfocused': 'labelAndName',
            'basicWhereAmI': 'labelAndName'
            },
    },

    ####################################################################
    #                                                                  #
    # Formatting for braille.                                          #
    #                                                                  #
    ####################################################################

    'braille': {
        'prefix': {
#            'focused':   'ancestors\
#                         + (rowHeader and [Region(" " + asString(rowHeader))])\
#                         + (columnHeader and [Region(" " + asString(columnHeader))])\
#                         + (radioButtonGroup and [Region(" " + asString(radioButtonGroup))])\
#                         + [Region(" ")]',
#            'unfocused': 'ancestors\
#                         + (rowHeader and [Region(" " + asString(rowHeader))])\
#                         + (columnHeader and [Region(" " + asString(columnHeader))])\
#                         + (radioButtonGroup and [Region(" " + asString(radioButtonGroup))])\
#                         + [Region(" ")]',
            'focused':   '(includeContext\
                           and (ancestors\
                                + (rowHeader and [Region(" " + asString(rowHeader))])\
                                + (columnHeader and [Region(" " + asString(columnHeader))])\
                                + (radioButtonGroup and [Region(" " + asString(radioButtonGroup))])\
                                + [Region(" ")])\
                           or [])',
            'unfocused': '(includeContext\
                           and (ancestors\
                                + (rowHeader and [Region(" " + asString(rowHeader))])\
                                + (columnHeader and [Region(" " + asString(columnHeader))])\
                                + (radioButtonGroup and [Region(" " + asString(radioButtonGroup))])\
                                + [Region(" ")])\
                           or [])',
            },
        'suffix': {
            'focused':   '(nodeLevel and [Region(" " + asString(nodeLevel))])',
            'unfocused': '(nodeLevel and [Region(" " + asString(nodeLevel))])',
            },
        'default': {
            'focused':   '[Component(obj,\
                                     asString(label + displayedText + value + roleName + required))]',
            'unfocused': '[Component(obj,\
                                     asString(label + displayedText + value + roleName + required))]',
            },
        #pyatspi.ROLE_ALERT: 'default'
        pyatspi.ROLE_ANIMATION: {
            'unfocused': '[Component(obj,\
                                     asString(label + displayedText + roleName + (description and space(": ") + description)))]',
            },
        #pyatspi.ROLE_ARROW: 'default'
        pyatspi.ROLE_CANVAS: {
            'unfocused': '[Component(obj,\
                                     asString(((label + displayedText + imageDescription) or name) + roleName))]'
            },
        pyatspi.ROLE_CHECK_BOX: {
            'unfocused': '[Component(obj,\
                                     asString(labelOrName + roleName),\
                                     indicator=asString(checkedState))]'
            },
        pyatspi.ROLE_CHECK_MENU_ITEM: {
            'unfocused': '[Component(obj,\
                                     asString(label + displayedText + roleName + availability) + asString(accelerator),\
                                     indicator=asString(checkedState))]'
            },
        #pyatspi.ROLE_COLUMN_HEADER: 'default'
        pyatspi.ROLE_COMBO_BOX: {
            # [[[TODO: WDW - maybe pass the label into the region constructor?
            # We could then use the cursorOffset field to indicate where the
            # combobox starts.]]]
            #
            'unfocused': '((comboBoxTextObj and [Text(comboBoxTextObj[0], asString(label), asString(eol))])\
                           or [Component(obj, asString(label + name), label and (len(asString(label)) + 1) or 0)])\
                          + [Region(" " + asString(roleName))]'
            },
        #pyatspi.ROLE_DESKTOP_ICON: 'default'
        pyatspi.ROLE_DIAL: {
            'unfocused': '[Component(obj,\
                                     asString(labelOrName + value + roleName + required))]'
            },
        #pyatspi.ROLE_DIALOG: 'default'
        #pyatspi.ROLE_DIRECTORY_PANE: 'default'
        pyatspi.ROLE_EMBEDDED: {
            'unfocused': '[Component(obj,\<commit_msg>Create an explicit braille formatting string for ROLE_DOCUMENT_FRAME<commit_after># Orca
#
# Copyright 2004-2009 Sun Microsystems Inc.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
# Boston MA  02110-1301 USA.

"""Manages the formatting settings for Orca."""

__id__        = "$Id:$"
__version__   = "$Revision:$"
__date__      = "$Date:$"
__copyright__ = "Copyright (c) 2004-2009 Sun Microsystems Inc."
__license__   = "LGPL"

import copy

import pyatspi

from . import object_properties
from . import settings

# pylint: disable-msg=C0301

TUTORIAL = '(tutorial and (pause + tutorial) or [])'
MNEMONIC = '(mnemonic and (pause + mnemonic + lineBreak) or [])'

BRAILLE_TEXT = '[Text(obj, asString(labelOrName + placeholderText), asString(eol))]\
                + (required and [Region(" " + asString(required))])\
                + (readOnly and [Region(" " + asString(readOnly))])'

formatting = {

    ####################################################################
    #                                                                  #
    # Strings Orca includes on its own (versus getting them from the   #
    # application.                                                     #
    #                                                                  #
    ####################################################################

    'strings' : {
        'speech': {
            'required': object_properties.STATE_REQUIRED_SPEECH,
            'readonly': object_properties.STATE_READ_ONLY_SPEECH,
            'insensitive': object_properties.STATE_INSENSITIVE_SPEECH,
            'checkbox': object_properties.CHECK_BOX_INDICATORS_SPEECH,
            'radiobutton': object_properties.RADIO_BUTTON_INDICATORS_SPEECH,
            'togglebutton': object_properties.TOGGLE_BUTTON_INDICATORS_SPEECH,
            'expansion': object_properties.EXPANSION_INDICATORS_SPEECH,
            'nodelevel': object_properties.NODE_LEVEL_SPEECH,
            'nestinglevel': object_properties.NESTING_LEVEL_SPEECH,
            'multiselect': object_properties.STATE_MULTISELECT_SPEECH,
            'iconindex': object_properties.ICON_INDEX_SPEECH,
            'groupindex': object_properties.GROUP_INDEX_SPEECH,
            'clickable': object_properties.STATE_CLICKABLE,
            'haslongdesc': object_properties.STATE_HAS_LONGDESC,
        },
        'braille': {
            'eol': object_properties.EOL_INDICATOR_BRAILLE,
            'required': object_properties.STATE_REQUIRED_BRAILLE,
            'readonly': object_properties.STATE_READ_ONLY_BRAILLE,
            'insensitive': object_properties.STATE_INSENSITIVE_BRAILLE,
            'checkbox': object_properties.CHECK_BOX_INDICATORS_BRAILLE,
            'radiobutton': object_properties.RADIO_BUTTON_INDICATORS_BRAILLE,
            'togglebutton': object_properties.TOGGLE_BUTTON_INDICATORS_BRAILLE,
            'expansion': object_properties.EXPANSION_INDICATORS_BRAILLE,
            'nodelevel': object_properties.NODE_LEVEL_BRAILLE,
            'nestinglevel': object_properties.NESTING_LEVEL_BRAILLE,
        },
    },

    ####################################################################
    #                                                                  #
    # Formatting for speech.                                           #
    #                                                                  #
    ####################################################################

    'speech': {
        'prefix': {
            'focused': '[]',
            'unfocused': 'oldAncestors + newAncestors',
            'basicWhereAmI': 'toolbar',
            'detailedWhereAmI' : '[]'
            },
        'suffix': {
            'focused': '[]',
            'unfocused': 'newNodeLevel + unselectedCell + ' + TUTORIAL,
            'basicWhereAmI': TUTORIAL + ' + description',
            'detailedWhereAmI' : '[]'
            },
        'default': {
            'focused': '[]',
            'unfocused': 'labelAndName + allTextSelection + roleName + availability + ' + MNEMONIC + ' + accelerator + childWidget',
            'basicWhereAmI': 'labelAndName + roleName',
            'detailedWhereAmI' : '[]'
            },
        pyatspi.ROLE_ALERT: {
            'unfocused': 'labelAndName + unrelatedLabels'
            },
        pyatspi.ROLE_ANIMATION: {
            'unfocused': 'labelAndName'
            },
        pyatspi.ROLE_CANVAS: {
            'focused': 'labelAndName + imageDescription + roleName + positionInList',
            'unfocused': 'labelAndName + imageDescription + roleName + positionInList',
            'basicWhereAmI': 'parentRoleName + labelAndName + selectedItemCount',
            'detailedWhereAmI': 'parentRoleName + labelAndName + selectedItemCount + selectedItems'
            },
        pyatspi.ROLE_CHECK_BOX: {
            'focused': 'checkedState',
            'unfocused': 'labelAndName + roleName + checkedState + required + availability + ' + MNEMONIC + ' + accelerator',
            'basicWhereAmI': 'namedContainingPanel + labelAndName + roleName + checkedState + ' + MNEMONIC + ' + accelerator + required'
            },
        pyatspi.ROLE_CHECK_MENU_ITEM: {
            'focused': 'checkedState',
            'unfocused': 'labelAndName + roleName + checkedState + required + availability + ' + MNEMONIC + ' + accelerator + positionInList',
            'basicWhereAmI': 'ancestors + labelAndName + roleName + checkedState + accelerator + positionInList + ' + MNEMONIC
            },
        pyatspi.ROLE_COLOR_CHOOSER: {
            'focused': 'value',
            'unfocused': 'label + roleName + value + required + availability + ' + MNEMONIC,
            'basicWhereAmI': 'label + roleName + value + percentage + ' + MNEMONIC + ' + accelerator + required'
            },
        pyatspi.ROLE_COMBO_BOX: {
            'focused': 'expandableState',
            'unfocused': 'label + name + roleName + positionInList + ' + MNEMONIC + ' + accelerator',
            'basicWhereAmI': 'label + roleName + name + positionInList + ' + MNEMONIC + ' + accelerator'
            },
        pyatspi.ROLE_DIAL: {
            'focused': 'value',
            'unfocused': 'labelOrName + roleName + value + required + availability + ' + MNEMONIC,
            'basicWhereAmI': 'labelOrName + roleName + value + percentage + ' + MNEMONIC + ' + accelerator + required'
            },
        pyatspi.ROLE_DIALOG: {
            'unfocused': 'labelAndName + unrelatedLabels'
            },
        pyatspi.ROLE_DOCUMENT_FRAME: {
            'basicWhereAmI': 'label + readOnly + textRole + textContent + anyTextSelection + ' + MNEMONIC,
            'detailedWhereAmI': 'label + readOnly + textRole + textContentWithAttributes + anyTextSelection + ' + MNEMONIC + ' + ' + TUTORIAL
            },
        pyatspi.ROLE_EMBEDDED: {
            'focused': 'embedded',
            'unfocused': 'embedded'
            },
        pyatspi.ROLE_ENTRY: {
            'focused': 'labelOrName + placeholderText + readOnly + textRole + currentLineText + allTextSelection',
            'unfocused': 'labelOrName + placeholderText + readOnly + textRole + currentLineText + allTextSelection + ' + MNEMONIC,
            'basicWhereAmI': 'labelOrName + placeholderText + readOnly + textRole + textContent + anyTextSelection + ' + MNEMONIC,
            'detailedWhereAmI': 'labelOrName + placeholderText + readOnly + textRole + textContentWithAttributes + anyTextSelection + ' + MNEMONIC + ' + ' + TUTORIAL
            },
        pyatspi.ROLE_FRAME: {
            'focused': 'labelAndName + roleName',
            'unfocused': 'labelAndName + allTextSelection + roleName + unfocusedDialogCount + availability'
            },
        pyatspi.ROLE_HEADING: {
            'basicWhereAmI': 'label + readOnly + textRole + textContent + anyTextSelection + ' + MNEMONIC,
            'detailedWhereAmI': 'label + readOnly + textRole + textContentWithAttributes + anyTextSelection + ' + MNEMONIC + ' + ' + TUTORIAL
            },
        pyatspi.ROLE_ICON: {
            'focused': 'labelAndName + imageDescription + roleName + positionInList',
            'unfocused': 'labelAndName + imageDescription + roleName + positionInList',
            'basicWhereAmI': 'parentRoleName + labelAndName + selectedItemCount',
            'detailedWhereAmI': 'parentRoleName + labelAndName + selectedItemCount + selectedItems'
            },
        pyatspi.ROLE_INFO_BAR: {
            'unfocused': 'labelAndName + unrelatedLabels'
            },
        pyatspi.ROLE_LABEL: {
            'basicWhereAmI': 'labelAndName + allTextSelection + roleName'
            },
        pyatspi.ROLE_LAYERED_PANE: {
            'focused': 'labelAndName + allTextSelection + roleName + availability + noShowingChildren',
            'unfocused': 'labelAndName + allTextSelection + roleName + availability + noShowingChildren',
            'basicWhereAmI': 'labelAndName + roleName + selectedItemCount',
            'detailedWhereAmI': 'labelAndName + roleName + selectedItemCount + selectedItems'
            },
        pyatspi.ROLE_LINK: {
            'unfocused': 'labelAndName + roleName + expandableState + availability + ' + MNEMONIC,
            'basicWhereAmI': 'linkInfo + siteDescription + fileSize + ' + MNEMONIC
            },
        pyatspi.ROLE_LIST: {
            'focused': 'labelOrName + multiselectableState + numberOfChildren',
            'unfocused': 'labelOrName + focusedItem + multiselectableState + numberOfChildren'
            },
        pyatspi.ROLE_LIST_BOX: {
            'focused': 'labelOrName + multiselectableState + numberOfChildren',
            'unfocused': 'labelOrName + focusedItem + multiselectableState + numberOfChildren'
            },
        pyatspi.ROLE_LIST_ITEM: {
            'focused': 'expandableState + availability',
            'unfocused': 'labelAndName + allTextSelection + expandableState + availability + positionInList + childWidget',
            'basicWhereAmI': 'label + roleName + name + positionInList + expandableState + (nodeLevel or nestingLevel)'
            },
        pyatspi.ROLE_MENU: {
            'focused': 'labelAndName + roleName',
            'unfocused': 'labelAndName + allTextSelection + roleName + availability + ' + MNEMONIC + ' + accelerator + positionInList',
            'basicWhereAmI': '(ancestors or parentRoleName) + labelAndName + roleName +  positionInList + ' + MNEMONIC
            },
        pyatspi.ROLE_MENU_ITEM: {
            'focused': 'expandableState',
            'unfocused': 'labelAndName + menuItemCheckedState + expandableState + availability + ' + MNEMONIC + ' + accelerator + positionInList',
            'basicWhereAmI': 'ancestors + labelAndName + accelerator + positionInList + ' + MNEMONIC
            },
        pyatspi.ROLE_NOTIFICATION: {
            'unfocused': 'roleName + unrelatedLabels'
            },
        pyatspi.ROLE_PAGE: {
            'focused': 'label + readOnly + currentLineText + anyTextSelection',
            'unfocused': 'label + readOnly + currentLineText + anyTextSelection + ' + MNEMONIC,
            'basicWhereAmI': 'label + readOnly + textRole + textContent + anyTextSelection + ' + MNEMONIC,
            'detailedWhereAmI': 'label + readOnly + textRole + textContentWithAttributes + anyTextSelection + ' + MNEMONIC
            },
        pyatspi.ROLE_PAGE_TAB: {
            'focused': 'labelAndName + roleName + positionInList + ' + MNEMONIC + ' + accelerator',
            'unfocused': 'labelAndName + roleName + positionInList + ' + MNEMONIC + ' + accelerator',
            'basicWhereAmI': 'parentRoleName + labelAndName + roleName + positionInList + ' + MNEMONIC + ' + accelerator'
            },
        pyatspi.ROLE_PANEL: {
            'focused': 'labelAndName + roleName',
            },
        pyatspi.ROLE_PARAGRAPH: {
            'focused': 'labelOrName + readOnly + textRole + currentLineText + allTextSelection',
            'unfocused': 'labelOrName + readOnly + textRole + currentLineText + allTextSelection + ' + MNEMONIC,
            'basicWhereAmI': 'label + readOnly + textRole + textContent + anyTextSelection + ' + MNEMONIC,
            'detailedWhereAmI': 'label + readOnly + textRole + textContentWithAttributes + anyTextSelection + ' + MNEMONIC + ' + ' + TUTORIAL
            },
        pyatspi.ROLE_PASSWORD_TEXT: {
            'focused': 'labelOrName + readOnly + textRole + currentLineText + allTextSelection',
            'unfocused': 'labelOrName + readOnly + textRole + currentLineText + allTextSelection + ' + MNEMONIC,
            'basicWhereAmI': 'label + readOnly + textRole + textContent + anyTextSelection + ' + MNEMONIC,
            'detailedWhereAmI': 'label + readOnly + textRole + textContentWithAttributes + anyTextSelection + ' + MNEMONIC + ' + ' + TUTORIAL
            },
        pyatspi.ROLE_PROGRESS_BAR: {
            'focused': 'percentage',
            'unfocused': 'labelAndName + percentage'
            },
        pyatspi.ROLE_PUSH_BUTTON: {
            'focused': 'expandableState',
            'unfocused': 'labelAndName + expandableState + roleName + availability + ' + MNEMONIC + ' + accelerator',
            'basicWhereAmI': 'labelAndName + expandableState + roleName + ' + MNEMONIC + ' + accelerator'
            },
        pyatspi.ROLE_RADIO_BUTTON: {
            'focused': 'radioState',
            'unfocused': 'labelAndName + radioState + roleName + availability + ' + MNEMONIC + ' + accelerator + positionInList',
            'basicWhereAmI': 'radioButtonGroup + labelAndName + roleName + radioState + positionInGroup + ' + MNEMONIC + ' + accelerator'
            },
        pyatspi.ROLE_RADIO_MENU_ITEM: {
            # OpenOffice check menu items currently have a role of "menu item"
            # rather then "check menu item", so we need to test if one of the
            # states is CHECKED. If it is, then add that in to the list of
            # speech utterances. Note that we can't tell if this is a "check
            # menu item" that is currently unchecked and speak that state.
            # See Orca bug #433398 for more details.
            #
            'focused': 'labelAndName + radioState + roleName + availability + positionInList',
            'unfocused': 'labelAndName + radioState + roleName + availability + ' + MNEMONIC + ' + accelerator + positionInList',
            'basicWhereAmI': 'ancestors + labelAndName + roleName + radioState + accelerator + positionInList + ' + MNEMONIC
            },
        pyatspi.ROLE_SCROLL_BAR: {
            'focused': 'value',
            'unfocused': 'labelOrName + roleName + value + required + availability + ' + MNEMONIC,
            'basicWhereAmI': 'labelOrName + roleName + value + percentage + ' + MNEMONIC + ' + accelerator + required'
            },
        pyatspi.ROLE_SECTION: {
            'basicWhereAmI': 'label + readOnly + textRole + textContent + anyTextSelection + ' + MNEMONIC,
            'detailedWhereAmI': 'label + readOnly + textRole + textContentWithAttributes + anyTextSelection + ' + MNEMONIC + ' + ' + TUTORIAL
            },
        pyatspi.ROLE_SLIDER: {
            'focused': 'value',
            'unfocused': 'labelOrName + roleName + value + required + availability + ' + MNEMONIC,
            'basicWhereAmI': 'labelOrName + roleName + value + percentage + ' + MNEMONIC + ' + accelerator + required'
            },
        pyatspi.ROLE_SPIN_BUTTON: {
            'focused': 'name',
            'unfocused': 'labelAndName + allTextSelection + roleName + availability + ' + MNEMONIC + ' + required',
            'basicWhereAmI': 'label + roleName + name + allTextSelection + ' + MNEMONIC + ' + accelerator + required'
            },
        pyatspi.ROLE_SPLIT_PANE: {
            'focused': 'value',
            'unfocused': 'labelAndName + roleName + value + availability + ' + MNEMONIC,
            'basicWhereAmI' : 'labelAndName + roleName + value'
            },
        pyatspi.ROLE_TABLE: {
            'focused': 'labelAndName + table',
            'unfocused': 'labelAndName + table',
            'basicWhereAmI': 'labelAndName + table'
            },
        pyatspi.ROLE_TABLE_CELL: {
            'focused': '(tableCell2ChildLabel + tableCell2ChildToggle)\
                        or (cellCheckedState + (expandableState and (expandableState + numberOfChildren)))',
            'unfocused': 'tableCellRow',
            'basicWhereAmI': 'parentRoleName + columnHeader + rowHeader + roleName + cellCheckedState + (realActiveDescendantDisplayedText or imageDescription + image) + columnAndRow + expandableState + nodeLevel',
            'detailedWhereAmI': 'parentRoleName + columnHeader + rowHeader + roleName + cellCheckedState + (realActiveDescendantDisplayedText or imageDescription + image) + columnAndRow + tableCellRow + expandableState + nodeLevel'
            },
        'REAL_ROLE_TABLE_CELL': {
            # the real cell information
            # note that pyatspi.ROLE_TABLE_CELL is used to work out if we need to
            # read a whole row. It calls REAL_ROLE_TABLE_CELL internally.
            # maybe it can be done in a cleaner way?
            #
            'focused':   '(tableCell2ChildLabel + tableCell2ChildToggle)\
                          or (cellCheckedState + (expandableState and (expandableState + numberOfChildren)))',
            'unfocused': '(tableCell2ChildLabel + tableCell2ChildToggle)\
                          or (newRowHeader + (newColumnHeader or columnHeaderIfToggleAndNoText) \
                              + cellCheckedState\
                              + (realActiveDescendantDisplayedText or imageDescription + image)\
                              + (expandableState and (expandableState + numberOfChildren))\
                              + required)'
            },
        pyatspi.ROLE_TEAROFF_MENU_ITEM: {
            'focused': '[]',
            'unfocused': 'labelAndName + allTextSelection + roleName + availability '
            },
        pyatspi.ROLE_TERMINAL: {
            'focused': 'terminal',
            'unfocused': 'terminal',
            'basicWhereAmI': 'label + readOnly + textRole + textContent + anyTextSelection + ' + MNEMONIC,
            'detailedWhereAmI': 'label + readOnly + textRole + textContentWithAttributes + anyTextSelection + ' + MNEMONIC + ' + ' + TUTORIAL
            },
        pyatspi.ROLE_TEXT: {
            'focused': 'labelOrName + placeholderText + readOnly + textRole + textIndentation + currentLineText + allTextSelection',
            'unfocused': 'labelOrName + placeholderText + readOnly + textRole + textIndentation + currentLineText + allTextSelection + ' + MNEMONIC,
            'basicWhereAmI': 'label + placeholderText + readOnly + textRole + textContent + anyTextSelection + ' + MNEMONIC,
            'detailedWhereAmI': 'label + placeholderText + readOnly + textRole + textContentWithAttributes + anyTextSelection + ' + MNEMONIC + ' + ' + TUTORIAL
            },
        pyatspi.ROLE_TOGGLE_BUTTON: {
            'focused': 'expandableState or toggleState',
            'unfocused': 'labelAndName + roleName + (expandableState or toggleState) + availability + ' + MNEMONIC + ' + accelerator',
            'basicWhereAmI': 'labelAndName + roleName + (expandableState or toggleState)'
            },
        pyatspi.ROLE_TOOL_TIP: {
            'unfocused': 'labelAndName',
            'basicWhereAmI': 'labelAndName'
            },
    },

    ####################################################################
    #                                                                  #
    # Formatting for braille.                                          #
    #                                                                  #
    ####################################################################

    'braille': {
        'prefix': {
#            'focused':   'ancestors\
#                         + (rowHeader and [Region(" " + asString(rowHeader))])\
#                         + (columnHeader and [Region(" " + asString(columnHeader))])\
#                         + (radioButtonGroup and [Region(" " + asString(radioButtonGroup))])\
#                         + [Region(" ")]',
#            'unfocused': 'ancestors\
#                         + (rowHeader and [Region(" " + asString(rowHeader))])\
#                         + (columnHeader and [Region(" " + asString(columnHeader))])\
#                         + (radioButtonGroup and [Region(" " + asString(radioButtonGroup))])\
#                         + [Region(" ")]',
            'focused':   '(includeContext\
                           and (ancestors\
                                + (rowHeader and [Region(" " + asString(rowHeader))])\
                                + (columnHeader and [Region(" " + asString(columnHeader))])\
                                + (radioButtonGroup and [Region(" " + asString(radioButtonGroup))])\
                                + [Region(" ")])\
                           or [])',
            'unfocused': '(includeContext\
                           and (ancestors\
                                + (rowHeader and [Region(" " + asString(rowHeader))])\
                                + (columnHeader and [Region(" " + asString(columnHeader))])\
                                + (radioButtonGroup and [Region(" " + asString(radioButtonGroup))])\
                                + [Region(" ")])\
                           or [])',
            },
        'suffix': {
            'focused':   '(nodeLevel and [Region(" " + asString(nodeLevel))])',
            'unfocused': '(nodeLevel and [Region(" " + asString(nodeLevel))])',
            },
        'default': {
            'focused':   '[Component(obj,\
                                     asString(label + displayedText + value + roleName + required))]',
            'unfocused': '[Component(obj,\
                                     asString(label + displayedText + value + roleName + required))]',
            },
        #pyatspi.ROLE_ALERT: 'default'
        pyatspi.ROLE_ANIMATION: {
            'unfocused': '[Component(obj,\
                                     asString(label + displayedText + roleName + (description and space(": ") + description)))]',
            },
        #pyatspi.ROLE_ARROW: 'default'
        pyatspi.ROLE_CANVAS: {
            'unfocused': '[Component(obj,\
                                     asString(((label + displayedText + imageDescription) or name) + roleName))]'
            },
        pyatspi.ROLE_CHECK_BOX: {
            'unfocused': '[Component(obj,\
                                     asString(labelOrName + roleName),\
                                     indicator=asString(checkedState))]'
            },
        pyatspi.ROLE_CHECK_MENU_ITEM: {
            'unfocused': '[Component(obj,\
                                     asString(label + displayedText + roleName + availability) + asString(accelerator),\
                                     indicator=asString(checkedState))]'
            },
        #pyatspi.ROLE_COLUMN_HEADER: 'default'
        pyatspi.ROLE_COMBO_BOX: {
            # [[[TODO: WDW - maybe pass the label into the region constructor?
            # We could then use the cursorOffset field to indicate where the
            # combobox starts.]]]
            #
            'unfocused': '((comboBoxTextObj and [Text(comboBoxTextObj[0], asString(label), asString(eol))])\
                           or [Component(obj, asString(label + name), label and (len(asString(label)) + 1) or 0)])\
                          + [Region(" " + asString(roleName))]'
            },
        #pyatspi.ROLE_DESKTOP_ICON: 'default'
        pyatspi.ROLE_DIAL: {
            'unfocused': '[Component(obj,\
                                     asString(labelOrName + value + roleName + required))]'
            },
        #pyatspi.ROLE_DIALOG: 'default'
        #pyatspi.ROLE_DIRECTORY_PANE: 'default'
        pyatspi.ROLE_DOCUMENT_FRAME: {
            'focused': '[Text(obj, asString(placeholderText), asString(eol))]\
                          + (required and [Region(" " + asString(required))])\
                          + (readOnly and [Region(" " + asString(readOnly))])',
            'unfocused': BRAILLE_TEXT
            },
        pyatspi.ROLE_EMBEDDED: {
            'unfocused': '[Component(obj,\
{'fraction_non_alphanumeric': 0.12312294104569615, 'fraction_numerical': 0.0018593746842094625, 'mean_word_length': 2.124921055955539, 'pattern_counts': {'":': 2, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 66, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6681956', 'n_tokens_mistral': 13759, 'n_tokens_neox': 13251, 'n_words': 2707}